first
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use WP_Smush;
|
||||
|
||||
/**
|
||||
* TODO: maybe reset the media item when:
|
||||
* - a new size is added
|
||||
*/
|
||||
class Media_Item_Cache {
|
||||
const CACHE_GROUP = 'wp-smushit';
|
||||
/**
|
||||
* Static instance
|
||||
*
|
||||
* @var self
|
||||
*/
|
||||
private static $instance;
|
||||
/**
|
||||
* @var Media_Item[]
|
||||
*/
|
||||
private $media_items;
|
||||
|
||||
/**
|
||||
* Static instance getter
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( empty( self::$instance ) ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function has( $id ) {
|
||||
$media_item = $this->get_from_cache( $id );
|
||||
|
||||
return ! empty( $media_item );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return Media_Item|null
|
||||
*/
|
||||
public function get( $id ) {
|
||||
$media_item = $this->get_from_cache( $id );
|
||||
if ( ! $media_item ) {
|
||||
$media_item = new Media_Item( $id );
|
||||
$this->save_to_cache( $id, $media_item );
|
||||
}
|
||||
|
||||
return $media_item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return Media_Item|null
|
||||
*/
|
||||
private function get_from_cache( $id ) {
|
||||
return $this->get_array_value(
|
||||
$this->media_items,
|
||||
$this->make_key( $id )
|
||||
);
|
||||
}
|
||||
|
||||
private function make_key( $id ) {
|
||||
$membership_type_postfix = WP_Smush::is_pro() ? 'pro' : 'free';
|
||||
|
||||
return "wp-smush-$membership_type_postfix-media-item-$id";
|
||||
}
|
||||
|
||||
private function save_to_cache( $id, $media_item ) {
|
||||
$this->media_items[ $this->make_key( $id ) ] = $media_item;
|
||||
}
|
||||
|
||||
public function remove( $id ) {
|
||||
unset( $this->media_items[ $this->make_key( $id ) ] );
|
||||
}
|
||||
|
||||
private function get_array_value( $array, $key ) {
|
||||
return $array && isset( $array[ $key ] )
|
||||
? $array[ $key ]
|
||||
: null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use Smush\Core\Controller;
|
||||
use Smush\Core\Error_Handler;
|
||||
use Smush\Core\Helper;
|
||||
use Smush\Core\Stats\Global_Stats;
|
||||
use WP_Smush;
|
||||
|
||||
/**
|
||||
* Performs operations on the media item
|
||||
*/
|
||||
class Media_Item_Controller extends Controller {
|
||||
public function __construct() {
|
||||
$this->register_action( 'wp_ajax_ignore_bulk_image', array( $this, 'ignore_bulk_image' ) );
|
||||
$this->register_action( 'wp_ajax_remove_from_skip_list', array( $this, 'remove_from_skip_list' ) );
|
||||
$this->register_action( 'wp_ajax_wp_smush_ignore_all_failed_items', array(
|
||||
$this,
|
||||
'ignore_all_failed_items',
|
||||
) );
|
||||
}
|
||||
|
||||
public function remove_from_skip_list() {
|
||||
check_ajax_referer( 'wp-smush-remove-skipped' );
|
||||
|
||||
if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
|
||||
wp_send_json_error( array(
|
||||
'error_message' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
|
||||
), 403 );
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['id'] ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$attachment_id = absint( $_POST['id'] );
|
||||
|
||||
$changed = $this->change_attachment_ignored_status( $attachment_id, false );
|
||||
if ( ! $changed ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'html' => WP_Smush::get_instance()->library()->generate_markup( $attachment_id ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function ignore_bulk_image() {
|
||||
check_ajax_referer( 'wp-smush-ajax' );
|
||||
|
||||
if ( ! Helper::is_user_allowed( 'upload_files' ) ) {
|
||||
wp_send_json_error( array(
|
||||
'error_msg' => esc_html__( "You don't have permission to work with uploaded files.", 'wp-smushit' ),
|
||||
), 403 );
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['id'] ) ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
$attachment_id = absint( $_POST['id'] );
|
||||
$changed = $this->change_attachment_ignored_status( $attachment_id, true );
|
||||
if ( ! $changed ) {
|
||||
wp_send_json_error();
|
||||
}
|
||||
|
||||
wp_send_json_success( array(
|
||||
'html' => WP_Smush::get_instance()->library()->generate_markup( $attachment_id ),
|
||||
) );
|
||||
}
|
||||
|
||||
public function ignore_all_failed_items() {
|
||||
check_ajax_referer( 'wp-smush-ajax' );
|
||||
|
||||
if ( ! Helper::is_user_allowed() ) {
|
||||
wp_send_json_error( array(
|
||||
'message' => __( "You don't have permission to do this.", 'wp-smushit' ),
|
||||
), 403 );
|
||||
}
|
||||
|
||||
$failed_images = Error_Handler::get_all_failed_images();
|
||||
if ( empty( $failed_images ) ) {
|
||||
wp_send_json_error( array( 'message' => __( 'Not found any failed items.', 'wp-smushit' ) ) );
|
||||
}
|
||||
|
||||
foreach ( $failed_images as $failed_image_id ) {
|
||||
$this->change_attachment_ignored_status( $failed_image_id, true );
|
||||
}
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
private function change_attachment_ignored_status( $attachment_id, $new_status ) {
|
||||
$media_item = Media_Item_Cache::get_instance()->get( $attachment_id );
|
||||
if ( ! $media_item->is_mime_type_supported() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$media_item->set_ignored( $new_status );
|
||||
$media_item->save();
|
||||
|
||||
do_action( 'wp_smush_attachment_ignored_status_changed', $attachment_id, $new_status );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use Smush\Core\Array_Utils;
|
||||
|
||||
class Media_Item_Optimization_Global_Stats extends Media_Item_Stats {
|
||||
/**
|
||||
* @var int How many media *items* are included in this instance.
|
||||
*/
|
||||
private $count = 0;
|
||||
|
||||
/**
|
||||
* @var int[] Ids of the attachments included in this instance.
|
||||
*/
|
||||
private $attachment_ids = array();
|
||||
private $array_utils;
|
||||
|
||||
public function __construct() {
|
||||
$this->array_utils = new Array_Utils();
|
||||
}
|
||||
|
||||
public function to_array() {
|
||||
$array = parent::to_array();
|
||||
$array['count'] = $this->get_count();
|
||||
$array['attachment_ids'] = join( ',', $this->get_attachment_ids() );
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function from_array( $array ) {
|
||||
parent::from_array( $array );
|
||||
|
||||
$this->set_count( (int) $this->get_array_value( $array, 'count' ) );
|
||||
|
||||
$attachment_ids = $this->get_array_value( $array, 'attachment_ids' );
|
||||
$attachment_ids = empty( $attachment_ids ) ? array() : explode( ',', $attachment_ids );
|
||||
$this->set_attachment_ids( $attachment_ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attachment_id int
|
||||
* @param $item_stats Media_Item_Stats
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function add_item_stats( $attachment_id, $item_stats ) {
|
||||
if ( $this->has_attachment_id( $attachment_id ) ) {
|
||||
return false;
|
||||
} else {
|
||||
parent::add( $item_stats );
|
||||
|
||||
$this->set_count( $this->get_count() + 1 );
|
||||
$this->add_attachment_id( $attachment_id );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attachment_id int
|
||||
* @param $item_stats Media_Item_Stats
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function subtract_item_stats( $attachment_id, $item_stats ) {
|
||||
if ( $this->has_attachment_id( $attachment_id ) ) {
|
||||
parent::subtract( $item_stats );
|
||||
|
||||
$this->set_count( $this->get_count() - 1 );
|
||||
$this->remove_attachment_id( $attachment_id );
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $addend Media_Item_Optimization_Global_Stats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add( $addend ) {
|
||||
parent::add( $addend );
|
||||
|
||||
$this->set_count( $this->get_count() + $addend->get_count() );
|
||||
$this->set_attachment_ids(
|
||||
$this->array_utils->fast_array_unique( array_merge(
|
||||
$this->get_attachment_ids(),
|
||||
$addend->get_attachment_ids()
|
||||
) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $subtrahend Media_Item_Optimization_Global_Stats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function subtract( $subtrahend ) {
|
||||
parent::subtract( $subtrahend );
|
||||
|
||||
$this->set_count( max( $this->get_count() - $subtrahend->get_count(), 0 ) );
|
||||
$this->set_attachment_ids(
|
||||
array_diff(
|
||||
$this->get_attachment_ids(),
|
||||
$subtrahend->get_attachment_ids()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_count() {
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $count
|
||||
*
|
||||
* @return Media_Item_Optimization_Global_Stats
|
||||
*/
|
||||
public function set_count( $count ) {
|
||||
$this->count = $count;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function add_attachment_id( $attachment_id ) {
|
||||
$this->attachment_ids[] = $attachment_id;
|
||||
}
|
||||
|
||||
private function remove_attachment_id( $attachment_id ) {
|
||||
$attachment_ids = $this->get_attachment_ids();
|
||||
$index = array_search( $attachment_id, $attachment_ids );
|
||||
if ( $index !== false ) {
|
||||
unset( $attachment_ids[ $index ] );
|
||||
$this->set_attachment_ids( $attachment_ids );
|
||||
}
|
||||
}
|
||||
|
||||
public function has_attachment_id( $attachment_id ) {
|
||||
return in_array( $attachment_id, $this->get_attachment_ids() );
|
||||
}
|
||||
|
||||
private function get_attachment_ids() {
|
||||
$attachment_ids = $this->attachment_ids;
|
||||
|
||||
return empty( $attachment_ids ) || ! is_array( $attachment_ids )
|
||||
? array()
|
||||
: $attachment_ids;
|
||||
}
|
||||
|
||||
private function set_attachment_ids( $attachment_ids ) {
|
||||
$this->attachment_ids = empty( $attachment_ids ) || ! is_array( $attachment_ids )
|
||||
? array()
|
||||
: $attachment_ids;
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
abstract class Media_Item_Optimization {
|
||||
/**
|
||||
* @param $media_item Media_Item
|
||||
*/
|
||||
abstract public function __construct( $media_item );
|
||||
|
||||
abstract public function get_key();
|
||||
|
||||
/**
|
||||
* @return Media_Item_Stats
|
||||
*/
|
||||
abstract public function get_stats();
|
||||
|
||||
/**
|
||||
* @return Media_Item_Stats
|
||||
*/
|
||||
abstract public function get_size_stats( $size_key );
|
||||
|
||||
abstract public function get_optimized_sizes_count();
|
||||
|
||||
abstract public function save();
|
||||
|
||||
abstract public function is_optimized();
|
||||
|
||||
abstract public function should_optimize();
|
||||
|
||||
abstract public function should_reoptimize();
|
||||
|
||||
/**
|
||||
* @param $size Media_Item_Size
|
||||
*/
|
||||
abstract public function should_optimize_size( $size );
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function delete_data();
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function optimize();
|
||||
|
||||
public function can_restore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function restore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function has_errors() {
|
||||
$wp_error = $this->get_errors();
|
||||
|
||||
return $wp_error
|
||||
&& is_a( $wp_error, '\WP_Error' )
|
||||
&& $wp_error->has_errors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WP_Error
|
||||
*/
|
||||
abstract public function get_errors();
|
||||
}
|
@@ -0,0 +1,450 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use Smush\Core\Backups\Backups;
|
||||
use Smush\Core\Helper;
|
||||
use Smush\Core\Smush\Smush_Optimization;
|
||||
use Smush\Core\Stats\Global_Stats;
|
||||
use WDEV_Logger;
|
||||
use WP_Error;
|
||||
|
||||
class Media_Item_Optimizer {
|
||||
const ERROR_META_KEY = 'wp-smush-optimization-errors';
|
||||
|
||||
/**
|
||||
* @var Media_Item_Optimization[]
|
||||
*/
|
||||
private $optimizations;
|
||||
|
||||
/**
|
||||
* @var Media_Item
|
||||
*/
|
||||
private $media_item;
|
||||
/**
|
||||
* @var Backups
|
||||
*/
|
||||
private $backups;
|
||||
/**
|
||||
* @var WDEV_Logger
|
||||
*/
|
||||
private $logger;
|
||||
/**
|
||||
* @var Global_Stats
|
||||
*/
|
||||
private $global_stats;
|
||||
|
||||
/**
|
||||
* @var WP_Error
|
||||
*/
|
||||
private $errors;
|
||||
|
||||
public function __construct( $media_item ) {
|
||||
$this->media_item = $media_item;
|
||||
$this->backups = new Backups();
|
||||
$this->logger = Helper::logger();
|
||||
$this->global_stats = Global_Stats::get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Media_Item_Optimization[]
|
||||
*/
|
||||
public function get_optimizations() {
|
||||
if ( is_null( $this->optimizations ) ) {
|
||||
$this->optimizations = $this->initialize_optimizations();
|
||||
}
|
||||
|
||||
return $this->optimizations;
|
||||
}
|
||||
|
||||
public function set_optimizations( $optimizations ) {
|
||||
$this->optimizations = $optimizations;
|
||||
}
|
||||
|
||||
private function initialize_optimizations() {
|
||||
return apply_filters( 'wp_smush_optimizations', array(), $this->media_item );
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: check the uses for this method to make sure they are prepared to receive null
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @return Media_Item_Optimization|null
|
||||
*/
|
||||
public function get_optimization( $key ) {
|
||||
return $this->get_array_value( $this->get_optimizations(), $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
*
|
||||
* @return Media_Item_Stats
|
||||
*/
|
||||
public function get_stats( $key ) {
|
||||
$optimization = $this->get_optimization( $key );
|
||||
if ( $optimization ) {
|
||||
return $optimization->get_stats();
|
||||
}
|
||||
|
||||
return new Media_Item_Stats();
|
||||
}
|
||||
|
||||
public function get_total_stats() {
|
||||
$total_stats = new Media_Item_Stats();
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
$total_stats->add( $optimization->get_stats() );
|
||||
}
|
||||
|
||||
return $total_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $optimization_key
|
||||
* @param $size_key
|
||||
*
|
||||
* @return Media_Item_Stats
|
||||
*/
|
||||
public function get_size_stats( $optimization_key, $size_key ) {
|
||||
$optimization = $this->get_optimization( $optimization_key );
|
||||
if ( $optimization ) {
|
||||
return $optimization->get_size_stats( $size_key );
|
||||
}
|
||||
|
||||
return new Media_Item_Stats();
|
||||
}
|
||||
|
||||
public function get_total_size_stats( $size_key ) {
|
||||
$total_stats = new Media_Item_Stats();
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
$total_stats->add( $optimization->get_size_stats( $size_key ) );
|
||||
}
|
||||
|
||||
return $total_stats;
|
||||
}
|
||||
|
||||
public function get_optimized_sizes_count() {
|
||||
$size_count = 0;
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
$optimized_sizes_count = $optimization->get_optimized_sizes_count();
|
||||
if ( $optimized_sizes_count > $size_count ) {
|
||||
$size_count = $optimized_sizes_count;
|
||||
}
|
||||
}
|
||||
|
||||
return $size_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the media item was optimized at some point. It may need to be reoptimized.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_optimized() {
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->is_optimized() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function should_optimize() {
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->should_optimize() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function should_reoptimize() {
|
||||
$should_reoptimize = false;
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->should_reoptimize() ) {
|
||||
$should_reoptimize = true;
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'wp_smush_should_resmush', $should_reoptimize, $this->media_item->get_id() );
|
||||
}
|
||||
|
||||
public function optimize() {
|
||||
if ( $this->restore_in_progress() ) {
|
||||
$this->logger->log( 'Prevented auto-smush during restore.' );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->in_progress() ) {
|
||||
$this->handle_error( 'in_progress', 'Smush already in progress' );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$media_item = $this->media_item;
|
||||
do_action(
|
||||
'wp_smush_before_smush_file',
|
||||
$media_item->get_id(),
|
||||
$media_item->get_wp_metadata()
|
||||
);
|
||||
|
||||
if ( $media_item->has_errors() || $media_item->is_skipped() ) {
|
||||
$this->adjust_global_stats_lists();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set_in_progress_transient();
|
||||
|
||||
$this->backups->maybe_create_backup( $media_item, $this );
|
||||
|
||||
$optimized = $this->run_optimizations();
|
||||
|
||||
do_action(
|
||||
'wp_smush_after_smush_file',
|
||||
$media_item->get_id(),
|
||||
$media_item->get_wp_metadata(),
|
||||
$optimized ? array() : $this->get_errors()
|
||||
);
|
||||
|
||||
if ( $optimized ) {
|
||||
do_action(
|
||||
'wp_smush_after_smush_successful',
|
||||
$media_item->get_id(),
|
||||
$media_item->get_wp_metadata()
|
||||
);
|
||||
|
||||
$this->delete_previous_optimization_errors();
|
||||
} else {
|
||||
$this->handle_optimization_errors();
|
||||
}
|
||||
|
||||
$this->delete_in_progress_transient();
|
||||
|
||||
return $optimized;
|
||||
}
|
||||
|
||||
public function restore() {
|
||||
if ( $this->in_progress() || $this->restore_in_progress() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set_restore_in_progress_transient();
|
||||
|
||||
$restoration_attempted = false;
|
||||
$restored = false;
|
||||
|
||||
// First, allow one of the optimizations to handle the restoration process
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->can_restore() ) {
|
||||
$restoration_attempted = true;
|
||||
$restored = $optimization->restore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $restoration_attempted ) {
|
||||
// Try the standard restoration
|
||||
$restored = $this->backups->restore_backup( $this->media_item );
|
||||
}
|
||||
|
||||
if ( $restored ) {
|
||||
// Before deleting all data subtract the stats
|
||||
$this->global_stats->subtract_item_stats( $this->media_item );
|
||||
$this->global_stats->subtract_optimized_images_count( $this->get_optimized_sizes_count() );
|
||||
|
||||
// Delete all the optimization data
|
||||
$this->delete_data();
|
||||
|
||||
// Delete optimization errors.
|
||||
$this->delete_previous_optimization_errors();
|
||||
|
||||
// Once all data has been deleted, adjust the lists
|
||||
$this->global_stats->adjust_lists_for_media_item( $this->media_item );
|
||||
}
|
||||
|
||||
$this->delete_restore_in_progress_transient();
|
||||
|
||||
return $restored;
|
||||
}
|
||||
|
||||
public function save() {
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
$optimization->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function get_array_value( $array, $key ) {
|
||||
return $array && isset( $array[ $key ] )
|
||||
? $array[ $key ]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Media_Item_Size $full_size
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function should_optimize_size( $full_size ) {
|
||||
$should_optimize_size = false;
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->should_optimize_size( $full_size ) ) {
|
||||
$should_optimize_size = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $should_optimize_size;
|
||||
}
|
||||
|
||||
public function delete_data() {
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
$optimization->delete_data();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function run_optimizations() {
|
||||
$all_optimized = true;
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->should_optimize() ) {
|
||||
$current_optimized = $optimization->optimize();
|
||||
$all_optimized = $all_optimized && $current_optimized;
|
||||
}
|
||||
}
|
||||
|
||||
return $all_optimized;
|
||||
}
|
||||
|
||||
private function adjust_global_stats_lists() {
|
||||
$this->global_stats->adjust_lists_for_media_item( $this->media_item );
|
||||
}
|
||||
|
||||
private function set_in_progress_transient() {
|
||||
set_transient( $this->in_progress_transient_key(), 1, HOUR_IN_SECONDS );
|
||||
}
|
||||
|
||||
private function delete_in_progress_transient() {
|
||||
delete_transient( $this->in_progress_transient_key() );
|
||||
}
|
||||
|
||||
public function in_progress() {
|
||||
return (bool) get_transient( $this->in_progress_transient_key() );
|
||||
}
|
||||
|
||||
private function in_progress_transient_key() {
|
||||
return 'smush-in-progress-' . $this->media_item->get_id();
|
||||
}
|
||||
|
||||
private function set_restore_in_progress_transient() {
|
||||
set_transient( $this->restore_in_progress_transient_key(), 1, HOUR_IN_SECONDS );
|
||||
}
|
||||
|
||||
private function delete_restore_in_progress_transient() {
|
||||
delete_transient( $this->restore_in_progress_transient_key() );
|
||||
}
|
||||
|
||||
public function restore_in_progress() {
|
||||
return (bool) get_transient( $this->restore_in_progress_transient_key() );
|
||||
}
|
||||
|
||||
private function restore_in_progress_transient_key() {
|
||||
return 'wp-smush-restore-' . $this->media_item->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $code
|
||||
* @param $error_message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function handle_error( $code, $error_message ) {
|
||||
$this->logger->error( $error_message );
|
||||
$this->set_errors( new WP_Error( $code, $error_message ) );
|
||||
$this->update_errors_meta();
|
||||
}
|
||||
|
||||
public function get_errors() {
|
||||
if ( is_null( $this->errors ) ) {
|
||||
$this->errors = $this->fetch_errors_from_meta();
|
||||
}
|
||||
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
private function set_errors( $errors ) {
|
||||
$this->errors = $errors;
|
||||
}
|
||||
|
||||
public function has_errors() {
|
||||
return $this->get_errors()->has_errors();
|
||||
}
|
||||
|
||||
private function set_optimization_errors() {
|
||||
$errors = new WP_Error();
|
||||
// Add optimization errors
|
||||
foreach ( $this->get_optimizations() as $optimization ) {
|
||||
if ( $optimization->has_errors() ) {
|
||||
$errors->merge_from( $optimization->get_errors() );
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_errors( $errors );
|
||||
}
|
||||
|
||||
private function fetch_errors_from_meta() {
|
||||
$wp_error = new WP_Error();
|
||||
$errors = get_post_meta( $this->media_item->get_id(), self::ERROR_META_KEY, true );
|
||||
|
||||
if ( empty( $errors ) || ! is_array( $errors ) ) {
|
||||
return $wp_error;
|
||||
}
|
||||
|
||||
foreach ( $errors as $error_code => $error_message ) {
|
||||
if ( empty( $error_message ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_array( $error_message ) ) {
|
||||
foreach ( $error_message as $error ) {
|
||||
$wp_error->add( $error_code, $error );
|
||||
}
|
||||
} else {
|
||||
$wp_error->add( $error_code, $error_message );
|
||||
}
|
||||
}
|
||||
|
||||
return $wp_error;
|
||||
}
|
||||
|
||||
private function update_errors_meta() {
|
||||
$errors_array = array();
|
||||
foreach ( $this->errors->get_error_codes() as $error_code ) {
|
||||
$errors_array[ $error_code ] = $this->errors->get_error_messages( $error_code );
|
||||
}
|
||||
|
||||
if ( ! empty( $errors_array ) ) {
|
||||
update_post_meta( $this->media_item->get_id(), self::ERROR_META_KEY, $errors_array );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function handle_optimization_errors() {
|
||||
$this->set_optimization_errors();
|
||||
$this->update_errors_meta();
|
||||
}
|
||||
|
||||
private function delete_previous_optimization_errors() {
|
||||
if ( $this->has_errors() ) {
|
||||
delete_post_meta( $this->media_item->get_id(), self::ERROR_META_KEY );
|
||||
$this->set_errors( null );
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use Smush\Core\Smush\Smush_Optimization;
|
||||
use Smush\Core\Smush_File;
|
||||
|
||||
class Media_Item_Query {
|
||||
public function fetch( $offset = 0, $limit = - 1 ) {
|
||||
global $wpdb;
|
||||
$query = $this->make_query( 'ID', $offset, $limit );
|
||||
|
||||
return $wpdb->get_col( $query );
|
||||
}
|
||||
|
||||
public function fetch_slice_post_meta( $slice, $slice_size ) {
|
||||
global $wpdb;
|
||||
|
||||
$offset = $this->get_offset( $slice, $slice_size );
|
||||
$limit = (int) $slice_size;
|
||||
|
||||
$ids_query = $this->make_query( 'ID', $offset, $limit );
|
||||
$query = "SELECT CONCAT(post_id, '-', meta_key), post_id, meta_key, meta_value FROM $wpdb->postmeta WHERE post_id IN (SELECT * FROM ($ids_query) AS slice_ids);";
|
||||
|
||||
return $wpdb->get_results( $query, OBJECT_K );
|
||||
}
|
||||
|
||||
public function fetch_slice_posts( $slice, $slice_size ) {
|
||||
global $wpdb;
|
||||
|
||||
$offset = $this->get_offset( $slice, $slice_size );
|
||||
$limit = (int) $slice_size;
|
||||
$posts_query = $this->make_query( '*', $offset, $limit );
|
||||
|
||||
return $wpdb->get_results( $posts_query, OBJECT_K );
|
||||
}
|
||||
|
||||
public function fetch_slice_ids( $slice, $slice_size ) {
|
||||
$offset = $this->get_offset( $slice, $slice_size );
|
||||
$limit = (int) $slice_size;
|
||||
|
||||
return $this->fetch( $offset, $limit );
|
||||
}
|
||||
|
||||
public function get_slice_count( $slice_size ) {
|
||||
if ( empty( $slice_size ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$image_attachment_count = $this->get_image_attachment_count();
|
||||
|
||||
return (int) ceil( $image_attachment_count / $slice_size );
|
||||
}
|
||||
|
||||
public function get_image_attachment_count() {
|
||||
global $wpdb;
|
||||
$query = $this->make_query( 'COUNT(*)' );
|
||||
|
||||
return (int) $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $select
|
||||
* @param $offset
|
||||
* @param $limit
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function make_query( $select, $offset = 0, $limit = - 1 ) {
|
||||
global $wpdb;
|
||||
$mime_types = ( new Smush_File() )->get_supported_mime_types();
|
||||
$placeholders = implode( ',', array_fill( 0, count( $mime_types ), '%s' ) );
|
||||
$column = $select;
|
||||
|
||||
$query = "SELECT %s FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type IN (%s)";
|
||||
$query = sprintf( $query, $column, $placeholders );
|
||||
$args = $mime_types;
|
||||
|
||||
if ( $limit > 0 ) {
|
||||
$query = "$query LIMIT %d";
|
||||
$args[] = $limit;
|
||||
|
||||
if ( $offset >= 0 ) {
|
||||
$query = "$query OFFSET %d";
|
||||
$args[] = $offset;
|
||||
}
|
||||
}
|
||||
|
||||
return $wpdb->prepare( $query, $args );
|
||||
}
|
||||
|
||||
public function get_lossy_count() {
|
||||
global $wpdb;
|
||||
|
||||
$query = $wpdb->prepare( "SELECT COUNT(DISTINCT post_id) FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = 1", Smush_Optimization::LOSSY_META_KEY );
|
||||
|
||||
return $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
public function get_smushed_count() {
|
||||
global $wpdb;
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT COUNT(DISTINCT post_meta_optimized.post_id) FROM $wpdb->postmeta as post_meta_optimized
|
||||
LEFT JOIN $wpdb->postmeta as post_meta_ignored ON post_meta_optimized.post_id = post_meta_ignored.post_id AND post_meta_ignored.meta_key= %s
|
||||
WHERE post_meta_optimized.meta_key = %s AND post_meta_ignored.meta_value IS NULL",
|
||||
Media_Item::IGNORED_META_KEY,
|
||||
Smush_Optimization::SMUSH_META_KEY
|
||||
);
|
||||
|
||||
return $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
public function get_ignored_count() {
|
||||
global $wpdb;
|
||||
|
||||
$query = $wpdb->prepare( "SELECT COUNT(DISTINCT post_id) FROM $wpdb->postmeta WHERE meta_key = %s", Media_Item::IGNORED_META_KEY );
|
||||
|
||||
return $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $slice
|
||||
* @param $slice_size
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
private function get_offset( $slice, $slice_size ) {
|
||||
$slice = (int) $slice;
|
||||
$slice_size = (int) $slice_size;
|
||||
|
||||
return ( $slice - 1 ) * $slice_size;
|
||||
}
|
||||
}
|
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
use Smush\Core\File_System;
|
||||
use Smush\Core\Settings;
|
||||
use WP_Smush;
|
||||
|
||||
class Media_Item_Size {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $key;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $file_name;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $mime_type;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $filesize;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $attachment_id;
|
||||
/**
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $wp_metadata;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size_limit;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $dir;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $base_url;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $extension;
|
||||
/**
|
||||
* @var File_System
|
||||
*/
|
||||
private $fs;
|
||||
|
||||
/**
|
||||
* @param $key string
|
||||
* @param $attachment_id int
|
||||
* @param $wp_size_metadata array
|
||||
*/
|
||||
public function __construct( $key, $attachment_id, $dir, $base_url, $wp_size_metadata ) {
|
||||
$this->key = $key;
|
||||
$this->attachment_id = $attachment_id;
|
||||
$this->dir = $dir;
|
||||
$this->base_url = $base_url;
|
||||
$this->wp_metadata = $wp_size_metadata;
|
||||
$this->fs = new File_System();
|
||||
|
||||
$this->size_limit = WP_Smush::is_pro()
|
||||
? WP_SMUSH_PREMIUM_MAX_BYTES
|
||||
: WP_SMUSH_MAX_BYTES;
|
||||
$this->settings = Settings::get_instance();
|
||||
$this->from_array( $wp_size_metadata );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $size_data array Typically an item from 'sizes' array returned by wp_get_attachment_metadata
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function from_array( $size_data ) {
|
||||
$this->set_file_name( (string) $this->get_array_value( $size_data, 'file' ) );
|
||||
$this->set_width( (int) $this->get_array_value( $size_data, 'width' ) );
|
||||
$this->set_height( (int) $this->get_array_value( $size_data, 'height' ) );
|
||||
$this->set_mime_type( (string) $this->get_array_value( $size_data, 'mime-type' ) );
|
||||
$this->set_filesize( (int) $this->get_array_value( $size_data, 'filesize' ) );
|
||||
}
|
||||
|
||||
private function get_array_value( $array, $key ) {
|
||||
return isset( $array[ $key ] ) ? $array[ $key ] : null;
|
||||
}
|
||||
|
||||
public function get_file_name_without_extension() {
|
||||
return mb_substr( $this->get_file_name(), 0, mb_strlen( $this->get_file_name() ) - mb_strlen( '.' . $this->get_extension() ) );
|
||||
}
|
||||
|
||||
public function get_file_name() {
|
||||
return $this->file_name;
|
||||
}
|
||||
|
||||
public function set_file_name( $file_name ) {
|
||||
$this->file_name = $file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_file_path() {
|
||||
return path_join( $this->dir, $this->get_file_name() );
|
||||
}
|
||||
|
||||
public function get_file_url() {
|
||||
$base_url = $this->base_url;
|
||||
$file_name = $this->get_file_name();
|
||||
|
||||
return "$base_url$file_name";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_width() {
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $width
|
||||
*/
|
||||
public function set_width( $width ) {
|
||||
$this->width = $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_height() {
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $height
|
||||
*/
|
||||
public function set_height( $height ) {
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_mime_type() {
|
||||
return $this->mime_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mime_type
|
||||
*/
|
||||
public function set_mime_type( $mime_type ) {
|
||||
$this->mime_type = $mime_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_filesize() {
|
||||
return $this->filesize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $filesize
|
||||
*/
|
||||
public function set_filesize( $filesize ) {
|
||||
$this->filesize = $filesize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_key() {
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function has_wp_metadata() {
|
||||
return ! empty( $this->wp_metadata );
|
||||
}
|
||||
|
||||
public function is_smushable() {
|
||||
return $this->is_size_selected_in_settings() &&
|
||||
$this->media_image_filter();
|
||||
}
|
||||
|
||||
public function exceeds_size_limit() {
|
||||
return $this->get_filesize() > $this->size_limit;
|
||||
}
|
||||
|
||||
private function media_image_filter() {
|
||||
return apply_filters( 'wp_smush_media_image', true, $this->get_key(), $this->get_file_path(), $this->get_attachment_id() );
|
||||
}
|
||||
|
||||
public function file_exists() {
|
||||
return $this->fs->file_exists( $this->get_file_path() );
|
||||
}
|
||||
|
||||
private function is_size_selected_in_settings() {
|
||||
if ( $this->get_key() === 'full' ) {
|
||||
return $this->settings->get( 'original' );
|
||||
}
|
||||
|
||||
$selected = $this->settings->get_setting( 'wp-smush-image_sizes' );
|
||||
if ( empty( $selected ) || ! is_array( $selected ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return in_array( $this->get_key(), $selected );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_size_limit() {
|
||||
return $this->size_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size_limit
|
||||
*/
|
||||
public function set_size_limit( $size_limit ) {
|
||||
$this->size_limit = $size_limit;
|
||||
}
|
||||
|
||||
public function get_dir() {
|
||||
return $this->dir;
|
||||
}
|
||||
|
||||
public function get_extension() {
|
||||
if ( is_null( $this->extension ) ) {
|
||||
$this->extension = $this->prepare_extension();
|
||||
}
|
||||
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
public function prepare_extension() {
|
||||
return pathinfo( $this->get_file_path(), PATHINFO_EXTENSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_attachment_id() {
|
||||
return $this->attachment_id;
|
||||
}
|
||||
}
|
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Media;
|
||||
|
||||
class Media_Item_Stats {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size_before = 0;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size_after = 0;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $time = 0.0;
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function get_percent() {
|
||||
return $this->calculate_percentage(
|
||||
$this->get_size_before(),
|
||||
$this->get_size_after()
|
||||
);
|
||||
}
|
||||
|
||||
public function get_human_bytes() {
|
||||
$bytes = $this->get_bytes();
|
||||
|
||||
return size_format(
|
||||
$bytes,
|
||||
$bytes >= 1024 ? 1 : 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_bytes() {
|
||||
$size_before = $this->get_size_before();
|
||||
$size_after = $this->get_size_after();
|
||||
|
||||
return $size_before > $size_after
|
||||
? $size_before - $size_after
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_size_before() {
|
||||
return $this->size_before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size_before
|
||||
*/
|
||||
public function set_size_before( $size_before ) {
|
||||
$this->size_before = (int) $size_before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function get_size_after() {
|
||||
return $this->size_after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size_after
|
||||
*/
|
||||
public function set_size_after( $size_after ) {
|
||||
$this->size_after = (int) $size_after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function get_time() {
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $time
|
||||
*/
|
||||
public function set_time( $time ) {
|
||||
$this->time = (float) $time;
|
||||
}
|
||||
|
||||
public function from_array( $array ) {
|
||||
$this->set_time( (float) $this->get_array_value( $array, 'time' ) );
|
||||
$this->set_size_before( (int) $this->get_array_value( $array, 'size_before' ) );
|
||||
$this->set_size_after( (int) $this->get_array_value( $array, 'size_after' ) );
|
||||
}
|
||||
|
||||
public function is_empty() {
|
||||
return empty( $this->get_size_before() ) && empty( $this->get_size_after() );
|
||||
}
|
||||
|
||||
public function to_array() {
|
||||
return array(
|
||||
'time' => $this->get_time(),
|
||||
'bytes' => $this->get_bytes(),
|
||||
'percent' => $this->get_percent(),
|
||||
'size_before' => $this->get_size_before(),
|
||||
'size_after' => $this->get_size_after(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_array_value( $array, $key ) {
|
||||
return isset( $array[ $key ] ) ? $array[ $key ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add values from the passed stats object to the current object
|
||||
*
|
||||
* @param $addend Media_Item_Stats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add( $addend ) {
|
||||
$new_size_before = $this->get_size_before() + $addend->get_size_before();
|
||||
$new_size_after = $this->get_size_after() + $addend->get_size_after();
|
||||
$new_time = $this->get_time() + $addend->get_time();
|
||||
|
||||
// Update with new values
|
||||
$this->set_time( $new_time );
|
||||
$this->set_size_before( $new_size_before );
|
||||
$this->set_size_after( $new_size_after );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $subtrahend Media_Item_Stats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function subtract( $subtrahend ) {
|
||||
$new_size_before = $this->get_size_before() - $subtrahend->get_size_before();
|
||||
$new_size_after = $this->get_size_after() - $subtrahend->get_size_after();
|
||||
$new_time = $this->get_time() - $subtrahend->get_time();
|
||||
|
||||
// Update with new values
|
||||
$this->set_time( max( $new_time, 0 ) );
|
||||
$this->set_size_before( max( $new_size_before, 0 ) );
|
||||
$this->set_size_after( max( $new_size_after, 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $to_check Media_Item_Stats
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function equals( $to_check ) {
|
||||
return $this->get_size_before() === $to_check->get_size_before()
|
||||
&& $this->get_size_after() === $to_check->get_size_after()
|
||||
&& $this->get_time() === $to_check->get_time();
|
||||
}
|
||||
|
||||
private function calculate_percentage( $size_before, $size_after ) {
|
||||
$savings = $size_before - $size_after;
|
||||
if ( $savings > 0 && $size_before > 0 ) {
|
||||
$percentage = ( $savings / $size_before ) * 100;
|
||||
|
||||
return $percentage > 0
|
||||
? round( $percentage, 2 )
|
||||
: $percentage;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $to_copy Media_Item_Stats
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function copy( $to_copy ) {
|
||||
$this->from_array( $to_copy->to_array() );
|
||||
}
|
||||
}
|
1143
wp-content/plugins/wp-smushit/core/media/class-media-item.php
Normal file
1143
wp-content/plugins/wp-smushit/core/media/class-media-item.php
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user