PluginProbe
Elementor Website Builder – more than just a page builder / 3.7.8
Elementor Website Builder – more than just a page builder v3.7.8
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 / managers / controls.php

controls.php in Elementor Website Builder – more than just a page builder 3.7.8, at includes/managers/controls.php

1,137 lines 25.5 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 controls manager.
10 *
11 * Elementor controls manager handler class is responsible for registering and
12 * initializing all the supported controls, both regular controls and the group
13 * controls.
14 *
15 * @since 1.0.0
16 */
17 class Controls_Manager {
18
19 /**
20 * Content tab.
21 */
22 const TAB_CONTENT = 'content';
23
24 /**
25 * Style tab.
26 */
27 const TAB_STYLE = 'style';
28
29 /**
30 * Advanced tab.
31 */
32 const TAB_ADVANCED = 'advanced';
33
34 /**
35 * Responsive tab.
36 */
37 const TAB_RESPONSIVE = 'responsive';
38
39 /**
40 * Layout tab.
41 */
42 const TAB_LAYOUT = 'layout';
43
44 /**
45 * Settings tab.
46 */
47 const TAB_SETTINGS = 'settings';
48
49 /**
50 * Text control.
51 */
52 const TEXT = 'text';
53
54 /**
55 * Number control.
56 */
57 const NUMBER = 'number';
58
59 /**
60 * Textarea control.
61 */
62 const TEXTAREA = 'textarea';
63
64 /**
65 * Select control.
66 */
67 const SELECT = 'select';
68
69 /**
70 * Switcher control.
71 */
72 const SWITCHER = 'switcher';
73
74 /**
75 * Button control.
76 */
77 const BUTTON = 'button';
78
79 /**
80 * Hidden control.
81 */
82 const HIDDEN = 'hidden';
83
84 /**
85 * Heading control.
86 */
87 const HEADING = 'heading';
88
89 /**
90 * Raw HTML control.
91 */
92 const RAW_HTML = 'raw_html';
93
94 /**
95 * Deprecated Notice control.
96 */
97 const DEPRECATED_NOTICE = 'deprecated_notice';
98
99 /**
100 * Popover Toggle control.
101 */
102 const POPOVER_TOGGLE = 'popover_toggle';
103
104 /**
105 * Section control.
106 */
107 const SECTION = 'section';
108
109 /**
110 * Tab control.
111 */
112 const TAB = 'tab';
113
114 /**
115 * Tabs control.
116 */
117 const TABS = 'tabs';
118
119 /**
120 * Divider control.
121 */
122 const DIVIDER = 'divider';
123
124 /**
125 * Color control.
126 */
127 const COLOR = 'color';
128
129 /**
130 * Media control.
131 */
132 const MEDIA = 'media';
133
134 /**
135 * Slider control.
136 */
137 const SLIDER = 'slider';
138
139 /**
140 * Dimensions control.
141 */
142 const DIMENSIONS = 'dimensions';
143
144 /**
145 * Choose control.
146 */
147 const CHOOSE = 'choose';
148
149 /**
150 * WYSIWYG control.
151 */
152 const WYSIWYG = 'wysiwyg';
153
154 /**
155 * Code control.
156 */
157 const CODE = 'code';
158
159 /**
160 * Font control.
161 */
162 const FONT = 'font';
163
164 /**
165 * Image dimensions control.
166 */
167 const IMAGE_DIMENSIONS = 'image_dimensions';
168
169 /**
170 * WordPress widget control.
171 */
172 const WP_WIDGET = 'wp_widget';
173
174 /**
175 * URL control.
176 */
177 const URL = 'url';
178
179 /**
180 * Repeater control.
181 */
182 const REPEATER = 'repeater';
183
184 /**
185 * Icon control.
186 */
187 const ICON = 'icon';
188
189 /**
190 * Icons control.
191 */
192 const ICONS = 'icons';
193
194 /**
195 * Gallery control.
196 */
197 const GALLERY = 'gallery';
198
199 /**
200 * Structure control.
201 */
202 const STRUCTURE = 'structure';
203
204 /**
205 * Select2 control.
206 */
207 const SELECT2 = 'select2';
208
209 /**
210 * Date/Time control.
211 */
212 const DATE_TIME = 'date_time';
213
214 /**
215 * Box shadow control.
216 */
217 const BOX_SHADOW = 'box_shadow';
218
219 /**
220 * Text shadow control.
221 */
222 const TEXT_SHADOW = 'text_shadow';
223
224 /**
225 * Entrance animation control.
226 */
227 const ANIMATION = 'animation';
228
229 /**
230 * Hover animation control.
231 */
232 const HOVER_ANIMATION = 'hover_animation';
233
234 /**
235 * Exit animation control.
236 */
237 const EXIT_ANIMATION = 'exit_animation';
238
239 /**
240 * Controls.
241 *
242 * Holds the list of all the controls. Default is `null`.
243 *
244 * @since 1.0.0
245 * @access private
246 *
247 * @var Base_Control[]
248 */
249 private $controls = null;
250
251 /**
252 * Control groups.
253 *
254 * Holds the list of all the control groups. Default is an empty array.
255 *
256 * @since 1.0.0
257 * @access private
258 *
259 * @var Group_Control_Base[]
260 */
261 private $control_groups = [];
262
263 /**
264 * Control stacks.
265 *
266 * Holds the list of all the control stacks. Default is an empty array.
267 *
268 * @since 1.0.0
269 * @access private
270 *
271 * @var array
272 */
273 private $stacks = [];
274
275 /**
276 * Tabs.
277 *
278 * Holds the list of all the tabs.
279 *
280 * @since 1.0.0
281 * @access private
282 * @static
283 *
284 * @var array
285 */
286 private static $tabs;
287
288 /**
289 * Init tabs.
290 *
291 * Initialize control tabs.
292 *
293 * @since 1.6.0
294 * @access private
295 * @static
296 */
297 private static function init_tabs() {
298 self::$tabs = [
299 self::TAB_CONTENT => esc_html__( 'Content', 'elementor' ),
300 self::TAB_STYLE => esc_html__( 'Style', 'elementor' ),
301 self::TAB_ADVANCED => esc_html__( 'Advanced', 'elementor' ),
302 self::TAB_RESPONSIVE => esc_html__( 'Responsive', 'elementor' ),
303 self::TAB_LAYOUT => esc_html__( 'Layout', 'elementor' ),
304 self::TAB_SETTINGS => esc_html__( 'Settings', 'elementor' ),
305 ];
306 }
307
308 /**
309 * Get tabs.
310 *
311 * Retrieve the tabs of the current control.
312 *
313 * @since 1.6.0
314 * @access public
315 * @static
316 *
317 * @return array Control tabs.
318 */
319 public static function get_tabs() {
320 if ( ! self::$tabs ) {
321 self::init_tabs();
322 }
323
324 return self::$tabs;
325 }
326
327 /**
328 * Add tab.
329 *
330 * This method adds a new tab to the current control.
331 *
332 * @since 1.6.0
333 * @access public
334 * @static
335 *
336 * @param string $tab_name Tab name.
337 * @param string $tab_label Tab label.
338 */
339 public static function add_tab( $tab_name, $tab_label = '' ) {
340 if ( ! self::$tabs ) {
341 self::init_tabs();
342 }
343
344 if ( isset( self::$tabs[ $tab_name ] ) ) {
345 return;
346 }
347
348 self::$tabs[ $tab_name ] = $tab_label;
349 }
350
351 public static function get_groups_names() {
352 // Group name must use "-" instead of "_"
353 return [
354 'background',
355 'border',
356 'typography',
357 'image-size',
358 'box-shadow',
359 'css-filter',
360 'text-shadow',
361 'flex-container',
362 'flex-item',
363 'text-stroke',
364 ];
365 }
366
367 public static function get_controls_names() {
368 return [
369 self::TEXT,
370 self::NUMBER,
371 self::TEXTAREA,
372 self::SELECT,
373 self::SWITCHER,
374
375 self::BUTTON,
376 self::HIDDEN,
377 self::HEADING,
378 self::RAW_HTML,
379 self::POPOVER_TOGGLE,
380 self::SECTION,
381 self::TAB,
382 self::TABS,
383 self::DIVIDER,
384 self::DEPRECATED_NOTICE,
385
386 self::COLOR,
387 self::MEDIA,
388 self::SLIDER,
389 self::DIMENSIONS,
390 self::CHOOSE,
391 self::WYSIWYG,
392 self::CODE,
393 self::FONT,
394 self::IMAGE_DIMENSIONS,
395
396 self::WP_WIDGET,
397
398 self::URL,
399 self::REPEATER,
400 self::ICON,
401 self::ICONS,
402 self::GALLERY,
403 self::STRUCTURE,
404 self::SELECT2,
405 self::DATE_TIME,
406 self::BOX_SHADOW,
407 self::TEXT_SHADOW,
408 self::ANIMATION,
409 self::HOVER_ANIMATION,
410 self::EXIT_ANIMATION,
411 ];
412 }
413
414 /**
415 * Register controls.
416 *
417 * This method creates a list of all the supported controls by requiring the
418 * control files and initializing each one of them.
419 *
420 * The list of supported controls includes the regular controls and the group
421 * controls.
422 *
423 * External developers can register new controls by hooking to the
424 * `elementor/controls/controls_registered` action.
425 *
426 * @since 3.1.0
427 * @access private
428 */
429 private function register_controls() {
430 $this->controls = [];
431
432 foreach ( self::get_controls_names() as $control_id ) {
433 $control_class_id = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $control_id ) ) );
434 $class_name = __NAMESPACE__ . '\Control_' . $control_class_id;
435
436 $this->register( new $class_name() );
437 }
438
439 // Group Controls
440 foreach ( self::get_groups_names() as $group_name ) {
441 $group_class_id = str_replace( ' ', '_', ucwords( str_replace( '-', ' ', $group_name ) ) );
442 $class_name = __NAMESPACE__ . '\Group_Control_' . $group_class_id;
443
444 $this->control_groups[ $group_name ] = new $class_name();
445 }
446
447 /**
448 * After controls registered.
449 *
450 * Fires after Elementor controls are registered.
451 *
452 * @since 1.0.0
453 * @deprecated 3.5.0 Use `elementor/controls/register` hook instead.
454 *
455 * @param Controls_Manager $this The controls manager.
456 */
457 // TODO: Uncomment when Pro uses the new hook.
458 //Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->do_deprecated_action(
459 // 'elementor/controls/controls_registered',
460 // [ $this ],
461 // '3.5.0',
462 // 'elementor/controls/register'
463 //);
464
465 do_action( 'elementor/controls/controls_registered', $this );
466
467 /**
468 * After controls registered.
469 *
470 * Fires after Elementor controls are registered.
471 *
472 * @since 3.5.0
473 *
474 * @param Controls_Manager $this The controls manager.
475 */
476 do_action( 'elementor/controls/register', $this );
477 }
478
479 /**
480 * Register control.
481 *
482 * This method adds a new control to the controls list. It adds any given
483 * control to any given control instance.
484 *
485 * @since 1.0.0
486 * @access public
487 * @deprecated 3.5.0 Use `$this->register()` instead.
488 *
489 * @param string $control_id Control ID.
490 * @param Base_Control $control_instance Control instance, usually the
491 * current instance.
492 */
493 public function register_control( $control_id, Base_Control $control_instance ) {
494 // TODO: Uncomment when Pro uses the new hook.
495 //Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function(
496 // __METHOD__,
497 // '3.5.0',
498 // 'register'
499 //);
500
501 $this->register( $control_instance, $control_id );
502 }
503
504 /**
505 * Register control.
506 *
507 * This method adds a new control to the controls list. It adds any given
508 * control to any given control instance.
509 *
510 * @since 3.5.0
511 * @access public
512 *
513 * @param Base_Control $control_instance Control instance, usually the current instance.
514 * @param string $control_id Control ID. Deprecated parameter.
515 *
516 * @return void
517 */
518 public function register( Base_Control $control_instance, $control_id = null ) {
519
520 // TODO: For BC. Remove in the future.
521 if ( $control_id ) {
522 Plugin::instance()->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_argument(
523 '$control_id', '3.5.0'
524 );
525 } else {
526 $control_id = $control_instance->get_type();
527 }
528
529 $this->controls[ $control_id ] = $control_instance;
530 }
531
532 /**
533 * Unregister control.
534 *
535 * This method removes control from the controls list.
536 *
537 * @since 1.0.0
538 * @access public
539 * @deprecated 3.5.0 Use `$this->unregister()` instead.
540 *
541 * @param string $control_id Control ID.
542 *
543 * @return bool True if the control was removed, False otherwise.
544 */
545 public function unregister_control( $control_id ) {
546 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function(
547 __METHOD__,
548 '3.5.0',
549 'unregister'
550 );
551
552 return $this->unregister( $control_id );
553 }
554
555 /**
556 * Unregister control.
557 *
558 * This method removes control from the controls list.
559 *
560 * @since 3.5.0
561 * @access public
562 *
563 * @param string $control_id Control ID.
564 *
565 * @return bool Whether the controls has been unregistered.
566 */
567 public function unregister( $control_id ) {
568 if ( ! isset( $this->controls[ $control_id ] ) ) {
569 return false;
570 }
571
572 unset( $this->controls[ $control_id ] );
573
574 return true;
575 }
576
577 /**
578 * Get controls.
579 *
580 * Retrieve the controls list from the current instance.
581 *
582 * @since 1.0.0
583 * @access public
584 *
585 * @return Base_Control[] Controls list.
586 */
587 public function get_controls() {
588 if ( null === $this->controls ) {
589 $this->register_controls();
590 }
591
592 return $this->controls;
593 }
594
595 /**
596 * Get control.
597 *
598 * Retrieve a specific control from the current controls instance.
599 *
600 * @since 1.0.0
601 * @access public
602 *
603 * @param string $control_id Control ID.
604 *
605 * @return bool|Base_Control Control instance, or False otherwise.
606 */
607 public function get_control( $control_id ) {
608 $controls = $this->get_controls();
609
610 return isset( $controls[ $control_id ] ) ? $controls[ $control_id ] : false;
611 }
612
613 /**
614 * Get controls data.
615 *
616 * Retrieve all the registered controls and all the data for each control.
617 *
618 * @since 1.0.0
619 * @access public
620 *
621 * @return array {
622 * Control data.
623 *
624 * @type array $name Control data.
625 * }
626 */
627 public function get_controls_data() {
628 $controls_data = [];
629
630 foreach ( $this->get_controls() as $name => $control ) {
631 $controls_data[ $name ] = $control->get_settings();
632 }
633
634 return $controls_data;
635 }
636
637 /**
638 * Render controls.
639 *
640 * Generate the final HTML for all the registered controls using the element
641 * template.
642 *
643 * @since 1.0.0
644 * @access public
645 */
646 public function render_controls() {
647 foreach ( $this->get_controls() as $control ) {
648 $control->print_template();
649 }
650 }
651
652 /**
653 * Get control groups.
654 *
655 * Retrieve a specific group for a given ID, or a list of all the control
656 * groups.
657 *
658 * If the given group ID is wrong, it will return `null`. When the ID valid,
659 * it will return the group control instance. When no ID was given, it will
660 * return all the control groups.
661 *
662 * @since 1.0.10
663 * @access public
664 *
665 * @param string $id Optional. Group ID. Default is null.
666 *
667 * @return null|Group_Control_Base|Group_Control_Base[]
668 */
669 public function get_control_groups( $id = null ) {
670 if ( $id ) {
671 return isset( $this->control_groups[ $id ] ) ? $this->control_groups[ $id ] : null;
672 }
673
674 return $this->control_groups;
675 }
676
677 /**
678 * Add group control.
679 *
680 * This method adds a new group control to the control groups list. It adds
681 * any given group control to any given group control instance.
682 *
683 * @since 1.0.0
684 * @access public
685 *
686 * @param string $id Group control ID.
687 * @param Group_Control_Base $instance Group control instance, usually the
688 * current instance.
689 *
690 * @return Group_Control_Base Group control instance.
691 */
692 public function add_group_control( $id, $instance ) {
693 $this->control_groups[ $id ] = $instance;
694
695 return $instance;
696 }
697
698 /**
699 * Enqueue control scripts and styles.
700 *
701 * Used to register and enqueue custom scripts and styles used by the control.
702 *
703 * @since 1.0.0
704 * @access public
705 */
706 public function enqueue_control_scripts() {
707 foreach ( $this->get_controls() as $control ) {
708 $control->enqueue();
709 }
710 }
711
712 /**
713 * Open new stack.
714 *
715 * This method adds a new stack to the control stacks list. It adds any
716 * given stack to the current control instance.
717 *
718 * @since 1.0.0
719 * @access public
720 *
721 * @param Controls_Stack $controls_stack Controls stack.
722 */
723 public function open_stack( Controls_Stack $controls_stack ) {
724 $stack_id = $controls_stack->get_unique_name();
725
726 $this->stacks[ $stack_id ] = [
727 'tabs' => [],
728 'controls' => [],
729 ];
730 }
731
732 /**
733 * Remove existing stack from the stacks cache
734 *
735 * Removes the stack of a passed instance from the Controls Manager's stacks cache.
736 *
737 * @param Controls_Stack $controls_stack
738 * @return void
739 */
740 public function delete_stack( Controls_Stack $controls_stack ) {
741 $stack_id = $controls_stack->get_unique_name();
742
743 unset( $this->stacks[ $stack_id ] );
744 }
745
746 /**
747 * Add control to stack.
748 *
749 * This method adds a new control to the stack.
750 *
751 * @since 1.0.0
752 * @access public
753 *
754 * @param Controls_Stack $element Element stack.
755 * @param string $control_id Control ID.
756 * @param array $control_data Control data.
757 * @param array $options Optional. Control additional options.
758 * Default is an empty array.
759 *
760 * @return bool True if control added, False otherwise.
761 */
762 public function add_control_to_stack( Controls_Stack $element, $control_id, $control_data, $options = [] ) {
763 $default_options = [
764 'overwrite' => false,
765 'index' => null,
766 ];
767
768 $options = array_merge( $default_options, $options );
769
770 $default_args = [
771 'type' => self::TEXT,
772 'tab' => self::TAB_CONTENT,
773 ];
774
775 $control_data['name'] = $control_id;
776
777 $control_data = array_merge( $default_args, $control_data );
778
779 $control_type_instance = $this->get_control( $control_data['type'] );
780
781 if ( ! $control_type_instance ) {
782 _doing_it_wrong( sprintf( '%1$s::%2$s', __CLASS__, __FUNCTION__ ), sprintf( 'Control type "%s" not found.', esc_html( $control_data['type'] ) ), '1.0.0' );
783 return false;
784 }
785
786 if ( $control_type_instance instanceof Base_Data_Control ) {
787 $control_default_value = $control_type_instance->get_default_value();
788
789 if ( is_array( $control_default_value ) ) {
790 $control_data['default'] = isset( $control_data['default'] ) ? array_merge( $control_default_value, $control_data['default'] ) : $control_default_value;
791 } else {
792 $control_data['default'] = isset( $control_data['default'] ) ? $control_data['default'] : $control_default_value;
793 }
794 }
795
796 $stack_id = $element->get_unique_name();
797
798 if ( ! $options['overwrite'] && isset( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
799 _doing_it_wrong( sprintf( '%1$s::%2$s', __CLASS__, __FUNCTION__ ), sprintf( 'Cannot redeclare control with same name "%s".', esc_html( $control_id ) ), '1.0.0' );
800
801 return false;
802 }
803
804 $tabs = self::get_tabs();
805
806 if ( ! isset( $tabs[ $control_data['tab'] ] ) ) {
807 $control_data['tab'] = $default_args['tab'];
808 }
809
810 $this->stacks[ $stack_id ]['tabs'][ $control_data['tab'] ] = $tabs[ $control_data['tab'] ];
811
812 $this->stacks[ $stack_id ]['controls'][ $control_id ] = $control_data;
813
814 if ( null !== $options['index'] ) {
815 $controls = $this->stacks[ $stack_id ]['controls'];
816
817 $controls_keys = array_keys( $controls );
818
819 array_splice( $controls_keys, $options['index'], 0, $control_id );
820
821 $this->stacks[ $stack_id ]['controls'] = array_merge( array_flip( $controls_keys ), $controls );
822 }
823
824 return true;
825 }
826
827 /**
828 * Remove control from stack.
829 *
830 * This method removes a control a the stack.
831 *
832 * @since 1.0.0
833 * @access public
834 *
835 * @param string $stack_id Stack ID.
836 * @param array|string $control_id The ID of the control to remove.
837 *
838 * @return bool|\WP_Error True if the stack was removed, False otherwise.
839 */
840 public function remove_control_from_stack( $stack_id, $control_id ) {
841 if ( is_array( $control_id ) ) {
842 foreach ( $control_id as $id ) {
843 $this->remove_control_from_stack( $stack_id, $id );
844 }
845
846 return true;
847 }
848
849 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
850 return new \WP_Error( 'Cannot remove not-exists control.' );
851 }
852
853 unset( $this->stacks[ $stack_id ]['controls'][ $control_id ] );
854
855 return true;
856 }
857
858 /**
859 * Get control from stack.
860 *
861 * Retrieve a specific control for a given a specific stack.
862 *
863 * If the given control does not exist in the stack, or the stack does not
864 * exist, it will return `WP_Error`. Otherwise, it will retrieve the control
865 * from the stack.
866 *
867 * @since 1.1.0
868 * @access public
869 *
870 * @param string $stack_id Stack ID.
871 * @param string $control_id Control ID.
872 *
873 * @return array|\WP_Error The control, or an error.
874 */
875 public function get_control_from_stack( $stack_id, $control_id ) {
876 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
877 return new \WP_Error( 'Cannot get a not-exists control.' );
878 }
879
880 return $this->stacks[ $stack_id ]['controls'][ $control_id ];
881 }
882
883 /**
884 * Update control in stack.
885 *
886 * This method updates the control data for a given stack.
887 *
888 * @since 1.1.0
889 * @access public
890 *
891 * @param Controls_Stack $element Element stack.
892 * @param string $control_id Control ID.
893 * @param array $control_data Control data.
894 * @param array $options Optional. Control additional options.
895 * Default is an empty array.
896 *
897 * @return bool True if control updated, False otherwise.
898 */
899 public function update_control_in_stack( Controls_Stack $element, $control_id, $control_data, array $options = [] ) {
900 $old_control_data = $this->get_control_from_stack( $element->get_unique_name(), $control_id );
901
902 if ( is_wp_error( $old_control_data ) ) {
903 return false;
904 }
905
906 if ( ! empty( $options['recursive'] ) ) {
907 $control_data = array_replace_recursive( $old_control_data, $control_data );
908 } else {
909 $control_data = array_merge( $old_control_data, $control_data );
910 }
911
912 return $this->add_control_to_stack( $element, $control_id, $control_data, [
913 'overwrite' => true,
914 ] );
915 }
916
917 /**
918 * Get stacks.
919 *
920 * Retrieve a specific stack for the list of stacks.
921 *
922 * If the given stack is wrong, it will return `null`. When the stack valid,
923 * it will return the the specific stack. When no stack was given, it will
924 * return all the stacks.
925 *
926 * @since 1.7.1
927 * @access public
928 *
929 * @param string $stack_id Optional. stack ID. Default is null.
930 *
931 * @return null|array A list of stacks.
932 */
933 public function get_stacks( $stack_id = null ) {
934 if ( $stack_id ) {
935 if ( isset( $this->stacks[ $stack_id ] ) ) {
936 return $this->stacks[ $stack_id ];
937 }
938
939 return null;
940 }
941
942 return $this->stacks;
943 }
944
945 /**
946 * Get element stack.
947 *
948 * Retrieve a specific stack for the list of stacks from the current instance.
949 *
950 * @since 1.0.0
951 * @access public
952 *
953 * @param Controls_Stack $controls_stack Controls stack.
954 *
955 * @return null|array Stack data if it exist, `null` otherwise.
956 */
957 public function get_element_stack( Controls_Stack $controls_stack ) {
958 $stack_id = $controls_stack->get_unique_name();
959
960 if ( ! isset( $this->stacks[ $stack_id ] ) ) {
961 return null;
962 }
963
964 return $this->stacks[ $stack_id ];
965 }
966
967 /**
968 * Add custom CSS controls.
969 *
970 * This method adds a new control for the "Custom CSS" feature. The free
971 * version of elementor uses this method to display an upgrade message to
972 * Elementor Pro.
973 *
974 * @since 1.0.0
975 * @access public
976 *
977 * @param Controls_Stack $controls_stack .
978 * @param string $tab
979 * @param array $additional_messages
980 *
981 */
982 public function add_custom_css_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) {
983 $controls_stack->start_controls_section(
984 'section_custom_css_pro',
985 [
986 'label' => esc_html__( 'Custom CSS', 'elementor' ),
987 'tab' => $tab,
988 ]
989 );
990
991 $messages = [
992 esc_html__( 'Custom CSS lets you add CSS code to any widget, and see it render live right in the editor.', 'elementor' ),
993 ];
994
995 if ( $additional_messages ) {
996 $messages = array_merge( $messages, $additional_messages );
997 }
998
999 $controls_stack->add_control(
1000 'custom_css_pro',
1001 [
1002 'type' => self::RAW_HTML,
1003 'raw' => $this->get_teaser_template( [
1004 'title' => esc_html__( 'Meet Our Custom CSS', 'elementor' ),
1005 'messages' => $messages,
1006 'link' => 'https://go.elementor.com/go-pro-custom-css/',
1007 ] ),
1008 ]
1009 );
1010
1011 $controls_stack->end_controls_section();
1012 }
1013
1014 /**
1015 * Add Page Transitions controls.
1016 *
1017 * This method adds a new control for the "Page Transitions" feature. The Core
1018 * version of elementor uses this method to display an upgrade message to
1019 * Elementor Pro.
1020 *
1021 * @param Controls_Stack $controls_stack .
1022 * @param string $tab
1023 * @param array $additional_messages
1024 *
1025 * @return void
1026 */
1027 public function add_page_transitions_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) {
1028 $controls_stack->start_controls_section(
1029 'section_page_transitions_teaser',
1030 [
1031 'label' => esc_html__( 'Page Transitions', 'elementor' ),
1032 'tab' => $tab,
1033 ]
1034 );
1035
1036 $messages = [
1037 esc_html__( 'Page Transitions let you style entrance and exit animations between pages as well as display loader until your page assets load.', 'elementor' ),
1038 ];
1039
1040 if ( $additional_messages ) {
1041 $messages = array_merge( $messages, $additional_messages );
1042 }
1043
1044 $controls_stack->add_control(
1045 'page_transitions_teaser',
1046 [
1047 'type' => self::RAW_HTML,
1048 'raw' => $this->get_teaser_template( [
1049 'title' => esc_html__( 'Meet Page Transitions', 'elementor' ),
1050 'messages' => $messages,
1051 'link' => 'https://go.elementor.com/go-pro-page-transitions/',
1052 ] ),
1053 ]
1054 );
1055
1056 $controls_stack->end_controls_section();
1057 }
1058
1059 public function get_teaser_template( $texts ) {
1060 ob_start();
1061 ?>
1062 <div class="elementor-nerd-box">
1063 <img class="elementor-nerd-box-icon" src="<?php echo esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ); ?>" />
1064 <div class="elementor-nerd-box-title"><?php Utils::print_unescaped_internal_string( $texts['title'] ); ?></div>
1065 <?php foreach ( $texts['messages'] as $message ) { ?>
1066 <div class="elementor-nerd-box-message"><?php Utils::print_unescaped_internal_string( $message ); ?></div>
1067 <?php }
1068
1069 // Show a `Go Pro` button only if the user doesn't have Pro.
1070 if ( $texts['link'] && ! Utils::has_pro() ) { ?>
1071 <a class="elementor-nerd-box-link elementor-button elementor-button-default elementor-button-go-pro" href="<?php echo esc_url( ( $texts['link'] ) ); ?>" target="_blank">
1072 <?php echo esc_html__( 'Upgrade Now', 'elementor' ); ?>
1073 </a>
1074 <?php } ?>
1075 </div>
1076 <?php
1077
1078 return ob_get_clean();
1079 }
1080
1081 /**
1082 * Get Responsive Control Device Suffix
1083 *
1084 * @param array $control
1085 * @return string $device suffix
1086 */
1087 public static function get_responsive_control_device_suffix( array $control ): string {
1088 if ( ! empty( $control['responsive']['max'] ) ) {
1089 $query_device = $control['responsive']['max'];
1090 } elseif ( ! empty( $control['responsive']['min'] ) ) {
1091 $query_device = $control['responsive']['min'];
1092 } else {
1093 return '';
1094 }
1095
1096 return 'desktop' === $query_device ? '' : '_' . $query_device;
1097 }
1098
1099 /**
1100 * Add custom attributes controls.
1101 *
1102 * This method adds a new control for the "Custom Attributes" feature. The free
1103 * version of elementor uses this method to display an upgrade message to
1104 * Elementor Pro.
1105 *
1106 * @since 2.8.3
1107 * @access public
1108 *
1109 * @param Controls_Stack $controls_stack.
1110 */
1111 public function add_custom_attributes_controls( Controls_Stack $controls_stack ) {
1112 $controls_stack->start_controls_section(
1113 'section_custom_attributes_pro',
1114 [
1115 'label' => esc_html__( 'Attributes', 'elementor' ),
1116 'tab' => self::TAB_ADVANCED,
1117 ]
1118 );
1119
1120 $controls_stack->add_control(
1121 'custom_attributes_pro',
1122 [
1123 'type' => self::RAW_HTML,
1124 'raw' => $this->get_teaser_template( [
1125 'title' => esc_html__( 'Meet Our Attributes', 'elementor' ),
1126 'messages' => [
1127 esc_html__( 'Attributes lets you add custom HTML attributes to any element.', 'elementor' ),
1128 ],
1129 'link' => 'https://go.elementor.com/go-pro-custom-attributes/',
1130 ] ),
1131 ]
1132 );
1133
1134 $controls_stack->end_controls_section();
1135 }
1136 }
1137