PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.4.3
Kubio AI Page Builder v2.4.3
2.8.3 2.8.2 2.8.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 2.0.0 2.1.1 2.1.2 2.1.3 2.2.0 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.5 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.6.2 2.6.3 2.6.5 2.6.6 2.6.7 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0
kubio / lib / src / Core / CustomizerImporter.php
kubio / lib / src / Core Last commit date
Background 1 year ago Blocks 1 year ago GlobalElements 3 years ago Layout 4 years ago License 2 years ago Separators 4 years ago StyleManager 1 year ago Styles 4 years ago Activation.php 1 year ago Backup.php 4 years ago CustomizerImporter.php 1 year ago Deactivation.php 4 years ago EditInKubioCustomizerPanel.php 4 years ago Element.php 2 years ago ElementBase.php 4 years ago Importer.php 2 years ago InnerBlocks.php 4 years ago LodashBasic.php 2 years ago Registry.php 3 years ago Utils.php 1 year ago
CustomizerImporter.php
1186 lines
1 <?php
2
3 namespace Kubio\Core;
4
5 use ColibriWP\Theme\Defaults;
6 use IlluminateAgnostic\Arr\Support\Arr;
7 use Kubio\Core\StyleManager\Utils;
8 use Kubio\Flags;
9
10 class CustomizerImporter {
11
12 private static $current_data = null;
13 private $content = '';
14 private $type = '';
15 private $slug = '';
16 private $type_process_callback = array();
17
18
19 public function __construct( $content, $type, $slug ) {
20 $this->content = $content;
21 $this->type = $type;
22 $this->slug = $slug;
23
24 $this->type_process_callback = array(
25 'wp_template_part' => array(
26 'footer' => array( $this, 'processFooter' ),
27 'front-header' => array( $this, 'processHeader' ),
28 'header' => array( $this, 'processHeader' ),
29 ),
30 'wp_template' => array(
31 '*' => array( $this, 'processTemplate' ),
32 ),
33 );
34 }
35
36 public function process() {
37
38 $this->loadCurrentData();
39
40 if ( $this->canProcessCurrent() ) {
41 $this->processCurrent();
42 }
43
44 return $this->content;
45 }
46
47 private function loadCurrentData() {
48 if ( static::$current_data === null ) {
49
50 $options_data_map = array(
51 'front-header.title.localProps.content' => 'front-header.title.value',
52 'front-header.subtitle.localProps.content' => 'front-header.subtitle.value',
53 'front-header.header-menu.style.descendants.innerMenu.justifyContent' => array(
54 'option' => 'front-header.header-menu.style.descendants.main-menu-ul.justifyContent',
55 'default' => 'center',
56 ),
57 'header.header-menu.style.descendants.innerMenu.justifyContent' => array(
58 'option' => 'header.header-menu.style.descendants.main-menu-ul.justifyContent',
59 'default' => 'center',
60 ),
61 );
62
63 $data = array();
64 if ( class_exists( Defaults::class ) ) {
65 $data = Defaults::getDefaults();
66
67 // set default to lorem ipsum - inside the editor it is `Click to edit...`
68 Arr::set( $data, 'front-header.subtitle.value', $data['lorem_ipsum'] );
69
70 $options = get_theme_mods();
71
72 foreach ( $options_data_map as $option_to_map => $map ) {
73 $option_to_set = is_array( $map ) ? $map['option'] : $map;
74 $default_value = is_array( $map ) ? $map['default'] : null;
75
76 $value = Arr::get( $options, $option_to_map, $default_value );
77 Arr::forget( $options, $option_to_map );
78
79 if ( $value ) {
80 $options[ $option_to_set ] = $value;
81 }
82 }
83
84 foreach ( $options as $option => $value ) {
85
86 // remove multiple dots in path - fixes bad formatting
87 $option = preg_replace( '#\.\.+#', '.', $option );
88 Arr::set( $data, $option, $value );
89 }
90 }
91
92 // Copy layoutType for logo
93 $front_header_logo_layout_type = Arr::get( $data, 'front-header.logo.props.layoutType' );
94 $header_logo_layout_type = Arr::get( $data, 'header.logo.props.layoutType' );
95
96 if ( $front_header_logo_layout_type !== $header_logo_layout_type ) {
97 Arr::set( $data, 'header.logo.props.layoutType', $front_header_logo_layout_type );
98 }
99 //
100
101 // Copy top-bar icons from front header
102 $front_header_icon_list = Arr::get( $data, 'front-header.icon_list' );
103 $front_header_social_icons = Arr::get( $data, 'front-header.social_icons' );
104
105 Arr::forget( $data, array( 'header.icon_list', 'header.social_icons' ) );
106
107 Arr::set( $data, 'header.icon_list', $front_header_icon_list );
108 Arr::set( $data, 'header.social_icons', $front_header_social_icons );
109 //
110
111 // Set menu hover effect for front and inner header
112 $menu_effect = Arr::get( $data, 'front-header.header-menu.props.hoverEffect.group.border.transition' );
113
114 Arr::forget( $data, 'front-header.header-menu.props.hoverEffect.group' );
115 Arr::forget( $data, 'header.header-menu.props.hoverEffect.group' );
116
117 Arr::set( $data, 'front-header.header-menu.props.hoverEffect.border.effect', $menu_effect );
118 Arr::set( $data, 'header.header-menu.props.hoverEffect.border.effect', $menu_effect );
119 //
120
121 static::$current_data = $data;
122 }
123
124 }
125
126 private function canProcessCurrent() {
127
128 if ( $this->type === 'wp_template' ) {
129 return true;
130 }
131
132 return isset( $this->getCurrentData()[ $this->slug ] );
133 }
134
135 public function getCurrentData() {
136 return static::$current_data;
137 }
138
139 private function processCurrent() {
140 $process_fn = Arr::get( $this->type_process_callback, "{$this->type}.{$this->slug}", null );
141
142 $process_fn_for_all = Arr::get( $this->type_process_callback, "{$this->type}.*", null );
143
144 if ( $process_fn || $process_fn_for_all ) {
145 $parsed_blocks = parse_blocks( $this->content );
146
147 if ( $process_fn ) {
148 $parsed_blocks = call_user_func( $process_fn, $parsed_blocks );
149 }
150
151 if ( $process_fn_for_all ) {
152 $parsed_blocks = call_user_func( $process_fn_for_all, $parsed_blocks );
153 }
154 $this->content = kubio_serialize_blocks( $parsed_blocks );
155 }
156 }
157
158 private function processTemplate( $parsed_blocks ) {
159 if ( $this->slug === 'index' && $this->type === 'wp_template' ) { //here is the blog
160 $parsed_blocks = static::removeSidebar( $parsed_blocks );
161 }
162
163 $parsed_blocks = $this->postProcessBlocks( $parsed_blocks, $this->getCurrentData() );
164
165 return $parsed_blocks;
166 }
167
168 private function postProcessBlocks( $parsed_blocks, $current_data ) {
169 foreach ( $parsed_blocks as $index => $block ) {
170 $parsed_blocks[ $index ] = $this->postProcessBlock( $block, $current_data );
171 $inner_blocks = $this->postProcessBlocks( $block['innerBlocks'], $current_data );
172 $parsed_blocks = $this->updateBlockInnerBlocks( $parsed_blocks, $index, $inner_blocks );
173 }
174
175 return $parsed_blocks;
176
177 }
178
179 private function postProcessBlock( $parsed_block, $current_data ) {
180 $block_name = $parsed_block['blockName'];
181
182 if ( $block_name === 'kubio/logo' ) {
183 $data = Arr::get( $current_data, 'logo' );
184 $parsed_block = $this->normalizeLogo( $parsed_block, $data );
185 }
186
187 if ( $block_name === 'kubio/image' ) {
188 $data = Arr::get( $current_data, 'hero.image' );
189 $parsed_block = $this->normalizeImage( $parsed_block, $data );
190 }
191
192 if ( $block_name === 'kubio/query-loop' ) {
193 $items_per_row = Arr::get( $current_data, 'blog_posts_per_row', 2 );
194 $masonry = Arr::get( $current_data, 'blog_enable_masonry', true );
195
196 Arr::set( $parsed_block, 'attrs.kubio.props.layout.itemsPerRow', intval( $items_per_row ) );
197
198 Arr::set( $parsed_block, 'attrs.masonry', $masonry );
199 }
200
201 if ( $block_name === 'kubio/post-featured-image' ) {
202 Arr::set(
203 $parsed_block,
204 'attrs.kubio.style.descendants.container.background.color',
205 Arr::get( $current_data, 'blog_post_thumb_placeholder_color', 'rgba(var(--kubio-color-5-variant-2),1)' )
206 );
207
208 Arr::set(
209 $parsed_block,
210 'attrs.showPlaceholder',
211 Arr::get( $current_data, 'blog_show_post_thumb_placeholder', true )
212 );
213 }
214 if ( $block_name === 'kubio/footer' ) {
215 Arr::set(
216 $parsed_block,
217 'attrs.kubio.props.useFooterParallax',
218 Arr::get( $current_data, 'footer.footer.props.useFooterParallax' )
219 );
220 }
221
222 if ( $block_name === 'kubio/dropdown-menu' && $this->slug === 'header' ) {
223 $data = $this->getCurrentData();
224 $menu_effect = Arr::get( $data, 'front-header.header-menu.props.hoverEffect.border.effect' );
225 Arr::set( $parsed_block, 'attrs.kubio.props.hoverEffect.border.effect', $menu_effect );
226 }
227
228 return $parsed_block;
229 }
230
231 private function normalizeLogo( $parsed_block, $data ) {
232
233 $layout_type = Arr::get( $data, 'props.layoutType', null );
234 $current_data = $this->getCurrentData();
235 $menu_layout_type = Arr::get( $current_data, $this->slug . '.navigation.props.layoutType' );
236
237 if ( $layout_type ) {
238 Arr::set( $parsed_block, 'attrs.kubio.props.layoutType', $layout_type );
239
240 if ( $menu_layout_type === 'logo-above-menu' ) {
241 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.alignItems', 'center' );
242 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.justifyContent', 'center' );
243 }
244 }
245
246 // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
247 if ( $alternate_logo = Arr::get( $current_data, 'alternate_logo', false ) ) {
248 kubio_set_global_data( 'alternateLogo', wp_get_attachment_image_url( intval( $alternate_logo ), 'full' ) );
249 }
250
251 return $parsed_block;
252 }
253
254 private function normalizeImage( $parsed_block, $data ) {
255
256 if ( ! $data ) {
257 return $parsed_block;
258 }
259
260 $style_ref = Arr::get( $data, 'styleRef' );
261
262 if ( $style_ref === Arr::get( $parsed_block, 'attrs.kubio.styleRef' ) ) {
263 $url = Arr::get( $data, 'localProps.url', '' );
264 Arr::set(
265 $parsed_block,
266 'attrs.url',
267 $url
268 );
269 Arr::set(
270 $parsed_block,
271 'attrs.id',
272 attachment_url_to_postid( $url )
273 );
274 Arr::set(
275 $parsed_block,
276 'attrs.alt',
277 __( 'Image', 'kubio' )
278 );
279 }
280
281 $style = $data['style'];
282 $x_value = Arr::get( $style, 'descendants.frameImage.transform.translate.x_value' );
283 $width = Arr::get( $style, 'descendants.frameImage.width' );
284 $height = Arr::get( $style, 'descendants.frameImage.height' );
285 $y_value = Arr::get( $style, 'descendants.frameImage.transform.translate.y_value' );
286
287 Arr::set(
288 $style,
289 'descendants.frameImage.width',
290 array(
291 'value' => $width,
292 'unit' => '%',
293 )
294 );
295 Arr::set(
296 $style,
297 'descendants.frameImage.height',
298 array(
299 'value' => $height,
300 'unit' => '%',
301 )
302 );
303
304 Arr::set(
305 $style,
306 'descendants.frameImage.transform.translate',
307 array(
308 array(
309 'axis' => 'x',
310 'value' => array(
311 'value' => $x_value,
312 'unit' => '%',
313 ),
314 ),
315 array(
316 'axis' => 'y',
317 'value' => array(
318 'value' => $y_value,
319 'unit' => '%',
320 ),
321 ),
322 )
323 );
324
325 $color = Arr::get( $style, 'descendants.frameImage.backgroundColor' );
326 $thickness = Arr::get( $style, 'descendants.frameImage.thickness' );
327 $props = Arr::get( $data, 'props' );
328
329 Arr::forget( $style, 'descendants.frameImage.thickness' );
330
331 if ( Arr::get( $props, 'frame.type' ) === 'border' ) {
332 Arr::forget( $style, 'descendants.frameImage.backgroundColor' );
333 Arr::set(
334 $style,
335 'descendants.frameImage.border',
336 array(
337 'left' => array(
338 'style' => 'solid',
339 'color' => $color,
340 'width' => array(
341 'value' => $thickness,
342 'unit' => 'px',
343 ),
344 ),
345
346 'right' => array(
347 'style' => 'solid',
348 'color' => $color,
349 'width' => array(
350 'value' => $thickness,
351 'unit' => 'px',
352 ),
353 ),
354
355 'top' => array(
356 'style' => 'solid',
357 'color' => $color,
358 'width' => array(
359 'value' => $thickness,
360 'unit' => 'px',
361 ),
362 ),
363
364 'bottom' => array(
365 'style' => 'solid',
366 'color' => $color,
367 'width' => array(
368 'value' => $thickness,
369 'unit' => 'px',
370 ),
371 ),
372 )
373 );
374 }
375
376 if ( Arr::get( $props, 'showFrameOverImage' ) ) {
377 Arr::set( $style, 'descendants.frameImage.zIndex', 1 );
378 Arr::set( $style, 'descendants.frameImage.boxShadow.enabled', Arr::get( $props, 'showFrameShadow' ) );
379 } else {
380 Arr::forget( $style, 'descendants.frameImage.zIndex' );
381 }
382
383 // Check - image has border style from design (https://mantis.iconvert.pro/view.php?id=55688)
384 $image_border_style = Arr::get( $parsed_block, 'attrs.kubio.style.descendants.image.border' );
385 if ( $image_border_style ) {
386 Arr::set( $style, 'descendants.image.border', $image_border_style );
387 }
388
389 Arr::set( $parsed_block, 'attrs.kubio.style', $style );
390 Arr::set(
391 $parsed_block,
392 'attrs.kubio.props.frame',
393 array(
394 'type' => Arr::get( $props, 'frame.type' ),
395 'enabled' => Arr::get( $props, 'enabledFrameOption' ),
396 'showFrameOverImage' => Arr::get( $props, 'showFrameOverImage' ),
397 )
398 );
399
400 return $parsed_block;
401 }
402
403 /**
404 * @param array $parsed_blocks
405 * @param $block_index
406 * @param $next_inner_blocks
407 *
408 * @return array
409 */
410 private function updateBlockInnerBlocks( array $parsed_blocks, $block_index, $next_inner_blocks ) {
411 $parsed_blocks[ $block_index ]['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
412
413 if ( count( $parsed_blocks[ $block_index ]['innerContent'] ) === 0 ) {
414 $parsed_blocks[ $block_index ]['innerContent'] = array( $parsed_blocks[ $block_index ]['innerHTML'] );
415 }
416
417 $parsed_blocks[ $block_index ]['innerBlocks'] = $next_inner_blocks;
418
419 return $parsed_blocks;
420 }
421
422 private function processFooter( $parsed_blocks ) {
423
424 $current_part_data = $this->getCurrentPartData();
425
426 foreach ( $current_part_data as $item_data ) {
427 $parsed_blocks = $this->updateBlocks( $parsed_blocks, $item_data );
428 }
429
430 return $parsed_blocks;
431 }
432
433 private function getCurrentPartData() {
434 return $this->getCurrentData()[ $this->slug ];
435 }
436
437 private function updateBlocks( $parsed_blocks, $item_data ) {
438
439 foreach ( $parsed_blocks as $index => &$block ) {
440
441 if ( ! isset( $item_data['styleRef'] ) ) {
442 continue;
443 }
444
445 $style_ref = Arr::get( $block, 'attrs.kubio.styleRef', null );
446
447 if ( $style_ref === $item_data['styleRef'] ) {
448 $kubio_attr = Arr::get( $block, 'attrs.kubio' );
449 $style = Arr::get( $item_data, 'style', array() );
450 $props = Arr::get( $item_data, 'props', array() );
451 $local_props = Arr::get( $item_data, 'localProps', array() );
452
453 list( $block, $kubio_attr_replacement ) = $this->normalizeBlockData(
454 $block,
455 array(
456 'style' => $style,
457 'props' => $props,
458 ),
459 $item_data
460 );
461
462 // if some prop in normalization nullified the block
463 if ( $block === null ) {
464 array_splice( $parsed_blocks, $index, 1 );
465 continue;
466 }
467
468 foreach ( $local_props as $attr => $value ) {
469 Arr::set( $block, "attrs.{$attr}", $value );
470 }
471
472 $kubio_attr = array_replace_recursive( $kubio_attr, $kubio_attr_replacement );
473
474 Arr::set( $block, 'attrs.kubio', $kubio_attr );
475 } else {
476 $next_inner_blocks = $this->updateBlocks( $block['innerBlocks'], $item_data );
477
478 // let the innerContent placeholders - null means inner block
479 $block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
480
481 if ( count( $block['innerContent'] ) === 0 ) {
482 $block['innerContent'] = array( $block['innerHTML'] );
483 }
484
485 $block['innerBlocks'] = $next_inner_blocks;
486 }
487
488 if ( $block ) {
489 $parsed_blocks[ $index ] = $block;
490 }
491 }
492
493 return $parsed_blocks;
494 }
495
496 private function normalizeBlockData( $parsed_block, $data, $item_data ) {
497 $block_name = $parsed_block['blockName'];
498
499 if ( $block_name === 'kubio/buttongroup' ) {
500 list( $parsed_block, $data ) = $this->normalizeButtonGroup( $parsed_block, $data, $item_data );
501 }
502
503 if ( in_array( $block_name, array( 'kubio/text', 'kubio/heading' ), true ) ) {
504 list( $parsed_block, $data ) = $this->normalizeTexts( $parsed_block, $data, $item_data );
505 }
506
507 if ( $block_name === 'kubio/navigation' ) {
508 list( $parsed_block, $data ) = $this->normalizeNavigation( $parsed_block, $data, $item_data );
509 }
510 if ( $block_name === 'kubio/iconlist' ) {
511 list( $parsed_block, $data ) = $this->normalizeIconsLists( $parsed_block, $data, $item_data );
512 }
513 if ( $block_name === 'kubio/social-icons' ) {
514 list( $parsed_block, $data ) = $this->normalizeIconsLists( $parsed_block, $data, $item_data );
515 }
516
517 if ( $block_name === 'kubio/hero' ) {
518 list( $parsed_block, $data ) = $this->normalizeHero( $parsed_block, $data, $item_data );
519 }
520
521 return array( $parsed_block, $data );
522 }
523
524 private function normalizeButtonGroup( $parsed_block, $data, $item_data ) {
525 $text_align = Arr::get( $data, 'style.textAlign', 'center' );
526 Arr::set( $data, 'style.descendants.spacing.textAlign', $text_align );
527 Arr::forget( $data, 'style.textAlign' );
528
529 $buttons = Arr::get( $item_data, 'value', array() );
530 $buttons = $this->maybeDecodeArray( $buttons );
531
532 if ( is_array( $buttons ) ) {
533 $buttons_order = array();
534 $next_inner_blocks = array();
535 foreach ( $buttons as $button ) {
536 $buttons_order[] = intval( $button['button_type'] );
537 }
538
539 foreach ( $buttons_order as $index => $button_index ) {
540 $next_inner_blocks[ $index ] = $parsed_block['innerBlocks'] [ $button_index ];
541 }
542
543 foreach ( $next_inner_blocks as $index => $inner_block ) {
544 $button = $buttons[ $index ];
545
546 $inner_block['innerHTML'] = $button['label'];
547 Arr::set( $inner_block, 'attrs.link.value', $button['url'] );
548
549 $next_inner_blocks[ $index ] = $inner_block;
550 }
551
552 $parsed_block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
553 $parsed_block['innerBlocks'] = $next_inner_blocks;
554 }
555
556 return array( $parsed_block, $data );
557 }
558
559 private function maybeDecodeArray( $data ) {
560 if ( is_array( $data ) ) {
561 return $data;
562 }
563
564 $decoded = json_decode( $data, true );
565
566 if ( json_last_error() === JSON_ERROR_NONE ) {
567 return $decoded;
568 }
569
570 $decoded = json_decode( urldecode( $data ), true );
571
572 if ( json_last_error() === JSON_ERROR_NONE ) {
573 return $decoded;
574 }
575
576 return array();
577
578 }
579
580 private function normalizeTexts( $parsed_block, $data, $item_data ) {
581 if ( Arr::get( $item_data, 'show' ) === false ) {
582 return array( null, $data );
583 }
584
585 $block_name = $parsed_block['blockName'];
586 if ( $block_name === 'kubio/heading' ) {
587 $value = Arr::get( $item_data, 'value', '' );
588 $parsed_block['innerHTML'] = $value;
589 }
590
591 // modify block innerContent to the new value
592 if ( $block_name === 'kubio/text' ) {
593 $value = Arr::get( $item_data, 'value', '' );
594 $parsed_block['innerHTML'] = $value;
595 }
596
597 return array( $parsed_block, $data );
598 }
599
600 private function normalizeNavigation( $parsed_block, $data, $item_data ) {
601 $show_top_bar = Arr::get( $item_data, 'props.showTopBar', false );
602 if ( ! $show_top_bar ) {
603 foreach ( $parsed_block['innerBlocks'] as $index => $inner_block ) {
604 if ( $inner_block['blockName'] === 'kubio/navigation-top-bar' ) {
605 array_splice( $parsed_block['innerBlocks'], $index, 1 );
606 }
607 }
608 $parsed_block['innerContent'] = array_fill( 0, count( $parsed_block['innerBlocks'] ), null );
609 } else {
610 foreach ( $parsed_block['innerBlocks'] as $index => $inner_block ) {
611 if ( $inner_block['blockName'] === 'kubio/navigation-top-bar' ) {
612 $nav_width = Arr::get( $data, 'props.width' );
613 Arr::set( $parsed_block, "innerBlocks.{$index}.attrs.kubio.props.width", $nav_width );
614 break;
615 }
616 }
617 }
618
619 $layout_type = Arr::get( $data, 'props.layoutType' );
620 Arr::forget( $data, 'props.layoutType' );
621
622 if ( $layout_type === 'logo-above-menu' ) {
623 $navigation_section_index = count( $parsed_block['innerBlocks'] ) - 1;
624 $navigation_row_path = "innerBlocks.{$navigation_section_index}.innerBlocks.0.innerBlocks.0";
625 $row = Arr::get( $parsed_block, $navigation_row_path );
626
627 $next_columns = array();
628
629 foreach ( $row['innerBlocks'] as $index => $column ) {
630 $column_type = Arr::get( $column, 'attrs.kubio.props.internal.navContent.type' );
631
632 if ( in_array( $column_type, array( 'logo', 'menu' ), true ) ) {
633 Arr::set(
634 $column,
635 'attrs.kubio._style.descendants.container.columnWidth',
636 array(
637 'type' => 'custom',
638 'custom' => array(
639 'value' => 100,
640 'unit' => '%',
641 ),
642 )
643 );
644
645 $next_columns[] = $column;
646 }
647 }
648
649 $row['innerBlocks'] = $next_columns;
650 $row['innerContent'] = array_fill( 0, count( $next_columns ), null );
651
652 Arr::set( $parsed_block, $navigation_row_path, $row );
653 }
654
655 $padding = Arr::get( $data, 'style.padding.top' );
656 Arr::forget( $data, 'style.padding' );
657 Arr::forget( $data, 'style.nav' );
658
659 Arr::set( $data, 'style.descendants.section.padding.top', $padding );
660 Arr::set( $data, 'style.descendants.section.padding.bottom', $padding );
661
662 return array( $parsed_block, $data );
663 }
664
665 private function normalizeIconsLists( $parsed_block, $data, $item_data ) {
666 $show = Arr::get( $item_data, 'show', false );
667 $block_name = $parsed_block['blockName'];
668
669 if ( ! $show ) {
670 return null;
671 }
672
673 if ( $block_name === 'kubio/social-icons' ) {
674 //Set default spacing for social icons
675 Arr::set(
676 $data,
677 'style.descendants.icon.margin.right',
678 array(
679 'value' => 10,
680 'unit' => 'px',
681 )
682 );
683 }
684
685 $first_icon = Arr::get( $parsed_block, 'innerBlocks.0', null );
686
687 if ( ! $first_icon ) {
688 return $parsed_block;
689 }
690
691 $icons_data = $this->maybeDecodeArray( Arr::get( $item_data, 'localProps.iconList', array() ) );
692 $next_inner_blocks = array();
693
694 foreach ( $icons_data as $icon ) {
695 $next_inner = $first_icon;
696
697 if ( $block_name === 'kubio/iconlist' ) {
698 Arr::set( $next_inner, 'attrs.text', Arr::get( $icon, 'text', '' ) );
699 Arr::set( $next_inner, 'innerHTML', Arr::get( $icon, 'text', '' ) );
700 Arr::set( $next_inner, 'innerContent.0', Arr::get( $icon, 'text', '' ) );
701 Arr::set( $next_inner, 'attrs.icon', Arr::get( $icon, 'icon.name' ) );
702 } else {
703 Arr::set(
704 $next_inner,
705 'attrs.icon',
706 array(
707 'name' => Arr::get( $icon, 'icon.name' ),
708 )
709 );
710 }
711
712 Arr::set(
713 $next_inner,
714 'attrs.link',
715 array(
716 'typeOpenLink' => 'sameWindow',
717 'value' => Arr::get( $icon, 'link_value', '' ),
718 'noFollow' => false,
719 'lightboxMedia' => '',
720 )
721 );
722
723 $next_inner_blocks[] = $next_inner;
724
725 }
726
727 if ( ! count( $next_inner_blocks ) ) {
728 return null;
729 }
730
731 $parsed_block['innerBlocks'] = $next_inner_blocks;
732 $parsed_block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
733
734 return array( $parsed_block, $data );
735 }
736
737 private function normalizeHero( $parsed_block, $data, $item_data ) {
738
739 $bottom_separator = Arr::get( $data, 'style.descendants.outer.separators.separatorBottom' );
740 $bg_type = Arr::get( $data, 'style.descendants.outer.background.type' );
741 $bg_slides = Arr::get( $data, 'style.descendants.outer.background.slideshow.slides' );
742 $gradient_bg = Arr::get( $data, 'style.descendants.outer.background.image.0.source.gradient' );
743 $overlay_gradient = Arr::get( $data, 'style.descendants.outer.background.overlay.gradient' );
744 $overlay_color = Arr::get( $data, 'style.descendants.outer.background.overlay.color' );
745 $overlay_gradient_opacity = Arr::get( $data, 'style.descendants.outer.background.overlay.gradient_opacity', 50 );
746 $internal_video = Arr::get( $data, 'style.descendants.outer.background.video.internalUrl', '' );
747 $external_video = Arr::get( $data, 'style.descendants.outer.background.video.externalUrl', '' );
748 $video_type = Arr::get( $data, 'style.descendants.outer.background.video.videoType', 'external' );
749
750 Arr::forget( $data, 'style.descendants.outer.background.slideshow.slides' );
751 Arr::forget( $data, 'style.descendants.outer.background.overlay.gradient_opacity' );
752 Arr::forget( $data, 'style.descendants.outer.separators.separatorBottom' );
753 Arr::forget( $data, 'style.descendants.outer.background.video.internalUrl' );
754 Arr::forget( $data, 'style.descendants.outer.background.video.externalUrl' );
755 Arr::forget( $data, 'style.descendants.outer.background.video.videoType' );
756
757 $bg_slides = static::prepareBackgroundSlides( $bg_slides );
758
759 list($r,$g,$b,$a) = sscanf( $overlay_color['value'], 'rgba(%d,%d,%d,%f)' );
760 list($r,$g,$b,$a) = sscanf( $overlay_color['value'], 'rgba(%d,%d,%d,%f)' );
761 if ( is_numeric( $r ) && is_numeric( $g ) && is_numeric( $b ) && is_numeric( $a ) ) {
762 $overlay_color = array(
763 'opacity' => $a,
764 'value' => "rgb($r,$g,$b)",
765 );
766 }
767
768 if ( is_numeric( $internal_video ) ) {
769 $internal_video = wp_get_attachment_url( (int) $internal_video );
770 }
771
772 Arr::set( $data, 'style.descendants.outer.background.slideshow.slides', $bg_slides );
773 Arr::set( $data, 'style.descendants.outer.background.overlay.color', $overlay_color );
774 Arr::set( $data, 'style.descendants.outer.separators.bottom', $bottom_separator );
775 Arr::set( $data, 'style.descendants.outer.background.video.internal.url', $internal_video );
776 Arr::set( $data, 'style.descendants.outer.background.video.external.url', $external_video );
777 Arr::set( $data, 'style.descendants.outer.background.video.type', $video_type );
778 Arr::set( $data, 'style.descendants.outer.separators.bottom', $bottom_separator );
779 Arr::set( $data, 'style.descendants.outer.textAlign', 'center' );
780
781 if ( $gradient_bg ) {
782 Arr::set( $data, 'style.descendants.outer.background.image.0.source.gradient', $this->composeGradient( $gradient_bg ) );
783 }
784
785 if ( $bg_type === 'color' ) {
786 Arr::set(
787 $data,
788 'style.descendants.outer.background.type',
789 'none'
790 );
791 } else if ( $bg_type === 'image' || $bg_type === 'gradient' ) {
792 Arr::set( $data, 'style.descendants.outer.background.image.0.source.type', $bg_type );
793 }
794
795 if ( $overlay_gradient ) {
796 Arr::set( $data, 'style.descendants.outer.background.overlay.gradient', $this->composeGradient( $overlay_gradient, $overlay_gradient_opacity ) );
797 }
798
799 $shape_light = Arr::get( $data, 'style.descendants.outer.background.overlay.light' );
800 if ( ! $shape_light ) {
801 $shape_light = 0;
802 }
803 Arr::forget( $data, 'style.descendants.outer.background.overlay.light' );
804 Arr::set( $data, 'style.descendants.outer.background.overlay.shape.light', $shape_light );
805
806 $overlay_shape = Arr::get( $data, 'style.descendants.outer.background.overlay.shape.value' );
807
808 $titled_shapes = array( 'dots', 'left-tilted-lines', 'right-tilted-lines' );
809 Arr::set( $data, 'style.descendants.outer.background.overlay.shape.isTile', in_array( $overlay_shape, $titled_shapes, true ) );
810
811 $padding_style_path = 'style.descendants.outer.padding';
812 $hero_padding_top = Arr::get( $item_data, 'style.padding.top.value' );
813 $hero_padding_bottom = Arr::get( $item_data, 'style.padding.bottom.value' );
814 $full_height = Arr::get( $item_data, 'full_height' );
815
816 if (
817 ( Flags::get( 'import_design', false ) === true && Flags::get( 'start_source' ) !== 'customizer-sidebar' ) ||
818 ! $hero_padding_top || ! $hero_padding_bottom
819 ) {
820 if ( ! $hero_padding_top ) {
821 $hero_padding_top = Arr::get( $item_data, 'style.descendants.outer.padding.top.value' );
822 }
823 if ( ! $hero_padding_bottom ) {
824 $hero_padding_bottom = Arr::get( $item_data, 'style.descendants.outer.padding.bottom.value' );
825 }
826 }
827
828 if ( $full_height ) {
829 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'full-screen' );
830 } else {
831 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'fit-to-content' );
832 }
833
834 if ( $this->slug === 'header' ) {
835 $show_title = Arr::get( static::$current_data, 'header.title.show' );
836
837 if ( ! $show_title ) { // Title hidden
838 $parsed_block['innerBlocks'] = $this->removePageTitleBlocks( $parsed_block['innerBlocks'] );
839 } else {
840 //Align inner title
841 if ( class_exists( Defaults::class ) ) {
842 $default_inner_title_text_align = Defaults::get( 'header.title.style.descendants.text.textAlign', 'center' );
843 } else {
844 $default_inner_title_text_align = 'center';
845 }
846 $parsed_block = static::alignInnerTitle( $parsed_block, $default_inner_title_text_align );
847 }
848
849 $customizer_hero_padding = array(
850 'top' => array(
851 'value' => $hero_padding_top,
852 'unit' => 'px',
853 ),
854 'bottom' => array(
855 'value' => $hero_padding_bottom,
856 'unit' => 'px',
857 ),
858 'left' => array(
859 'value' => 20,
860 'unit' => 'px',
861 ),
862 'right' => array(
863 'value' => 20,
864 'unit' => 'px',
865 ),
866 );
867 }
868
869 if ( $this->slug === 'front-header' ) {
870 $show_buttons = $this->getHeroShowButtons();
871
872 if ( ! $show_buttons && isset( $parsed_block['innerBlocks'] ) ) {
873 $parsed_block['innerBlocks'] = $this->removeHeroButtons( $parsed_block['innerBlocks'] );
874 }
875
876 $customizer_hero_padding = array(
877 'top' => array(
878 'value' => $hero_padding_top,
879 'unit' => 'px',
880 ),
881 'bottom' => array(
882 'value' => $hero_padding_bottom,
883 'unit' => 'px',
884 ),
885 'left' => array(
886 'value' => 0,
887 'unit' => 'px',
888 ),
889 'right' => array(
890 'value' => 0,
891 'unit' => 'px',
892 ),
893 );
894
895 //Update hero text column width
896 $customizer_hero_column_width = get_theme_mod( 'front-header.hero.hero_column_width', Defaults::get( 'front-header.hero.hero_column_width', 66 ) );
897 $hero_custom_width = Arr::get( $parsed_block, 'innerBlocks.0.innerBlocks.0.attrs.kubio._style.descendants.container.columnWidth.custom.value' );
898 if ( $hero_custom_width && ( $hero_custom_width !== $customizer_hero_column_width ) ) {
899 Arr::set( $parsed_block, 'innerBlocks.0.innerBlocks.0.attrs.kubio._style.descendants.container.columnWidth.custom.value', $customizer_hero_column_width );
900 }
901 }
902
903 Arr::forget( $data, $padding_style_path );
904 Arr::set( $data, $padding_style_path, $customizer_hero_padding );
905
906 return array( $parsed_block, $data );
907 }
908
909 public function getHeroShowButtons() {
910 $show_buttons = Arr::get( static::$current_data, 'front-header.buttons.show' );
911
912 return $show_buttons;
913 }
914
915 /**
916 * Recursively removes kubio/buttongroup blocks from $blocks. Returns what remains after remove.
917 * @param $blocks
918 * @return array
919 */
920 public function removeHeroButtons( $blocks ) {
921 $blocks = array_filter(
922 $blocks,
923 function ( $block ) {
924 if ( $this->blockIsTypeOf( $block, 'kubio/buttongroup' ) ) {
925 return false;
926 }
927 return true;
928 }
929 );
930
931 foreach ( $blocks as &$block ) {
932 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
933 $block['innerBlocks'] = $this->removeHeroButtons( $block['innerBlocks'] );
934 }
935 }
936
937 return $blocks;
938 }
939
940 /**
941 * Recursively removes kubio/page-title blocks from $blocks. Returns what remains after remove.
942 * @param $blocks
943 * @return array
944 */
945 public function removePageTitleBlocks( $blocks ) {
946 $blocks = array_filter(
947 $blocks,
948 function ( $block ) {
949 if ( $this->blockIsTypeOf( $block, 'kubio/page-title' ) ) {
950 return false;
951 }
952 return true;
953 }
954 );
955
956 foreach ( $blocks as &$block ) {
957 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
958 $block['innerBlocks'] = $this->removePageTitleBlocks( $block['innerBlocks'] );
959 }
960 }
961
962 return $blocks;
963 }
964
965 /**
966 * Checks if block is of a specific type
967 * @param $block
968 * @param $type
969 * @return bool
970 */
971 public function blockIsTypeOf( $block, $type ) {
972 if ( isset( $block['blockName'] ) ) {
973 if ( $block['blockName'] === $type ) {
974 return true;
975 }
976 }
977 return false;
978 }
979
980 private function composeGradient( $value, $opacity = 100 ) {
981 $steps = $value['steps'];
982 $stepts_strings = array();
983
984 foreach ( $steps as $step ) {
985 $stepts_strings[] = $this->gradientStepToString( $step, $opacity );
986 }
987
988 $steps = implode( ', ', $stepts_strings );
989
990 return "linear-gradient({$value['angle']}deg, {$steps} )";
991 }
992
993 private function gradientStepToString( $step, $opacity = 100 ) {
994 if ( strpos( $step['color'], 'rgba' ) !== false || strpos( $step['color'], 'RGBA' ) !== false ) {
995 $color = $step['color'];
996 } else {
997 $color = Utils::hex2rgba( $step['color'], intval( $opacity ) / 100 );
998 }
999
1000 return "{$color} {$step['position']}%";
1001 }
1002
1003
1004 private function processHeader( $parsed_blocks ) {
1005 $current_part_data = $this->getCurrentPartData();
1006
1007 foreach ( $current_part_data as $item_data ) {
1008 $parsed_blocks = $this->updateBlocks( $parsed_blocks, $item_data );
1009 }
1010
1011 $current_hero_layout = Arr::get( $current_part_data, 'hero.props.heroSection.layout' );
1012
1013 $hero_column_width = Arr::get( $current_part_data, 'hero.hero_column_width' );
1014
1015 if ( $current_hero_layout ) {
1016 switch ( $current_hero_layout ) {
1017 case 'textOnly':
1018 $parsed_blocks = $this->removeHeroMediaColumn( $parsed_blocks );
1019 break;
1020 case 'textWithMediaOnLeft':
1021 $parsed_blocks = $this->swapHeroColumns( $parsed_blocks );
1022 break;
1023 }
1024 }
1025
1026 $parsed_blocks = $this->setColumnsWidth( $parsed_blocks, $hero_column_width );
1027 $parsed_blocks = $this->postProcessBlocks( $parsed_blocks, $current_part_data );
1028
1029 return $parsed_blocks;
1030 }
1031
1032 private function removeHeroMediaColumn( $parsed_blocks ) {
1033
1034 foreach ( $parsed_blocks as $index => $block ) {
1035 if ( Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
1036 array_splice( $parsed_blocks, $index, 1 );
1037 break;
1038 } else {
1039 $next_inner_blocks = $this->removeHeroMediaColumn( $block['innerBlocks'] );
1040
1041 // let the innerContent placeholders - null means inner block
1042 $parsed_blocks = $this->updateBlockInnerBlocks( $parsed_blocks, $index, $next_inner_blocks );
1043 }
1044 }
1045
1046 return $parsed_blocks;
1047 }
1048
1049 private function swapHeroColumns( $parsed_blocks ) {
1050
1051 foreach ( $parsed_blocks as $index => $block ) {
1052 $inner_blocks = $block['innerBlocks'];
1053
1054 $inner_blocks_are_hero_columns = false;
1055
1056 // check if inner blocks are hero columns, otherwise check each child children's
1057 foreach ( $inner_blocks as $inner_block ) {
1058 if ( Arr::get( $inner_block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
1059 $inner_blocks_are_hero_columns = true;
1060 break;
1061 }
1062 }
1063
1064 if ( $inner_blocks_are_hero_columns ) {
1065 $parsed_blocks[ $index ]['innerBlocks'] = array_reverse( $inner_blocks );
1066 break;
1067 } else {
1068 $parsed_blocks[ $index ]['innerBlocks'] = $this->swapHeroColumns( $inner_blocks );
1069 }
1070 }
1071
1072 return $parsed_blocks;
1073
1074 }
1075
1076 private function setColumnsWidth( $parsed_blocks, $text_column_width ) {
1077 foreach ( $parsed_blocks as $index => $block ) {
1078 $column_type = Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' );
1079 if ( $column_type ) {
1080 $value = $column_type === 'text' ? intval( $text_column_width ) : 100 - $text_column_width;
1081 Arr::set(
1082 $block,
1083 'attrs.kubio._style.descendants.container.columnWidth',
1084 array(
1085 'type' => 'custom',
1086 'custom' => array(
1087 'value' => $value,
1088 'unit' => '%',
1089 ),
1090 )
1091 );
1092
1093 $parsed_blocks[ $index ] = $block;
1094 } else {
1095 $parsed_blocks[ $index ]['innerBlocks'] = $this->setColumnsWidth( $block['innerBlocks'], $text_column_width );
1096 }
1097 }
1098
1099 return $parsed_blocks;
1100 }
1101
1102 public static function prepareBackgroundSlides( $slides ) {
1103 foreach ( $slides as $index => &$slide ) {
1104 $slide['id'] = $index + 1;
1105 $slide['icon'] = false;
1106 }
1107
1108 return $slides;
1109 }
1110
1111 public static function alignInnerTitle( $parsed_block, $text_align ) {
1112 if ( isset( $parsed_block['blockName'] ) && $parsed_block['blockName'] === 'kubio/page-title' ) {
1113 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.textAlign', $text_align );
1114 } else {
1115 if ( isset( $parsed_block['innerBlocks'] ) && count( $parsed_block['innerBlocks'] ) ) {
1116 foreach ( $parsed_block['innerBlocks'] as &$block ) {
1117 $block = static::alignInnerTitle( $block, $text_align );
1118 }
1119 }
1120 }
1121
1122 return $parsed_block;
1123 }
1124
1125 public static function themeHasModifiedOptions() {
1126 $keys = array_keys( get_theme_mods() );
1127
1128 foreach ( $keys as $key ) {
1129 if ( strpos( $key, 'header.' ) === 0 ||
1130 strpos( $key, 'front-header.' ) === 0 ||
1131 strpos( $key, 'blog_' ) === 0
1132 ) {
1133 return true;
1134 }
1135 }
1136 return false;
1137 }
1138
1139 static function removeSidebar( $parsed_blocks ) {
1140 $query_layout = null;
1141 $layout_index = null;
1142 $replaced = false;
1143
1144 foreach ( $parsed_blocks as $index => $block ) {
1145 if ( Arr::get( $block, 'blockName' ) === 'kubio/query-layout' ) {
1146 $query_layout = $block;
1147 $layout_index = $index;
1148 break;
1149 }
1150 }
1151
1152 if ( $query_layout ) {
1153 $row_inner_blocks = Arr::get( $query_layout, 'innerBlocks.0.innerBlocks' );
1154
1155 if ( count( $row_inner_blocks ) > 1 ) {
1156 foreach ( $row_inner_blocks as $index => $block ) {
1157 if ( Arr::get( $block, 'innerBlocks.0.blockName' ) === 'kubio/sidebar' ) {
1158 array_splice( $row_inner_blocks, $index, 1 );
1159 $replaced = true;
1160 break;
1161 }
1162 }
1163
1164 if ( $replaced ) {
1165 Arr::set( $parsed_blocks, "{$layout_index}.innerBlocks.0.innerBlocks", static::swapColumns( $row_inner_blocks ) );
1166 }
1167 }
1168 }
1169
1170 return $parsed_blocks;
1171
1172 }
1173
1174 static function swapColumns( $row ) {
1175 if ( ! is_array( $row ) || count( $row ) < 2 ) {
1176 return $row;
1177 }
1178
1179 $temp = $row[0];
1180 $row[0] = $row[1];
1181 $row[1] = $temp;
1182
1183 return $row;
1184 }
1185 }
1186