PluginProbe
Elementor Website Builder – more than just a page builder / 3.1.1
Elementor Website Builder – more than just a page builder v3.1.1
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 / base / widget-base.php

widget-base.php in Elementor Website Builder – more than just a page builder 3.1.1, at includes/base/widget-base.php

908 lines 23.1 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 widget base.
10 *
11 * An abstract class to register new Elementor widgets. It extended the
12 * `Element_Base` class to inherit its properties.
13 *
14 * This abstract class must be extended in order to register new widgets.
15 *
16 * @since 1.0.0
17 * @abstract
18 */
19 abstract class Widget_Base extends Element_Base {
20
21 /**
22 * Whether the widget has content.
23 *
24 * Used in cases where the widget has no content. When widgets uses only
25 * skins to display dynamic content generated on the server. For example the
26 * posts widget in Elementor Pro. Default is true, the widget has content
27 * template.
28 *
29 * @access protected
30 *
31 * @var bool
32 */
33 protected $_has_template_content = true;
34
35 /**
36 * Get element type.
37 *
38 * Retrieve the element type, in this case `widget`.
39 *
40 * @since 1.0.0
41 * @access public
42 * @static
43 *
44 * @return string The type.
45 */
46 public static function get_type() {
47 return 'widget';
48 }
49
50 /**
51 * Get widget icon.
52 *
53 * Retrieve the widget icon.
54 *
55 * @since 1.0.0
56 * @access public
57 *
58 * @return string Widget icon.
59 */
60 public function get_icon() {
61 return 'eicon-apps';
62 }
63
64 /**
65 * Get widget keywords.
66 *
67 * Retrieve the widget keywords.
68 *
69 * @since 1.0.10
70 * @access public
71 *
72 * @return array Widget keywords.
73 */
74 public function get_keywords() {
75 return [];
76 }
77
78 /**
79 * Get widget categories.
80 *
81 * Retrieve the widget categories.
82 *
83 * @since 1.0.10
84 * @access public
85 *
86 * @return array Widget categories.
87 */
88 public function get_categories() {
89 return [ 'general' ];
90 }
91
92 /**
93 * Widget base constructor.
94 *
95 * Initializing the widget base class.
96 *
97 * @since 1.0.0
98 * @access public
99 *
100 * @throws \Exception If arguments are missing when initializing a full widget
101 * instance.
102 *
103 * @param array $data Widget data. Default is an empty array.
104 * @param array|null $args Optional. Widget default arguments. Default is null.
105 */
106 public function __construct( $data = [], $args = null ) {
107 parent::__construct( $data, $args );
108
109 $is_type_instance = $this->is_type_instance();
110
111 if ( ! $is_type_instance && null === $args ) {
112 throw new \Exception( '`$args` argument is required when initializing a full widget instance.' );
113 }
114
115 if ( $is_type_instance ) {
116 if ( $this->has_own_method( '_register_skins', self::class ) ) {
117 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( '_register_skins', '3.1.0', __CLASS__ . '::register_skins()' );
118
119 $this->_register_skins();
120 } else {
121 $this->register_skins();
122 }
123
124 $widget_name = $this->get_name();
125
126 /**
127 * Widget skin init.
128 *
129 * Fires when Elementor widget is being initialized.
130 *
131 * The dynamic portion of the hook name, `$widget_name`, refers to the widget name.
132 *
133 * @since 1.0.0
134 *
135 * @param Widget_Base $this The current widget.
136 */
137 do_action( "elementor/widget/{$widget_name}/skins_init", $this );
138 }
139 }
140
141 /**
142 * Get stack.
143 *
144 * Retrieve the widget stack of controls.
145 *
146 * @since 1.9.2
147 * @access public
148 *
149 * @param bool $with_common_controls Optional. Whether to include the common controls. Default is true.
150 *
151 * @return array Widget stack of controls.
152 */
153 public function get_stack( $with_common_controls = true ) {
154 $stack = parent::get_stack();
155
156 if ( $with_common_controls && 'common' !== $this->get_unique_name() ) {
157 /** @var Widget_Common $common_widget */
158 $common_widget = Plugin::$instance->widgets_manager->get_widget_types( 'common' );
159
160 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
161
162 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
163 }
164
165 return $stack;
166 }
167
168 /**
169 * Get widget controls pointer index.
170 *
171 * Retrieve widget pointer index where the next control should be added.
172 *
173 * While using injection point, it will return the injection point index. Otherwise index of the last control of the
174 * current widget itself without the common controls, plus one.
175 *
176 * @since 1.9.2
177 * @access public
178 *
179 * @return int Widget controls pointer index.
180 */
181 public function get_pointer_index() {
182 $injection_point = $this->get_injection_point();
183
184 if ( null !== $injection_point ) {
185 return $injection_point['index'];
186 }
187
188 return count( $this->get_stack( false )['controls'] );
189 }
190
191 /**
192 * Show in panel.
193 *
194 * Whether to show the widget in the panel or not. By default returns true.
195 *
196 * @since 1.0.0
197 * @access public
198 *
199 * @return bool Whether to show the widget in the panel or not.
200 */
201 public function show_in_panel() {
202 return true;
203 }
204
205 /**
206 * Start widget controls section.
207 *
208 * Used to add a new section of controls to the widget. Regular controls and
209 * skin controls.
210 *
211 * Note that when you add new controls to widgets they must be wrapped by
212 * `start_controls_section()` and `end_controls_section()`.
213 *
214 * @since 1.0.0
215 * @access public
216 *
217 * @param string $section_id Section ID.
218 * @param array $args Section arguments Optional.
219 */
220 public function start_controls_section( $section_id, array $args = [] ) {
221 parent::start_controls_section( $section_id, $args );
222
223 static $is_first_section = true;
224
225 if ( $is_first_section ) {
226 $this->register_skin_control();
227
228 $is_first_section = false;
229 }
230 }
231
232 /**
233 * Register the Skin Control if the widget has skins.
234 *
235 * An internal method that is used to add a skin control to the widget.
236 * Added at the top of the controls section.
237 *
238 * @since 2.0.0
239 * @access private
240 */
241 private function register_skin_control() {
242 $skins = $this->get_skins();
243 if ( ! empty( $skins ) ) {
244 $skin_options = [];
245
246 if ( $this->_has_template_content ) {
247 $skin_options[''] = __( 'Default', 'elementor' );
248 }
249
250 foreach ( $skins as $skin_id => $skin ) {
251 $skin_options[ $skin_id ] = $skin->get_title();
252 }
253
254 // Get the first item for default value
255 $default_value = array_keys( $skin_options );
256 $default_value = array_shift( $default_value );
257
258 if ( 1 >= count( $skin_options ) ) {
259 $this->add_control(
260 '_skin',
261 [
262 'label' => __( 'Skin', 'elementor' ),
263 'type' => Controls_Manager::HIDDEN,
264 'default' => $default_value,
265 ]
266 );
267 } else {
268 $this->add_control(
269 '_skin',
270 [
271 'label' => __( 'Skin', 'elementor' ),
272 'type' => Controls_Manager::SELECT,
273 'default' => $default_value,
274 'options' => $skin_options,
275 ]
276 );
277 }
278 }
279 }
280
281 /**
282 * Register widget skins - deprecated prefixed method
283 *
284 * @since 1.7.12
285 * @access protected
286 * @deprecated 3.1.0
287 */
288 protected function _register_skins() {
289 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0', __CLASS__ . '::register_skins()' );
290
291 $this->register_skins();
292 }
293
294 /**
295 * Register widget skins.
296 *
297 * This method is activated while initializing the widget base class. It is
298 * used to assign skins to widgets with `add_skin()` method.
299 *
300 * Usage:
301 *
302 * protected function register_skins() {
303 * $this->add_skin( new Skin_Classic( $this ) );
304 * }
305 *
306 * @since 3.1.0
307 * @access protected
308 */
309 protected function register_skins() {}
310
311 /**
312 * Get initial config.
313 *
314 * Retrieve the current widget initial configuration.
315 *
316 * Adds more configuration on top of the controls list, the tabs assigned to
317 * the control, element name, type, icon and more. This method also adds
318 * widget type, keywords and categories.
319 *
320 * @since 2.9.0
321 * @access protected
322 *
323 * @return array The initial widget config.
324 */
325 protected function get_initial_config() {
326 $config = [
327 'widget_type' => $this->get_name(),
328 'keywords' => $this->get_keywords(),
329 'categories' => $this->get_categories(),
330 'html_wrapper_class' => $this->get_html_wrapper_class(),
331 'show_in_panel' => $this->show_in_panel(),
332 ];
333
334 $stack = Plugin::$instance->controls_manager->get_element_stack( $this );
335
336 if ( $stack ) {
337 $config['controls'] = $this->get_stack( false )['controls'];
338 $config['tabs_controls'] = $this->get_tabs_controls();
339 }
340
341 return array_merge( parent::get_initial_config(), $config );
342 }
343
344 /**
345 * @since 2.3.1
346 * @access protected
347 */
348 protected function should_print_empty() {
349 return false;
350 }
351
352 /**
353 * Print widget content template.
354 *
355 * Used to generate the widget content template on the editor, using a
356 * Backbone JavaScript template.
357 *
358 * @since 2.0.0
359 * @access protected
360 *
361 * @param string $template_content Template content.
362 */
363 protected function print_template_content( $template_content ) {
364 ?>
365 <div class="elementor-widget-container">
366 <?php
367 echo $template_content; // XSS ok.
368 ?>
369 </div>
370 <?php
371 }
372
373 /**
374 * Parse text editor.
375 *
376 * Parses the content from rich text editor with shortcodes, oEmbed and
377 * filtered data.
378 *
379 * @since 1.0.0
380 * @access protected
381 *
382 * @param string $content Text editor content.
383 *
384 * @return string Parsed content.
385 */
386 protected function parse_text_editor( $content ) {
387 /** This filter is documented in wp-includes/widgets/class-wp-widget-text.php */
388 $content = apply_filters( 'widget_text', $content, $this->get_settings() );
389
390 $content = shortcode_unautop( $content );
391 $content = do_shortcode( $content );
392 $content = wptexturize( $content );
393
394 if ( $GLOBALS['wp_embed'] instanceof \WP_Embed ) {
395 $content = $GLOBALS['wp_embed']->autoembed( $content );
396 }
397
398 return $content;
399 }
400
401 /**
402 * Get HTML wrapper class.
403 *
404 * Retrieve the widget container class. Can be used to override the
405 * container class for specific widgets.
406 *
407 * @since 2.0.9
408 * @access protected
409 */
410 protected function get_html_wrapper_class() {
411 return 'elementor-widget-' . $this->get_name();
412 }
413
414 /**
415 * Add widget render attributes.
416 *
417 * Used to add attributes to the current widget wrapper HTML tag.
418 *
419 * @since 1.0.0
420 * @access protected
421 */
422 protected function add_render_attributes() {
423 parent::add_render_attributes();
424
425 $this->add_render_attribute(
426 '_wrapper', 'class', [
427 'elementor-widget',
428 $this->get_html_wrapper_class(),
429 ]
430 );
431
432 $settings = $this->get_settings();
433
434 $this->add_render_attribute( '_wrapper', 'data-widget_type', $this->get_name() . '.' . ( ! empty( $settings['_skin'] ) ? $settings['_skin'] : 'default' ) );
435 }
436
437 /**
438 * Add lightbox data to image link.
439 *
440 * Used to add lightbox data attributes to image link HTML.
441 *
442 * @since 2.9.1
443 * @access public
444 *
445 * @param string $link_html Image link HTML.
446 * @param string $id Attachment id.
447 *
448 * @return string Image link HTML with lightbox data attributes.
449 */
450 public function add_lightbox_data_to_image_link( $link_html, $id ) {
451 $settings = $this->get_settings_for_display();
452 $open_lightbox = isset( $settings['open_lightbox'] ) ? $settings['open_lightbox'] : null;
453
454 if ( Plugin::$instance->editor->is_edit_mode() ) {
455 $this->add_render_attribute( 'link', 'class', 'elementor-clickable', true );
456 }
457
458 $this->add_lightbox_data_attributes( 'link', $id, $open_lightbox, $this->get_id(), true );
459 return preg_replace( '/^<a/', '<a ' . $this->get_render_attribute_string( 'link' ), $link_html );
460 }
461
462 /**
463 * Add Light-Box attributes.
464 *
465 * Used to add Light-Box-related data attributes to links that open media files.
466 *
467 * @param array|string $element The link HTML element.
468 * @param int $id The ID of the image
469 * @param string $lightbox_setting_key The setting key that dictates weather to open the image in a lightbox
470 * @param string $group_id Unique ID for a group of lightbox images
471 * @param bool $overwrite Optional. Whether to overwrite existing
472 * attribute. Default is false, not to overwrite.
473 *
474 * @return Widget_Base Current instance of the widget.
475 * @since 2.9.0
476 * @access public
477 *
478 */
479 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
480 $kit = Plugin::$instance->kits_manager->get_active_kit();
481
482 $is_global_image_lightbox_enabled = 'yes' === $kit->get_settings( 'global_image_lightbox' );
483
484 if ( 'no' === $lightbox_setting_key ) {
485 if ( $is_global_image_lightbox_enabled ) {
486 $this->add_render_attribute( $element, 'data-elementor-open-lightbox', 'no' );
487 }
488
489 return $this;
490 }
491
492 if ( 'yes' !== $lightbox_setting_key && ! $is_global_image_lightbox_enabled ) {
493 return $this;
494 }
495
496 $attributes['data-elementor-open-lightbox'] = 'yes';
497
498 if ( $group_id ) {
499 $attributes['data-elementor-lightbox-slideshow'] = $group_id;
500 }
501
502 if ( $id ) {
503 $lightbox_image_attributes = Plugin::$instance->images_manager->get_lightbox_image_attributes( $id );
504
505 if ( isset( $lightbox_image_attributes['title'] ) ) {
506 $attributes['data-elementor-lightbox-title'] = $lightbox_image_attributes['title'];
507 }
508
509 if ( isset( $lightbox_image_attributes['description'] ) ) {
510 $attributes['data-elementor-lightbox-description'] = $lightbox_image_attributes['description'];
511 }
512 }
513
514 $this->add_render_attribute( $element, $attributes, null, $overwrite );
515
516 return $this;
517 }
518
519 /**
520 * Render widget output on the frontend.
521 *
522 * Used to generate the final HTML displayed on the frontend.
523 *
524 * Note that if skin is selected, it will be rendered by the skin itself,
525 * not the widget.
526 *
527 * @since 1.0.0
528 * @access public
529 */
530 public function render_content() {
531 /**
532 * Before widget render content.
533 *
534 * Fires before Elementor widget is being rendered.
535 *
536 * @since 1.0.0
537 *
538 * @param Widget_Base $this The current widget.
539 */
540 do_action( 'elementor/widget/before_render_content', $this );
541
542 ob_start();
543
544 $skin = $this->get_current_skin();
545 if ( $skin ) {
546 $skin->set_parent( $this );
547 $skin->render_by_mode();
548 } else {
549 $this->render_by_mode();
550 }
551
552 $widget_content = ob_get_clean();
553
554 if ( empty( $widget_content ) ) {
555 return;
556 }
557 ?>
558 <div class="elementor-widget-container">
559 <?php
560
561 /**
562 * Render widget content.
563 *
564 * Filters the widget content before it's rendered.
565 *
566 * @since 1.0.0
567 *
568 * @param string $widget_content The content of the widget.
569 * @param Widget_Base $this The widget.
570 */
571 $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
572
573 echo $widget_content; // XSS ok.
574 ?>
575 </div>
576 <?php
577 }
578
579 /**
580 * Render widget plain content.
581 *
582 * Elementor saves the page content in a unique way, but it's not the way
583 * WordPress saves data. This method is used to save generated HTML to the
584 * database as plain content the WordPress way.
585 *
586 * When rendering plain content, it allows other WordPress plugins to
587 * interact with the content - to search, check SEO and other purposes. It
588 * also allows the site to keep working even if Elementor is deactivated.
589 *
590 * Note that if the widget uses shortcodes to display the data, the best
591 * practice is to return the shortcode itself.
592 *
593 * Also note that if the widget don't display any content it should return
594 * an empty string. For example Elementor Pro Form Widget uses this method
595 * to return an empty string because there is no content to return. This way
596 * if Elementor Pro will be deactivated there won't be any form to display.
597 *
598 * @since 1.0.0
599 * @access public
600 */
601 public function render_plain_content() {
602 $this->render_content();
603 }
604
605 /**
606 * Before widget rendering.
607 *
608 * Used to add stuff before the widget `_wrapper` element.
609 *
610 * @since 1.0.0
611 * @access public
612 */
613 public function before_render() {
614 ?>
615 <div <?php $this->print_render_attribute_string( '_wrapper' ); ?>>
616 <?php
617 }
618
619 /**
620 * After widget rendering.
621 *
622 * Used to add stuff after the widget `_wrapper` element.
623 *
624 * @since 1.0.0
625 * @access public
626 */
627 public function after_render() {
628 ?>
629 </div>
630 <?php
631 }
632
633 /**
634 * Get the element raw data.
635 *
636 * Retrieve the raw element data, including the id, type, settings, child
637 * elements and whether it is an inner element.
638 *
639 * The data with the HTML used always to display the data, but the Elementor
640 * editor uses the raw data without the HTML in order not to render the data
641 * again.
642 *
643 * @since 1.0.0
644 * @access public
645 *
646 * @param bool $with_html_content Optional. Whether to return the data with
647 * HTML content or without. Used for caching.
648 * Default is false, without HTML.
649 *
650 * @return array Element raw data.
651 */
652 public function get_raw_data( $with_html_content = false ) {
653 $data = parent::get_raw_data( $with_html_content );
654
655 unset( $data['isInner'] );
656
657 $data['widgetType'] = $this->get_data( 'widgetType' );
658
659 if ( $with_html_content ) {
660 ob_start();
661
662 $this->render_content();
663
664 $data['htmlCache'] = ob_get_clean();
665 }
666
667 return $data;
668 }
669
670 /**
671 * Print widget content.
672 *
673 * Output the widget final HTML on the frontend.
674 *
675 * @since 1.0.0
676 * @access protected
677 */
678 protected function print_content() {
679 $this->render_content();
680 }
681
682 /**
683 * Get default data.
684 *
685 * Retrieve the default widget data. Used to reset the data on initialization.
686 *
687 * @since 1.0.0
688 * @access protected
689 *
690 * @return array Default data.
691 */
692 protected function get_default_data() {
693 $data = parent::get_default_data();
694
695 $data['widgetType'] = '';
696
697 return $data;
698 }
699
700 /**
701 * Get default child type.
702 *
703 * Retrieve the widget child type based on element data.
704 *
705 * @since 1.0.0
706 * @access protected
707 *
708 * @param array $element_data Widget ID.
709 *
710 * @return array|false Child type or false if it's not a valid widget.
711 */
712 protected function _get_default_child_type( array $element_data ) {
713 return Plugin::$instance->elements_manager->get_element_types( 'section' );
714 }
715
716 /**
717 * Get repeater setting key.
718 *
719 * Retrieve the unique setting key for the current repeater item. Used to connect the current element in the
720 * repeater to it's settings model and it's control in the panel.
721 *
722 * PHP usage (inside `Widget_Base::render()` method):
723 *
724 * $tabs = $this->get_settings( 'tabs' );
725 * foreach ( $tabs as $index => $item ) {
726 * $tab_title_setting_key = $this->get_repeater_setting_key( 'tab_title', 'tabs', $index );
727 * $this->add_inline_editing_attributes( $tab_title_setting_key, 'none' );
728 * echo '<div ' . $this->get_render_attribute_string( $tab_title_setting_key ) . '>' . $item['tab_title'] . '</div>';
729 * }
730 *
731 * @since 1.8.0
732 * @access protected
733 *
734 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
735 * @param string $repeater_key The repeater key containing the array of all the items in the repeater (e.g. `tabs`).
736 * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
737 *
738 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
739 */
740 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
741 return implode( '.', [ $repeater_key, $repeater_item_index, $setting_key ] );
742 }
743
744 /**
745 * Add inline editing attributes.
746 *
747 * Define specific area in the element to be editable inline. The element can have several areas, with this method
748 * you can set the area inside the element that can be edited inline. You can also define the type of toolbar the
749 * user will see, whether it will be a basic toolbar or an advanced one.
750 *
751 * Note: When you use wysiwyg control use the advanced toolbar, with textarea control use the basic toolbar. Text
752 * control should not have toolbar.
753 *
754 * PHP usage (inside `Widget_Base::render()` method):
755 *
756 * $this->add_inline_editing_attributes( 'text', 'advanced' );
757 * echo '<div ' . $this->get_render_attribute_string( 'text' ) . '>' . $this->get_settings( 'text' ) . '</div>';
758 *
759 * @since 1.8.0
760 * @access protected
761 *
762 * @param string $key Element key.
763 * @param string $toolbar Optional. Toolbar type. Accepted values are `advanced`, `basic` or `none`. Default is
764 * `basic`.
765 */
766 protected function add_inline_editing_attributes( $key, $toolbar = 'basic' ) {
767 if ( ! Plugin::$instance->editor->is_edit_mode() ) {
768 return;
769 }
770
771 $this->add_render_attribute( $key, [
772 'class' => 'elementor-inline-editing',
773 'data-elementor-setting-key' => $key,
774 ] );
775
776 if ( 'basic' !== $toolbar ) {
777 $this->add_render_attribute( $key, [
778 'data-elementor-inline-editing-toolbar' => $toolbar,
779 ] );
780 }
781 }
782
783 /**
784 * Add new skin.
785 *
786 * Register new widget skin to allow the user to set custom designs. Must be
787 * called inside the `register_skins()` method.
788 *
789 * @since 1.0.0
790 * @access public
791 *
792 * @param Skin_Base $skin Skin instance.
793 */
794 public function add_skin( Skin_Base $skin ) {
795 Plugin::$instance->skins_manager->add_skin( $this, $skin );
796 }
797
798 /**
799 * Get single skin.
800 *
801 * Retrieve a single skin based on skin ID, from all the skin assigned to
802 * the widget. If the skin does not exist or not assigned to the widget,
803 * return false.
804 *
805 * @since 1.0.0
806 * @access public
807 *
808 * @param string $skin_id Skin ID.
809 *
810 * @return string|false Single skin, or false.
811 */
812 public function get_skin( $skin_id ) {
813 $skins = $this->get_skins();
814 if ( isset( $skins[ $skin_id ] ) ) {
815 return $skins[ $skin_id ];
816 }
817
818 return false;
819 }
820
821 /**
822 * Get current skin ID.
823 *
824 * Retrieve the ID of the current skin.
825 *
826 * @since 1.0.0
827 * @access public
828 *
829 * @return string Current skin.
830 */
831 public function get_current_skin_id() {
832 return $this->get_settings( '_skin' );
833 }
834
835 /**
836 * Get current skin.
837 *
838 * Retrieve the current skin, or if non exist return false.
839 *
840 * @since 1.0.0
841 * @access public
842 *
843 * @return Skin_Base|false Current skin or false.
844 */
845 public function get_current_skin() {
846 return $this->get_skin( $this->get_current_skin_id() );
847 }
848
849 /**
850 * Remove widget skin.
851 *
852 * Unregister an existing skin and remove it from the widget.
853 *
854 * @since 1.0.0
855 * @access public
856 *
857 * @param string $skin_id Skin ID.
858 *
859 * @return \WP_Error|true Whether the skin was removed successfully from the widget.
860 */
861 public function remove_skin( $skin_id ) {
862 return Plugin::$instance->skins_manager->remove_skin( $this, $skin_id );
863 }
864
865 /**
866 * Get widget skins.
867 *
868 * Retrieve all the skin assigned to the widget.
869 *
870 * @since 1.0.0
871 * @access public
872 *
873 * @return Skin_Base[]
874 */
875 public function get_skins() {
876 return Plugin::$instance->skins_manager->get_skins( $this );
877 }
878
879 /**
880 * @param string $plugin_title Plugin's title
881 * @param string $since Plugin version widget was deprecated
882 * @param string $last Plugin version in which the widget will be removed
883 * @param string $replacement Widget replacement
884 */
885 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
886 $this->start_controls_section( 'Deprecated',
887 [
888 'label' => __( 'Deprecated', 'elementor' ),
889 ]
890 );
891
892 $this->add_control(
893 'deprecated_notice',
894 [
895 'type' => Controls_Manager::DEPRECATED_NOTICE,
896 'widget' => $this->get_title(),
897 'since' => $since,
898 'last' => $last,
899 'plugin' => $plugin_title,
900 'replacement' => $replacement,
901 ]
902 );
903
904 $this->end_controls_section();
905
906 }
907 }
908