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

1,647 lines 39.3 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 'start' => [
1191 'title' => esc_html__( 'Start', 'elementor' ),
1192 'icon' => 'eicon-text-align-left',
1193 ],
1194 'center' => [
1195 'title' => esc_html__( 'Center', 'elementor' ),
1196 'icon' => 'eicon-text-align-center',
1197 ],
1198 'end' => [
1199 'title' => esc_html__( 'End', '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 'classes' => 'elementor-control-start-end',
1208 'selectors_dictionary' => [
1209 'left' => is_rtl() ? 'end' : 'start',
1210 'right' => is_rtl() ? 'start' : 'end',
1211 ],
1212 'selectors' => [
1213 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1214 ],
1215 ]
1216 );
1217
1218 $this->end_controls_section();
1219
1220 // Section Advanced.
1221 $this->start_controls_section(
1222 'section_advanced',
1223 [
1224 'label' => esc_html__( 'Advanced', 'elementor' ),
1225 'tab' => Controls_Manager::TAB_ADVANCED,
1226 ]
1227 );
1228
1229 $this->add_responsive_control(
1230 'margin',
1231 [
1232 'label' => esc_html__( 'Margin', 'elementor' ),
1233 'type' => Controls_Manager::DIMENSIONS,
1234 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1235 'allowed_dimensions' => 'vertical',
1236 'placeholder' => [
1237 'top' => '',
1238 'right' => 'auto',
1239 'bottom' => '',
1240 'left' => 'auto',
1241 ],
1242 'selectors' => [
1243 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1244 ],
1245 ]
1246 );
1247
1248 $this->add_responsive_control(
1249 'padding',
1250 [
1251 'label' => esc_html__( 'Padding', 'elementor' ),
1252 'type' => Controls_Manager::DIMENSIONS,
1253 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1254 'selectors' => [
1255 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1256 ],
1257 ]
1258 );
1259
1260 $this->add_responsive_control(
1261 'z_index',
1262 [
1263 'label' => esc_html__( 'Z-Index', 'elementor' ),
1264 'type' => Controls_Manager::NUMBER,
1265 'min' => 0,
1266 'selectors' => [
1267 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1268 ],
1269 ]
1270 );
1271
1272 $this->add_control(
1273 '_element_id',
1274 [
1275 'label' => esc_html__( 'CSS ID', 'elementor' ),
1276 'type' => Controls_Manager::TEXT,
1277 'default' => '',
1278 'ai' => [
1279 'active' => false,
1280 ],
1281 'dynamic' => [
1282 'active' => true,
1283 ],
1284 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1285 'style_transfer' => false,
1286 'classes' => 'elementor-control-direction-ltr',
1287 ]
1288 );
1289
1290 $this->add_control(
1291 'css_classes',
1292 [
1293 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1294 'type' => Controls_Manager::TEXT,
1295 'default' => '',
1296 'ai' => [
1297 'active' => false,
1298 ],
1299 'dynamic' => [
1300 'active' => true,
1301 ],
1302 'prefix_class' => '',
1303 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1304 'classes' => 'elementor-control-direction-ltr',
1305 ]
1306 );
1307
1308 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
1309
1310 $this->end_controls_section();
1311
1312 $this->start_controls_section(
1313 'section_effects',
1314 [
1315 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1316 'tab' => Controls_Manager::TAB_ADVANCED,
1317 ]
1318 );
1319
1320 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
1321
1322 $this->add_responsive_control(
1323 'animation',
1324 [
1325 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1326 'type' => Controls_Manager::ANIMATION,
1327 'frontend_available' => true,
1328 ]
1329 );
1330
1331 $this->add_control(
1332 'animation_duration',
1333 [
1334 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1335 'type' => Controls_Manager::SELECT,
1336 'default' => '',
1337 'options' => [
1338 'slow' => esc_html__( 'Slow', 'elementor' ),
1339 '' => esc_html__( 'Normal', 'elementor' ),
1340 'fast' => esc_html__( 'Fast', 'elementor' ),
1341 ],
1342 'prefix_class' => 'animated-',
1343 'condition' => [
1344 'animation!' => '',
1345 ],
1346 ]
1347 );
1348
1349 $this->add_control(
1350 'animation_delay',
1351 [
1352 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1353 'type' => Controls_Manager::NUMBER,
1354 'default' => '',
1355 'min' => 0,
1356 'step' => 100,
1357 'condition' => [
1358 'animation!' => '',
1359 ],
1360 'render_type' => 'none',
1361 'frontend_available' => true,
1362 ]
1363 );
1364
1365 $this->end_controls_section();
1366
1367 // Section Responsive.
1368 $this->start_controls_section(
1369 '_section_responsive',
1370 [
1371 'label' => esc_html__( 'Responsive', 'elementor' ),
1372 'tab' => Controls_Manager::TAB_ADVANCED,
1373 ]
1374 );
1375
1376 // The controls should be displayed from largest to smallest breakpoint, so we reverse the array.
1377 $active_breakpoints = array_reverse( Plugin::$instance->breakpoints->get_active_breakpoints() );
1378
1379 foreach ( $active_breakpoints as $breakpoint_key => $breakpoint ) {
1380 $this->add_control(
1381 'reverse_order_' . $breakpoint_key,
1382 [
1383 'label' => esc_html__( 'Reverse Columns', 'elementor' ) . ' (' . $breakpoint->get_label() . ')',
1384 'type' => Controls_Manager::SWITCHER,
1385 'default' => '',
1386 'prefix_class' => 'elementor-',
1387 'return_value' => 'reverse-' . $breakpoint_key,
1388 ]
1389 );
1390 }
1391
1392 $this->add_control(
1393 'heading_visibility',
1394 [
1395 'label' => esc_html__( 'Visibility', 'elementor' ),
1396 'type' => Controls_Manager::HEADING,
1397 'separator' => 'before',
1398 ]
1399 );
1400
1401 $this->add_control(
1402 'responsive_description',
1403 [
1404 'raw' => sprintf(
1405 /* translators: 1: Link open tag, 2: Link close tag. */
1406 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' ),
1407 '<a href="javascript: $e.run( \'panel/close\' )">',
1408 '</a>'
1409 ),
1410 'type' => Controls_Manager::RAW_HTML,
1411 'content_classes' => 'elementor-descriptor',
1412 ]
1413 );
1414
1415 $this->add_hidden_device_controls();
1416
1417 $this->end_controls_section();
1418
1419 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1420
1421 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1422 }
1423
1424 /**
1425 * Render section output in the editor.
1426 *
1427 * Used to generate the live preview, using a Backbone JavaScript template.
1428 *
1429 * @since 2.9.0
1430 * @access protected
1431 */
1432 protected function content_template() {
1433 ?>
1434 <#
1435 if ( settings.background_video_link ) {
1436 let videoAttributes = 'autoplay muted playsinline';
1437
1438 if ( ! settings.background_play_once ) {
1439 videoAttributes += ' loop';
1440 }
1441
1442 view.addRenderAttribute(
1443 'background-video-container',
1444 {
1445 'class': 'elementor-background-video-container',
1446 }
1447 );
1448
1449 if ( ! settings.background_play_on_mobile ) {
1450 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1451 }
1452 #>
1453 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1454 <div class="elementor-background-video-embed" role="presentation"></div>
1455 <video class="elementor-background-video-hosted" role="presentation" {{ videoAttributes }}></video>
1456 </div>
1457 <# } #>
1458 <div class="elementor-background-overlay"></div>
1459 <div class="elementor-shape elementor-shape-top" aria-hidden="true"></div>
1460 <div class="elementor-shape elementor-shape-bottom" aria-hidden="true"></div>
1461 <div class="elementor-container elementor-column-gap-{{ settings.gap }}"></div>
1462 <?php
1463 }
1464
1465 /**
1466 * Before section rendering.
1467 *
1468 * Used to add stuff before the section element.
1469 *
1470 * @since 1.0.0
1471 * @access public
1472 */
1473 public function before_render() {
1474 $settings = $this->get_settings_for_display();
1475 ?>
1476 <<?php
1477 // PHPCS - the method get_html_tag is safe.
1478 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1479 ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1480 <?php
1481 if ( 'video' === $settings['background_background'] ) :
1482 if ( $settings['background_video_link'] ) :
1483 $is_embed_video = Embed::is_embed_video( $settings['background_video_link'] );
1484
1485 $this->add_render_attribute(
1486 'background-video-container',
1487 [
1488 'class' => 'elementor-background-video-container',
1489 ]
1490 );
1491
1492 if ( ! $settings['background_play_on_mobile'] ) {
1493 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1494 }
1495 ?>
1496 <div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
1497 <?php if ( $is_embed_video ) : ?>
1498 <div class="elementor-background-video-embed" role="presentation"></div>
1499 <?php
1500 else :
1501 $video_tag_attributes = 'autoplay muted playsinline';
1502 if ( 'yes' !== $settings['background_play_once'] ) :
1503 $video_tag_attributes .= ' loop';
1504 endif;
1505 ?>
1506 <video class="elementor-background-video-hosted" role="presentation" <?php
1507 // PHPCS - the variable $video_tag_attributes is a plain string.
1508 echo $video_tag_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1509 ?>></video>
1510 <?php endif; ?>
1511 </div>
1512 <?php
1513 endif;
1514 endif;
1515
1516 $overlay_background = $settings['background_overlay_background'] ?? '';
1517 $overlay_hover_background = $settings['background_overlay_hover_background'] ?? '';
1518
1519 $has_background_overlay = in_array( $overlay_background, [ 'classic', 'gradient' ], true ) ||
1520 in_array( $overlay_hover_background, [ 'classic', 'gradient' ], true );
1521
1522 if ( $has_background_overlay ) :
1523 ?>
1524 <div class="elementor-background-overlay"></div>
1525 <?php
1526 endif;
1527
1528 if ( $settings['shape_divider_top'] ) {
1529 $this->print_shape_divider( 'top' );
1530 }
1531
1532 if ( $settings['shape_divider_bottom'] ) {
1533 $this->print_shape_divider( 'bottom' );
1534 }
1535 ?>
1536 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1537 <?php
1538 }
1539
1540 /**
1541 * After section rendering.
1542 *
1543 * Used to add stuff after the section element.
1544 *
1545 * @since 1.0.0
1546 * @access public
1547 */
1548 public function after_render() {
1549 ?>
1550 </div>
1551 </<?php
1552 // PHPCS - the method get_html_tag is safe.
1553 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1554 ?>>
1555 <?php
1556 }
1557
1558 /**
1559 * Add section render attributes.
1560 *
1561 * Used to add attributes to the current section wrapper HTML tag.
1562 *
1563 * @since 1.3.0
1564 * @access protected
1565 */
1566 protected function add_render_attributes() {
1567
1568 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1569
1570 $this->add_render_attribute(
1571 '_wrapper', 'class', [
1572 'elementor-section',
1573 'elementor-' . $section_type . '-section',
1574 ]
1575 );
1576
1577 parent::add_render_attributes();
1578 }
1579
1580 /**
1581 * Get default child type.
1582 *
1583 * Retrieve the section child type based on element data.
1584 *
1585 * @since 1.0.0
1586 * @access protected
1587 *
1588 * @param array $element_data Element ID.
1589 *
1590 * @return Element_Base Section default child type.
1591 */
1592 protected function _get_default_child_type( array $element_data ) {
1593 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1594 }
1595
1596 /**
1597 * Get HTML tag.
1598 *
1599 * Retrieve the section element HTML tag.
1600 *
1601 * @since 1.5.3
1602 * @access private
1603 *
1604 * @return string Section HTML tag.
1605 */
1606 protected function get_html_tag() {
1607 $html_tag = $this->get_settings( 'html_tag' );
1608
1609 if ( empty( $html_tag ) ) {
1610 $html_tag = 'section';
1611 }
1612
1613 return Utils::validate_html_tag( $html_tag );
1614 }
1615
1616 /**
1617 * Print section shape divider.
1618 *
1619 * Used to generate the shape dividers HTML.
1620 *
1621 * @since 1.3.0
1622 * @access private
1623 *
1624 * @param string $side Shape divider side, used to set the shape key.
1625 */
1626 protected function print_shape_divider( $side ) {
1627 $settings = $this->get_active_settings();
1628 $base_setting_key = "shape_divider_$side";
1629 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1630 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1631 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1632 return;
1633 }
1634
1635 ?>
1636 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" aria-hidden="true" data-negative="<?php
1637 Utils::print_unescaped_internal_string( $negative ? 'true' : 'false' );
1638 ?>">
1639 <?php
1640 // PHPCS - The file content is being read from a strict file path structure.
1641 echo Utils::file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1642 ?>
1643 </div>
1644 <?php
1645 }
1646 }
1647