PluginProbe
Elementor Website Builder – more than just a page builder / 3.32.2
Elementor Website Builder – more than just a page builder v3.32.2
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / elements / section.php

section.php in Elementor Website Builder – more than just a page builder 3.32.2, at includes/elements/section.php

1,644 lines 39.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit; // Exit if accessed directly.
6 }
7
8 /**
9 * Elementor section element.
10 *
11 * Elementor section handler class is responsible for initializing the section
12 * element.
13 *
14 * @since 1.0.0
15 */
16 class Element_Section extends Element_Base {
17
18 /**
19 * Section predefined columns presets.
20 *
21 * Holds the predefined columns width for each columns count available by
22 * default by Elementor. Default is an empty array.
23 *
24 * Note that when the user creates a section he can define custom sizes for
25 * the columns. But Elementor sets default values for predefined columns.
26 *
27 * For example two columns 50% width each one, or three columns 33.33% each
28 * one. This property hold the data for those preset values.
29 *
30 * @since 1.0.0
31 * @access private
32 * @static
33 *
34 * @var array Section presets.
35 */
36 private static $presets = [];
37
38 /**
39 * Get element type.
40 *
41 * Retrieve the element type, in this case `section`.
42 *
43 * @since 2.1.0
44 * @access public
45 * @static
46 *
47 * @return string The type.
48 */
49 public static function get_type() {
50 return 'section';
51 }
52
53 /**
54 * Get section name.
55 *
56 * Retrieve the section name.
57 *
58 * @since 1.0.0
59 * @access public
60 *
61 * @return string Section name.
62 */
63 public function get_name() {
64 return 'section';
65 }
66
67 /**
68 * Get section title.
69 *
70 * Retrieve the section title.
71 *
72 * @since 1.0.0
73 * @access public
74 *
75 * @return string Section title.
76 */
77 public function get_title() {
78 return esc_html__( 'Section', 'elementor' );
79 }
80
81 /**
82 * Get section icon.
83 *
84 * Retrieve the section icon.
85 *
86 * @since 1.0.0
87 * @access public
88 *
89 * @return string Section icon.
90 */
91 public function get_icon() {
92 return 'eicon-columns';
93 }
94
95 protected function is_dynamic_content(): bool {
96 return false;
97 }
98
99 /**
100 * Get presets.
101 *
102 * Retrieve a specific preset columns for a given columns count, or a list
103 * of all the preset if no parameters passed.
104 *
105 * @since 1.0.0
106 * @access public
107 * @static
108 *
109 * @param int $columns_count Optional. Columns count. Default is null.
110 * @param int $preset_index Optional. Preset index. Default is null.
111 *
112 * @return array Section presets.
113 */
114 public static function get_presets( $columns_count = null, $preset_index = null ) {
115 if ( ! self::$presets ) {
116 self::init_presets();
117 }
118
119 $presets = self::$presets;
120
121 if ( null !== $columns_count ) {
122 $presets = $presets[ $columns_count ];
123 }
124
125 if ( null !== $preset_index ) {
126 $presets = $presets[ $preset_index ];
127 }
128
129 return $presets;
130 }
131
132 /**
133 * Initialize presets.
134 *
135 * Initializing the section presets and set the number of columns the
136 * section can have by default. For example a column can have two columns
137 * 50% width each one, or three columns 33.33% each one.
138 *
139 * Note that Elementor sections have default section presets but the user
140 * can set custom number of columns and define custom sizes for each column.
141
142 * @since 1.0.0
143 * @access public
144 * @static
145 */
146 public static function init_presets() {
147 $additional_presets = [
148 2 => [
149 [
150 'preset' => [ 33, 66 ],
151 ],
152 [
153 'preset' => [ 66, 33 ],
154 ],
155 ],
156 3 => [
157 [
158 'preset' => [ 25, 25, 50 ],
159 ],
160 [
161 'preset' => [ 50, 25, 25 ],
162 ],
163 [
164 'preset' => [ 25, 50, 25 ],
165 ],
166 [
167 'preset' => [ 16, 66, 16 ],
168 ],
169 ],
170 ];
171
172 foreach ( range( 1, 10 ) as $columns_count ) {
173 self::$presets[ $columns_count ] = [
174 [
175 'preset' => [],
176 ],
177 ];
178
179 $preset_unit = floor( 1 / $columns_count * 100 );
180
181 for ( $i = 0; $i < $columns_count; $i++ ) {
182 self::$presets[ $columns_count ][0]['preset'][] = $preset_unit;
183 }
184
185 if ( ! empty( $additional_presets[ $columns_count ] ) ) {
186 self::$presets[ $columns_count ] = array_merge( self::$presets[ $columns_count ], $additional_presets[ $columns_count ] );
187 }
188
189 foreach ( self::$presets[ $columns_count ] as $preset_index => & $preset ) {
190 $preset['key'] = $columns_count . $preset_index;
191 }
192 }
193 }
194
195 /**
196 * Get initial config.
197 *
198 * Retrieve the current section initial configuration.
199 *
200 * Adds more configuration on top of the controls list, the tabs assigned to
201 * the control, element name, type, icon and more. This method also adds
202 * section presets.
203 *
204 * @since 2.9.0
205 * @access protected
206 *
207 * @return array The initial config.
208 */
209 protected function get_initial_config() {
210 $config = parent::get_initial_config();
211
212 $config['presets'] = self::get_presets();
213 $config['controls'] = $this->get_controls();
214 $config['tabs_controls'] = $this->get_tabs_controls();
215
216 return $config;
217 }
218
219 /**
220 * Register section controls.
221 *
222 * Used to add new controls to the section element.
223 *
224 * @since 3.1.0
225 * @access protected
226 */
227 protected function register_controls() {
228 $this->start_controls_section(
229 'section_layout',
230 [
231 'label' => esc_html__( 'Layout', 'elementor' ),
232 'tab' => Controls_Manager::TAB_LAYOUT,
233 ]
234 );
235
236 // Element Name for the Navigator.
237 $this->add_control(
238 '_title',
239 [
240 'label' => esc_html__( 'Title', 'elementor' ),
241 'type' => Controls_Manager::HIDDEN,
242 'render_type' => 'none',
243 ]
244 );
245
246 $this->add_control(
247 'layout',
248 [
249 'label' => esc_html__( 'Content Width', 'elementor' ),
250 'type' => Controls_Manager::SELECT,
251 'default' => 'boxed',
252 'options' => [
253 'boxed' => esc_html__( 'Boxed', 'elementor' ),
254 'full_width' => esc_html__( 'Full Width', 'elementor' ),
255 ],
256 'prefix_class' => 'elementor-section-',
257 ]
258 );
259
260 $this->add_responsive_control(
261 'content_width',
262 [
263 'label' => esc_html__( 'Width', 'elementor' ),
264 'type' => Controls_Manager::SLIDER,
265 'range' => [
266 'px' => [
267 'min' => 500,
268 'max' => 1600,
269 ],
270 ],
271 'selectors' => [
272 '{{WRAPPER}} > .elementor-container' => 'max-width: {{SIZE}}{{UNIT}};',
273 ],
274 'condition' => [
275 'layout' => [ 'boxed' ],
276 ],
277 ]
278 );
279
280 $this->add_control(
281 'gap',
282 [
283 'label' => esc_html__( 'Columns Gap', 'elementor' ),
284 'type' => Controls_Manager::SELECT,
285 'default' => 'default',
286 'options' => [
287 'default' => esc_html__( 'Default', 'elementor' ),
288 'no' => esc_html__( 'No Gap', 'elementor' ),
289 'narrow' => esc_html__( 'Narrow', 'elementor' ),
290 'extended' => esc_html__( 'Extended', 'elementor' ),
291 'wide' => esc_html__( 'Wide', 'elementor' ),
292 'wider' => esc_html__( 'Wider', 'elementor' ),
293 'custom' => esc_html__( 'Custom', 'elementor' ),
294 ],
295 ]
296 );
297
298 $this->add_responsive_control(
299 'gap_columns_custom',
300 [
301 'label' => esc_html__( 'Custom Columns Gap', 'elementor' ),
302 'type' => Controls_Manager::SLIDER,
303 'range' => [
304 'px' => [
305 'max' => 500,
306 ],
307 ],
308 'size_units' => [ 'px', '%', 'em', 'rem', 'vh', 'vw', 'custom' ],
309 'selectors' => [
310 '{{WRAPPER}} .elementor-column-gap-custom .elementor-column > .elementor-element-populated' => 'padding: {{SIZE}}{{UNIT}};',
311 ],
312 'condition' => [
313 'gap' => 'custom',
314 ],
315 ]
316 );
317
318 $this->add_control(
319 'height',
320 [
321 'label' => esc_html__( 'Height', 'elementor' ),
322 'type' => Controls_Manager::SELECT,
323 'default' => 'default',
324 'options' => [
325 'default' => esc_html__( 'Default', 'elementor' ),
326 'full' => esc_html__( 'Fit To Screen', 'elementor' ),
327 'min-height' => esc_html__( 'Min Height', 'elementor' ),
328 ],
329 'prefix_class' => 'elementor-section-height-',
330 'hide_in_inner' => true,
331 ]
332 );
333
334 $this->add_responsive_control(
335 'custom_height',
336 [
337 'label' => esc_html__( 'Minimum Height', 'elementor' ),
338 'type' => Controls_Manager::SLIDER,
339 'default' => [
340 'size' => 400,
341 ],
342 'range' => [
343 'px' => [
344 'max' => 1440,
345 ],
346 ],
347 'size_units' => [ 'px', 'em', 'rem', 'vh', 'vw', 'custom' ],
348 'selectors' => [
349 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
350 ],
351 'condition' => [
352 'height' => [ 'min-height' ],
353 ],
354 'hide_in_inner' => true,
355 ]
356 );
357
358 $this->add_control(
359 'height_inner',
360 [
361 'label' => esc_html__( 'Height', 'elementor' ),
362 'type' => Controls_Manager::SELECT,
363 'default' => 'default',
364 'options' => [
365 'default' => esc_html__( 'Default', 'elementor' ),
366 'full' => esc_html__( 'Fit To Screen', 'elementor' ),
367 'min-height' => esc_html__( 'Min Height', 'elementor' ),
368 ],
369 'prefix_class' => 'elementor-section-height-',
370 'hide_in_top' => true,
371 ]
372 );
373
374 $this->add_responsive_control(
375 'custom_height_inner',
376 [
377 'label' => esc_html__( 'Minimum Height', 'elementor' ),
378 'type' => Controls_Manager::SLIDER,
379 'default' => [
380 'size' => 400,
381 ],
382 'range' => [
383 'px' => [
384 'max' => 1440,
385 ],
386 ],
387 'selectors' => [
388 '{{WRAPPER}} > .elementor-container' => 'min-height: {{SIZE}}{{UNIT}};',
389 ],
390 'condition' => [
391 'height_inner' => [ 'min-height' ],
392 ],
393 'size_units' => [ 'px', 'em', 'rem', 'vh', 'vw', 'custom' ],
394 'hide_in_top' => true,
395 ]
396 );
397
398 $this->add_control(
399 'column_position',
400 [
401 'label' => esc_html__( 'Column Position', 'elementor' ),
402 'type' => Controls_Manager::SELECT,
403 'default' => 'middle',
404 'options' => [
405 'stretch' => esc_html__( 'Stretch', 'elementor' ),
406 'top' => esc_html__( 'Top', 'elementor' ),
407 'middle' => esc_html__( 'Middle', 'elementor' ),
408 'bottom' => esc_html__( 'Bottom', 'elementor' ),
409 ],
410 'prefix_class' => 'elementor-section-items-',
411 'condition' => [
412 'height' => [ 'full', 'min-height' ],
413 ],
414 ]
415 );
416
417 $this->add_control(
418 'content_position',
419 [
420 'label' => esc_html__( 'Vertical Align', 'elementor' ),
421 'type' => Controls_Manager::SELECT,
422 'default' => '',
423 'options' => [
424 '' => esc_html__( 'Default', 'elementor' ),
425 'top' => esc_html__( 'Top', 'elementor' ),
426 'middle' => esc_html__( 'Middle', 'elementor' ),
427 'bottom' => esc_html__( 'Bottom', 'elementor' ),
428 'space-between' => esc_html__( 'Space Between', 'elementor' ),
429 'space-around' => esc_html__( 'Space Around', 'elementor' ),
430 'space-evenly' => esc_html__( 'Space Evenly', 'elementor' ),
431 ],
432 'selectors_dictionary' => [
433 'top' => 'flex-start',
434 'middle' => 'center',
435 'bottom' => 'flex-end',
436 ],
437 'selectors' => [
438 '{{WRAPPER}} > .elementor-container > .elementor-column > .elementor-widget-wrap' => 'align-content: {{VALUE}}; align-items: {{VALUE}};',
439 ],
440 // TODO: The following line is for BC since 2.7.0.
441 'prefix_class' => 'elementor-section-content-',
442 ]
443 );
444
445 $this->add_control(
446 'overflow',
447 [
448 'label' => esc_html__( 'Overflow', 'elementor' ),
449 'type' => Controls_Manager::SELECT,
450 'default' => '',
451 'options' => [
452 '' => esc_html__( 'Default', 'elementor' ),
453 'hidden' => esc_html__( 'Hidden', 'elementor' ),
454 ],
455 'selectors' => [
456 '{{WRAPPER}}' => 'overflow: {{VALUE}}',
457 ],
458 ]
459 );
460
461 $this->add_control(
462 'stretch_section',
463 [
464 'label' => esc_html__( 'Stretch Section', 'elementor' ),
465 'type' => Controls_Manager::SWITCHER,
466 'default' => '',
467 'return_value' => 'section-stretched',
468 'prefix_class' => 'elementor-',
469 'hide_in_inner' => true,
470 'description' => sprintf(
471 '%1$s <a href="https://go.elementor.com/stretch-section/" target="_blank">%2$s</a>',
472 esc_html__( 'Stretch the section to the full width of the page using JS.', 'elementor' ),
473 esc_html__( 'Learn more', 'elementor' )
474 ),
475 'render_type' => 'none',
476 'frontend_available' => true,
477 ]
478 );
479
480 $possible_tags = [
481 'div',
482 'header',
483 'footer',
484 'main',
485 'article',
486 'section',
487 'aside',
488 'nav',
489 ];
490
491 $options = [
492 '' => esc_html__( 'Default', 'elementor' ),
493 ] + array_combine( $possible_tags, $possible_tags );
494
495 $this->add_control(
496 'html_tag',
497 [
498 'label' => esc_html__( 'HTML Tag', 'elementor' ),
499 'type' => Controls_Manager::SELECT,
500 'options' => $options,
501 'separator' => 'before',
502 ]
503 );
504
505 $this->end_controls_section();
506
507 // Section Structure.
508 $this->start_controls_section(
509 'section_structure',
510 [
511 'label' => esc_html__( 'Structure', 'elementor' ),
512 'tab' => Controls_Manager::TAB_LAYOUT,
513 ]
514 );
515
516 $this->add_control(
517 'structure',
518 [
519 'label' => esc_html__( 'Structure', 'elementor' ),
520 'type' => Controls_Manager::STRUCTURE,
521 'default' => '10',
522 'render_type' => 'none',
523 'style_transfer' => false,
524 ]
525 );
526
527 $this->end_controls_section();
528
529 // Section background.
530 $this->start_controls_section(
531 'section_background',
532 [
533 'label' => esc_html__( 'Background', 'elementor' ),
534 'tab' => Controls_Manager::TAB_STYLE,
535 ]
536 );
537
538 $this->start_controls_tabs( 'tabs_background' );
539
540 $this->start_controls_tab(
541 'tab_background_normal',
542 [
543 'label' => esc_html__( 'Normal', 'elementor' ),
544 ]
545 );
546
547 $this->add_group_control(
548 Group_Control_Background::get_type(),
549 [
550 'name' => 'background',
551 'types' => [ 'classic', 'gradient', 'video', 'slideshow' ],
552 'fields_options' => [
553 'background' => [
554 'frontend_available' => true,
555 ],
556 ],
557 ]
558 );
559
560 $this->add_control(
561 'handle_slideshow_asset_loading',
562 [
563 'type' => Controls_Manager::HIDDEN,
564 'assets' => [
565 'styles' => [
566 [
567 'name' => 'e-swiper',
568 'conditions' => [
569 'terms' => [
570 [
571 'name' => 'background_background',
572 'operator' => '===',
573 'value' => 'slideshow',
574 ],
575 ],
576 ],
577 ],
578 ],
579 'scripts' => [
580 [
581 'name' => 'swiper',
582 'conditions' => [
583 'terms' => [
584 [
585 'name' => 'background_background',
586 'operator' => '===',
587 'value' => 'slideshow',
588 ],
589 ],
590 ],
591 ],
592 ],
593 ],
594 ]
595 );
596
597 $this->end_controls_tab();
598
599 $this->start_controls_tab(
600 'tab_background_hover',
601 [
602 'label' => esc_html__( 'Hover', 'elementor' ),
603 ]
604 );
605
606 $this->add_group_control(
607 Group_Control_Background::get_type(),
608 [
609 'name' => 'background_hover',
610 'selector' => '{{WRAPPER}}:hover',
611 ]
612 );
613
614 $this->add_control(
615 'background_hover_transition',
616 [
617 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
618 'type' => Controls_Manager::SLIDER,
619 'default' => [
620 'size' => 0.3,
621 ],
622 'range' => [
623 'px' => [
624 'min' => 0,
625 'max' => 3,
626 'step' => 0.1,
627 ],
628 ],
629 'render_type' => 'ui',
630 'separator' => 'before',
631 ]
632 );
633
634 $this->end_controls_tab();
635
636 $this->end_controls_tabs();
637
638 $this->end_controls_section();
639
640 // Background Overlay.
641 $this->start_controls_section(
642 'section_background_overlay',
643 [
644 'label' => esc_html__( 'Background Overlay', 'elementor' ),
645 'tab' => Controls_Manager::TAB_STYLE,
646 ]
647 );
648
649 $this->start_controls_tabs( 'tabs_background_overlay' );
650
651 $this->start_controls_tab(
652 'tab_background_overlay_normal',
653 [
654 'label' => esc_html__( 'Normal', 'elementor' ),
655 ]
656 );
657
658 $this->add_group_control(
659 Group_Control_Background::get_type(),
660 [
661 'name' => 'background_overlay',
662 'selector' => '{{WRAPPER}} > .elementor-background-overlay',
663 ]
664 );
665
666 $this->add_responsive_control(
667 'background_overlay_opacity',
668 [
669 'label' => esc_html__( 'Opacity', 'elementor' ),
670 'type' => Controls_Manager::SLIDER,
671 'default' => [
672 'size' => .5,
673 ],
674 'range' => [
675 'px' => [
676 'max' => 1,
677 'step' => 0.01,
678 ],
679 ],
680 'selectors' => [
681 '{{WRAPPER}} > .elementor-background-overlay' => 'opacity: {{SIZE}};',
682 ],
683 'condition' => [
684 'background_overlay_background' => [ 'classic', 'gradient' ],
685 ],
686 ]
687 );
688
689 $this->add_group_control(
690 Group_Control_Css_Filter::get_type(),
691 [
692 'name' => 'css_filters',
693 'selector' => '{{WRAPPER}} .elementor-background-overlay',
694 'conditions' => [
695 'relation' => 'or',
696 'terms' => [
697 [
698 'name' => 'background_overlay_image[url]',
699 'operator' => '!==',
700 'value' => '',
701 ],
702 [
703 'name' => 'background_overlay_color',
704 'operator' => '!==',
705 'value' => '',
706 ],
707 ],
708 ],
709 ]
710 );
711
712 $this->add_control(
713 'overlay_blend_mode',
714 [
715 'label' => esc_html__( 'Blend Mode', 'elementor' ),
716 'type' => Controls_Manager::SELECT,
717 'options' => [
718 '' => esc_html__( 'Normal', 'elementor' ),
719 'multiply' => esc_html__( 'Multiply', 'elementor' ),
720 'screen' => esc_html__( 'Screen', 'elementor' ),
721 'overlay' => esc_html__( 'Overlay', 'elementor' ),
722 'darken' => esc_html__( 'Darken', 'elementor' ),
723 'lighten' => esc_html__( 'Lighten', 'elementor' ),
724 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
725 'saturation' => esc_html__( 'Saturation', 'elementor' ),
726 'color' => esc_html__( 'Color', 'elementor' ),
727 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
728 'difference' => esc_html__( 'Difference', 'elementor' ),
729 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
730 'hue' => esc_html__( 'Hue', 'elementor' ),
731 ],
732 'selectors' => [
733 '{{WRAPPER}} > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
734 ],
735 'conditions' => [
736 'relation' => 'or',
737 'terms' => [
738 [
739 'name' => 'background_overlay_image[url]',
740 'operator' => '!==',
741 'value' => '',
742 ],
743 [
744 'name' => 'background_overlay_color',
745 'operator' => '!==',
746 'value' => '',
747 ],
748 ],
749 ],
750 ]
751 );
752
753 $this->end_controls_tab();
754
755 $this->start_controls_tab(
756 'tab_background_overlay_hover',
757 [
758 'label' => esc_html__( 'Hover', 'elementor' ),
759 ]
760 );
761
762 $this->add_group_control(
763 Group_Control_Background::get_type(),
764 [
765 'name' => 'background_overlay_hover',
766 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
767 ]
768 );
769
770 $this->add_responsive_control(
771 'background_overlay_hover_opacity',
772 [
773 'label' => esc_html__( 'Opacity', 'elementor' ),
774 'type' => Controls_Manager::SLIDER,
775 'default' => [
776 'size' => .5,
777 ],
778 'range' => [
779 'px' => [
780 'max' => 1,
781 'step' => 0.01,
782 ],
783 ],
784 'selectors' => [
785 '{{WRAPPER}}:hover > .elementor-background-overlay' => 'opacity: {{SIZE}};',
786 ],
787 'condition' => [
788 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
789 ],
790 ]
791 );
792
793 $this->add_group_control(
794 Group_Control_Css_Filter::get_type(),
795 [
796 'name' => 'css_filters_hover',
797 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
798 ]
799 );
800
801 $this->add_control(
802 'background_overlay_hover_transition',
803 [
804 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
805 'type' => Controls_Manager::SLIDER,
806 'default' => [
807 'size' => 0.3,
808 ],
809 'range' => [
810 'px' => [
811 'min' => 0,
812 'max' => 3,
813 'step' => 0.1,
814 ],
815 ],
816 'render_type' => 'ui',
817 'separator' => 'before',
818 ]
819 );
820
821 $this->end_controls_tab();
822
823 $this->end_controls_tabs();
824
825 $this->end_controls_section();
826
827 // Section border.
828 $this->start_controls_section(
829 'section_border',
830 [
831 'label' => esc_html__( 'Border', 'elementor' ),
832 'tab' => Controls_Manager::TAB_STYLE,
833 ]
834 );
835
836 $this->start_controls_tabs( 'tabs_border' );
837
838 $this->start_controls_tab(
839 'tab_border_normal',
840 [
841 'label' => esc_html__( 'Normal', 'elementor' ),
842 ]
843 );
844
845 $this->add_group_control(
846 Group_Control_Border::get_type(),
847 [
848 'name' => 'border',
849 ]
850 );
851
852 $this->add_responsive_control(
853 'border_radius',
854 [
855 'label' => esc_html__( 'Border Radius', 'elementor' ),
856 'type' => Controls_Manager::DIMENSIONS,
857 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
858 'selectors' => [
859 '{{WRAPPER}}, {{WRAPPER}} > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
860 ],
861 ]
862 );
863
864 $this->add_group_control(
865 Group_Control_Box_Shadow::get_type(),
866 [
867 'name' => 'box_shadow',
868 ]
869 );
870
871 $this->end_controls_tab();
872
873 $this->start_controls_tab(
874 'tab_border_hover',
875 [
876 'label' => esc_html__( 'Hover', 'elementor' ),
877 ]
878 );
879
880 $this->add_group_control(
881 Group_Control_Border::get_type(),
882 [
883 'name' => 'border_hover',
884 'selector' => '{{WRAPPER}}:hover',
885 ]
886 );
887
888 $this->add_responsive_control(
889 'border_radius_hover',
890 [
891 'label' => esc_html__( 'Border Radius', 'elementor' ),
892 'type' => Controls_Manager::DIMENSIONS,
893 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
894 'selectors' => [
895 '{{WRAPPER}}:hover, {{WRAPPER}}:hover > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
896 ],
897 ]
898 );
899
900 $this->add_group_control(
901 Group_Control_Box_Shadow::get_type(),
902 [
903 'name' => 'box_shadow_hover',
904 'selector' => '{{WRAPPER}}:hover',
905 ]
906 );
907
908 $this->add_control(
909 'border_hover_transition',
910 [
911 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
912 'type' => Controls_Manager::SLIDER,
913 'separator' => 'before',
914 'default' => [
915 'size' => 0.3,
916 ],
917 'range' => [
918 'px' => [
919 'min' => 0,
920 'max' => 3,
921 'step' => 0.1,
922 ],
923 ],
924 'conditions' => [
925 'relation' => 'or',
926 'terms' => [
927 [
928 'name' => 'background_background',
929 'operator' => '!==',
930 'value' => '',
931 ],
932 [
933 'name' => 'border_hover_border',
934 'operator' => '!==',
935 'value' => '',
936 ],
937 ],
938 ],
939 'selectors' => [
940 '{{WRAPPER}}' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
941 '{{WRAPPER}} > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
942 ],
943 ]
944 );
945
946 $this->end_controls_tab();
947
948 $this->end_controls_tabs();
949
950 $this->end_controls_section();
951
952 // Section Shape Divider.
953 $this->start_controls_section(
954 'section_shape_divider',
955 [
956 'label' => esc_html__( 'Shape Divider', 'elementor' ),
957 'tab' => Controls_Manager::TAB_STYLE,
958 ]
959 );
960
961 $this->start_controls_tabs( 'tabs_shape_dividers' );
962
963 foreach ( [
964 'top' => esc_html__( 'Top', 'elementor' ),
965 'bottom' => esc_html__( 'Bottom', 'elementor' ),
966 ] as $side => $side_label ) {
967 $base_control_key = "shape_divider_$side";
968
969 $this->start_controls_tab(
970 "tab_$base_control_key",
971 [
972 'label' => $side_label,
973 ]
974 );
975
976 $this->add_control(
977 $base_control_key,
978 [
979 'label' => esc_html__( 'Type', 'elementor' ),
980 'type' => Controls_Manager::VISUAL_CHOICE,
981 'label_block' => true,
982 'columns' => 2,
983 'options' => Shapes::get_shapes(),
984 'render_type' => 'none',
985 'frontend_available' => true,
986 'assets' => [
987 'styles' => [
988 [
989 'name' => 'e-shapes',
990 'conditions' => [
991 'terms' => [
992 [
993 'name' => $base_control_key,
994 'operator' => '!==',
995 'value' => '',
996 ],
997 ],
998 ],
999 ],
1000 ],
1001 ],
1002 ]
1003 );
1004
1005 $this->add_control(
1006 $base_control_key . '_color',
1007 [
1008 'label' => esc_html__( 'Color', 'elementor' ),
1009 'type' => Controls_Manager::COLOR,
1010 'condition' => [
1011 "shape_divider_$side!" => '',
1012 ],
1013 'selectors' => [
1014 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
1015 ],
1016 ]
1017 );
1018
1019 $this->add_responsive_control(
1020 $base_control_key . '_width',
1021 [
1022 'label' => esc_html__( 'Width', 'elementor' ),
1023 'type' => Controls_Manager::SLIDER,
1024 'size_units' => [ '%', 'vw', 'custom' ],
1025 'default' => [
1026 'unit' => '%',
1027 ],
1028 'tablet_default' => [
1029 'unit' => '%',
1030 ],
1031 'mobile_default' => [
1032 'unit' => '%',
1033 ],
1034 'range' => [
1035 '%' => [
1036 'min' => 100,
1037 'max' => 300,
1038 ],
1039 'vw' => [
1040 'min' => 100,
1041 'max' => 300,
1042 ],
1043 ],
1044 'condition' => [
1045 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1046 ],
1047 'selectors' => [
1048 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1049 ],
1050 ]
1051 );
1052
1053 $this->add_responsive_control(
1054 $base_control_key . '_height',
1055 [
1056 'label' => esc_html__( 'Height', 'elementor' ),
1057 'type' => Controls_Manager::SLIDER,
1058 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
1059 'range' => [
1060 'px' => [
1061 'max' => 500,
1062 ],
1063 'em' => [
1064 'max' => 50,
1065 ],
1066 'rem' => [
1067 'max' => 50,
1068 ],
1069 ],
1070 'condition' => [
1071 "shape_divider_$side!" => '',
1072 ],
1073 'selectors' => [
1074 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1075 ],
1076 ]
1077 );
1078
1079 $this->add_control(
1080 $base_control_key . '_flip',
1081 [
1082 'label' => esc_html__( 'Flip', 'elementor' ),
1083 'type' => Controls_Manager::SWITCHER,
1084 'condition' => [
1085 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1086 ],
1087 'selectors' => [
1088 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1089 ],
1090 ]
1091 );
1092
1093 $this->add_control(
1094 $base_control_key . '_negative',
1095 [
1096 'label' => esc_html__( 'Invert', 'elementor' ),
1097 'type' => Controls_Manager::SWITCHER,
1098 'frontend_available' => true,
1099 'condition' => [
1100 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1101 ],
1102 'render_type' => 'none',
1103 ]
1104 );
1105
1106 $this->add_control(
1107 $base_control_key . '_above_content',
1108 [
1109 'label' => esc_html__( 'Bring to Front', 'elementor' ),
1110 'type' => Controls_Manager::SWITCHER,
1111 'selectors' => [
1112 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1113 ],
1114 'condition' => [
1115 "shape_divider_$side!" => '',
1116 ],
1117 ]
1118 );
1119
1120 $this->end_controls_tab();
1121 }
1122
1123 $this->end_controls_tabs();
1124
1125 $this->end_controls_section();
1126
1127 // Section Typography.
1128 $this->start_controls_section(
1129 'section_typo',
1130 [
1131 'label' => esc_html__( 'Typography', 'elementor' ),
1132 'tab' => Controls_Manager::TAB_STYLE,
1133 ]
1134 );
1135
1136 $this->add_control(
1137 'heading_color',
1138 [
1139 'label' => esc_html__( 'Heading Color', 'elementor' ),
1140 'type' => Controls_Manager::COLOR,
1141 'default' => '',
1142 'selectors' => [
1143 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1144 ],
1145 ]
1146 );
1147
1148 $this->add_control(
1149 'color_text',
1150 [
1151 'label' => esc_html__( 'Text Color', 'elementor' ),
1152 'type' => Controls_Manager::COLOR,
1153 'default' => '',
1154 'selectors' => [
1155 '{{WRAPPER}}' => 'color: {{VALUE}};',
1156 ],
1157 ]
1158 );
1159
1160 $this->add_control(
1161 'color_link',
1162 [
1163 'label' => esc_html__( 'Link Color', 'elementor' ),
1164 'type' => Controls_Manager::COLOR,
1165 'default' => '',
1166 'selectors' => [
1167 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1168 ],
1169 ]
1170 );
1171
1172 $this->add_control(
1173 'color_link_hover',
1174 [
1175 'label' => esc_html__( 'Link Hover Color', 'elementor' ),
1176 'type' => Controls_Manager::COLOR,
1177 'default' => '',
1178 'selectors' => [
1179 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1180 ],
1181 ]
1182 );
1183
1184 $this->add_responsive_control(
1185 'text_align',
1186 [
1187 'label' => esc_html__( 'Text Align', 'elementor' ),
1188 'type' => Controls_Manager::CHOOSE,
1189 'options' => [
1190 'left' => [
1191 'title' => esc_html__( 'Left', 'elementor' ),
1192 'icon' => 'eicon-text-align-left',
1193 ],
1194 'center' => [
1195 'title' => esc_html__( 'Center', 'elementor' ),
1196 'icon' => 'eicon-text-align-center',
1197 ],
1198 'right' => [
1199 'title' => esc_html__( 'Right', 'elementor' ),
1200 'icon' => 'eicon-text-align-right',
1201 ],
1202 'justify' => [
1203 'title' => esc_html__( 'Justified', 'elementor' ),
1204 'icon' => 'eicon-text-align-justify',
1205 ],
1206 ],
1207 'selectors' => [
1208 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1209 ],
1210 ]
1211 );
1212
1213 $this->end_controls_section();
1214
1215 // Section Advanced.
1216 $this->start_controls_section(
1217 'section_advanced',
1218 [
1219 'label' => esc_html__( 'Advanced', 'elementor' ),
1220 'tab' => Controls_Manager::TAB_ADVANCED,
1221 ]
1222 );
1223
1224 $this->add_responsive_control(
1225 'margin',
1226 [
1227 'label' => esc_html__( 'Margin', 'elementor' ),
1228 'type' => Controls_Manager::DIMENSIONS,
1229 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1230 'allowed_dimensions' => 'vertical',
1231 'placeholder' => [
1232 'top' => '',
1233 'right' => 'auto',
1234 'bottom' => '',
1235 'left' => 'auto',
1236 ],
1237 'selectors' => [
1238 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1239 ],
1240 ]
1241 );
1242
1243 $this->add_responsive_control(
1244 'padding',
1245 [
1246 'label' => esc_html__( 'Padding', 'elementor' ),
1247 'type' => Controls_Manager::DIMENSIONS,
1248 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1249 'selectors' => [
1250 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1251 ],
1252 ]
1253 );
1254
1255 $this->add_responsive_control(
1256 'z_index',
1257 [
1258 'label' => esc_html__( 'Z-Index', 'elementor' ),
1259 'type' => Controls_Manager::NUMBER,
1260 'min' => 0,
1261 'selectors' => [
1262 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1263 ],
1264 ]
1265 );
1266
1267 $this->add_control(
1268 '_element_id',
1269 [
1270 'label' => esc_html__( 'CSS ID', 'elementor' ),
1271 'type' => Controls_Manager::TEXT,
1272 'default' => '',
1273 'ai' => [
1274 'active' => false,
1275 ],
1276 'dynamic' => [
1277 'active' => true,
1278 ],
1279 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1280 'style_transfer' => false,
1281 'classes' => 'elementor-control-direction-ltr',
1282 ]
1283 );
1284
1285 $this->add_control(
1286 'css_classes',
1287 [
1288 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1289 'type' => Controls_Manager::TEXT,
1290 'default' => '',
1291 'ai' => [
1292 'active' => false,
1293 ],
1294 'dynamic' => [
1295 'active' => true,
1296 ],
1297 'prefix_class' => '',
1298 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1299 'classes' => 'elementor-control-direction-ltr',
1300 ]
1301 );
1302
1303 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
1304
1305 $this->end_controls_section();
1306
1307 $this->start_controls_section(
1308 'section_effects',
1309 [
1310 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1311 'tab' => Controls_Manager::TAB_ADVANCED,
1312 ]
1313 );
1314
1315 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
1316
1317 $this->add_responsive_control(
1318 'animation',
1319 [
1320 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1321 'type' => Controls_Manager::ANIMATION,
1322 'frontend_available' => true,
1323 ]
1324 );
1325
1326 $this->add_control(
1327 'animation_duration',
1328 [
1329 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1330 'type' => Controls_Manager::SELECT,
1331 'default' => '',
1332 'options' => [
1333 'slow' => esc_html__( 'Slow', 'elementor' ),
1334 '' => esc_html__( 'Normal', 'elementor' ),
1335 'fast' => esc_html__( 'Fast', 'elementor' ),
1336 ],
1337 'prefix_class' => 'animated-',
1338 'condition' => [
1339 'animation!' => '',
1340 ],
1341 ]
1342 );
1343
1344 $this->add_control(
1345 'animation_delay',
1346 [
1347 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1348 'type' => Controls_Manager::NUMBER,
1349 'default' => '',
1350 'min' => 0,
1351 'step' => 100,
1352 'condition' => [
1353 'animation!' => '',
1354 ],
1355 'render_type' => 'none',
1356 'frontend_available' => true,
1357 ]
1358 );
1359
1360 $this->end_controls_section();
1361
1362 // Section Responsive.
1363 $this->start_controls_section(
1364 '_section_responsive',
1365 [
1366 'label' => esc_html__( 'Responsive', 'elementor' ),
1367 'tab' => Controls_Manager::TAB_ADVANCED,
1368 ]
1369 );
1370
1371 // The controls should be displayed from largest to smallest breakpoint, so we reverse the array.
1372 $active_breakpoints = array_reverse( Plugin::$instance->breakpoints->get_active_breakpoints() );
1373
1374 foreach ( $active_breakpoints as $breakpoint_key => $breakpoint ) {
1375 $this->add_control(
1376 'reverse_order_' . $breakpoint_key,
1377 [
1378 'label' => esc_html__( 'Reverse Columns', 'elementor' ) . ' (' . $breakpoint->get_label() . ')',
1379 'type' => Controls_Manager::SWITCHER,
1380 'default' => '',
1381 'prefix_class' => 'elementor-',
1382 'return_value' => 'reverse-' . $breakpoint_key,
1383 ]
1384 );
1385 }
1386
1387 $this->add_control(
1388 'heading_visibility',
1389 [
1390 'label' => esc_html__( 'Visibility', 'elementor' ),
1391 'type' => Controls_Manager::HEADING,
1392 'separator' => 'before',
1393 ]
1394 );
1395
1396 $this->add_control(
1397 'responsive_description',
1398 [
1399 'raw' => sprintf(
1400 /* translators: 1: Link open tag, 2: Link close tag. */
1401 esc_html__( 'Responsive visibility will take effect only on %1$s preview mode %2$s or live page, and not while editing in Elementor.', 'elementor' ),
1402 '<a href="javascript: $e.run( \'panel/close\' )">',
1403 '</a>'
1404 ),
1405 'type' => Controls_Manager::RAW_HTML,
1406 'content_classes' => 'elementor-descriptor',
1407 ]
1408 );
1409
1410 $this->add_hidden_device_controls();
1411
1412 $this->end_controls_section();
1413
1414 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1415
1416 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1417 }
1418
1419 /**
1420 * Render section output in the editor.
1421 *
1422 * Used to generate the live preview, using a Backbone JavaScript template.
1423 *
1424 * @since 2.9.0
1425 * @access protected
1426 */
1427 protected function content_template() {
1428 ?>
1429 <#
1430 if ( settings.background_video_link ) {
1431 let videoAttributes = 'autoplay muted playsinline';
1432
1433 if ( ! settings.background_play_once ) {
1434 videoAttributes += ' loop';
1435 }
1436
1437 view.addRenderAttribute(
1438 'background-video-container',
1439 {
1440 'class': 'elementor-background-video-container',
1441 'aria-hidden': 'true',
1442 }
1443 );
1444
1445 if ( ! settings.background_play_on_mobile ) {
1446 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1447 }
1448 #>
1449 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1450 <div class="elementor-background-video-embed"></div>
1451 <video class="elementor-background-video-hosted" {{ videoAttributes }}></video>
1452 </div>
1453 <# } #>
1454 <div class="elementor-background-overlay"></div>
1455 <div class="elementor-shape elementor-shape-top" aria-hidden="true"></div>
1456 <div class="elementor-shape elementor-shape-bottom" aria-hidden="true"></div>
1457 <div class="elementor-container elementor-column-gap-{{ settings.gap }}"></div>
1458 <?php
1459 }
1460
1461 /**
1462 * Before section rendering.
1463 *
1464 * Used to add stuff before the section element.
1465 *
1466 * @since 1.0.0
1467 * @access public
1468 */
1469 public function before_render() {
1470 $settings = $this->get_settings_for_display();
1471 ?>
1472 <<?php
1473 // PHPCS - the method get_html_tag is safe.
1474 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1475 ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1476 <?php
1477 if ( 'video' === $settings['background_background'] ) :
1478 if ( $settings['background_video_link'] ) :
1479 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
1480
1481 $this->add_render_attribute(
1482 'background-video-container',
1483 [
1484 'class' => 'elementor-background-video-container',
1485 'aria-hidden' => 'true',
1486 ]
1487 );
1488
1489 if ( ! $settings['background_play_on_mobile'] ) {
1490 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1491 }
1492 ?>
1493 <div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
1494 <?php if ( $video_properties ) : ?>
1495 <div class="elementor-background-video-embed"></div>
1496 <?php
1497 else :
1498 $video_tag_attributes = 'autoplay muted playsinline';
1499 if ( 'yes' !== $settings['background_play_once'] ) :
1500 $video_tag_attributes .= ' loop';
1501 endif;
1502 ?>
1503 <video class="elementor-background-video-hosted" <?php
1504 // PHPCS - the variable $video_tag_attributes is a plain string.
1505 echo $video_tag_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1506 ?>></video>
1507 <?php endif; ?>
1508 </div>
1509 <?php
1510 endif;
1511 endif;
1512
1513 $overlay_background = $settings['background_overlay_background'] ?? '';
1514 $overlay_hover_background = $settings['background_overlay_hover_background'] ?? '';
1515
1516 $has_background_overlay = in_array( $overlay_background, [ 'classic', 'gradient' ], true ) ||
1517 in_array( $overlay_hover_background, [ 'classic', 'gradient' ], true );
1518
1519 if ( $has_background_overlay ) :
1520 ?>
1521 <div class="elementor-background-overlay"></div>
1522 <?php
1523 endif;
1524
1525 if ( $settings['shape_divider_top'] ) {
1526 $this->print_shape_divider( 'top' );
1527 }
1528
1529 if ( $settings['shape_divider_bottom'] ) {
1530 $this->print_shape_divider( 'bottom' );
1531 }
1532 ?>
1533 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1534 <?php
1535 }
1536
1537 /**
1538 * After section rendering.
1539 *
1540 * Used to add stuff after the section element.
1541 *
1542 * @since 1.0.0
1543 * @access public
1544 */
1545 public function after_render() {
1546 ?>
1547 </div>
1548 </<?php
1549 // PHPCS - the method get_html_tag is safe.
1550 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1551 ?>>
1552 <?php
1553 }
1554
1555 /**
1556 * Add section render attributes.
1557 *
1558 * Used to add attributes to the current section wrapper HTML tag.
1559 *
1560 * @since 1.3.0
1561 * @access protected
1562 */
1563 protected function add_render_attributes() {
1564
1565 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1566
1567 $this->add_render_attribute(
1568 '_wrapper', 'class', [
1569 'elementor-section',
1570 'elementor-' . $section_type . '-section',
1571 ]
1572 );
1573
1574 parent::add_render_attributes();
1575 }
1576
1577 /**
1578 * Get default child type.
1579 *
1580 * Retrieve the section child type based on element data.
1581 *
1582 * @since 1.0.0
1583 * @access protected
1584 *
1585 * @param array $element_data Element ID.
1586 *
1587 * @return Element_Base Section default child type.
1588 */
1589 protected function _get_default_child_type( array $element_data ) {
1590 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1591 }
1592
1593 /**
1594 * Get HTML tag.
1595 *
1596 * Retrieve the section element HTML tag.
1597 *
1598 * @since 1.5.3
1599 * @access private
1600 *
1601 * @return string Section HTML tag.
1602 */
1603 protected function get_html_tag() {
1604 $html_tag = $this->get_settings( 'html_tag' );
1605
1606 if ( empty( $html_tag ) ) {
1607 $html_tag = 'section';
1608 }
1609
1610 return Utils::validate_html_tag( $html_tag );
1611 }
1612
1613 /**
1614 * Print section shape divider.
1615 *
1616 * Used to generate the shape dividers HTML.
1617 *
1618 * @since 1.3.0
1619 * @access private
1620 *
1621 * @param string $side Shape divider side, used to set the shape key.
1622 */
1623 protected function print_shape_divider( $side ) {
1624 $settings = $this->get_active_settings();
1625 $base_setting_key = "shape_divider_$side";
1626 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1627 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1628 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1629 return;
1630 }
1631
1632 ?>
1633 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" aria-hidden="true" data-negative="<?php
1634 Utils::print_unescaped_internal_string( $negative ? 'true' : 'false' );
1635 ?>">
1636 <?php
1637 // PHPCS - The file content is being read from a strict file path structure.
1638 echo Utils::file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1639 ?>
1640 </div>
1641 <?php
1642 }
1643 }
1644