turn self::$global_styles_presets; } /** * Scrape all block names from global styles and store in self::$global_styles_block_names. * * Used in conjunction with self::render_duotone_support to output the * duotone filters defined in the theme.json global styles. * * @since 6.3.0 * * @return string[] An array of global style block slugs, keyed on the block name. */ private static function get_all_global_style_block_names() { if ( isset( self::$global_styles_block_names ) ) { return self::$global_styles_block_names; } // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); $theme_json = $tree->get_raw_data(); self::$global_styles_block_names = array(); foreach ( $block_nodes as $block_node ) { // This block definition doesn't include any duotone settings. Skip it. if ( empty( $block_node['duotone'] ) ) { continue; } // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' or 'var:preset|duotone|blue-orange'. $duotone_attr_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); $duotone_attr = _wp_array_get( $theme_json, $duotone_attr_path, array() ); if ( empty( $duotone_attr ) ) { continue; } // If it has a duotone filter preset, save the block name and the preset slug. $slug = self::get_slug_from_attribute( $duotone_attr ); if ( $slug && $slug !== $duotone_attr ) { self::$global_styles_block_names[ $block_node['name'] ] = $slug; } } return self::$global_styles_block_names; } /** * Render out the duotone CSS styles and SVG. * * The hooks self::set_global_style_block_names and self::set_global_styles_presets * must be called before this function. * * @since 6.3.0 * * @param string $block_content Rendered block content. * @param array $block Block object. * @param WP_Block $wp_block The block instance. * @return string Filtered block content. */ public static function render_duotone_support( $block_content, $block, $wp_block ) { if ( ! $block['blockName'] ) { return $block_content; } $duotone_selector = self::get_selector( $wp_block->block_type ); if ( ! $duotone_selector ) { return $block_content; } $global_styles_block_names = self::get_all_global_style_block_names(); // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); $has_global_styles_duotone = array_key_exists( $block['blockName'], $global_styles_block_names ); if ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) { return $block_content; } // Generate the pieces needed for rendering a duotone to the page. if ( $has_duotone_attribute ) { /* * Possible values for duotone attribute: * 1. Array of colors - e.g. array('#000000', '#ffffff'). * 2. Variable for an existing Duotone preset - e.g. 'var:preset|duotone|blue-orange' or 'var(--wp--preset--duotone--blue-orange)'' * 3. A CSS string - e.g. 'unset' to remove globally applied duotone. */ $duotone_attr = $block['attrs']['style']['color']['duotone']; $is_preset = is_string( $duotone_attr ) && self::is_preset( $duotone_attr ); $is_css = is_string( $duotone_attr ) && ! $is_preset; $is_custom = is_array( $duotone_attr ); if ( $is_preset ) { $slug = self::get_slug_from_attribute( $duotone_attr ); // e.g. 'blue-orange'. $filter_id = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-blue-orange'. $filter_value = self::get_css_var( $slug ); // e.g. 'var(--wp--preset--duotone--blue-orange)'. // CSS custom property, SVG filter, and block CSS. self::enqueue_global_styles_preset( $filter_id, $duotone_selector, $filter_value ); } elseif ( $is_css ) { $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); // e.g. 'unset-1'. $filter_id = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-unset-1'. $filter_value = $duotone_attr; // e.g. 'unset'. // Just block CSS. self::enqueue_block_css( $filter_id, $duotone_selector, $filter_value ); } elseif ( $is_custom ) { $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); // e.g. '000000-ffffff-2'. $filter_id = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-000000-ffffff-2'. $filter_value = self::get_filter_url( $filter_id ); // e.g. 'url(#wp-duotone-filter-000000-ffffff-2)'. $filter_data = array( 'slug' => $slug, 'colors' => $duotone_attr, ); // SVG filter and block CSS. self::enqueue_custom_filter( $filter_id, $duotone_selector, $filter_value, $filter_data ); } } elseif ( $has_global_styles_duotone ) { $slug = $global_styles_block_names[ $block['blockName'] ]; // e.g. 'blue-orange'. $filter_id = self::get_filter_id( $slug ); // e.g. 'wp-duotone-filter-blue-orange'. $filter_value = self::get_css_var( $slug ); // e.g. 'var(--wp--preset--duotone--blue-orange)'. // CSS custom property, SVG filter, and block CSS. self::enqueue_global_styles_preset( $filter_id, $duotone_selector, $filter_value ); } // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. $tags = new WP_HTML_Tag_Processor( $block_content ); if ( $tags->next_tag() ) { $tags->add_class( $filter_id ); } return $tags->get_updated_html(); } /** * Appends the used block duotone filter declarations to the inline block supports CSS. * * Uses the declarations saved in earlier calls to self::enqueue_block_css. * * @since 6.3.0 */ public static function output_block_styles() { if ( ! empty( self::$block_css_declarations ) ) { wp_style_engine_get_stylesheet_from_css_rules( self::$block_css_declarations, array( 'context' => 'block-supports', ) ); } } /** * Appends the used global style duotone filter presets (CSS custom * properties) to the inline global styles CSS. * * Uses the declarations saved in earlier calls to self::enqueue_global_styles_preset. * * @since 6.3.0 */ public static function output_global_styles() { if ( ! empty( self::$used_global_styles_presets ) ) { wp_add_inline_style( 'global-styles', self::get_global_styles_presets( self::$used_global_styles_presets ) ); } } /** * Outputs all necessary SVG for duotone filters, CSS for classic themes. * * Uses the declarations saved in earlier calls to self::enqueue_global_styles_preset * and self::enqueue_custom_filter. * * @since 6.3.0 */ public static function output_footer_assets() { if ( ! empty( self::$used_svg_filter_data ) ) { echo self::get_svg_definitions( self::$used_svg_filter_data ); } // In block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. if ( ! wp_is_block_theme() ) { $style_tag_id = 'core-block-supports-duotone'; wp_register_style( $style_tag_id, false ); if ( ! empty( self::$used_global_styles_presets ) ) { wp_add_inline_style( $style_tag_id, self::get_global_styles_presets( self::$used_global_styles_presets ) ); } if ( ! empty( self::$block_css_declarations ) ) { wp_add_inline_style( $style_tag_id, wp_style_engine_get_stylesheet_from_css_rules( self::$block_css_declarations ) ); } wp_enqueue_style( $style_tag_id ); } } /** * Adds the duotone SVGs and CSS custom properties to the editor settings. * * This allows the properties to be pulled in by the EditorStyles component * in JS and rendered in the post editor. * * @since 6.3.0 * * @param array $settings The block editor settings from the `block_editor_settings_all` filter. * @return array The editor settings with duotone SVGs and CSS custom properties. */ public static function add_editor_settings( $settings ) { $global_styles_presets = self::get_all_global_styles_presets(); if ( ! empty( $global_styles_presets ) ) { if ( ! isset( $settings['styles'] ) ) { $settings['styles'] = array(); } $settings['styles'][] = array( // For the editor we can add all of the presets by default. 'assets' => self::get_svg_definitions( $global_styles_presets ), // The 'svgs' type is new in 6.3 and requires the corresponding JS changes in the EditorStyles component to work. '__unstableType' => 'svgs', // These styles not generated by global styles, so this must be false or they will be stripped out in wp_get_block_editor_settings. 'isGlobalStyles' => false, ); $settings['styles'][] = array( // For the editor we can add all of the presets by default. 'css' => self::get_global_styles_presets( $global_styles_presets ), // This must be set and must be something other than 'theme' or they will be stripped out in the post editor component. '__unstableType' => 'presets', // These styles are no longer generated by global styles, so this must be false or they will be stripped out in wp_get_block_editor_settings. 'isGlobalStyles' => false, ); } return $settings; } /** * Migrates the experimental duotone support flag to the stabilized location. * * This moves `supports.color.__experimentalDuotone` to `supports.filter.duotone`. * * @since 6.3.0 * * @param array $settings Current block type settings. * @param array $metadata Block metadata as read in via block.json. * @return array Filtered block type settings. */ public static function migrate_experimental_duotone_support_flag( $settings, $metadata ) { $duotone_support = isset( $metadata['supports']['color']['__experimentalDuotone'] ) ? $metadata['supports']['color']['__experimentalDuotone'] : null; if ( ! isset( $settings['supports']['filter']['duotone'] ) && null !== $duotone_support ) { _wp_array_set( $settings, array( 'supports', 'filter', 'duotone' ), (bool) $duotone_support ); } return $settings; } /** * Gets the CSS filter property value from a preset. * * Exported for the deprecated function wp_get_duotone_filter_id(). * * @internal * * @since 6.3.0 * @deprecated 6.3.0 * * @param array $preset The duotone preset. * @return string The CSS filter property value. */ public static function get_filter_css_property_value_from_preset( $preset ) { _deprecated_function( __FUNCTION__, '6.3.0' ); if ( isset( $preset['colors'] ) && is_string( $preset['colors'] ) ) { return $preset['colors']; } $filter_id = self::get_filter_id_from_preset( $preset ); return 'url(#' . $filter_id . ')'; } } || 'php' === $ext ) { return $url; } $filter = current_filter(); $rejected_files = get_rocket_cdn_reject_files(); if ( 'template_directory_uri' === $filter && ! empty( $rejected_files ) ) { return $url; } switch ( $filter ) { case 'wp_get_attachment_url': case 'wp_calculate_image_srcset': $zone = array( 'all', 'images' ); break; case 'smilies_src': $zone = array( 'all', 'images' ); break; case 'stylesheet_uri': case 'wp_minify_css_url': case 'wp_minify_js_url': case 'bwp_get_minify_src': $zone = array( 'all', 'css_and_js', $ext ); break; default: $zone = array( 'all', $ext ); break; } $cnames = get_rocket_cdn_cnames( $zone ); if ( $cnames ) { $url = get_rocket_cdn_url( $url, $zone ); } return $url; } /** * Replace URL by CDN of images displayed using wp_get_attachment_image_src * * @since 2.9.2 * @deprecated 3.4 * @author Remy Perona * @source https://github.com/wp-media/wp-rocket/issues/271#issuecomment-269849927 * * @param array $image An array containing the src, width and height of the image. * @return array Array with updated src URL */ function rocket_cdn_attachment_image_src( $image ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $image; } if ( ! (bool) $image ) { return $image; } if ( is_admin() || is_preview() || is_feed() ) { return $image; } $zones = array( 'all', 'images' ); if ( ! (bool) get_rocket_cdn_cnames( $zones ) ) { return $image; } $image[0] = get_rocket_cdn_url( $image[0], $zones ); return $image; } /** * Replace srcset URLs by CDN URLs for WP responsive images * * @since WP 4.4 * @since 2.6.14 * @deprecated 3.4 * @author Remy Perona * * @param array $sources multidimensional array containing srcset images urls. * @return array $sources */ function rocket_add_cdn_on_srcset( $sources ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $sources; } if ( (bool) $sources ) { foreach ( $sources as $width => $data ) { $sources[ $width ]['url'] = rocket_cdn_file( $data['url'] ); } } return $sources; } /** * Replace URL by CDN of all images display in a post content or a widget text. * * @since 2.1 * @deprecated 3.4 * * @param string $html HTML content to parse. * @return string modified HTML content */ function rocket_cdn_images( $html ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); // Don't use CDN if the image is in admin, a feed or in a post preview. if ( is_admin() || is_feed() || is_preview() || empty( $html ) || defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $html; } $zone = array( 'all', 'images' ); $cnames = get_rocket_cdn_cnames( $zone ); if ( $cnames ) { $cnames = array_flip( $cnames ); $wp_content_dirname = wp_parse_url( content_url(), PHP_URL_PATH ); $custom_media_uploads_dirname = ''; $uploads_info = wp_upload_dir(); if ( ! empty( $uploads_info['baseurl'] ) ) { $custom_media_uploads_dirname = '|' . trailingslashit( wp_parse_url( $uploads_info['baseurl'], PHP_URL_PATH ) ); } // Get all images of the content. preg_match_all( '#]+?)src=([\'"\\\]*)([^\'"\s\\\>]+)([\'"\\\]*)([^>]*)>#i', $html, $images_match ); foreach ( $images_match[3] as $k => $image_url ) { $parse_url = get_rocket_parse_url( $image_url ); $path = trim( $parse_url['path'] ); $host = $parse_url['host']; if ( empty( $path ) || ! preg_match( '#(' . $wp_content_dirname . $custom_media_uploads_dirname . '|wp-includes)#', $path ) ) { continue; } if ( isset( $cnames[ $host ] ) ) { continue; } // Image path is relative, apply the host to it. if ( empty( $host ) ) { $image_url = home_url( '/' ) . ltrim( $image_url, '/' ); $host = rocket_extract_url_component( $image_url, PHP_URL_HOST ); } // Check if the link isn't external. if ( rocket_extract_url_component( home_url(), PHP_URL_HOST ) !== $host ) { continue; } // Check if the URL isn't a DATA-URI. if ( false !== strpos( $image_url, 'data:image' ) ) { continue; } $html = str_replace( $images_match[0][ $k ], /** * Filter the image HTML output with the CDN link * * @since 2.5.5 * * @param array $html Output that will be printed. */ apply_filters( 'rocket_cdn_images_html', sprintf( '', trim( $images_match[1][ $k ] ), 'src=' . $images_match[2][ $k ] . get_rocket_cdn_url( $image_url, $zone ) . $images_match[4][ $k ], trim( $images_match[5][ $k ] ) ) ), $html ); } } return $html; } /** * Replace URL by CDN of all inline styles containing url() * * @since 2.9 * @deprecated 3.4 * @author Remy Perona * * @param string $html HTML content of the page. * @return string modified HTML content */ function rocket_cdn_inline_styles( $html ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( is_preview() || empty( $html ) || defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $html; } $zone = array( 'all', 'images', ); $cnames = get_rocket_cdn_cnames( $zone ); if ( $cnames ) { preg_match_all( '/url\((?![\'\"]?data)[\"\']?([^\)\"\']+)[\"\']?\)/i', $html, $matches ); if ( (bool) $matches ) { foreach ( $matches[1] as $k => $url ) { $url = str_replace( array( ' ', '\t', '\n', '\r', '\0', '\x0B', '"', "'", '"', ''' ), '', $url ); if ( '#' === substr( $url, 0, 1 ) ) { continue; } $url = get_rocket_cdn_url( $url, $zone ); $property = str_replace( $matches[1][ $k ], $url, $matches[0][ $k ] ); $html = str_replace( $matches[0][ $k ], $property, $html ); } } } return $html; } /** * Replace URL by CDN for custom files * * @since 2.9 * @deprecated 3.4 * @author Remy Perona * * @param string $html HTML content of the page. * @return string modified HTML content */ function rocket_cdn_custom_files( $html ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( is_preview() || empty( $html ) || defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $html; } $image_types = [ 'jpg', 'jpeg', 'jpe', 'png', 'gif', 'webp', 'bmp', 'tiff', ]; $other_types = [ 'mp3', 'ogg', 'mp4', 'm4v', 'avi', 'mov', 'flv', 'swf', 'webm', 'pdf', 'doc', 'docx', 'txt', 'zip', 'tar', 'bz2', 'tgz', 'rar', ]; $zones = array_filter( array_unique( get_rocket_option( 'cdn_zone', [] ) ) ); if ( empty( $zones ) ) { return $html; } if ( ! in_array( 'all', $zones, true ) && ! in_array( 'images', $zones, true ) ) { return $html; } $cdn_zones = []; $file_types = []; if ( in_array( 'images', $zones, true ) ) { $cdn_zones[] = 'images'; $file_types = array_merge( $file_types, $image_types ); } if ( in_array( 'all', $zones, true ) ) { $cdn_zones[] = 'all'; $file_types = array_merge( $file_types, $image_types, $other_types ); } $cnames = get_rocket_cdn_cnames( $cdn_zones ); if ( empty( $cnames ) ) { return $html; } /** * Filters the filetypes allowed for the CDN * * @since 2.9 * @author Remy Perona * * @param array $filetypes Array of file types. */ $file_types = apply_filters( 'rocket_cdn_custom_filetypes', $file_types ); $file_types = implode( '|', $file_types ); preg_match_all( '#]+?href=[\'"]?([^"\'>]+\.(?:' . $file_types . '))[\'"]?[^>]*>#i', $html, $matches ); if ( ! (bool) $matches ) { return $html; } foreach ( $matches[1] as $key => $url ) { $url = trim( $url, " \t\n\r\0\x0B\"'" ); $url = get_rocket_cdn_url( $url, $cdn_zones ); $src = str_replace( $matches[1][ $key ], $url, $matches[0][ $key ] ); $html = str_replace( $matches[0][ $key ], $src, $html ); } return $html; } /** * Replace URL by CDN of all scripts and styles enqueues with WordPress functions * * @since 2.9 Only add protocol if $src is an absolute url * @since 2.1 * @deprecated 3.4 * * @param string $src URL of the file. * @return string modified URL */ function rocket_cdn_enqueue( $src ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); // Don't use CDN if in admin, in login page, in register page or in a post preview. if ( is_admin() || is_preview() || in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ), true ) || defined( 'DONOTROCKETOPTIMIZE' ) && DONOTROCKETOPTIMIZE ) { return $src; } if ( rocket_extract_url_component( $src, PHP_URL_HOST ) !== '' ) { $src = rocket_add_url_protocol( $src ); } $zone = array( 'all', 'css_and_js' ); // Add only CSS zone. if ( 'style_loader_src' === current_filter() ) { $zone[] = 'css'; } // Add only JS zone. if ( 'script_loader_src' === current_filter() ) { $zone[] = 'js'; } $cnames = get_rocket_cdn_cnames( $zone ); if ( $cnames ) { // Check if the path isn't empty. if ( trim( rocket_extract_url_component( $src, PHP_URL_PATH ), '/' ) !== '' ) { $src = get_rocket_cdn_url( $src, $zone ); } } return $src; } /** * Get all files we don't allow to get in CDN. * * @since 2.5 * @deprecated 3.4 * * @return string A pipe-separated list of rejected files. */ function get_rocket_cdn_reject_files() { _deprecated_function( __FUNCTION__ . '()', '3.4', '\WP_Rocket\Subscriber\CDN\CDN::get_excluded_files()' ); $files = get_rocket_option( 'cdn_reject_files', [] ); /** * Filter the rejected files. * * @since 2.5 * * @param array $files List of rejected files. */ $files = (array) apply_filters( 'rocket_cdn_reject_files', $files ); $files = array_filter( $files ); $files = array_flip( array_flip( $files ) ); return implode( '|', $files ); } /** * Conflict with Envira Gallery: changes the URL argument if using WP Rocket CDN and Envira * * @since 2.6.5 * @since 3.4 * * @param array $args An array of arguments. * @return array Updated array of arguments */ function rocket_cdn_resize_image_args_on_envira_gallery( $args ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( ! isset( $args['url'] ) || (int) get_rocket_option( 'cdn' ) === 0 ) { return $args; } $cnames_host = array_flip( get_rocket_cnames_host() ); $url_host = rocket_extract_url_component( $args['url'], PHP_URL_HOST ); $home_host = rocket_extract_url_component( home_url(), PHP_URL_HOST ); if ( isset( $cnames_host[ $url_host ] ) ) { $args['url'] = str_replace( $url_host, $home_host , $args['url'] ); } return $args; } /** * Conflict with Envira Gallery: changes the resized URL if using WP Rocket CDN and Envira * * @since 2.6.5 * @since 3.4 * * @param string $url Resized image URL. * @return string Resized image URL using the CDN URL */ function rocket_cdn_resized_url_on_envira_gallery( $url ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( (int) get_rocket_option( 'cdn' ) === 0 ) { return $url; } $url = get_rocket_cdn_url( $url, array( 'all', 'images' ) ); return $url; } /** * Apply CDN settings to Beaver Builder parallax. * * @since 3.2.1 * @deprecated 3.4 * @author Grégory Viguier * * @param array $attrs HTML attributes. * @return array */ function rocket_beaver_builder_add_cdn_to_parallax( $attrs ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( ! empty( $attrs['data-parallax-image'] ) ) { $attrs['data-parallax-image'] = get_rocket_cdn_url( $attrs['data-parallax-image'], [ 'all', 'images' ] ); } return $attrs; } if ( class_exists( 'WR2X_Admin' ) ) : /** * Conflict with WP Retina x2: Apply CDN on srcset attribute. * * @since 2.9.1 Use global $wr2x_admin * @since 2.5.5 * @deprecated 3.4 * * @param string $url URL of the image. * @return string Updated URL with CDN */ function rocket_cdn_on_images_from_wp_retina_x2( $url ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); global $wr2x_admin; if ( ! method_exists( $wr2x_admin, 'is_pro' ) || ! $wr2x_admin->is_pro() ) { return $url; } $cdn_domain = get_option( 'wr2x_cdn_domain' ); if ( ! empty( $cdn_domain ) ) { return $url; } return get_rocket_cdn_url( $url, array( 'all', 'images' ) ); } endif; /** * Conflict with Avada theme and WP Rocket CDN * * @since 2.6.1 * @deprecated 3.4 * * @param array $vars An array of variables. * @param string $handle Name of the avada resource. * @return array updated array of variables */ function rocket_fix_cdn_for_avada_theme( $vars, $handle ) { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( 'avada-dynamic' === $handle && get_rocket_option( 'cdn' ) ) { $src = get_rocket_cdn_url( get_template_directory_uri() . '/assets/less/theme/dynamic.less' ); $vars['template-directory'] = sprintf( '~"%s"', dirname( dirname( dirname( dirname( $src ) ) ) ) ); $vars['lessurl'] = sprintf( '~"%s"', dirname( $src ) ); } return $vars; } /** * Conflict with Aqua Resizer & IrishMiss Framework: Apply CDN without blank src!! * * @since 2.5.8 Add compatibility with IrishMiss Framework * @since 2.5.5 * @deprecated 3.4 */ function rocket_cdn_on_aqua_resizer() { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( function_exists( 'aq_resize' ) || function_exists( 'miss_display_image' ) ) { remove_filter( 'wp_get_attachment_url' , 'rocket_cdn_file', PHP_INT_MAX ); add_filter( 'rocket_lazyload_html', 'rocket_add_cdn_on_custom_attr' ); } } /** * Conflict with Revolution Slider & Master Slider: Apply CDN on data-lazyload|data-src attribute. * * @since 2.5.5 * @deprecated 3.4 */ function rocket_cdn_on_sliders_with_lazyload() { _deprecated_function( __FUNCTION__ . '()', '3.4' ); if ( class_exists( 'RevSliderFront' ) || class_exists( 'Master_Slider' ) ) { add_filter( 'rocket_cdn_images_html', 'rocket_add_cdn_on_custom_attr' ); } }