PluginProbe
Elementor Website Builder – more than just a page builder / 3.6.6
Elementor Website Builder – more than just a page builder v3.6.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 +202 -105 4.1.53.6.6 View file →
@@ -1,9 +1,9 @@
1 1 <?php
2 2 namespace Elementor;
3 3
4 -use Elementor\Core\Utils\Promotions\Filtered_Promotions_Manager;
5 -use Elementor\Utils;
4 +use Elementor\Core\Page_Assets\Data_Managers\Responsive_Widgets as Responsive_Widgets_Data_Manager;
5 +use Elementor\Core\Page_Assets\Data_Managers\Widgets_Css as Widgets_Css_Data_Manager;
6 6
7 7 if ( ! defined( 'ABSPATH' ) ) {
8 8 exit; // Exit if accessed directly.
9 9 }
@@ -48,8 +48,14 @@
48 48 * @var array
49 49 */
50 50 public static $registered_runtime_widgets = [];
51 51
52 + public static $registered_inline_css_widgets = [];
53 +
54 + private static $widgets_css_data_manager;
55 +
56 + private static $responsive_widgets_data_manager;
57 +
52 58 /**
53 59 * Get element type.
54 60 *
55 61 * Retrieve the element type, in this case `widget`.
@@ -106,22 +112,8 @@
106 112 return [ 'general' ];
107 113 }
108 114
109 115 /**
110 - * Get widget upsale data.
111 - *
112 - * Retrieve the widget promotion data.
113 - *
114 - * @since 3.18.0
115 - * @access protected
116 - *
117 - * @return array|null Widget promotion data.
118 - */
119 - protected function get_upsale_data() {
120 - return null;
121 - }
122 -
123 - /**
124 116 * Widget base constructor.
125 117 *
126 118 * Initializing the widget base class.
127 119 *
@@ -139,9 +131,9 @@
139 131
140 132 $is_type_instance = $this->is_type_instance();
141 133
142 134 if ( ! $is_type_instance && null === $args ) {
143 - throw new \Exception( 'An `$args` argument is required when initializing a full widget instance.' );
135 + throw new \Exception( '`$args` argument is required when initializing a full widget instance.' );
144 136 }
145 137
146 138 if ( $is_type_instance ) {
147 139 if ( $this->has_own_method( '_register_skins', self::class ) ) {
@@ -183,11 +175,11 @@
183 175 */
184 176 public function get_stack( $with_common_controls = true ) {
185 177 $stack = parent::get_stack();
186 178
187 - if ( $with_common_controls && ! $this instanceof Widget_Common_Base ) {
188 - /** @var Widget_Common_Base $common_widget */
189 - $common_widget = Plugin::$instance->widgets_manager->get_widget_types( $this->get_common_widget_name() );
179 + if ( $with_common_controls && 'common' !== $this->get_unique_name() ) {
180 + /** @var Widget_Common $common_widget */
181 + $common_widget = Plugin::$instance->widgets_manager->get_widget_types( 'common' );
190 182
191 183 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
192 184
193 185 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
@@ -195,16 +187,8 @@
195 187
196 188 return $stack;
197 189 }
198 190
199 - private function get_common_widget_name() {
200 - if ( Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' ) ) {
201 - return $this->has_widget_inner_wrapper() ? 'common' : 'common-optimized';
202 - }
203 -
204 - return 'common';
205 - }
206 -
207 191 /**
208 192 * Get widget controls pointer index.
209 193 *
210 194 * Retrieve widget pointer index where the next control should be added.
@@ -300,9 +284,9 @@
300 284 foreach ( $skins as $skin_id => $skin ) {
301 285 $skin_options[ $skin_id ] = $skin->get_title();
302 286 }
303 287
304 - // Get the first item for default value.
288 + // Get the first item for default value
305 289 $default_value = array_keys( $skin_options );
306 290 $default_value = array_shift( $default_value );
307 291
308 292 if ( 1 >= count( $skin_options ) ) {
@@ -332,12 +316,12 @@
332 316 * Register widget skins - deprecated prefixed method
333 317 *
334 318 * @since 1.7.12
335 319 * @access protected
336 - * @deprecated 3.1.0 Use `register_skins()` method instead.
320 + * @deprecated 3.1.0
337 321 */
338 322 protected function _register_skins() {
339 - Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0', 'register_skins()' );
323 + Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0', __CLASS__ . '::register_skins()' );
340 324
341 325 $this->register_skins();
342 326 }
343 327
@@ -379,22 +363,10 @@
379 363 'categories' => $this->get_categories(),
380 364 'html_wrapper_class' => $this->get_html_wrapper_class(),
381 365 'show_in_panel' => $this->show_in_panel(),
382 366 'hide_on_search' => $this->hide_on_search(),
383 - 'upsale_data' => Plugin::$instance->experiments->is_feature_active( 'e_panel_promotions' ) ? null : $this->get_upsale_data(),
384 - 'is_dynamic_content' => $this->is_dynamic_content(),
385 - 'has_widget_inner_wrapper' => $this->has_widget_inner_wrapper(),
386 367 ];
387 368
388 - if ( isset( $config['upsale_data'] ) && is_array( $config['upsale_data'] ) ) {
389 - $filter_name = 'elementor/widgets/' . $this->get_name() . '/custom_promotion';
390 - $config['upsale_data'] = Filtered_Promotions_Manager::get_filtered_promotion_data( $config['upsale_data'], $filter_name, 'upgrade_url' );
391 - }
392 -
393 - if ( isset( $config['upsale_data']['image'] ) ) {
394 - $config['upsale_data']['image'] = esc_url( $config['upsale_data']['image'] );
395 - }
396 -
397 369 $stack = Plugin::$instance->controls_manager->get_element_stack( $this );
398 370
399 371 if ( $stack ) {
400 372 $config['controls'] = $this->get_stack( false )['controls'];
@@ -423,15 +395,15 @@
423 395 *
424 396 * @param string $template_content Template content.
425 397 */
426 398 protected function print_template_content( $template_content ) {
427 - if ( $this->has_widget_inner_wrapper() ) : ?>
399 + ?>
428 400 <div class="elementor-widget-container">
429 - <?php endif;
430 - Utils::print_unescaped_internal_string( $template_content );
431 - if ( $this->has_widget_inner_wrapper() ) : ?>
401 + <?php
402 + echo $template_content; // XSS ok.
403 + ?>
432 404 </div>
433 - <?php endif;
405 + <?php
434 406 }
435 407
436 408 /**
437 409 * Parse text editor.
@@ -541,17 +513,18 @@
541 513 *
542 514 * Used to add Light-Box-related data attributes to links that open media files.
543 515 *
544 516 * @param array|string $element The link HTML element.
545 - * @param int $id The ID of the image.
546 - * @param string $lightbox_setting_key The setting key that dictates whether to open the image in a lightbox.
547 - * @param string $group_id Unique ID for a group of lightbox images.
548 - * @param bool $overwrite Optional. Whether to overwrite existing
549 - * attribute. Default is false, not to overwrite.
517 + * @param int $id The ID of the image
518 + * @param string $lightbox_setting_key The setting key that dictates weather to open the image in a lightbox
519 + * @param string $group_id Unique ID for a group of lightbox images
520 + * @param bool $overwrite Optional. Whether to overwrite existing
521 + * attribute. Default is false, not to overwrite.
550 522 *
551 523 * @return Widget_Base Current instance of the widget.
552 524 * @since 2.9.0
553 525 * @access public
526 + *
554 527 */
555 528 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
556 529 $kit = Plugin::$instance->kits_manager->get_active_kit();
557 530
@@ -595,9 +568,9 @@
595 568 $attributes['data-elementor-lightbox-description'] = $lightbox_image_attributes['description'];
596 569 }
597 570 }
598 571
599 - $attributes['data-e-action-hash'] = Plugin::instance()->frontend->create_action_hash( 'lightbox', $action_hash_params );
572 + $attributes['e-action-hash'] = Plugin::instance()->frontend->create_action_hash( 'lightbox', $action_hash_params );
600 573
601 574 $this->add_render_attribute( $element, $attributes, null, $overwrite );
602 575
603 576 return $this;
@@ -640,16 +613,19 @@
640 613
641 614 if ( empty( $widget_content ) ) {
642 615 return;
643 616 }
644 - if ( $this->has_widget_inner_wrapper() ) : ?>
617 + ?>
645 618 <div class="elementor-widget-container">
646 - <?php endif; ?>
647 619 <?php
648 620 if ( $this->is_widget_first_render( $this->get_group_name() ) ) {
649 621 $this->register_runtime_widget( $this->get_group_name() );
650 622 }
651 623
624 + $this->print_widget_css();
625 +
626 + // get_name
627 +
652 628 /**
653 629 * Render widget content.
654 630 *
655 631 * Filters the widget content before it's rendered.
@@ -659,13 +635,13 @@
659 635 * @param string $widget_content The content of the widget.
660 636 * @param Widget_Base $this The widget.
661 637 */
662 638 $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
663 - Utils::print_unescaped_internal_string( $widget_content );
639 +
640 + echo $widget_content; // XSS ok.
664 641 ?>
665 - <?php if ( $this->has_widget_inner_wrapper() ) : ?>
666 642 </div>
667 - <?php endif;
643 + <?php
668 644 }
669 645
670 646 protected function is_widget_first_render( $widget_name ) {
671 647 return ! in_array( $widget_name, self::$registered_runtime_widgets, true );
@@ -696,16 +672,8 @@
696 672 public function render_plain_content() {
697 673 $this->render_content();
698 674 }
699 675
700 - public function render_markdown(): string {
701 - ob_start();
702 - $this->render_content();
703 - $html = ob_get_clean();
704 -
705 - return wp_strip_all_tags( $html );
706 - }
707 -
708 676 /**
709 677 * Before widget rendering.
710 678 *
711 679 * Used to add stuff before the widget `_wrapper` element.
@@ -787,10 +755,10 @@
787 755 *
788 756 * Script tags are allowed on frontend according to the WP theme securing policy.
789 757 *
790 758 * @param string $setting
791 - * @param null $repeater_name
792 - * @param null $index
759 + * @param null $repeater_name
760 + * @param null $index
793 761 */
794 762 final public function print_unescaped_setting( $setting, $repeater_name = null, $index = null ) {
795 763 if ( $repeater_name ) {
796 764 $repeater = $this->get_settings_for_display( $repeater_name );
@@ -855,9 +823,9 @@
855 823 * @access protected
856 824 *
857 825 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
858 826 * @param string $repeater_key The repeater key containing the array of all the items in the repeater (e.g. `tabs`).
859 - * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
827 + * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
860 828 *
861 829 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
862 830 */
863 831 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
@@ -1014,13 +982,27 @@
1014 982 return $this->get_name();
1015 983 }
1016 984
1017 985 /**
1018 - * @param string $plugin_title Plugin's title.
1019 - * @param string $since Plugin version widget was deprecated.
1020 - * @param string $last Plugin version in which the widget will be removed.
1021 - * @param string $replacement Widget replacement.
986 + * Get Inline CSS dependencies.
987 + *
988 + * Retrieve a list of inline CSS dependencies that the element requires.
989 + *
990 + * @since 3.3.0
991 + * @access public
992 + *
993 + * @return array.
1022 994 */
995 + public function get_inline_css_depends() {
996 + return [];
997 + }
998 +
999 + /**
1000 + * @param string $plugin_title Plugin's title
1001 + * @param string $since Plugin version widget was deprecated
1002 + * @param string $last Plugin version in which the widget will be removed
1003 + * @param string $replacement Widget replacement
1004 + */
1023 1005 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
1024 1006 $this->start_controls_section(
1025 1007 'Deprecated',
1026 1008 [
@@ -1040,52 +1022,167 @@
1040 1022 ]
1041 1023 );
1042 1024
1043 1025 $this->end_controls_section();
1026 +
1044 1027 }
1045 1028
1029 + public function register_runtime_widget( $widget_name ) {
1030 + self::$registered_runtime_widgets[] = $widget_name;
1031 + }
1032 +
1033 + public function get_widget_css_config( $widget_name ) {
1034 + $direction = is_rtl() ? '-rtl' : '';
1035 +
1036 + $has_custom_breakpoints = $this->is_custom_breakpoints_widget();
1037 +
1038 + $file_name = 'widget-' . $widget_name . $direction . '.min.css';
1039 +
1040 + // The URL of the widget's external CSS file that is loaded in case that the CSS content is too large to be printed inline.
1041 + $file_url = Plugin::$instance->frontend->get_frontend_file_url( $file_name, $has_custom_breakpoints );
1042 +
1043 + // The local path of the widget's CSS file that is being read and saved in the DB when the CSS content should be printed inline.
1044 + $file_path = Plugin::$instance->frontend->get_frontend_file_path( $file_name, $has_custom_breakpoints );
1045 +
1046 + return [
1047 + 'key' => $widget_name,
1048 + 'version' => ELEMENTOR_VERSION,
1049 + 'file_path' => $file_path,
1050 + 'data' => [
1051 + 'file_url' => $file_url,
1052 + ],
1053 + ];
1054 + }
1055 +
1056 + public function get_css_config() {
1057 + return $this->get_widget_css_config( $this->get_group_name() );
1058 + }
1059 +
1060 + public function get_responsive_widgets_config() {
1061 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1062 +
1063 + return [
1064 + 'key' => $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_DATABASE_KEY,
1065 + 'version' => ELEMENTOR_VERSION,
1066 + 'file_path' => ELEMENTOR_ASSETS_PATH . $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_FILE_PATH,
1067 + ];
1068 + }
1069 +
1070 + public function get_responsive_widgets() {
1071 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1072 +
1073 + $config = $this->get_responsive_widgets_config();
1074 +
1075 + return $responsive_widgets_data_manager->get_asset_data_from_config( $config );
1076 + }
1077 +
1046 1078 /**
1047 - * Init controls.
1079 + * Get Responsive Widgets Data Manager.
1048 1080 *
1049 - * Reset the `is_first_section` flag to true, so when the Stacks are cleared
1050 - * all the controls will be registered again with their skins and settings.
1081 + * Retrieve the data manager that handles widgets that are using media queries for custom-breakpoints values.
1051 1082 *
1052 - * @since 3.14.0
1083 + * @since 3.5.0
1053 1084 * @access protected
1085 + *
1086 + * @return Responsive_Widgets_Data_Manager
1054 1087 */
1055 - protected function init_controls() {
1056 - $this->is_first_section = true;
1057 - parent::init_controls();
1058 - }
1088 + protected function get_responsive_widgets_data_manager() {
1089 + if ( ! self::$responsive_widgets_data_manager ) {
1090 + self::$responsive_widgets_data_manager = new Responsive_Widgets_Data_Manager();
1091 + }
1059 1092
1060 - public function register_runtime_widget( $widget_name ) {
1061 - self::$registered_runtime_widgets[] = $widget_name;
1093 + return self::$responsive_widgets_data_manager;
1062 1094 }
1063 1095
1064 1096 /**
1065 - * Mark widget as deprecated.
1097 + * Is Custom Breakpoints Widget.
1066 1098 *
1067 - * Use `get_deprecation_message()` method to print the message control at specific location in register_controls().
1099 + * Checking if there are active custom-breakpoints and if the widget use them.
1068 1100 *
1069 - * @param string $version The version of Elementor that deprecated the widget.
1070 - * @param string $message A message regarding the deprecation.
1071 - * @param string $replacement The widget that should be used instead.
1101 + * @since 3.5.0
1102 + * @access protected
1103 + *
1104 + * @return boolean
1072 1105 */
1073 - protected function add_deprecation_message( $version, $message, $replacement ) {
1074 - // Expose the config for handling in JS.
1075 - $this->set_config( 'deprecation', [
1076 - 'version' => $version,
1077 - 'message' => $message,
1078 - 'replacement' => $replacement,
1079 - ] );
1106 + protected function is_custom_breakpoints_widget() {
1107 + $has_custom_breakpoints = Plugin::$instance->breakpoints->has_custom_breakpoints();
1080 1108
1081 - $this->add_control(
1082 - 'deprecation_message',
1083 - [
1084 - 'type' => Controls_Manager::ALERT,
1085 - 'alert_type' => 'info',
1086 - 'content' => $message,
1087 - 'separator' => 'after',
1088 - ]
1089 - );
1109 + if ( $has_custom_breakpoints ) {
1110 + $responsive_widgets = $this->get_responsive_widgets();
1111 +
1112 + // The $widget_name can also represents a widgets group name, therefore we need to use the current widget name to check if it's responsive widget.
1113 + $current_widget_name = $this->get_name();
1114 +
1115 + // If the widget is not implementing custom-breakpoints media queries then it has no custom- css file.
1116 + if ( ! isset( $responsive_widgets[ $current_widget_name ] ) ) {
1117 + $has_custom_breakpoints = false;
1118 + }
1119 + }
1120 +
1121 + return $has_custom_breakpoints;
1122 + }
1123 +
1124 + private function get_widget_css() {
1125 + $widgets_css_data_manager = $this->get_widgets_css_data_manager();
1126 +
1127 + $widgets_list = $this->get_inline_css_depends();
1128 +
1129 + $widgets_list[] = $this->get_group_name();
1130 +
1131 + $widget_css = '';
1132 +
1133 + foreach ( $widgets_list as $widget_data ) {
1134 + $widget_name = isset( $widget_data['name'] ) ? $widget_data['name'] : $widget_data;
1135 +
1136 + if ( ! in_array( $widget_name, self::$registered_inline_css_widgets, true ) ) {
1137 + if ( $this->get_group_name() === $widget_name ) {
1138 + $config = $this->get_css_config();
1139 + } else {
1140 + /**
1141 + * The core-dependency allowing to create a dependency specifically with the core widgets.
1142 + * Otherwise, the config will be taken from the class that inherits from Widget_Base.
1143 + */
1144 + $is_core_dependency = isset( $widget_data['is_core_dependency'] ) ? true : false;
1145 +
1146 + $config = $is_core_dependency ? self::get_widget_css_config( $widget_name ) : $this->get_widget_css_config( $widget_name );
1147 + }
1148 +
1149 + $widget_css .= $widgets_css_data_manager->get_asset_data_from_config( $config );
1150 +
1151 + self::$registered_inline_css_widgets[] = $widget_name;
1152 + }
1153 + }
1154 +
1155 + return $widget_css;
1156 +
1157 + }
1158 +
1159 + private function is_inline_css_mode() {
1160 + static $is_active;
1161 +
1162 + if ( null === $is_active ) {
1163 + $is_edit_mode = Plugin::$instance->editor->is_edit_mode();
1164 + $is_preview_mode = Plugin::$instance->preview->is_preview_mode();
1165 + $is_optimized_mode = Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_loading' );
1166 +
1167 + $is_active = ( Utils::is_script_debug() || $is_edit_mode || $is_preview_mode || ! $is_optimized_mode ) ? false : true;
1168 + }
1169 +
1170 + return $is_active;
1171 + }
1172 +
1173 + private function print_widget_css() {
1174 + if ( ! $this->is_inline_css_mode() ) {
1175 + return;
1176 + }
1177 +
1178 + Utils::print_unescaped_internal_string( $this->get_widget_css() );
1179 + }
1180 +
1181 + private function get_widgets_css_data_manager() {
1182 + if ( ! self::$widgets_css_data_manager ) {
1183 + self::$widgets_css_data_manager = new Widgets_Css_Data_Manager();
1184 + }
1185 +
1186 + return self::$widgets_css_data_manager;
1090 1187 }
1091 1188 }