PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.4
Elementor Website Builder – more than just a page builder v3.6.4
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.6.4, at includes/managers/controls.php

1,105 lines 24.8 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 * Add control to stack.
734 *
735 * This method adds a new control to the stack.
736 *
737 * @since 1.0.0
738 * @access public
739 *
740 * @param Controls_Stack $element Element stack.
741 * @param string $control_id Control ID.
742 * @param array $control_data Control data.
743 * @param array $options Optional. Control additional options.
744 * Default is an empty array.
745 *
746 * @return bool True if control added, False otherwise.
747 */
748 public function add_control_to_stack( Controls_Stack $element, $control_id, $control_data, $options = [] ) {
749 $default_options = [
750 'overwrite' => false,
751 'index' => null,
752 ];
753
754 $options = array_merge( $default_options, $options );
755
756 $default_args = [
757 'type' => self::TEXT,
758 'tab' => self::TAB_CONTENT,
759 ];
760
761 $control_data['name'] = $control_id;
762
763 $control_data = array_merge( $default_args, $control_data );
764
765 $control_type_instance = $this->get_control( $control_data['type'] );
766
767 if ( ! $control_type_instance ) {
768 _doing_it_wrong( sprintf( '%1$s::%2$s', __CLASS__, __FUNCTION__ ), sprintf( 'Control type "%s" not found.', esc_html( $control_data['type'] ) ), '1.0.0' );
769 return false;
770 }
771
772 if ( $control_type_instance instanceof Base_Data_Control ) {
773 $control_default_value = $control_type_instance->get_default_value();
774
775 if ( is_array( $control_default_value ) ) {
776 $control_data['default'] = isset( $control_data['default'] ) ? array_merge( $control_default_value, $control_data['default'] ) : $control_default_value;
777 } else {
778 $control_data['default'] = isset( $control_data['default'] ) ? $control_data['default'] : $control_default_value;
779 }
780 }
781
782 $stack_id = $element->get_unique_name();
783
784 if ( ! $options['overwrite'] && isset( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
785 _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' );
786
787 return false;
788 }
789
790 $tabs = self::get_tabs();
791
792 if ( ! isset( $tabs[ $control_data['tab'] ] ) ) {
793 $control_data['tab'] = $default_args['tab'];
794 }
795
796 $this->stacks[ $stack_id ]['tabs'][ $control_data['tab'] ] = $tabs[ $control_data['tab'] ];
797
798 $this->stacks[ $stack_id ]['controls'][ $control_id ] = $control_data;
799
800 if ( null !== $options['index'] ) {
801 $controls = $this->stacks[ $stack_id ]['controls'];
802
803 $controls_keys = array_keys( $controls );
804
805 array_splice( $controls_keys, $options['index'], 0, $control_id );
806
807 $this->stacks[ $stack_id ]['controls'] = array_merge( array_flip( $controls_keys ), $controls );
808 }
809
810 return true;
811 }
812
813 /**
814 * Remove control from stack.
815 *
816 * This method removes a control a the stack.
817 *
818 * @since 1.0.0
819 * @access public
820 *
821 * @param string $stack_id Stack ID.
822 * @param array|string $control_id The ID of the control to remove.
823 *
824 * @return bool|\WP_Error True if the stack was removed, False otherwise.
825 */
826 public function remove_control_from_stack( $stack_id, $control_id ) {
827 if ( is_array( $control_id ) ) {
828 foreach ( $control_id as $id ) {
829 $this->remove_control_from_stack( $stack_id, $id );
830 }
831
832 return true;
833 }
834
835 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
836 return new \WP_Error( 'Cannot remove not-exists control.' );
837 }
838
839 unset( $this->stacks[ $stack_id ]['controls'][ $control_id ] );
840
841 return true;
842 }
843
844 /**
845 * Get control from stack.
846 *
847 * Retrieve a specific control for a given a specific stack.
848 *
849 * If the given control does not exist in the stack, or the stack does not
850 * exist, it will return `WP_Error`. Otherwise, it will retrieve the control
851 * from the stack.
852 *
853 * @since 1.1.0
854 * @access public
855 *
856 * @param string $stack_id Stack ID.
857 * @param string $control_id Control ID.
858 *
859 * @return array|\WP_Error The control, or an error.
860 */
861 public function get_control_from_stack( $stack_id, $control_id ) {
862 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) {
863 return new \WP_Error( 'Cannot get a not-exists control.' );
864 }
865
866 return $this->stacks[ $stack_id ]['controls'][ $control_id ];
867 }
868
869 /**
870 * Update control in stack.
871 *
872 * This method updates the control data for a given stack.
873 *
874 * @since 1.1.0
875 * @access public
876 *
877 * @param Controls_Stack $element Element stack.
878 * @param string $control_id Control ID.
879 * @param array $control_data Control data.
880 * @param array $options Optional. Control additional options.
881 * Default is an empty array.
882 *
883 * @return bool True if control updated, False otherwise.
884 */
885 public function update_control_in_stack( Controls_Stack $element, $control_id, $control_data, array $options = [] ) {
886 $old_control_data = $this->get_control_from_stack( $element->get_unique_name(), $control_id );
887
888 if ( is_wp_error( $old_control_data ) ) {
889 return false;
890 }
891
892 if ( ! empty( $options['recursive'] ) ) {
893 $control_data = array_replace_recursive( $old_control_data, $control_data );
894 } else {
895 $control_data = array_merge( $old_control_data, $control_data );
896 }
897
898 return $this->add_control_to_stack( $element, $control_id, $control_data, [
899 'overwrite' => true,
900 ] );
901 }
902
903 /**
904 * Get stacks.
905 *
906 * Retrieve a specific stack for the list of stacks.
907 *
908 * If the given stack is wrong, it will return `null`. When the stack valid,
909 * it will return the the specific stack. When no stack was given, it will
910 * return all the stacks.
911 *
912 * @since 1.7.1
913 * @access public
914 *
915 * @param string $stack_id Optional. stack ID. Default is null.
916 *
917 * @return null|array A list of stacks.
918 */
919 public function get_stacks( $stack_id = null ) {
920 if ( $stack_id ) {
921 if ( isset( $this->stacks[ $stack_id ] ) ) {
922 return $this->stacks[ $stack_id ];
923 }
924
925 return null;
926 }
927
928 return $this->stacks;
929 }
930
931 /**
932 * Get element stack.
933 *
934 * Retrieve a specific stack for the list of stacks from the current instance.
935 *
936 * @since 1.0.0
937 * @access public
938 *
939 * @param Controls_Stack $controls_stack Controls stack.
940 *
941 * @return null|array Stack data if it exist, `null` otherwise.
942 */
943 public function get_element_stack( Controls_Stack $controls_stack ) {
944 $stack_id = $controls_stack->get_unique_name();
945
946 if ( ! isset( $this->stacks[ $stack_id ] ) ) {
947 return null;
948 }
949
950 return $this->stacks[ $stack_id ];
951 }
952
953 /**
954 * Add custom CSS controls.
955 *
956 * This method adds a new control for the "Custom CSS" feature. The free
957 * version of elementor uses this method to display an upgrade message to
958 * Elementor Pro.
959 *
960 * @since 1.0.0
961 * @access public
962 *
963 * @param Controls_Stack $controls_stack .
964 * @param string $tab
965 * @param array $additional_messages
966 *
967 */
968 public function add_custom_css_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) {
969 $controls_stack->start_controls_section(
970 'section_custom_css_pro',
971 [
972 'label' => esc_html__( 'Custom CSS', 'elementor' ),
973 'tab' => $tab,
974 ]
975 );
976
977 $messages = [
978 esc_html__( 'Custom CSS lets you add CSS code to any widget, and see it render live right in the editor.', 'elementor' ),
979 ];
980
981 if ( $additional_messages ) {
982 $messages = array_merge( $messages, $additional_messages );
983 }
984
985 $controls_stack->add_control(
986 'custom_css_pro',
987 [
988 'type' => self::RAW_HTML,
989 'raw' => $this->get_teaser_template( [
990 'title' => esc_html__( 'Meet Our Custom CSS', 'elementor' ),
991 'messages' => $messages,
992 'link' => 'https://elementor.com/pro/?utm_source=panel-custom-css&utm_campaign=gopro&utm_medium=wp-dash',
993 ] ),
994 ]
995 );
996
997 $controls_stack->end_controls_section();
998 }
999
1000 /**
1001 * Add Page Transitions controls.
1002 *
1003 * This method adds a new control for the "Page Transitions" feature. The Core
1004 * version of elementor uses this method to display an upgrade message to
1005 * Elementor Pro.
1006 *
1007 * @param Controls_Stack $controls_stack .
1008 * @param string $tab
1009 * @param array $additional_messages
1010 *
1011 * @return void
1012 */
1013 public function add_page_transitions_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) {
1014 $controls_stack->start_controls_section(
1015 'section_page_transitions_teaser',
1016 [
1017 'label' => esc_html__( 'Page Transitions', 'elementor' ),
1018 'tab' => $tab,
1019 ]
1020 );
1021
1022 $messages = [
1023 esc_html__( 'Page Transitions let you style entrance and exit animations between pages as well as display loader until your page assets load.', 'elementor' ),
1024 ];
1025
1026 if ( $additional_messages ) {
1027 $messages = array_merge( $messages, $additional_messages );
1028 }
1029
1030 $controls_stack->add_control(
1031 'page_transitions_teaser',
1032 [
1033 'type' => self::RAW_HTML,
1034 'raw' => $this->get_teaser_template( [
1035 'title' => esc_html__( 'Meet Page Transitions', 'elementor' ),
1036 'messages' => $messages,
1037 'link' => 'https://elementor.com/pro/?utm_source=panel-page-transitions&utm_campaign=gopro&utm_medium=wp-dash',
1038 ] ),
1039 ]
1040 );
1041
1042 $controls_stack->end_controls_section();
1043 }
1044
1045 public function get_teaser_template( $texts ) {
1046 ob_start();
1047 ?>
1048 <div class="elementor-nerd-box">
1049 <img class="elementor-nerd-box-icon" src="<?php echo esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ); ?>" />
1050 <div class="elementor-nerd-box-title"><?php Utils::print_unescaped_internal_string( $texts['title'] ); ?></div>
1051 <?php foreach ( $texts['messages'] as $message ) { ?>
1052 <div class="elementor-nerd-box-message"><?php Utils::print_unescaped_internal_string( $message ); ?></div>
1053 <?php }
1054
1055 // Show a `Go Pro` button only if the user doesn't have Pro.
1056 if ( $texts['link'] && ! Utils::has_pro() ) { ?>
1057 <a class="elementor-nerd-box-link elementor-button elementor-button-default elementor-button-go-pro" href="<?php echo esc_url( Utils::get_pro_link( $texts['link'] ) ); ?>" target="_blank">
1058 <?php echo esc_html__( 'Go Pro', 'elementor' ); ?>
1059 </a>
1060 <?php } ?>
1061 </div>
1062 <?php
1063
1064 return ob_get_clean();
1065 }
1066
1067 /**
1068 * Add custom attributes controls.
1069 *
1070 * This method adds a new control for the "Custom Attributes" feature. The free
1071 * version of elementor uses this method to display an upgrade message to
1072 * Elementor Pro.
1073 *
1074 * @since 2.8.3
1075 * @access public
1076 *
1077 * @param Controls_Stack $controls_stack.
1078 */
1079 public function add_custom_attributes_controls( Controls_Stack $controls_stack ) {
1080 $controls_stack->start_controls_section(
1081 'section_custom_attributes_pro',
1082 [
1083 'label' => esc_html__( 'Attributes', 'elementor' ),
1084 'tab' => self::TAB_ADVANCED,
1085 ]
1086 );
1087
1088 $controls_stack->add_control(
1089 'custom_attributes_pro',
1090 [
1091 'type' => self::RAW_HTML,
1092 'raw' => $this->get_teaser_template( [
1093 'title' => esc_html__( 'Meet Our Attributes', 'elementor' ),
1094 'messages' => [
1095 esc_html__( 'Attributes lets you add custom HTML attributes to any element.', 'elementor' ),
1096 ],
1097 'link' => 'https://elementor.com/pro/?utm_source=panel-custom-attributes&utm_campaign=gopro&utm_medium=wp-dash',
1098 ] ),
1099 ]
1100 );
1101
1102 $controls_stack->end_controls_section();
1103 }
1104 }
1105