PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.16.0
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.16.0
2.16.0 2.15.0 2.14.0 2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 All 83 releases
← All changes | includes/blocks/price-menu-item/block.php +204 -39 2.9.1 → 2.16.0 View file →
@@ -1,7 +1,11 @@
1 1 <?php
2 2 namespace ABlocks\Blocks\PriceMenuItem;
3 3
4 +if ( ! defined( 'ABSPATH' ) ) {
5 + exit;
6 +}
7 +
4 8 use ABlocks\Classes\BlockBaseAbstract;
5 9 use ABlocks\Classes\CssGenerator;
6 10 use ABlocks\Controls\Icon;
7 11 use ABlocks\Controls\Alignment;
@@ -8,8 +12,10 @@
8 12 use ABlocks\Controls\Typography;
9 13 use ABlocks\Controls\TextShadow;
10 14 use ABlocks\Controls\TextStroke;
11 15 use ABlocks\Controls\Range;
16 +use ABlocks\Controls\Color;
17 +use ABlocks\Helper;
12 18
13 19 class Block extends BlockBaseAbstract {
14 20 protected $parent_block_name = 'price-menu';
15 21 protected $block_name = 'price-menu-item';
@@ -21,15 +27,24 @@
21 27 $css_generator->add_class_styles(
22 28 '{{WRAPPER}} .ablocks-icon-wrap',
23 29 Icon::get_wrapper_css( $attributes ),
24 30 Icon::get_wrapper_css( $attributes, 'Tablet' ),
25 - Icon::get_wrapper_css( $attributes, 'Mobile' )
31 + Icon::get_wrapper_css( $attributes, 'Mobile' ),
32 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_wrapper_css( $attributes, $device ); } )
26 33 );
27 34 $css_generator->add_class_styles(
35 + '{{WRAPPER}} .ablocks-icon-wrap:hover',
36 + Icon::get_wrapper_hover_css( $attributes ),
37 + Icon::get_wrapper_hover_css( $attributes, 'Tablet' ),
38 + Icon::get_wrapper_hover_css( $attributes, 'Mobile' ),
39 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_wrapper_hover_css( $attributes, $device ); } )
40 + );
41 + $css_generator->add_class_styles(
28 42 '{{WRAPPER}} .ablocks-icon-wrap img.ablocks-image-icon',
29 43 Icon::get_element_image_css( $attributes ),
30 44 Icon::get_element_image_css( $attributes, 'Tablet' ),
31 45 Icon::get_element_image_css( $attributes, 'Mobile' ),
46 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_element_image_css( $attributes, $device ); } )
32 47 );
33 48 $css_generator->add_class_styles(
34 49 '{{WRAPPER}} .ablocks-icon-wrap img.ablocks-image-icon:hover',
35 50 Icon::get_element_image_hover_css( $attributes ),
@@ -34,8 +49,9 @@
34 49 '{{WRAPPER}} .ablocks-icon-wrap img.ablocks-image-icon:hover',
35 50 Icon::get_element_image_hover_css( $attributes ),
36 51 Icon::get_element_image_hover_css( $attributes, 'Tablet' ),
37 52 Icon::get_element_image_hover_css( $attributes, 'Mobile' ),
53 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_element_image_hover_css( $attributes, $device ); } )
38 54 );
39 55 $css_generator->add_class_styles(
40 56 '{{WRAPPER}} .ablocks-icon-wrap svg.ablocks-svg-icon',
41 57 Icon::get_element_css( $attributes ),
@@ -40,8 +56,9 @@
40 56 '{{WRAPPER}} .ablocks-icon-wrap svg.ablocks-svg-icon',
41 57 Icon::get_element_css( $attributes ),
42 58 Icon::get_element_css( $attributes, 'Tablet' ),
43 59 Icon::get_element_css( $attributes, 'Mobile' ),
60 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_element_css( $attributes, $device ); } )
44 61 );
45 62 $css_generator->add_class_styles(
46 63 '{{WRAPPER}} .ablocks-icon-wrap svg.ablocks-svg-icon:hover',
47 64 Icon::get_element_image_hover_css( $attributes ),
@@ -46,8 +63,9 @@
46 63 '{{WRAPPER}} .ablocks-icon-wrap svg.ablocks-svg-icon:hover',
47 64 Icon::get_element_image_hover_css( $attributes ),
48 65 Icon::get_element_image_hover_css( $attributes, 'Tablet' ),
49 66 Icon::get_element_image_hover_css( $attributes, 'Mobile' ),
67 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return Icon::get_element_image_hover_css( $attributes, $device ); } )
50 68 );
51 69 // TitleText CSS
52 70 $css_generator->add_class_styles(
53 71 '{{WRAPPER}} .ablocks-price-menu-item-details-title',
@@ -53,8 +71,9 @@
53 71 '{{WRAPPER}} .ablocks-price-menu-item-details-title',
54 72 $this->get_title_text_css( $attributes, '' ),
55 73 $this->get_title_text_css( $attributes, 'Tablet' ),
56 74 $this->get_title_text_css( $attributes, 'Mobile' ),
75 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_title_text_css( $attributes, $device ); } )
57 76 );
58 77 // DescriptionText CSS
59 78 $css_generator->add_class_styles(
60 79 '{{WRAPPER}} .ablocks-price-menu-item-details-des',
@@ -60,8 +79,9 @@
60 79 '{{WRAPPER}} .ablocks-price-menu-item-details-des',
61 80 $this->get_description_text_css( $attributes, '' ),
62 81 $this->get_description_text_css( $attributes, 'Tablet' ),
63 82 $this->get_description_text_css( $attributes, 'Mobile' ),
83 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_description_text_css( $attributes, $device ); } )
64 84 );
65 85 // SeparatorText CSS
66 86 $css_generator->add_class_styles(
67 87 '{{WRAPPER}} .ablocks-price-menu-divider__pattern-' . ( $attributes['dividerType'] === 'mask-style' ? 'mask' : 'css' ),
@@ -67,8 +87,9 @@
67 87 '{{WRAPPER}} .ablocks-price-menu-divider__pattern-' . ( $attributes['dividerType'] === 'mask-style' ? 'mask' : 'css' ),
68 88 $this->get_divider_css( $attributes, '' ),
69 89 $this->get_divider_css( $attributes, 'Tablet' ),
70 90 $this->get_divider_css( $attributes, 'Mobile' ),
91 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_divider_css( $attributes, $device ); } )
71 92 );
72 93 // PriceText CSS
73 94 $css_generator->add_class_styles(
74 95 '{{WRAPPER}} .ablocks-price-menu-item-price',
@@ -74,24 +95,190 @@
74 95 '{{WRAPPER}} .ablocks-price-menu-item-price',
75 96 $this->get_price_text_css( $attributes, '' ),
76 97 $this->get_price_text_css( $attributes, 'Tablet' ),
77 98 $this->get_price_text_css( $attributes, 'Mobile' ),
99 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return $this->get_price_text_css( $attributes, $device ); } )
78 100 );
101 + // Divider width (item override of the parent's width)
102 + $css_generator->add_class_styles(
103 + '{{WRAPPER}} .ablocks-divider',
104 + self::get_divider_width_css( $attributes, '' ),
105 + self::get_divider_width_css( $attributes, 'Tablet' ),
106 + self::get_divider_width_css( $attributes, 'Mobile' ),
107 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return self::get_divider_width_css( $attributes, $device ); } )
108 + );
109 + $css_generator->add_class_styles(
110 + '{{WRAPPER}} .ablocks-price-menu-item',
111 + self::get_item_width_css( $attributes, '' ),
112 + self::get_item_width_css( $attributes, 'Tablet' ),
113 + self::get_item_width_css( $attributes, 'Mobile' ),
114 + $css_generator->custom_device_map( function ( $device ) use ( $attributes ) { return self::get_item_width_css( $attributes, $device ); } )
115 + );
116 + $css_generator->add_class_styles(
117 + '{{WRAPPER}} .ablocks-price-menu-item-details-brief > .ablocks-price-menu-item-price',
118 + self::get_price_row_css( $attributes )
119 + );
120 + // Responsive placements: hide the slots not used on each device.
121 + foreach ( [
122 + 'divider' => isset( $attributes['placeDivider'] ) ? $attributes['placeDivider'] : '',
123 + 'price' => isset( $attributes['placePrice'] ) ? $attributes['placePrice'] : '',
124 + ] as $kind => $placement ) {
125 + foreach ( self::get_used_placements( $placement ) as $slot ) {
126 + $css_generator->add_class_styles(
127 + '{{WRAPPER}} .' . self::get_slot_class_name( $kind, $slot ),
128 + self::get_slot_css( $placement, $slot, '' ),
129 + self::get_slot_css( $placement, $slot, 'Tablet' ),
130 + self::get_slot_css( $placement, $slot, 'Mobile' ),
131 + $css_generator->custom_device_map( function ( $device ) use ( $placement, $slot ) { return self::get_slot_css( $placement, $slot, $device ); } )
132 + );
133 + }
134 + }
79 135
80 136 return $css_generator->generate_css();
81 137 }
82 138
83 - public function get_title_text_css( $attributes, $device = '' ) {
84 - $css = [];
85 - $title_color = isset( $attributes['titleColor'] ) ? $attributes['titleColor'] : '';
139 + /**
140 + * Divider width as a custom property; mirrors get_divider_width_css() in
141 + * src/blocks/price-menu-item/styling.js. The parent passes its own property
142 + * and default. A width without a stored unit keeps the legacy unit: % with a
143 + * description, px without.
144 + */
145 + public static function get_divider_width_css( $attributes, $device = '', $property = '--ablocks-pm-item-divider-width', $default_value = null ) {
146 + return Range::get_css([
147 + 'attributeValue' => isset( $attributes['width'] ) ? $attributes['width'] : [],
148 + 'attributeObjectKey' => 'value',
149 + 'isResponsive' => true,
150 + 'defaultValue' => $default_value,
151 + 'hasUnit' => true,
152 + 'unitDefaultValue' => ! empty( $attributes['allowDescription'] ) ? '%' : 'px',
153 + 'property' => $property,
154 + 'device' => $device,
155 + ]);
156 + }
86 157
87 - if ( isset( $attributes['titleColor'] ) ) {
88 - $css['color'] = $title_color;
158 + // A responsive member for the device, inherited from wider devices; '' when unset.
159 + private static function resolve_member( $value, $key, $device ) {
160 + $target = 'Desktop' === $device ? '' : (string) $device;
161 + foreach ( array_merge( [ $target ], Helper::get_responsive_ancestors( $target ) ) as $suffix ) {
162 + $member = is_array( $value ) && isset( $value[ $key . $suffix ] ) && ! is_array( $value[ $key . $suffix ] ) ? (string) $value[ $key . $suffix ] : '';
163 + if ( Helper::has_responsive_value( $member ) ) {
164 + return $member;
165 + }
89 166 }
167 + return '';
168 + }
90 169
170 + // A % Title & price gap in effect on this device (unit default px).
171 + public static function is_percent_title_price_gap( $attributes, $device = '' ) {
172 + $gap = isset( $attributes['titlePriceGap'] ) ? $attributes['titlePriceGap'] : [];
173 + return '' !== self::resolve_member( $gap, 'value', $device ) && '%' === Range::get_unit( [
174 + 'attributeValue' => $gap,
175 + 'attributeObjectKey' => 'value',
176 + 'unitDefaultValue' => 'px',
177 + 'device' => $device,
178 + ] );
179 + }
180 +
181 + // A % on the title row; mirrors isPercentTitleRow() in styling.js. The legacy
182 + // implicit % (Allow description, no stored unit) is left alone.
183 + public static function is_percent_title_row( $attributes, $device = '' ) {
184 + return self::is_percent_title_price_gap( $attributes, $device ) || (
185 + ! empty( $attributes['allowDivider'] ) &&
186 + 'near title' === self::get_placement( isset( $attributes['placeDivider'] ) ? $attributes['placeDivider'] : '', $device ) &&
187 + '%' === self::resolve_member( isset( $attributes['width'] ) ? $attributes['width'] : [], 'valueUnit', $device )
188 + );
189 + }
190 +
191 + private static function has_percent_unit( $value ) {
192 + if ( ! is_array( $value ) ) {
193 + return false;
194 + }
195 + foreach ( $value as $key => $member ) {
196 + if ( 0 === strpos( $key, 'valueUnit' ) && '%' === $member ) {
197 + return true;
198 + }
199 + }
200 + return false;
201 + }
202 +
203 + public static function has_percent_title_price_gap( $attributes ) {
204 + return self::has_percent_unit( isset( $attributes['titlePriceGap'] ) ? $attributes['titlePriceGap'] : [] );
205 + }
206 +
207 + // Whether any device can use the % title row, so narrower devices that do
208 + // not must reset the item width they would otherwise inherit.
209 + public static function has_percent_title_row( $attributes ) {
210 + return self::has_percent_title_price_gap( $attributes ) || (
211 + ! empty( $attributes['allowDivider'] ) &&
212 + in_array( 'near title', self::get_used_placements( isset( $attributes['placeDivider'] ) ? $attributes['placeDivider'] : '' ), true ) &&
213 + self::has_percent_unit( isset( $attributes['width'] ) ? $attributes['width'] : [] )
214 + );
215 + }
216 +
217 + // Once Price alignment is chosen the item spans its row and the price fills
218 + // the space after the title/divider so text-align can position it. A % on
219 + // the title row needs the same; mirrors get_item_width_css() in styling.js.
220 + public static function get_item_width_css( $attributes, $device = '' ) {
221 + if ( ! empty( $attributes['priceAlignmentCustom'] ) ) {
222 + return $device ? [] : [ 'width' => '100%' ];
223 + }
224 + if ( self::is_percent_title_row( $attributes, $device ) ) {
225 + return [ 'width' => '100%' ];
226 + }
227 + return $device && self::has_percent_title_row( $attributes ) ? [ 'width' => 'fit-content' ] : [];
228 + }
229 +
230 + public static function get_price_row_css( $attributes ) {
231 + return ! empty( $attributes['priceAlignmentCustom'] ) ? [ 'flex-grow' => '1' ] : [];
232 + }
233 +
234 + /**
235 + * placeDivider / placePrice: a legacy string or a responsive array
236 + * ( value, valueTablet, valueMobile, … ). Mirrors placement.js.
237 + */
238 + public static function get_placement( $placement, $device = '' ) {
239 + $placement = is_array( $placement ) ? $placement : [ 'value' => (string) $placement ];
240 + $target = 'Desktop' === $device ? '' : (string) $device;
241 + foreach ( array_merge( [ $target ], Helper::get_responsive_ancestors( $target ) ) as $suffix ) {
242 + $value = isset( $placement[ 'value' . $suffix ] ) ? $placement[ 'value' . $suffix ] : '';
243 + if ( Helper::has_responsive_value( $value ) ) {
244 + return $value;
245 + }
246 + }
247 + return '';
248 + }
249 +
250 + public static function get_used_placements( $placement ) {
251 + if ( ! is_array( $placement ) ) {
252 + return Helper::has_responsive_value( $placement ) ? [ $placement ] : [];
253 + }
254 + $used = [];
255 + foreach ( $placement as $key => $value ) {
256 + if ( 0 === strpos( $key, 'value' ) && is_string( $value ) && Helper::has_responsive_value( $value ) ) {
257 + $used[] = $value;
258 + }
259 + }
260 + return array_values( array_unique( $used ) );
261 + }
262 +
263 + // The placement is a block attribute and this name lands in a selector of
264 + // an inline <style>, which esc_css_value() does not cover; keep it a class.
265 + public static function get_slot_class_name( $kind, $placement ) {
266 + return 'ablocks-price-menu-' . $kind . '-slot--' . sanitize_html_class( preg_replace( '/\s+/', '-', $placement ) );
267 + }
268 +
269 + public static function get_slot_css( $placement, $slot, $device = '' ) {
270 + if ( count( self::get_used_placements( $placement ) ) < 2 ) {
271 + return [];
272 + }
273 + return [ 'display' => self::get_placement( $placement, $device ) === $slot ? 'block' : 'none' ];
274 + }
275 +
276 + public function get_title_text_css( $attributes, $device = '' ) {
277 + $typographyValueGlobal = ! empty( $attributes['titleTypographyGlobal'] ) ? $attributes['titleTypographyGlobal'] : array();
91 278 return array_merge(
92 - $css,
93 - isset( $attributes['titleTypography'] ) ? Typography::get_css( $attributes['titleTypography'], '', $device ) : [],
279 + [ 'color' => Color::get_css( isset( $attributes['titleColor'] ) ? $attributes['titleColor'] : '' ) ],
280 + isset( $attributes['titleTypography'] ) ? Typography::get_css( $attributes['titleTypography'], '', $device, $typographyValueGlobal ) : [],
94 281 isset( $attributes['titleTextStroke'] ) ? TextStroke::get_css( $attributes['titleTextStroke'], '', $device ) : [],
95 282 isset( $attributes['titleTextShadow'] ) ? TextShadow::get_css( $attributes['titleTextShadow'], '', $device ) : [],
96 283 isset( $attributes['titleAlignment'] ) ? Alignment::get_css( $attributes['titleAlignment'], 'text-align', $device ) : [],
97 284 );
@@ -96,18 +283,13 @@
96 283 isset( $attributes['titleAlignment'] ) ? Alignment::get_css( $attributes['titleAlignment'], 'text-align', $device ) : [],
97 284 );
98 285 }
99 286 public function get_description_text_css( $attributes, $device = '' ) {
100 - $css = [];
101 - $description_color = isset( $attributes['descriptionColor'] ) ? $attributes['descriptionColor'] : '';
287 + $typographyValueGlobal = ! empty( $attributes['descriptionTypographyGlobal'] ) ? $attributes['descriptionTypographyGlobal'] : array();
102 288
103 - if ( isset( $attributes['descriptionColor'] ) ) {
104 - $css['color'] = $description_color;
105 - }
106 -
107 289 return array_merge(
108 - $css,
109 - isset( $attributes['descriptionTypography'] ) ? Typography::get_css( $attributes['descriptionTypography'], '', $device ) : [],
290 + [ 'color' => Color::get_css( isset( $attributes['descriptionColor'] ) ? $attributes['descriptionColor'] : '' ) ],
291 + isset( $attributes['descriptionTypography'] ) ? Typography::get_css( $attributes['descriptionTypography'], '', $device, $typographyValueGlobal ) : [],
110 292 isset( $attributes['descriptionTextStroke'] ) ? TextStroke::get_css( $attributes['descriptionTextStroke'], '', $device ) : [],
111 293 isset( $attributes['descriptionTextShadow'] ) ? TextShadow::get_css( $attributes['descriptionTextShadow'], '', $device ) : [],
112 294 isset( $attributes['descriptionAlignment'] ) ? Alignment::get_css( $attributes['descriptionAlignment'], 'text-align', $device ) : [],
113 295 );
@@ -113,14 +295,13 @@
113 295 );
114 296 }
115 297 public function get_divider_css( $attributes, $device = '' ) {
116 298 $css = [];
117 - $divider_width = isset( $attributes['width'][ 'value' . $device ] ) ? $attributes['width'][ 'value' . $device ] : 60;
118 - $divider_color = isset( $attributes['color'] ) ? $attributes['color'] : '#000000';
119 - $default_Unit = $attributes['allowDescription'] === true ? '%' : 'px';
120 299
121 300 if ( ! empty( $attributes['color'] ) ) {
122 - $css['--ablocks-divider-pattern-color'] = $divider_color;
301 + $css['--ablocks-divider-pattern-color'] = Color::get_css(
302 + isset( $attributes['color'] ) ? $attributes['color'] : '#000000');
303 +
123 304 }
124 305
125 306 $moreRangeCSS = [];
126 307 if ( isset( $attributes['dividerType'] ) && $attributes['dividerType'] === 'mask-style' && isset( $attributes['size'] ) && ! empty( $attributes['size'] ) ) {
@@ -154,32 +335,16 @@
154 335 }
155 336
156 337 return array_merge(
157 338 $css,
158 - Range::get_css([
159 - 'attributeValue' => $attributes['width'],
160 - 'attribute_object_key' => 'value',
161 - 'isResponsive' => true,
162 - 'defaultValue' => null,
163 - 'hasUnit' => false,
164 - 'unitDefaultValue' => $attributes['allowDescription'] === true ? '%' : 'px',
165 - 'property' => 'width',
166 - 'device' => $device,
167 - ]),
168 339 $moreRangeCSS,
169 340 );
170 341 }
171 342 public function get_price_text_css( $attributes, $device = '' ) {
172 - $css = [];
173 - $price_color = isset( $attributes['priceColor'] ) ? $attributes['priceColor'] : '';
174 -
175 - if ( isset( $attributes['priceColor'] ) ) {
176 - $css['color'] = $price_color;
177 - }
178 -
343 + $typographyValueGlobal = ! empty( $attributes['priceTypographyGlobal'] ) ? $attributes['priceTypographyGlobal'] : array();
179 344 return array_merge(
180 - $css,
181 - isset( $attributes['priceTypography'] ) ? Typography::get_css( $attributes['priceTypography'], '', $device ) : [],
345 + [ 'color' => Color::get_css( isset( $attributes['priceColor'] ) ? $attributes['priceColor'] : '' ) ],
346 + isset( $attributes['priceTypography'] ) ? Typography::get_css( $attributes['priceTypography'], '', $device, $typographyValueGlobal ) : [],
182 347 isset( $attributes['priceTextStroke'] ) ? TextStroke::get_css( $attributes['priceTextStroke'], '', $device ) : [],
183 348 isset( $attributes['priceTextShadow'] ) ? TextShadow::get_css( $attributes['priceTextShadow'], '', $device ) : [],
184 349 isset( $attributes['priceAlignment'] ) ? Alignment::get_css( $attributes['priceAlignment'], 'text-align', $device ) : [],
185 350 );