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