PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.6.1
Kubio AI Page Builder v2.6.1
2.9.1 2.9.0 2.8.6 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
1177 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.descendants.outer.padding.top.value' );
810 $hero_padding_bottom = Arr::get( $item_data, 'style.descendants.outer.padding.bottom.value' );
811 $hero_padding_left = Arr::get( $item_data, 'style.descendants.outer.padding.left', array( 'value' => 0, 'unit' => 'px' ) );
812 $hero_padding_right = Arr::get( $item_data, 'style.descendants.outer.padding.right', array( 'value' => 0, 'unit' => 'px' ) );
813 $full_height = Arr::get( $item_data, 'full_height' );
814
815 if (
816 ( Flags::get( 'import_design', false ) === true && Flags::get( 'start_source' ) !== 'customizer-sidebar' ) ||
817 ! $hero_padding_top || ! $hero_padding_bottom
818 ) {
819 if ( ! $hero_padding_top ) {
820 $hero_padding_top = Arr::get( $item_data, 'style.descendants.outer.padding.top.value' );
821 }
822 if ( ! $hero_padding_bottom ) {
823 $hero_padding_bottom = Arr::get( $item_data, 'style.descendants.outer.padding.bottom.value' );
824 }
825 }
826
827 if ( $full_height ) {
828 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'full-screen' );
829 } else {
830 Arr::set( $data, 'style.descendants.outer.customHeight.type', 'fit-to-content' );
831 }
832
833 if ( $this->slug === 'header' ) {
834 $show_title = Arr::get( static::$current_data, 'header.title.show' );
835
836 if ( ! $show_title ) { // Title hidden
837 $parsed_block['innerBlocks'] = $this->removePageTitleBlocks( $parsed_block['innerBlocks'] );
838 } else {
839 //Align inner title
840 if ( class_exists( Defaults::class ) ) {
841 $default_inner_title_text_align = Defaults::get( 'header.title.style.descendants.text.textAlign', 'center' );
842 } else {
843 $default_inner_title_text_align = 'center';
844 }
845 $parsed_block = static::alignInnerTitle( $parsed_block, $default_inner_title_text_align );
846 }
847
848 $customizer_hero_padding = array(
849 'top' => array(
850 'value' => $hero_padding_top,
851 'unit' => 'px',
852 ),
853 'bottom' => array(
854 'value' => $hero_padding_bottom,
855 'unit' => 'px',
856 ),
857 'left' => array(
858 'value' => 20,
859 'unit' => 'px',
860 ),
861 'right' => array(
862 'value' => 20,
863 'unit' => 'px',
864 ),
865 );
866 }
867
868 if ( $this->slug === 'front-header' ) {
869 $show_buttons = $this->getHeroShowButtons();
870
871 if ( ! $show_buttons && isset( $parsed_block['innerBlocks'] ) ) {
872 $parsed_block['innerBlocks'] = $this->removeHeroButtons( $parsed_block['innerBlocks'] );
873 }
874
875 $customizer_hero_padding = array(
876 'top' => array(
877 'value' => $hero_padding_top,
878 'unit' => 'px',
879 ),
880 'bottom' => array(
881 'value' => $hero_padding_bottom,
882 'unit' => 'px',
883 ),
884 'left' => $hero_padding_left,
885 'right' => $hero_padding_right,
886 );
887
888 //Update hero text column width
889 $customizer_hero_column_width = get_theme_mod( 'front-header.hero.hero_column_width', Defaults::get( 'front-header.hero.hero_column_width', 66 ) );
890 $hero_custom_width = Arr::get( $parsed_block, 'innerBlocks.0.innerBlocks.0.attrs.kubio._style.descendants.container.columnWidth.custom.value' );
891 if ( $hero_custom_width && ( $hero_custom_width !== $customizer_hero_column_width ) ) {
892 Arr::set( $parsed_block, 'innerBlocks.0.innerBlocks.0.attrs.kubio._style.descendants.container.columnWidth.custom.value', $customizer_hero_column_width );
893 }
894 }
895
896 Arr::forget( $data, $padding_style_path );
897 Arr::set( $data, $padding_style_path, $customizer_hero_padding );
898
899 return array( $parsed_block, $data );
900 }
901
902 public function getHeroShowButtons() {
903 $show_buttons = Arr::get( static::$current_data, 'front-header.buttons.show' );
904
905 return $show_buttons;
906 }
907
908 /**
909 * Recursively removes kubio/buttongroup blocks from $blocks. Returns what remains after remove.
910 * @param $blocks
911 * @return array
912 */
913 public function removeHeroButtons( $blocks ) {
914 $blocks = array_filter(
915 $blocks,
916 function ( $block ) {
917 if ( $this->blockIsTypeOf( $block, 'kubio/buttongroup' ) ) {
918 return false;
919 }
920 return true;
921 }
922 );
923
924 foreach ( $blocks as &$block ) {
925 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
926 $block['innerBlocks'] = $this->removeHeroButtons( $block['innerBlocks'] );
927 }
928 }
929
930 return $blocks;
931 }
932
933 /**
934 * Recursively removes kubio/page-title blocks from $blocks. Returns what remains after remove.
935 * @param $blocks
936 * @return array
937 */
938 public function removePageTitleBlocks( $blocks ) {
939 $blocks = array_filter(
940 $blocks,
941 function ( $block ) {
942 if ( $this->blockIsTypeOf( $block, 'kubio/page-title' ) ) {
943 return false;
944 }
945 return true;
946 }
947 );
948
949 foreach ( $blocks as &$block ) {
950 if ( isset( $block['innerBlocks'] ) && count( $block['innerBlocks'] ) ) {
951 $block['innerBlocks'] = $this->removePageTitleBlocks( $block['innerBlocks'] );
952 }
953 }
954
955 return $blocks;
956 }
957
958 /**
959 * Checks if block is of a specific type
960 * @param $block
961 * @param $type
962 * @return bool
963 */
964 public function blockIsTypeOf( $block, $type ) {
965 if ( isset( $block['blockName'] ) ) {
966 if ( $block['blockName'] === $type ) {
967 return true;
968 }
969 }
970 return false;
971 }
972
973 private function composeGradient( $value, $opacity = 100 ) {
974 $steps = $value['steps'];
975 $stepts_strings = array();
976
977 foreach ( $steps as $step ) {
978 $stepts_strings[] = $this->gradientStepToString( $step, $opacity );
979 }
980
981 $steps = implode( ', ', $stepts_strings );
982
983 return "linear-gradient({$value['angle']}deg, {$steps} )";
984 }
985
986 private function gradientStepToString( $step, $opacity = 100 ) {
987 if ( strpos( $step['color'], 'rgba' ) !== false || strpos( $step['color'], 'RGBA' ) !== false ) {
988 $color = $step['color'];
989 } else {
990 $color = Utils::hex2rgba( $step['color'], intval( $opacity ) / 100 );
991 }
992
993 return "{$color} {$step['position']}%";
994 }
995
996
997 private function processHeader( $parsed_blocks ) {
998 $current_part_data = $this->getCurrentPartData();
999
1000 foreach ( $current_part_data as $item_data ) {
1001 $parsed_blocks = $this->updateBlocks( $parsed_blocks, $item_data );
1002 }
1003
1004 $current_hero_layout = Arr::get( $current_part_data, 'hero.props.heroSection.layout' );
1005
1006 $hero_column_width = Arr::get( $current_part_data, 'hero.hero_column_width' );
1007
1008 if ( $current_hero_layout ) {
1009 switch ( $current_hero_layout ) {
1010 case 'textOnly':
1011 $parsed_blocks = $this->removeHeroMediaColumn( $parsed_blocks );
1012 break;
1013 case 'textWithMediaOnLeft':
1014 $parsed_blocks = $this->swapHeroColumns( $parsed_blocks );
1015 break;
1016 }
1017 }
1018
1019 $parsed_blocks = $this->setColumnsWidth( $parsed_blocks, $hero_column_width );
1020 $parsed_blocks = $this->postProcessBlocks( $parsed_blocks, $current_part_data );
1021
1022 return $parsed_blocks;
1023 }
1024
1025 private function removeHeroMediaColumn( $parsed_blocks ) {
1026
1027 foreach ( $parsed_blocks as $index => $block ) {
1028 if ( Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
1029 array_splice( $parsed_blocks, $index, 1 );
1030 break;
1031 } else {
1032 $next_inner_blocks = $this->removeHeroMediaColumn( $block['innerBlocks'] );
1033
1034 // let the innerContent placeholders - null means inner block
1035 $parsed_blocks = $this->updateBlockInnerBlocks( $parsed_blocks, $index, $next_inner_blocks );
1036 }
1037 }
1038
1039 return $parsed_blocks;
1040 }
1041
1042 private function swapHeroColumns( $parsed_blocks ) {
1043
1044 foreach ( $parsed_blocks as $index => $block ) {
1045 $inner_blocks = $block['innerBlocks'];
1046
1047 $inner_blocks_are_hero_columns = false;
1048
1049 // check if inner blocks are hero columns, otherwise check each child children's
1050 foreach ( $inner_blocks as $inner_block ) {
1051 if ( Arr::get( $inner_block, 'attrs.kubio.props.internal.heroSection.type' ) === 'media' ) {
1052 $inner_blocks_are_hero_columns = true;
1053 break;
1054 }
1055 }
1056
1057 if ( $inner_blocks_are_hero_columns ) {
1058 $parsed_blocks[ $index ]['innerBlocks'] = array_reverse( $inner_blocks );
1059 break;
1060 } else {
1061 $parsed_blocks[ $index ]['innerBlocks'] = $this->swapHeroColumns( $inner_blocks );
1062 }
1063 }
1064
1065 return $parsed_blocks;
1066 }
1067
1068 private function setColumnsWidth( $parsed_blocks, $text_column_width ) {
1069 foreach ( $parsed_blocks as $index => $block ) {
1070 $column_type = Arr::get( $block, 'attrs.kubio.props.internal.heroSection.type' );
1071 if ( $column_type ) {
1072 $value = $column_type === 'text' ? intval( $text_column_width ) : 100 - $text_column_width;
1073 Arr::set(
1074 $block,
1075 'attrs.kubio._style.descendants.container.columnWidth',
1076 array(
1077 'type' => 'custom',
1078 'custom' => array(
1079 'value' => $value,
1080 'unit' => '%',
1081 ),
1082 )
1083 );
1084
1085 $parsed_blocks[ $index ] = $block;
1086 } else {
1087 $parsed_blocks[ $index ]['innerBlocks'] = $this->setColumnsWidth( $block['innerBlocks'], $text_column_width );
1088 }
1089 }
1090
1091 return $parsed_blocks;
1092 }
1093
1094 public static function prepareBackgroundSlides( $slides ) {
1095 foreach ( $slides as $index => &$slide ) {
1096 $slide['id'] = $index + 1;
1097 $slide['icon'] = false;
1098 }
1099
1100 return $slides;
1101 }
1102
1103 public static function alignInnerTitle( $parsed_block, $text_align ) {
1104 if ( isset( $parsed_block['blockName'] ) && $parsed_block['blockName'] === 'kubio/page-title' ) {
1105 Arr::set( $parsed_block, 'attrs.kubio.style.descendants.container.textAlign', $text_align );
1106 } else {
1107 if ( isset( $parsed_block['innerBlocks'] ) && count( $parsed_block['innerBlocks'] ) ) {
1108 foreach ( $parsed_block['innerBlocks'] as &$block ) {
1109 $block = static::alignInnerTitle( $block, $text_align );
1110 }
1111 }
1112 }
1113
1114 return $parsed_block;
1115 }
1116
1117 public static function themeHasModifiedOptions() {
1118 $keys = array_keys( get_theme_mods() );
1119
1120 foreach ( $keys as $key ) {
1121 if ( strpos( $key, 'header.' ) === 0 ||
1122 strpos( $key, 'front-header.' ) === 0 ||
1123 strpos( $key, 'blog_' ) === 0
1124 ) {
1125 return true;
1126 }
1127 }
1128 return false;
1129 }
1130
1131 static function removeSidebar( $parsed_blocks ) {
1132 $query_layout = null;
1133 $layout_index = null;
1134 $replaced = false;
1135
1136 foreach ( $parsed_blocks as $index => $block ) {
1137 if ( Arr::get( $block, 'blockName' ) === 'kubio/query-layout' ) {
1138 $query_layout = $block;
1139 $layout_index = $index;
1140 break;
1141 }
1142 }
1143
1144 if ( $query_layout ) {
1145 $row_inner_blocks = Arr::get( $query_layout, 'innerBlocks.0.innerBlocks' );
1146
1147 if ( count( $row_inner_blocks ) > 1 ) {
1148 foreach ( $row_inner_blocks as $index => $block ) {
1149 if ( Arr::get( $block, 'innerBlocks.0.blockName' ) === 'kubio/sidebar' ) {
1150 array_splice( $row_inner_blocks, $index, 1 );
1151 $replaced = true;
1152 break;
1153 }
1154 }
1155
1156 if ( $replaced ) {
1157 Arr::set( $parsed_blocks, "{$layout_index}.innerBlocks.0.innerBlocks", static::swapColumns( $row_inner_blocks ) );
1158 }
1159 }
1160 }
1161
1162 return $parsed_blocks;
1163 }
1164
1165 static function swapColumns( $row ) {
1166 if ( ! is_array( $row ) || count( $row ) < 2 ) {
1167 return $row;
1168 }
1169
1170 $temp = $row[0];
1171 $row[0] = $row[1];
1172 $row[1] = $temp;
1173
1174 return $row;
1175 }
1176 }
1177