File "class-webp-optimization.php"
Full Path: /home/digimqhe/flashdigi.uk/wp-smushit/core/webp/class-webp-optimization.php
File size: 8.5 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace Smush\Core\Webp;
use Smush\Core\Array_Utils;
use Smush\Core\File_System;
use Smush\Core\Media\Media_Item;
use Smush\Core\Media\Media_Item_Optimization;
use Smush\Core\Media\Media_Item_Size;
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';
const WEBP_META_KEY = 'wp-smush-webp-data';
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;
/**
* @var Media_Item_Stats[]
*/
private $size_stats = array();
/**
* @var Array_Utils
*/
private $array_utils;
/**
* @var array
*/
private $meta;
/**
* @var Media_Item_Stats
*/
private $stats;
private $reset_properties = array(
'meta',
'stats',
'size_stats',
);
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();
$this->array_utils = new Array_Utils();
}
public function get_key() {
return self::OPTIMIZATION_KEY;
}
public function get_name() {
return __( 'WebP', 'wp-smushit' );
}
public function is_optimized() {
$stats_available = ! $this->get_stats()->is_empty();
if ( $stats_available ) {
return true;
}
return $this->webp_helper->legacy_webp_flag_file_exists( $this->media_item->get_id() );
}
public function should_optimize() {
if (
$this->media_item->is_skipped()
|| $this->media_item->has_errors()
|| $this->settings->is_avif_module_active()
|| ! $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;
}
if ( ! $this->has_converted_file() ) {
return true;
}
$smushable_sizes = $this->get_sizes_to_convert();
foreach ( $smushable_sizes as $size ) {
$size_stats = $this->get_size_stats( $size->get_key() );
$webp_file_path = $this->webp_helper->get_webp_file_path( $size->get_file_path() );
$size_has_webp_file = $this->fs->file_exists( $webp_file_path );
$is_size_optimized = ! $size_stats->is_empty() || $size_has_webp_file;
if ( ! $is_size_optimized ) {
return true;
}
}
return false;
}
private function has_converted_file() {
$smushable_sizes = $this->get_sizes_to_convert();
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() {
$attachment_id = $this->media_item->get_id();
$meta = $this->make_meta();
if ( ! empty( $meta ) ) {
update_post_meta( $attachment_id, self::WEBP_META_KEY, $meta );
$this->reset();
// TODO: this is a legacy flag
$this->webp_helper->unset_legacy_webp_flag( $attachment_id );
}
}
public function get_stats() {
if ( is_null( $this->stats ) ) {
$this->stats = $this->prepare_stats();
}
return $this->stats;
}
private function prepare_stats() {
$meta = $this->array_utils->get_array_value( $this->get_meta(), 'stats' );
$meta = $this->array_utils->ensure_array( $meta );
$stats = new Media_Item_Stats();
$stats->from_array( $meta );
return $stats;
}
public function get_size_stats( $size_key ) {
if ( empty( $this->size_stats[ $size_key ] ) ) {
$this->size_stats[ $size_key ] = $this->prepare_size_stats( $size_key );
}
return $this->size_stats[ $size_key ];
}
private function prepare_size_stats( $size_key ) {
$size_webp_stats = new Media_Item_Stats();
$size_webp_stats->from_array( $this->get_size_meta( $size_key ) );
return $size_webp_stats;
}
public function get_file() {
$meta = $this->get_meta();
return $this->array_utils->get_array_value( $meta, 'file', '' );
}
public function get_meta() {
if ( is_null( $this->meta ) ) {
$this->meta = $this->fetch_meta();
}
return $this->meta;
}
private function fetch_meta() {
$post_meta = get_post_meta( $this->media_item->get_id(), self::WEBP_META_KEY, true );
return $this->array_utils->ensure_array( $post_meta );
}
private function get_sizes_meta() {
$smush_meta = $this->get_meta();
$sizes_meta = $this->array_utils->get_array_value( $smush_meta, 'sizes' );
return $this->array_utils->ensure_array( $sizes_meta );
}
private function get_size_meta( $size_key ) {
$sizes = $this->get_sizes_meta();
$size = $this->array_utils->get_array_value( $sizes, $size_key );
return $this->array_utils->ensure_array( $size );
}
private function make_meta() {
$meta = array();
$meta['stats'] = $this->get_stats()->to_array();
foreach ( $this->get_sizes_to_convert() as $size_key => $size ) {
$size_stats = $this->get_size_stats( $size_key );
if ( ! $size_stats->is_empty() ) {
$meta['sizes'][ $size_key ] = $size_stats->to_array();
}
}
$file_path = $this->media_item->get_full_or_scaled_size()->get_file_path();
$webp_rel_path = $this->webp_helper->file_path_to_webp_flag( $this->webp_helper->get_webp_file_path( $file_path ) );
$meta['file'] = $webp_rel_path;
return $meta;
}
public function should_optimize_size( $size ) {
if ( ! $this->should_optimize() ) {
return false;
}
return array_key_exists(
$size->get_key(),
$this->get_sizes_to_convert()
);
}
public function delete_data() {
// TODO: this is a legacy flag
$this->webp_helper->unset_legacy_webp_flag( $this->media_item->get_id() );
delete_post_meta( $this->media_item->get_id(), self::WEBP_META_KEY );
$this->reset();
}
public function optimize() {
$files_data = array_map( function ( $size ) {
return array(
'url' => $size->get_file_url(),
'path' => $size->get_file_path(),
);
}, $this->get_sizes_to_convert() );
$responses = $this->converter->smush( $files_data );
$success_responses = array_filter( $responses );
if ( count( $success_responses ) !== count( $responses ) ) {
return false;
}
$media_item_stats = new Media_Item_Stats();
foreach ( $responses as $size_key => $data ) {
$this->update_from_response( $size_key, $data, $media_item_stats );
}
$this->get_stats()->from_array( $media_item_stats->to_array() );
$this->save();
return true;
}
public function get_optimized_file_url( $original_file_url ) {
return $this->webp_helper->get_webp_file_url( $original_file_url );
}
public function get_errors() {
return $this->converter->get_errors();
}
public function get_optimized_sizes_count() {
$count = 0;
$sizes = $this->get_sizes_meta();
foreach ( $sizes as $size_key => $size ) {
$size_stats = $this->get_size_stats( $size_key );
if ( $size_stats && ! $size_stats->is_empty() ) {
$count ++;
}
}
return $count;
}
/**
* @param $size_key
* @param object $data
* @param $media_item_stats Media_Item_Stats
*/
private function update_from_response( $size_key, $data, $media_item_stats ) {
$size_stats = $this->get_size_stats( $size_key );
$size_stats->from_array( $this->size_stats_from_response( $size_stats, $data ) );
$media_item_stats->add( $size_stats );
}
/**
* @param $existing_stats Media_Item_Stats
* @param $data \stdClass Response from the API
*
* @return array
*/
private function size_stats_from_response( $existing_stats, $data ) {
$data_before_size = empty( $data->before_size ) ? 0 : $data->before_size;
$data_after_size = empty( $data->after_size ) ? 0 : $data->after_size;
$data_time = empty( $data->time ) ? 0 : $data->time;
$size_before = max( $existing_stats->get_size_before(), $data_before_size ); // We want to use the oldest before size
return array(
'size_before' => $size_before,
'size_after' => $data_after_size,
'time' => $data_time,
);
}
private function reset() {
foreach ( $this->reset_properties as $property ) {
$this->$property = null;
}
}
/**
* @return Media_Item_Size[]
*/
public function get_sizes_to_convert() {
return $this->media_item->get_smushable_sizes();
}
}