PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 1.6.4
Kubio AI Page Builder v1.6.4
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 3 years ago Blocks 3 years ago GlobalElements 4 years ago Layout 4 years ago License 4 years ago Separators 4 years ago StyleManager 3 years ago Styles 4 years ago Activation.php 3 years ago Backup.php 4 years ago CustomizerImporter.php 3 years ago Deactivation.php 4 years ago EditInKubioCustomizerPanel.php 4 years ago Element.php 4 years ago ElementBase.php 4 years ago Importer.php 3 years ago InnerBlocks.php 4 years ago LodashBasic.php 4 years ago Registry.php 4 years ago Utils.php 3 years ago
CustomizerImporter.php
1097 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
160 $parsed_blocks = $this->postProcessBlocks( $parsed_blocks, $this->getCurrentData() );
161
162 return $parsed_blocks;
163 }
164
165 private function postProcessBlocks( $parsed_blocks, $current_data ) {
166 foreach ( $parsed_blocks as $index => $block ) {
167 $parsed_blocks[ $index ] = $this->postProcessBlock( $block, $current_data );
168 $inner_blocks = $this->postProcessBlocks( $block['innerBlocks'], $current_data );
169 $parsed_blocks = $this->updateBlockInnerBlocks( $parsed_blocks, $index, $inner_blocks );
170 }
171
172 return $parsed_blocks;
173
174 }
175
176 private function postProcessBlock( $parsed_block, $current_data ) {
177 $block_name = $parsed_block['blockName'];
178
179 if ( $block_name === 'kubio/logo' ) {
180 $data = Arr::get( $current_data, 'logo' );
181 $parsed_block = $this->normalizeLogo( $parsed_block, $data );
182 }
183
184 if ( $block_name === 'kubio/image' ) {
185 $data = Arr::get( $current_data, 'hero.image' );
186 $parsed_block = $this->normalizeImage( $parsed_block, $data );
187 }
188
189 if ( $block_name === 'kubio/query-loop' ) {
190 $items_per_row = Arr::get( $current_data, 'blog_posts_per_row', 2 );
191 $masonry = Arr::get( $current_data, 'blog_enable_masonry', true );
192
193 Arr::set( $parsed_block, 'attrs.kubio.props.layout.itemsPerRow', intval( $items_per_row ) );
194
195 Arr::set( $parsed_block, 'attrs.masonry', $masonry );
196 }
197
198 if ( $block_name === 'kubio/post-featured-image' ) {
199 Arr::set(
200 $parsed_block,
201 'attrs.kubio.style.descendants.container.background.color',
202 Arr::get( $current_data, 'blog_post_thumb_placeholder_color', 'rgba(var(--kubio-color-5-variant-2),1)' )
203 );
204
205 Arr::set(
206 $parsed_block,
207 'attrs.showPlaceholder',
208 Arr::get( $current_data, 'blog_show_post_thumb_placeholder', true )
209 );
210 }
211 if ( $block_name === 'kubio/footer' ) {
212 Arr::set(
213 $parsed_block,
214 'attrs.kubio.props.useFooterParallax',
215 Arr::get( $current_data, 'footer.footer.props.useFooterParallax' )
216 );
217 }
218
219 if ( $block_name === 'kubio/dropdown-menu' && $this->slug === 'header' ) {
220 $data = $this->getCurrentData();
221 $menu_effect = Arr::get( $data, 'front-header.header-menu.props.hoverEffect.border.effect' );
222 Arr::set( $parsed_block, 'attrs.kubio.props.hoverEffect.border.effect', $menu_effect );
223 }
224
225 return $parsed_block;
226 }
227
228 private function normalizeLogo( $parsed_block, $data ) {
229
230 $layout_type = Arr::get( $data, 'props.layoutType', null );
231 $current_data = $this->getCurrentData();
232 $menu_layout_type = Arr::get( $current_data, $this->slug . '.navigation.props.layoutType' );
233
234 if ( $layout_type ) {
235 Arr::set( $parsed_block, 'attrs.kubio.props.layoutType', $layout_type );
236
237 if ( $menu_layout_type === 'logo-above-menu' ) {
238 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.alignItems', 'center' );
239 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.justifyContent', 'center' );
240 }
241 }
242
243 if ( $alternate_logo = Arr::get( $current_data, 'alternate_logo', false ) ) {
244 kubio_set_global_data( 'alternateLogo', wp_get_attachment_image_url( intval( $alternate_logo ), 'full' ) );
245 }
246
247 return $parsed_block;
248 }
249
250 private function normalizeImage( $parsed_block, $data ) {
251
252 if ( ! $data ) {
253 return $parsed_block;
254 }
255
256 $style_ref = Arr::get( $data, 'styleRef' );
257
258 if ( $style_ref === Arr::get( $parsed_block, 'attrs.kubio.styleRef' ) ) {
259 $url = Arr::get( $data, 'localProps.url', '' );
260 Arr::set(
261 $parsed_block,
262 'attrs.url',
263 $url
264 );
265 Arr::set(
266 $parsed_block,
267 'attrs.id',
268 attachment_url_to_postid( $url )
269 );
270 Arr::set(
271 $parsed_block,
272 'attrs.alt',
273 __( 'Image', 'kubio' )
274 );
275 }
276
277 $style = $data['style'];
278 $x_value = Arr::get( $style, 'descendants.frameImage.transform.translate.x_value' );
279 $width = Arr::get( $style, 'descendants.frameImage.width' );
280 $height = Arr::get( $style, 'descendants.frameImage.height' );
281 $y_value = Arr::get( $style, 'descendants.frameImage.transform.translate.y_value' );
282
283 Arr::set(
284 $style,
285 'descendants.frameImage.width',
286 array(
287 'value' => $width,
288 'unit' => '%',
289 )
290 );
291 Arr::set(
292 $style,
293 'descendants.frameImage.height',
294 array(
295 'value' => $height,
296 'unit' => '%',
297 )
298 );
299
300 Arr::set(
301 $style,
302 'descendants.frameImage.transform.translate',
303 array(
304 array(
305 'axis' => 'x',
306 'value' => array(
307 'value' => $x_value,
308 'unit' => '%',
309 ),
310 ),
311 array(
312 'axis' => 'y',
313 'value' => array(
314 'value' => $y_value,
315 'unit' => '%',
316 ),
317 ),
318 array(
319 'axis' => 'y',
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 } else {
379 Arr::forget( $style, 'descendants.frameImage.zIndex' );
380 }
381
382 Arr::set( $parsed_block, 'attrs.kubio.style', $style );
383 Arr::set(
384 $parsed_block,
385 'attrs.kubio.props.frame',
386 array(
387 'type' => Arr::get( $props, 'frame.type' ),
388 'enabled' => Arr::get( $props, 'enabledFrameOption' ),
389 'showFrameOverImage' => Arr::get( $props, 'showFrameOverImage' ),
390 )
391 );
392
393 return $parsed_block;
394 }
395
396 /**
397 * @param array $parsed_blocks
398 * @param $block_index
399 * @param $next_inner_blocks
400 *
401 * @return array
402 */
403 private function updateBlockInnerBlocks( array $parsed_blocks, $block_index, $next_inner_blocks ) {
404 $parsed_blocks[ $block_index ]['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
405
406 if ( count( $parsed_blocks[ $block_index ]['innerContent'] ) === 0 ) {
407 $parsed_blocks[ $block_index ]['innerContent'] = array( $parsed_blocks[ $block_index ]['innerHTML'] );
408 }
409
410 $parsed_blocks[ $block_index ]['innerBlocks'] = $next_inner_blocks;
411
412 return $parsed_blocks;
413 }
414
415 private function processFooter( $parsed_blocks ) {
416
417 $current_part_data = $this->getCurrentPartData();
418
419 foreach ( $current_part_data as $item_data ) {
420 $parsed_blocks = $this->updateBlocks( $parsed_blocks, $item_data );
421 }
422
423 return $parsed_blocks;
424 }
425
426 private function getCurrentPartData() {
427 return $this->getCurrentData()[ $this->slug ];
428 }
429
430 private function updateBlocks( $parsed_blocks, $item_data ) {
431
432 foreach ( $parsed_blocks as $index => &$block ) {
433
434 if ( ! isset( $item_data['styleRef'] ) ) {
435 continue;
436 }
437
438 $styleRef = Arr::get( $block, 'attrs.kubio.styleRef', null );
439
440 if ( $styleRef === $item_data['styleRef'] ) {
441 $kubio_attr = Arr::get( $block, 'attrs.kubio' );
442 $style = Arr::get( $item_data, 'style', array() );
443 $props = Arr::get( $item_data, 'props', array() );
444 $local_props = Arr::get( $item_data, 'localProps', array() );
445
446 list( $block, $kubio_attr_replacement ) = $this->normalizeBlockData(
447 $block,
448 array(
449 'style' => $style,
450 'props' => $props,
451 ),
452 $item_data
453 );
454
455 // if some prop in normalization nullified the block
456 if ( $block === null ) {
457 array_splice( $parsed_blocks, $index, 1 );
458 continue;
459 }
460
461 foreach ( $local_props as $attr => $value ) {
462 Arr::set( $block, "attrs.{$attr}", $value );
463 }
464
465 $kubio_attr = array_replace_recursive( $kubio_attr, $kubio_attr_replacement );
466
467 Arr::set( $block, 'attrs.kubio', $kubio_attr );
468 } else {
469 $next_inner_blocks = $this->updateBlocks( $block['innerBlocks'], $item_data );
470
471 // let the innerContent placeholders - null means inner block
472 $block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
473
474 if ( count( $block['innerContent'] ) === 0 ) {
475 $block['innerContent'] = array( $block['innerHTML'] );
476 }
477
478 $block['innerBlocks'] = $next_inner_blocks;
479 }
480
481 if ( $block ) {
482 $parsed_blocks[ $index ] = $block;
483 }
484 }
485
486 return $parsed_blocks;
487 }
488
489 private function normalizeBlockData( $parsed_block, $data, $item_data ) {
490 $block_name = $parsed_block['blockName'];
491
492 if ( $block_name === 'kubio/buttongroup' ) {
493 list( $parsed_block, $data ) = $this->normalizeButtonGroup( $parsed_block, $data, $item_data );
494 }
495
496 if ( in_array( $block_name, array( 'kubio/text', 'kubio/heading' ) ) ) {
497 list( $parsed_block, $data ) = $this->normalizeTexts( $parsed_block, $data, $item_data );
498 }
499
500 if ( $block_name === 'kubio/navigation' ) {
501 list( $parsed_block, $data ) = $this->normalizeNavigation( $parsed_block, $data, $item_data );
502 }
503 if ( $block_name === 'kubio/iconlist' ) {
504 list( $parsed_block, $data ) = $this->normalizeIconsLists( $parsed_block, $data, $item_data );
505 }
506 if ( $block_name === 'kubio/social-icons' ) {
507 list( $parsed_block, $data ) = $this->normalizeIconsLists( $parsed_block, $data, $item_data );
508 }
509
510 if ( $block_name === 'kubio/hero' ) {
511 list( $parsed_block, $data ) = $this->normalizeHero( $parsed_block, $data, $item_data );
512 }
513
514 return array( $parsed_block, $data );
515 }
516
517 private function normalizeButtonGroup( $parsed_block, $data, $item_data ) {
518 $text_align = Arr::get( $data, 'style.textAlign', 'center' );
519 Arr::set( $data, 'style.descendants.spacing.textAlign', $text_align );
520 Arr::forget( $data, 'style.textAlign' );
521
522 $buttons = Arr::get( $item_data, 'value', array() );
523 $buttons = $this->maybeDecodeArray( $buttons );
524
525 if ( is_array( $buttons ) ) {
526 $buttons_order = array();
527 $next_inner_blocks = array();
528 foreach ( $buttons as $button ) {
529 $buttons_order[] = intval( $button['button_type'] );
530 }
531
532 foreach ( $buttons_order as $index => $button_index ) {
533 $next_inner_blocks[ $index ] = $parsed_block['innerBlocks'] [ $button_index ];
534 }
535
536 foreach ( $next_inner_blocks as $index => $inner_block ) {
537 $button = $buttons[ $index ];
538
539 $inner_block['innerHTML'] = $button['label'];
540 Arr::set( $inner_block, 'attrs.link.value', $button['url'] );
541
542 $next_inner_blocks[ $index ] = $inner_block;
543 }
544
545 $parsed_block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
546 $parsed_block['innerBlocks'] = $next_inner_blocks;
547 }
548
549 return array( $parsed_block, $data );
550 }
551
552 private function maybeDecodeArray( $data ) {
553 if ( is_array( $data ) ) {
554 return $data;
555 }
556
557 $decoded = json_decode( $data, true );
558
559 if ( json_last_error() === JSON_ERROR_NONE ) {
560 return $decoded;
561 }
562
563 $decoded = json_decode( urldecode( $data ), true );
564
565 if ( json_last_error() === JSON_ERROR_NONE ) {
566 return $decoded;
567 }
568
569 return array();
570
571 }
572
573 private function normalizeTexts( $parsed_block, $data, $item_data ) {
574 if ( Arr::get( $item_data, 'show' ) === false ) {
575 return array( null, $data );
576 }
577
578 $block_name = $parsed_block['blockName'];
579 if ( $block_name === 'kubio/heading' ) {
580 $value = Arr::get( $item_data, 'value', '' );
581 $parsed_block['innerHTML'] = $value;
582 }
583
584 // modify block innerContent to the new value
585 if ( $block_name === 'kubio/text' ) {
586 $value = Arr::get( $item_data, 'value', '' );
587 $parsed_block['innerHTML'] = $value;
588 }
589
590 return array( $parsed_block, $data );
591 }
592
593 private function normalizeNavigation( $parsed_block, $data, $item_data ) {
594 $show_top_bar = Arr::get( $item_data, 'props.showTopBar', false );
595 if ( ! $show_top_bar ) {
596 foreach ( $parsed_block['innerBlocks'] as $index => $inner_block ) {
597 if ( $inner_block['blockName'] === 'kubio/navigation-top-bar' ) {
598 array_splice( $parsed_block['innerBlocks'], $index, 1 );
599 }
600 }
601 $parsed_block['innerContent'] = array_fill( 0, count( $parsed_block['innerBlocks'] ), null );
602 } else {
603 foreach ( $parsed_block['innerBlocks'] as $index => $inner_block ) {
604 if ( $inner_block['blockName'] === 'kubio/navigation-top-bar' ) {
605 $nav_width = Arr::get( $data, 'props.width' );
606 Arr::set( $parsed_block, "innerBlocks.{$index}.attrs.kubio.props.width", $nav_width );
607 break;
608 }
609 }
610 }
611
612 $layout_type = Arr::get( $data, 'props.layoutType' );
613 Arr::forget( $data, 'props.layoutType' );
614
615 if ( $layout_type === 'logo-above-menu' ) {
616 $navigation_section_index = count( $parsed_block['innerBlocks'] ) - 1;
617 $navigation_row_path = "innerBlocks.{$navigation_section_index}.innerBlocks.0.innerBlocks.0";
618 $row = Arr::get( $parsed_block, $navigation_row_path );
619
620 $next_columns = array();
621
622 foreach ( $row['innerBlocks'] as $index => $column ) {
623 $column_type = Arr::get( $column, 'attrs.kubio.props.internal.navContent.type' );
624
625 if ( in_array( $column_type, array( 'logo', 'menu' ) ) ) {
626 Arr::set(
627 $column,
628 'attrs.kubio._style.descendants.container.columnWidth',
629 array(
630 'type' => 'custom',
631 'custom' => array(
632 'value' => 100,
633 'unit' => '%',
634 ),
635 )
636 );
637
638 $next_columns[] = $column;
639 }
640 }
641
642 $row['innerBlocks'] = $next_columns;
643 $row['innerContent'] = array_fill( 0, count( $next_columns ), null );
644
645 Arr::set( $parsed_block, $navigation_row_path, $row );
646 }
647
648 $padding = Arr::get( $data, 'style.padding.top' );
649 Arr::forget( $data, 'style.padding' );
650 Arr::forget( $data, 'style.nav' );
651
652 Arr::set( $data, 'style.descendants.section.padding.top', $padding );
653 Arr::set( $data, 'style.descendants.section.padding.bottom', $padding );
654
655 return array( $parsed_block, $data );
656 }
657
658 private function normalizeIconsLists( $parsed_block, $data, $item_data ) {
659 $show = Arr::get( $item_data, 'show', false );
660 $block_name = $parsed_block['blockName'];
661
662 if ( ! $show ) {
663 return null;
664 }
665
666 $first_icon = Arr::get( $parsed_block, 'innerBlocks.0', null );
667
668 if ( ! $first_icon ) {
669 return $parsed_block;
670 }
671
672 $icons_data = $this->maybeDecodeArray( Arr::get( $item_data, 'localProps.iconList', array() ) );
673 $next_inner_blocks = array();
674
675 foreach ( $icons_data as $icon ) {
676 $next_inner = $first_icon;
677
678 if ( $block_name === 'kubio/iconlist' ) {
679 Arr::set( $next_inner, 'attrs.text', Arr::get( $icon, 'text', '' ) );
680 Arr::set( $next_inner, 'innerHTML', Arr::get( $icon, 'text', '' ) );
681 Arr::set( $next_inner, 'innerContent.0', Arr::get( $icon, 'text', '' ) );
682 Arr::set( $next_inner, 'attrs.icon', Arr::get( $icon, 'icon.name' ) );
683 } else {
684 Arr::set(
685 $next_inner,
686 'attrs.icon',
687 array(
688 'name' => Arr::get( $icon, 'icon.name' ),
689 )
690 );
691 }
692
693 Arr::set(
694 $next_inner,
695 'attrs.link',
696 array(
697 'typeOpenLink' => 'sameWindow',
698 'value' => Arr::get( $icon, 'link_value', '' ),
699 'noFollow' => false,
700 'lightboxMedia' => '',
701 )
702 );
703
704 $next_inner_blocks[] = $next_inner;
705
706 }
707
708 if ( ! count( $next_inner_blocks ) ) {
709 return null;
710 }
711
712 $parsed_block['innerBlocks'] = $next_inner_blocks;
713 $parsed_block['innerContent'] = array_fill( 0, count( $next_inner_blocks ), null );
714
715 return array( $parsed_block, $data );
716 }
717
718 private function normalizeHero( $parsed_block, $data, $item_data ) {
719
720 $bottom_separator = Arr::get( $data, 'style.descendants.outer.separators.separatorBottom' );
721 $bg_type = Arr::get( $data, 'style.descendants.outer.background.type' );
722 $bg_slides = Arr::get( $data, 'style.descendants.outer.background.slideshow.slides' );
723 $gradient_bg = Arr::get( $data, 'style.descendants.outer.background.image.0.source.gradient' );
724 $overlay_gradient = Arr::get( $data, 'style.descendants.outer.background.overlay.gradient' );
725 $overlay_color = Arr::get( $data, 'style.descendants.outer.background.overlay.color' );
726 $overlay_gradient_opacity = Arr::get( $data, 'style.descendants.outer.background.overlay.gradient_opacity', 50 );
727 $internal_video = Arr::get( $data, 'style.descendants.outer.background.video.internalUrl', '' );
728 $external_video = Arr::get( $data, 'style.descendants.outer.background.video.externalUrl', '' );
729 $video_type = Arr::get( $data, 'style.descendants.outer.background.video.videoType', 'external' );
730
731 Arr::forget( $data, 'style.descendants.outer.background.slideshow.slides' );
732 Arr::forget( $data, 'style.descendants.outer.background.overlay.gradient_opacity' );
733 Arr::forget( $data, 'style.descendants.outer.separators.separatorBottom' );
734 Arr::forget( $data, 'style.descendants.outer.background.video.internalUrl' );
735 Arr::forget( $data, 'style.descendants.outer.background.video.externalUrl' );
736 Arr::forget( $data, 'style.descendants.outer.background.video.videoType' );
737
738 $bg_slides = static::prepareBackgroundSlides( $bg_slides );
739
740 list($r,$g,$b,$a) = sscanf( $overlay_color['value'], 'rgba(%d,%d,%d,%f)' );
741 list($r,$g,$b,$a) = sscanf( $overlay_color['value'], 'rgba(%d,%d,%d,%f)' );
742 if ( is_numeric( $r ) && is_numeric( $g ) && is_numeric( $b ) && is_numeric( $a ) ) {
743 $overlay_color = array(
744 'opacity' => $a,
745 'value' => "rgb($r,$g,$b)",
746 );
747 }
748
749 if ( is_numeric( $internal_video ) ) {
750 $internal_video = wp_get_attachment_url( (int) $internal_video );
751 }
752
753 Arr::set( $data, 'style.descendants.outer.background.slideshow.slides', $bg_slides );
754 Arr::set( $data, 'style.descendants.outer.background.overlay.color', $overlay_color );
755 Arr::set( $data, 'style.descendants.outer.separators.bottom', $bottom_separator );
756 Arr::set( $data, 'style.descendants.outer.background.video.internal.url', $internal_video );
757 Arr::set( $data, 'style.descendants.outer.background.video.external.url', $external_video );
758 Arr::set( $data, 'style.descendants.outer.background.video.type', $video_type );
759 Arr::set( $data, 'style.descendants.outer.separators.bottom', $bottom_separator );
760 Arr::set( $data, 'style.descendants.outer.textAlign', 'center' );
761
762 if ( $gradient_bg ) {
763 Arr::set( $data, 'style.descendants.outer.background.image.0.source.gradient', $this->composeGradient( $gradient_bg ) );
764 }
765
766 if ( $bg_type === 'image' ) {
767 Arr::set( $data, 'style.descendants.outer.background.image.0.source.type', $bg_type );
768 }
769
770 if ( $bg_type === 'gradient' ) {
771 Arr::set( $data, 'style.descendants.outer.background.image.0.source.type', $bg_type );
772 }
773
774 if ( $overlay_gradient ) {
775 Arr::set( $data, 'style.descendants.outer.background.overlay.gradient', $this->composeGradient( $overlay_gradient, $overlay_gradient_opacity ) );
776 }
777
778 $overlay_shape = Arr::get( $data, 'style.descendants.outer.background.overlay.shape.value' );
779
780 $titled_shapes = array( 'dots', 'left-tilted-lines', 'right-tilted-lines' );
781 Arr::set( $data, 'style.descendants.outer.background.overlay.shape.isTile', in_array( $overlay_shape, $titled_shapes ) );
782
783 $padding_style_path = 'style.descendants.outer.padding';
784 $hero_padding_top = Arr::get( $item_data, 'style.padding.top.value' );
785 $hero_padding_bottom = Arr::get( $item_data, 'style.padding.bottom.value' );
786 $full_height = Arr::get( $item_data, 'full_height' );
787
788 if ( Flags::get( 'import_design', false ) === true ) {
789 $hero_padding_top = Arr::get( $item_data, 'style.descendants.outer.padding.top.value' );
790 $hero_padding_bottom = Arr::get( $item_data, 'style.descendants.outer.padding.bottom.value' );
791 }
792
793 if ( $full_height ) {
794 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'full-screen' );
795 } else {
796 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'fit-to-content' );
797 }
798
799 if ( $this->slug === 'header' ) {
800 $show_title = Arr::get( static::$current_data, 'header.title.show' );
801
802 if ( ! $show_title ) { // Title hidden
803 $parsed_block['innerBlocks'] = $this->removePageTitleBlocks( $parsed_block['innerBlocks'] );
804 } else {
805 //Align inner title
806 if ( class_exists( Defaults::class ) ) {
807 $default_inner_title_text_align = Defaults::get( 'header.title.style.descendants.text.textAlign', 'center' );
808 } else {
809 $default_inner_title_text_align = 'center';
810 }
811 $parsed_block = static::alignInnerTitle( $parsed_block, $default_inner_title_text_align );
812 }
813
814 $customizer_hero_padding = array(
815 'top' => array(
816 'value' => $hero_padding_top,
817 'unit' => 'px',
818 ),
819 'bottom' => array(
820 'value' => $hero_padding_bottom,
821 'unit' => 'px',
822 ),
823 'left' => array(
824 'value' => 20,
825 'unit' => 'px',
826 ),
827 'right' => array(
828 'value' => 20,
829 'unit' => 'px',
830 ),
831 );
832 }
833
834 if ( $this->slug === 'front-header' ) {
835 $show_buttons = $this->getHeroShowButtons();
836
837 if ( ! $show_buttons && isset( $parsed_block['innerBlocks'] ) ) {
838 $parsed_block['innerBlocks'] = $this->removeHeroButtons( $parsed_block['innerBlocks'] );
839 }
840
841 $customizer_hero_padding = array(
842 'top' => array(
843 'value' => $hero_padding_top,
844 'unit' => 'px',
845 ),
846 'bottom' => array(
847 'value' => $hero_padding_bottom,
848 'unit' => 'px',
849 ),
850 'left' => array(
851 'value' => 0,
852 'unit' => 'px',
853 ),
854 'right' => array(
855 'value' => 0,
856 'unit' => 'px',
857 ),
858 );
859 }
860
861 Arr::forget( $data, $padding_style_path );
862 Arr::set( $data, $padding_style_path, $customizer_hero_padding );
863
864 return array( $parsed_block, $data );
865 }
866
867 public function getHeroShowButtons() {
868 $show_buttons = Arr::get( static::$current_data, 'front-header.buttons.show' );
869
870 return $show_buttons;
871 }
872
873 /**
874 * Recursively removes kubio/buttongroup blocks from $blocks. Returns what remains after remove.
875 * @param $blocks
876 * @return array
877 */
878 public function removeHeroButtons( $blocks ) {
879 $blocks = array_filter(
880 $blocks,
881 function ( $block ) {
882 if ( $this->blockIsTypeOf( $block, 'kubio/buttongroup' ) ) {
883 return false;
884 }
885 return true;
886 }
887 );
888
889 foreach ( $blocks as &$block ) {
890 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
891 $block['innerBlocks'] = $this->removeHeroButtons( $block['innerBlocks'] );
892 }
893 }
894
895 return $blocks;
896 }
897
898 /**
899 * Recursively removes kubio/page-title blocks from $blocks. Returns what remains after remove.
900 * @param $blocks
901 * @return array
902 */
903 public function removePageTitleBlocks( $blocks ) {
904 $blocks = array_filter(
905 $blocks,
906 function ( $block ) {
907 if ( $this->blockIsTypeOf( $block, 'kubio/page-title' ) ) {
908 return false;
909 }
910 return true;
911 }
912 );
913
914 foreach ( $blocks as &$block ) {
915 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
916 $block['innerBlocks'] = $this->removePageTitleBlocks( $block['innerBlocks'] );
917 }
918 }
919
920 return $blocks;
921 }
922
923 /**
924 * Checks if block is of a specific type
925 * @param $block
926 * @param $type
927 * @return bool
928 */
929 public function blockIsTypeOf( $block, $type ) {
930 if ( isset( $block['blockName'] ) ) {
931 if ( $block['blockName'] === $type ) {
932 return true;
933 }
934 }
935 return false;
936 }
937
938 private function composeGradient( $value, $opacity = 100 ) {
939 $steps = $value['steps'];
940 $stepts_strings = array();
941
942 foreach ( $steps as $step ) {
943 $stepts_strings[] = $this->gradientStepToString( $step, $opacity );
944 }
945
946 $steps = implode( ', ', $stepts_strings );
947
948 return "linear-gradient({$value['angle']}deg, {$steps} )";
949 }
950
951 private function gradientStepToString( $step, $opacity = 100 ) {
952 if ( strpos( $step['color'], 'rgba' ) !== false || strpos( $step['color'], 'RGBA' ) !== false ) {
953 $color = $step['color'];
954 } else {
955 $color = Utils::hex2rgba( $step['color'], intval( $opacity ) / 100 );
956 }
957
958 return "{$color} {$step['position']}%";
959 }
960
961
962 private function processHeader( $parsed_blocks ) {
963 $current_part_data = $this->getCurrentPartData();
964
965 foreach ( $current_part_data as $index => $item_data ) {
966 $parsed_blocks = $this->updateBlocks( $parsed_blocks, $item_data );
967 }
968
969 $current_hero_layout = Arr::get( $current_part_data, 'hero.props.heroSection.layout' );
970
971 $hero_column_width = Arr::get( $current_part_data, 'hero.hero_column_width' );
972
973 if ( $current_hero_layout ) {
974 switch ( $current_hero_layout ) {
975 case 'textOnly':
976 $parsed_blocks = $this->removeHeroMediaColumn( $parsed_blocks );
977 break;
978 case 'textWithMediaOnLeft':
979 $parsed_blocks = $this->swapHeroColumns( $parsed_blocks );
980 break;
981 }
982 }
983
984 $parsed_blocks = $this->setColumnsWidth( $parsed_blocks, $hero_column_width );
985 $parsed_blocks = $this->postProcessBlocks( $parsed_blocks, $current_part_data );
986
987 return $parsed_blocks;
988 }
989
990 private function removeHeroMediaColumn( $parsed_blocks ) {
991
992 foreach ( $parsed_blocks as $index => $block ) {
993 if ( Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
994 array_splice( $parsed_blocks, $index, 1 );
995 break;
996 } else {
997 $next_inner_blocks = $this->removeHeroMediaColumn( $block['innerBlocks'] );
998
999 // let the innerContent placeholders - null means inner block
1000 $parsed_blocks = $this->updateBlockInnerBlocks( $parsed_blocks, $index, $next_inner_blocks );
1001 }
1002 }
1003
1004 return $parsed_blocks;
1005 }
1006
1007 private function swapHeroColumns( $parsed_blocks ) {
1008
1009 foreach ( $parsed_blocks as $index => $block ) {
1010 $inner_blocks = $block['innerBlocks'];
1011
1012 $inner_blocks_are_hero_columns = false;
1013
1014 // check if inner blocks are hero columns, otherwise check each child children's
1015 foreach ( $inner_blocks as $inner_block ) {
1016 if ( Arr::get( $inner_block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
1017 $inner_blocks_are_hero_columns = true;
1018 break;
1019 }
1020 }
1021
1022 if ( $inner_blocks_are_hero_columns ) {
1023 $parsed_blocks[ $index ]['innerBlocks'] = array_reverse( $inner_blocks );
1024 break;
1025 } else {
1026 $parsed_blocks[ $index ]['innerBlocks'] = $this->swapHeroColumns( $inner_blocks );
1027 }
1028 }
1029
1030 return $parsed_blocks;
1031
1032 }
1033
1034 private function setColumnsWidth( $parsed_blocks, $text_column_width ) {
1035 foreach ( $parsed_blocks as $index => $block ) {
1036 $column_type = Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' );
1037 if ( $column_type ) {
1038 $value = $column_type === 'text' ? intval( $text_column_width ) : 100 - $text_column_width;
1039 Arr::set(
1040 $block,
1041 'attrs.kubio._style.descendants.container.columnWidth',
1042 array(
1043 'type' => 'custom',
1044 'custom' => array(
1045 'value' => $value,
1046 'unit' => '%',
1047 ),
1048 )
1049 );
1050
1051 $parsed_blocks[ $index ] = $block;
1052 } else {
1053 $parsed_blocks[ $index ]['innerBlocks'] = $this->setColumnsWidth( $block['innerBlocks'], $text_column_width );
1054 }
1055 }
1056
1057 return $parsed_blocks;
1058 }
1059
1060 public static function prepareBackgroundSlides( $slides ) {
1061 foreach ( $slides as $index => &$slide ) {
1062 $slide['id'] = $index + 1;
1063 $slide['icon'] = false;
1064 }
1065
1066 return $slides;
1067 }
1068
1069 public static function alignInnerTitle( $parsed_block, $textAlign ) {
1070 if ( isset( $parsed_block['blockName'] ) && $parsed_block['blockName'] === 'kubio/page-title' ) {
1071 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.textAlign', $textAlign );
1072 } else {
1073 if ( isset( $parsed_block['innerBlocks'] ) && count( $parsed_block['innerBlocks'] ) ) {
1074 foreach ( $parsed_block['innerBlocks'] as &$block ) {
1075 $block = static::alignInnerTitle( $block, $textAlign );
1076 }
1077 }
1078 }
1079
1080 return $parsed_block;
1081 }
1082
1083 public static function themeHasModifiedOptions() {
1084 $keys = array_keys( get_theme_mods() );
1085
1086 foreach ( $keys as $key ) {
1087 if ( strpos( $key, 'header.' ) === 0 ||
1088 strpos( $key, 'front-header.' ) === 0 ||
1089 strpos( $key, 'blog_' ) === 0
1090 ) {
1091 return true;
1092 }
1093 }
1094 return false;
1095 }
1096 }
1097