PluginProbe
Elementor Website Builder – more than just a page builder / 3.27.3
Elementor Website Builder – more than just a page builder v3.27.3
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.27.3, at includes/elements/section.php

1,638 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 $shapes_options = [
964 '' => esc_html__( 'None', 'elementor' ),
965 ];
966
967 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
968 $shapes_options[ $shape_name ] = $shape_props['title'];
969 }
970
971 foreach ( [
972 'top' => esc_html__( 'Top', 'elementor' ),
973 'bottom' => esc_html__( 'Bottom', 'elementor' ),
974 ] as $side => $side_label ) {
975 $base_control_key = "shape_divider_$side";
976
977 $this->start_controls_tab(
978 "tab_$base_control_key",
979 [
980 'label' => $side_label,
981 ]
982 );
983
984 $this->add_control(
985 $base_control_key,
986 [
987 'label' => esc_html__( 'Type', 'elementor' ),
988 'type' => Controls_Manager::SELECT,
989 'options' => $shapes_options,
990 'render_type' => 'none',
991 'frontend_available' => true,
992 'assets' => [
993 'styles' => [
994 [
995 'name' => 'e-shapes',
996 'conditions' => [
997 'terms' => [
998 [
999 'name' => $base_control_key,
1000 'operator' => '!==',
1001 'value' => '',
1002 ],
1003 ],
1004 ],
1005 ],
1006 ],
1007 ],
1008 ]
1009 );
1010
1011 $this->add_control(
1012 $base_control_key . '_color',
1013 [
1014 'label' => esc_html__( 'Color', 'elementor' ),
1015 'type' => Controls_Manager::COLOR,
1016 'condition' => [
1017 "shape_divider_$side!" => '',
1018 ],
1019 'selectors' => [
1020 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
1021 ],
1022 ]
1023 );
1024
1025 $this->add_responsive_control(
1026 $base_control_key . '_width',
1027 [
1028 'label' => esc_html__( 'Width', 'elementor' ),
1029 'type' => Controls_Manager::SLIDER,
1030 'size_units' => [ '%', 'vw', 'custom' ],
1031 'default' => [
1032 'unit' => '%',
1033 ],
1034 'tablet_default' => [
1035 'unit' => '%',
1036 ],
1037 'mobile_default' => [
1038 'unit' => '%',
1039 ],
1040 'range' => [
1041 '%' => [
1042 'min' => 100,
1043 'max' => 300,
1044 ],
1045 'vw' => [
1046 'min' => 100,
1047 'max' => 300,
1048 ],
1049 ],
1050 'condition' => [
1051 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1052 ],
1053 'selectors' => [
1054 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1055 ],
1056 ]
1057 );
1058
1059 $this->add_responsive_control(
1060 $base_control_key . '_height',
1061 [
1062 'label' => esc_html__( 'Height', 'elementor' ),
1063 'type' => Controls_Manager::SLIDER,
1064 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
1065 'range' => [
1066 'px' => [
1067 'max' => 500,
1068 ],
1069 'em' => [
1070 'max' => 50,
1071 ],
1072 'rem' => [
1073 'max' => 50,
1074 ],
1075 ],
1076 'condition' => [
1077 "shape_divider_$side!" => '',
1078 ],
1079 'selectors' => [
1080 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1081 ],
1082 ]
1083 );
1084
1085 $this->add_control(
1086 $base_control_key . '_flip',
1087 [
1088 'label' => esc_html__( 'Flip', 'elementor' ),
1089 'type' => Controls_Manager::SWITCHER,
1090 'condition' => [
1091 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1092 ],
1093 'selectors' => [
1094 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1095 ],
1096 ]
1097 );
1098
1099 $this->add_control(
1100 $base_control_key . '_negative',
1101 [
1102 'label' => esc_html__( 'Invert', 'elementor' ),
1103 'type' => Controls_Manager::SWITCHER,
1104 'frontend_available' => true,
1105 'condition' => [
1106 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1107 ],
1108 'render_type' => 'none',
1109 ]
1110 );
1111
1112 $this->add_control(
1113 $base_control_key . '_above_content',
1114 [
1115 'label' => esc_html__( 'Bring to Front', 'elementor' ),
1116 'type' => Controls_Manager::SWITCHER,
1117 'selectors' => [
1118 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1119 ],
1120 'condition' => [
1121 "shape_divider_$side!" => '',
1122 ],
1123 ]
1124 );
1125
1126 $this->end_controls_tab();
1127 }
1128
1129 $this->end_controls_tabs();
1130
1131 $this->end_controls_section();
1132
1133 // Section Typography
1134 $this->start_controls_section(
1135 'section_typo',
1136 [
1137 'label' => esc_html__( 'Typography', 'elementor' ),
1138 'tab' => Controls_Manager::TAB_STYLE,
1139 ]
1140 );
1141
1142 $this->add_control(
1143 'heading_color',
1144 [
1145 'label' => esc_html__( 'Heading Color', 'elementor' ),
1146 'type' => Controls_Manager::COLOR,
1147 'default' => '',
1148 'selectors' => [
1149 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1150 ],
1151 ]
1152 );
1153
1154 $this->add_control(
1155 'color_text',
1156 [
1157 'label' => esc_html__( 'Text Color', 'elementor' ),
1158 'type' => Controls_Manager::COLOR,
1159 'default' => '',
1160 'selectors' => [
1161 '{{WRAPPER}}' => 'color: {{VALUE}};',
1162 ],
1163 ]
1164 );
1165
1166 $this->add_control(
1167 'color_link',
1168 [
1169 'label' => esc_html__( 'Link Color', 'elementor' ),
1170 'type' => Controls_Manager::COLOR,
1171 'default' => '',
1172 'selectors' => [
1173 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1174 ],
1175 ]
1176 );
1177
1178 $this->add_control(
1179 'color_link_hover',
1180 [
1181 'label' => esc_html__( 'Link Hover Color', 'elementor' ),
1182 'type' => Controls_Manager::COLOR,
1183 'default' => '',
1184 'selectors' => [
1185 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1186 ],
1187 ]
1188 );
1189
1190 $this->add_responsive_control(
1191 'text_align',
1192 [
1193 'label' => esc_html__( 'Text Align', 'elementor' ),
1194 'type' => Controls_Manager::CHOOSE,
1195 'options' => [
1196 'left' => [
1197 'title' => esc_html__( 'Left', 'elementor' ),
1198 'icon' => 'eicon-text-align-left',
1199 ],
1200 'center' => [
1201 'title' => esc_html__( 'Center', 'elementor' ),
1202 'icon' => 'eicon-text-align-center',
1203 ],
1204 'right' => [
1205 'title' => esc_html__( 'Right', 'elementor' ),
1206 'icon' => 'eicon-text-align-right',
1207 ],
1208 'justify' => [
1209 'title' => esc_html__( 'Justified', 'elementor' ),
1210 'icon' => 'eicon-text-align-justify',
1211 ],
1212 ],
1213 'selectors' => [
1214 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1215 ],
1216 ]
1217 );
1218
1219 $this->end_controls_section();
1220
1221 // Section Advanced
1222 $this->start_controls_section(
1223 'section_advanced',
1224 [
1225 'label' => esc_html__( 'Advanced', 'elementor' ),
1226 'tab' => Controls_Manager::TAB_ADVANCED,
1227 ]
1228 );
1229
1230 $this->add_responsive_control(
1231 'margin',
1232 [
1233 'label' => esc_html__( 'Margin', 'elementor' ),
1234 'type' => Controls_Manager::DIMENSIONS,
1235 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1236 'allowed_dimensions' => 'vertical',
1237 'placeholder' => [
1238 'top' => '',
1239 'right' => 'auto',
1240 'bottom' => '',
1241 'left' => 'auto',
1242 ],
1243 'selectors' => [
1244 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1245 ],
1246 ]
1247 );
1248
1249 $this->add_responsive_control(
1250 'padding',
1251 [
1252 'label' => esc_html__( 'Padding', 'elementor' ),
1253 'type' => Controls_Manager::DIMENSIONS,
1254 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1255 'selectors' => [
1256 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1257 ],
1258 ]
1259 );
1260
1261 $this->add_responsive_control(
1262 'z_index',
1263 [
1264 'label' => esc_html__( 'Z-Index', 'elementor' ),
1265 'type' => Controls_Manager::NUMBER,
1266 'min' => 0,
1267 'selectors' => [
1268 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1269 ],
1270 ]
1271 );
1272
1273 $this->add_control(
1274 '_element_id',
1275 [
1276 'label' => esc_html__( 'CSS ID', 'elementor' ),
1277 'type' => Controls_Manager::TEXT,
1278 'default' => '',
1279 'ai' => [
1280 'active' => false,
1281 ],
1282 'dynamic' => [
1283 'active' => true,
1284 ],
1285 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1286 'style_transfer' => false,
1287 'classes' => 'elementor-control-direction-ltr',
1288 ]
1289 );
1290
1291 $this->add_control(
1292 'css_classes',
1293 [
1294 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1295 'type' => Controls_Manager::TEXT,
1296 'default' => '',
1297 'ai' => [
1298 'active' => false,
1299 ],
1300 'dynamic' => [
1301 'active' => true,
1302 ],
1303 'prefix_class' => '',
1304 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1305 'classes' => 'elementor-control-direction-ltr',
1306 ]
1307 );
1308
1309 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
1310
1311 $this->end_controls_section();
1312
1313 $this->start_controls_section(
1314 'section_effects',
1315 [
1316 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1317 'tab' => Controls_Manager::TAB_ADVANCED,
1318 ]
1319 );
1320
1321 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
1322
1323 $this->add_responsive_control(
1324 'animation',
1325 [
1326 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1327 'type' => Controls_Manager::ANIMATION,
1328 'frontend_available' => true,
1329 ]
1330 );
1331
1332 $this->add_control(
1333 'animation_duration',
1334 [
1335 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1336 'type' => Controls_Manager::SELECT,
1337 'default' => '',
1338 'options' => [
1339 'slow' => esc_html__( 'Slow', 'elementor' ),
1340 '' => esc_html__( 'Normal', 'elementor' ),
1341 'fast' => esc_html__( 'Fast', 'elementor' ),
1342 ],
1343 'prefix_class' => 'animated-',
1344 'condition' => [
1345 'animation!' => '',
1346 ],
1347 ]
1348 );
1349
1350 $this->add_control(
1351 'animation_delay',
1352 [
1353 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1354 'type' => Controls_Manager::NUMBER,
1355 'default' => '',
1356 'min' => 0,
1357 'step' => 100,
1358 'condition' => [
1359 'animation!' => '',
1360 ],
1361 'render_type' => 'none',
1362 'frontend_available' => true,
1363 ]
1364 );
1365
1366 $this->end_controls_section();
1367
1368 // Section Responsive
1369 $this->start_controls_section(
1370 '_section_responsive',
1371 [
1372 'label' => esc_html__( 'Responsive', 'elementor' ),
1373 'tab' => Controls_Manager::TAB_ADVANCED,
1374 ]
1375 );
1376
1377 // The controls should be displayed from largest to smallest breakpoint, so we reverse the array.
1378 $active_breakpoints = array_reverse( Plugin::$instance->breakpoints->get_active_breakpoints() );
1379
1380 foreach ( $active_breakpoints as $breakpoint_key => $breakpoint ) {
1381 $this->add_control(
1382 'reverse_order_' . $breakpoint_key,
1383 [
1384 'label' => esc_html__( 'Reverse Columns', 'elementor' ) . ' (' . $breakpoint->get_label() . ')',
1385 'type' => Controls_Manager::SWITCHER,
1386 'default' => '',
1387 'prefix_class' => 'elementor-',
1388 'return_value' => 'reverse-' . $breakpoint_key,
1389 ]
1390 );
1391 }
1392
1393 $this->add_control(
1394 'heading_visibility',
1395 [
1396 'label' => esc_html__( 'Visibility', 'elementor' ),
1397 'type' => Controls_Manager::HEADING,
1398 'separator' => 'before',
1399 ]
1400 );
1401
1402 $this->add_control(
1403 'responsive_description',
1404 [
1405 'raw' => sprintf(
1406 /* translators: 1: Link open tag, 2: Link close tag. */
1407 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' ),
1408 '<a href="javascript: $e.run( \'panel/close\' )">',
1409 '</a>'
1410 ),
1411 'type' => Controls_Manager::RAW_HTML,
1412 'content_classes' => 'elementor-descriptor',
1413 ]
1414 );
1415
1416 $this->add_hidden_device_controls();
1417
1418 $this->end_controls_section();
1419
1420 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1421
1422 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1423 }
1424
1425 /**
1426 * Render section output in the editor.
1427 *
1428 * Used to generate the live preview, using a Backbone JavaScript template.
1429 *
1430 * @since 2.9.0
1431 * @access protected
1432 */
1433 protected function content_template() {
1434 ?>
1435 <#
1436 if ( settings.background_video_link ) {
1437 let videoAttributes = 'autoplay muted playsinline';
1438
1439 if ( ! settings.background_play_once ) {
1440 videoAttributes += ' loop';
1441 }
1442
1443 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
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"></div>
1456 <div class="elementor-shape elementor-shape-bottom"></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( 'background-video-container', 'class', 'elementor-background-video-container' );
1482
1483 if ( ! $settings['background_play_on_mobile'] ) {
1484 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1485 }
1486 ?>
1487 <div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
1488 <?php if ( $video_properties ) : ?>
1489 <div class="elementor-background-video-embed"></div>
1490 <?php
1491 else :
1492 $video_tag_attributes = 'autoplay muted playsinline';
1493 if ( 'yes' !== $settings['background_play_once'] ) :
1494 $video_tag_attributes .= ' loop';
1495 endif;
1496 ?>
1497 <video class="elementor-background-video-hosted" <?php
1498 // PHPCS - the variable $video_tag_attributes is a plain string.
1499 echo $video_tag_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1500 ?>></video>
1501 <?php endif; ?>
1502 </div>
1503 <?php
1504 endif;
1505 endif;
1506
1507 $overlay_background = $settings['background_overlay_background'] ?? '';
1508 $overlay_hover_background = $settings['background_overlay_hover_background'] ?? '';
1509
1510 $has_background_overlay = in_array( $overlay_background, [ 'classic', 'gradient' ], true ) ||
1511 in_array( $overlay_hover_background, [ 'classic', 'gradient' ], true );
1512
1513 if ( $has_background_overlay ) :
1514 ?>
1515 <div class="elementor-background-overlay"></div>
1516 <?php
1517 endif;
1518
1519 if ( $settings['shape_divider_top'] ) {
1520 $this->print_shape_divider( 'top' );
1521 }
1522
1523 if ( $settings['shape_divider_bottom'] ) {
1524 $this->print_shape_divider( 'bottom' );
1525 }
1526 ?>
1527 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1528 <?php
1529 }
1530
1531 /**
1532 * After section rendering.
1533 *
1534 * Used to add stuff after the section element.
1535 *
1536 * @since 1.0.0
1537 * @access public
1538 */
1539 public function after_render() {
1540 ?>
1541 </div>
1542 </<?php
1543 // PHPCS - the method get_html_tag is safe.
1544 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1545 ?>>
1546 <?php
1547 }
1548
1549 /**
1550 * Add section render attributes.
1551 *
1552 * Used to add attributes to the current section wrapper HTML tag.
1553 *
1554 * @since 1.3.0
1555 * @access protected
1556 */
1557 protected function add_render_attributes() {
1558
1559 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1560
1561 $this->add_render_attribute(
1562 '_wrapper', 'class', [
1563 'elementor-section',
1564 'elementor-' . $section_type . '-section',
1565 ]
1566 );
1567
1568 parent::add_render_attributes();
1569 }
1570
1571 /**
1572 * Get default child type.
1573 *
1574 * Retrieve the section child type based on element data.
1575 *
1576 * @since 1.0.0
1577 * @access protected
1578 *
1579 * @param array $element_data Element ID.
1580 *
1581 * @return Element_Base Section default child type.
1582 */
1583 protected function _get_default_child_type( array $element_data ) {
1584 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1585 }
1586
1587 /**
1588 * Get HTML tag.
1589 *
1590 * Retrieve the section element HTML tag.
1591 *
1592 * @since 1.5.3
1593 * @access private
1594 *
1595 * @return string Section HTML tag.
1596 */
1597 protected function get_html_tag() {
1598 $html_tag = $this->get_settings( 'html_tag' );
1599
1600 if ( empty( $html_tag ) ) {
1601 $html_tag = 'section';
1602 }
1603
1604 return Utils::validate_html_tag( $html_tag );
1605 }
1606
1607 /**
1608 * Print section shape divider.
1609 *
1610 * Used to generate the shape dividers HTML.
1611 *
1612 * @since 1.3.0
1613 * @access private
1614 *
1615 * @param string $side Shape divider side, used to set the shape key.
1616 */
1617 protected function print_shape_divider( $side ) {
1618 $settings = $this->get_active_settings();
1619 $base_setting_key = "shape_divider_$side";
1620 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1621 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1622 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1623 return;
1624 }
1625
1626 ?>
1627 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php
1628 Utils::print_unescaped_internal_string( $negative ? 'true' : 'false' );
1629 ?>">
1630 <?php
1631 // PHPCS - The file content is being read from a strict file path structure.
1632 echo Utils::file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1633 ?>
1634 </div>
1635 <?php
1636 }
1637 }
1638