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