first
This commit is contained in:
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract class for an integration module: class Abstract_Integration
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @package Smush\Core\Modules\Integrations
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use Smush\Core\Settings;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Abstract_Integration
|
||||
*/
|
||||
abstract class Abstract_Integration {
|
||||
|
||||
/**
|
||||
* Module slug.
|
||||
*
|
||||
* @var string $module
|
||||
*/
|
||||
protected $module;
|
||||
|
||||
/**
|
||||
* Module class - free module by default, can be pro.
|
||||
*
|
||||
* @var string $class Accepts: 'free', 'pro'.
|
||||
*/
|
||||
protected $class = 'free';
|
||||
|
||||
/**
|
||||
* Module status.
|
||||
*
|
||||
* @var bool $enabled
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* Settings class instance for easier access.
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Abstract_Integration constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->settings = Settings::get_instance();
|
||||
|
||||
// Filters the setting variable to add module setting title and description.
|
||||
add_filter( 'wp_smush_settings', array( $this, 'register' ) );
|
||||
|
||||
// Disable setting.
|
||||
add_filter( 'wp_smush_integration_status_' . $this->module, array( $this, 'setting_status' ) );
|
||||
|
||||
// Show submit button if one of the integrations available.
|
||||
add_filter( 'wp_smush_integration_show_submit', array( $this, 'enable_submit_button' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update setting status - disable module functionality if not enabled.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setting_status() {
|
||||
return ! $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to enable the submit button or not.
|
||||
*
|
||||
* @since 3.9.8
|
||||
*
|
||||
* @param bool $enabled Current status.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function enable_submit_button( $enabled ) {
|
||||
return $enabled || $this->enabled;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Avada integration module.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @package Smush\Core\Integrations
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use Smush\Core\Modules\CDN;
|
||||
use Smush\Core\Modules\Helpers\Parser;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Avada
|
||||
*/
|
||||
class Avada {
|
||||
|
||||
/**
|
||||
* CDN module instance.
|
||||
*
|
||||
* @var CDN $cdn
|
||||
*/
|
||||
private $cdn;
|
||||
|
||||
/**
|
||||
* Avada constructor.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param CDN $cdn CDN module.
|
||||
*/
|
||||
public function __construct( CDN $cdn ) {
|
||||
if ( $cdn->is_active() ) {
|
||||
$this->cdn = $cdn;
|
||||
add_filter( 'smush_cdn_bg_image_tag', array( $this, 'replace_cdn_links' ) );
|
||||
|
||||
if ( defined( 'FUSION_BUILDER_PLUGIN_DIR' ) ) {
|
||||
add_filter( 'smush_after_process_background_images', array( $this, 'smush_cdn_image_replaced' ), 10, 3 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all the image src with cdn link.
|
||||
*
|
||||
* @param string $content Content of the current post.
|
||||
* @param string $image Backround Image tag without src.
|
||||
* @param string $img_src Image src.
|
||||
* @return string
|
||||
*/
|
||||
public function smush_cdn_image_replaced( $content, $image, $img_src ) {
|
||||
if ( $this->cdn->is_supported_path( $img_src ) ) {
|
||||
$new_src = $this->cdn->generate_cdn_url( $img_src );
|
||||
|
||||
if ( $new_src ) {
|
||||
$content = str_replace( $img_src, $new_src, $content );
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace images from data-bg-url with CDN links.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string $img Image.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function replace_cdn_links( $img ) {
|
||||
$image_src = Parser::get_attribute( $img, 'data-bg-url' );
|
||||
if ( $image_src ) {
|
||||
// Store the original source to be used later on.
|
||||
$original_src = $image_src;
|
||||
|
||||
// Replace the data-bg-url of the image with CDN link.
|
||||
if ( $this->cdn->is_supported_path( $image_src ) ) {
|
||||
$image_src = $this->cdn->generate_cdn_url( $image_src );
|
||||
|
||||
if ( $image_src ) {
|
||||
$img = preg_replace( '#(data-bg-url=["|\'])' . $original_src . '(["|\'])#i', '\1' . $image_src . '\2', $img, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $img;
|
||||
}
|
||||
|
||||
}
|
676
wp-content/plugins/wp-smushit/core/integrations/class-common.php
Normal file
676
wp-content/plugins/wp-smushit/core/integrations/class-common.php
Normal file
@ -0,0 +1,676 @@
|
||||
<?php
|
||||
/**
|
||||
* Smush integration with various plugins: Common class
|
||||
*
|
||||
* @package Smush\Core\Integrations
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @author Anton Vanyukov <anton@incsub.com>
|
||||
*
|
||||
* @copyright (c) 2018, Incsub (http://incsub.com)
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use Smush\Core\Helper;
|
||||
use Smush\Core\Modules\Helpers\Parser;
|
||||
use Smush\Core\Modules\Smush;
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton class class Common
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
class Common {
|
||||
|
||||
/**
|
||||
* Common constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( is_admin() ) {
|
||||
// AJAX Thumbnail Rebuild integration.
|
||||
add_filter( 'wp_smush_media_image', array( $this, 'skip_images' ), 10, 2 );
|
||||
|
||||
// Optimise WP retina 2x images.
|
||||
add_action( 'wr2x_retina_file_added', array( $this, 'smush_retina_image' ), 20, 3 );
|
||||
|
||||
// Remove any pre_get_posts_filters added by WP Media Folder plugin.
|
||||
add_action( 'wp_smush_remove_filters', array( $this, 'remove_filters' ) );
|
||||
}
|
||||
|
||||
// WPML integration.
|
||||
add_action( 'wpml_updated_attached_file', array( $this, 'wpml_undo_ignore_attachment' ) );
|
||||
add_action( 'wpml_after_duplicate_attachment', array( $this, 'wpml_ignore_duplicate_attachment' ), 10, 2 );
|
||||
add_action( 'wpml_after_copy_attached_file_postmeta', array( $this, 'wpml_ignore_duplicate_attachment' ), 10, 2 );
|
||||
|
||||
// ReCaptcha lazy load.
|
||||
add_filter( 'smush_skip_iframe_from_lazy_load', array( $this, 'exclude_recaptcha_iframe' ), 10, 2 );
|
||||
|
||||
// Compatibility modules for lazy loading.
|
||||
add_filter( 'smush_skip_image_from_lazy_load', array( $this, 'lazy_load_compat' ), 10, 3 );
|
||||
|
||||
// Soliloquy slider CDN support.
|
||||
add_filter( 'soliloquy_image_src', array( $this, 'soliloquy_image_src' ) );
|
||||
|
||||
// Translate Press integration.
|
||||
add_filter( 'smush_skip_image_from_lazy_load', array( $this, 'trp_translation_editor' ) );
|
||||
|
||||
// Jetpack CDN compatibility.
|
||||
add_filter( 'smush_cdn_skip_image', array( $this, 'jetpack_cdn_compat' ), 10, 2 );
|
||||
|
||||
// WP Maintenance Plugin integration.
|
||||
add_action( 'template_redirect', array( $this, 'wp_maintenance_mode' ) );
|
||||
|
||||
// WooCommerce's product gallery thumbnail CDN support.
|
||||
add_filter( 'woocommerce_single_product_image_thumbnail_html', array( $this, 'woocommerce_cdn_gallery_thumbnails' ) );
|
||||
|
||||
// Buddyboss theme and its platform plugin integration.
|
||||
add_filter( 'wp_smush_cdn_before_process_src', array( $this, 'buddyboss_platform_modify_image_src' ), 10, 2 );
|
||||
|
||||
// GiveWP donation form load lazyload images in iframe.
|
||||
add_action( 'give_donation_form_top', array( $this, 'givewp_skip_image_lazy_load' ), 0 );
|
||||
|
||||
// Thumbnail regeneration handler.
|
||||
add_filter( 'wp_generate_attachment_metadata', array( $this, 'maybe_handle_thumbnail_generation' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any pre_get_posts_filters added by WP Media Folder plugin.
|
||||
*/
|
||||
public function remove_filters() {
|
||||
// Remove any filters added b WP media Folder plugin to get the all attachments.
|
||||
if ( class_exists( 'Wp_Media_Folder' ) ) {
|
||||
global $wp_media_folder;
|
||||
if ( is_object( $wp_media_folder ) ) {
|
||||
remove_filter( 'pre_get_posts', array( $wp_media_folder, 'wpmf_pre_get_posts1' ) );
|
||||
remove_filter( 'pre_get_posts', array( $wp_media_folder, 'wpmf_pre_get_posts' ), 0, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
global $wpml_query_filter;
|
||||
|
||||
// If WPML is not installed, return.
|
||||
if ( ! is_object( $wpml_query_filter ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove language filter and let all the images be smushed at once.
|
||||
if ( has_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ) ) ) {
|
||||
remove_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ), 10, 2 );
|
||||
remove_filter( 'posts_where', array( $wpml_query_filter, 'posts_where_filter' ), 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* AJAX Thumbnail Rebuild
|
||||
*
|
||||
* @since 2.8
|
||||
*/
|
||||
|
||||
/**
|
||||
* AJAX Thumbnail Rebuild integration.
|
||||
*
|
||||
* If this is a thumbnail regeneration - only continue for selected thumbs
|
||||
* (no need to regenerate everything else).
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @param string $smush_image Image size.
|
||||
* @param string $size_key Thumbnail size.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function skip_images( $smush_image, $size_key ) {
|
||||
if ( empty( $_POST['regen'] ) || ! is_array( $_POST['regen'] ) ) { // Input var ok.
|
||||
return $smush_image;
|
||||
}
|
||||
|
||||
$smush_sizes = wp_unslash( $_POST['regen'] ); // Input var ok.
|
||||
|
||||
if ( in_array( $size_key, $smush_sizes, true ) ) {
|
||||
return $smush_image;
|
||||
}
|
||||
|
||||
// Do not regenerate other thumbnails for regenerate action.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* WP Retina 2x
|
||||
*/
|
||||
|
||||
/**
|
||||
* Smush Retina images for WP Retina 2x, Update Stats.
|
||||
*
|
||||
* @param int $id Attachment ID.
|
||||
* @param string $retina_file Retina image.
|
||||
* @param string $image_size Image size.
|
||||
*/
|
||||
public function smush_retina_image( $id, $retina_file, $image_size ) {
|
||||
$smush = WP_Smush::get_instance()->core()->mod->smush;
|
||||
|
||||
/**
|
||||
* Allows to Enable/Disable WP Retina 2x Integration
|
||||
*/
|
||||
$smush_retina_images = apply_filters( 'smush_retina_images', true );
|
||||
|
||||
// Check if Smush retina images is enabled.
|
||||
if ( ! $smush_retina_images ) {
|
||||
return;
|
||||
}
|
||||
// Check for Empty fields.
|
||||
if ( empty( $id ) || empty( $retina_file ) || empty( $image_size ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not smush if auto smush is turned off.
|
||||
if ( ! $smush->should_auto_smush( $id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to skip a image from smushing
|
||||
*
|
||||
* @param bool $smush_image Smush image or not
|
||||
* @param string $image_size Size of image being smushed
|
||||
* @param string $retina_file Retina file path.
|
||||
* @param int $id Attachment ID.
|
||||
*
|
||||
* @since 3.9.6 Add two parameters for the filter.
|
||||
*/
|
||||
$smush_image = apply_filters( 'wp_smush_media_image', true, $image_size, $retina_file, $id );
|
||||
|
||||
if ( ! $smush_image ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stats = $smush->do_smushit( $retina_file );
|
||||
// If we squeezed out something, Update stats.
|
||||
if ( ! is_wp_error( $stats ) && ! empty( $stats['data'] ) && isset( $stats['data'] ) && $stats['data']->bytes_saved > 0 ) {
|
||||
$image_size = $image_size . '@2x';
|
||||
|
||||
$this->update_smush_stats_single( $id, $stats, $image_size );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the smush stats for a single image size.
|
||||
*
|
||||
* @param int $id Attachment ID.
|
||||
* @param array $smush_stats Smush stats.
|
||||
* @param string $image_size Image size.
|
||||
*/
|
||||
private function update_smush_stats_single( $id, $smush_stats, $image_size = '' ) {
|
||||
// Return, if we don't have image id or stats for it.
|
||||
if ( empty( $id ) || empty( $smush_stats ) || empty( $image_size ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$smush = WP_Smush::get_instance()->core()->mod->smush;
|
||||
$data = $smush_stats['data'];
|
||||
// Get existing Stats.
|
||||
$stats = get_post_meta( $id, Smush::$smushed_meta_key, true );
|
||||
|
||||
// Update existing Stats.
|
||||
if ( ! empty( $stats ) ) {
|
||||
// Update stats for each size.
|
||||
if ( isset( $stats['sizes'] ) ) {
|
||||
// if stats for a particular size doesn't exists.
|
||||
if ( empty( $stats['sizes'][ $image_size ] ) ) {
|
||||
// Update size wise details.
|
||||
$stats['sizes'][ $image_size ] = (object) $smush->array_fill_placeholders( $smush->get_size_signature(), (array) $data );
|
||||
} else {
|
||||
// Update compression percent and bytes saved for each size.
|
||||
$stats['sizes'][ $image_size ]->bytes = $stats['sizes'][ $image_size ]->bytes + $data->bytes_saved;
|
||||
$stats['sizes'][ $image_size ]->percent = $stats['sizes'][ $image_size ]->percent + $data->compression;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create new stats.
|
||||
$stats = array(
|
||||
'stats' => array_merge(
|
||||
$smush->get_size_signature(),
|
||||
array(
|
||||
'api_version' => - 1,
|
||||
'lossy' => - 1,
|
||||
)
|
||||
),
|
||||
'sizes' => array(),
|
||||
);
|
||||
|
||||
$stats['stats']['api_version'] = $data->api_version;
|
||||
$stats['stats']['lossy'] = $data->lossy;
|
||||
$stats['stats']['keep_exif'] = ! empty( $data->keep_exif ) ? $data->keep_exif : 0;
|
||||
|
||||
// Update size wise details.
|
||||
$stats['sizes'][ $image_size ] = (object) $smush->array_fill_placeholders( $smush->get_size_signature(), (array) $data );
|
||||
}
|
||||
|
||||
// Calculate the total compression.
|
||||
$stats = WP_Smush::get_instance()->core()->total_compression( $stats );
|
||||
|
||||
update_post_meta( $id, Smush::$smushed_meta_key, $stats );
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* WPML
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ignore WPML duplicated images from Smush.
|
||||
*
|
||||
* If WPML is duplicating images, we need to mark them as ignored for Smushing
|
||||
* because the image is same for all those duplicated attachment posts. This is
|
||||
* required to avoid wrong Smush stats.
|
||||
*
|
||||
* @param int $attachment_id Original attachment ID.
|
||||
* @param int $duplicated_attachment_id Duplicated attachment ID.
|
||||
*
|
||||
* @since 3.9.4
|
||||
*/
|
||||
public function wpml_ignore_duplicate_attachment( $attachment_id, $duplicated_attachment_id ) {
|
||||
// Ignore the image from Smush if duplicate.
|
||||
update_post_meta( $duplicated_attachment_id, 'wp-smush-ignore-bulk', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an image from the ignored list.
|
||||
*
|
||||
* When a new image is added instead of duplicate, we need to remove it
|
||||
* from the ignored list to make it available for Smushing.
|
||||
*
|
||||
* @param int $attachment_id Attachment ID.
|
||||
*
|
||||
* @since 3.9.4
|
||||
*/
|
||||
public function wpml_undo_ignore_attachment( $attachment_id ) {
|
||||
// Delete ignore flag.
|
||||
delete_post_meta( $attachment_id, 'wp-smush-ignore-bulk' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip ReCaptcha iframes from lazy loading.
|
||||
*
|
||||
* @since 3.4.2
|
||||
*
|
||||
* @param bool $skip Should skip? Default: false.
|
||||
* @param string $src Iframe url.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exclude_recaptcha_iframe( $skip, $src ) {
|
||||
return false !== strpos( $src, 'recaptcha/api' );
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* Soliloquy slider
|
||||
*
|
||||
* @since 3.6.2
|
||||
*/
|
||||
|
||||
/**
|
||||
* Replace slider image links with CDN links.
|
||||
*
|
||||
* @param string $src Image source.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function soliloquy_image_src( $src ) {
|
||||
$cdn = WP_Smush::get_instance()->core()->mod->cdn;
|
||||
|
||||
if ( ! $cdn->get_status() || empty( $src ) ) {
|
||||
return $src;
|
||||
}
|
||||
|
||||
if ( $cdn->is_supported_path( $src ) ) {
|
||||
return $cdn->generate_cdn_url( $src );
|
||||
}
|
||||
|
||||
return $src;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* Translate Press
|
||||
*
|
||||
* @since 3.6.3
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disables "Lazy Load" on Translate Press translate editor
|
||||
*
|
||||
* @param bool $skip Should skip? Default: false.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function trp_translation_editor( $skip ) {
|
||||
if ( ! class_exists( '\TRP_Translate_Press' ) || ! isset( $_GET['trp-edit-translation'] ) ) {
|
||||
return $skip;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* Jetpack
|
||||
*
|
||||
* @since 3.7.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* Skips the url from the srcset from our CDN when it's already served by Jetpack's CDN.
|
||||
*
|
||||
* @since 3.7.1
|
||||
*
|
||||
* @param bool $skip Should skip? Default: false.
|
||||
* @param string $url Source.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function jetpack_cdn_compat( $skip, $url ) {
|
||||
if ( ! class_exists( '\Jetpack' ) ) {
|
||||
return $skip;
|
||||
}
|
||||
|
||||
if ( method_exists( '\Jetpack', 'is_module_active' ) && ! \Jetpack::is_module_active( 'photon' ) ) {
|
||||
return $skip;
|
||||
}
|
||||
|
||||
$parsed_url = wp_parse_url( $url );
|
||||
|
||||
// The image already comes from Jetpack's CDN.
|
||||
if ( preg_match( '#^i[\d]{1}.wp.com$#i', $parsed_url['host'] ) ) {
|
||||
return true;
|
||||
}
|
||||
return $skip;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* WP Maintenance Plugin
|
||||
*
|
||||
* @since 3.8.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disable page parsing when "Maintenance" is enabled
|
||||
*
|
||||
* @since 3.8.0
|
||||
*/
|
||||
public function wp_maintenance_mode() {
|
||||
if ( ! class_exists( '\MTNC' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $mt_options;
|
||||
|
||||
if ( ! is_user_logged_in() && ! empty( $mt_options['state'] ) ) {
|
||||
add_filter( 'wp_smush_should_skip_parse', '__return_true' );
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* WooCommerce
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Replaces the product's gallery thumbnail URL with the CDN URL.
|
||||
*
|
||||
* WC uses a <div data-thumbnail=""> attribute to get the thumbnail
|
||||
* img src which is then added via JS. Our regex for parsing the page
|
||||
* doesn't check for this div and attribute (and it shouldn't, it becomes too slow).
|
||||
*
|
||||
* We can remove this if we ever use the filter "wp_get_attachment_image_src"
|
||||
* to replace the images' src URL with the CDN one.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param string $html The thumbnail markup.
|
||||
* @return string
|
||||
*/
|
||||
public function woocommerce_cdn_gallery_thumbnails( $html ) {
|
||||
$cdn = WP_Smush::get_instance()->core()->mod->cdn;
|
||||
|
||||
// Replace only when the CDN is active.
|
||||
if ( ! $cdn->get_status() ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
preg_match_all( '/<(div)\b(?>\s+(?:data-thumb=[\'"](?P<thumb>[^\'"]*)[\'"])|[^\s>]+|\s+)*>/is', $html, $matches );
|
||||
|
||||
if ( ! $matches || ! is_array( $matches ) ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
foreach ( $matches as $key => $url ) {
|
||||
// Only use the match for the thumbnail URL if it's supported.
|
||||
if ( 'thumb' !== $key || empty( $url[0] ) || ! $cdn->is_supported_path( $url[0] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Replace the data-thumb attribute of the div with the CDN link.
|
||||
$cdn_url = $cdn->generate_cdn_url( $url[0] );
|
||||
if ( $cdn_url ) {
|
||||
$html = str_replace( $url[0], $cdn_url, $html );
|
||||
}
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* Various modules
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lazy loading compatibility checks.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*
|
||||
* @param bool $skip Should skip? Default: false.
|
||||
* @param string $src Image url.
|
||||
* @param string $image Image.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function lazy_load_compat( $skip, $src, $image ) {
|
||||
// Avoid conflicts if attributes are set (another plugin, for example).
|
||||
if ( false !== strpos( $image, 'data-src' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compatibility with Essential Grid lazy loading.
|
||||
if ( false !== strpos( $image, 'data-lazysrc' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compatibility with JetPack lazy loading.
|
||||
if ( false !== strpos( $image, 'jetpack-lazy-image' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compatibility with Slider Revolution's lazy loading.
|
||||
if ( false !== strpos( $image, '/revslider/' ) && false !== strpos( $image, 'data-lazyload' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $skip;
|
||||
}
|
||||
|
||||
/**
|
||||
* CDN compatibility with Buddyboss platform
|
||||
*
|
||||
* @param string $src Image source.
|
||||
* @param string $image Actual image element.
|
||||
*
|
||||
* @return string Original or modified image source.
|
||||
*/
|
||||
public function buddyboss_platform_modify_image_src( $src, $image ) {
|
||||
if ( ! defined( 'BP_PLATFORM_VERSION' ) ) {
|
||||
return $src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility with buddyboss theme and it's platform plugin.
|
||||
*
|
||||
* Buddyboss platform plugin uses the placeholder image as it's main src.
|
||||
* And process_src() method below uses the same placeholder.png to create
|
||||
* the srcset when "Automatic resizing" options is enabled for CDN.
|
||||
* ---------
|
||||
* Replacing the placeholder with actual image source as early as possible.
|
||||
* Checks:
|
||||
* 1. The image source contains buddyboss-platform in its string
|
||||
* 2. The image source contains placeholder.png and is crucial because there are other
|
||||
* images as well which doesn't uses placeholder.
|
||||
*/
|
||||
if ( false !== strpos( $src, 'buddyboss-platform' ) && false !== strpos( $src, 'placeholder.png' ) ) {
|
||||
$new_src = Parser::get_attribute( $image, 'data-src' );
|
||||
|
||||
if ( ! empty( $new_src ) ) {
|
||||
$src = $new_src;
|
||||
}
|
||||
}
|
||||
|
||||
return $src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip images from lazy loading on GiveWP forms.
|
||||
*
|
||||
* @since 3.8.8
|
||||
*/
|
||||
public function givewp_skip_image_lazy_load() {
|
||||
add_filter( 'wp_smush_should_skip_parse', '__return_true' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method to handle thumbnail generation.
|
||||
*
|
||||
* We use this trick to call self::thumbnail_regenerate_handler()
|
||||
* to avoid it called several times while calling wp_generate_attachment_metadata().
|
||||
* 1. wp_generate_attachment_metadata -> wp_create_image_subsizes -> wp_update_attachment_metadata().
|
||||
* 2. wp_generate_attachment_metadata -> _wp_make_subsizes -> wp_update_attachment_metadata().
|
||||
* 3. After calling wp_generate_attachment_metadata() => We should only add our filter here.
|
||||
*
|
||||
* @param array $metadata Image metadata.
|
||||
* @return array The provided metadata.
|
||||
*/
|
||||
public function maybe_handle_thumbnail_generation( $metadata ) {
|
||||
/**
|
||||
* Add filter to handle thumbnail generation.
|
||||
* We use a big priority because it seems WP has an issue for this case,
|
||||
* after we remove this filter, all registered filters after this priority of this hook will not call.
|
||||
*/
|
||||
add_filter( 'wp_update_attachment_metadata', array( $this, 'thumbnail_regenerate_handler' ), 99999, 2 ); // S3 is using priority 110.
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for 'wp_update_attachment_metadata' WordPress hook used by Smush to detect
|
||||
* regenerated thumbnails and mark them as pending for (re)smush.
|
||||
*
|
||||
* @since 3.9.2
|
||||
*
|
||||
* @param array $new_meta New metadata.
|
||||
* @param int $attachment_id The attachment ID.
|
||||
*
|
||||
* @since 3.9.6 Disable this filter while async uploading,
|
||||
* and update compatible with S3, and only call it after generated metadata.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function thumbnail_regenerate_handler( $new_meta, $attachment_id ) {
|
||||
// Remove the filter as we are no longer need it.
|
||||
remove_filter( 'wp_update_attachment_metadata', array( $this, 'thumbnail_regenerate_handler' ), 99999 );
|
||||
|
||||
/**
|
||||
* Skip if there is WP uploading a new image,
|
||||
* or the attachment is not an image or does not have thumbnails.
|
||||
*/
|
||||
if (
|
||||
empty( $new_meta['sizes'] )
|
||||
// Async uploading.
|
||||
|| isset( $_POST['post_id'] ) || isset( $_FILES['async-upload'] )
|
||||
// Smushed it, don't need to check it again.
|
||||
|| did_action( 'wp_smush_before_smush_file' )
|
||||
// Disable when restoring.
|
||||
|| did_action( 'wp_smush_before_restore_backup' )
|
||||
// Only support Image.
|
||||
|| ! Helper::is_smushable( $attachment_id )
|
||||
) {
|
||||
return $new_meta;
|
||||
}
|
||||
|
||||
// Skip if the attachment has an active smush operation or in being restored by Smush or ignored.
|
||||
if ( get_transient( 'smush-in-progress-' . $attachment_id ) || get_transient( 'wp-smush-restore-' . $attachment_id ) || get_post_meta( $attachment_id, 'wp-smush-ignore-bulk', true ) ) {
|
||||
return $new_meta;
|
||||
}
|
||||
|
||||
$smush_meta = get_post_meta( $attachment_id, Smush::$smushed_meta_key, true );
|
||||
|
||||
// Skip attachments without Smush meta key.
|
||||
if ( empty( $smush_meta ) ) {
|
||||
return $new_meta;
|
||||
}
|
||||
|
||||
$size_increased = false;
|
||||
/**
|
||||
* Get attached file
|
||||
* If there is generating the image, S3 also downloaded it,
|
||||
* so we don't need to download it if it doesn't exist.
|
||||
*/
|
||||
$attached_file = Helper::get_attached_file( $attachment_id, 'original' );// S3+.
|
||||
// If the main file does not exist, there is not generating the thumbnail, return.
|
||||
if ( ! file_exists( $attached_file ) ) {
|
||||
return $new_meta;
|
||||
}
|
||||
|
||||
// We need only the last $new_meta['sizes'] element of each subsequent call
|
||||
// to wp_update_attachment_metadata() made by wp_create_image_subsizes().
|
||||
$size = array_keys( $new_meta['sizes'] )[ count( $new_meta['sizes'] ) - 1 ];
|
||||
|
||||
$file_dir = dirname( $attached_file );
|
||||
$file_name = $file_dir . '/' . $new_meta['sizes'][ $size ]['file'];
|
||||
|
||||
$actual_size = is_file( $file_name ) ? filesize( $file_name ) : false;
|
||||
$stored_size = isset( $smush_meta['sizes'][ $size ]->size_after ) ? $smush_meta['sizes'][ $size ]->size_after : false;
|
||||
|
||||
// Only do the comparison if we have both the actual and the database stored size.
|
||||
if ( $actual_size && $stored_size ) {
|
||||
$size_increased = $actual_size > 1.01 * $stored_size;// Not much we can do if save less than 1%.
|
||||
}
|
||||
|
||||
// File size increased? Let's remove all
|
||||
// Smush related meta keys for this attachment.
|
||||
if ( $size_increased ) {
|
||||
/**
|
||||
* When regenerate an image, we only generate the sub-sizes,
|
||||
* so we don't need to delete the saving data of PNG2JPG.
|
||||
* And similar for resizing, we also added filter for big_image_size_threshold,
|
||||
* and we don't use the resizing meta for any conditional, so it's ok to keep it.
|
||||
*/
|
||||
// Remove stats and update cache.
|
||||
WP_Smush::get_instance()->core()->remove_stats( $attachment_id );
|
||||
}
|
||||
|
||||
return $new_meta;
|
||||
}
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
/**
|
||||
* Smush integration with WPBakery Page Builder: Composer class
|
||||
*
|
||||
* @package Smush\Core\Integrations
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @author Anton Vanyukov <anton@incsub.com>
|
||||
*
|
||||
* @copyright (c) 2018, Incsub (http://incsub.com)
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Composer for WPBakery Page Builder integration.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*/
|
||||
class Composer extends Abstract_Integration {
|
||||
|
||||
/**
|
||||
* Composer constructor.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->module = 'js_builder';
|
||||
$this->class = 'free';
|
||||
|
||||
$this->check_for_js_builder();
|
||||
|
||||
parent::__construct();
|
||||
|
||||
// Hook at the end of setting row to output a error div.
|
||||
add_action( 'smush_setting_column_right_inside', array( $this, 'additional_notice' ) );
|
||||
|
||||
if ( $this->settings->get( 'js_builder' ) ) {
|
||||
add_filter( 'image_make_intermediate_size', array( $this, 'process_image_resize' ) );
|
||||
|
||||
// CDN link image handler for ajax based loading.
|
||||
add_filter( 'wp_get_attachment_image_src', array( $this, 'cdn_attachment_image_src' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* OVERWRITE PARENT CLASS FUNCTIONALITY
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filters the setting variable to add NextGen setting title and description
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param array $settings Settings.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function register( $settings ) {
|
||||
$settings[ $this->module ] = array(
|
||||
'label' => esc_html__( 'Enable WPBakery Page Builder integration', 'wp-smushit' ),
|
||||
'short_label' => esc_html__( 'WPBakery Page Builder', 'wp-smushit' ),
|
||||
'desc' => esc_html__( 'Allow smushing images resized in WPBakery Page Builder editor.', 'wp-smushit' ),
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show additional notice if the required plugins are not installed.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $name Setting name.
|
||||
*/
|
||||
public function additional_notice( $name ) {
|
||||
if ( $this->module === $name && ! $this->enabled ) {
|
||||
?>
|
||||
<div class="sui-toggle-content">
|
||||
<div class="sui-notice">
|
||||
<div class="sui-notice-content">
|
||||
<div class="sui-notice-message">
|
||||
<i class="sui-notice-icon sui-icon-info" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e( 'To use this feature you need be using WPBakery Page Builder.', 'wp-smushit' ); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* PUBLIC CLASSES
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if the file source is a registered attachment and if not - Smush it.
|
||||
*
|
||||
* TODO: with little adjustments this can be used for all page builders.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @param string $image_src Image src.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function process_image_resize( $image_src ) {
|
||||
$vc_editable = filter_input( INPUT_GET, 'vc_editable', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE );
|
||||
$vc_action = filter_input( INPUT_POST, 'action', FILTER_SANITIZE_SPECIAL_CHARS );
|
||||
|
||||
global $pagename, $vc_manager;
|
||||
|
||||
/**
|
||||
* There are three types of situations:
|
||||
* 1. $vc_editable and $vc_action will be set in the frontend page builder
|
||||
* 2. $pagename in the backend.
|
||||
* 3. $vc_manager is a fallback (could possibly cause issues).
|
||||
*/
|
||||
if ( ( ! $vc_editable || 'vc_load_shortcode' !== $vc_action ) && ( ! isset( $pagename ) || 'page-builder' !== $pagename ) && ( ! $vc_manager || ! is_object( $vc_manager ) ) ) {
|
||||
return $image_src;
|
||||
}
|
||||
|
||||
// Save the original image source.
|
||||
$vc_image = $image_src;
|
||||
|
||||
// Remove the [width]x[height] params from URL.
|
||||
$size = array();
|
||||
if ( preg_match( '/(\d+)x(\d+)\.(?:' . implode( '|', array( 'gif', 'jpg', 'jpeg', 'png' ) ) . '){1}$/i', $image_src, $size ) ) {
|
||||
$image_src = str_replace( '-' . $size[1] . 'x' . $size[2], '', $image_src );
|
||||
}
|
||||
|
||||
// Convert image src to URL.
|
||||
$upload_dir = wp_get_upload_dir();
|
||||
$image_url = str_replace( $upload_dir['path'], $upload_dir['url'], $image_src );
|
||||
|
||||
// Try to get the attachment ID.
|
||||
$attachment_id = attachment_url_to_postid( $image_url );
|
||||
|
||||
if ( ! wp_attachment_is_image( $attachment_id ) ) {
|
||||
return $vc_image;
|
||||
}
|
||||
|
||||
$image = image_get_intermediate_size( $attachment_id, array( $size[1], $size[2] ) );
|
||||
|
||||
if ( $image ) {
|
||||
return $vc_image;
|
||||
}
|
||||
|
||||
// Smush image. TODO: should we update the stats?
|
||||
WP_Smush::get_instance()->core()->mod->smush->do_smushit( $vc_image );
|
||||
|
||||
return $vc_image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the image src with cdn link for all the Ajax requests.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @see SMUSH-206
|
||||
*
|
||||
* @param array|false $image {
|
||||
* Array of image data, or boolean false if no image is available.
|
||||
*
|
||||
* @type string $0 Image source URL.
|
||||
* @type int $1 Image width in pixels.
|
||||
* @type int $2 Image height in pixels.
|
||||
* @type bool $3 Whether the image is a resized image.
|
||||
* }
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function cdn_attachment_image_src( $image ) {
|
||||
if ( ! wp_doing_ajax() ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$cdn = WP_Smush::get_instance()->core()->mod->cdn;
|
||||
|
||||
if ( ! $cdn->get_status() ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
if ( is_array( $image ) && ! empty( $image[0] ) ) {
|
||||
$image[0] = $cdn->generate_cdn_url( $image[0] );
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* PRIVATE CLASSES
|
||||
*/
|
||||
|
||||
/**
|
||||
* Should only be active when WPBakery Page Builder is installed.
|
||||
*
|
||||
* @since 3.2.1
|
||||
*
|
||||
* @see https://kb.wpbakery.com/docs/inner-api/vc_disable_frontend
|
||||
*/
|
||||
private function check_for_js_builder() {
|
||||
// This function exists since WPBakery 4.0 (02.03.2014) and is listed
|
||||
// on their API docs. It should be stable enough to rely on it.
|
||||
$this->enabled = defined( 'WPB_VC_VERSION' ) && function_exists( 'vc_disable_frontend' );
|
||||
}
|
||||
|
||||
}
|
170
wp-content/plugins/wp-smushit/core/integrations/class-envira.php
Normal file
170
wp-content/plugins/wp-smushit/core/integrations/class-envira.php
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration with Envira Gallery
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @package Smush\Core\Integrations
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use Smush\Core\Modules\CDN;
|
||||
use Smush\Core\Modules\Helpers\Parser;
|
||||
use Smush\Core\Settings;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Envira
|
||||
*/
|
||||
class Envira {
|
||||
|
||||
/**
|
||||
* CDN module instance.
|
||||
*
|
||||
* @var CDN $cdn
|
||||
*/
|
||||
private $cdn;
|
||||
|
||||
/**
|
||||
* Envira constructor.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param CDN $cdn CDN module.
|
||||
*/
|
||||
public function __construct( CDN $cdn ) {
|
||||
if ( is_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Settings::get_instance()->get( 'lazy_load' ) ) {
|
||||
add_filter( 'smush_skip_image_from_lazy_load', array( $this, 'skip_lazy_load' ), 10, 3 );
|
||||
add_filter( 'envira_gallery_indexable_images', array( $this, 'add_no_lazyload_class' ) );
|
||||
}
|
||||
|
||||
if ( $cdn->is_active() ) {
|
||||
$this->cdn = $cdn;
|
||||
add_filter( 'smush_cdn_image_tag', array( $this, 'replace_cdn_links' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not lazy load images from Envira Gallery.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param bool $lazy_load Should skip? Default: false.
|
||||
* @param string $src Image url.
|
||||
* @param string $img Image.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function skip_lazy_load( $lazy_load, $src, $img ) {
|
||||
$classes = Parser::get_attribute( $img, 'class' );
|
||||
return false !== strpos( $classes, 'envira-lazy' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace images from data-envira-src and data-envira-srcset with CDN links.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string $img Image.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function replace_cdn_links( $img ) {
|
||||
$image_src = Parser::get_attribute( $img, 'data-envira-src' );
|
||||
if ( $image_src ) {
|
||||
// Store the original source to be used later on.
|
||||
$original_src = $image_src;
|
||||
|
||||
// Replace the data-envira-src of the image with CDN link.
|
||||
$image_src = $this->convert_url_to_cdn( $image_src );
|
||||
if ( $image_src ) {
|
||||
$img = preg_replace( '#(data-envira-src=["|\'])' . $original_src . '(["|\'])#i', '\1' . $image_src . '\2', $img, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
$image_srcset = Parser::get_attribute( $img, 'data-envira-srcset' );
|
||||
if ( $image_srcset ) {
|
||||
// Do not add our own srcset attributes.
|
||||
add_filter( 'smush_skip_adding_srcset', '__return_true' );
|
||||
|
||||
// Store the original source to be used later on.
|
||||
$original_src = $image_srcset;
|
||||
$replace = false;
|
||||
|
||||
$images = Parser::get_links_from_content( $image_srcset );
|
||||
if ( isset( $images[0] ) && is_array( $images[0] ) ) {
|
||||
foreach ( $images[0] as $image ) {
|
||||
// Replace the data-envira-srcset of the image with CDN link.
|
||||
$image_src = $this->convert_url_to_cdn( $image );
|
||||
if ( $image_src ) {
|
||||
$replace = true;
|
||||
$image_srcset = preg_replace( '#' . $image . '#i', '\1' . $image_src . '\2', $image_srcset, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $replace ) {
|
||||
$img = preg_replace( '#(data-envira-srcset=["|\'])' . $original_src . '(["|\'])#i', '\1' . $image_srcset . '\2', $img, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return $img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Galleries in Envira will use a noscript tag with images. Smush can't filter the DOM tree, so we will add
|
||||
* a no-lazyload class to every image.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*
|
||||
* @param string $images String of img tags that will go inside nocscript element.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_no_lazyload_class( $images ) {
|
||||
$parsed = ( new Parser() )->get_images_from_content( $images );
|
||||
|
||||
if ( empty( $parsed ) ) {
|
||||
return $images;
|
||||
}
|
||||
|
||||
foreach ( $parsed[0] as $image ) {
|
||||
$original = $image;
|
||||
$class = Parser::get_attribute( $image, 'class' );
|
||||
if ( ! $class ) {
|
||||
Parser::add_attribute( $image, 'class', 'no-lazyload' );
|
||||
} else {
|
||||
Parser::add_attribute( $image, 'class', $class . ' no-lazyload' );
|
||||
}
|
||||
|
||||
$images = str_replace( $original, $image, $images );
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert URL to CDN link.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string $url Image URL.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function convert_url_to_cdn( $url ) {
|
||||
if ( ! $this->cdn->is_supported_path( $url ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->cdn->generate_cdn_url( $url );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration with Gravity Forms: Gravity_Forms class
|
||||
*
|
||||
* This integration will automatically compress images on Gravity Forms upload.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @package Smush\Core\Integrations
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use GFFormsModel;
|
||||
use Smush\Core\Core;
|
||||
use Smush\Core\Helper;
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Gravity_Forms for Gravity Forms integration.
|
||||
*
|
||||
* This integration will automatically compress images on Gravity Forms upload.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @see Abstract_Integration
|
||||
*/
|
||||
class Gravity_Forms extends Abstract_Integration {
|
||||
|
||||
/**
|
||||
* Gravity_Forms constructor.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->module = 'gform';
|
||||
$this->class = 'free';
|
||||
$this->enabled = defined( 'GF_SUPPORTED_WP_VERSION' ) && class_exists( 'GFForms' );
|
||||
|
||||
parent::__construct();
|
||||
|
||||
// Hook at the end of setting row to output an error div.
|
||||
add_action( 'smush_setting_column_right_inside', array( $this, 'additional_notice' ) );
|
||||
|
||||
// Return if Gravity Form integration or auto compression is not enabled.
|
||||
if ( ! $this->enabled || ! $this->settings->get( 'gform' ) || ! $this->settings->get( 'auto' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Track gravity form submission and validate if there is any image uploaded in Image or File Upload fields.
|
||||
add_action( 'gform_after_submission', array( $this, 'smush_gform_after_submission' ), 10, 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* ************************************
|
||||
*
|
||||
* OVERWRITE PARENT CLASS FUNCTIONALITY
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filters the setting variable to add Gravity Form setting title and description
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param array $settings Settings.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register( $settings ) {
|
||||
$settings[ $this->module ] = array(
|
||||
'label' => esc_html__( 'Enable Gravity Forms integration', 'wp-smushit' ),
|
||||
'short_label' => esc_html__( 'Gravity Forms', 'wp-smushit' ),
|
||||
'desc' => esc_html__( 'Allow compressing images uploaded with Gravity Forms.', 'wp-smushit' ),
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show additional notice if the required plugins are not installed.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param string $name Setting name.
|
||||
*/
|
||||
public function additional_notice( $name ) {
|
||||
if ( $this->module === $name && ! $this->enabled ) {
|
||||
?>
|
||||
<div class="sui-toggle-content">
|
||||
<div class="sui-notice">
|
||||
<div class="sui-notice-content">
|
||||
<div class="sui-notice-message">
|
||||
<i class="sui-notice-icon sui-icon-info" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e( 'To use this feature you need be using Gravity Forms.', 'wp-smushit' ); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing automatic image smush on Gravity Forms upload.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param Object $entry Entry Object.
|
||||
* @param Object $form Form Object.
|
||||
*/
|
||||
public function smush_gform_after_submission( $entry, $form ) {
|
||||
$fields = $form['fields'];
|
||||
|
||||
foreach ( $fields as $field ) {
|
||||
if ( 'fileupload' !== $field->type && 'post_image' !== $field->type ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'rgar' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$uploaded_files = rgar( $entry, $field->id );
|
||||
$uploaded_files = $this->smush_parse_files( $uploaded_files, $field );
|
||||
|
||||
if ( ! is_array( $uploaded_files ) || empty( $uploaded_files ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $uploaded_files as $_file ) {
|
||||
$dir = $this->get_gform_upload_dir( $form['id'] );
|
||||
|
||||
if ( ! $dir || ! isset( $dir['url'] ) || ! isset( $dir['path'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = str_replace( $dir['url'], $dir['path'], $_file );
|
||||
|
||||
// Get mime type from file path.
|
||||
$mime = Helper::get_mime_type( $file );
|
||||
|
||||
// If image file not exist or image type not supported.
|
||||
if ( ! file_exists( $file ) || ! in_array( $mime, Core::$mime_types, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WP_Smush::get_instance()->core()->mod->smush->do_smushit( $file );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upload directory url and path.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param int $form_id Form ID.
|
||||
* @return bool|array
|
||||
*/
|
||||
public function get_gform_upload_dir( $form_id ) {
|
||||
if ( ! class_exists( 'GFFormsModel' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dir = GFFormsModel::get_file_upload_path( $form_id, 'PLACEHOLDER' );
|
||||
$dir['path'] = dirname( $dir['path'] );
|
||||
$dir['url'] = dirname( $dir['url'] );
|
||||
|
||||
return $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsing uploaded files.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param mixed $files File path.
|
||||
* @param Object $field Form field object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function smush_parse_files( $files, $field ) {
|
||||
if ( empty( $files ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( $this->smush_is_json( $files ) ) {
|
||||
$files = json_decode( $files );
|
||||
} elseif ( 'post_image' === $field->get_input_type() ) {
|
||||
$file_bits = explode( '|:|', $files );
|
||||
$files = array( $file_bits[0] );
|
||||
} else {
|
||||
$files = array( $files );
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check entry files in JSON format.
|
||||
*
|
||||
* @since 3.9.10
|
||||
*
|
||||
* @param String $string File string.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function smush_is_json( $string ) {
|
||||
// Duplicate contents of GFCommon::is_json() here to supports versions of GF older than GF 2.5.
|
||||
if ( is_string( $string ) && in_array( substr( $string, 0, 1 ), array( '{', '[' ) ) && is_array( json_decode( $string, ARRAY_A ) ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
/**
|
||||
* Smush integration with Gutenberg editor: Gutenberg class
|
||||
*
|
||||
* @package Smush\Core\Integrations
|
||||
* @since 2.8.1
|
||||
*
|
||||
* @author Anton Vanyukov <anton@incsub.com>
|
||||
*
|
||||
* @copyright (c) 2018, Incsub (http://incsub.com)
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Gutenberg for Gutenberg integration.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*/
|
||||
class Gutenberg extends Abstract_Integration {
|
||||
|
||||
/**
|
||||
* Gutenberg constructor.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->module = 'gutenberg';
|
||||
$this->class = 'free';
|
||||
|
||||
$this->check_for_gutenberg();
|
||||
|
||||
parent::__construct();
|
||||
|
||||
if ( ! $this->enabled ) {
|
||||
// Disable setting if Gutenberg is not active.
|
||||
add_filter( 'wp_smush_integration_status_' . $this->module, '__return_true' );
|
||||
|
||||
// Hook at the end of setting row to output an error div.
|
||||
add_action( 'smush_setting_column_right_inside', array( $this, 'integration_error' ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Register gutenberg block assets.
|
||||
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_gb' ) );
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* OVERWRITE PARENT CLASS FUNCTIONALITY
|
||||
*/
|
||||
|
||||
/**
|
||||
* Filters the setting variable to add Gutenberg setting title and description.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*
|
||||
* @param array $settings Settings array.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function register( $settings ) {
|
||||
$settings[ $this->module ] = array(
|
||||
'label' => esc_html__( 'Show Smush stats in Gutenberg blocks', 'wp-smushit' ),
|
||||
'short_label' => esc_html__( 'Gutenberg Support', 'wp-smushit' ),
|
||||
'desc' => esc_html__(
|
||||
'Add statistics and the manual smush button to Gutenberg blocks that display images.',
|
||||
'wp-smushit'
|
||||
),
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* PUBLIC CLASSES
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prints the message for Gutenberg setup.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*
|
||||
* @param string $setting_key Settings key.
|
||||
*/
|
||||
public function integration_error( $setting_key ) {
|
||||
// Return if not Gutenberg integration.
|
||||
if ( $this->module !== $setting_key ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="sui-toggle-content">
|
||||
<div class="sui-notice">
|
||||
<div class="sui-notice-content">
|
||||
<div class="sui-notice-message">
|
||||
<i class="sui-notice-icon sui-icon-info" aria-hidden="true"></i>
|
||||
<p><?php esc_html_e( 'To use this feature you need to install and activate the Gutenberg plugin.', 'wp-smushit' ); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Gutenberg block assets for backend editor.
|
||||
*
|
||||
* `wp-blocks`: includes block type registration and related functions.
|
||||
* `wp-element`: includes the WordPress Element abstraction for describing the structure of your blocks.
|
||||
* `wp-i18n`: To internationalize the block's text.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*/
|
||||
public function enqueue_gb() {
|
||||
$enabled = $this->settings->get( $this->module );
|
||||
|
||||
if ( ! $enabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Gutenberg block scripts.
|
||||
wp_enqueue_script(
|
||||
'smush-gutenberg',
|
||||
WP_SMUSH_URL . 'app/assets/js/smush-blocks.min.js',
|
||||
array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
|
||||
WP_SMUSH_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
*
|
||||
* PRIVATE CLASSES
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make sure we only enqueue when Gutenberg is active.
|
||||
*
|
||||
* For WordPress pre 5.0 - only when Gutenberg plugin is installed.
|
||||
* For WordPress 5.0+ - only when Classic Editor is NOT installed.
|
||||
*
|
||||
* @since 3.0.2
|
||||
*/
|
||||
private function check_for_gutenberg() {
|
||||
global $wp_version;
|
||||
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
/* @noinspection PhpIncludeInspection */
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
// Check if WordPress 5.0 or higher.
|
||||
$is_wp5point0 = version_compare( $wp_version, '4.9.9', '>' );
|
||||
|
||||
if ( $is_wp5point0 ) {
|
||||
$this->enabled = ! is_plugin_active( 'classic-editor/classic-editor.php' );
|
||||
} else {
|
||||
$this->enabled = is_plugin_active( 'gutenberg/gutenberg.php' );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Integrations;
|
||||
|
||||
use Smush\Core\Helper;
|
||||
|
||||
/**
|
||||
* @method identify( int $user_id )
|
||||
* @method register( string $property, mixed $value )
|
||||
* @method registerAll( array $properties )
|
||||
* @method track( string $event, array $properties = array() )
|
||||
*/
|
||||
class Mixpanel {
|
||||
private $mixpanel;
|
||||
|
||||
public function __construct( $project_token ) {
|
||||
$this->mixpanel = class_exists( '\Mixpanel' ) && method_exists( '\Mixpanel', 'getInstance' )
|
||||
? \Mixpanel::getInstance( $project_token, array(
|
||||
'error_callback' => array( $this, 'handle_error' ),
|
||||
) )
|
||||
: null;
|
||||
}
|
||||
|
||||
public function handle_error( $code, $data ) {
|
||||
Helper::logger()->error( "$code: $data" );
|
||||
}
|
||||
|
||||
public function __call( $name, $arguments ) {
|
||||
if ( method_exists( $this->mixpanel, $name ) ) {
|
||||
return call_user_func_array(
|
||||
array( $this->mixpanel, $name ),
|
||||
$arguments
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
1126
wp-content/plugins/wp-smushit/core/integrations/class-nextgen.php
Normal file
1126
wp-content/plugins/wp-smushit/core/integrations/class-nextgen.php
Normal file
File diff suppressed because it is too large
Load Diff
1547
wp-content/plugins/wp-smushit/core/integrations/class-s3.php
Normal file
1547
wp-content/plugins/wp-smushit/core/integrations/class-s3.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,866 @@
|
||||
<?php
|
||||
/**
|
||||
* Adds the Bulk Page and Smush Column to NextGen Gallery
|
||||
*
|
||||
* @package Smush\Core\Integrations\NextGen
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Umesh Kumar <umesh@incsub.com>
|
||||
*
|
||||
* @copyright (c) 2016, Incsub (http://incsub.com)
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations\NextGen;
|
||||
|
||||
use C_Component_Registry;
|
||||
use C_Gallery_Storage;
|
||||
use nggdb;
|
||||
use Smush\App\Media_Library;
|
||||
use Smush\Core\Core;
|
||||
use Smush\Core\Helper;
|
||||
use Smush\Core\Integrations\NextGen;
|
||||
use Smush\Core\Settings;
|
||||
use stdClass;
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Admin
|
||||
*/
|
||||
class Admin extends NextGen {
|
||||
|
||||
/**
|
||||
* Total image count.
|
||||
*
|
||||
* @var int $total_count
|
||||
*/
|
||||
public $total_count = 0;
|
||||
|
||||
/**
|
||||
* Count of images ( Attachments ), Does not includes additional sizes that might have been created.
|
||||
*
|
||||
* @var int $smushed_count
|
||||
*/
|
||||
public $smushed_count = 0;
|
||||
|
||||
/**
|
||||
* Includes the count of different sizes an image might have
|
||||
*
|
||||
* @var int $image_count
|
||||
*/
|
||||
public $image_count = 0;
|
||||
|
||||
/**
|
||||
* Remaining count.
|
||||
*
|
||||
* @var int $remaining_count
|
||||
*/
|
||||
public $remaining_count = 0;
|
||||
|
||||
/**
|
||||
* Super Smushed.
|
||||
*
|
||||
* @var int $super_smushed
|
||||
*/
|
||||
public $super_smushed = 0;
|
||||
|
||||
/**
|
||||
* Smushed images.
|
||||
*
|
||||
* @var array $smushed
|
||||
*/
|
||||
public $smushed = array();
|
||||
|
||||
/**
|
||||
* Stores all lossless smushed IDs.
|
||||
*
|
||||
* @var array $resmush_ids
|
||||
*/
|
||||
public $resmush_ids = array();
|
||||
|
||||
/**
|
||||
* Stats class object.
|
||||
*
|
||||
* @var Stats
|
||||
*/
|
||||
public $ng_stats;
|
||||
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Admin constructor.
|
||||
*
|
||||
* @param Stats $stats Class object.
|
||||
*/
|
||||
public function __construct( Stats $stats ) {
|
||||
$this->ng_stats = $stats;
|
||||
$this->settings = Settings::get_instance();
|
||||
|
||||
// Update the number of columns.
|
||||
add_filter( 'ngg_manage_images_number_of_columns', array( $this, 'wp_smush_manage_images_number_of_columns' ) );
|
||||
|
||||
// Update resmush list, if a NextGen image is deleted.
|
||||
add_action( 'ngg_delete_picture', array( $this, 'update_resmush_list' ) );
|
||||
|
||||
// Update Stats, if a NextGen image is deleted.
|
||||
add_action( 'ngg_delete_picture', array( $this, 'update_nextgen_stats' ) );
|
||||
|
||||
// Update Stats, Lists - if a NextGen Gallery is deleted.
|
||||
add_action( 'ngg_delete_gallery', array( $this->ng_stats, 'update_stats_cache' ) );
|
||||
|
||||
// Update the Super Smush count, after the smushing.
|
||||
add_action( 'wp_smush_image_optimised_nextgen', array( $this, 'update_lists_after_optimizing' ), '', 2 );
|
||||
|
||||
// Reset smush data after restoring the image.
|
||||
add_action( 'ngg_recovered_image', array( $this, 'reset_smushdata' ) );
|
||||
|
||||
add_action( 'wp_ajax_nextgen_get_stats', array( $this, 'ajax_get_stats' ) );
|
||||
|
||||
add_filter( 'wp_smush_nextgen_scan_stats', array( $this, 'scan_images' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a column name for WP Smush.
|
||||
*
|
||||
* @param array $columns Current columns.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function wp_smush_image_column_name( $columns ) {
|
||||
// Latest next gen takes string, while the earlier WP Smush plugin shows there use to be a array.
|
||||
if ( is_array( $columns ) ) {
|
||||
$columns['wp_smush_image'] = esc_html__( 'Smush', 'wp-smushit' );
|
||||
} else {
|
||||
$columns = esc_html__( 'Smush', 'wp-smushit' );
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Smush option / Stats, depending if image is already smushed or not.
|
||||
*
|
||||
* @param string $column_name Column name.
|
||||
* @param object|int $id Image object or ID.
|
||||
*
|
||||
* @return array|bool|string|void
|
||||
*/
|
||||
public function wp_smush_column_options( $column_name, $id ) {
|
||||
// NExtGen Doesn't returns Column name, weird? yeah, right, it is proper because hook is called for the particular column.
|
||||
if ( 'wp_smush_image' === $column_name || '' === $column_name ) {
|
||||
// We're not using our in-house function Smush\Core\Integrations\Nextgen::get_nextgen_image_from_id()
|
||||
// as we're already instializing the nextgen gallery object, we need $storage instance later.
|
||||
// Registry Object for NextGen Gallery.
|
||||
$registry = C_Component_Registry::get_instance();
|
||||
|
||||
/**
|
||||
* Gallery Storage Object.
|
||||
*
|
||||
* @var C_Gallery_Storage $storage
|
||||
*/
|
||||
$storage = $registry->get_utility( 'I_Gallery_Storage' );
|
||||
|
||||
// We'll get the image object in $id itself, else fetch it using Gallery Storage.
|
||||
if ( is_object( $id ) ) {
|
||||
$image = $id;
|
||||
} else {
|
||||
// get an image object.
|
||||
$image = $storage->object->_image_mapper->find( $id );
|
||||
}
|
||||
|
||||
// Check if it is supported image format, get image type to do that get the absolute path.
|
||||
$file_path = $storage->get_image_abspath( $image, 'full' );
|
||||
|
||||
// Get image type from file path.
|
||||
$image_type = $this->get_file_type( $file_path );
|
||||
|
||||
// If image type not supported.
|
||||
if ( ! $image_type || ! in_array( $image_type, Core::$mime_types, true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$image->meta_data = $this->get_combined_stats( $image->meta_data );
|
||||
|
||||
// Check Image metadata, if smushed, print the stats or super smush button.
|
||||
if ( ! empty( $image->meta_data['wp_smush'] ) ) {
|
||||
// Echo the smush stats.
|
||||
return $this->show_stats( $image->pid, $image->meta_data['wp_smush'], $image_type );
|
||||
}
|
||||
|
||||
// Print the status of image, if Not smushed.
|
||||
return $this->set_status( $image->pid );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Localize Translations And Stats
|
||||
*/
|
||||
public function localize() {
|
||||
$handle = 'smush-admin';
|
||||
|
||||
$upgrade_url = add_query_arg(
|
||||
array(
|
||||
'utm_source' => 'smush',
|
||||
'utm_medium' => 'plugin',
|
||||
'utm_campaign' => 'smush_bulksmush_issues_filesizelimit_notice',
|
||||
),
|
||||
'https://wpmudev.com/project/wp-smush-pro/'
|
||||
);
|
||||
|
||||
if ( WP_Smush::is_pro() ) {
|
||||
$error_in_bulk = esc_html__( '{{smushed}}/{{total}} images were successfully compressed, {{errors}} encountered issues.', 'wp-smushit' );
|
||||
} else {
|
||||
$error_in_bulk = sprintf(
|
||||
/* translators: %1$s - opening link tag, %2$s - Close the link </a> */
|
||||
esc_html__( '{{smushed}}/{{total}} images were successfully compressed, {{errors}} encountered issues. Are you hitting the 5MB "size limit exceeded" warning? %1$sUpgrade to Smush Pro%2$s to optimize unlimited image files.', 'wp-smushit' ),
|
||||
'<a href="' . esc_url( $upgrade_url ) . '" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
|
||||
$wp_smush_msgs = array(
|
||||
'nonce' => wp_create_nonce( 'wp-smush-ajax' ),
|
||||
'resmush' => esc_html__( 'Super-Smush', 'wp-smushit' ),
|
||||
'smush_now' => esc_html__( 'Smush Now', 'wp-smushit' ),
|
||||
'error_in_bulk' => $error_in_bulk,
|
||||
'all_resmushed' => esc_html__( 'All images are fully optimized.', 'wp-smushit' ),
|
||||
'restore' => esc_html__( 'Restoring image...', 'wp-smushit' ),
|
||||
'smushing' => esc_html__( 'Smushing image...', 'wp-smushit' ),
|
||||
);
|
||||
|
||||
wp_localize_script( $handle, 'wp_smush_msgs', $wp_smush_msgs );
|
||||
|
||||
$data = $this->ng_stats->get_global_stats();
|
||||
|
||||
wp_localize_script( $handle, 'wp_smushit_data', $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the count of columns for Nextgen Gallery Manage page.
|
||||
*
|
||||
* @param int $count Current columns count.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function wp_smush_manage_images_number_of_columns( $count ) {
|
||||
$count ++;
|
||||
|
||||
// Add column Heading.
|
||||
add_filter( "ngg_manage_images_column_{$count}_header", array( $this, 'wp_smush_image_column_name' ) );
|
||||
|
||||
// Add Column data.
|
||||
add_filter( "ngg_manage_images_column_{$count}_content", array( $this, 'wp_smush_column_options' ), 10, 2 );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set send button status
|
||||
*
|
||||
* @param int $pid ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function set_status( $pid ) {
|
||||
// the status.
|
||||
$status_txt = __( 'Not processed', 'wp-smushit' );
|
||||
|
||||
// we need to show the smush button.
|
||||
$show_button = true;
|
||||
|
||||
// the button text.
|
||||
$button_txt = __( 'Smush', 'wp-smushit' );
|
||||
|
||||
// If we are not showing smush button, append progress bar, else it is already there.
|
||||
if ( ! $show_button ) {
|
||||
$status_txt .= Media_Library::progress_bar();
|
||||
}
|
||||
|
||||
return $this->column_html( $pid, $status_txt, $button_txt, $show_button );
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the column html
|
||||
*
|
||||
* @param string $pid Media id.
|
||||
* @param string $status_txt Status text.
|
||||
* @param string $button_txt Button label.
|
||||
* @param boolean $show_button Whether to shoe the button.
|
||||
* @param bool $smushed Image compressed or not.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function column_html( $pid, $status_txt = '', $button_txt = '', $show_button = true, $smushed = false ) {
|
||||
$class = $smushed ? '' : ' sui-hidden';
|
||||
$html = '<p class="smush-status' . $class . '">' . $status_txt . '</p>';
|
||||
|
||||
// if we aren't showing the button.
|
||||
if ( ! $show_button ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
$html .= '<div class="sui-smush-media smush-status-links">';
|
||||
$html .= wp_nonce_field( 'wp_smush_nextgen', '_wp_smush_nonce', '', false );
|
||||
$html .= '<button class="button button-primary wp-smush-nextgen-send" data-id="' . $pid . '">
|
||||
<span>' . $button_txt . '</span>
|
||||
</button>';
|
||||
$html .= '</div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the resmush list for NextGen gallery, remove the given id
|
||||
*
|
||||
* @param int $attachment_id Attachment ID.
|
||||
*/
|
||||
public function update_resmush_list( $attachment_id ) {
|
||||
if ( $this->ng_stats->get_reoptimize_list()->has_id( $attachment_id ) ) {
|
||||
return $this->ng_stats->get_reoptimize_list()->remove_id( $attachment_id );
|
||||
}
|
||||
return $this->ng_stats->get_reoptimize_list()->add_id( $attachment_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the stats for the given attachment id, and subtract them from Global stats
|
||||
*
|
||||
* @param int $attachment_id Attachment ID.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update_nextgen_stats( $attachment_id ) {
|
||||
if ( empty( $attachment_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$image_id = absint( (int) $attachment_id );
|
||||
|
||||
// Get the absolute path for original image.
|
||||
$image = $this->get_nextgen_image_from_id( $image_id );
|
||||
|
||||
// Image Metadata.
|
||||
$metadata = ! empty( $image ) ? $image->meta_data : '';
|
||||
|
||||
$smush_stats = ! empty( $metadata['wp_smush'] ) ? $metadata['wp_smush'] : '';
|
||||
|
||||
if ( empty( $smush_stats ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nextgen_stats = get_option( 'wp_smush_stats_nextgen', false );
|
||||
if ( ! $nextgen_stats ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! empty( $nextgen_stats['size_before'] ) && ! empty( $nextgen_stats['size_after'] ) && $nextgen_stats['size_before'] > 0 && $nextgen_stats['size_after'] > 0 && $nextgen_stats['size_before'] >= $smush_stats['stats']['size_before'] ) {
|
||||
$nextgen_stats['size_before'] = $nextgen_stats['size_before'] - $smush_stats['stats']['size_before'];
|
||||
$nextgen_stats['size_after'] = $nextgen_stats['size_after'] - $smush_stats['stats']['size_after'];
|
||||
$nextgen_stats['bytes'] = $nextgen_stats['size_before'] - $nextgen_stats['size_after'];
|
||||
if ( 0 === $nextgen_stats['bytes'] && 0 === $nextgen_stats['size_before'] ) {
|
||||
$nextgen_stats['percent'] = 0;
|
||||
} else {
|
||||
$nextgen_stats['percent'] = ( $nextgen_stats['bytes'] / $nextgen_stats['size_before'] ) * 100;
|
||||
}
|
||||
$nextgen_stats['human'] = size_format( $nextgen_stats['bytes'], 1 );
|
||||
}
|
||||
|
||||
// Update Stats.
|
||||
update_option( 'wp_smush_stats_nextgen', $nextgen_stats, false );
|
||||
|
||||
// Remove from Super Smush list.
|
||||
$this->ng_stats->get_supper_smushed_list()->remove_id( $image_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Super Smush count for NextGen Gallery
|
||||
*
|
||||
* @param int $image_id Image ID.
|
||||
* @param array $stats Stats.
|
||||
*/
|
||||
public function update_lists_after_optimizing( $image_id, $stats ) {
|
||||
if ( isset( $stats['stats']['lossy'] ) && 1 === (int) $stats['stats']['lossy'] ) {
|
||||
$this->ng_stats->get_supper_smushed_list()->add_id( $image_id );
|
||||
}
|
||||
$this->update_resmush_list( $image_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize NextGen Gallery Stats
|
||||
*/
|
||||
public function setup_image_counts() {
|
||||
$this->total_count = $this->ng_stats->total_count();
|
||||
$this->smushed_count = $this->ng_stats->get_smushed_count();
|
||||
$this->image_count = $this->ng_stats->get_smushed_image_count();
|
||||
$this->resmush_ids = $this->ng_stats->get_reoptimize_list()->get_ids();
|
||||
$this->super_smushed = $this->ng_stats->get_supper_smushed_count();
|
||||
$this->remaining_count = $this->ng_stats->get_remaining_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image count for nextgen images
|
||||
*
|
||||
* @param array $images Array of attachments to get the image count for.
|
||||
* @param bool $exclude_resmush_ids Whether to exclude resmush ids or not.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_image_count( $images = array(), $exclude_resmush_ids = true ) {
|
||||
if ( empty( $images ) || ! is_array( $images ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$image_count = 0;
|
||||
// $image in here is expected to be metadata array
|
||||
foreach ( $images as $image_k => $image ) {
|
||||
// Get image object if not there already.
|
||||
if ( ! is_array( $image ) ) {
|
||||
$image = $this->get_nextgen_image_from_id( $image );
|
||||
// Get the meta.
|
||||
$image = ! empty( $image->meta_data ) ? $image->meta_data : '';
|
||||
}
|
||||
// If there are no smush stats, skip.
|
||||
if ( empty( $image['wp_smush'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If resmush ids needs to be excluded.
|
||||
if ( $exclude_resmush_ids && ( ! empty( $this->resmush_ids ) && in_array( $image_k, $this->resmush_ids ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the image count.
|
||||
if ( ! empty( $image['wp_smush']['sizes'] ) ) {
|
||||
$image_count += count( $image['wp_smush']['sizes'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $image_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the resizing stats and smush stats , One time operation - performed during the image optimization
|
||||
*
|
||||
* @param array $metadata Image metadata.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function get_combined_stats( $metadata ) {
|
||||
if ( empty( $metadata ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
$smush_stats = ! empty( $metadata['wp_smush'] ) ? $metadata['wp_smush'] : '';
|
||||
$resize_savings = ! empty( $metadata['wp_smush_resize_savings'] ) ? $metadata['wp_smush_resize_savings'] : '';
|
||||
|
||||
if ( empty( $resize_savings ) || empty( $smush_stats ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
$smush_stats['stats']['bytes'] = ! empty( $resize_savings['bytes'] ) ? $smush_stats['stats']['bytes'] + $resize_savings['bytes'] : $smush_stats['stats']['bytes'];
|
||||
$smush_stats['stats']['size_before'] = ! empty( $resize_savings['size_before'] ) ? $smush_stats['stats']['size_before'] + $resize_savings['size_before'] : $smush_stats['stats']['size_before'];
|
||||
$smush_stats['stats']['size_after'] = ! empty( $resize_savings['size_after'] ) ? $smush_stats['stats']['size_after'] + $resize_savings['size_after'] : $smush_stats['stats']['size_after'];
|
||||
$smush_stats['stats']['percent'] = ! empty( $resize_savings['size_before'] ) ? ( $smush_stats['stats']['bytes'] / $smush_stats['stats']['size_before'] ) * 100 : $smush_stats['stats']['percent'];
|
||||
|
||||
// Round off.
|
||||
$smush_stats['stats']['percent'] = round( $smush_stats['stats']['percent'], 2 );
|
||||
|
||||
if ( ! empty( $smush_stats['sizes']['full'] ) ) {
|
||||
// Full Image.
|
||||
$smush_stats['sizes']['full']['bytes'] = ! empty( $resize_savings['bytes'] ) ? $smush_stats['sizes']['full']['bytes'] + $resize_savings['bytes'] : $smush_stats['sizes']['full']['bytes'];
|
||||
$smush_stats['sizes']['full']['size_before'] = ! empty( $resize_savings['size_before'] ) ? $smush_stats['sizes']['full']['size_before'] + $resize_savings['size_before'] : $smush_stats['sizes']['full']['size_before'];
|
||||
$smush_stats['sizes']['full']['size_after'] = ! empty( $resize_savings['size_after'] ) ? $smush_stats['sizes']['full']['size_after'] + $resize_savings['size_after'] : $smush_stats['sizes']['full']['size_after'];
|
||||
$smush_stats['sizes']['full']['percent'] = ! empty( $smush_stats['sizes']['full']['bytes'] ) && $smush_stats['sizes']['full']['size_before'] > 0 ? ( $smush_stats['sizes']['full']['bytes'] / $smush_stats['sizes']['full']['size_before'] ) * 100 : $smush_stats['sizes']['full']['percent'];
|
||||
|
||||
$smush_stats['sizes']['full']['percent'] = round( $smush_stats['sizes']['full']['percent'], 2 );
|
||||
} else {
|
||||
$smush_stats['sizes']['full'] = $resize_savings;
|
||||
}
|
||||
|
||||
$metadata['wp_smush'] = $smush_stats;
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset smush data after restoring the image.
|
||||
*
|
||||
* @since 3.10.0
|
||||
*
|
||||
* @param stdClass $image Image object for NextGen gallery.
|
||||
* @param false|string $attachment_file_path The full file path, if it's provided we will reset the dimension.
|
||||
*/
|
||||
public function reset_smushdata( $image, $attachment_file_path = false ) {
|
||||
if ( empty( $image->meta_data['wp_smush'] ) && empty( $image->meta_data['wp_smush_resize_savings'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ng_stats->subtract_image_stats( $image );
|
||||
|
||||
// Remove the Meta, And send json success.
|
||||
$image->meta_data['wp_smush'] = '';
|
||||
|
||||
// Remove resized data.
|
||||
if ( ! empty( $image->meta_data['wp_smush_resize_savings'] ) ) {
|
||||
$image->meta_data['wp_smush_resize_savings'] = '';
|
||||
|
||||
if ( $attachment_file_path && file_exists( $attachment_file_path ) ) {
|
||||
// Update the dimension.
|
||||
list( $width, $height ) = getimagesize( $attachment_file_path );
|
||||
if ( $width ) {
|
||||
$image->meta_data['width'] = $width;
|
||||
$image->meta_data['full']['width'] = $width;
|
||||
}
|
||||
if ( $height ) {
|
||||
$image->meta_data['height'] = $height;
|
||||
$image->meta_data['full']['height'] = $height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update metadata.
|
||||
nggdb::update_image_meta( $image->pid, $image->meta_data );
|
||||
|
||||
/**
|
||||
* Called after the image has been successfully restored
|
||||
*
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @param int $image_id ID of the restored image.
|
||||
*/
|
||||
do_action( 'wp_smush_image_nextgen_restored', $image->pid );
|
||||
}
|
||||
|
||||
public function ajax_get_stats() {
|
||||
check_ajax_referer( 'wp-smush-ajax', '_nonce' );
|
||||
|
||||
// Check capability.
|
||||
if ( ! Helper::is_user_allowed( 'manage_options' ) ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'notice' => esc_html__( "You don't have permission to do this.", 'wp-smushit' ),
|
||||
'noticeType' => 'error',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$stats = $this->get_global_stats_with_bulk_smush_content_and_notice();
|
||||
|
||||
wp_send_json_success( $stats );
|
||||
}
|
||||
|
||||
private function get_global_stats_with_bulk_smush_content_and_notice() {
|
||||
$stats = $this->get_global_stats_with_bulk_smush_content();
|
||||
$remaining_count = $stats['remaining_count'];
|
||||
|
||||
if ( $remaining_count > 0 ) {
|
||||
$stats['noticeType'] = 'warning';
|
||||
$stats['notice'] = sprintf(
|
||||
/* translators: %1$d - number of images, %2$s - opening a tag, %3$s - closing a tag */
|
||||
esc_html__( 'Image check complete, you have %1$d images that need smushing. %2$sBulk smush now!%3$s', 'wp-smushit' ),
|
||||
$remaining_count,
|
||||
'<a href="#" class="wp-smush-trigger-nextgen-bulk">',
|
||||
'</a>'
|
||||
);
|
||||
} else {
|
||||
$stats['notice'] = esc_html__( 'Yay! All images are optimized as per your current settings.', 'wp-smushit' );
|
||||
$stats['noticeType'] = 'success';
|
||||
}
|
||||
return $stats;
|
||||
}
|
||||
|
||||
private function get_global_stats_with_bulk_smush_content() {
|
||||
$stats = $this->ng_stats->get_global_stats();
|
||||
$remaining_count = $stats['remaining_count'];
|
||||
$reoptimize_count = $stats['count_resmush'];
|
||||
$optimize_count = $stats['count_unsmushed'];
|
||||
|
||||
if ( $remaining_count > 0 ) {
|
||||
ob_start();
|
||||
WP_Smush::get_instance()->admin()->print_pending_bulk_smush_content(
|
||||
$remaining_count,
|
||||
$reoptimize_count,
|
||||
$optimize_count
|
||||
);
|
||||
$content = ob_get_clean();
|
||||
$stats['content'] = $content;
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
public function scan_images() {
|
||||
$resmush_list = array();
|
||||
$attachments = $this->ng_stats->get_ngg_images();
|
||||
// Check if any of the smushed image needs to be resmushed.
|
||||
if ( ! empty( $attachments ) && is_array( $attachments ) ) {
|
||||
foreach ( $attachments as $attachment_k => $metadata ) {
|
||||
$smush_data = ! empty( $metadata['wp_smush'] ) ? $metadata['wp_smush'] : array();
|
||||
if ( $this->should_resmush( $smush_data ) ) {
|
||||
$resmush_list[] = $attachment_k;
|
||||
}
|
||||
}// End of Foreach Loop
|
||||
|
||||
// Store the resmush list in Options table.
|
||||
$this->ng_stats->get_reoptimize_list()->update_ids( $resmush_list );
|
||||
}
|
||||
|
||||
// Delete resmush list if empty.
|
||||
if ( empty( $resmush_list ) ) {
|
||||
$this->ng_stats->get_reoptimize_list()->delete_ids();
|
||||
}
|
||||
|
||||
return $this->get_global_stats_with_bulk_smush_content_and_notice();
|
||||
}
|
||||
|
||||
private function should_resmush( $smush_data ) {
|
||||
if ( empty( $smush_data['stats'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->lossy_optimization_required( $smush_data )
|
||||
|| $this->strip_exif_optimization_required( $smush_data )
|
||||
|| $this->original_optimization_required( $smush_data );
|
||||
}
|
||||
|
||||
private function lossy_optimization_required( $smush_data ) {
|
||||
$required_lossy_level = $this->settings->get_lossy_level_setting();
|
||||
$current_lossy_level = ! empty( $smush_data['stats']['lossy'] ) ? (int) $smush_data['stats']['lossy'] : 0;
|
||||
return $current_lossy_level < $required_lossy_level;
|
||||
}
|
||||
|
||||
private function strip_exif_optimization_required( $smush_data ) {
|
||||
return $this->settings->get( 'strip_exif' ) && ! empty( $smush_data['stats']['keep_exif'] ) && ( 1 === (int) $smush_data['stats']['keep_exif'] );
|
||||
}
|
||||
|
||||
private function original_optimization_required( $smush_data ) {
|
||||
return $this->settings->get( 'original' ) && empty( $smush_data['sizes']['full'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the smush stats for the image
|
||||
*
|
||||
* @param int $pid Image Id stored in nextgen table.
|
||||
* @param bool|array $wp_smush_data Stats, stored after smushing the image.
|
||||
* @param string $image_type Used for determining if not gif, to show the Super Smush button.
|
||||
*
|
||||
* @uses Admin::column_html(), WP_Smush::get_restore_link(), WP_Smush::get_resmush_link()
|
||||
*
|
||||
* @return bool|array|string
|
||||
*/
|
||||
public function show_stats( $pid, $wp_smush_data = false, $image_type = '' ) {
|
||||
if ( empty( $wp_smush_data ) ) {
|
||||
return false;
|
||||
}
|
||||
$button_txt = '';
|
||||
$show_button = false;
|
||||
$show_resmush = false;
|
||||
|
||||
$bytes = isset( $wp_smush_data['stats']['bytes'] ) ? $wp_smush_data['stats']['bytes'] : 0;
|
||||
$bytes_readable = ! empty( $bytes ) ? size_format( $bytes, 1 ) : '';
|
||||
$percent = isset( $wp_smush_data['stats']['percent'] ) ? $wp_smush_data['stats']['percent'] : 0;
|
||||
$percent = $percent < 0 ? 0 : $percent;
|
||||
|
||||
$status_txt = '';
|
||||
if ( isset( $wp_smush_data['stats']['size_before'] ) && $wp_smush_data['stats']['size_before'] == 0 && ! empty( $wp_smush_data['sizes'] ) ) {
|
||||
$status_txt = __( 'Already Optimized', 'wp-smushit' );
|
||||
} else {
|
||||
if ( 0 === (int) $bytes || 0 === (int) $percent ) {
|
||||
$status_txt = __( 'Already Optimized', 'wp-smushit' );
|
||||
|
||||
// Add resmush option if needed.
|
||||
$show_resmush = $this->should_resmush( $wp_smush_data );
|
||||
if ( $show_resmush ) {
|
||||
$status_txt .= '<div class="sui-smush-media smush-status-links">';
|
||||
$status_txt .= $this->get_resmsuh_link( $pid );
|
||||
$status_txt .= '</div>';
|
||||
}
|
||||
} elseif ( ! empty( $percent ) && ! empty( $bytes_readable ) ) {
|
||||
$status_txt = sprintf( /* translators: %1$s: reduced by bytes, %2$s: size format */
|
||||
__( 'Reduced by %1$s (%2$01.1f%%)', 'wp-smushit' ),
|
||||
$bytes_readable,
|
||||
number_format_i18n( $percent, 2 )
|
||||
);
|
||||
$status_txt .= '<div class="sui-smush-media smush-status-links">';
|
||||
|
||||
$show_resmush = $this->should_resmush( $wp_smush_data );
|
||||
|
||||
if ( $show_resmush ) {
|
||||
$status_txt .= $this->get_resmsuh_link( $pid );
|
||||
}
|
||||
|
||||
// Restore Image: Check if we need to show the restore image option.
|
||||
$show_restore = $this->show_restore_option( $pid, $wp_smush_data );
|
||||
|
||||
if ( $show_restore ) {
|
||||
if ( $show_resmush ) {
|
||||
// Show Separator.
|
||||
$status_txt .= ' | ';
|
||||
}
|
||||
$status_txt .= $this->get_restore_link( $pid );
|
||||
}
|
||||
// Show detailed stats if available.
|
||||
if ( ! empty( $wp_smush_data['sizes'] ) ) {
|
||||
if ( $show_resmush || $show_restore ) {
|
||||
// Show Separator.
|
||||
$status_txt .= ' | ';
|
||||
} else {
|
||||
// Show the link in next line.
|
||||
$status_txt .= '<br />';
|
||||
}
|
||||
// Detailed Stats Link.
|
||||
$status_txt .= '<a href="#" class="smush-stats-details">' . esc_html__( 'Smush stats', 'wp-smushit' ) . ' [<span class="stats-toggle">+</span>]</a>';
|
||||
|
||||
// Get metadata For the image
|
||||
// Registry Object for NextGen Gallery.
|
||||
$registry = C_Component_Registry::get_instance();
|
||||
|
||||
/**
|
||||
* Gallery Storage Object.
|
||||
*
|
||||
* @var C_Gallery_Storage $storage
|
||||
*/
|
||||
$storage = $registry->get_utility( 'I_Gallery_Storage' );
|
||||
|
||||
// get an array of sizes available for the $image.
|
||||
$sizes = $storage->get_image_sizes();
|
||||
|
||||
$image = $storage->object->_image_mapper->find( $pid );
|
||||
|
||||
$full_image = $storage->get_image_abspath( $image, 'full' );
|
||||
|
||||
// Stats.
|
||||
$stats = $this->get_detailed_stats( $pid, $wp_smush_data, array( 'sizes' => $sizes ), $full_image );
|
||||
|
||||
$status_txt .= $stats;
|
||||
$status_txt .= '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If show button is true for some reason, column html can print out the button for us.
|
||||
return $this->column_html( $pid, $status_txt, $button_txt, $show_button, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Stats for a image formatted into a nice table
|
||||
*
|
||||
* @param int $image_id Image ID.
|
||||
* @param array $wp_smush_data Smush data.
|
||||
* @param array $attachment_metadata Attachment metadata.
|
||||
* @param string $full_image Full sized image.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_detailed_stats( $image_id, $wp_smush_data, $attachment_metadata, $full_image ) {
|
||||
$stats = '<div id="smush-stats-' . $image_id . '" class="smush-stats-wrapper hidden">
|
||||
<table class="wp-smush-stats-holder">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><strong>' . esc_html__( 'Image size', 'wp-smushit' ) . '</strong></th>
|
||||
<th><strong>' . esc_html__( 'Savings', 'wp-smushit' ) . '</strong></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
$size_stats = $wp_smush_data['sizes'];
|
||||
|
||||
// Reorder Sizes as per the maximum savings.
|
||||
uasort( $size_stats, array( $this, 'cmp' ) );
|
||||
|
||||
// Show Sizes and their compression.
|
||||
foreach ( $size_stats as $size_key => $size_value ) {
|
||||
$size_value = ! is_object( $size_value ) ? (object) $size_value : $size_value;
|
||||
if ( $size_value->bytes > 0 ) {
|
||||
$stats .= '<tr>
|
||||
<td>' . strtoupper( $size_key ) . '</td>
|
||||
<td>' . size_format( $size_value->bytes, 1 );
|
||||
|
||||
}
|
||||
|
||||
// Add percentage if set.
|
||||
if ( isset( $size_value->percent ) && $size_value->percent > 0 ) {
|
||||
$stats .= " ( $size_value->percent% )";
|
||||
}
|
||||
|
||||
$stats .= '</td>
|
||||
</tr>';
|
||||
}
|
||||
$stats .= '</tbody>
|
||||
</table>
|
||||
</div>';
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare Values
|
||||
*
|
||||
* @param object|array $a First object.
|
||||
* @param object|array $b Second object.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function cmp( $a, $b ) {
|
||||
if ( is_object( $a ) ) {
|
||||
// Check and typecast $b if required.
|
||||
$b = is_object( $b ) ? $b : (object) $b;
|
||||
|
||||
return $b->bytes - $a->bytes ;
|
||||
} elseif ( is_array( $a ) ) {
|
||||
$b = is_array( $b ) ? $b : (array) $b;
|
||||
|
||||
return $b['bytes'] - $a['bytes'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a Resmush link for a image.
|
||||
*
|
||||
* @param int $image_id Attachment ID.
|
||||
* @param string $type Type of attachment.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function get_resmsuh_link( $image_id ) {
|
||||
if ( empty( $image_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$class = 'wp-smush-action wp-smush-title sui-tooltip sui-tooltip-constrained wp-smush-nextgen-resmush';
|
||||
|
||||
return sprintf(
|
||||
'<a href="#" data-tooltip="%s" data-id="%d" data-nonce="%s" class="%s">%s</a>',
|
||||
esc_html__( 'Smush image including original file', 'wp-smushit' ),
|
||||
$image_id,
|
||||
wp_create_nonce( 'wp-smush-resmush-' . $image_id ),
|
||||
$class,
|
||||
esc_html__( 'Resmush', 'wp-smushit' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a restore link for given image id
|
||||
*
|
||||
* @param int $image_id Attachment ID.
|
||||
* @param string $type Attachment type.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function get_restore_link( $image_id ) {
|
||||
if ( empty( $image_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$class = 'wp-smush-action wp-smush-title sui-tooltip wp-smush-nextgen-restore';
|
||||
|
||||
return sprintf(
|
||||
'<a href="#" data-tooltip="%s" data-id="%d" data-nonce="%s" class="%s">%s</a>',
|
||||
esc_html__( 'Restore original image', 'wp-smushit' ),
|
||||
$image_id,
|
||||
wp_create_nonce( 'wp-smush-restore-' . $image_id ),
|
||||
$class,
|
||||
esc_html__( 'Restore', 'wp-smushit' )
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,686 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles all the stats related functions
|
||||
*
|
||||
* @package Smush\Core\Integrations\NextGen
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Umesh Kumar <umesh@incsub.com>
|
||||
*
|
||||
* @copyright (c) 2016, Incsub (http://incsub.com)
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations\NextGen;
|
||||
|
||||
use C_Component_Registry;
|
||||
use C_Gallery_Storage;
|
||||
use C_NextGen_Serializable;
|
||||
use Exception;
|
||||
use Ngg_Serializable;
|
||||
use Smush\Core\Attachment_Id_List;
|
||||
use Smush\Core\Integrations\NextGen;
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class
|
||||
*
|
||||
* TODO refactor stats by using the new core stats to clean the code.
|
||||
*/
|
||||
class Stats extends NextGen {
|
||||
|
||||
const REOPTIMIZE_LIST_OPTION_ID = 'wp-smush-nextgen-reoptimize-list';
|
||||
|
||||
const SUPPER_SMUSHED_LIST_OPTION_ID = 'wp-smush-nextgen-super-smushed-list';
|
||||
|
||||
const SMUSH_STATS_OPTION_ID = 'wp_smush_stats_nextgen';
|
||||
|
||||
/**
|
||||
* Contains the total Stats, for displaying it on bulk page
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $stats = array();
|
||||
|
||||
/**
|
||||
* PRO user status.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_pro_user;
|
||||
|
||||
/**
|
||||
* @var Attachment_Id_List
|
||||
*/
|
||||
private $reoptimize_list;
|
||||
|
||||
/**
|
||||
* @var Attachment_Id_List
|
||||
*/
|
||||
private $supper_smushed_list;
|
||||
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
private $global_stats;
|
||||
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
private $unsmushed_images;
|
||||
|
||||
/**
|
||||
* @var null|int.
|
||||
*/
|
||||
private $remaining_count;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $percent_optimized = 0;
|
||||
|
||||
/**
|
||||
* Stats constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->is_pro_user = WP_Smush::is_pro();
|
||||
$this->reoptimize_list = new Attachment_Id_List( self::REOPTIMIZE_LIST_OPTION_ID );
|
||||
$this->supper_smushed_list = new Attachment_Id_List( self::SUPPER_SMUSHED_LIST_OPTION_ID );
|
||||
|
||||
|
||||
// Clear stats cache when an image is restored.
|
||||
add_action( 'wp_smush_image_nextgen_restored', array( $this, 'clear_cache' ) );
|
||||
|
||||
// Add the resizing stats to Global stats.
|
||||
add_action( 'wp_smush_image_nextgen_resized', array( $this, 'update_stats' ), '', 2 );
|
||||
|
||||
// Get the stats for single image, update the global stats.
|
||||
add_action( 'wp_smush_nextgen_image_stats', array( $this, 'update_stats' ), '', 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the images id for nextgen gallery
|
||||
*
|
||||
* @param bool $force_refresh Optional. Whether to force the cache to be refreshed.
|
||||
* Default false.
|
||||
*
|
||||
* @param bool $return_ids Whether to return the ids array, set to false by default.
|
||||
*
|
||||
* @return int|mixed Returns the images ids or the count
|
||||
*/
|
||||
public static function total_count( $force_refresh = false, $return_ids = false ) {
|
||||
// Check for the wp_smush_images in the 'nextgen' group.
|
||||
$attachment_ids = wp_cache_get( 'wp_smush_images', 'nextgen' );
|
||||
|
||||
// If nothing is found, build the object.
|
||||
if ( true === $force_refresh || false === $attachment_ids ) {
|
||||
// Get the nextgen image IDs.
|
||||
$attachment_ids = self::get_nextgen_attachments();
|
||||
|
||||
if ( ! is_wp_error( $attachment_ids ) ) {
|
||||
// In this case we don't need a timed cache expiration.
|
||||
wp_cache_set( 'wp_smush_images', $attachment_ids, 'nextgen' );
|
||||
}
|
||||
}
|
||||
|
||||
return $return_ids ? $attachment_ids : count( $attachment_ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ngg images list(id and meta ) or count
|
||||
*
|
||||
* @param string $type Whether to return smushed images or unsmushed images.
|
||||
* @param bool|false $count Return count only.
|
||||
* @param bool|false $force_update True/false to update the cache or not.
|
||||
*
|
||||
* @return bool|mixed Returns assoc array of image ids and meta or Image count
|
||||
*
|
||||
* @throws Exception Exception.
|
||||
*/
|
||||
public function get_ngg_images( $type = 'smushed', $count = false, $force_update = false ) {
|
||||
global $wpdb;
|
||||
|
||||
$limit = apply_filters( 'wp_smush_nextgen_query_limit', 1000 );
|
||||
$offset = 0;
|
||||
|
||||
// Check type of images being queried.
|
||||
if ( ! in_array( $type, array( 'smushed', 'unsmushed' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for the wp_smush_images_smushed in the 'nextgen' group.
|
||||
$images = wp_cache_get( 'wp_smush_images_' . $type, 'nextgen' );
|
||||
|
||||
// If nothing is found, build the object.
|
||||
if ( ! $images || $force_update ) {
|
||||
// Query Attachments for meta key.
|
||||
$attachments = $wpdb->get_results( $wpdb->prepare( "SELECT pid, meta_data FROM {$wpdb->nggpictures} LIMIT %d, %d", $offset, $limit ) ); // Db call ok.
|
||||
while ( ! empty( $attachments ) ) {
|
||||
foreach ( $attachments as $attachment ) {
|
||||
// Check if it has `wp_smush` key.
|
||||
if ( class_exists( 'Ngg_Serializable' ) ) {
|
||||
$meta = ( new Ngg_Serializable() )->unserialize( $attachment->meta_data );
|
||||
} elseif ( class_exists( 'C_NextGen_Serializable' ) && method_exists( 'C_NextGen_Serializable', 'unserialize' ) ) {
|
||||
$meta = C_NextGen_Serializable::unserialize( $attachment->meta_data );
|
||||
} else {
|
||||
// If you can't parse it without NextGen - don't parse at all.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store pid in image meta.
|
||||
if ( is_array( $meta ) && empty( $meta['pid'] ) ) {
|
||||
$meta['pid'] = $attachment->pid;
|
||||
} elseif ( is_object( $meta ) && empty( $meta->pid ) ) {
|
||||
$meta->pid = $attachment->pid;
|
||||
}
|
||||
|
||||
// Check meta for wp_smush.
|
||||
if ( ! is_array( $meta ) || empty( $meta['wp_smush'] ) ) {
|
||||
$unsmushed_images[ $attachment->pid ] = $meta;
|
||||
continue;
|
||||
}
|
||||
$smushed_images[ $attachment->pid ] = $meta;
|
||||
}
|
||||
// Set the offset.
|
||||
$offset += $limit;
|
||||
|
||||
$attachments = $wpdb->get_results( $wpdb->prepare( "SELECT pid, meta_data FROM {$wpdb->nggpictures} LIMIT %d, %d", $offset, $limit ) ); // Db call ok.
|
||||
}
|
||||
if ( ! empty( $smushed_images ) ) {
|
||||
wp_cache_set( 'wp_smush_images_smushed', $smushed_images, 'nextgen', 300 );
|
||||
}
|
||||
if ( ! empty( $unsmushed_images ) ) {
|
||||
wp_cache_set( 'wp_smush_images_unsmushed', $unsmushed_images, 'nextgen', 300 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'smushed' === $type ) {
|
||||
$smushed_images = ! empty( $smushed_images ) ? $smushed_images : $images;
|
||||
if ( ! $smushed_images ) {
|
||||
return 0;
|
||||
}
|
||||
return $count ? count( $smushed_images ) : $smushed_images;
|
||||
}
|
||||
|
||||
$unsmushed_images = ! empty( $unsmushed_images ) ? $unsmushed_images : $images;
|
||||
if ( ! $unsmushed_images ) {
|
||||
return 0;
|
||||
}
|
||||
return $count ? count( $unsmushed_images ) : $unsmushed_images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updated the global smush stats for NextGen gallery
|
||||
*
|
||||
* @param int $image_id Image ID.
|
||||
* @param array $stats Compression stats fo respective image.
|
||||
*/
|
||||
public function update_stats( $image_id, $stats ) {
|
||||
$stats = ! empty( $stats['stats'] ) ? $stats['stats'] : '';
|
||||
|
||||
$smush_stats = $this->get_cache_smush_stats();
|
||||
|
||||
if ( ! empty( $stats ) ) {
|
||||
// Human Readable.
|
||||
$smush_stats['human'] = ! empty( $smush_stats['bytes'] ) ? size_format( $smush_stats['bytes'], 1 ) : '';
|
||||
|
||||
// Size of images before the compression.
|
||||
$smush_stats['size_before'] = ! empty( $smush_stats['size_before'] ) ? ( $smush_stats['size_before'] + $stats['size_before'] ) : $stats['size_before'];
|
||||
|
||||
// Size of image after compression.
|
||||
$smush_stats['size_after'] = ! empty( $smush_stats['size_after'] ) ? ( $smush_stats['size_after'] + $stats['size_after'] ) : $stats['size_after'];
|
||||
|
||||
$smush_stats['bytes'] = ! empty( $smush_stats['size_before'] ) && ! empty( $smush_stats['size_after'] ) ? ( $smush_stats['size_before'] - $smush_stats['size_after'] ) : 0;
|
||||
|
||||
// Compression Percentage.
|
||||
$smush_stats['percent'] = ! empty( $smush_stats['size_before'] ) && ! empty( $smush_stats['size_after'] ) && $smush_stats['size_before'] > 0 ? ( $smush_stats['bytes'] / $smush_stats['size_before'] ) * 100 : $stats['percent'];
|
||||
}
|
||||
|
||||
update_option( self::SMUSH_STATS_OPTION_ID, $smush_stats, false );
|
||||
$this->clear_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the object cache for NextGen stats.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function clear_cache() {
|
||||
wp_cache_delete( 'wp_smush_images_smushed', 'nextgen' );
|
||||
wp_cache_delete( 'wp_smush_images_unsmushed', 'nextgen' );
|
||||
wp_cache_delete( 'wp_smush_images', 'nextgen' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachment stats for a image
|
||||
*
|
||||
* @param object|array|int $id Attachment ID.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_attachment_stats( $image ) {
|
||||
// We'll get the image object in $image itself, else fetch it using Gallery Storage.
|
||||
if ( is_numeric( $image ) ) {
|
||||
// Registry Object for NextGen Gallery.
|
||||
$registry = C_Component_Registry::get_instance();
|
||||
|
||||
// Gallery Storage Object.
|
||||
$storage = $registry->get_utility( 'I_Gallery_Storage' );
|
||||
|
||||
// get an image object.
|
||||
$image = $storage->object->_image_mapper->find( $image );
|
||||
}
|
||||
|
||||
$smush_savings = $this->get_image_smush_savings( $image );
|
||||
$resize_savings = $this->get_image_resize_savings( $image );
|
||||
|
||||
return $this->recalculate_stats( 'add', $smush_savings, $resize_savings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Nextgen Smush stats
|
||||
*
|
||||
* @return bool|mixed|void
|
||||
*/
|
||||
public function get_smush_stats() {
|
||||
$smushed_stats = array(
|
||||
'bytes' => 0,
|
||||
'size_before' => 0,
|
||||
'size_after' => 0,
|
||||
'percent' => 0,
|
||||
);
|
||||
|
||||
// Clear up the stats.
|
||||
if ( 0 == $this->total_count() || $this->get_smushed_count() < 1 ) {
|
||||
delete_option( self::SMUSH_STATS_OPTION_ID );
|
||||
}
|
||||
|
||||
// Check for the wp_smush_images in the 'nextgen' group.
|
||||
$stats = $this->get_cache_smush_stats();
|
||||
|
||||
$size_before = (int) $this->get_array_value( $stats, 'size_before' );
|
||||
if ( empty( $size_before ) ) {
|
||||
return $smushed_stats;
|
||||
}
|
||||
$size_after = (int) $this->get_array_value( $stats, 'size_after' );
|
||||
$stats['bytes'] = $size_before - $size_after;
|
||||
$stats['bytes'] = $stats['bytes'] > 0 ? $stats['bytes'] : 0;
|
||||
$stats['percent'] = ( $stats['bytes'] / $stats['size_before'] ) * 100;
|
||||
// Round off precentage.
|
||||
$stats['percent'] = ! empty( $stats['percent'] ) ? round( $stats['percent'], 1 ) : 0;
|
||||
$stats['human'] = size_format( $stats['bytes'], $stats['bytes'] >= 1024 ? 1 : 0 );
|
||||
|
||||
$smushed_stats = array_merge( $smushed_stats, $stats );
|
||||
|
||||
// Gotta remove the stats for re-smush ids.
|
||||
if ( $this->get_reoptimize_list()->get_count() ) {
|
||||
$resmush_stats = $this->get_stats_for_ids( $this->get_reoptimize_list()->get_ids() );
|
||||
// Recalculate stats, Remove stats for resmush ids.
|
||||
$smushed_stats = $this->recalculate_stats( 'sub', $smushed_stats, $resmush_stats );
|
||||
}
|
||||
|
||||
return $smushed_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the combined stats for given Ids
|
||||
*
|
||||
* @param array $ids Image IDs.
|
||||
*
|
||||
* @return array|bool Array of Stats for the given ids
|
||||
*/
|
||||
public function get_stats_for_ids( $ids = array() ) {
|
||||
// Return if we don't have an array or no ids.
|
||||
if ( ! is_array( $ids ) || empty( $ids ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the Stats array.
|
||||
$stats = array(
|
||||
'size_before' => 0,
|
||||
'size_after' => 0,
|
||||
);
|
||||
// Calculate the stats, Expensive Operation.
|
||||
foreach ( $ids as $id ) {
|
||||
$image_stats = $this->get_attachment_stats( $id );
|
||||
$stats = $this->recalculate_stats( 'add', $stats, $image_stats );
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Subtract the values from 2nd array to First array
|
||||
* This function is very specific to current requirement of stats re-calculation
|
||||
*
|
||||
* @param string $op 'add', 'sub' Add or Subtract the values.
|
||||
* @param array $a1 First array.
|
||||
* @param array $a2 Second array.
|
||||
*
|
||||
* @return array Return $a1
|
||||
*/
|
||||
private function recalculate_stats( $op = 'add', $a1 = array(), $a2 = array() ) {
|
||||
// If the first array itself is not set, return.
|
||||
if ( empty( $a1 ) ) {
|
||||
return $a1;
|
||||
}
|
||||
|
||||
// Iterate over keys in first array, and add/subtract the values.
|
||||
foreach ( $a1 as $k => $v ) {
|
||||
// If the key is not set in 2nd array, skip.
|
||||
if ( empty( $a2[ $k ] ) || ! in_array( $k, array( 'size_before', 'size_after' ) ) ) {
|
||||
continue;
|
||||
}
|
||||
// Else perform the operation, Considers the value to be integer, doesn't performs a check.
|
||||
if ( 'sub' === $op ) {
|
||||
// Subtract the value.
|
||||
$a1[ $k ] -= $a2[ $k ];
|
||||
} elseif ( 'add' === $op ) {
|
||||
// Add the value.
|
||||
$a1[ $k ] += $a2[ $k ];
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate percentage and human savings.
|
||||
$a1['bytes'] = $a1['size_before'] - $a1['size_after'];
|
||||
$a1['percent'] = $a1['bytes'] > 0 ? round( ( $a1['bytes'] / $a1['size_before'] ) * 100, 1 ) : 0;
|
||||
$a1['human'] = $a1['bytes'] > 0 ? size_format( $a1['bytes'], 1 ) : 0;
|
||||
|
||||
return $a1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Super smushed images from the given images array
|
||||
*
|
||||
* @param array $images Array of images containing metadata.
|
||||
*
|
||||
* @return array Array containing ids of supersmushed images
|
||||
*/
|
||||
private function get_super_smushed_images( $images = array() ) {
|
||||
if ( empty( $images ) ) {
|
||||
return array();
|
||||
}
|
||||
$super_smushed = array();
|
||||
// Iterate Over all the images.
|
||||
foreach ( $images as $image_k => $image ) {
|
||||
if ( empty( $image ) || ! is_array( $image ) || ! isset( $image['wp_smush'] ) ) {
|
||||
continue;
|
||||
}
|
||||
// Check for lossy compression.
|
||||
if ( ! empty( $image['wp_smush']['stats'] ) && ! empty( $image['wp_smush']['stats']['lossy'] ) ) {
|
||||
$super_smushed[] = $image_k;
|
||||
}
|
||||
}
|
||||
return $super_smushed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate stats for the given smushed ids and update the cache
|
||||
* Update Super smushed image ids
|
||||
*
|
||||
* @throws Exception Exception.
|
||||
*/
|
||||
public function update_stats_cache() {
|
||||
// Get the Image ids.
|
||||
$smushed_images = $this->get_ngg_images( 'smushed' );
|
||||
$super_smushed = array(
|
||||
'ids' => array(),
|
||||
'timestamp' => '',
|
||||
);
|
||||
|
||||
$stats = $this->get_stats_for_ids( $smushed_images );
|
||||
$lossy = $this->get_super_smushed_images( $smushed_images );
|
||||
|
||||
if ( empty( $stats['bytes'] ) && ! empty( $stats['size_before'] ) ) {
|
||||
$stats['bytes'] = $stats['size_before'] - $stats['size_after'];
|
||||
}
|
||||
$stats['human'] = size_format( ! empty( $stats['bytes'] ) ? $stats['bytes'] : 0 );
|
||||
if ( ! empty( $stats['size_before'] ) ) {
|
||||
$stats['percent'] = ( $stats['bytes'] / $stats['size_before'] ) * 100;
|
||||
$stats['percent'] = round( $stats['percent'], 2 );
|
||||
}
|
||||
|
||||
// Update Re-smush list.
|
||||
if ( is_array( WP_Smush::get_instance()->core()->nextgen->ng_admin->resmush_ids ) && is_array( $smushed_images ) ) {
|
||||
$resmush_ids = array_intersect( WP_Smush::get_instance()->core()->nextgen->ng_admin->resmush_ids, array_keys( $smushed_images ) );
|
||||
}
|
||||
|
||||
// If we have resmush ids, add it to db.
|
||||
if ( ! empty( $resmush_ids ) ) {
|
||||
// Update re-smush images to db.
|
||||
$this->get_reoptimize_list()->update_ids( $resmush_ids );
|
||||
}
|
||||
|
||||
// Update Super smushed images in db.
|
||||
$this->get_supper_smushed_list()->update_ids( $lossy );
|
||||
|
||||
// Update Stats Cache.
|
||||
update_option( self::SMUSH_STATS_OPTION_ID, $stats, false );
|
||||
|
||||
}
|
||||
|
||||
public function get_reoptimize_list() {
|
||||
return $this->reoptimize_list;
|
||||
}
|
||||
|
||||
public function get_supper_smushed_list() {
|
||||
return $this->supper_smushed_list;
|
||||
}
|
||||
|
||||
public function get_supper_smushed_count() {
|
||||
return count( $this->get_supper_smushed() );
|
||||
}
|
||||
|
||||
private function get_supper_smushed() {
|
||||
$super_smushed = $this->get_supper_smushed_list()->get_ids();
|
||||
|
||||
// If we have images to be resmushed, Update supersmush list.
|
||||
$resmush_ids = $this->get_reoptimize_list()->get_ids();
|
||||
if ( ! empty( $resmush_ids ) && ! empty( $super_smushed ) ) {
|
||||
$super_smushed = array_diff( $super_smushed, $resmush_ids );
|
||||
}
|
||||
|
||||
// If supersmushed images are more than total, clean it up.
|
||||
if ( count( $super_smushed ) > self::total_count() ) {
|
||||
$super_smushed = $this->cleanup_super_smush_data();
|
||||
}
|
||||
|
||||
return (array) $super_smushed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup Super-smush images array against the all ids in gallery
|
||||
*
|
||||
* @return array|mixed|void
|
||||
*/
|
||||
private function cleanup_super_smush_data() {
|
||||
$supper_smushed_list = $this->get_supper_smushed_list();
|
||||
$super_smushed = $supper_smushed_list->get_ids();
|
||||
$ids = self::total_count( false, true );
|
||||
|
||||
if ( ! empty( $super_smushed ) && is_array( $ids ) ) {
|
||||
$super_smushed = array_intersect( $super_smushed, $ids );
|
||||
}
|
||||
|
||||
$supper_smushed_list->update_ids( $super_smushed );
|
||||
}
|
||||
|
||||
public function get_global_stats() {
|
||||
if ( $this->global_stats ) {
|
||||
return $this->global_stats;
|
||||
}
|
||||
|
||||
$stats = $this->get_smush_stats();
|
||||
$human_bytes = $this->get_array_value( $stats, 'human' );
|
||||
if ( empty( $human_bytes ) ) {
|
||||
$human_bytes = '0 B';
|
||||
}
|
||||
|
||||
$this->global_stats = array(
|
||||
'count_supersmushed' => $this->get_supper_smushed_count(),
|
||||
'count_smushed' => $this->get_smushed_count(),
|
||||
'count_total' => $this->total_count(),
|
||||
'count_images' => $this->get_smushed_image_count(),
|
||||
'count_resize' => 0,
|
||||
'count_skipped' => 0,
|
||||
'unsmushed' => $this->get_unsmushed_images(),
|
||||
'count_unsmushed' => count( $this->get_unsmushed_images() ),
|
||||
'resmush' => $this->get_reoptimize_list()->get_ids(),
|
||||
'count_resmush' => $this->get_reoptimize_list()->get_count(),
|
||||
'size_before' => $this->get_array_value( $stats, 'size_before' ),
|
||||
'size_after' => $this->get_array_value( $stats, 'size_after' ),
|
||||
'savings_bytes' => $this->get_array_value( $stats, 'bytes' ),
|
||||
'human_bytes' => $human_bytes,
|
||||
'savings_resize' => 0,
|
||||
'savings_resize_human' => 0,
|
||||
'savings_conversion' => 0,
|
||||
'savings_dir_smush' => 0,
|
||||
'savings_percent' => $this->get_array_value( $stats, 'percent' ),
|
||||
'percent_grade' => $this->get_grade_class(),
|
||||
'percent_metric' => $this->get_percent_metric(),
|
||||
'percent_optimized' => $this->get_percent_optimized(),
|
||||
'remaining_count' => $this->get_remaining_count(),
|
||||
);
|
||||
|
||||
return $this->global_stats;
|
||||
}
|
||||
|
||||
public function get_smushed_image_count() {
|
||||
$ng_smushed_images = $this->get_ngg_images( 'smushed' );
|
||||
if ( empty( $ng_smushed_images ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$image_count = 0;
|
||||
// $image in here is expected to be metadata array
|
||||
foreach ( $ng_smushed_images as $pid => $image ) {
|
||||
// If there are no smush stats, skip.
|
||||
if ( empty( $image['wp_smush'] ) || $this->get_reoptimize_list()->has_id( $pid ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the image count.
|
||||
if ( ! empty( $image['wp_smush']['sizes'] ) ) {
|
||||
$image_count += count( $image['wp_smush']['sizes'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $image_count;
|
||||
}
|
||||
|
||||
public function get_smushed_count() {
|
||||
return $this->total_count() - $this->get_remaining_count();
|
||||
}
|
||||
|
||||
public function get_unsmushed_images() {
|
||||
if ( null !== $this->unsmushed_images ) {
|
||||
return $this->unsmushed_images;
|
||||
}
|
||||
$ng_unsmushed_images = $this->get_ngg_images( 'unsmushed' );
|
||||
if ( ! $ng_unsmushed_images ) {
|
||||
return array();
|
||||
}
|
||||
$this->unsmushed_images = array_keys( $ng_unsmushed_images );
|
||||
|
||||
return $this->unsmushed_images;
|
||||
}
|
||||
|
||||
public function get_remaining_count() {
|
||||
if ( null === $this->remaining_count ) {
|
||||
$unsmushed_images = $this->get_unsmushed_images();
|
||||
$resmush_ids = $this->get_reoptimize_list()->get_ids();
|
||||
$remaining_images = array_unique( array_merge( $resmush_ids, $unsmushed_images ) );
|
||||
$this->remaining_count = count( $remaining_images );
|
||||
}
|
||||
|
||||
return $this->remaining_count;
|
||||
}
|
||||
|
||||
private function get_percent_optimized() {
|
||||
$smushed_count = $this->get_smushed_count();
|
||||
if ( $smushed_count < 1 ) {
|
||||
return $this->percent_optimized;
|
||||
}
|
||||
|
||||
$total_optimizable_count = $this->total_count();
|
||||
$remaining_count = $this->get_remaining_count();
|
||||
$this->percent_optimized = floor( ( $total_optimizable_count - $remaining_count ) * 100 / $total_optimizable_count );
|
||||
if ( $this->percent_optimized > 100 ) {
|
||||
$this->percent_optimized = 100;
|
||||
} elseif ( $this->percent_optimized < 0 ) {
|
||||
$this->percent_optimized = 0;
|
||||
}
|
||||
|
||||
return $this->percent_optimized;
|
||||
}
|
||||
|
||||
private function get_percent_metric() {
|
||||
$percent_optimized = $this->get_percent_optimized();
|
||||
return 0.0 === (float) $percent_optimized ? 100 : $percent_optimized;
|
||||
}
|
||||
|
||||
private function get_grade_class() {
|
||||
$percent_optimized = $this->get_percent_optimized();
|
||||
if ( 0 === $percent_optimized ) {
|
||||
return 'sui-grade-dismissed';
|
||||
}
|
||||
|
||||
$grade = 'sui-grade-f';
|
||||
if ( $percent_optimized >= 60 && $percent_optimized < 90 ) {
|
||||
$grade = 'sui-grade-c';
|
||||
} elseif ( $percent_optimized >= 90 ) {
|
||||
$grade = 'sui-grade-a';
|
||||
}
|
||||
|
||||
return $grade;
|
||||
}
|
||||
|
||||
public function get_array_value( $array, $key ) {
|
||||
return isset( $array[ $key ] ) ? $array[ $key ] : null;
|
||||
}
|
||||
|
||||
public function subtract_image_stats( $image ) {
|
||||
$stats = $this->get_cache_smush_stats();
|
||||
$stats = $this->recalculate_stats( 'sub', $stats, $this->get_attachment_stats( $image ) );
|
||||
$this->update_smush_stats( $stats );
|
||||
}
|
||||
|
||||
private function get_image_smush_savings( $image ) {
|
||||
$image = (array) $image;
|
||||
if ( ! empty( $image['meta_data']['wp_smush']['stats'] ) ) {
|
||||
return $image['meta_data']['wp_smush']['stats'];
|
||||
}
|
||||
|
||||
if ( ! empty( $image['wp_smush']['stats'] ) ) {
|
||||
return $image['wp_smush']['stats'];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
private function get_image_resize_savings( $image ) {
|
||||
$image = (array) $image;
|
||||
|
||||
if ( ! empty( $image['meta_data']['wp_smush_resize_savings'] ) ) {
|
||||
return $image['meta_data']['wp_smush_resize_savings'];
|
||||
}
|
||||
|
||||
if ( ! empty( $image['wp_smush_resize_savings'] ) ) {
|
||||
return $image['wp_smush_resize_savings'];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
private function update_smush_stats( $stats ) {
|
||||
return update_option( self::SMUSH_STATS_OPTION_ID, $stats );
|
||||
}
|
||||
|
||||
private function get_cache_smush_stats() {
|
||||
return get_option( self::SMUSH_STATS_OPTION_ID, array() );
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* Extend NextGen Mixin class to smush dynamic images.
|
||||
*
|
||||
* @package Smush\Core\Integrations\NextGen
|
||||
*/
|
||||
|
||||
namespace Smush\Core\Integrations\NextGen;
|
||||
|
||||
use C_Component_Registry;
|
||||
use C_Gallery_Storage;
|
||||
use C_Image;
|
||||
use Mixin;
|
||||
use nggdb;
|
||||
use WP_Smush;
|
||||
|
||||
if ( ! defined( 'WPINC' ) ) {
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Thumbs
|
||||
*/
|
||||
class Thumbs extends Mixin {
|
||||
/**
|
||||
* Overrides the NextGen Gallery function, to smush the dynamic images and thumbnails created by gallery
|
||||
*
|
||||
* @param int|object|C_Image $image Image object.
|
||||
* @param string $size Size.
|
||||
* @param array|null $params Optional. Parameters array.
|
||||
* @param bool $skip_defaults Optional. Skip defaults.
|
||||
*
|
||||
* @return bool|object
|
||||
*/
|
||||
function generate_image_size( $image, $size, $params = null, $skip_defaults = false ) {
|
||||
$smush = WP_Smush::get_instance()->core()->mod->smush;
|
||||
|
||||
$image_id = ! empty( $image->pid ) ? $image->pid : '';
|
||||
// Get image from storage object if we don't have it already.
|
||||
if ( empty( $image_id ) ) {
|
||||
// Get metadata For the image.
|
||||
// Registry Object for NextGen Gallery.
|
||||
$registry = C_Component_Registry::get_instance();
|
||||
|
||||
/**
|
||||
* Gallery Storage Object.
|
||||
*
|
||||
* @var C_Gallery_Storage $storage
|
||||
*/
|
||||
$storage = $registry->get_utility( 'I_Gallery_Storage' );
|
||||
|
||||
$image_id = $storage->object->_get_image_id( $image );
|
||||
}
|
||||
// Call the actual function to generate the image, and pass the image to smush.
|
||||
$success = $this->call_parent( 'generate_image_size', $image, $size, $params, $skip_defaults );
|
||||
if ( $success ) {
|
||||
$filename = $success->fileName;
|
||||
// Smush it, if it exists.
|
||||
if ( file_exists( $filename ) ) {
|
||||
$response = $smush->do_smushit( $filename );
|
||||
|
||||
// If the image was smushed.
|
||||
if ( ! is_wp_error( $response ) && ! empty( $response['data'] ) && $response['data']->bytes_saved > 0 ) {
|
||||
// Check for existing stats.
|
||||
if ( ! empty( $image->meta_data ) && ! empty( $image->meta_data['wp_smush'] ) ) {
|
||||
$stats = $image->meta_data['wp_smush'];
|
||||
} else {
|
||||
// Initialize stats array.
|
||||
$stats = array(
|
||||
'stats' => array_merge(
|
||||
$smush->get_size_signature(),
|
||||
array(
|
||||
'api_version' => - 1,
|
||||
'lossy' => - 1,
|
||||
'keep_exif' => false,
|
||||
)
|
||||
),
|
||||
'sizes' => array(),
|
||||
);
|
||||
|
||||
$stats['bytes'] = $response['data']->bytes_saved;
|
||||
$stats['percent'] = $response['data']->compression;
|
||||
$stats['size_after'] = $response['data']->after_size;
|
||||
$stats['size_before'] = $response['data']->before_size;
|
||||
$stats['time'] = $response['data']->time;
|
||||
}
|
||||
$stats['sizes'][ $size ] = (object) $smush->array_fill_placeholders( $smush->get_size_signature(), (array) $response['data'] );
|
||||
|
||||
if ( isset( $image->metadata ) ) {
|
||||
$image->meta_data['wp_smush'] = $stats;
|
||||
nggdb::update_image_meta( $image->pid, $image->meta_data );
|
||||
}
|
||||
|
||||
// Allows To get the stats for each image, after the image is smushed.
|
||||
do_action( 'wp_smush_nextgen_image_stats', $image_id, $stats );
|
||||
}
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user