PATH:
home
/
letacommog
/
slution01
/
wp-content
/
plugins
/
tiny-compress-images
/
src
<?php /* * Tiny Compress Images - WordPress plugin. * Copyright (C) 2015-2018 Tinify B.V. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ class Tiny_Image { const ORIGINAL = 0; /** @var Tiny_Settings */ private $settings; private $id; private $name; private $wp_metadata; private $sizes = array(); private $statistics = array(); public function __construct( $settings, $id, $wp_metadata = null, $tiny_metadata = null, $active_sizes = null, $active_tinify_sizes = null ) { $this->settings = $settings; $this->id = $id; $this->wp_metadata = $wp_metadata; $this->parse_wp_metadata(); $this->parse_tiny_metadata( $tiny_metadata ); $this->detect_duplicates( $active_sizes, $active_tinify_sizes ); } private function parse_wp_metadata() { if ( ! is_array( $this->wp_metadata ) ) { $this->wp_metadata = wp_get_attachment_metadata( $this->id ); } if ( ! is_array( $this->wp_metadata ) || ! isset( $this->wp_metadata['file'] ) ) { /* No file metadata found, this might be another plugin messing with metadata. Simply ignore this! */ return; } $upload_dir = wp_upload_dir(); $path_prefix = $upload_dir['basedir'] . '/'; $path_info = pathinfo( $this->wp_metadata['file'] ); if ( isset( $path_info['dirname'] ) ) { $path_prefix .= $path_info['dirname'] . '/'; } /* Do not use pathinfo for getting the filename. It doesn't work when the filename starts with a special character. */ $path_parts = explode( '/', $this->wp_metadata['file'] ); $this->name = end( $path_parts ); $filename = $path_prefix . $this->name; $this->sizes[ self::ORIGINAL ] = new Tiny_Image_Size( $filename ); // Ensure 'sizes' exists and is an array to prevent PHP Warnings $sizes = isset( $this->wp_metadata['sizes'] ) && is_array( $this->wp_metadata['sizes'] ) ? $this->wp_metadata['sizes'] : array(); $sanitized_sizes = array(); foreach ( $sizes as $size_name => $size_info ) { // size is valid when its an array and has a file if ( is_array( $size_info ) && isset( $size_info['file'] ) ) { // Add to sanitized metadata $sanitized_sizes[ $size_name ] = $size_info; $this->sizes[ $size_name ] = new Tiny_Image_Size( $path_prefix . $size_info['file'] ); } } // Update the metadata with only the valid sizes found $this->wp_metadata['sizes'] = $sanitized_sizes; } private function detect_duplicates( $active_sizes, $active_tinify_sizes ) { $filenames = array(); if ( is_array( $this->wp_metadata ) && isset( $this->wp_metadata['file'] ) && isset( $this->wp_metadata['sizes'] ) && is_array( $this->wp_metadata['sizes'] ) ) { if ( null == $active_sizes ) { $active_sizes = $this->settings->get_sizes(); } if ( null == $active_tinify_sizes ) { $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); } foreach ( $this->wp_metadata['sizes'] as $size_name => $size ) { if ( $this->sizes[ $size_name ]->has_been_compressed() && array_key_exists( $size_name, $active_sizes ) ) { $filenames = $this->duplicate_check( $filenames, $size['file'], $size_name ); } } foreach ( $this->wp_metadata['sizes'] as $size_name => $size ) { if ( in_array( $size_name, $active_tinify_sizes, true ) ) { $filenames = $this->duplicate_check( $filenames, $size['file'], $size_name ); } } foreach ( $this->wp_metadata['sizes'] as $size_name => $size ) { if ( array_key_exists( $size_name, $active_sizes ) ) { $filenames = $this->duplicate_check( $filenames, $size['file'], $size_name ); } } foreach ( $this->wp_metadata['sizes'] as $size_name => $size ) { $filenames = $this->duplicate_check( $filenames, $size['file'], $size_name ); } } } private function duplicate_check( $filenames, $file, $size_name ) { if ( isset( $filenames[ $file ] ) ) { if ( $filenames[ $file ] != $size_name ) { $this->sizes[ $size_name ]->mark_duplicate( $filenames[ $file ] ); } } else { $filenames[ $file ] = $size_name; } return $filenames; } private function parse_tiny_metadata( $tiny_metadata = null ) { if ( is_null( $tiny_metadata ) ) { $tiny_metadata = get_post_meta( $this->id, Tiny_Config::META_KEY, true ); } if ( $tiny_metadata ) { foreach ( $tiny_metadata as $size => $meta ) { if ( ! isset( $this->sizes[ $size ] ) ) { if ( self::is_retina( $size ) && Tiny_Settings::wr2x_active() ) { $size_name = rtrim( $size, '_wr2x' ); if ( 'original' === $size_name ) { $size_name = '0'; } $retina_path = wr2x_get_retina( $this->sizes[ $size_name ]->filename ); $this->sizes[ $size ] = new Tiny_Image_Size( $retina_path ); } else { $this->sizes[ $size ] = new Tiny_Image_Size(); } } $this->sizes[ $size ]->meta = $meta; } } } public function get_id() { return $this->id; } public function get_name() { return $this->name; } public function get_wp_metadata() { return $this->wp_metadata; } public function file_type_allowed() { return in_array( $this->get_mime_type(), array( 'image/jpeg', 'image/png', 'image/webp' ) ); } public function get_mime_type() { return get_post_mime_type( $this->id ); } public function compress() { if ( $this->settings->get_compressor() === null || ! $this->file_type_allowed() ) { return; } $success = 0; $failed = 0; $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); if ( $this->settings->get_conversion_enabled() ) { $uncompressed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); $unprocessed_sizes = $uncompressed_sizes + $unconverted_sizes; } else { $unprocessed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); } $compressor = $this->settings->get_compressor(); $convert_to = $this->convert_to(); foreach ( $unprocessed_sizes as $size_name => $size ) { if ( ! $size->is_duplicate() ) { $size->add_tiny_meta_start(); $this->update_tiny_post_meta(); $resize = $this->settings->get_resize_options( $size_name ); $preserve = $this->settings->get_preserve_options( $size_name ); try { $response = $compressor->compress_file( $size->filename, $resize, $preserve, $convert_to ); // ensure that all conversion are in the same format as the first one $convert_to = isset( $response['convert'] ) ? array( $response['convert']['type'] ) : $convert_to; $size->add_tiny_meta( $response ); $success++; } catch ( Tiny_Exception $e ) { $size->add_tiny_meta_error( $e ); $failed++; } $this->add_wp_metadata( $size_name, $size ); $this->update_tiny_post_meta(); } } /* Other plugins can hook into this action to execute custom logic after the image sizes have been compressed, ie. cache flushing. */ do_action( 'tiny_image_after_compression', $this->id, $success ); return array( 'success' => $success, 'failed' => $failed, ); } public function delete_converted_image() { $sizes = $this->get_image_sizes(); foreach ( $sizes as $size ) { $size->delete_converted_image_size(); } } public function compress_retina( $size_name, $path ) { if ( $this->settings->get_compressor() === null || ! $this->file_type_allowed() ) { return; } if ( ! isset( $this->sizes[ $size_name ] ) ) { $this->sizes[ $size_name ] = new Tiny_Image_Size( $path ); } $size = $this->sizes[ $size_name ]; $compressor = $this->settings->get_compressor(); $convert_to = $this->convert_to(); if ( ! $size->has_been_compressed() ) { $size->add_tiny_meta_start(); $this->update_tiny_post_meta(); $preserve = $this->settings->get_preserve_options( $size_name ); try { $response = $compressor->compress_file( $path, false, $preserve, $convert_to ); $size->add_tiny_meta( $response ); } catch ( Tiny_Exception $e ) { $size->add_tiny_meta_error( $e ); } $this->update_tiny_post_meta(); } } public function remove_retina_metadata() { // Remove metadata from all sizes, as this callback only fires when all // retina sizes are deleted. foreach ( $this->sizes as $size_name => $size ) { if ( self::is_retina( $size_name ) ) { unset( $this->sizes[ $size_name ] ); } } $this->update_tiny_post_meta(); } public function add_wp_metadata( $size_name, $size ) { if ( self::is_original( $size_name ) ) { if ( isset( $size->meta['output'] ) ) { $output = $size->meta['output']; if ( isset( $output['width'] ) && isset( $output['height'] ) ) { $this->wp_metadata['width'] = $output['width']; $this->wp_metadata['height'] = $output['height']; $this->wp_metadata['filesize'] = $output['size']; } } } } public function update_tiny_post_meta() { $tiny_metadata = array(); foreach ( $this->sizes as $size_name => $size ) { $tiny_metadata[ $size_name ] = $size->meta; } update_post_meta( $this->id, Tiny_Config::META_KEY, $tiny_metadata ); /* This action is being used by WPML: https://gist.github.com/srdjan-jcc/5c47685cda4da471dff5757ba3ce5ab1 */ do_action( 'updated_tiny_postmeta', $this->id, Tiny_Config::META_KEY, $tiny_metadata ); } public function get_image_sizes() { $original = isset( $this->sizes[ self::ORIGINAL ] ) ? array( self::ORIGINAL => $this->sizes[ self::ORIGINAL ], ) : array(); $compressed = array(); $uncompressed = array(); foreach ( $this->sizes as $size_name => $size ) { if ( self::is_original( $size_name ) ) { continue; } if ( $size->has_been_compressed() ) { $compressed[ $size_name ] = $size; } else { $uncompressed[ $size_name ] = $size; } } ksort( $compressed ); ksort( $uncompressed ); return $original + $compressed + $uncompressed; } public function get_image_size( $size = self::ORIGINAL, $create = false ) { if ( isset( $this->sizes[ $size ] ) ) { return $this->sizes[ $size ]; } elseif ( $create ) { return new Tiny_Image_Size(); } else { return null; } } public function filter_image_sizes( $method, $filter_sizes = null ) { $selection = array(); if ( is_null( $filter_sizes ) ) { $filter_sizes = array_keys( $this->sizes ); } foreach ( $filter_sizes as $size_name ) { if ( ! isset( $this->sizes[ $size_name ] ) ) { continue; } $tiny_image_size = $this->sizes[ $size_name ]; if ( $tiny_image_size->$method() ) { $selection[ $size_name ] = $tiny_image_size; } } return $selection; } public function get_count( $methods, $count_sizes = null ) { $stats = array_fill_keys( $methods, 0 ); if ( is_null( $count_sizes ) ) { $count_sizes = array_keys( $this->sizes ); } foreach ( $count_sizes as $size ) { if ( ! isset( $this->sizes[ $size ] ) ) { continue; } foreach ( $methods as $method ) { if ( $this->sizes[ $size ]->$method() ) { $stats[ $method ]++; } } } return $stats; } public function get_latest_error() { $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); $error_message = null; $last_timestamp = null; foreach ( $this->sizes as $size_name => $size ) { if ( in_array( $size_name, $active_tinify_sizes, true ) ) { if ( isset( $size->meta['error'] ) && isset( $size->meta['message'] ) ) { if ( null === $last_timestamp || $last_timestamp < $size->meta['timestamp'] ) { $last_timestamp = $size->meta['timestamp']; $error_message = Tiny_Helpers::truncate_text( $size->meta['message'], 140 ); } } } } return $error_message; } public function get_savings( $stats ) { $before = $stats['initial_total_size']; $after = $stats['compressed_total_size']; if ( 0 === $before ) { $savings = 0; } else { $savings = ($before - $after) / $before * 100; } return '' . number_format( $savings, 1 ); } public function get_statistics( $active_sizes, $active_tinify_sizes ) { if ( $this->statistics ) { error_log( 'Strangely the image statistics are asked for again.' ); return $this->statistics; } $this->statistics['initial_total_size'] = 0; $this->statistics['compressed_total_size'] = 0; $this->statistics['image_sizes_compressed'] = 0; $this->statistics['available_uncompressed_sizes'] = 0; $this->statistics['image_sizes_converted'] = 0; $this->statistics['available_unconverted_sizes'] = 0; foreach ( $this->sizes as $size_name => $size ) { // skip duplicates or inactive sizes if ( $size->is_duplicate() || ! isset( $active_sizes[ $size_name ] ) ) { continue; } $file_size = $size->filesize(); $is_active_size = in_array( $size_name, $active_tinify_sizes, true ); if ( isset( $size->meta['input'] ) ) { $input_size = (int) $size->meta['input']['size']; $this->statistics['initial_total_size'] += $input_size; if ( isset( $size->meta['output'] ) ) { $output_size = (int) $size->meta['output']['size']; if ( $size->modified() ) { $this->statistics['compressed_total_size'] += $file_size; if ( $is_active_size ) { $this->statistics['available_uncompressed_sizes']++; } } else { $this->statistics['compressed_total_size'] += $output_size; $this->statistics['image_sizes_compressed']++; } } else { $this->statistics['compressed_total_size'] += $input_size; } } elseif ( $size->exists() ) { $this->statistics['initial_total_size'] += $file_size; $this->statistics['compressed_total_size'] += $file_size; if ( $is_active_size ) { $this->statistics['available_uncompressed_sizes']++; } } if ( $is_active_size ) { if ( $size->has_been_converted() ) { $this->statistics['image_sizes_converted']++; } else { $this->statistics['available_unconverted_sizes']++; } } }// End foreach(). return $this->statistics; } public static function is_original( $size ) { return self::ORIGINAL === $size; } public static function is_retina( $size ) { return strrpos( $size, 'wr2x' ) === strlen( $size ) - strlen( 'wr2x' ); } public function can_be_converted() { return $this->settings->get_conversion_enabled() && $this->file_type_allowed(); } /** * Get the targeted conversion. * If original is already converted, then we use the originals' mimetype. * If nothing is converted yet, we use the settings conversion settings. * * @since 3.6.4 * * @return array{string} mimetypes to which the image should be converted to */ private function convert_to() { $convert_settings = $this->settings->get_conversion_options(); if ( ! $convert_settings['convert'] ) { // conversion is off so return no mimetypes to convert to return array(); } if ( isset( $this->sizes[ self::ORIGINAL ] ) ) { // original is not in sizes so mimetypes are open return $convert_settings['convert_to']; } $original_img_size = $this->sizes[ self::ORIGINAL ]; if ( $original_img_size->converted() ) { // original has been convert so use that mimetype to convert to return array( $original_img_size->meta['convert']['type'] ); } return $convert_settings['convert_to']; } /** * Marks the image as compressed without actually compressing it. * * This method parses existing metadata and delegates to each image size to mark * itself as compressed. It considers conversion settings when marking the sizes. * This is useful for images that are already optimized or when you want to skip * compression while still marking them as processed in the system. * * @since 3.0.0 */ public function mark_as_compressed() { $this->parse_tiny_metadata(); $conversion_enabled = $this->settings->get_conversion_enabled(); $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); if ( $this->settings->get_conversion_enabled() ) { $uncompressed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); $unprocessed_sizes = $uncompressed_sizes + $unconverted_sizes; } else { $unprocessed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); } foreach ( $unprocessed_sizes as $size ) { $size->mark_as_compressed( $conversion_enabled ); } $this->update_tiny_post_meta(); } }
[+]
..
[+]
images
[+]
config
[-] class-tiny-wp-base.php
[edit]
[-] class-tiny-image-size.php
[edit]
[-] class-tiny-picture.php
[edit]
[+]
views
[+]
js
[+]
vendor
[-] class-tiny-settings.php
[edit]
[-] class-tiny-compress.php
[edit]
[-] class-tiny-compress-fopen.php
[edit]
[-] class-tiny-cli.php
[edit]
[-] class-tiny-notices.php
[edit]
[+]
css
[+]
compatibility
[-] class-tiny-image.php
[edit]
[+]
data
[-] class-tiny-php.php
[edit]
[-] class-tiny-compress-client.php
[edit]
[-] class-tiny-exception.php
[edit]
[-] class-tiny-plugin.php
[edit]
[-] class-tiny-helpers.php
[edit]
[-] class-tiny-bulk-optimization.php
[edit]