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

1,624 lines 38.9 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 ],
580 ]
581 );
582
583 $this->end_controls_tab();
584
585 $this->start_controls_tab(
586 'tab_background_hover',
587 [
588 'label' => esc_html__( 'Hover', 'elementor' ),
589 ]
590 );
591
592 $this->add_group_control(
593 Group_Control_Background::get_type(),
594 [
595 'name' => 'background_hover',
596 'selector' => '{{WRAPPER}}:hover',
597 ]
598 );
599
600 $this->add_control(
601 'background_hover_transition',
602 [
603 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
604 'type' => Controls_Manager::SLIDER,
605 'default' => [
606 'size' => 0.3,
607 ],
608 'range' => [
609 'px' => [
610 'min' => 0,
611 'max' => 3,
612 'step' => 0.1,
613 ],
614 ],
615 'render_type' => 'ui',
616 'separator' => 'before',
617 ]
618 );
619
620 $this->end_controls_tab();
621
622 $this->end_controls_tabs();
623
624 $this->end_controls_section();
625
626 // Background Overlay
627 $this->start_controls_section(
628 'section_background_overlay',
629 [
630 'label' => esc_html__( 'Background Overlay', 'elementor' ),
631 'tab' => Controls_Manager::TAB_STYLE,
632 ]
633 );
634
635 $this->start_controls_tabs( 'tabs_background_overlay' );
636
637 $this->start_controls_tab(
638 'tab_background_overlay_normal',
639 [
640 'label' => esc_html__( 'Normal', 'elementor' ),
641 ]
642 );
643
644 $this->add_group_control(
645 Group_Control_Background::get_type(),
646 [
647 'name' => 'background_overlay',
648 'selector' => '{{WRAPPER}} > .elementor-background-overlay',
649 ]
650 );
651
652 $this->add_responsive_control(
653 'background_overlay_opacity',
654 [
655 'label' => esc_html__( 'Opacity', 'elementor' ),
656 'type' => Controls_Manager::SLIDER,
657 'default' => [
658 'size' => .5,
659 ],
660 'range' => [
661 'px' => [
662 'max' => 1,
663 'step' => 0.01,
664 ],
665 ],
666 'selectors' => [
667 '{{WRAPPER}} > .elementor-background-overlay' => 'opacity: {{SIZE}};',
668 ],
669 'condition' => [
670 'background_overlay_background' => [ 'classic', 'gradient' ],
671 ],
672 ]
673 );
674
675 $this->add_group_control(
676 Group_Control_Css_Filter::get_type(),
677 [
678 'name' => 'css_filters',
679 'selector' => '{{WRAPPER}} .elementor-background-overlay',
680 'conditions' => [
681 'relation' => 'or',
682 'terms' => [
683 [
684 'name' => 'background_overlay_image[url]',
685 'operator' => '!==',
686 'value' => '',
687 ],
688 [
689 'name' => 'background_overlay_color',
690 'operator' => '!==',
691 'value' => '',
692 ],
693 ],
694 ],
695 ]
696 );
697
698 $this->add_control(
699 'overlay_blend_mode',
700 [
701 'label' => esc_html__( 'Blend Mode', 'elementor' ),
702 'type' => Controls_Manager::SELECT,
703 'options' => [
704 '' => esc_html__( 'Normal', 'elementor' ),
705 'multiply' => esc_html__( 'Multiply', 'elementor' ),
706 'screen' => esc_html__( 'Screen', 'elementor' ),
707 'overlay' => esc_html__( 'Overlay', 'elementor' ),
708 'darken' => esc_html__( 'Darken', 'elementor' ),
709 'lighten' => esc_html__( 'Lighten', 'elementor' ),
710 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
711 'saturation' => esc_html__( 'Saturation', 'elementor' ),
712 'color' => esc_html__( 'Color', 'elementor' ),
713 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
714 'difference' => esc_html__( 'Difference', 'elementor' ),
715 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
716 'hue' => esc_html__( 'Hue', 'elementor' ),
717 ],
718 'selectors' => [
719 '{{WRAPPER}} > .elementor-background-overlay' => 'mix-blend-mode: {{VALUE}}',
720 ],
721 'conditions' => [
722 'relation' => 'or',
723 'terms' => [
724 [
725 'name' => 'background_overlay_image[url]',
726 'operator' => '!==',
727 'value' => '',
728 ],
729 [
730 'name' => 'background_overlay_color',
731 'operator' => '!==',
732 'value' => '',
733 ],
734 ],
735 ],
736 ]
737 );
738
739 $this->end_controls_tab();
740
741 $this->start_controls_tab(
742 'tab_background_overlay_hover',
743 [
744 'label' => esc_html__( 'Hover', 'elementor' ),
745 ]
746 );
747
748 $this->add_group_control(
749 Group_Control_Background::get_type(),
750 [
751 'name' => 'background_overlay_hover',
752 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
753 ]
754 );
755
756 $this->add_responsive_control(
757 'background_overlay_hover_opacity',
758 [
759 'label' => esc_html__( 'Opacity', 'elementor' ),
760 'type' => Controls_Manager::SLIDER,
761 'default' => [
762 'size' => .5,
763 ],
764 'range' => [
765 'px' => [
766 'max' => 1,
767 'step' => 0.01,
768 ],
769 ],
770 'selectors' => [
771 '{{WRAPPER}}:hover > .elementor-background-overlay' => 'opacity: {{SIZE}};',
772 ],
773 'condition' => [
774 'background_overlay_hover_background' => [ 'classic', 'gradient' ],
775 ],
776 ]
777 );
778
779 $this->add_group_control(
780 Group_Control_Css_Filter::get_type(),
781 [
782 'name' => 'css_filters_hover',
783 'selector' => '{{WRAPPER}}:hover > .elementor-background-overlay',
784 ]
785 );
786
787 $this->add_control(
788 'background_overlay_hover_transition',
789 [
790 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
791 'type' => Controls_Manager::SLIDER,
792 'default' => [
793 'size' => 0.3,
794 ],
795 'range' => [
796 'px' => [
797 'min' => 0,
798 'max' => 3,
799 'step' => 0.1,
800 ],
801 ],
802 'render_type' => 'ui',
803 'separator' => 'before',
804 ]
805 );
806
807 $this->end_controls_tab();
808
809 $this->end_controls_tabs();
810
811 $this->end_controls_section();
812
813 // Section border
814 $this->start_controls_section(
815 'section_border',
816 [
817 'label' => esc_html__( 'Border', 'elementor' ),
818 'tab' => Controls_Manager::TAB_STYLE,
819 ]
820 );
821
822 $this->start_controls_tabs( 'tabs_border' );
823
824 $this->start_controls_tab(
825 'tab_border_normal',
826 [
827 'label' => esc_html__( 'Normal', 'elementor' ),
828 ]
829 );
830
831 $this->add_group_control(
832 Group_Control_Border::get_type(),
833 [
834 'name' => 'border',
835 ]
836 );
837
838 $this->add_responsive_control(
839 'border_radius',
840 [
841 'label' => esc_html__( 'Border Radius', 'elementor' ),
842 'type' => Controls_Manager::DIMENSIONS,
843 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
844 'selectors' => [
845 '{{WRAPPER}}, {{WRAPPER}} > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
846 ],
847 ]
848 );
849
850 $this->add_group_control(
851 Group_Control_Box_Shadow::get_type(),
852 [
853 'name' => 'box_shadow',
854 ]
855 );
856
857 $this->end_controls_tab();
858
859 $this->start_controls_tab(
860 'tab_border_hover',
861 [
862 'label' => esc_html__( 'Hover', 'elementor' ),
863 ]
864 );
865
866 $this->add_group_control(
867 Group_Control_Border::get_type(),
868 [
869 'name' => 'border_hover',
870 'selector' => '{{WRAPPER}}:hover',
871 ]
872 );
873
874 $this->add_responsive_control(
875 'border_radius_hover',
876 [
877 'label' => esc_html__( 'Border Radius', 'elementor' ),
878 'type' => Controls_Manager::DIMENSIONS,
879 'size_units' => [ 'px', '%', 'em', 'rem', 'custom' ],
880 'selectors' => [
881 '{{WRAPPER}}:hover, {{WRAPPER}}:hover > .elementor-background-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
882 ],
883 ]
884 );
885
886 $this->add_group_control(
887 Group_Control_Box_Shadow::get_type(),
888 [
889 'name' => 'box_shadow_hover',
890 'selector' => '{{WRAPPER}}:hover',
891 ]
892 );
893
894 $this->add_control(
895 'border_hover_transition',
896 [
897 'label' => esc_html__( 'Transition Duration', 'elementor' ) . ' (s)',
898 'type' => Controls_Manager::SLIDER,
899 'separator' => 'before',
900 'default' => [
901 'size' => 0.3,
902 ],
903 'range' => [
904 'px' => [
905 'min' => 0,
906 'max' => 3,
907 'step' => 0.1,
908 ],
909 ],
910 'conditions' => [
911 'relation' => 'or',
912 'terms' => [
913 [
914 'name' => 'background_background',
915 'operator' => '!==',
916 'value' => '',
917 ],
918 [
919 'name' => 'border_border',
920 'operator' => '!==',
921 'value' => '',
922 ],
923 ],
924 ],
925 'selectors' => [
926 '{{WRAPPER}}' => 'transition: background {{background_hover_transition.SIZE}}s, border {{SIZE}}s, border-radius {{SIZE}}s, box-shadow {{SIZE}}s',
927 '{{WRAPPER}} > .elementor-background-overlay' => 'transition: background {{background_overlay_hover_transition.SIZE}}s, border-radius {{SIZE}}s, opacity {{background_overlay_hover_transition.SIZE}}s',
928 ],
929 ]
930 );
931
932 $this->end_controls_tab();
933
934 $this->end_controls_tabs();
935
936 $this->end_controls_section();
937
938 // Section Shape Divider
939 $this->start_controls_section(
940 'section_shape_divider',
941 [
942 'label' => esc_html__( 'Shape Divider', 'elementor' ),
943 'tab' => Controls_Manager::TAB_STYLE,
944 ]
945 );
946
947 $this->start_controls_tabs( 'tabs_shape_dividers' );
948
949 $shapes_options = [
950 '' => esc_html__( 'None', 'elementor' ),
951 ];
952
953 foreach ( Shapes::get_shapes() as $shape_name => $shape_props ) {
954 $shapes_options[ $shape_name ] = $shape_props['title'];
955 }
956
957 foreach ( [
958 'top' => esc_html__( 'Top', 'elementor' ),
959 'bottom' => esc_html__( 'Bottom', 'elementor' ),
960 ] as $side => $side_label ) {
961 $base_control_key = "shape_divider_$side";
962
963 $this->start_controls_tab(
964 "tab_$base_control_key",
965 [
966 'label' => $side_label,
967 ]
968 );
969
970 $this->add_control(
971 $base_control_key,
972 [
973 'label' => esc_html__( 'Type', 'elementor' ),
974 'type' => Controls_Manager::SELECT,
975 'options' => $shapes_options,
976 'render_type' => 'none',
977 'frontend_available' => true,
978 'assets' => [
979 'styles' => [
980 [
981 'name' => 'e-shapes',
982 'conditions' => [
983 'terms' => [
984 [
985 'name' => $base_control_key,
986 'operator' => '!==',
987 'value' => '',
988 ],
989 ],
990 ],
991 ],
992 ],
993 ],
994 ]
995 );
996
997 $this->add_control(
998 $base_control_key . '_color',
999 [
1000 'label' => esc_html__( 'Color', 'elementor' ),
1001 'type' => Controls_Manager::COLOR,
1002 'condition' => [
1003 "shape_divider_$side!" => '',
1004 ],
1005 'selectors' => [
1006 "{{WRAPPER}} > .elementor-shape-$side .elementor-shape-fill" => 'fill: {{UNIT}};',
1007 ],
1008 ]
1009 );
1010
1011 $this->add_responsive_control(
1012 $base_control_key . '_width',
1013 [
1014 'label' => esc_html__( 'Width', 'elementor' ),
1015 'type' => Controls_Manager::SLIDER,
1016 'size_units' => [ '%', 'vw', 'custom' ],
1017 'default' => [
1018 'unit' => '%',
1019 ],
1020 'tablet_default' => [
1021 'unit' => '%',
1022 ],
1023 'mobile_default' => [
1024 'unit' => '%',
1025 ],
1026 'range' => [
1027 '%' => [
1028 'min' => 100,
1029 'max' => 300,
1030 ],
1031 'vw' => [
1032 'min' => 100,
1033 'max' => 300,
1034 ],
1035 ],
1036 'condition' => [
1037 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'height_only', Shapes::FILTER_EXCLUDE ) ),
1038 ],
1039 'selectors' => [
1040 "{{WRAPPER}} > .elementor-shape-$side svg" => 'width: calc({{SIZE}}{{UNIT}} + 1.3px)',
1041 ],
1042 ]
1043 );
1044
1045 $this->add_responsive_control(
1046 $base_control_key . '_height',
1047 [
1048 'label' => esc_html__( 'Height', 'elementor' ),
1049 'type' => Controls_Manager::SLIDER,
1050 'size_units' => [ 'px', 'em', 'rem', 'custom' ],
1051 'range' => [
1052 'px' => [
1053 'max' => 500,
1054 ],
1055 'em' => [
1056 'max' => 50,
1057 ],
1058 'rem' => [
1059 'max' => 50,
1060 ],
1061 ],
1062 'condition' => [
1063 "shape_divider_$side!" => '',
1064 ],
1065 'selectors' => [
1066 "{{WRAPPER}} > .elementor-shape-$side svg" => 'height: {{SIZE}}{{UNIT}};',
1067 ],
1068 ]
1069 );
1070
1071 $this->add_control(
1072 $base_control_key . '_flip',
1073 [
1074 'label' => esc_html__( 'Flip', 'elementor' ),
1075 'type' => Controls_Manager::SWITCHER,
1076 'condition' => [
1077 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_flip' ) ),
1078 ],
1079 'selectors' => [
1080 "{{WRAPPER}} > .elementor-shape-$side svg" => 'transform: translateX(-50%) rotateY(180deg)',
1081 ],
1082 ]
1083 );
1084
1085 $this->add_control(
1086 $base_control_key . '_negative',
1087 [
1088 'label' => esc_html__( 'Invert', 'elementor' ),
1089 'type' => Controls_Manager::SWITCHER,
1090 'frontend_available' => true,
1091 'condition' => [
1092 "shape_divider_$side" => array_keys( Shapes::filter_shapes( 'has_negative' ) ),
1093 ],
1094 'render_type' => 'none',
1095 ]
1096 );
1097
1098 $this->add_control(
1099 $base_control_key . '_above_content',
1100 [
1101 'label' => esc_html__( 'Bring to Front', 'elementor' ),
1102 'type' => Controls_Manager::SWITCHER,
1103 'selectors' => [
1104 "{{WRAPPER}} > .elementor-shape-$side" => 'z-index: 2; pointer-events: none',
1105 ],
1106 'condition' => [
1107 "shape_divider_$side!" => '',
1108 ],
1109 ]
1110 );
1111
1112 $this->end_controls_tab();
1113 }
1114
1115 $this->end_controls_tabs();
1116
1117 $this->end_controls_section();
1118
1119 // Section Typography
1120 $this->start_controls_section(
1121 'section_typo',
1122 [
1123 'label' => esc_html__( 'Typography', 'elementor' ),
1124 'tab' => Controls_Manager::TAB_STYLE,
1125 ]
1126 );
1127
1128 $this->add_control(
1129 'heading_color',
1130 [
1131 'label' => esc_html__( 'Heading Color', 'elementor' ),
1132 'type' => Controls_Manager::COLOR,
1133 'default' => '',
1134 'selectors' => [
1135 '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
1136 ],
1137 ]
1138 );
1139
1140 $this->add_control(
1141 'color_text',
1142 [
1143 'label' => esc_html__( 'Text Color', 'elementor' ),
1144 'type' => Controls_Manager::COLOR,
1145 'default' => '',
1146 'selectors' => [
1147 '{{WRAPPER}}' => 'color: {{VALUE}};',
1148 ],
1149 ]
1150 );
1151
1152 $this->add_control(
1153 'color_link',
1154 [
1155 'label' => esc_html__( 'Link Color', 'elementor' ),
1156 'type' => Controls_Manager::COLOR,
1157 'default' => '',
1158 'selectors' => [
1159 '{{WRAPPER}} a' => 'color: {{VALUE}};',
1160 ],
1161 ]
1162 );
1163
1164 $this->add_control(
1165 'color_link_hover',
1166 [
1167 'label' => esc_html__( 'Link Hover Color', 'elementor' ),
1168 'type' => Controls_Manager::COLOR,
1169 'default' => '',
1170 'selectors' => [
1171 '{{WRAPPER}} a:hover' => 'color: {{VALUE}};',
1172 ],
1173 ]
1174 );
1175
1176 $this->add_responsive_control(
1177 'text_align',
1178 [
1179 'label' => esc_html__( 'Text Align', 'elementor' ),
1180 'type' => Controls_Manager::CHOOSE,
1181 'options' => [
1182 'left' => [
1183 'title' => esc_html__( 'Left', 'elementor' ),
1184 'icon' => 'eicon-text-align-left',
1185 ],
1186 'center' => [
1187 'title' => esc_html__( 'Center', 'elementor' ),
1188 'icon' => 'eicon-text-align-center',
1189 ],
1190 'right' => [
1191 'title' => esc_html__( 'Right', 'elementor' ),
1192 'icon' => 'eicon-text-align-right',
1193 ],
1194 'justify' => [
1195 'title' => esc_html__( 'Justified', 'elementor' ),
1196 'icon' => 'eicon-text-align-justify',
1197 ],
1198 ],
1199 'selectors' => [
1200 '{{WRAPPER}} > .elementor-container' => 'text-align: {{VALUE}};',
1201 ],
1202 ]
1203 );
1204
1205 $this->end_controls_section();
1206
1207 // Section Advanced
1208 $this->start_controls_section(
1209 'section_advanced',
1210 [
1211 'label' => esc_html__( 'Advanced', 'elementor' ),
1212 'tab' => Controls_Manager::TAB_ADVANCED,
1213 ]
1214 );
1215
1216 $this->add_responsive_control(
1217 'margin',
1218 [
1219 'label' => esc_html__( 'Margin', 'elementor' ),
1220 'type' => Controls_Manager::DIMENSIONS,
1221 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1222 'allowed_dimensions' => 'vertical',
1223 'placeholder' => [
1224 'top' => '',
1225 'right' => 'auto',
1226 'bottom' => '',
1227 'left' => 'auto',
1228 ],
1229 'selectors' => [
1230 '{{WRAPPER}}' => 'margin-top: {{TOP}}{{UNIT}}; margin-bottom: {{BOTTOM}}{{UNIT}};',
1231 ],
1232 ]
1233 );
1234
1235 $this->add_responsive_control(
1236 'padding',
1237 [
1238 'label' => esc_html__( 'Padding', 'elementor' ),
1239 'type' => Controls_Manager::DIMENSIONS,
1240 'size_units' => [ 'px', '%', 'em', 'rem', 'vw', 'custom' ],
1241 'selectors' => [
1242 '{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
1243 ],
1244 ]
1245 );
1246
1247 $this->add_responsive_control(
1248 'z_index',
1249 [
1250 'label' => esc_html__( 'Z-Index', 'elementor' ),
1251 'type' => Controls_Manager::NUMBER,
1252 'min' => 0,
1253 'selectors' => [
1254 '{{WRAPPER}}' => 'z-index: {{VALUE}};',
1255 ],
1256 ]
1257 );
1258
1259 $this->add_control(
1260 '_element_id',
1261 [
1262 'label' => esc_html__( 'CSS ID', 'elementor' ),
1263 'type' => Controls_Manager::TEXT,
1264 'default' => '',
1265 'ai' => [
1266 'active' => false,
1267 ],
1268 'dynamic' => [
1269 'active' => true,
1270 ],
1271 'title' => esc_html__( 'Add your custom id WITHOUT the Pound key. e.g: my-id', 'elementor' ),
1272 'style_transfer' => false,
1273 'classes' => 'elementor-control-direction-ltr',
1274 ]
1275 );
1276
1277 $this->add_control(
1278 'css_classes',
1279 [
1280 'label' => esc_html__( 'CSS Classes', 'elementor' ),
1281 'type' => Controls_Manager::TEXT,
1282 'default' => '',
1283 'ai' => [
1284 'active' => false,
1285 ],
1286 'dynamic' => [
1287 'active' => true,
1288 ],
1289 'prefix_class' => '',
1290 'title' => esc_html__( 'Add your custom class WITHOUT the dot. e.g: my-class', 'elementor' ),
1291 'classes' => 'elementor-control-direction-ltr',
1292 ]
1293 );
1294
1295 Plugin::$instance->controls_manager->add_display_conditions_controls( $this );
1296
1297 $this->end_controls_section();
1298
1299 $this->start_controls_section(
1300 'section_effects',
1301 [
1302 'label' => esc_html__( 'Motion Effects', 'elementor' ),
1303 'tab' => Controls_Manager::TAB_ADVANCED,
1304 ]
1305 );
1306
1307 Plugin::$instance->controls_manager->add_motion_effects_promotion_control( $this );
1308
1309 $this->add_responsive_control(
1310 'animation',
1311 [
1312 'label' => esc_html__( 'Entrance Animation', 'elementor' ),
1313 'type' => Controls_Manager::ANIMATION,
1314 'frontend_available' => true,
1315 ]
1316 );
1317
1318 $this->add_control(
1319 'animation_duration',
1320 [
1321 'label' => esc_html__( 'Animation Duration', 'elementor' ),
1322 'type' => Controls_Manager::SELECT,
1323 'default' => '',
1324 'options' => [
1325 'slow' => esc_html__( 'Slow', 'elementor' ),
1326 '' => esc_html__( 'Normal', 'elementor' ),
1327 'fast' => esc_html__( 'Fast', 'elementor' ),
1328 ],
1329 'prefix_class' => 'animated-',
1330 'condition' => [
1331 'animation!' => '',
1332 ],
1333 ]
1334 );
1335
1336 $this->add_control(
1337 'animation_delay',
1338 [
1339 'label' => esc_html__( 'Animation Delay', 'elementor' ) . ' (ms)',
1340 'type' => Controls_Manager::NUMBER,
1341 'default' => '',
1342 'min' => 0,
1343 'step' => 100,
1344 'condition' => [
1345 'animation!' => '',
1346 ],
1347 'render_type' => 'none',
1348 'frontend_available' => true,
1349 ]
1350 );
1351
1352 $this->end_controls_section();
1353
1354 // Section Responsive
1355 $this->start_controls_section(
1356 '_section_responsive',
1357 [
1358 'label' => esc_html__( 'Responsive', 'elementor' ),
1359 'tab' => Controls_Manager::TAB_ADVANCED,
1360 ]
1361 );
1362
1363 // The controls should be displayed from largest to smallest breakpoint, so we reverse the array.
1364 $active_breakpoints = array_reverse( Plugin::$instance->breakpoints->get_active_breakpoints() );
1365
1366 foreach ( $active_breakpoints as $breakpoint_key => $breakpoint ) {
1367 $this->add_control(
1368 'reverse_order_' . $breakpoint_key,
1369 [
1370 'label' => esc_html__( 'Reverse Columns', 'elementor' ) . ' (' . $breakpoint->get_label() . ')',
1371 'type' => Controls_Manager::SWITCHER,
1372 'default' => '',
1373 'prefix_class' => 'elementor-',
1374 'return_value' => 'reverse-' . $breakpoint_key,
1375 ]
1376 );
1377 }
1378
1379 $this->add_control(
1380 'heading_visibility',
1381 [
1382 'label' => esc_html__( 'Visibility', 'elementor' ),
1383 'type' => Controls_Manager::HEADING,
1384 'separator' => 'before',
1385 ]
1386 );
1387
1388 $this->add_control(
1389 'responsive_description',
1390 [
1391 'raw' => sprintf(
1392 /* translators: 1: Link open tag, 2: Link close tag. */
1393 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' ),
1394 '<a href="javascript: $e.run( \'panel/close\' )">',
1395 '</a>'
1396 ),
1397 'type' => Controls_Manager::RAW_HTML,
1398 'content_classes' => 'elementor-descriptor',
1399 ]
1400 );
1401
1402 $this->add_hidden_device_controls();
1403
1404 $this->end_controls_section();
1405
1406 Plugin::$instance->controls_manager->add_custom_attributes_controls( $this );
1407
1408 Plugin::$instance->controls_manager->add_custom_css_controls( $this );
1409 }
1410
1411 /**
1412 * Render section output in the editor.
1413 *
1414 * Used to generate the live preview, using a Backbone JavaScript template.
1415 *
1416 * @since 2.9.0
1417 * @access protected
1418 */
1419 protected function content_template() {
1420 ?>
1421 <#
1422 if ( settings.background_video_link ) {
1423 let videoAttributes = 'autoplay muted playsinline';
1424
1425 if ( ! settings.background_play_once ) {
1426 videoAttributes += ' loop';
1427 }
1428
1429 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1430
1431 if ( ! settings.background_play_on_mobile ) {
1432 view.addRenderAttribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1433 }
1434 #>
1435 <div {{{ view.getRenderAttributeString( 'background-video-container' ) }}}>
1436 <div class="elementor-background-video-embed"></div>
1437 <video class="elementor-background-video-hosted elementor-html5-video" {{ videoAttributes }}></video>
1438 </div>
1439 <# } #>
1440 <div class="elementor-background-overlay"></div>
1441 <div class="elementor-shape elementor-shape-top"></div>
1442 <div class="elementor-shape elementor-shape-bottom"></div>
1443 <div class="elementor-container elementor-column-gap-{{ settings.gap }}"></div>
1444 <?php
1445 }
1446
1447 /**
1448 * Before section rendering.
1449 *
1450 * Used to add stuff before the section element.
1451 *
1452 * @since 1.0.0
1453 * @access public
1454 */
1455 public function before_render() {
1456 $settings = $this->get_settings_for_display();
1457 ?>
1458 <<?php
1459 // PHPCS - the method get_html_tag is safe.
1460 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1461 ?> <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
1462 <?php
1463 if ( 'video' === $settings['background_background'] ) :
1464 if ( $settings['background_video_link'] ) :
1465 $video_properties = Embed::get_video_properties( $settings['background_video_link'] );
1466
1467 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-background-video-container' );
1468
1469 if ( ! $settings['background_play_on_mobile'] ) {
1470 $this->add_render_attribute( 'background-video-container', 'class', 'elementor-hidden-mobile' );
1471 }
1472 ?>
1473 <div <?php $this->print_render_attribute_string( 'background-video-container' ); ?>>
1474 <?php if ( $video_properties ) : ?>
1475 <div class="elementor-background-video-embed"></div>
1476 <?php
1477 else :
1478 $video_tag_attributes = 'autoplay muted playsinline';
1479 if ( 'yes' !== $settings['background_play_once'] ) :
1480 $video_tag_attributes .= ' loop';
1481 endif;
1482 ?>
1483 <video class="elementor-background-video-hosted elementor-html5-video" <?php
1484 // PHPCS - the variable $video_tag_attributes is a plain string.
1485 echo $video_tag_attributes; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1486 ?>></video>
1487 <?php endif; ?>
1488 </div>
1489 <?php
1490 endif;
1491 endif;
1492
1493 $overlay_background = $settings['background_overlay_background'] ?? '';
1494 $overlay_hover_background = $settings['background_overlay_hover_background'] ?? '';
1495
1496 $has_background_overlay = in_array( $overlay_background, [ 'classic', 'gradient' ], true ) ||
1497 in_array( $overlay_hover_background, [ 'classic', 'gradient' ], true );
1498
1499 if ( $has_background_overlay ) :
1500 ?>
1501 <div class="elementor-background-overlay"></div>
1502 <?php
1503 endif;
1504
1505 if ( $settings['shape_divider_top'] ) {
1506 $this->print_shape_divider( 'top' );
1507 }
1508
1509 if ( $settings['shape_divider_bottom'] ) {
1510 $this->print_shape_divider( 'bottom' );
1511 }
1512 ?>
1513 <div class="elementor-container elementor-column-gap-<?php echo esc_attr( $settings['gap'] ); ?>">
1514 <?php
1515 }
1516
1517 /**
1518 * After section rendering.
1519 *
1520 * Used to add stuff after the section element.
1521 *
1522 * @since 1.0.0
1523 * @access public
1524 */
1525 public function after_render() {
1526 ?>
1527 </div>
1528 </<?php
1529 // PHPCS - the method get_html_tag is safe.
1530 echo $this->get_html_tag(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1531 ?>>
1532 <?php
1533 }
1534
1535 /**
1536 * Add section render attributes.
1537 *
1538 * Used to add attributes to the current section wrapper HTML tag.
1539 *
1540 * @since 1.3.0
1541 * @access protected
1542 */
1543 protected function add_render_attributes() {
1544
1545 $section_type = $this->get_data( 'isInner' ) ? 'inner' : 'top';
1546
1547 $this->add_render_attribute(
1548 '_wrapper', 'class', [
1549 'elementor-section',
1550 'elementor-' . $section_type . '-section',
1551 ]
1552 );
1553
1554 parent::add_render_attributes();
1555 }
1556
1557 /**
1558 * Get default child type.
1559 *
1560 * Retrieve the section child type based on element data.
1561 *
1562 * @since 1.0.0
1563 * @access protected
1564 *
1565 * @param array $element_data Element ID.
1566 *
1567 * @return Element_Base Section default child type.
1568 */
1569 protected function _get_default_child_type( array $element_data ) {
1570 return Plugin::$instance->elements_manager->get_element_types( 'column' );
1571 }
1572
1573 /**
1574 * Get HTML tag.
1575 *
1576 * Retrieve the section element HTML tag.
1577 *
1578 * @since 1.5.3
1579 * @access private
1580 *
1581 * @return string Section HTML tag.
1582 */
1583 protected function get_html_tag() {
1584 $html_tag = $this->get_settings( 'html_tag' );
1585
1586 if ( empty( $html_tag ) ) {
1587 $html_tag = 'section';
1588 }
1589
1590 return Utils::validate_html_tag( $html_tag );
1591 }
1592
1593 /**
1594 * Print section shape divider.
1595 *
1596 * Used to generate the shape dividers HTML.
1597 *
1598 * @since 1.3.0
1599 * @access private
1600 *
1601 * @param string $side Shape divider side, used to set the shape key.
1602 */
1603 protected function print_shape_divider( $side ) {
1604 $settings = $this->get_active_settings();
1605 $base_setting_key = "shape_divider_$side";
1606 $negative = ! empty( $settings[ $base_setting_key . '_negative' ] );
1607 $shape_path = Shapes::get_shape_path( $settings[ $base_setting_key ], $negative );
1608 if ( ! is_file( $shape_path ) || ! is_readable( $shape_path ) ) {
1609 return;
1610 }
1611
1612 ?>
1613 <div class="elementor-shape elementor-shape-<?php echo esc_attr( $side ); ?>" data-negative="<?php
1614 Utils::print_unescaped_internal_string( $negative ? 'true' : 'false' );
1615 ?>">
1616 <?php
1617 // PHPCS - The file content is being read from a strict file path structure.
1618 echo Utils::file_get_contents( $shape_path ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1619 ?>
1620 </div>
1621 <?php
1622 }
1623 }
1624