his->get_image_size( $src ); // This is an image placeholder - do not generate srcset. if ( $width === $height && 1 === $width ) { return false; } $image_meta = array( 'width' => $width, 'height' => $height, ); } $size_array = array( absint( $width ), absint( $height ) ); $srcset = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id ); /** * In some rare cases, the wp_calculate_image_srcset() will not generate any srcset, because there are * not image sizes defined. If that is the case, try to revert to our custom maybe_generate_srcset() to * generate the srcset string. * * Also srcset will not be generated for images that are not part of the media library (no $attachment_id). */ if ( ! $srcset ) { $srcset = $this->maybe_generate_srcset( $width, $height, $src, $image_meta ); } $sizes = $srcset ? wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id ) : false; return array( $srcset, $sizes ); } /** * Try to generate srcset. * * @since 3.0 * * @param int $width Attachment width. * @param int $height Attachment height. * @param string $src Image source. * @param array $meta Image meta. * * @return bool|string */ private function maybe_generate_srcset( $width, $height, $src, $meta ) { $sources[ $width ] = array( 'url' => $this->generate_cdn_url( $src ), 'descriptor' => 'w', 'value' => $width, ); $sources = $this->set_additional_srcset( $sources, array( absint( $width ), absint( $height ) ), $src, $meta ); $srcsets = array(); if ( 1 < count( $sources ) ) { foreach ( $sources as $source ) { $srcsets[] = str_replace( ' ', '%20', $source['url'] ) . ' ' . $source['value'] . $source['descriptor']; } return implode( ',', $srcsets ); } return false; } /** * Check if the image path is supported by the CDN. * * @since 3.0 * @since 3.3.0 Changed access to public. * * @param string $src Image path. * * @return bool|string */ public function is_supported_path( $src ) { // Remove whitespaces. $src = trim( $src ); // No image? Return. if ( empty( $src ) ) { return false; } // Allow only these extensions in CDN. $path = wp_parse_url( $src, PHP_URL_PATH ); $ext = strtolower( pathinfo( $path, PATHINFO_EXTENSION ) ); if ( ! in_array( $ext, $this->supported_extensions, true ) ) { return false; } $url_parts = wp_parse_url( $src ); // Unsupported scheme. if ( isset( $url_parts['scheme'] ) && 'http' !== $url_parts['scheme'] && 'https' !== $url_parts['scheme'] ) { return false; } if ( ! isset( $url_parts['scheme'] ) && 0 === strpos( $src, '//' ) ) { $src = is_ssl() ? 'https:' . $src : 'http:' . $src; } // This is a relative path, try to get the URL. if ( ! isset( $url_parts['host'] ) && ! isset( $url_parts['scheme'] ) ) { $src = site_url( $src ); } $mapped_domain = $this->check_mapped_domain(); /** * There are chances for a custom uploads directory using UPLOADS constant. * * But some security plugins (for example, WP Hide & Security Enhance) will allow replacing paths via Nginx/Apache * rules. So for this reason, we don't want the path to be replaced everywhere with the custom UPLOADS constant, * we just want to let the user redefine it here, in the CDN. * * @since 3.4.0 * * @param array $uploads { * Array of information about the upload directory. * * @type string $path Base directory and subdirectory or full path to upload directory. * @type string $url Base URL and subdirectory or absolute URL to upload directory. * @type string $subdir Subdirectory if uploads use year/month folders option is on. * @type string $basedir Path without subdir. * @type string $baseurl URL path without subdir. * @type string|false $error False or error message. * } * * Usage (replace /wp-content/uploads/ with /media/ directory): * * add_filter( * 'smush_cdn_custom_uploads_dir', * function( $uploads ) { * $uploads['baseurl'] = 'https://example.com/media'; * return $uploads; * } * ); */ $uploads = apply_filters( 'smush_cdn_custom_uploads_dir', wp_get_upload_dir() ); // Check if the src is within custom uploads directory. $uploads = isset( $uploads['baseurl'] ) ? false !== strpos( $src, $uploads['baseurl'] ) : true; if ( ( false === strpos( $src, content_url() ) && ! $uploads ) || ( is_multisite() && $mapped_domain && false === strpos( $src, $mapped_domain ) ) ) { return false; } return $src; } /** * Support for domain mapping plugin. * * @since 3.1.1 */ private function check_mapped_domain() { if ( ! is_multisite() ) { return false; } if ( ! defined( 'DOMAINMAP_BASEFILE' ) ) { return false; } $domain = wp_cache_get( 'smush_mapped_site_domain', 'smush' ); if ( ! $domain ) { global $wpdb; $domain = $wpdb->get_var( $wpdb->prepare( "SELECT domain FROM {$wpdb->base_prefix}domain_mapping WHERE blog_id = %d ORDER BY id LIMIT 1", get_current_blog_id() ) ); // Db call ok. if ( null !== $domain ) { wp_cache_add( 'smush_mapped_site_domain', $domain, 'smush' ); } } return $domain; } /** * Init the page parser. */ private function init_parser() { $background_images = $this->settings->get( 'background_images' ); if ( $background_images ) { $this->parser->enable( 'background_images' ); } $this->parser->enable( 'cdn' ); } /** * Try to get the image dimensions from a local file. * * @since 3.4.0 * @param string $url Image URL. * * @return array|false */ private function get_image_size( $url ) { if ( $this->site_url !== $this->home_url ) { $url = str_replace( $this->site_url, $this->home_url, $url ); } $path = wp_make_link_relative( $url ); $path = wp_normalize_path( ABSPATH . $path ); if ( ! file_exists( $path ) ) { return false; } return getimagesize( $path ); } }