PluginProbe
Elementor Website Builder – more than just a page builder / 3.19.2
Elementor Website Builder – more than just a page builder v3.19.2
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 +214 -63 4.0.93.19.2 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`.
@@ -105,18 +111,8 @@
105 111 public function get_categories() {
106 112 return [ 'general' ];
107 113 }
108 114
109 - /**
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 115 protected function get_upsale_data() {
120 116 return null;
121 117 }
122 118
@@ -183,11 +179,11 @@
183 179 */
184 180 public function get_stack( $with_common_controls = true ) {
185 181 $stack = parent::get_stack();
186 182
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() );
183 + if ( $with_common_controls && 'common' !== $this->get_unique_name() ) {
184 + /** @var Widget_Common $common_widget */
185 + $common_widget = Plugin::$instance->widgets_manager->get_widget_types( 'common' );
190 186
191 187 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
192 188
193 189 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
@@ -195,16 +191,8 @@
195 191
196 192 return $stack;
197 193 }
198 194
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 195 /**
208 196 * Get widget controls pointer index.
209 197 *
210 198 * Retrieve widget pointer index where the next control should be added.
@@ -300,9 +288,9 @@
300 288 foreach ( $skins as $skin_id => $skin ) {
301 289 $skin_options[ $skin_id ] = $skin->get_title();
302 290 }
303 291
304 - // Get the first item for default value.
292 + // Get the first item for default value
305 293 $default_value = array_keys( $skin_options );
306 294 $default_value = array_shift( $default_value );
307 295
308 296 if ( 1 >= count( $skin_options ) ) {
@@ -380,21 +368,10 @@
380 368 'html_wrapper_class' => $this->get_html_wrapper_class(),
381 369 'show_in_panel' => $this->show_in_panel(),
382 370 'hide_on_search' => $this->hide_on_search(),
383 371 'upsale_data' => $this->get_upsale_data(),
384 - 'is_dynamic_content' => $this->is_dynamic_content(),
385 - 'has_widget_inner_wrapper' => $this->has_widget_inner_wrapper(),
386 372 ];
387 373
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 374 $stack = Plugin::$instance->controls_manager->get_element_stack( $this );
398 375
399 376 if ( $stack ) {
400 377 $config['controls'] = $this->get_stack( false )['controls'];
@@ -423,15 +400,15 @@
423 400 *
424 401 * @param string $template_content Template content.
425 402 */
426 403 protected function print_template_content( $template_content ) {
427 - if ( $this->has_widget_inner_wrapper() ) : ?>
404 + ?>
428 405 <div class="elementor-widget-container">
429 - <?php endif;
430 - Utils::print_unescaped_internal_string( $template_content );
431 - if ( $this->has_widget_inner_wrapper() ) : ?>
406 + <?php
407 + echo $template_content; // XSS ok.
408 + ?>
432 409 </div>
433 - <?php endif;
410 + <?php
434 411 }
435 412
436 413 /**
437 414 * Parse text editor.
@@ -541,17 +518,18 @@
541 518 *
542 519 * Used to add Light-Box-related data attributes to links that open media files.
543 520 *
544 521 * @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.
522 + * @param int $id The ID of the image
523 + * @param string $lightbox_setting_key The setting key that dictates weather to open the image in a lightbox
524 + * @param string $group_id Unique ID for a group of lightbox images
525 + * @param bool $overwrite Optional. Whether to overwrite existing
526 + * attribute. Default is false, not to overwrite.
550 527 *
551 528 * @return Widget_Base Current instance of the widget.
552 529 * @since 2.9.0
553 530 * @access public
531 + *
554 532 */
555 533 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
556 534 $kit = Plugin::$instance->kits_manager->get_active_kit();
557 535
@@ -640,16 +618,19 @@
640 618
641 619 if ( empty( $widget_content ) ) {
642 620 return;
643 621 }
644 - if ( $this->has_widget_inner_wrapper() ) : ?>
622 + ?>
645 623 <div class="elementor-widget-container">
646 - <?php endif; ?>
647 624 <?php
648 625 if ( $this->is_widget_first_render( $this->get_group_name() ) ) {
649 626 $this->register_runtime_widget( $this->get_group_name() );
650 627 }
651 628
629 + $this->print_widget_css();
630 +
631 + // get_name
632 +
652 633 /**
653 634 * Render widget content.
654 635 *
655 636 * Filters the widget content before it's rendered.
@@ -659,13 +640,13 @@
659 640 * @param string $widget_content The content of the widget.
660 641 * @param Widget_Base $this The widget.
661 642 */
662 643 $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
663 - Utils::print_unescaped_internal_string( $widget_content );
644 +
645 + echo $widget_content; // XSS ok.
664 646 ?>
665 - <?php if ( $this->has_widget_inner_wrapper() ) : ?>
666 647 </div>
667 - <?php endif;
648 + <?php
668 649 }
669 650
670 651 protected function is_widget_first_render( $widget_name ) {
671 652 return ! in_array( $widget_name, self::$registered_runtime_widgets, true );
@@ -779,10 +760,10 @@
779 760 *
780 761 * Script tags are allowed on frontend according to the WP theme securing policy.
781 762 *
782 763 * @param string $setting
783 - * @param null $repeater_name
784 - * @param null $index
764 + * @param null $repeater_name
765 + * @param null $index
785 766 */
786 767 final public function print_unescaped_setting( $setting, $repeater_name = null, $index = null ) {
787 768 if ( $repeater_name ) {
788 769 $repeater = $this->get_settings_for_display( $repeater_name );
@@ -847,9 +828,9 @@
847 828 * @access protected
848 829 *
849 830 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
850 831 * @param string $repeater_key The repeater key containing the array of all the items in the repeater (e.g. `tabs`).
851 - * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
832 + * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
852 833 *
853 834 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
854 835 */
855 836 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
@@ -1006,13 +987,27 @@
1006 987 return $this->get_name();
1007 988 }
1008 989
1009 990 /**
1010 - * @param string $plugin_title Plugin's title.
1011 - * @param string $since Plugin version widget was deprecated.
1012 - * @param string $last Plugin version in which the widget will be removed.
1013 - * @param string $replacement Widget replacement.
991 + * Get Inline CSS dependencies.
992 + *
993 + * Retrieve a list of inline CSS dependencies that the element requires.
994 + *
995 + * @since 3.3.0
996 + * @access public
997 + *
998 + * @return array.
1014 999 */
1000 + public function get_inline_css_depends() {
1001 + return [];
1002 + }
1003 +
1004 + /**
1005 + * @param string $plugin_title Plugin's title
1006 + * @param string $since Plugin version widget was deprecated
1007 + * @param string $last Plugin version in which the widget will be removed
1008 + * @param string $replacement Widget replacement
1009 + */
1015 1010 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
1016 1011 $this->start_controls_section(
1017 1012 'Deprecated',
1018 1013 [
@@ -1052,16 +1047,61 @@
1052 1047 public function register_runtime_widget( $widget_name ) {
1053 1048 self::$registered_runtime_widgets[] = $widget_name;
1054 1049 }
1055 1050
1051 + public function get_widget_css_config( $widget_name ) {
1052 + $direction = is_rtl() ? '-rtl' : '';
1053 +
1054 + $has_custom_breakpoints = $this->is_custom_breakpoints_widget();
1055 +
1056 + $file_name = 'widget-' . $widget_name . $direction . '.min.css';
1057 +
1058 + // 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.
1059 + $file_url = Plugin::$instance->frontend->get_frontend_file_url( $file_name, $has_custom_breakpoints );
1060 +
1061 + // 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.
1062 + $file_path = Plugin::$instance->frontend->get_frontend_file_path( $file_name, $has_custom_breakpoints );
1063 +
1064 + return [
1065 + 'key' => $widget_name,
1066 + 'version' => ELEMENTOR_VERSION,
1067 + 'file_path' => $file_path,
1068 + 'data' => [
1069 + 'file_url' => $file_url,
1070 + ],
1071 + ];
1072 + }
1073 +
1074 + public function get_css_config() {
1075 + return $this->get_widget_css_config( $this->get_group_name() );
1076 + }
1077 +
1078 + public function get_responsive_widgets_config() {
1079 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1080 +
1081 + return [
1082 + 'key' => $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_DATABASE_KEY,
1083 + 'version' => ELEMENTOR_VERSION,
1084 + 'file_path' => ELEMENTOR_ASSETS_PATH . $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_FILE_PATH,
1085 + ];
1086 + }
1087 +
1088 + public function get_responsive_widgets() {
1089 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1090 +
1091 + $config = $this->get_responsive_widgets_config();
1092 +
1093 + return $responsive_widgets_data_manager->get_asset_data_from_config( $config );
1094 + }
1095 +
1056 1096 /**
1057 1097 * Mark widget as deprecated.
1058 1098 *
1059 1099 * Use `get_deprecation_message()` method to print the message control at specific location in register_controls().
1060 1100 *
1061 - * @param string $version The version of Elementor that deprecated the widget.
1062 - * @param string $message A message regarding the deprecation.
1063 - * @param string $replacement The widget that should be used instead.
1101 + * @param $version string The version of Elementor that deprecated the widget.
1102 + * @param $message string A message regarding the deprecation.
1103 + * @param $replacement string The widget that should be used instead.
1064 1104 */
1065 1105 protected function add_deprecation_message( $version, $message, $replacement ) {
1066 1106 // Expose the config for handling in JS.
1067 1107 $this->set_config( 'deprecation', [
@@ -1072,12 +1112,123 @@
1072 1112
1073 1113 $this->add_control(
1074 1114 'deprecation_message',
1075 1115 [
1076 - 'type' => Controls_Manager::ALERT,
1077 - 'alert_type' => 'info',
1078 - 'content' => $message,
1116 + 'type' => Controls_Manager::RAW_HTML,
1117 + 'raw' => $message,
1118 + 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
1079 1119 'separator' => 'after',
1080 1120 ]
1081 1121 );
1122 + }
1123 +
1124 + /**
1125 + * Get Responsive Widgets Data Manager.
1126 + *
1127 + * Retrieve the data manager that handles widgets that are using media queries for custom-breakpoints values.
1128 + *
1129 + * @since 3.5.0
1130 + * @access protected
1131 + *
1132 + * @return Responsive_Widgets_Data_Manager
1133 + */
1134 + protected function get_responsive_widgets_data_manager() {
1135 + if ( ! self::$responsive_widgets_data_manager ) {
1136 + self::$responsive_widgets_data_manager = new Responsive_Widgets_Data_Manager();
1137 + }
1138 +
1139 + return self::$responsive_widgets_data_manager;
1140 + }
1141 +
1142 + /**
1143 + * Is Custom Breakpoints Widget.
1144 + *
1145 + * Checking if there are active custom-breakpoints and if the widget use them.
1146 + *
1147 + * @since 3.5.0
1148 + * @access protected
1149 + *
1150 + * @return boolean
1151 + */
1152 + protected function is_custom_breakpoints_widget() {
1153 + $has_custom_breakpoints = Plugin::$instance->breakpoints->has_custom_breakpoints();
1154 +
1155 + if ( $has_custom_breakpoints ) {
1156 + $responsive_widgets = $this->get_responsive_widgets();
1157 +
1158 + // 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.
1159 + $current_widget_name = $this->get_name();
1160 +
1161 + // If the widget is not implementing custom-breakpoints media queries then it has no custom- css file.
1162 + if ( ! isset( $responsive_widgets[ $current_widget_name ] ) ) {
1163 + $has_custom_breakpoints = false;
1164 + }
1165 + }
1166 +
1167 + return $has_custom_breakpoints;
1168 + }
1169 +
1170 + private function get_widget_css() {
1171 + $widgets_css_data_manager = $this->get_widgets_css_data_manager();
1172 +
1173 + $widgets_list = $this->get_inline_css_depends();
1174 +
1175 + $widgets_list[] = $this->get_group_name();
1176 +
1177 + $widget_css = '';
1178 +
1179 + foreach ( $widgets_list as $widget_data ) {
1180 + $widget_name = isset( $widget_data['name'] ) ? $widget_data['name'] : $widget_data;
1181 +
1182 + if ( ! in_array( $widget_name, self::$registered_inline_css_widgets, true ) ) {
1183 + if ( $this->get_group_name() === $widget_name ) {
1184 + $config = $this->get_css_config();
1185 + } else {
1186 + /**
1187 + * The core-dependency allowing to create a dependency specifically with the core widgets.
1188 + * Otherwise, the config will be taken from the class that inherits from Widget_Base.
1189 + */
1190 + $is_core_dependency = isset( $widget_data['is_core_dependency'] ) ? true : false;
1191 +
1192 + $config = $is_core_dependency ? self::get_widget_css_config( $widget_name ) : $this->get_widget_css_config( $widget_name );
1193 + }
1194 +
1195 + $widget_css .= $widgets_css_data_manager->get_asset_data_from_config( $config );
1196 +
1197 + self::$registered_inline_css_widgets[] = $widget_name;
1198 + }
1199 + }
1200 +
1201 + return $widget_css;
1202 +
1203 + }
1204 +
1205 + private function is_inline_css_mode() {
1206 + static $is_active;
1207 +
1208 + if ( null === $is_active ) {
1209 + $is_edit_mode = Plugin::$instance->editor->is_edit_mode();
1210 + $is_preview_mode = Plugin::$instance->preview->is_preview_mode();
1211 + $is_optimized_mode = Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_loading' );
1212 +
1213 + $is_active = ( Utils::is_script_debug() || $is_edit_mode || $is_preview_mode || ! $is_optimized_mode ) ? false : true;
1214 + }
1215 +
1216 + return $is_active;
1217 + }
1218 +
1219 + private function print_widget_css() {
1220 + if ( ! $this->is_inline_css_mode() ) {
1221 + return;
1222 + }
1223 +
1224 + Utils::print_unescaped_internal_string( $this->get_widget_css() );
1225 + }
1226 +
1227 + private function get_widgets_css_data_manager() {
1228 + if ( ! self::$widgets_css_data_manager ) {
1229 + self::$widgets_css_data_manager = new Widgets_Css_Data_Manager();
1230 + }
1231 +
1232 + return self::$widgets_css_data_manager;
1082 1233 }
1083 1234 }