PluginProbe
Elementor Website Builder – more than just a page builder / 3.4.0-dev9
Elementor Website Builder – more than just a page builder v3.4.0-dev9
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/utils.php +60 -278 4.0.73.4.0-dev9 View file →
@@ -1,10 +1,7 @@
1 1 <?php
2 2 namespace Elementor;
3 3
4 -use Elementor\Core\Files\Fonts\Google_Font;
5 -use Elementor\Core\Utils\Collection;
6 -
7 4 if ( ! defined( 'ABSPATH' ) ) {
8 5 exit; // Exit if accessed directly.
9 6 }
10 7
@@ -19,19 +16,15 @@
19 16 class Utils {
20 17
21 18 const DEPRECATION_RANGE = 0.4;
22 19
23 - const EDITOR_BREAK_LINES_OPTION_KEY = 'elementor_editor_break_lines';
24 -
25 20 /**
26 - * A list of safe tags for `validate_html_tag` method.
21 + * A list of safe tage for `validate_html_tag` method.
27 22 */
28 23 const ALLOWED_HTML_WRAPPER_TAGS = [
29 24 'a',
30 25 'article',
31 26 'aside',
32 - 'button',
33 - 'form',
34 27 'div',
35 28 'footer',
36 29 'h1',
37 30 'h2',
@@ -83,36 +76,31 @@
83 76 'd' => true,
84 77 'fill' => true,
85 78 ],
86 79 ],
87 - 'image' => [
88 - 'img' => [
89 - 'srcset' => true,
90 - 'sizes' => true,
91 - ],
92 - ],
93 80 ];
94 81
95 82 /**
96 - * Variables for free to pro upsale modal promotions
83 + * Is ajax.
84 + *
85 + * Whether the current request is a WordPress ajax request.
86 + *
87 + * @since 1.0.0
88 + * @deprecated 2.6.0 Use `wp_doing_ajax()` instead.
89 + * @access public
90 + * @static
91 + *
92 + * @return bool True if it's a WordPress ajax request, false otherwise.
97 93 */
94 + public static function is_ajax() {
95 + _deprecated_function( __METHOD__, '2.6.0', 'wp_doing_ajax()' );
98 96
99 - const ANIMATED_HEADLINE = 'animated_headline';
97 + return wp_doing_ajax();
98 + }
100 99
101 - const CTA = 'cta';
102 -
103 - const VIDEO_PLAYLIST = 'video_playlist';
104 -
105 - const TESTIMONIAL_WIDGET = 'testimonial_widget';
106 -
107 - const IMAGE_CAROUSEL = 'image_carousel';
108 -
109 100 /**
110 - * Whether WordPress CLI mode is enabled or not.
101 + * Is WP CLI.
111 102 *
112 - * @access public
113 - * @static
114 - *
115 103 * @return bool
116 104 */
117 105 public static function is_wp_cli() {
118 106 return defined( 'WP_CLI' ) && WP_CLI;
@@ -118,8 +106,10 @@
118 106 return defined( 'WP_CLI' ) && WP_CLI;
119 107 }
120 108
121 109 /**
110 + * Is script debug.
111 + *
122 112 * Whether script debug is enabled or not.
123 113 *
124 114 * @since 1.0.0
125 115 * @access public
@@ -124,9 +114,9 @@
124 114 * @since 1.0.0
125 115 * @access public
126 116 * @static
127 117 *
128 - * @return bool
118 + * @return bool True if it's a script debug is active, false otherwise.
129 119 */
130 120 public static function is_script_debug() {
131 121 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
132 122 }
@@ -131,32 +121,8 @@
131 121 return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
132 122 }
133 123
134 124 /**
135 - * Whether Elementor debug is enabled or not.
136 - *
137 - * @access public
138 - * @static
139 - *
140 - * @return bool
141 - */
142 - public static function is_elementor_debug() {
143 - return defined( 'ELEMENTOR_DEBUG' ) && ELEMENTOR_DEBUG;
144 - }
145 -
146 - /**
147 - * Whether Elementor test mode is enabled or not.
148 - *
149 - * @access public
150 - * @static
151 - *
152 - * @return bool
153 - */
154 - public static function is_elementor_tests() {
155 - return defined( 'ELEMENTOR_TESTS' ) && ELEMENTOR_TESTS;
156 - }
157 -
158 - /**
159 125 * Get pro link.
160 126 *
161 127 * Retrieve the link to Elementor Pro.
162 128 *
@@ -195,54 +161,38 @@
195 161 * @since 2.1.0
196 162 * @static
197 163 * @access public
198 164 *
199 - * @param string $from
200 - * @param string $to
165 + * @param $from
166 + * @param $to
201 167 *
202 168 * @return string
203 - * @throws \Exception If URLs are missing or invalid URLs provided.
169 + * @throws \Exception
204 170 */
205 171 public static function replace_urls( $from, $to ) {
206 172 $from = trim( $from );
207 173 $to = trim( $to );
208 174
209 - if ( empty( $from ) ) {
210 - throw new \Exception( 'Couldn’t replace your address because the old URL was not provided. Try again by entering the old URL.' );
211 - }
212 -
213 - if ( empty( $to ) ) {
214 - throw new \Exception( 'Couldn’t replace your address because the new URL was not provided. Try again by entering the new URL.' );
215 - }
216 -
217 175 if ( $from === $to ) {
218 - throw new \Exception( 'Couldn’t replace your address because both of the URLs provided are identical. Try again by entering different URLs.' );
176 + throw new \Exception( esc_html__( 'The `from` and `to` URL\'s must be different', 'elementor' ) );
219 177 }
220 178
221 179 $is_valid_urls = ( filter_var( $from, FILTER_VALIDATE_URL ) && filter_var( $to, FILTER_VALIDATE_URL ) );
222 -
223 180 if ( ! $is_valid_urls ) {
224 - throw new \Exception( 'Couldn’t replace your address because at least one of the URLs provided are invalid. Try again by entering valid URLs.' );
181 + throw new \Exception( esc_html__( 'The `from` and `to` URL\'s must be valid URL\'s', 'elementor' ) );
225 182 }
226 183
227 184 global $wpdb;
228 - $escaped_from = str_replace( '/', '\\/', $from );
229 - $escaped_to = str_replace( '/', '\\/', $to );
230 - $meta_value_like = '[%'; // meta_value LIKE '[%' are json formatted
231 185
186 + // @codingStandardsIgnoreStart cannot use `$wpdb->prepare` because it remove's the backslashes
232 187 $rows_affected = $wpdb->query(
233 - $wpdb->prepare(
234 - "UPDATE {$wpdb->postmeta} " .
235 - 'SET `meta_value` = REPLACE(`meta_value`, %s, %s) ' .
236 - "WHERE `meta_key` = '_elementor_data' AND `meta_value` LIKE %s;",
237 - $escaped_from,
238 - $escaped_to,
239 - $meta_value_like
240 - )
241 - );
188 + "UPDATE {$wpdb->postmeta} " .
189 + "SET `meta_value` = REPLACE(`meta_value`, '" . str_replace( '/', '\\\/', $from ) . "', '" . str_replace( '/', '\\\/', $to ) . "') " .
190 + "WHERE `meta_key` = '_elementor_data' AND `meta_value` LIKE '[%' ;" ); // meta_value LIKE '[%' are json formatted
191 + // @codingStandardsIgnoreEnd
242 192
243 193 if ( false === $rows_affected ) {
244 - throw new \Exception( 'An error occurred while replacing URL\'s.' );
194 + throw new \Exception( esc_html__( 'An error occurred', 'elementor' ) );
245 195 }
246 196
247 197 // Allow externals to replace-urls, when they have to.
248 198 $rows_affected += (int) apply_filters( 'elementor/tools/replace-urls', 0, $from, $to );
@@ -247,13 +197,12 @@
247 197 // Allow externals to replace-urls, when they have to.
248 198 $rows_affected += (int) apply_filters( 'elementor/tools/replace-urls', 0, $from, $to );
249 199
250 200 Plugin::$instance->files_manager->clear_cache();
251 - Google_Font::clear_cache();
252 201
253 202 return sprintf(
254 - /* translators: %d: Number of rows. */
255 - _n( '%d database row affected.', '%d database rows affected.', $rows_affected, 'elementor' ),
203 + /* translators: %d: Number of rows */
204 + _n( '%d row affected.', '%d rows affected.', $rows_affected, 'elementor' ),
256 205 $rows_affected
257 206 );
258 207 }
259 208
@@ -280,9 +229,9 @@
280 229 *
281 230 * Filters whether the post type supports editing with Elementor.
282 231 *
283 232 * @since 1.0.0
284 - * @deprecated 2.2.0 Use `elementor/utils/is_post_support` hook Instead.
233 + * @deprecated 2.2.0 Use `elementor/utils/is_post_support` Instead
285 234 *
286 235 * @param bool $is_supported Whether the post type supports editing with Elementor.
287 236 * @param int $post_id Post ID.
288 237 * @param string $post_type Post type.
@@ -399,10 +348,10 @@
399 348 if ( ! defined( 'DONOTCDN' ) ) {
400 349 define( 'DONOTCDN', true );
401 350 }
402 351
403 - if ( ! defined( 'DONOTCACHEOBJECT' ) ) {
404 - define( 'DONOTCACHEOBJECT', true );
352 + if ( ! defined( 'DONOTCACHCEOBJECT' ) ) {
353 + define( 'DONOTCACHCEOBJECT', true );
405 354 }
406 355
407 356 // Set the headers to prevent caching for the different browsers.
408 357 nocache_headers();
@@ -441,12 +390,11 @@
441 390 * Retrieve a custom URL for creating a new post/page using Elementor.
442 391 *
443 392 * @since 1.9.0
444 393 * @access public
445 - * @deprecated 3.3.0 Use `Plugin::$instance->documents->get_create_new_post_url()` instead.
446 394 * @static
447 395 *
448 - * @param string $post_type Optional. Post type slug. Default is 'page'.
396 + * @param string $post_type Optional. Post type slug. Default is 'page'.
449 397 * @param string|null $template_type Optional. Query arg 'template_type'. Default is null.
450 398 *
451 399 * @return string A URL for creating new post using Elementor.
452 400 */
@@ -513,14 +461,14 @@
513 461 * @since 2.1.2
514 462 * @access public
515 463 * @static
516 464 */
517 - public static function array_inject( $base_array, $key, $insert ) {
518 - $length = array_search( $key, array_keys( $base_array ), true ) + 1;
465 + public static function array_inject( $array, $key, $insert ) {
466 + $length = array_search( $key, array_keys( $array ), true ) + 1;
519 467
520 - return array_slice( $base_array, 0, $length, true ) +
468 + return array_slice( $array, 0, $length, true ) +
521 469 $insert +
522 - array_slice( $base_array, $length, null, true );
470 + array_slice( $array, $length, null, true );
523 471 }
524 472
525 473 /**
526 474 * Render html attributes
@@ -558,25 +506,18 @@
558 506 }
559 507
560 508 public static function get_meta_viewport( $context = '' ) {
561 509 $meta_tag = '<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />';
562 -
563 510 /**
564 511 * Viewport meta tag.
565 512 *
566 - * Filters the meta tag containing the viewport information.
513 + * Filters the Elementor preview URL.
567 514 *
568 - * This hook can be used to change the initial viewport meta tag set by Elementor
569 - * and replace it with a different viewport tag.
570 - *
571 515 * @since 2.5.0
572 516 *
573 517 * @param string $meta_tag Viewport meta tag.
574 - * @param string $context Page context.
575 518 */
576 - $meta_tag = apply_filters( 'elementor/template/viewport_tag', $meta_tag, $context );
577 -
578 - return $meta_tag;
519 + return apply_filters( 'elementor/template/viewport_tag', $meta_tag, $context );
579 520 }
580 521
581 522 /**
582 523 * Add Elementor Config js vars to the relevant script handle,
@@ -581,17 +522,16 @@
581 522 /**
582 523 * Add Elementor Config js vars to the relevant script handle,
583 524 * WP will wrap it with <script> tag.
584 525 * To make sure this script runs thru the `script_loader_tag` hook, use a known handle value.
585 - *
586 526 * @param string $handle
587 527 * @param string $js_var
588 - * @param mixed $config
528 + * @param mixed $config
589 529 */
590 530 public static function print_js_config( $handle, $js_var, $config ) {
591 531 $config = wp_json_encode( $config );
592 532
593 - if ( get_option( self::EDITOR_BREAK_LINES_OPTION_KEY ) ) {
533 + if ( get_option( 'elementor_editor_break_lines' ) ) {
594 534 // Add new lines to avoid memory limits in some hosting servers that handles the buffer output according to new line characters
595 535 $config = str_replace( '}},"', '}},' . PHP_EOL . '"', $config );
596 536 }
597 537
@@ -616,9 +556,9 @@
616 556
617 557 /**
618 558 * Checks a control value for being empty, including a string of '0' not covered by PHP's empty().
619 559 *
620 - * @param mixed $source
560 + * @param mixed $source
621 561 * @param bool|string $key
622 562 *
623 563 * @return bool
624 564 */
@@ -637,30 +577,15 @@
637 577 public static function has_pro() {
638 578 return defined( 'ELEMENTOR_PRO_VERSION' );
639 579 }
640 580
641 - public static function is_pro_installed_and_not_active(): bool {
642 - if ( ! function_exists( 'get_plugins' ) ) {
643 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
644 - }
645 -
646 - $file_path = self::get_elementor_pro_file_path();
647 - $installed_plugins = get_plugins();
648 -
649 - return isset( $installed_plugins[ $file_path ] );
650 - }
651 -
652 - private static function get_elementor_pro_file_path(): string {
653 - return 'elementor-pro/elementor-pro.php';
654 - }
655 -
656 581 /**
657 582 * Convert HTMLEntities to UTF-8 characters
658 583 *
659 - * @param string $html_string
584 + * @param $string
660 585 * @return string
661 586 */
662 - public static function urlencode_html_entities( $html_string ) {
587 + public static function urlencode_html_entities( $string ) {
663 588 $entities_dictionary = [
664 589 '&#145;' => "'", // Opening single quote
665 590 '&#146;' => "'", // Closing single quote
666 591 '&#147;' => '"', // Closing double quote
@@ -673,11 +598,11 @@
673 598 '&#8222;' => '"', // Double low quote
674 599 ];
675 600
676 601 // Decode decimal entities
677 - $html_string = str_replace( array_keys( $entities_dictionary ), array_values( $entities_dictionary ), $html_string );
602 + $string = str_replace( array_keys( $entities_dictionary ), array_values( $entities_dictionary ), $string );
678 603
679 - return rawurlencode( html_entity_decode( $html_string, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) );
604 + return rawurlencode( html_entity_decode( $string, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) );
680 605 }
681 606
682 607 /**
683 608 * Parse attributes that come as a string of comma-delimited key|value pairs.
@@ -750,10 +675,10 @@
750 675 * Fired by `admin_menu` action.
751 676 *
752 677 * @since 3.1.0
753 678 *
754 - * @param string $menu_slug
755 - * @param string $new_label
679 + * @param $menu_slug
680 + * @param $new_label
756 681 * @access public
757 682 */
758 683 public static function change_submenu_first_item_label( $menu_slug, $new_label ) {
759 684 global $submenu;
@@ -772,9 +697,9 @@
772 697 *
773 698 * @return string
774 699 */
775 700 public static function validate_html_tag( $tag ) {
776 - return $tag && in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS ) ? $tag : 'div';
701 + return in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS ) ? $tag : 'div';
777 702 }
778 703
779 704 /**
780 705 * Safe print a validated HTML tag.
@@ -788,10 +713,10 @@
788 713
789 714 /**
790 715 * Print internal content (not user input) without escaping.
791 716 */
792 - public static function print_unescaped_internal_string( $internal_string ) {
793 - echo $internal_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
717 + public static function print_unescaped_internal_string( $string ) {
718 + echo $string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
794 719 }
795 720
796 721 /**
797 722 * Get recently edited posts query.
@@ -804,9 +729,8 @@
804 729 * @return \WP_Query
805 730 */
806 731 public static function get_recently_edited_posts_query( $args = [] ) {
807 732 $args = wp_parse_args( $args, [
808 - 'no_found_rows' => true,
809 733 'post_type' => 'any',
810 734 'post_status' => [ 'publish', 'draft' ],
811 735 'posts_per_page' => '3',
812 736 'meta_key' => '_elementor_edit_mode',
@@ -816,161 +740,19 @@
816 740
817 741 return new \WP_Query( $args );
818 742 }
819 743
820 - public static function print_wp_kses_extended( $text, array $tags ) {
744 + public static function print_wp_kses_extended( string $string, array $tags ) {
821 745 $allowed_html = wp_kses_allowed_html( 'post' );
746 + // Since PHP 5.6 cannot use isset() on the result of an expression.
747 + $extended_allowed_html_tags = self::EXTENDED_ALLOWED_HTML_TAGS;
822 748
823 749 foreach ( $tags as $tag ) {
824 - if ( isset( self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] ) ) {
750 + if ( isset( $extended_allowed_html_tags[ $tag ] ) ) {
825 751 $extended_tags = apply_filters( "elementor/extended_allowed_html_tags/{$tag}", self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] );
826 - $allowed_html = array_replace_recursive( $allowed_html, $extended_tags );
752 + $allowed_html = array_merge( $allowed_html, $extended_tags );
827 753 }
828 754 }
829 755
830 - echo wp_kses( $text, $allowed_html );
831 - }
832 -
833 - public static function is_elementor_path( $path ) {
834 - $path = wp_normalize_path( $path );
835 -
836 - /**
837 - * Elementor related paths.
838 - *
839 - * Filters Elementor related paths.
840 - *
841 - * @param string[] $available_paths
842 - */
843 - $available_paths = apply_filters( 'elementor/utils/elementor_related_paths', [ ELEMENTOR_PATH ] );
844 -
845 - return (bool) ( new Collection( $available_paths ) )
846 - ->map( function ( $p ) {
847 - // `untrailingslashit` in order to include other plugins prefixed with elementor.
848 - return untrailingslashit( wp_normalize_path( $p ) );
849 - } )
850 - ->find(function ( $p ) use ( $path ) {
851 - return false !== strpos( $path, $p );
852 - } );
853 - }
854 -
855 - /**
856 - * @param string $file
857 - * @param mixed ...$args
858 - * @return false|string
859 - */
860 - public static function file_get_contents( $file, ...$args ) {
861 - if ( ! is_file( $file ) || ! is_readable( $file ) ) {
862 - return false;
863 - }
864 - return file_get_contents( $file, ...$args );
865 - }
866 -
867 - public static function get_super_global_value( $super_global, $key ) {
868 - if ( ! isset( $super_global[ $key ] ) ) {
869 - return null;
870 - }
871 -
872 - if ( $_FILES === $super_global ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
873 - return isset( $super_global[ $key ]['name'] ) ?
874 - self::sanitize_file_name( $super_global[ $key ] ) :
875 - self::sanitize_multi_upload( $super_global[ $key ] );
876 - }
877 -
878 - return wp_kses_post_deep( wp_unslash( $super_global[ $key ] ) );
879 - }
880 -
881 - private static function sanitize_multi_upload( $fields ) {
882 - return array_map( function( $field ) {
883 - return array_map( 'self::sanitize_file_name', $field );
884 - }, $fields );
885 - }
886 -
887 - private static function sanitize_file_name( $file ) {
888 - $file['name'] = sanitize_file_name( $file['name'] );
889 -
890 - return $file;
891 - }
892 -
893 - /**
894 - * Return specific object property value if exist from array of keys.
895 - *
896 - * @param array $base_array
897 - * @param array $keys
898 - * @return mixed|null
899 - */
900 - public static function get_array_value_by_keys( $base_array, $keys ) {
901 - $keys = (array) $keys;
902 - foreach ( $keys as $key ) {
903 - if ( ! isset( $base_array[ $key ] ) ) {
904 - return null;
905 - }
906 - $base_array = $base_array[ $key ];
907 - }
908 - return $base_array;
909 - }
910 -
911 - public static function get_cached_callback( $callback, $cache_key, $cache_time = 24 * HOUR_IN_SECONDS ) {
912 - $cache = get_site_transient( $cache_key );
913 -
914 - if ( ! $cache ) {
915 - $cache = call_user_func( $callback );
916 -
917 - if ( ! is_wp_error( $cache ) ) {
918 - set_site_transient( $cache_key, $cache, $cache_time );
919 - }
920 - }
921 -
922 - return $cache;
923 - }
924 -
925 - public static function is_sale_time(): bool {
926 - $sale_start_time = gmmktime( 12, 0, 0, 11, 25, 2025 );
927 - $sale_end_time = gmmktime( 3, 59, 0, 12, 3, 2025 );
928 -
929 - $now_time = gmdate( 'U' );
930 -
931 - return $now_time >= $sale_start_time && $now_time <= $sale_end_time;
932 - }
933 -
934 - public static function safe_throw( string $message ) {
935 - if ( ! static::is_elementor_debug() ) {
936 - return;
937 - }
938 -
939 - throw new \Exception( esc_html( $message ) );
940 - }
941 -
942 - public static function has_invalid_post_permissions( $post ): bool {
943 - $is_image_attachment = 'attachment' === $post->post_type && strpos( $post->post_mime_type, 'image/' ) === 0;
944 -
945 - if ( $is_image_attachment ) {
946 - return false;
947 - }
948 -
949 - $is_private = 'private' === $post->post_status
950 - && ! current_user_can( 'read_private_posts', $post->ID );
951 -
952 - $not_allowed = 'publish' !== $post->post_status
953 - && ! current_user_can( 'edit_post', $post->ID );
954 -
955 - $password_required = post_password_required( $post->ID )
956 - && ! current_user_can( 'edit_post', $post->ID );
957 -
958 - return $is_private || $not_allowed || $password_required;
959 - }
960 -
961 - public static function is_custom_kit_applied() {
962 - return (bool) Plugin::$instance->kits_manager->get_previous_id();
963 - }
964 -
965 - public static function decode_string( string $encoded_string, ?string $fallback = '' ) {
966 - try {
967 - return base64_decode( $encoded_string, true ) ?? $fallback;
968 - } catch ( \Exception $e ) {
969 - return $fallback;
970 - }
971 - }
972 -
973 - public static function encode_string( string $decoded_string ): string {
974 - return base64_encode( $decoded_string );
756 + echo wp_kses( $string, $allowed_html );
975 757 }
976 758 }