PluginProbe
Elementor Website Builder – more than just a page builder / 3.0.6
Elementor Website Builder – more than just a page builder v3.0.6
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
← All changes | includes/base/widget-base.php +49 -280 4.3.0-beta23.0.6 View file →
@@ -1,11 +1,7 @@
1 1 <?php
2 2 namespace Elementor;
3 3
4 -use Elementor\Core\Frontend\Widget_Content_Render_Mode;
5 -use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager;
6 -use Elementor\Utils;
7 -
8 4 if ( ! defined( 'ABSPATH' ) ) {
9 5 exit; // Exit if accessed directly.
10 6 }
11 7
@@ -20,8 +16,9 @@
20 16 * @since 1.0.0
21 17 * @abstract
22 18 */
23 19 abstract class Widget_Base extends Element_Base {
20 +
24 21 /**
25 22 * Whether the widget has content.
26 23 *
27 24 * Used in cases where the widget has no content. When widgets uses only
@@ -34,24 +31,9 @@
34 31 * @var bool
35 32 */
36 33 protected $_has_template_content = true;
37 34
38 - private $is_first_section = true;
39 -
40 35 /**
41 - * Registered Runtime Widgets.
42 - *
43 - * Registering in runtime all widgets that are being used on the page.
44 - *
45 - * @since 3.3.0
46 - * @access public
47 - * @static
48 - *
49 - * @var array
50 - */
51 - public static $registered_runtime_widgets = [];
52 -
53 - /**
54 36 * Get element type.
55 37 *
56 38 * Retrieve the element type, in this case `widget`.
57 39 *
@@ -107,22 +89,8 @@
107 89 return [ 'general' ];
108 90 }
109 91
110 92 /**
111 - * Get widget upsale data.
112 - *
113 - * Retrieve the widget promotion data.
114 - *
115 - * @since 3.18.0
116 - * @access protected
117 - *
118 - * @return array|null Widget promotion data.
119 - */
120 - protected function get_upsale_data() {
121 - return null;
122 - }
123 -
124 - /**
125 93 * Widget base constructor.
126 94 *
127 95 * Initializing the widget base class.
128 96 *
@@ -140,20 +108,14 @@
140 108
141 109 $is_type_instance = $this->is_type_instance();
142 110
143 111 if ( ! $is_type_instance && null === $args ) {
144 - throw new \Exception( 'An `$args` argument is required when initializing a full widget instance.' );
112 + throw new \Exception( '`$args` argument is required when initializing a full widget instance.' );
145 113 }
146 114
147 115 if ( $is_type_instance ) {
148 - if ( $this->has_own_method( '_register_skins', self::class ) ) {
149 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( '_register_skins', '3.1.0', __CLASS__ . '::register_skins()' );
116 + $this->_register_skins();
150 117
151 - $this->_register_skins();
152 - } else {
153 - $this->register_skins();
154 - }
155 -
156 118 $widget_name = $this->get_name();
157 119
158 120 /**
159 121 * Widget skin init.
@@ -184,11 +146,11 @@
184 146 */
185 147 public function get_stack( $with_common_controls = true ) {
186 148 $stack = parent::get_stack();
187 149
188 - if ( $with_common_controls && ! $this instanceof Widget_Common_Base ) {
189 - /** @var Widget_Common_Base $common_widget */
190 - $common_widget = Plugin::$instance->widgets_manager->get_widget_types( $this->get_common_widget_name() );
150 + if ( $with_common_controls && 'common' !== $this->get_unique_name() ) {
151 + /** @var Widget_Common $common_widget */
152 + $common_widget = Plugin::$instance->widgets_manager->get_widget_types( 'common' );
191 153
192 154 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
193 155
194 156 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
@@ -196,16 +158,8 @@
196 158
197 159 return $stack;
198 160 }
199 161
200 - private function get_common_widget_name() {
201 - if ( Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ) ) {
202 - return $this->has_widget_inner_wrapper() ? 'common' : 'common-optimized';
203 - }
204 -
205 - return 'common';
206 - }
207 -
208 162 /**
209 163 * Get widget controls pointer index.
210 164 *
211 165 * Retrieve widget pointer index where the next control should be added.
@@ -242,21 +196,8 @@
242 196 return true;
243 197 }
244 198
245 199 /**
246 - * Hide on search.
247 - *
248 - * Whether to hide the widget on search in the panel or not. By default returns false.
249 - *
250 - * @access public
251 - *
252 - * @return bool Whether to hide the widget when searching for widget or not.
253 - */
254 - public function hide_on_search() {
255 - return false;
256 - }
257 -
258 - /**
259 200 * Start widget controls section.
260 201 *
261 202 * Used to add a new section of controls to the widget. Regular controls and
262 203 * skin controls.
@@ -272,12 +213,14 @@
272 213 */
273 214 public function start_controls_section( $section_id, array $args = [] ) {
274 215 parent::start_controls_section( $section_id, $args );
275 216
276 - if ( $this->is_first_section ) {
217 + static $is_first_section = true;
218 +
219 + if ( $is_first_section ) {
277 220 $this->register_skin_control();
278 221
279 - $this->is_first_section = false;
222 + $is_first_section = false;
280 223 }
281 224 }
282 225
283 226 /**
@@ -294,9 +237,9 @@
294 237 if ( ! empty( $skins ) ) {
295 238 $skin_options = [];
296 239
297 240 if ( $this->_has_template_content ) {
298 - $skin_options[''] = esc_html__( 'Default', 'elementor' );
241 + $skin_options[''] = __( 'Default', 'elementor' );
299 242 }
300 243
301 244 foreach ( $skins as $skin_id => $skin ) {
302 245 $skin_options[ $skin_id ] = $skin->get_title();
@@ -301,9 +244,9 @@
301 244 foreach ( $skins as $skin_id => $skin ) {
302 245 $skin_options[ $skin_id ] = $skin->get_title();
303 246 }
304 247
305 - // Get the first item for default value.
248 + // Get the first item for default value
306 249 $default_value = array_keys( $skin_options );
307 250 $default_value = array_shift( $default_value );
308 251
309 252 if ( 1 >= count( $skin_options ) ) {
@@ -309,9 +252,9 @@
309 252 if ( 1 >= count( $skin_options ) ) {
310 253 $this->add_control(
311 254 '_skin',
312 255 [
313 - 'label' => esc_html__( 'Skin', 'elementor' ),
256 + 'label' => __( 'Skin', 'elementor' ),
314 257 'type' => Controls_Manager::HIDDEN,
315 258 'default' => $default_value,
316 259 ]
317 260 );
@@ -318,9 +261,9 @@
318 261 } else {
319 262 $this->add_control(
320 263 '_skin',
321 264 [
322 - 'label' => esc_html__( 'Skin', 'elementor' ),
265 + 'label' => __( 'Skin', 'elementor' ),
323 266 'type' => Controls_Manager::SELECT,
324 267 'default' => $default_value,
325 268 'options' => $skin_options,
326 269 ]
@@ -329,21 +272,8 @@
329 272 }
330 273 }
331 274
332 275 /**
333 - * Register widget skins - deprecated prefixed method
334 - *
335 - * @since 1.7.12
336 - * @access protected
337 - * @deprecated 3.1.0 Use `register_skins()` method instead.
338 - */
339 - protected function _register_skins() {
340 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0', 'register_skins()' );
341 -
342 - $this->register_skins();
343 - }
344 -
345 - /**
346 276 * Register widget skins.
347 277 *
348 278 * This method is activated while initializing the widget base class. It is
349 279 * used to assign skins to widgets with `add_skin()` method.
@@ -349,16 +279,16 @@
349 279 * used to assign skins to widgets with `add_skin()` method.
350 280 *
351 281 * Usage:
352 282 *
353 - * protected function register_skins() {
283 + * protected function _register_skins() {
354 284 * $this->add_skin( new Skin_Classic( $this ) );
355 285 * }
356 286 *
357 - * @since 3.1.0
287 + * @since 1.7.12
358 288 * @access protected
359 289 */
360 - protected function register_skins() {}
290 + protected function _register_skins() {}
361 291
362 292 /**
363 293 * Get initial config.
364 294 *
@@ -379,23 +309,10 @@
379 309 'keywords' => $this->get_keywords(),
380 310 'categories' => $this->get_categories(),
381 311 'html_wrapper_class' => $this->get_html_wrapper_class(),
382 312 'show_in_panel' => $this->show_in_panel(),
383 - 'hide_on_search' => $this->hide_on_search(),
384 - 'upsale_data' => null,
385 - 'is_dynamic_content' => $this->is_dynamic_content(),
386 - 'has_widget_inner_wrapper' => $this->has_widget_inner_wrapper(),
387 313 ];
388 314
389 - if ( isset( $config['upsale_data'] ) && is_array( $config['upsale_data'] ) ) {
390 - $filter_name = 'elementor/widgets/' . $this->get_name() . '/custom_promotion';
391 - $config['upsale_data'] = Filtered_Promotions_Manager::get_filtered_promotion_data( $config['upsale_data'], $filter_name, 'upgrade_url' );
392 - }
393 -
394 - if ( isset( $config['upsale_data']['image'] ) ) {
395 - $config['upsale_data']['image'] = esc_url( $config['upsale_data']['image'] );
396 - }
397 -
398 315 $stack = Plugin::$instance->controls_manager->get_element_stack( $this );
399 316
400 317 if ( $stack ) {
401 318 $config['controls'] = $this->get_stack( false )['controls'];
@@ -401,9 +318,9 @@
401 318 $config['controls'] = $this->get_stack( false )['controls'];
402 319 $config['tabs_controls'] = $this->get_tabs_controls();
403 320 }
404 321
405 - return array_replace_recursive( parent::get_initial_config(), $config );
322 + return array_merge( parent::get_initial_config(), $config );
406 323 }
407 324
408 325 /**
409 326 * @since 2.3.1
@@ -424,15 +341,15 @@
424 341 *
425 342 * @param string $template_content Template content.
426 343 */
427 344 protected function print_template_content( $template_content ) {
428 - if ( $this->has_widget_inner_wrapper() ) : ?>
345 + ?>
429 346 <div class="elementor-widget-container">
430 - <?php endif;
431 - Utils::print_unescaped_internal_string( $template_content );
432 - if ( $this->has_widget_inner_wrapper() ) : ?>
347 + <?php
348 + echo $template_content; // XSS ok.
349 + ?>
433 350 </div>
434 - <?php endif;
351 + <?php
435 352 }
436 353
437 354 /**
438 355 * Parse text editor.
@@ -462,22 +379,8 @@
462 379 return $content;
463 380 }
464 381
465 382 /**
466 - * Safe print parsed text editor.
467 - *
468 - * @uses static::parse_text_editor.
469 - *
470 - * @access protected
471 - *
472 - * @param string $content Text editor content.
473 - */
474 - final protected function print_text_editor( $content ) {
475 - // PHPCS - the method `parse_text_editor` is safe.
476 - echo static::parse_text_editor( $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
477 - }
478 -
479 - /**
480 383 * Get HTML wrapper class.
481 384 *
482 385 * Retrieve the widget container class. Can be used to override the
483 386 * container class for specific widgets.
@@ -496,10 +399,10 @@
496 399 *
497 400 * @since 1.0.0
498 401 * @access protected
499 402 */
500 - protected function add_render_attributes() {
501 - parent::add_render_attributes();
403 + protected function _add_render_attributes() {
404 + parent::_add_render_attributes();
502 405
503 406 $this->add_render_attribute(
504 407 '_wrapper', 'class', [
505 408 'elementor-widget',
@@ -542,17 +445,18 @@
542 445 *
543 446 * Used to add Light-Box-related data attributes to links that open media files.
544 447 *
545 448 * @param array|string $element The link HTML element.
546 - * @param int $id The ID of the image.
547 - * @param string $lightbox_setting_key The setting key that dictates whether to open the image in a lightbox.
548 - * @param string $group_id Unique ID for a group of lightbox images.
549 - * @param bool $overwrite Optional. Whether to overwrite existing
550 - * attribute. Default is false, not to overwrite.
449 + * @param int $id The ID of the image
450 + * @param string $lightbox_setting_key The setting key that dictates weather to open the image in a lightbox
451 + * @param string $group_id Unique ID for a group of lightbox images
452 + * @param bool $overwrite Optional. Whether to overwrite existing
453 + * attribute. Default is false, not to overwrite.
551 454 *
552 455 * @return Widget_Base Current instance of the widget.
553 456 * @since 2.9.0
554 457 * @access public
458 + *
555 459 */
556 460 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
557 461 $kit = Plugin::$instance->kits_manager->get_active_kit();
558 462
@@ -559,9 +463,9 @@
559 463 $is_global_image_lightbox_enabled = 'yes' === $kit->get_settings( 'global_image_lightbox' );
560 464
561 465 if ( 'no' === $lightbox_setting_key ) {
562 466 if ( $is_global_image_lightbox_enabled ) {
563 - $this->add_render_attribute( $element, 'data-elementor-open-lightbox', 'no', $overwrite );
467 + $this->add_render_attribute( $element, 'data-elementor-open-lightbox', 'no' );
564 468 }
565 469
566 470 return $this;
567 471 }
@@ -571,19 +475,10 @@
571 475 }
572 476
573 477 $attributes['data-elementor-open-lightbox'] = 'yes';
574 478
575 - $action_hash_params = [];
576 -
577 - if ( $id ) {
578 - $action_hash_params['id'] = $id;
579 - $action_hash_params['url'] = wp_get_attachment_url( $id );
580 - }
581 -
582 479 if ( $group_id ) {
583 480 $attributes['data-elementor-lightbox-slideshow'] = $group_id;
584 -
585 - $action_hash_params['slideshow'] = $group_id;
586 481 }
587 482
588 483 if ( $id ) {
589 484 $lightbox_image_attributes = Plugin::$instance->images_manager->get_lightbox_image_attributes( $id );
@@ -596,10 +491,8 @@
596 491 $attributes['data-elementor-lightbox-description'] = $lightbox_image_attributes['description'];
597 492 }
598 493 }
599 494
600 - $attributes['data-e-action-hash'] = Plugin::instance()->frontend->create_action_hash( 'lightbox', $action_hash_params );
601 -
602 495 $this->add_render_attribute( $element, $attributes, null, $overwrite );
603 496
604 497 return $this;
605 498 }
@@ -624,9 +517,9 @@
624 517 * @since 1.0.0
625 518 *
626 519 * @param Widget_Base $this The current widget.
627 520 */
628 - do_action( 'elementor/widget/before_render_content', $this, [ 'mode' => Widget_Content_Render_Mode::NORMAL ] );
521 + do_action( 'elementor/widget/before_render_content', $this );
629 522
630 523 ob_start();
631 524
632 525 $skin = $this->get_current_skin();
@@ -631,11 +524,11 @@
631 524
632 525 $skin = $this->get_current_skin();
633 526 if ( $skin ) {
634 527 $skin->set_parent( $this );
635 - $skin->render_by_mode();
528 + $skin->render();
636 529 } else {
637 - $this->render_by_mode();
530 + $this->render();
638 531 }
639 532
640 533 $widget_content = ob_get_clean();
641 534
@@ -641,15 +534,11 @@
641 534
642 535 if ( empty( $widget_content ) ) {
643 536 return;
644 537 }
645 - if ( $this->has_widget_inner_wrapper() ) : ?>
538 + ?>
646 539 <div class="elementor-widget-container">
647 - <?php endif; ?>
648 540 <?php
649 - if ( $this->is_widget_first_render( $this->get_group_name() ) ) {
650 - $this->register_runtime_widget( $this->get_group_name() );
651 - }
652 541
653 542 /**
654 543 * Render widget content.
655 544 *
@@ -659,20 +548,16 @@
659 548 *
660 549 * @param string $widget_content The content of the widget.
661 550 * @param Widget_Base $this The widget.
662 551 */
663 - $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this, [ 'mode' => Widget_Content_Render_Mode::NORMAL ] );
664 - Utils::print_unescaped_internal_string( $widget_content );
552 + $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
553 +
554 + echo $widget_content; // XSS ok.
665 555 ?>
666 - <?php if ( $this->has_widget_inner_wrapper() ) : ?>
667 556 </div>
668 - <?php endif;
557 + <?php
669 558 }
670 559
671 - protected function is_widget_first_render( $widget_name ) {
672 - return ! in_array( $widget_name, self::$registered_runtime_widgets, true );
673 - }
674 -
675 560 /**
676 561 * Render widget plain content.
677 562 *
678 563 * Elementor saves the page content in a unique way, but it's not the way
@@ -697,43 +582,8 @@
697 582 public function render_plain_content() {
698 583 $this->render_content();
699 584 }
700 585
701 - public function render_markdown(): string {
702 - $content = $this->get_render_content_for_markdown();
703 -
704 - if ( '' === $content ) {
705 - return '';
706 - }
707 -
708 - return \Elementor\Modules\MarkdownRender\Html_To_Markdown::convert( $content );
709 - }
710 -
711 - protected function get_render_content_for_markdown(): string {
712 - $render_args = [ 'mode' => Widget_Content_Render_Mode::MARKDOWN ];
713 -
714 - do_action( 'elementor/widget/before_render_content', $this, $render_args );
715 -
716 - ob_start();
717 -
718 - $skin = $this->get_current_skin();
719 -
720 - if ( $skin ) {
721 - $skin->set_parent( $this );
722 - $skin->render_by_mode();
723 - } else {
724 - $this->render_by_mode();
725 - }
726 -
727 - $widget_content = ob_get_clean();
728 -
729 - if ( '' === $widget_content ) {
730 - return '';
731 - }
732 -
733 - return apply_filters( 'elementor/widget/render_content', $widget_content, $this, $render_args );
734 - }
735 -
736 586 /**
737 587 * Before widget rendering.
738 588 *
739 589 * Used to add stuff before the widget `_wrapper` element.
@@ -805,33 +655,13 @@
805 655 *
806 656 * @since 1.0.0
807 657 * @access protected
808 658 */
809 - protected function print_content() {
659 + protected function _print_content() {
810 660 $this->render_content();
811 661 }
812 662
813 663 /**
814 - * Print a setting content without escaping.
815 - *
816 - * Script tags are allowed on frontend according to the WP theme securing policy.
817 - *
818 - * @param string $setting
819 - * @param null $repeater_name
820 - * @param null $index
821 - */
822 - final public function print_unescaped_setting( $setting, $repeater_name = null, $index = null ) {
823 - if ( $repeater_name ) {
824 - $repeater = $this->get_settings_for_display( $repeater_name );
825 - $output = $repeater[ $index ][ $setting ];
826 - } else {
827 - $output = $this->get_settings_for_display( $setting );
828 - }
829 -
830 - echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
831 - }
832 -
833 - /**
834 664 * Get default data.
835 665 *
836 666 * Retrieve the default widget data. Used to reset the data on initialization.
837 667 *
@@ -883,9 +713,9 @@
883 713 * @access protected
884 714 *
885 715 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
886 716 * @param string $repeater_key The repeater key containing the array of all the items in the repeater (e.g. `tabs`).
887 - * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
717 + * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
888 718 *
889 719 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
890 720 */
891 721 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
@@ -934,9 +764,9 @@
934 764 /**
935 765 * Add new skin.
936 766 *
937 767 * Register new widget skin to allow the user to set custom designs. Must be
938 - * called inside the `register_skins()` method.
768 + * called inside the `_register_skins()` method.
939 769 *
940 770 * @since 1.0.0
941 771 * @access public
942 772 *
@@ -1027,33 +857,17 @@
1027 857 return Plugin::$instance->skins_manager->get_skins( $this );
1028 858 }
1029 859
1030 860 /**
1031 - * Get group name.
1032 - *
1033 - * Some widgets need to use group names, this method allows you to create them.
1034 - * By default it retrieves the regular name.
1035 - *
1036 - * @since 3.3.0
1037 - * @access public
1038 - *
1039 - * @return string Unique name.
861 + * @param string $plugin_title Plugin's title
862 + * @param string $since Plugin version widget was deprecated
863 + * @param string $last Plugin version in which the widget will be removed
864 + * @param string $replacement Widget replacement
1040 865 */
1041 - public function get_group_name() {
1042 - return $this->get_name();
1043 - }
1044 -
1045 - /**
1046 - * @param string $plugin_title Plugin's title.
1047 - * @param string $since Plugin version widget was deprecated.
1048 - * @param string $last Plugin version in which the widget will be removed.
1049 - * @param string $replacement Widget replacement.
1050 - */
1051 866 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
1052 - $this->start_controls_section(
1053 - 'Deprecated',
867 + $this->start_controls_section( 'Deprecated',
1054 868 [
1055 - 'label' => esc_html__( 'Deprecated', 'elementor' ),
869 + 'label' => __( 'Deprecated', 'elementor' ),
1056 870 ]
1057 871 );
1058 872
1059 873 $this->add_control(
@@ -1068,52 +882,7 @@
1068 882 ]
1069 883 );
1070 884
1071 885 $this->end_controls_section();
1072 - }
1073 886
1074 - /**
1075 - * Init controls.
1076 - *
1077 - * Reset the `is_first_section` flag to true, so when the Stacks are cleared
1078 - * all the controls will be registered again with their skins and settings.
1079 - *
1080 - * @since 3.14.0
1081 - * @access protected
1082 - */
1083 - protected function init_controls() {
1084 - $this->is_first_section = true;
1085 - parent::init_controls();
1086 - }
1087 -
1088 - public function register_runtime_widget( $widget_name ) {
1089 - self::$registered_runtime_widgets[] = $widget_name;
1090 - }
1091 -
1092 - /**
1093 - * Mark widget as deprecated.
1094 - *
1095 - * Use `get_deprecation_message()` method to print the message control at specific location in register_controls().
1096 - *
1097 - * @param string $version The version of Elementor that deprecated the widget.
1098 - * @param string $message A message regarding the deprecation.
1099 - * @param string $replacement The widget that should be used instead.
1100 - */
1101 - protected function add_deprecation_message( $version, $message, $replacement ) {
1102 - // Expose the config for handling in JS.
1103 - $this->set_config( 'deprecation', [
1104 - 'version' => $version,
1105 - 'message' => $message,
1106 - 'replacement' => $replacement,
1107 - ] );
1108 -
1109 - $this->add_control(
1110 - 'deprecation_message',
1111 - [
1112 - 'type' => Controls_Manager::ALERT,
1113 - 'alert_type' => 'info',
1114 - 'content' => $message,
1115 - 'separator' => 'after',
1116 - ]
1117 - );
1118 887 }
1119 888 }