ey_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 $menu_slug * @param $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( $string ) { echo $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( $string, 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( $string, $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 $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 ) { 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 * @param $keys * @return key|false */ public static function get_array_value_by_keys( $array, $keys ) { $keys = (array) $keys; foreach ( $keys as $key ) { if ( ! isset( $array[ $key ] ) ) { return null; } $array = $array[ $key ]; } return $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; } } ey_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 $menu_slug * @param $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( $string ) { echo $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( $string, 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( $string, $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 $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 ) { 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 * @param $keys * @return key|false */ public static function get_array_value_by_keys( $array, $keys ) { $keys = (array) $keys; foreach ( $keys as $key ) { if ( ! isset( $array[ $key ] ) ) { return null; } $array = $array[ $key ]; } return $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; } }