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

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