controls.php (23122B)
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 ]; 362 } 363 364 public static function get_controls_names() { 365 return [ 366 self::TEXT, 367 self::NUMBER, 368 self::TEXTAREA, 369 self::SELECT, 370 self::SWITCHER, 371 372 self::BUTTON, 373 self::HIDDEN, 374 self::HEADING, 375 self::RAW_HTML, 376 self::POPOVER_TOGGLE, 377 self::SECTION, 378 self::TAB, 379 self::TABS, 380 self::DIVIDER, 381 self::DEPRECATED_NOTICE, 382 383 self::COLOR, 384 self::MEDIA, 385 self::SLIDER, 386 self::DIMENSIONS, 387 self::CHOOSE, 388 self::WYSIWYG, 389 self::CODE, 390 self::FONT, 391 self::IMAGE_DIMENSIONS, 392 393 self::WP_WIDGET, 394 395 self::URL, 396 self::REPEATER, 397 self::ICON, 398 self::ICONS, 399 self::GALLERY, 400 self::STRUCTURE, 401 self::SELECT2, 402 self::DATE_TIME, 403 self::BOX_SHADOW, 404 self::TEXT_SHADOW, 405 self::ANIMATION, 406 self::HOVER_ANIMATION, 407 self::EXIT_ANIMATION, 408 ]; 409 } 410 411 /** 412 * Register controls. 413 * 414 * This method creates a list of all the supported controls by requiring the 415 * control files and initializing each one of them. 416 * 417 * The list of supported controls includes the regular controls and the group 418 * controls. 419 * 420 * External developers can register new controls by hooking to the 421 * `elementor/controls/controls_registered` action. 422 * 423 * @since 3.1.0 424 * @access private 425 */ 426 private function register_controls() { 427 $this->controls = []; 428 429 foreach ( self::get_controls_names() as $control_id ) { 430 $control_class_id = str_replace( ' ', '_', ucwords( str_replace( '_', ' ', $control_id ) ) ); 431 $class_name = __NAMESPACE__ . '\Control_' . $control_class_id; 432 433 $this->register_control( $control_id, new $class_name() ); 434 } 435 436 // Group Controls 437 foreach ( self::get_groups_names() as $group_name ) { 438 $group_class_id = str_replace( ' ', '_', ucwords( str_replace( '-', ' ', $group_name ) ) ); 439 $class_name = __NAMESPACE__ . '\Group_Control_' . $group_class_id; 440 441 $this->control_groups[ $group_name ] = new $class_name(); 442 } 443 444 /** 445 * After controls registered. 446 * 447 * Fires after Elementor controls are registered. 448 * 449 * @since 1.0.0 450 * 451 * @param Controls_Manager $this The controls manager. 452 */ 453 do_action( 'elementor/controls/controls_registered', $this ); 454 } 455 456 /** 457 * Register control. 458 * 459 * This method adds a new control to the controls list. It adds any given 460 * control to any given control instance. 461 * 462 * @since 1.0.0 463 * @access public 464 * 465 * @param string $control_id Control ID. 466 * @param Base_Control $control_instance Control instance, usually the 467 * current instance. 468 */ 469 public function register_control( $control_id, Base_Control $control_instance ) { 470 $this->controls[ $control_id ] = $control_instance; 471 } 472 473 /** 474 * Unregister control. 475 * 476 * This method removes control from the controls list. 477 * 478 * @since 1.0.0 479 * @access public 480 * 481 * @param string $control_id Control ID. 482 * 483 * @return bool True if the control was removed, False otherwise. 484 */ 485 public function unregister_control( $control_id ) { 486 if ( ! isset( $this->controls[ $control_id ] ) ) { 487 return false; 488 } 489 490 unset( $this->controls[ $control_id ] ); 491 492 return true; 493 } 494 495 /** 496 * Get controls. 497 * 498 * Retrieve the controls list from the current instance. 499 * 500 * @since 1.0.0 501 * @access public 502 * 503 * @return Base_Control[] Controls list. 504 */ 505 public function get_controls() { 506 if ( null === $this->controls ) { 507 $this->register_controls(); 508 } 509 510 return $this->controls; 511 } 512 513 /** 514 * Get control. 515 * 516 * Retrieve a specific control from the current controls instance. 517 * 518 * @since 1.0.0 519 * @access public 520 * 521 * @param string $control_id Control ID. 522 * 523 * @return bool|Base_Control Control instance, or False otherwise. 524 */ 525 public function get_control( $control_id ) { 526 $controls = $this->get_controls(); 527 528 return isset( $controls[ $control_id ] ) ? $controls[ $control_id ] : false; 529 } 530 531 /** 532 * Get controls data. 533 * 534 * Retrieve all the registered controls and all the data for each control. 535 * 536 * @since 1.0.0 537 * @access public 538 * 539 * @return array { 540 * Control data. 541 * 542 * @type array $name Control data. 543 * } 544 */ 545 public function get_controls_data() { 546 $controls_data = []; 547 548 foreach ( $this->get_controls() as $name => $control ) { 549 $controls_data[ $name ] = $control->get_settings(); 550 } 551 552 return $controls_data; 553 } 554 555 /** 556 * Render controls. 557 * 558 * Generate the final HTML for all the registered controls using the element 559 * template. 560 * 561 * @since 1.0.0 562 * @access public 563 */ 564 public function render_controls() { 565 foreach ( $this->get_controls() as $control ) { 566 $control->print_template(); 567 } 568 } 569 570 /** 571 * Get control groups. 572 * 573 * Retrieve a specific group for a given ID, or a list of all the control 574 * groups. 575 * 576 * If the given group ID is wrong, it will return `null`. When the ID valid, 577 * it will return the group control instance. When no ID was given, it will 578 * return all the control groups. 579 * 580 * @since 1.0.10 581 * @access public 582 * 583 * @param string $id Optional. Group ID. Default is null. 584 * 585 * @return null|Group_Control_Base|Group_Control_Base[] 586 */ 587 public function get_control_groups( $id = null ) { 588 if ( $id ) { 589 return isset( $this->control_groups[ $id ] ) ? $this->control_groups[ $id ] : null; 590 } 591 592 return $this->control_groups; 593 } 594 595 /** 596 * Add group control. 597 * 598 * This method adds a new group control to the control groups list. It adds 599 * any given group control to any given group control instance. 600 * 601 * @since 1.0.0 602 * @access public 603 * 604 * @param string $id Group control ID. 605 * @param Group_Control_Base $instance Group control instance, usually the 606 * current instance. 607 * 608 * @return Group_Control_Base Group control instance. 609 */ 610 public function add_group_control( $id, $instance ) { 611 $this->control_groups[ $id ] = $instance; 612 613 return $instance; 614 } 615 616 /** 617 * Enqueue control scripts and styles. 618 * 619 * Used to register and enqueue custom scripts and styles used by the control. 620 * 621 * @since 1.0.0 622 * @access public 623 */ 624 public function enqueue_control_scripts() { 625 foreach ( $this->get_controls() as $control ) { 626 $control->enqueue(); 627 } 628 } 629 630 /** 631 * Open new stack. 632 * 633 * This method adds a new stack to the control stacks list. It adds any 634 * given stack to the current control instance. 635 * 636 * @since 1.0.0 637 * @access public 638 * 639 * @param Controls_Stack $controls_stack Controls stack. 640 */ 641 public function open_stack( Controls_Stack $controls_stack ) { 642 $stack_id = $controls_stack->get_unique_name(); 643 644 $this->stacks[ $stack_id ] = [ 645 'tabs' => [], 646 'controls' => [], 647 ]; 648 } 649 650 /** 651 * Add control to stack. 652 * 653 * This method adds a new control to the stack. 654 * 655 * @since 1.0.0 656 * @access public 657 * 658 * @param Controls_Stack $element Element stack. 659 * @param string $control_id Control ID. 660 * @param array $control_data Control data. 661 * @param array $options Optional. Control additional options. 662 * Default is an empty array. 663 * 664 * @return bool True if control added, False otherwise. 665 */ 666 public function add_control_to_stack( Controls_Stack $element, $control_id, $control_data, $options = [] ) { 667 $default_options = [ 668 'overwrite' => false, 669 'index' => null, 670 ]; 671 672 $options = array_merge( $default_options, $options ); 673 674 $default_args = [ 675 'type' => self::TEXT, 676 'tab' => self::TAB_CONTENT, 677 ]; 678 679 $control_data['name'] = $control_id; 680 681 $control_data = array_merge( $default_args, $control_data ); 682 683 $control_type_instance = $this->get_control( $control_data['type'] ); 684 685 if ( ! $control_type_instance ) { 686 _doing_it_wrong( sprintf( '%1$s::%2$s', __CLASS__, __FUNCTION__ ), sprintf( 'Control type "%s" not found.', esc_html( $control_data['type'] ) ), '1.0.0' ); 687 return false; 688 } 689 690 if ( $control_type_instance instanceof Base_Data_Control ) { 691 $control_default_value = $control_type_instance->get_default_value(); 692 693 if ( is_array( $control_default_value ) ) { 694 $control_data['default'] = isset( $control_data['default'] ) ? array_merge( $control_default_value, $control_data['default'] ) : $control_default_value; 695 } else { 696 $control_data['default'] = isset( $control_data['default'] ) ? $control_data['default'] : $control_default_value; 697 } 698 } 699 700 $stack_id = $element->get_unique_name(); 701 702 if ( ! $options['overwrite'] && isset( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) { 703 _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' ); 704 705 return false; 706 } 707 708 $tabs = self::get_tabs(); 709 710 if ( ! isset( $tabs[ $control_data['tab'] ] ) ) { 711 $control_data['tab'] = $default_args['tab']; 712 } 713 714 $this->stacks[ $stack_id ]['tabs'][ $control_data['tab'] ] = $tabs[ $control_data['tab'] ]; 715 716 $this->stacks[ $stack_id ]['controls'][ $control_id ] = $control_data; 717 718 if ( null !== $options['index'] ) { 719 $controls = $this->stacks[ $stack_id ]['controls']; 720 721 $controls_keys = array_keys( $controls ); 722 723 array_splice( $controls_keys, $options['index'], 0, $control_id ); 724 725 $this->stacks[ $stack_id ]['controls'] = array_merge( array_flip( $controls_keys ), $controls ); 726 } 727 728 return true; 729 } 730 731 /** 732 * Remove control from stack. 733 * 734 * This method removes a control a the stack. 735 * 736 * @since 1.0.0 737 * @access public 738 * 739 * @param string $stack_id Stack ID. 740 * @param array|string $control_id The ID of the control to remove. 741 * 742 * @return bool|\WP_Error True if the stack was removed, False otherwise. 743 */ 744 public function remove_control_from_stack( $stack_id, $control_id ) { 745 if ( is_array( $control_id ) ) { 746 foreach ( $control_id as $id ) { 747 $this->remove_control_from_stack( $stack_id, $id ); 748 } 749 750 return true; 751 } 752 753 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) { 754 return new \WP_Error( 'Cannot remove not-exists control.' ); 755 } 756 757 unset( $this->stacks[ $stack_id ]['controls'][ $control_id ] ); 758 759 return true; 760 } 761 762 /** 763 * Get control from stack. 764 * 765 * Retrieve a specific control for a given a specific stack. 766 * 767 * If the given control does not exist in the stack, or the stack does not 768 * exist, it will return `WP_Error`. Otherwise, it will retrieve the control 769 * from the stack. 770 * 771 * @since 1.1.0 772 * @access public 773 * 774 * @param string $stack_id Stack ID. 775 * @param string $control_id Control ID. 776 * 777 * @return array|\WP_Error The control, or an error. 778 */ 779 public function get_control_from_stack( $stack_id, $control_id ) { 780 if ( empty( $this->stacks[ $stack_id ]['controls'][ $control_id ] ) ) { 781 return new \WP_Error( 'Cannot get a not-exists control.' ); 782 } 783 784 return $this->stacks[ $stack_id ]['controls'][ $control_id ]; 785 } 786 787 /** 788 * Update control in stack. 789 * 790 * This method updates the control data for a given stack. 791 * 792 * @since 1.1.0 793 * @access public 794 * 795 * @param Controls_Stack $element Element stack. 796 * @param string $control_id Control ID. 797 * @param array $control_data Control data. 798 * @param array $options Optional. Control additional options. 799 * Default is an empty array. 800 * 801 * @return bool True if control updated, False otherwise. 802 */ 803 public function update_control_in_stack( Controls_Stack $element, $control_id, $control_data, array $options = [] ) { 804 $old_control_data = $this->get_control_from_stack( $element->get_unique_name(), $control_id ); 805 806 if ( is_wp_error( $old_control_data ) ) { 807 return false; 808 } 809 810 if ( ! empty( $options['recursive'] ) ) { 811 $control_data = array_replace_recursive( $old_control_data, $control_data ); 812 } else { 813 $control_data = array_merge( $old_control_data, $control_data ); 814 } 815 816 return $this->add_control_to_stack( $element, $control_id, $control_data, [ 817 'overwrite' => true, 818 ] ); 819 } 820 821 /** 822 * Get stacks. 823 * 824 * Retrieve a specific stack for the list of stacks. 825 * 826 * If the given stack is wrong, it will return `null`. When the stack valid, 827 * it will return the the specific stack. When no stack was given, it will 828 * return all the stacks. 829 * 830 * @since 1.7.1 831 * @access public 832 * 833 * @param string $stack_id Optional. stack ID. Default is null. 834 * 835 * @return null|array A list of stacks. 836 */ 837 public function get_stacks( $stack_id = null ) { 838 if ( $stack_id ) { 839 if ( isset( $this->stacks[ $stack_id ] ) ) { 840 return $this->stacks[ $stack_id ]; 841 } 842 843 return null; 844 } 845 846 return $this->stacks; 847 } 848 849 /** 850 * Get element stack. 851 * 852 * Retrieve a specific stack for the list of stacks from the current instance. 853 * 854 * @since 1.0.0 855 * @access public 856 * 857 * @param Controls_Stack $controls_stack Controls stack. 858 * 859 * @return null|array Stack data if it exist, `null` otherwise. 860 */ 861 public function get_element_stack( Controls_Stack $controls_stack ) { 862 $stack_id = $controls_stack->get_unique_name(); 863 864 if ( ! isset( $this->stacks[ $stack_id ] ) ) { 865 return null; 866 } 867 868 return $this->stacks[ $stack_id ]; 869 } 870 871 /** 872 * Add custom CSS controls. 873 * 874 * This method adds a new control for the "Custom CSS" feature. The free 875 * version of elementor uses this method to display an upgrade message to 876 * Elementor Pro. 877 * 878 * @since 1.0.0 879 * @access public 880 * 881 * @param Controls_Stack $controls_stack . 882 * @param string $tab 883 * @param array $additional_messages 884 * 885 */ 886 public function add_custom_css_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) { 887 $controls_stack->start_controls_section( 888 'section_custom_css_pro', 889 [ 890 'label' => esc_html__( 'Custom CSS', 'elementor' ), 891 'tab' => $tab, 892 ] 893 ); 894 895 $messages = [ 896 __( 'Custom CSS lets you add CSS code to any widget, and see it render live right in the editor.', 'elementor' ), 897 ]; 898 899 if ( $additional_messages ) { 900 $messages = array_merge( $messages, $additional_messages ); 901 } 902 903 $controls_stack->add_control( 904 'custom_css_pro', 905 [ 906 'type' => self::RAW_HTML, 907 'raw' => $this->get_teaser_template( [ 908 'title' => esc_html__( 'Meet Our Custom CSS', 'elementor' ), 909 'messages' => $messages, 910 'link' => 'https://elementor.com/pro/?utm_source=panel-custom-css&utm_campaign=gopro&utm_medium=wp-dash', 911 ] ), 912 ] 913 ); 914 915 $controls_stack->end_controls_section(); 916 } 917 918 /** 919 * Add Page Transitions controls. 920 * 921 * This method adds a new control for the "Page Transitions" feature. The Core 922 * version of elementor uses this method to display an upgrade message to 923 * Elementor Pro. 924 * 925 * @param Controls_Stack $controls_stack . 926 * @param string $tab 927 * @param array $additional_messages 928 * 929 * @return void 930 */ 931 public function add_page_transitions_controls( Controls_Stack $controls_stack, $tab = self::TAB_ADVANCED, $additional_messages = [] ) { 932 $controls_stack->start_controls_section( 933 'section_page_transitions_teaser', 934 [ 935 'label' => __( 'Page Transitions', 'elementor' ), 936 'tab' => $tab, 937 ] 938 ); 939 940 $messages = [ 941 __( 'Page Transitions let you style entrance and exit animations between pages as well as display loader until your page assets load.', 'elementor' ), 942 ]; 943 944 if ( $additional_messages ) { 945 $messages = array_merge( $messages, $additional_messages ); 946 } 947 948 $controls_stack->add_control( 949 'page_transitions_teaser', 950 [ 951 'type' => self::RAW_HTML, 952 'raw' => $this->get_teaser_template( [ 953 'title' => __( 'Meet Page Transitions', 'elementor' ), 954 'messages' => $messages, 955 'link' => 'https://elementor.com/pro/?utm_source=panel-page-transitions&utm_campaign=gopro&utm_medium=wp-dash', 956 ] ), 957 ] 958 ); 959 960 $controls_stack->end_controls_section(); 961 } 962 963 public function get_teaser_template( $texts ) { 964 ob_start(); 965 ?> 966 <div class="elementor-nerd-box"> 967 <img class="elementor-nerd-box-icon" src="<?php echo esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ); ?>" /> 968 <div class="elementor-nerd-box-title"><?php Utils::print_unescaped_internal_string( $texts['title'] ); ?></div> 969 <?php foreach ( $texts['messages'] as $message ) { ?> 970 <div class="elementor-nerd-box-message"><?php Utils::print_unescaped_internal_string( $message ); ?></div> 971 <?php } 972 973 // Show a `Go Pro` button only if the user doesn't have Pro. 974 if ( $texts['link'] && ! Utils::has_pro() ) { ?> 975 <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"> 976 <?php echo esc_html__( 'Go Pro', 'elementor' ); ?> 977 </a> 978 <?php } ?> 979 </div> 980 <?php 981 982 return ob_get_clean(); 983 } 984 985 /** 986 * Add custom attributes controls. 987 * 988 * This method adds a new control for the "Custom Attributes" feature. The free 989 * version of elementor uses this method to display an upgrade message to 990 * Elementor Pro. 991 * 992 * @since 2.8.3 993 * @access public 994 * 995 * @param Controls_Stack $controls_stack. 996 */ 997 public function add_custom_attributes_controls( Controls_Stack $controls_stack ) { 998 $controls_stack->start_controls_section( 999 'section_custom_attributes_pro', 1000 [ 1001 'label' => esc_html__( 'Attributes', 'elementor' ), 1002 'tab' => self::TAB_ADVANCED, 1003 ] 1004 ); 1005 1006 $controls_stack->add_control( 1007 'custom_attributes_pro', 1008 [ 1009 'type' => self::RAW_HTML, 1010 'raw' => $this->get_teaser_template( [ 1011 'title' => esc_html__( 'Meet Our Attributes', 'elementor' ), 1012 'messages' => [ 1013 __( 'Attributes lets you add custom HTML attributes to any element.', 'elementor' ), 1014 ], 1015 'link' => 'https://elementor.com/pro/?utm_source=panel-custom-attributes&utm_campaign=gopro&utm_medium=wp-dash', 1016 ] ), 1017 ] 1018 ); 1019 1020 $controls_stack->end_controls_section(); 1021 } 1022 }