PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.3
Elementor Website Builder – more than just a page builder v4.3.3
4.3.3 4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 All 456 releases
elementor / modules / atomic-widgets / css-converter / converters / box-shadow-property-converter.php

box-shadow-property-converter.php in Elementor Website Builder – more than just a page builder 4.3.3, at modules/atomic-widgets/css-converter/converters/box-shadow-property-converter.php

141 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\AtomicWidgets\CssConverter\Converters;
4
5 use Elementor\Modules\AtomicWidgets\CssConverter\Conversion_Context;
6 use Elementor\Modules\AtomicWidgets\CssConverter\Property_Converter_Base;
7 use Elementor\Modules\AtomicWidgets\CssConverter\ValueParsers\Css_Token_Splitter;
8 use Elementor\Modules\AtomicWidgets\CssConverter\ValueParsers\Size_Value_Parser;
9 use Elementor\Modules\AtomicWidgets\PropTypes\Box_Shadow_Prop_Type;
10 use Elementor\Modules\AtomicWidgets\PropTypes\Color_Prop_Type;
11 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
12 use Elementor\Modules\AtomicWidgets\PropTypes\Shadow_Prop_Type;
13 use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Converter for the `box-shadow` CSS property -> Box_Shadow_Prop_Type (array of Shadow_Prop_Type).
21 *
22 * Per-layer CSS grammar:
23 * <shadow> = <color>? && [<length>{2,4}] && inset?
24 *
25 * Token classification (paren-aware so rgb(255 0 0) stays one token):
26 * - `inset` -> position keyword
27 * - parses as Size -> length token
28 * - anything else -> color (at most one per layer)
29 *
30 * Length mapping by count:
31 * 2 -> hOffset, vOffset
32 * 3 -> hOffset, vOffset, blur
33 * 4 -> hOffset, vOffset, blur, spread
34 * Any other count, multiple colors, or unrecognised tokens decline the entire declaration to custom_css.
35 *
36 * Defaults:
37 * - missing color -> `currentColor` (CSS spec default)
38 * - missing blur/spread -> 0 px
39 *
40 * Special values:
41 * - `none` -> declines to custom_css. An empty Box_Shadow array is not persisted and renders no
42 * declaration, so it cannot override a shadow from a class or a wider breakpoint.
43 */
44 class Box_Shadow_Property_Converter extends Property_Converter_Base {
45 const INSET_KEYWORD = 'inset';
46 const DEFAULT_COLOR = 'currentColor';
47 const ZERO_SIZE = [
48 'size' => 0,
49 'unit' => 'px',
50 ];
51
52 protected function get_supported_properties(): array {
53 return [ 'box-shadow' ];
54 }
55
56 protected function do_convert( Conversion_Context $context, array $rule ): bool {
57 $value = trim( $rule['value'] );
58
59 if ( '' === $value || 'none' === strtolower( $value ) ) {
60 return false;
61 }
62
63 $layers = Css_Token_Splitter::split_by_comma( $value );
64 $shadows = [];
65
66 foreach ( $layers as $layer ) {
67 $shadow = $this->parse_layer( trim( $layer ) );
68
69 if ( null === $shadow ) {
70 return false;
71 }
72
73 $shadows[] = $shadow;
74 }
75
76 $context->set_prop( 'box-shadow', Box_Shadow_Prop_Type::generate( $shadows ) );
77
78 return true;
79 }
80
81 private function parse_layer( string $layer ): ?array {
82 $tokens = Css_Token_Splitter::split_by_whitespace( $layer );
83
84 if ( empty( $tokens ) ) {
85 return null;
86 }
87
88 $lengths = [];
89 $color = null;
90 $is_inset = false;
91
92 foreach ( $tokens as $token ) {
93 if ( self::INSET_KEYWORD === strtolower( $token ) ) {
94 if ( $is_inset ) {
95 return null;
96 }
97
98 $is_inset = true;
99 continue;
100 }
101
102 $size = Size_Value_Parser::parse( $token );
103
104 if ( null !== $size ) {
105 $lengths[] = $size;
106 continue;
107 }
108
109 if ( null !== $color ) {
110 return null;
111 }
112
113 $color = $token;
114 }
115
116 $length_count = count( $lengths );
117
118 if ( $length_count < 2 || $length_count > 4 ) {
119 return null;
120 }
121
122 return Shadow_Prop_Type::generate( $this->build_shadow_fields( $lengths, $color, $is_inset ) );
123 }
124
125 private function build_shadow_fields( array $lengths, ?string $color, bool $is_inset ): array {
126 $fields = [
127 'hOffset' => Size_Prop_Type::generate( $lengths[0] ),
128 'vOffset' => Size_Prop_Type::generate( $lengths[1] ),
129 'blur' => Size_Prop_Type::generate( $lengths[2] ?? self::ZERO_SIZE ),
130 'spread' => Size_Prop_Type::generate( $lengths[3] ?? self::ZERO_SIZE ),
131 'color' => Color_Prop_Type::generate( $color ?? self::DEFAULT_COLOR ),
132 ];
133
134 if ( $is_inset ) {
135 $fields['position'] = String_Prop_Type::generate( self::INSET_KEYWORD );
136 }
137
138 return $fields;
139 }
140 }
141