PluginProbe
Elementor Website Builder – more than just a page builder / 3.20.0-dev3
Elementor Website Builder – more than just a page builder v3.20.0-dev3
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 +219 -84 4.3.0-beta33.20.0-dev3 View file →
@@ -1,10 +1,10 @@
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;
6 +use Elementor\Core\Utils\Promotions\Validate_Promotion;
7 7
8 8 if ( ! defined( 'ABSPATH' ) ) {
9 9 exit; // Exit if accessed directly.
10 10 }
@@ -49,8 +49,14 @@
49 49 * @var array
50 50 */
51 51 public static $registered_runtime_widgets = [];
52 52
53 + public static $registered_inline_css_widgets = [];
54 +
55 + private static $widgets_css_data_manager;
56 +
57 + private static $responsive_widgets_data_manager;
58 +
53 59 /**
54 60 * Get element type.
55 61 *
56 62 * Retrieve the element type, in this case `widget`.
@@ -184,11 +190,11 @@
184 190 */
185 191 public function get_stack( $with_common_controls = true ) {
186 192 $stack = parent::get_stack();
187 193
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() );
194 + if ( $with_common_controls && 'common' !== $this->get_unique_name() ) {
195 + /** @var Widget_Common $common_widget */
196 + $common_widget = Plugin::$instance->widgets_manager->get_widget_types( 'common' );
191 197
192 198 $stack['controls'] = array_merge( $stack['controls'], $common_widget->get_controls() );
193 199
194 200 $stack['tabs'] = array_merge( $stack['tabs'], $common_widget->get_tabs_controls() );
@@ -196,16 +202,8 @@
196 202
197 203 return $stack;
198 204 }
199 205
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 206 /**
209 207 * Get widget controls pointer index.
210 208 *
211 209 * Retrieve widget pointer index where the next control should be added.
@@ -301,9 +299,9 @@
301 299 foreach ( $skins as $skin_id => $skin ) {
302 300 $skin_options[ $skin_id ] = $skin->get_title();
303 301 }
304 302
305 - // Get the first item for default value.
303 + // Get the first item for default value
306 304 $default_value = array_keys( $skin_options );
307 305 $default_value = array_shift( $default_value );
308 306
309 307 if ( 1 >= count( $skin_options ) ) {
@@ -380,17 +378,12 @@
380 378 'categories' => $this->get_categories(),
381 379 'html_wrapper_class' => $this->get_html_wrapper_class(),
382 380 'show_in_panel' => $this->show_in_panel(),
383 381 '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(),
382 + 'upsale_data' => $this->get_upsale_data(),
387 383 ];
388 384
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 - }
385 + $config['upsale_data'] = apply_filters( 'elementor/widgets/' . $this->get_name() . '/custom_promotion', $config['upsale_data'] ) ?? $this->get_upsale_data();
393 386
394 387 if ( isset( $config['upsale_data']['image'] ) ) {
395 388 $config['upsale_data']['image'] = esc_url( $config['upsale_data']['image'] );
396 389 }
@@ -400,8 +393,11 @@
400 393 if ( $stack ) {
401 394 $config['controls'] = $this->get_stack( false )['controls'];
402 395 $config['tabs_controls'] = $this->get_tabs_controls();
403 396 }
397 + if ( isset( $config['upsale_data']['upgrade_url'] ) && false === Validate_Promotion::domain_is_on_elementor_dot_com( $config['upsale_data']['upgrade_url'] ) ) {
398 + $config['upsale_data']['upgrade_url'] = esc_url( $this->get_upsale_data()['upgrade_url'] );
399 + }
404 400
405 401 return array_replace_recursive( parent::get_initial_config(), $config );
406 402 }
407 403
@@ -424,15 +420,15 @@
424 420 *
425 421 * @param string $template_content Template content.
426 422 */
427 423 protected function print_template_content( $template_content ) {
428 - if ( $this->has_widget_inner_wrapper() ) : ?>
424 + ?>
429 425 <div class="elementor-widget-container">
430 - <?php endif;
431 - Utils::print_unescaped_internal_string( $template_content );
432 - if ( $this->has_widget_inner_wrapper() ) : ?>
426 + <?php
427 + echo $template_content; // XSS ok.
428 + ?>
433 429 </div>
434 - <?php endif;
430 + <?php
435 431 }
436 432
437 433 /**
438 434 * Parse text editor.
@@ -542,17 +538,18 @@
542 538 *
543 539 * Used to add Light-Box-related data attributes to links that open media files.
544 540 *
545 541 * @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.
542 + * @param int $id The ID of the image
543 + * @param string $lightbox_setting_key The setting key that dictates weather to open the image in a lightbox
544 + * @param string $group_id Unique ID for a group of lightbox images
545 + * @param bool $overwrite Optional. Whether to overwrite existing
546 + * attribute. Default is false, not to overwrite.
551 547 *
552 548 * @return Widget_Base Current instance of the widget.
553 549 * @since 2.9.0
554 550 * @access public
551 + *
555 552 */
556 553 public function add_lightbox_data_attributes( $element, $id = null, $lightbox_setting_key = null, $group_id = null, $overwrite = false ) {
557 554 $kit = Plugin::$instance->kits_manager->get_active_kit();
558 555
@@ -624,9 +621,9 @@
624 621 * @since 1.0.0
625 622 *
626 623 * @param Widget_Base $this The current widget.
627 624 */
628 - do_action( 'elementor/widget/before_render_content', $this, [ 'mode' => Widget_Content_Render_Mode::NORMAL ] );
625 + do_action( 'elementor/widget/before_render_content', $this );
629 626
630 627 ob_start();
631 628
632 629 $skin = $this->get_current_skin();
@@ -641,16 +638,19 @@
641 638
642 639 if ( empty( $widget_content ) ) {
643 640 return;
644 641 }
645 - if ( $this->has_widget_inner_wrapper() ) : ?>
642 + ?>
646 643 <div class="elementor-widget-container">
647 - <?php endif; ?>
648 644 <?php
649 645 if ( $this->is_widget_first_render( $this->get_group_name() ) ) {
650 646 $this->register_runtime_widget( $this->get_group_name() );
651 647 }
652 648
649 + $this->print_widget_css();
650 +
651 + // get_name
652 +
653 653 /**
654 654 * Render widget content.
655 655 *
656 656 * Filters the widget content before it's rendered.
@@ -659,14 +659,14 @@
659 659 *
660 660 * @param string $widget_content The content of the widget.
661 661 * @param Widget_Base $this The widget.
662 662 */
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 );
663 + $widget_content = apply_filters( 'elementor/widget/render_content', $widget_content, $this );
664 +
665 + echo $widget_content; // XSS ok.
665 666 ?>
666 - <?php if ( $this->has_widget_inner_wrapper() ) : ?>
667 667 </div>
668 - <?php endif;
668 + <?php
669 669 }
670 670
671 671 protected function is_widget_first_render( $widget_name ) {
672 672 return ! in_array( $widget_name, self::$registered_runtime_widgets, true );
@@ -697,43 +697,8 @@
697 697 public function render_plain_content() {
698 698 $this->render_content();
699 699 }
700 700
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 701 /**
737 702 * Before widget rendering.
738 703 *
739 704 * Used to add stuff before the widget `_wrapper` element.
@@ -815,10 +780,10 @@
815 780 *
816 781 * Script tags are allowed on frontend according to the WP theme securing policy.
817 782 *
818 783 * @param string $setting
819 - * @param null $repeater_name
820 - * @param null $index
784 + * @param null $repeater_name
785 + * @param null $index
821 786 */
822 787 final public function print_unescaped_setting( $setting, $repeater_name = null, $index = null ) {
823 788 if ( $repeater_name ) {
824 789 $repeater = $this->get_settings_for_display( $repeater_name );
@@ -883,9 +848,9 @@
883 848 * @access protected
884 849 *
885 850 * @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
886 851 * @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`).
852 + * @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
888 853 *
889 854 * @return string The repeater setting key (e.g. `tabs.3.tab_title`).
890 855 */
891 856 protected function get_repeater_setting_key( $setting_key, $repeater_key, $repeater_item_index ) {
@@ -1042,13 +1007,27 @@
1042 1007 return $this->get_name();
1043 1008 }
1044 1009
1045 1010 /**
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.
1011 + * Get Inline CSS dependencies.
1012 + *
1013 + * Retrieve a list of inline CSS dependencies that the element requires.
1014 + *
1015 + * @since 3.3.0
1016 + * @access public
1017 + *
1018 + * @return array.
1050 1019 */
1020 + public function get_inline_css_depends() {
1021 + return [];
1022 + }
1023 +
1024 + /**
1025 + * @param string $plugin_title Plugin's title
1026 + * @param string $since Plugin version widget was deprecated
1027 + * @param string $last Plugin version in which the widget will be removed
1028 + * @param string $replacement Widget replacement
1029 + */
1051 1030 protected function deprecated_notice( $plugin_title, $since, $last = '', $replacement = '' ) {
1052 1031 $this->start_controls_section(
1053 1032 'Deprecated',
1054 1033 [
@@ -1088,16 +1067,61 @@
1088 1067 public function register_runtime_widget( $widget_name ) {
1089 1068 self::$registered_runtime_widgets[] = $widget_name;
1090 1069 }
1091 1070
1071 + public function get_widget_css_config( $widget_name ) {
1072 + $direction = is_rtl() ? '-rtl' : '';
1073 +
1074 + $has_custom_breakpoints = $this->is_custom_breakpoints_widget();
1075 +
1076 + $file_name = 'widget-' . $widget_name . $direction . '.min.css';
1077 +
1078 + // 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.
1079 + $file_url = Plugin::$instance->frontend->get_frontend_file_url( $file_name, $has_custom_breakpoints );
1080 +
1081 + // 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.
1082 + $file_path = Plugin::$instance->frontend->get_frontend_file_path( $file_name, $has_custom_breakpoints );
1083 +
1084 + return [
1085 + 'key' => $widget_name,
1086 + 'version' => ELEMENTOR_VERSION,
1087 + 'file_path' => $file_path,
1088 + 'data' => [
1089 + 'file_url' => $file_url,
1090 + ],
1091 + ];
1092 + }
1093 +
1094 + public function get_css_config() {
1095 + return $this->get_widget_css_config( $this->get_group_name() );
1096 + }
1097 +
1098 + public function get_responsive_widgets_config() {
1099 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1100 +
1101 + return [
1102 + 'key' => $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_DATABASE_KEY,
1103 + 'version' => ELEMENTOR_VERSION,
1104 + 'file_path' => ELEMENTOR_ASSETS_PATH . $responsive_widgets_data_manager::RESPONSIVE_WIDGETS_FILE_PATH,
1105 + ];
1106 + }
1107 +
1108 + public function get_responsive_widgets() {
1109 + $responsive_widgets_data_manager = $this->get_responsive_widgets_data_manager();
1110 +
1111 + $config = $this->get_responsive_widgets_config();
1112 +
1113 + return $responsive_widgets_data_manager->get_asset_data_from_config( $config );
1114 + }
1115 +
1092 1116 /**
1093 1117 * Mark widget as deprecated.
1094 1118 *
1095 1119 * Use `get_deprecation_message()` method to print the message control at specific location in register_controls().
1096 1120 *
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.
1121 + * @param $version string The version of Elementor that deprecated the widget.
1122 + * @param $message string A message regarding the deprecation.
1123 + * @param $replacement string The widget that should be used instead.
1100 1124 */
1101 1125 protected function add_deprecation_message( $version, $message, $replacement ) {
1102 1126 // Expose the config for handling in JS.
1103 1127 $this->set_config( 'deprecation', [
@@ -1114,6 +1138,117 @@
1114 1138 'content' => $message,
1115 1139 'separator' => 'after',
1116 1140 ]
1117 1141 );
1142 + }
1143 +
1144 + /**
1145 + * Get Responsive Widgets Data Manager.
1146 + *
1147 + * Retrieve the data manager that handles widgets that are using media queries for custom-breakpoints values.
1148 + *
1149 + * @since 3.5.0
1150 + * @access protected
1151 + *
1152 + * @return Responsive_Widgets_Data_Manager
1153 + */
1154 + protected function get_responsive_widgets_data_manager() {
1155 + if ( ! self::$responsive_widgets_data_manager ) {
1156 + self::$responsive_widgets_data_manager = new Responsive_Widgets_Data_Manager();
1157 + }
1158 +
1159 + return self::$responsive_widgets_data_manager;
1160 + }
1161 +
1162 + /**
1163 + * Is Custom Breakpoints Widget.
1164 + *
1165 + * Checking if there are active custom-breakpoints and if the widget use them.
1166 + *
1167 + * @since 3.5.0
1168 + * @access protected
1169 + *
1170 + * @return boolean
1171 + */
1172 + protected function is_custom_breakpoints_widget() {
1173 + $has_custom_breakpoints = Plugin::$instance->breakpoints->has_custom_breakpoints();
1174 +
1175 + if ( $has_custom_breakpoints ) {
1176 + $responsive_widgets = $this->get_responsive_widgets();
1177 +
1178 + // 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.
1179 + $current_widget_name = $this->get_name();
1180 +
1181 + // If the widget is not implementing custom-breakpoints media queries then it has no custom- css file.
1182 + if ( ! isset( $responsive_widgets[ $current_widget_name ] ) ) {
1183 + $has_custom_breakpoints = false;
1184 + }
1185 + }
1186 +
1187 + return $has_custom_breakpoints;
1188 + }
1189 +
1190 + private function get_widget_css() {
1191 + $widgets_css_data_manager = $this->get_widgets_css_data_manager();
1192 +
1193 + $widgets_list = $this->get_inline_css_depends();
1194 +
1195 + $widgets_list[] = $this->get_group_name();
1196 +
1197 + $widget_css = '';
1198 +
1199 + foreach ( $widgets_list as $widget_data ) {
1200 + $widget_name = isset( $widget_data['name'] ) ? $widget_data['name'] : $widget_data;
1201 +
1202 + if ( ! in_array( $widget_name, self::$registered_inline_css_widgets, true ) ) {
1203 + if ( $this->get_group_name() === $widget_name ) {
1204 + $config = $this->get_css_config();
1205 + } else {
1206 + /**
1207 + * The core-dependency allowing to create a dependency specifically with the core widgets.
1208 + * Otherwise, the config will be taken from the class that inherits from Widget_Base.
1209 + */
1210 + $is_core_dependency = isset( $widget_data['is_core_dependency'] ) ? true : false;
1211 +
1212 + $config = $is_core_dependency ? self::get_widget_css_config( $widget_name ) : $this->get_widget_css_config( $widget_name );
1213 + }
1214 +
1215 + $widget_css .= $widgets_css_data_manager->get_asset_data_from_config( $config );
1216 +
1217 + self::$registered_inline_css_widgets[] = $widget_name;
1218 + }
1219 + }
1220 +
1221 + return $widget_css;
1222 +
1223 + }
1224 +
1225 + private function is_inline_css_mode() {
1226 + static $is_active;
1227 +
1228 + if ( null === $is_active ) {
1229 + $is_edit_mode = Plugin::$instance->editor->is_edit_mode();
1230 + $is_preview_mode = Plugin::$instance->preview->is_preview_mode();
1231 + $is_optimized_mode = Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_loading' );
1232 +
1233 + $is_active = ( Utils::is_script_debug() || $is_edit_mode || $is_preview_mode || ! $is_optimized_mode ) ? false : true;
1234 + }
1235 +
1236 + return $is_active;
1237 + }
1238 +
1239 + private function print_widget_css() {
1240 + if ( ! $this->is_inline_css_mode() ) {
1241 + return;
1242 + }
1243 +
1244 + Utils::print_unescaped_internal_string( $this->get_widget_css() );
1245 + }
1246 +
1247 + private function get_widgets_css_data_manager() {
1248 + if ( ! self::$widgets_css_data_manager ) {
1249 + self::$widgets_css_data_manager = new Widgets_Css_Data_Manager();
1250 + }
1251 +
1252 + return self::$widgets_css_data_manager;
1118 1253 }
1119 1254 }