PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.1
Elementor Website Builder – more than just a page builder v4.3.1
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 4.1.0-dev2 All 455 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.1, at modules/atomic-widgets/css-converter/converters/box-shadow-property-converter.php

145 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` -> empty Box_Shadow array (clears the prop).
42 */
43 class Box_Shadow_Property_Converter extends Property_Converter_Base {
44 const INSET_KEYWORD = 'inset';
45 const DEFAULT_COLOR = 'currentColor';
46 const ZERO_SIZE = [
47 'size' => 0,
48 'unit' => 'px',
49 ];
50
51 protected function get_supported_properties(): array {
52 return [ 'box-shadow' ];
53 }
54
55 protected function do_convert( Conversion_Context $context, array $rule ): bool {
56 $value = trim( $rule['value'] );
57
58 if ( '' === $value ) {
59 return false;
60 }
61
62 if ( 'none' === strtolower( $value ) ) {
63 $context->set_prop( 'box-shadow', Box_Shadow_Prop_Type::generate( [] ) );
64 return true;
65 }
66
67 $layers = Css_Token_Splitter::split_by_comma( $value );
68 $shadows = [];
69
70 foreach ( $layers as $layer ) {
71 $shadow = $this->parse_layer( trim( $layer ) );
72
73 if ( null === $shadow ) {
74 return false;
75 }
76
77 $shadows[] = $shadow;
78 }
79
80 $context->set_prop( 'box-shadow', Box_Shadow_Prop_Type::generate( $shadows ) );
81
82 return true;
83 }
84
85 private function parse_layer( string $layer ): ?array {
86 $tokens = Css_Token_Splitter::split_by_whitespace( $layer );
87
88 if ( empty( $tokens ) ) {
89 return null;
90 }
91
92 $lengths = [];
93 $color = null;
94 $is_inset = false;
95
96 foreach ( $tokens as $token ) {
97 if ( self::INSET_KEYWORD === strtolower( $token ) ) {
98 if ( $is_inset ) {
99 return null;
100 }
101
102 $is_inset = true;
103 continue;
104 }
105
106 $size = Size_Value_Parser::parse( $token );
107
108 if ( null !== $size ) {
109 $lengths[] = $size;
110 continue;
111 }
112
113 if ( null !== $color ) {
114 return null;
115 }
116
117 $color = $token;
118 }
119
120 $length_count = count( $lengths );
121
122 if ( $length_count < 2 || $length_count > 4 ) {
123 return null;
124 }
125
126 return Shadow_Prop_Type::generate( $this->build_shadow_fields( $lengths, $color, $is_inset ) );
127 }
128
129 private function build_shadow_fields( array $lengths, ?string $color, bool $is_inset ): array {
130 $fields = [
131 'hOffset' => Size_Prop_Type::generate( $lengths[0] ),
132 'vOffset' => Size_Prop_Type::generate( $lengths[1] ),
133 'blur' => Size_Prop_Type::generate( $lengths[2] ?? self::ZERO_SIZE ),
134 'spread' => Size_Prop_Type::generate( $lengths[3] ?? self::ZERO_SIZE ),
135 'color' => Color_Prop_Type::generate( $color ?? self::DEFAULT_COLOR ),
136 ];
137
138 if ( $is_inset ) {
139 $fields['position'] = String_Prop_Type::generate( self::INSET_KEYWORD );
140 }
141
142 return $fields;
143 }
144 }
145