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.1 4.3.0 4.3.0-beta3 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 All 454 releases
← All changes | includes/base/widget-base.php +217 -102 4.3.03.19.2 View file →
@@ -1,10 +1,9 @@
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;
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;
7 6
8 7 if ( ! defined( 'ABSPATH' ) ) {
9 8 exit; // Exit if accessed directly.
10 9 }
@@ -49,8 +48,14 @@
49 48 * @var array
50 49 */
51 50 public static $registered_runtime_widgets = [];
52 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 +
53 58 /**
54 59 * Get element type.
55 60 *
56 61 * Retrieve the element type, in this case `widget`.
@@ -106,18 +111,8 @@
106 111 public function get_categories() {
107 112 return [ 'general' ];
108 113 }
109 114
110 - /**
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 115 protected function get_upsale_data() {
121 116 return null;
122 117 }
123 118
@@ -184,11 +179,11 @@
184 179 */
185 180 public function get_stack( $with_common_controls = true ) {
186 181 $stack = parent::get_stack();
187 182
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() );
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' );
191 186
192 187 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
193 188
194 189 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
@@ -196,16 +191,8 @@
196 191
197 192 return $stack;
198 193 }
199 194
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 195 /**
209 196 * Get widget controls pointer index.
210 197 *
211 198 * Retrieve widget pointer index where the next control should be added.
@@ -301,9 +288,9 @@
301 288 foreach ( $skins as $skin_id => $skin ) {
302 289 $skin_options[ $skin_id ] = $skin->get_title();
303 290 }
304 291
305 - // Get the first item for default value.
292 + // Get the first item for default value
306 293 $default_value = array_keys( $skin_options );
307 294 $default_value = array_shift( $default_value );
308 295
309 296 if ( 1 >= count( $skin_options ) ) {
@@ -380,22 +367,11 @@
380 367 'categories' => $this->get_categories(),
381 368 'html_wrapper_class' => $this->get_html_wrapper_class(),
382 369 'show_in_panel' => $this->show_in_panel(),
383 370 '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(),
371 + 'upsale_data' => $this->get_upsale_data(),
387 372 ];
388 373
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 374 $stack = Plugin::$instance->controls_manager->get_element_stack( $this );
399 375
400 376 if ( $stack ) {
401 377 $config['controls'] = $this->get_stack( false )['controls'];
@@ -424,15 +400,15 @@
424 400 *
425 401 * @param string $template_content Template content.
426 402 */
427 403 protected function print_template_content( $template_content ) {
428 - if ( $this->has_widget_inner_wrapper() ) : ?>
404 + ?>
429 405 <div class="elementor-widget-container">
430 - <?php endif;
431 - Utils::print_unescaped_internal_string( $template_content );
432 - if ( $this->has_widget_inner_wrapper() ) : ?>
406 + <?php
407 + echo $template_content; // XSS ok.
408 + ?>
433 409 </div>
434 - <?php endif;
410 + <?php
435 411 }
436 412
437 413 /**
438 414 * Parse text editor.
@@ -542,17 +518,18 @@
542 518 *
543 519 * Used to add Light-Box-related data attributes to links that open media files.
544 520 *
545 521 * @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.
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.
551 527 *
552 528 * @return Widget_Base Current instance of the widget.
553 529 * @since 2.9.0
554 530 * @access public
531 + *
555 532 */
556 533 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
557 534 $kit = Plugin::$instance->kits_manager->get_active_kit();
558 535
@@ -624,9 +601,9 @@
624 601 * @since 1.0.0
625 602 *
626 603 * @param Widget_Base $this The current widget.
627 604 */
628 - do_action( 'elementor/widget/before_render_content', $this, [ 'mode' => Widget_Content_Render_Mode::NORMAL ] );
605 + do_action( 'elementor/widget/before_render_content', $this );
629 606
630 607 ob_start();
631 608
632 609 $skin = $this->get_current_skin();
@@ -641,16 +618,19 @@
641 618
642 619 if ( empty( $widget_content ) ) {
643 620 return;
644 621 }
645 - if ( $this->has_widget_inner_wrapper() ) : ?>
622 + ?>
646 623 <div class="elementor-widget-container">
647 - <?php endif; ?>
648 624 <?php
649 625 if ( $this->is_widget_first_render( $this->get_group_name() ) ) {
650 626 $this->register_runtime_widget( $this->get_group_name() );
651 627 }
652 628
629 + $this->print_widget_css();
630 +
631 + // get_name
632 +
653 633 /**
654 634 * Render widget content.
655 635 *
656 636 * Filters the widget content before it's rendered.
@@ -659,14 +639,14 @@
659 639 *
660 640 * @param string $widget_content The content of the widget.
661 641 * @param Widget_Base $this The widget.
662 642 */
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 );
643 + $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
644 +
645 + echo $widget_content; // XSS ok.
665 646 ?>
666 - <?php if ( $this->has_widget_inner_wrapper() ) : ?>
667 647 </div>
668 - <?php endif;
648 + <?php
669 649 }
670 650
671 651 protected function is_widget_first_render( $widget_name ) {
672 652 return ! in_array( $widget_name, self::$registered_runtime_widgets, true );
@@ -697,43 +677,8 @@
697 677 public function render_plain_content() {
698 678 $this->render_content();
699 679 }
700 680
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 681 /**
737 682 * Before widget rendering.
738 683 *
739 684 * Used to add stuff before the widget `_wrapper` element.
@@ -815,10 +760,10 @@
815 760 *
816 761 * Script tags are allowed on frontend according to the WP theme securing policy.
817 762 *
818 763 * @param string $setting
819 - * @param null $repeater_name
820 - * @param null $index
764 + * @param null $repeater_name
765 + * @param null $index
821 766 */
822 767 final public function print_unescaped_setting( $setting, $repeater_name = null, $index = null ) {
823 768 if ( $repeater_name ) {
824 769 $repeater = $this->get_settings_for_display( $repeater_name );
@@ -883,9 +828,9 @@
883 828 * @access protected
884 829 *
885 830 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
886 831 * @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`).
832 + * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
888 833 *
889 834 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
890 835 */
891 836 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
@@ -1042,13 +987,27 @@
1042 987 return $this->get_name();
1043 988 }
1044 989
1045 990 /**
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.
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.
1050 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 + */
1051 1010 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
1052 1011 $this->start_controls_section(
1053 1012 'Deprecated',
1054 1013 [
@@ -1088,16 +1047,61 @@
1088 1047 public function register_runtime_widget( $widget_name ) {
1089 1048 self::$registered_runtime_widgets[] = $widget_name;
1090 1049 }
1091 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 +
1092 1096 /**
1093 1097 * Mark widget as deprecated.
1094 1098 *
1095 1099 * Use `get_deprecation_message()` method to print the message control at specific location in register_controls().
1096 1100 *
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.
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.
1100 1104 */
1101 1105 protected function add_deprecation_message( $version, $message, $replacement ) {
1102 1106 // Expose the config for handling in JS.
1103 1107 $this->set_config( 'deprecation', [
@@ -1108,12 +1112,123 @@
1108 1112
1109 1113 $this->add_control(
1110 1114 'deprecation_message',
1111 1115 [
1112 - 'type' => Controls_Manager::ALERT,
1113 - 'alert_type' => 'info',
1114 - 'content' => $message,
1116 + 'type' => Controls_Manager::RAW_HTML,
1117 + 'raw' => $message,
1118 + 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
1115 1119 'separator' => 'after',
1116 1120 ]
1117 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;
1118 1233 }
1119 1234 }