/ Opening single quote '’' => "'", // Closing single quote '“' => '"', // Closing double quote '”' => '"', // Opening double quote '‘' => "'", // Closing single quote '’' => "'", // Opening single quote '‚' => "'", // Single low quote '“' => '"', // Closing double quote '”' => '"', // Opening double quote '„' => '"', // Double low quote ]; // Decode decimal entities $html_string = str_replace( array_keys( $entities_dictionary ), array_values( $entities_dictionary ), $html_string ); return rawurlencode( html_entity_decode( $html_string, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) ); } /** * Parse attributes that come as a string of comma-delimited key|value pairs. * Removes Javascript events and unescaped `href` attributes. * * @param string $attributes_string * * @param string $delimiter Default comma `,`. * * @return array */ public static function parse_custom_attributes( $attributes_string, $delimiter = ',' ) { $attributes = explode( $delimiter, $attributes_string ); $result = []; foreach ( $attributes as $attribute ) { $attr_key_value = explode( '|', $attribute ); $attr_key = mb_strtolower( $attr_key_value[0] ); // Remove any not allowed characters. preg_match( '/[-_a-z0-9]+/', $attr_key, $attr_key_matches ); if ( empty( $attr_key_matches[0] ) ) { continue; } $attr_key = $attr_key_matches[0]; // Avoid Javascript events and unescaped href. if ( 'href' === $attr_key || 'on' === substr( $attr_key, 0, 2 ) ) { continue; } if ( isset( $attr_key_value[1] ) ) { $attr_value = trim( $attr_key_value[1] ); } else { $attr_value = ''; } $result[ $attr_key ] = $attr_value; } return $result; } public static function find_element_recursive( $elements, $id ) { foreach ( $elements as $element ) { if ( $id === $element['id'] ) { return $element; } if ( ! empty( $element['elements'] ) ) { $element = self::find_element_recursive( $element['elements'], $id ); if ( $element ) { return $element; } } } return false; } /** * Change Submenu First Item Label * * Overwrite the label of the first submenu item of an admin menu item. * * Fired by `admin_menu` action. * * @since 3.1.0 * * @param string $menu_slug * @param string $new_label * @access public */ public static function change_submenu_first_item_label( $menu_slug, $new_label ) { global $submenu; if ( isset( $submenu[ $menu_slug ] ) ) { // @codingStandardsIgnoreStart $submenu[ $menu_slug ][0][0] = $new_label; // @codingStandardsIgnoreEnd } } /** * Validate an HTML tag against a safe allowed list. * * @param string $tag * * @return string */ public static function validate_html_tag( $tag ) { return $tag && in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS ) ? $tag : 'div'; } /** * Safe print a validated HTML tag. * * @param string $tag */ public static function print_validated_html_tag( $tag ) { // PHPCS - the method validate_html_tag is safe. echo self::validate_html_tag( $tag ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Print internal content (not user input) without escaping. */ public static function print_unescaped_internal_string( $internal_string ) { echo $internal_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get recently edited posts query. * * Returns `WP_Query` of the recent edited posts. * By default max posts ( $args['posts_per_page'] ) is 3. * * @param array $args * * @return \WP_Query */ public static function get_recently_edited_posts_query( $args = [] ) { $args = wp_parse_args( $args, [ 'no_found_rows' => true, 'post_type' => 'any', 'post_status' => [ 'publish', 'draft' ], 'posts_per_page' => '3', 'meta_key' => '_elementor_edit_mode', 'meta_value' => 'builder', 'orderby' => 'modified', ] ); return new \WP_Query( $args ); } public static function print_wp_kses_extended( $text, array $tags ) { $allowed_html = wp_kses_allowed_html( 'post' ); foreach ( $tags as $tag ) { if ( isset( self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] ) ) { $extended_tags = apply_filters( "elementor/extended_allowed_html_tags/{$tag}", self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] ); $allowed_html = array_replace_recursive( $allowed_html, $extended_tags ); } } echo wp_kses( $text, $allowed_html ); } public static function is_elementor_path( $path ) { $path = wp_normalize_path( $path ); /** * Elementor related paths. * * Filters Elementor related paths. * * @param string[] $available_paths */ $available_paths = apply_filters( 'elementor/utils/elementor_related_paths', [ ELEMENTOR_PATH ] ); return (bool) ( new Collection( $available_paths ) ) ->map( function ( $p ) { // `untrailingslashit` in order to include other plugins prefixed with elementor. return untrailingslashit( wp_normalize_path( $p ) ); } ) ->find(function ( $p ) use ( $path ) { return false !== strpos( $path, $p ); } ); } /** * @param string $file * @param mixed ...$args * @return false|string */ public static function file_get_contents( $file, ...$args ) { if ( ! is_file( $file ) || ! is_readable( $file ) ) { return false; } return file_get_contents( $file, ...$args ); } public static function get_super_global_value( $super_global, $key ) { if ( ! isset( $super_global[ $key ] ) ) { return null; } if ( $_FILES === $super_global ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return isset( $super_global[ $key ]['name'] ) ? self::sanitize_file_name( $super_global[ $key ] ) : self::sanitize_multi_upload( $super_global[ $key ] ); } return wp_kses_post_deep( wp_unslash( $super_global[ $key ] ) ); } private static function sanitize_multi_upload( $fields ) { return array_map( function( $field ) { return array_map( 'self::sanitize_file_name', $field ); }, $fields ); } private static function sanitize_file_name( $file ) { $file['name'] = sanitize_file_name( $file['name'] ); return $file; } /** * Return specific object property value if exist from array of keys. * * @param array $base_array * @param array $keys * @return mixed|null */ public static function get_array_value_by_keys( $base_array, $keys ) { $keys = (array) $keys; foreach ( $keys as $key ) { if ( ! isset( $base_array[ $key ] ) ) { return null; } $base_array = $base_array[ $key ]; } return $base_array; } public static function get_cached_callback( $callback, $cache_key, $cache_time = 24 * HOUR_IN_SECONDS ) { $cache = get_site_transient( $cache_key ); if ( ! $cache ) { $cache = call_user_func( $callback ); if ( ! is_wp_error( $cache ) ) { set_site_transient( $cache_key, $cache, $cache_time ); } } return $cache; } public static function is_sale_time(): bool { $sale_start_time = gmmktime( 12, 0, 0, 11, 25, 2025 ); $sale_end_time = gmmktime( 3, 59, 0, 12, 3, 2025 ); $now_time = gmdate( 'U' ); return $now_time >= $sale_start_time && $now_time <= $sale_end_time; } public static function safe_throw( string $message ) { if ( ! static::is_elementor_debug() ) { return; } throw new \Exception( esc_html( $message ) ); } public static function has_invalid_post_permissions( $post ): bool { $is_image_attachment = 'attachment' === $post->post_type && strpos( $post->post_mime_type, 'image/' ) === 0; if ( $is_image_attachment ) { return false; } $is_private = 'private' === $post->post_status && ! current_user_can( 'read_private_posts', $post->ID ); $not_allowed = 'publish' !== $post->post_status && ! current_user_can( 'edit_post', $post->ID ); $password_required = post_password_required( $post->ID ) && ! current_user_can( 'edit_post', $post->ID ); return $is_private || $not_allowed || $password_required; } public static function is_custom_kit_applied() { return (bool) Plugin::$instance->kits_manager->get_previous_id(); } public static function decode_string( string $encoded_string, ?string $fallback = '' ) { try { return base64_decode( $encoded_string, true ) ?? $fallback; } catch ( \Exception $e ) { return $fallback; } } public static function encode_string( string $decoded_string ): string { return base64_encode( $decoded_string ); } } / Opening single quote '’' => "'", // Closing single quote '“' => '"', // Closing double quote '”' => '"', // Opening double quote '‘' => "'", // Closing single quote '’' => "'", // Opening single quote '‚' => "'", // Single low quote '“' => '"', // Closing double quote '”' => '"', // Opening double quote '„' => '"', // Double low quote ]; // Decode decimal entities $html_string = str_replace( array_keys( $entities_dictionary ), array_values( $entities_dictionary ), $html_string ); return rawurlencode( html_entity_decode( $html_string, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) ); } /** * Parse attributes that come as a string of comma-delimited key|value pairs. * Removes Javascript events and unescaped `href` attributes. * * @param string $attributes_string * * @param string $delimiter Default comma `,`. * * @return array */ public static function parse_custom_attributes( $attributes_string, $delimiter = ',' ) { $attributes = explode( $delimiter, $attributes_string ); $result = []; foreach ( $attributes as $attribute ) { $attr_key_value = explode( '|', $attribute ); $attr_key = mb_strtolower( $attr_key_value[0] ); // Remove any not allowed characters. preg_match( '/[-_a-z0-9]+/', $attr_key, $attr_key_matches ); if ( empty( $attr_key_matches[0] ) ) { continue; } $attr_key = $attr_key_matches[0]; // Avoid Javascript events and unescaped href. if ( 'href' === $attr_key || 'on' === substr( $attr_key, 0, 2 ) ) { continue; } if ( isset( $attr_key_value[1] ) ) { $attr_value = trim( $attr_key_value[1] ); } else { $attr_value = ''; } $result[ $attr_key ] = $attr_value; } return $result; } public static function find_element_recursive( $elements, $id ) { foreach ( $elements as $element ) { if ( $id === $element['id'] ) { return $element; } if ( ! empty( $element['elements'] ) ) { $element = self::find_element_recursive( $element['elements'], $id ); if ( $element ) { return $element; } } } return false; } /** * Change Submenu First Item Label * * Overwrite the label of the first submenu item of an admin menu item. * * Fired by `admin_menu` action. * * @since 3.1.0 * * @param string $menu_slug * @param string $new_label * @access public */ public static function change_submenu_first_item_label( $menu_slug, $new_label ) { global $submenu; if ( isset( $submenu[ $menu_slug ] ) ) { // @codingStandardsIgnoreStart $submenu[ $menu_slug ][0][0] = $new_label; // @codingStandardsIgnoreEnd } } /** * Validate an HTML tag against a safe allowed list. * * @param string $tag * * @return string */ public static function validate_html_tag( $tag ) { return $tag && in_array( strtolower( $tag ), self::ALLOWED_HTML_WRAPPER_TAGS ) ? $tag : 'div'; } /** * Safe print a validated HTML tag. * * @param string $tag */ public static function print_validated_html_tag( $tag ) { // PHPCS - the method validate_html_tag is safe. echo self::validate_html_tag( $tag ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Print internal content (not user input) without escaping. */ public static function print_unescaped_internal_string( $internal_string ) { echo $internal_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get recently edited posts query. * * Returns `WP_Query` of the recent edited posts. * By default max posts ( $args['posts_per_page'] ) is 3. * * @param array $args * * @return \WP_Query */ public static function get_recently_edited_posts_query( $args = [] ) { $args = wp_parse_args( $args, [ 'no_found_rows' => true, 'post_type' => 'any', 'post_status' => [ 'publish', 'draft' ], 'posts_per_page' => '3', 'meta_key' => '_elementor_edit_mode', 'meta_value' => 'builder', 'orderby' => 'modified', ] ); return new \WP_Query( $args ); } public static function print_wp_kses_extended( $text, array $tags ) { $allowed_html = wp_kses_allowed_html( 'post' ); foreach ( $tags as $tag ) { if ( isset( self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] ) ) { $extended_tags = apply_filters( "elementor/extended_allowed_html_tags/{$tag}", self::EXTENDED_ALLOWED_HTML_TAGS[ $tag ] ); $allowed_html = array_replace_recursive( $allowed_html, $extended_tags ); } } echo wp_kses( $text, $allowed_html ); } public static function is_elementor_path( $path ) { $path = wp_normalize_path( $path ); /** * Elementor related paths. * * Filters Elementor related paths. * * @param string[] $available_paths */ $available_paths = apply_filters( 'elementor/utils/elementor_related_paths', [ ELEMENTOR_PATH ] ); return (bool) ( new Collection( $available_paths ) ) ->map( function ( $p ) { // `untrailingslashit` in order to include other plugins prefixed with elementor. return untrailingslashit( wp_normalize_path( $p ) ); } ) ->find(function ( $p ) use ( $path ) { return false !== strpos( $path, $p ); } ); } /** * @param string $file * @param mixed ...$args * @return false|string */ public static function file_get_contents( $file, ...$args ) { if ( ! is_file( $file ) || ! is_readable( $file ) ) { return false; } return file_get_contents( $file, ...$args ); } public static function get_super_global_value( $super_global, $key ) { if ( ! isset( $super_global[ $key ] ) ) { return null; } if ( $_FILES === $super_global ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return isset( $super_global[ $key ]['name'] ) ? self::sanitize_file_name( $super_global[ $key ] ) : self::sanitize_multi_upload( $super_global[ $key ] ); } return wp_kses_post_deep( wp_unslash( $super_global[ $key ] ) ); } private static function sanitize_multi_upload( $fields ) { return array_map( function( $field ) { return array_map( 'self::sanitize_file_name', $field ); }, $fields ); } private static function sanitize_file_name( $file ) { $file['name'] = sanitize_file_name( $file['name'] ); return $file; } /** * Return specific object property value if exist from array of keys. * * @param array $base_array * @param array $keys * @return mixed|null */ public static function get_array_value_by_keys( $base_array, $keys ) { $keys = (array) $keys; foreach ( $keys as $key ) { if ( ! isset( $base_array[ $key ] ) ) { return null; } $base_array = $base_array[ $key ]; } return $base_array; } public static function get_cached_callback( $callback, $cache_key, $cache_time = 24 * HOUR_IN_SECONDS ) { $cache = get_site_transient( $cache_key ); if ( ! $cache ) { $cache = call_user_func( $callback ); if ( ! is_wp_error( $cache ) ) { set_site_transient( $cache_key, $cache, $cache_time ); } } return $cache; } public static function is_sale_time(): bool { $sale_start_time = gmmktime( 12, 0, 0, 11, 25, 2025 ); $sale_end_time = gmmktime( 3, 59, 0, 12, 3, 2025 ); $now_time = gmdate( 'U' ); return $now_time >= $sale_start_time && $now_time <= $sale_end_time; } public static function safe_throw( string $message ) { if ( ! static::is_elementor_debug() ) { return; } throw new \Exception( esc_html( $message ) ); } public static function has_invalid_post_permissions( $post ): bool { $is_image_attachment = 'attachment' === $post->post_type && strpos( $post->post_mime_type, 'image/' ) === 0; if ( $is_image_attachment ) { return false; } $is_private = 'private' === $post->post_status && ! current_user_can( 'read_private_posts', $post->ID ); $not_allowed = 'publish' !== $post->post_status && ! current_user_can( 'edit_post', $post->ID ); $password_required = post_password_required( $post->ID ) && ! current_user_can( 'edit_post', $post->ID ); return $is_private || $not_allowed || $password_required; } public static function is_custom_kit_applied() { return (bool) Plugin::$instance->kits_manager->get_previous_id(); } public static function decode_string( string $encoded_string, ?string $fallback = '' ) { try { return base64_decode( $encoded_string, true ) ?? $fallback; } catch ( \Exception $e ) { return $fallback; } } public static function encode_string( string $decoded_string ): string { return base64_encode( $decoded_string ); } }