first
This commit is contained in:
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\Controller;
|
||||
use Smush\Core\File_System;
|
||||
use Smush\Core\Helper;
|
||||
use Smush\Core\Media\Media_Item_Cache;
|
||||
use Smush\Core\Stats\Global_Stats;
|
||||
|
||||
class Webp_Controller extends Controller {
|
||||
const WEBP_OPTIMIZATION_ORDER = 20;
|
||||
/**
|
||||
* @var Webp_Helper
|
||||
*/
|
||||
private $helper;
|
||||
/**
|
||||
* @var Global_Stats
|
||||
*/
|
||||
private $global_stats;
|
||||
/**
|
||||
* @var Media_Item_Cache
|
||||
*/
|
||||
private $media_item_cache;
|
||||
/**
|
||||
* @var \WDEV_Logger|null
|
||||
*/
|
||||
private $logger;
|
||||
/**
|
||||
* @var File_System
|
||||
*/
|
||||
private $fs;
|
||||
|
||||
public function __construct() {
|
||||
$this->helper = new Webp_Helper();
|
||||
$this->global_stats = Global_Stats::get();
|
||||
$this->media_item_cache = Media_Item_Cache::get_instance();
|
||||
$this->logger = Helper::logger();
|
||||
$this->fs = new File_System();
|
||||
|
||||
$this->register_action( 'wp_smush_png_jpg_converted', array( $this, 'delete_webp_versions_of_pngs' ), 10, 4 );
|
||||
$this->register_action( 'delete_attachment', array( $this, 'delete_webp_versions_before_delete' ) );
|
||||
$this->register_filter( 'wp_smush_optimizations', array(
|
||||
$this,
|
||||
'add_webp_optimization',
|
||||
), self::WEBP_OPTIMIZATION_ORDER, 2 );
|
||||
$this->register_filter( 'wp_smush_global_optimization_stats', array( $this, 'add_webp_global_stats' ) );
|
||||
$this->register_action( 'wp_smush_before_restore_backup', array(
|
||||
$this,
|
||||
'delete_webp_versions_on_restore',
|
||||
), 10, 2 );
|
||||
$this->register_action( 'wp_smush_settings_updated', array(
|
||||
$this,
|
||||
'maybe_mark_global_stats_as_outdated',
|
||||
), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $backup_full_path
|
||||
* @param $attachment_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_webp_versions_on_restore( $backup_full_path, $attachment_id ) {
|
||||
$media_item = Media_Item_Cache::get_instance()->get( $attachment_id );
|
||||
if ( ! $media_item->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->helper->delete_media_item_webp_versions( $media_item );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete_webp_versions_before_delete( $attachment_id ) {
|
||||
$media_item = $this->media_item_cache->get( $attachment_id );
|
||||
if ( $media_item->is_valid() ) {
|
||||
foreach ( $media_item->get_size_paths() as $size_path ) {
|
||||
$this->delete_webp_version( $size_path );
|
||||
}
|
||||
} else {
|
||||
$this->logger->error( sprintf( 'Count not delete webp versions of the media item [%d]', $attachment_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function delete_webp_versions_of_pngs( $attachment_id, $meta, $stats, $png_paths ) {
|
||||
foreach ( $png_paths as $png_path ) {
|
||||
$this->delete_webp_version( $png_path );
|
||||
}
|
||||
|
||||
$this->helper->unset_webp_flag( $attachment_id );
|
||||
}
|
||||
|
||||
public function delete_webp_version( $original_path ) {
|
||||
$webp_file_path = $this->helper->get_webp_file_path( $original_path );
|
||||
if ( $this->fs->file_exists( $webp_file_path ) ) {
|
||||
$this->fs->unlink( $webp_file_path );
|
||||
}
|
||||
}
|
||||
|
||||
public function add_webp_optimization( $optimizations, $media_item ) {
|
||||
$optimization = new Webp_Optimization( $media_item );
|
||||
$optimizations[ $optimization->get_key() ] = $optimization;
|
||||
|
||||
return $optimizations;
|
||||
}
|
||||
|
||||
public function add_webp_global_stats( $stats ) {
|
||||
$stats[ Webp_Optimization::OPTIMIZATION_KEY ] = new Webp_Optimization_Global_Stats_Persistable();
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
public function maybe_mark_global_stats_as_outdated( $old_settings, $settings ) {
|
||||
$old_webp_status = ! empty( $old_settings['webp_mod'] );
|
||||
$new_webp_status = ! empty( $settings['webp_mod'] );
|
||||
if ( $old_webp_status !== $new_webp_status ) {
|
||||
$this->global_stats->mark_as_outdated();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\Smush\Smusher;
|
||||
|
||||
class Webp_Converter extends Smusher {
|
||||
/**
|
||||
* @var Webp_Helper
|
||||
*/
|
||||
private $webp_helper;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->webp_helper = new Webp_Helper();
|
||||
}
|
||||
|
||||
protected function get_api_request_headers( $file_path ) {
|
||||
$headers = parent::get_api_request_headers( $file_path );
|
||||
$headers['webp'] = 'true';
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function save_smushed_image_file( $file_path, $image ) {
|
||||
$webp_file_path = $this->webp_helper->get_webp_file_path( $file_path, true );
|
||||
$file_saved = file_put_contents( $webp_file_path, $image );
|
||||
if ( ! $file_saved ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $webp_file_path;
|
||||
}
|
||||
}
|
62
wp-content/plugins/wp-smushit/core/webp/class-webp-dir.php
Normal file
62
wp-content/plugins/wp-smushit/core/webp/class-webp-dir.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\Upload_Dir;
|
||||
|
||||
class Webp_Dir extends Upload_Dir {
|
||||
private $webp_path;
|
||||
|
||||
private $webp_rel_path;
|
||||
|
||||
private $webp_url;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_webp_path() {
|
||||
if ( is_null( $this->webp_path ) ) {
|
||||
$this->webp_path = $this->prepare_webp_path();
|
||||
}
|
||||
|
||||
return $this->webp_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_webp_rel_path() {
|
||||
if ( is_null( $this->webp_rel_path ) ) {
|
||||
$this->webp_rel_path = $this->prepare_webp_rel_path();
|
||||
}
|
||||
|
||||
return $this->webp_rel_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_webp_url() {
|
||||
if ( is_null( $this->webp_url ) ) {
|
||||
$this->webp_url = $this->prepare_webp_url();
|
||||
}
|
||||
|
||||
return $this->webp_url;
|
||||
}
|
||||
|
||||
private function prepare_webp_path() {
|
||||
return dirname( $this->get_upload_path() ) . '/smush-webp';
|
||||
}
|
||||
|
||||
private function prepare_webp_rel_path() {
|
||||
return dirname( $this->get_upload_rel_path() ) . '/smush-webp';
|
||||
}
|
||||
|
||||
private function prepare_webp_url() {
|
||||
return dirname( $this->get_upload_url() ) . '/smush-webp';
|
||||
}
|
||||
|
||||
protected function prepare_root_path() {
|
||||
return apply_filters( 'smush_webp_rules_root_path_base', parent::prepare_root_path() );
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\File_System;
|
||||
use Smush\Core\Media\Media_Item;
|
||||
use Smush\Core\Smush\Smush_Optimization;
|
||||
|
||||
class Webp_Helper {
|
||||
const WEBP_FLAG = 'webp_flag';
|
||||
/**
|
||||
* @var Webp_Dir
|
||||
*/
|
||||
private $webp_dir;
|
||||
/**
|
||||
* @var File_System
|
||||
*/
|
||||
private $fs;
|
||||
|
||||
public function __construct() {
|
||||
$this->webp_dir = new Webp_Dir();
|
||||
$this->fs = new File_System();
|
||||
}
|
||||
|
||||
public function get_webp_file_path( $file_path, $make = false ) {
|
||||
$file_rel_path = substr( $file_path, strlen( $this->webp_dir->get_upload_path() ) );
|
||||
$webp_file_path = $this->webp_dir->get_webp_path() . $file_rel_path . '.webp';
|
||||
|
||||
if ( $make ) {
|
||||
$webp_file_dir = dirname( $webp_file_path );
|
||||
if ( ! $this->fs->is_dir( $webp_file_dir ) ) {
|
||||
wp_mkdir_p( $webp_file_dir );
|
||||
}
|
||||
}
|
||||
|
||||
return $webp_file_path;
|
||||
}
|
||||
|
||||
public function supported_mime_types() {
|
||||
return array(
|
||||
'image/jpg',
|
||||
'image/jpeg',
|
||||
'image/x-citrix-jpeg',
|
||||
'image/png',
|
||||
'image/x-png',
|
||||
);
|
||||
}
|
||||
|
||||
public function get_webp_flag( $attachment_id ) {
|
||||
$meta = $this->get_smush_meta( $attachment_id );
|
||||
|
||||
return empty( $meta[ self::WEBP_FLAG ] ) ? '' : $meta[ self::WEBP_FLAG ];
|
||||
}
|
||||
|
||||
public function update_webp_flag( $attachment_id, $value ) {
|
||||
$meta = $this->get_smush_meta( $attachment_id );
|
||||
if ( empty( $value ) ) {
|
||||
unset( $meta[ self::WEBP_FLAG ] );
|
||||
} else {
|
||||
$meta[ self::WEBP_FLAG ] = $value;
|
||||
}
|
||||
update_post_meta( $attachment_id, Smush_Optimization::SMUSH_META_KEY, $meta );
|
||||
}
|
||||
|
||||
public function unset_webp_flag( $attachment_id ) {
|
||||
$this->update_webp_flag( $attachment_id, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|mixed
|
||||
*/
|
||||
private function get_smush_meta( $attachment_id ) {
|
||||
$meta = get_post_meta( $attachment_id, Smush_Optimization::SMUSH_META_KEY, true );
|
||||
|
||||
return empty( $meta ) ? array() : $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $media_item Media_Item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_media_item_webp_versions( $media_item ) {
|
||||
foreach ( $media_item->get_sizes() as $size ) {
|
||||
$webp_file_path = $this->get_webp_file_path( $size->get_file_path() );
|
||||
if ( $this->fs->file_exists( $webp_file_path ) ) {
|
||||
$this->fs->unlink( $webp_file_path );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\Stats\Media_Item_Optimization_Global_Stats_Persistable;
|
||||
|
||||
class Webp_Optimization_Global_Stats_Persistable extends Media_Item_Optimization_Global_Stats_Persistable {
|
||||
const GLOBAL_STATS_OPTION_ID = 'wp-smush-webp-global-stats';
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct( self::GLOBAL_STATS_OPTION_ID );
|
||||
}
|
||||
|
||||
public function save() {
|
||||
// Doing nothing. Since we don't keep stats for individual media items we can't
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Smush\Core\Webp;
|
||||
|
||||
use Smush\Core\File_System;
|
||||
use Smush\Core\Media\Media_Item;
|
||||
use Smush\Core\Media\Media_Item_Optimization;
|
||||
use Smush\Core\Media\Media_Item_Stats;
|
||||
use Smush\Core\Settings;
|
||||
|
||||
/**
|
||||
* TODO: the response from the API has webp: false and mime_content_type of the written file is not webp, investigate
|
||||
*/
|
||||
class Webp_Optimization extends Media_Item_Optimization {
|
||||
const OPTIMIZATION_KEY = 'webp_optimization';
|
||||
private $webp_dir;
|
||||
/**
|
||||
* @var Media_Item
|
||||
*/
|
||||
private $media_item;
|
||||
/**
|
||||
* @var Webp_Helper
|
||||
*/
|
||||
private $webp_helper;
|
||||
/**
|
||||
* @var Settings|null
|
||||
*/
|
||||
private $settings;
|
||||
/**
|
||||
* @var Webp_Converter
|
||||
*/
|
||||
private $converter;
|
||||
/**
|
||||
* @var File_System
|
||||
*/
|
||||
private $fs;
|
||||
|
||||
public function __construct( $media_item ) {
|
||||
$this->webp_dir = new Webp_Dir();
|
||||
$this->webp_helper = new Webp_Helper();
|
||||
$this->media_item = $media_item;
|
||||
$this->settings = Settings::get_instance();
|
||||
$this->converter = new Webp_Converter();
|
||||
$this->fs = new File_System();
|
||||
}
|
||||
|
||||
public function get_key() {
|
||||
return self::OPTIMIZATION_KEY;
|
||||
}
|
||||
|
||||
public function is_optimized() {
|
||||
$attachment_id = $this->media_item->get_id();
|
||||
$webp_flag = $this->webp_helper->get_webp_flag( $attachment_id );
|
||||
if ( empty( $webp_flag ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$webp_file_path = trailingslashit( $this->webp_dir->get_webp_path() ) . ltrim( $webp_flag, '/' );
|
||||
|
||||
return $this->fs->file_exists( $webp_file_path );
|
||||
}
|
||||
|
||||
public function should_optimize() {
|
||||
if (
|
||||
$this->media_item->is_skipped()
|
||||
|| $this->media_item->has_errors()
|
||||
|| ! $this->settings->is_webp_module_active()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array(
|
||||
$this->media_item->get_mime_type(),
|
||||
$this->webp_helper->supported_mime_types(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function should_reoptimize() {
|
||||
if ( ! $this->should_optimize() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$smushable_sizes = $this->media_item->get_smushable_sizes();
|
||||
foreach ( $smushable_sizes as $size ) {
|
||||
$webp_file_path = $this->webp_helper->get_webp_file_path( $size->get_file_path() );
|
||||
if ( ! $this->fs->file_exists( $webp_file_path ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$webp_file_path = $this->webp_helper->get_webp_file_path( $this->media_item->get_main_size()->get_file_path() );
|
||||
if ( $this->fs->file_exists( $webp_file_path ) ) {
|
||||
$relative_path = substr( $webp_file_path, strlen( $this->webp_dir->get_webp_path() . '/' ) );
|
||||
$this->webp_helper->update_webp_flag( $this->media_item->get_id(), $relative_path );
|
||||
}
|
||||
}
|
||||
|
||||
public function get_stats() {
|
||||
// Empty stats for now since we don't store webp savings
|
||||
return new Media_Item_Stats();
|
||||
}
|
||||
|
||||
public function get_size_stats( $size_key ) {
|
||||
// Empty stats for now since we don't store webp savings
|
||||
return new Media_Item_Stats();
|
||||
}
|
||||
|
||||
public function should_optimize_size( $size ) {
|
||||
if ( ! $this->should_optimize() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array_key_exists(
|
||||
$size->get_key(),
|
||||
$this->media_item->get_smushable_sizes()
|
||||
);
|
||||
}
|
||||
|
||||
public function delete_data() {
|
||||
$this->webp_helper->unset_webp_flag( $this->media_item->get_id() );
|
||||
}
|
||||
|
||||
public function optimize() {
|
||||
$media_item = $this->media_item;
|
||||
$file_paths = array_map( function ( $size ) {
|
||||
return $size->get_file_path();
|
||||
}, $media_item->get_smushable_sizes() );
|
||||
$responses = $this->converter->smush( $file_paths );
|
||||
$success_responses = array_filter( $responses );
|
||||
if ( count( $success_responses ) !== count( $responses ) ) {
|
||||
return false;
|
||||
}
|
||||
$this->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_errors() {
|
||||
return $this->converter->get_errors();
|
||||
}
|
||||
|
||||
public function get_optimized_sizes_count() {
|
||||
// We don't keep per-size stats
|
||||
return 0;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user