PluginProbe
JetFormBuilder — Dynamic Blocks Form Builder / 3.6.6
JetFormBuilder — Dynamic Blocks Form Builder v3.6.6
3.6.6.1 3.6.6 3.6.5.4 3.6.5.3 3.6.5.2 3.6.5.1 3.6.5 3.6.4.2 3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 All 134 releases
jetformbuilder / modules / framework / blocks-style-manager / style-engine.php

style-engine.php in JetFormBuilder — Dynamic Blocks Form Builder 3.6.6, at modules/framework/blocks-style-manager/style-engine.php

394 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CSS parser engine
4 */
5 namespace Crocoblock\Blocks_Style;
6
7 class Style_Engine {
8
9 protected $attrs = array();
10
11 protected $css_props = array();
12
13 protected $class_name = '';
14
15 protected $styles = array();
16
17 protected $responsive_styles = array();
18
19 protected $variables = array();
20
21 protected $current_breakpoint = '';
22
23 protected $breakpoints = array(
24 '__desktop' => array(
25 'minWidth' => 992,
26 ),
27 '__tablet' => array(
28 'maxWidth' => 991,
29 ),
30 '__mobile' => array(
31 'maxWidth' => 478,
32 ),
33 );
34
35 /**
36 * Constructor
37 *
38 * @param array $attrs Block attributes.
39 * @param array $css_props CSS properties.
40 */
41 public function __construct( $attrs = array(), $css_props = array() ) {
42
43 $this->class_name = self::get_classname_from_attrs( $attrs );
44
45 if ( ! empty( $attrs['_uniqueClassName'] ) ) {
46 unset( $attrs['_uniqueClassName'] );
47 }
48
49 $this->attrs = $attrs;
50 $this->css_props = $css_props;
51 }
52
53 /**
54 * Get class name from attributes.
55 *
56 * @param array $attrs Block attributes.
57 * @return string
58 */
59 public static function get_classname_from_attrs( $attrs = array() ) {
60 return ! empty( $attrs['_uniqueClassName'] ) ? $attrs['_uniqueClassName'] : '';
61 }
62
63 /**
64 * Get class name of the block
65 *
66 * @return string
67 */
68 public function get_class_name() {
69 return $this->class_name;
70 }
71
72 /**
73 * Load field handlers.
74 *
75 * This method is used to load field handlers for the block styles.
76 * It checks if the base class exists and includes it if not.
77 */
78 public function load_field_handlers() {
79
80 if ( ! class_exists( '\Crocoblock\Blocks_Style\Field_Handlers\Base' ) ) {
81 require_once dirname( __FILE__ ) . '/field-handlers/base.php';
82 }
83 }
84
85 /**
86 * Get styles for the block.
87 *
88 * @return array
89 */
90 public function get_styles() {
91
92 $this->load_field_handlers();
93
94 foreach ( array_keys( $this->breakpoints ) as $breakpoint ) {
95
96 $this->current_breakpoint = $breakpoint;
97
98 if ( ! empty( $this->attrs[ $breakpoint ] ) && is_array( $this->attrs[ $breakpoint ] ) ) {
99
100 foreach ( $this->attrs[ $breakpoint ] as $prop_id => $prop_value ) {
101
102 if ( ! empty( $this->css_props[ $prop_id ] ) ) {
103 $prop = $this->css_props[ $prop_id ];
104 } else {
105 continue;
106 }
107
108 if ( ! empty( $prop['css_selector'] ) && is_array( $prop['css_selector'] ) ) {
109 foreach ( $prop['css_selector'] as $selector => $definition ) {
110 $this->add_selector_to_styles( array(
111 'prop' => $prop_id,
112 'type' => $prop['type'],
113 'selectoor' => $selector,
114 'definition' => $definition,
115 'value' => $prop_value,
116 ) );
117 }
118 }
119
120 if ( ! empty( $prop['css_var'] ) && is_array( $prop['css_var'] ) ) {
121 $handler = $this->get_field_handler( $prop['type'], $prop_value );
122 if ( $handler ) {
123 $prop['css_var']['suffix'] = $breakpoint;
124 $variable = $handler->parse_variable( $prop['css_var'] );
125 if ( ! empty( $variable ) ) {
126 $this->variables = array_merge( $this->variables, $variable );
127 }
128 $prop['css_var']['suffix'] = false;
129 }
130 }
131 }
132
133 unset( $this->attrs[ $breakpoint ] );
134 }
135
136 $this->current_breakpoint = '';
137 }
138
139 foreach ( $this->attrs as $prop_id => $prop_value ) {
140
141 if ( ! empty( $this->css_props[ $prop_id ] ) ) {
142 $prop = $this->css_props[ $prop_id ];
143 } else {
144 continue;
145 }
146
147 if ( ! empty( $prop['css_selector'] ) && is_array( $prop['css_selector'] ) ) {
148 foreach ( $prop['css_selector'] as $selector => $definition ) {
149 $this->add_selector_to_styles( array(
150 'prop' => $prop_id,
151 'type' => $prop['type'],
152 'selectoor' => $selector,
153 'definition' => $definition,
154 'value' => $prop_value,
155 ) );
156 }
157 }
158
159 if ( ! empty( $prop['css_var'] ) && is_array( $prop['css_var'] ) ) {
160 $handler = $this->get_field_handler( $prop['type'], $prop_value );
161 if ( $handler ) {
162 $variable = $handler->parse_variable( $prop['css_var'] );
163 if ( ! empty( $variable ) ) {
164 $this->variables = array_merge( $this->variables, $variable );
165 }
166 }
167 }
168 }
169
170 return array(
171 'styles' => $this->stringify_selectors( $this->styles ) . $this->get_responsive_styles(),
172 'variables' => $this->stringify_props( $this->variables ),
173 );
174 }
175
176 /**
177 * Get responsive styles.
178 *
179 * @return string
180 */
181 public function get_responsive_styles() {
182
183 $css = '';
184
185 if ( ! empty( $this->responsive_styles ) && is_array( $this->responsive_styles ) ) {
186 foreach ( $this->responsive_styles as $breakpoint => $selectors ) {
187 if ( ! empty( $selectors ) && is_array( $selectors ) ) {
188 $css .= '@media screen and (';
189 if ( ! empty( $this->breakpoints[ $breakpoint ]['minWidth'] ) ) {
190 $css .= 'min-width: ' . $this->breakpoints[ $breakpoint ]['minWidth'] . 'px';
191 }
192 if ( ! empty( $this->breakpoints[ $breakpoint ]['maxWidth'] ) ) {
193 $css .= 'max-width: ' . $this->breakpoints[ $breakpoint ]['maxWidth'] . 'px';
194 }
195 $css .= ') { ';
196 $css .= $this->stringify_selectors( $selectors );
197 $css .= ' } ';
198 }
199 }
200 }
201
202 return ' ' . $css;
203 }
204
205 /**
206 * Adds selector to styles.
207 *
208 * @param array $selector_data Selector data.
209 */
210 public function add_selector_to_styles( $selector_data = array() ) {
211
212 $parsed_rule = $this->generate_css_rules(
213 $selector_data['prop'],
214 $selector_data['type'],
215 $selector_data['definition'],
216 $selector_data['value']
217 );
218
219 if ( empty( $parsed_rule ) ) {
220 return;
221 }
222
223 $parsed_selector = $this->generate_css_selector( $selector_data['selectoor'] );
224
225 if ( ! $this->current_breakpoint ) {
226
227 if ( empty( $this->styles[ $parsed_selector ] ) ) {
228 $this->styles[ $parsed_selector ] = array();
229 }
230
231 $this->styles[ $parsed_selector ][] = $parsed_rule;
232 } else {
233
234 $breakpoint = $this->current_breakpoint;
235
236 if ( empty( $this->responsive_styles[ $breakpoint ][ $parsed_selector ] ) ) {
237 $this->responsive_styles[ $breakpoint ][ $parsed_selector ] = array();
238 }
239
240 $this->responsive_styles[ $breakpoint ][ $parsed_selector ][] = $parsed_rule;
241 }
242 }
243
244 /**
245 * Generates a valid CSS selector.
246 *
247 * @param string $selector CSS selector to generate.
248 * @return string Parsed CSS selector.
249 */
250 public function generate_css_selector( $selector = '' ) {
251
252 if ( empty( $selector ) ) {
253 return '';
254 }
255
256 return Field_Handlers\Base::replace_data(
257 $selector,
258 apply_filters( 'crocoblock/style-manager/css-selector-macros', array(
259 'wrapper' => '.' . $this->class_name,
260 'id' => $this->class_name,
261 ), $this )
262 );
263 }
264
265 /**
266 * Generates a valid CSS props set for given selector
267 * and actual attributes data.
268 *
269 * @param string $prop_id Property ID (to get it form attributes).
270 * @param string $prop_type Property type to get correct parser.
271 * @param string $def CSS rule definition with macros, which will be replaced with values.
272 * @param array $value Value to parse (optional, if not set, will be taken from attributes).
273 * @return void
274 */
275 public function generate_css_rules( $prop_id, $prop_type, $def = '', $value = array() ) {
276
277 if ( empty($value ) ) {
278 return;
279 }
280
281 $handler = $this->get_field_handler( $prop_type, $value );
282
283 if ( ! $handler ) {
284 return;
285 }
286
287 return $handler->get_css_rule( $def );
288 }
289
290 /**
291 * Get field handler by type.
292 *
293 * @param string $type Field type.
294 * @param mixed $raw_value Raw value to parse.
295 * @return \Crocoblock\Blocks_Style\Field_Handlers\Base|false
296 */
297 public function get_field_handler( $type = '', $raw_value = '' ) {
298
299 switch ( $type ) {
300
301 case 'range':
302
303 if ( ! class_exists( '\Crocoblock\Blocks_Style\Field_Handlers\Range' ) ) {
304 require_once dirname( __FILE__ ) . '/field-handlers/range.php';
305 }
306
307 return new Field_Handlers\Range( $raw_value );
308
309 case 'typography':
310
311 if ( ! class_exists( '\Crocoblock\Blocks_Style\Field_Handlers\Typography' ) ) {
312 require_once dirname( __FILE__ ) . '/field-handlers/typography.php';
313 }
314
315 return new Field_Handlers\Typography( $raw_value );
316
317 case 'border':
318
319 if ( ! class_exists( '\Crocoblock\Blocks_Style\Field_Handlers\Border' ) ) {
320 require_once dirname( __FILE__ ) . '/field-handlers/border.php';
321 }
322
323 return new Field_Handlers\Border( $raw_value );
324
325 case 'dimensions':
326
327 if ( ! class_exists( '\Crocoblock\Blocks_Style\Field_Handlers\Dimensions' ) ) {
328 require_once dirname( __FILE__ ) . '/field-handlers/dimensions.php';
329 }
330
331 return new Field_Handlers\Dimensions( $raw_value );
332
333 default:
334 return new Field_Handlers\Base( $raw_value );
335 }
336 }
337
338 /**
339 * Generates a valid CSS selectors set.
340 *
341 * Input format:
342 * array(
343 * 'selector_1' => array( 'css_prop_1:value_1', 'css_prop_2:value_2' ),
344 * 'selector_2' => array( 'css_prop_3:value_3', 'css_prop_4:value_4' ),
345 * );
346 *
347 * Output format:
348 * '.selector_1 { css_prop_1: value_1; css_prop_2: value_2; }
349 * .selector_2 { css_prop_3: value_3; css_prop_4: value_4; }'
350 *
351 * @param array $selectors
352 * @return void
353 */
354 public function stringify_selectors( $selectors = array() ) {
355
356 $css = '';
357
358 if ( ! empty( $selectors ) && is_array( $selectors ) ) {
359 foreach ( $selectors as $selector => $props ) {
360 if ( ! empty( $props ) && is_array( $props ) ) {
361 $css .= $selector . ' { ' . $this->stringify_props( $props ) . ' } ';
362 }
363 }
364 }
365
366 return trim( $css );
367 }
368
369 /**
370 * Generates a valid CSS definitions set.
371 *
372 * Input format:
373 * array(
374 * 'css_prop_1: value_1',
375 * 'css_prop_2: value_2',
376 * );
377 *
378 * Output format:
379 * 'css_prop_1: value_1; css_prop_2: value_2;'
380 *
381 * @param array $props
382 * @return void
383 */
384 public function stringify_props( $props = array() ) {
385
386 if ( empty( $props ) || ! is_array( $props ) ) {
387 return '';
388 }
389
390 return implode( ';', array_map( function( $prop ) {
391 return rtrim( $prop, ';' );
392 }, $props ) ) . ';';
393 }
394 }