BossBey File Manager
PHP:
8.2.30
OS:
Linux
User:
imagivibe
Root
/
home
/
imagivibe
/
www
/
wp-content
/
plugins
/
sg-cachepress
/
core
/
Images_Optimizer
📤 Upload
📝 New File
📁 New Folder
Close
Editing: Images_Optimizer.php
<?php namespace SiteGround_Optimizer\Images_Optimizer; use SiteGround_Optimizer\Supercacher\Supercacher; use SiteGround_Optimizer\Options\Options; use SiteGround_Optimizer\Front_End_Optimization\Front_End_Optimization; use SiteGround_Helper\Helper_Service; /** * SG Images_Optimizer main plugin class */ class Images_Optimizer extends Abstract_Images_Optimizer { /** * Set max image width. Default is 2560. * * @since 6.0.0 * * @var int max width value. */ const MAX_IMAGE_WIDTH = 2560; /** * Array containing options used for status updates. * * @var array */ public $options_map = array( 'completed' => 'siteground_optimizer_image_optimization_completed', 'status' => 'siteground_optimizer_image_optimization_status', 'stopped' => 'siteground_optimizer_image_optimization_stopped', ); /** * The type of image optimization. * * @var string */ public $type = 'image'; /** * The total non-optimized images option. * * @var string */ public $non_optimized = 'siteground_optimizer_total_unoptimized_images'; /** * The batch name * * @var string */ public $batch_skipped = 'siteground_optimizer_is_optimized'; /** * The ajax action we are using. * * @var string */ public $action = 'siteground_optimizer_start_image_optimization'; /** * Array containing all process * * @var array */ public $process_map = array( 'filter' => 'siteground_optimizer_image_optimization_timeout', 'attempts' => 'siteground_optimizer_optimization_attempts', 'failed' => 'siteground_optimizer_optimization_failed', ); /** * The type of cron we want to fire. * * @var string */ public $cron_type = 'siteground_optimizer_start_image_optimization_cron'; /** * The process lock we are using. * * @var string */ public $process_lock = 'siteground_optimizer_image_optimization_lock'; /** * The map for the compression levels for different file types. * * @var array */ public $compression_level_map = array( // IMAGETYPE_GIF. 1 => array( '1' => '-O1', // Low. '2' => '-O2', // Medium. '3' => '-O3', // High. ), // IMAGETYPE_JPEG. 2 => array( '1' => '-m85', // Low. '2' => '-m60', // Medium. '3' => '-m20', // High. ), // IMAGETYPE_PNG. 3 => array( '1' => '-o1', '2' => '-o2', '3' => '-o3', ), ); /** * The map for the maximum image width option. * * @var array */ public $default_max_width_sizes = array( array( 'label' => '2560px', 'value' => 2560, 'selected' => 0, ), array( 'label' => '2048px', 'value' => 2048, 'selected' => 0, ), array( 'label' => '1920px', 'value' => 1920, 'selected' => 0, ), array( 'label' => 'Disabled', 'value' => 0, 'selected' => 0, ), ); /** * Optimize the image * * @since 5.0.0 * * @param int $id The image id. * @param array $metadata The image metadata. * * @return bool True on success, false on failure. */ public function optimize( $id, $metadata ) { // Load the uploads dir. $upload_dir = wp_get_upload_dir(); // Get path to main image. $main_image = get_attached_file( $id ); // Bail if the override is disabled and the image has a custom compression level. if ( 1 !== intval( get_option( 'siteground_optimizer_overwrite_custom' ) ) && ! empty( get_post_meta( $id, 'siteground_optimizer_compression_level', true ) ) ) { return false; } // Get the basename. $basename = basename( $main_image ); // Get the command placeholder. It will be used by main image and to optimize the different image sizes. $status = $this->execute_optimization_command( $main_image ); // Optimization failed. if ( true === boolval( $status ) ) { update_post_meta( $id, 'siteground_optimizer_optimization_failed', 1 ); return false; } // Check if there are any sizes. if ( ! empty( $metadata['sizes'] ) ) { // Loop through all image sizes and optimize them as well. foreach ( $metadata['sizes'] as $size ) { // Replace main image with the cropped image and run the optimization command. $status = $this->execute_optimization_command( str_replace( $basename, $size['file'], $main_image ) ); // Optimization failed. if ( true === boolval( $status ) ) { update_post_meta( $id, 'siteground_optimizer_optimization_failed', 1 ); return false; } } } // Save the original filesize in new post meta. update_post_meta( $id, 'siteground_optimizer_original_filesize', $metadata['filesize'] ) ; // Replace the filesize in the metadata. $metadata['filesize'] = filesize( $main_image ); // Update the attachment metadata. wp_update_attachment_metadata( $id, $metadata ); // Everything ran smoothly. update_post_meta( $id, 'siteground_optimizer_is_optimized', 1 ); return true; } /** * Resize the uploaded image if width is greather than allowed. * * @since 6.0.0 * * @param array $image_data - contains file, url, type. */ public function resize( $image_data ) { // Getting the option value from the db and applying additional filters, if any. $image_resize_option = apply_filters( 'sgo_set_max_image_width', get_option( 'siteground_optimizer_resize_images', 2560 ) ); // Disable resize, if it's set so in the DB and no filters are found. if ( 0 === intval ( $image_resize_option ) ) { return false; } // Adding a min value. $image_resize_option = intval( $image_resize_option ) < 1200 ? 1200 : intval( $image_resize_option ); return intval( $image_resize_option ); } /** * Check if image exists and perform optimiation. * * @since 5.0.0 * * @param string $filepath The path to the file. * * @return bool False on success, true on failure. */ private function execute_optimization_command( $filepath, $compression_level = null ) { // Bail if the file doens't exists. if ( ! file_exists( $filepath ) ) { return true; } // Get option for the selected compression level. $compression_level = is_null( $compression_level ) ? intval( get_option( 'siteground_optimizer_compression_level' ) ) : $compression_level; // Bail if compression level is set to None. if ( 0 === $compression_level ) { return true; } $backup_filepath = preg_replace( '~.(png|jpg|jpeg|gif)$~', '.bak.$1', $filepath ); if ( Options::is_enabled( 'siteground_optimizer_backup_media' ) && ! file_exists( $backup_filepath ) ) { copy( $filepath, $backup_filepath ); } $status = $this->optimize_image( file_exists( $backup_filepath ) ? $backup_filepath : $filepath, $compression_level ); // Create webp copy of the webp is enabled. if ( Options::is_enabled( 'siteground_optimizer_webp_support' ) ) { Images_Optimizer_Webp::generate_webp_file( $filepath ); } return $status; } /** * Optimize the image. * * @since 6.0.0 * * @param string $filepath The image filepath. * @param int $level The optimization level. * * @return string The status code. */ public function optimize_image( $filepath, $level ) { // Get image type. $type = exif_imagetype( $filepath ); $output_filepath = preg_replace( '~\.bak.(png|jpg|jpeg|gif)$~', '.$1', $filepath ); switch ( $type ) { case IMAGETYPE_GIF: $placeholder = 'gifsicle %s --careful %s -o %s 2>&1'; break; case IMAGETYPE_JPEG: // DO NOT REMOVE THE LINE BELOW! // The jpegoptim doesn't support input/output params, so we need to create a backup of the original image. // However, if the filepaths are the same, this is skipped. if ( $filepath !== $output_filepath ) { copy( $filepath, $output_filepath ); } $placeholder = 'jpegoptim %1$s %3$s 2>&1'; break; case IMAGETYPE_PNG: // Bail if the image is bigger than 500k. // PNG usage is not recommended and images bigger than 500kb // hit the limits. if ( filesize( $filepath ) > self::PNGS_SIZE_LIMIT ) { return true; } $placeholder = 'optipng %s %s -out=%s 2>&1'; break; default: // Bail if the image type is not supported. return true; } // Optimize the image. exec( sprintf( $placeholder, // The command. $this->compression_level_map[ $type ][ $level ], // The compression level. $filepath, // Image path. $output_filepath // New Image path. ), $output, $status ); return $status; } /** * Optimize the preview image. * * @since 6.0.0 * * @param int $id The attachment id. */ public function get_preview_images( $id ) { $filepath = ! empty( $id ) ? get_attached_file( $id ) : \SiteGround_Optimizer\DIR . '/assets/images/preview.jpg'; $urls = array( 0 => array( 'compression' => 0, 'url' => str_replace( ABSPATH, Helper_Service::get_home_url(), $filepath ), 'size' => $this->get_human_readable_size( $filepath ), ), ); $output_dir = Front_End_Optimization::get_instance()->get_assets_dir() . 'previews/'; $basename = basename( $filepath ); if ( ! is_dir( $output_dir ) ) { Front_End_Optimization::get_instance()->create_directory( $output_dir ); } foreach ( $this->compression_level_map as $type => $levels ) { // Generate output folder. $output = $output_dir . $basename; // Copy the image. copy( $filepath, $output ); $this->optimize_image( $output, $type ); $new_filename = str_replace( basename( $output ), $type . '-' . $basename, $output ); rename( // phpcs:ignore $output, $new_filename ); $urls[ $type ]['url'] = str_replace( ABSPATH, Helper_Service::get_home_url(), $new_filename ); $urls[ $type ]['compression'] = intval( $type ); $urls[ $type ]['size'] = $this->get_human_readable_size( $new_filename ); } return $urls; } /** * Get a human readable string containing information regarding the size of a file. * * @since 6.0.0 * * @param string $filepath The path of the file that has to be sized. * * @return string The human-readable string with the size of the file. */ public function get_human_readable_size( $filepath ) { // Get the size of the file in bytes. $size = filesize( $filepath ); // Possible unit types. $units = array( 'B', 'kB', 'MB' ); $step = 1024; $i = 0; // Divide the size until it's less than 1 to find the correct unit. while ( ( $size / $step ) > 0.9 ) { $size = $size / $step; $i++; } // Return the human readable string. return round( $size, 2 ) . $units[ $i ]; } /** * Restore the original images. * * @since 6.0.0 * * @return The result of restore. */ public function restore_originals() { $basedir = Helper_Service::get_uploads_dir(); exec( "find $basedir -regextype posix-extended -type f -regex '.*bak.(png|jpg|jpeg|gif)$' -exec rename '.bak' '' {} \;", $output, $result ); // Reset the images metadata. $this->reset_images_filesize_meta(); // Reset the optimization status. $this->reset_image_optimization_status(); return $result; } /** * Delete the backup image on image delete. * * @since 6.0.0 * * @param int $id The attachment ID. */ public function delete_backups( $id ) { global $wp_filesystem; $main_image = get_attached_file( $id ); $metadata = wp_get_attachment_metadata( $id ); $basename = basename( $main_image ); $wp_filesystem->delete( preg_replace( '~.(png|jpg|jpeg|gif)$~', '.bak.$1', $main_image ) ); if ( ! empty( $metadata['sizes'] ) ) { // Loop through all image sizes and optimize them as well. foreach ( $metadata['sizes'] as $size ) { $wp_filesystem->delete( preg_replace( '~.(png|jpg|jpeg|gif)$~', '.bak.$1', str_replace( $basename, $size['file'], $main_image ) ) ); } } } /** * Add custom metabox for compression level per attachment, on the media screen. * * @since 6.0.6 * * @param array $form_fields Fields of the edit_attachment form. * @param WP_Post $post The object containing the attachment. * * @return array Fields of the edit_attachment form. */ public function custom_attachment_compression_level_field( $form_fields, $post ) { // Get current attachment compression level. $field_value = get_post_meta( $post->ID, 'siteground_optimizer_compression_level', true ); // If field value is empty - fallback to site global option. if ( ! is_numeric( $field_value ) ) { $field_value = get_option( 'siteground_optimizer_compression_level' ); } // The field html. $html = '<select name="compression_level">'; // Select options. $options = array( 'None', 'Low', 'Medium', 'High', ); // Add the select options to the html. foreach ( $options as $key => $value ) { $html .= '<option' . selected( $field_value, $key, false ) . ' value="' . $key . '">' . $value . '</option>'; } $html .= '</select>'; $form_fields['compression_level'] = array( 'value' => $field_value ? intval( $field_value ) : '', 'label' => __( 'Compression Level', 'sg-cachepress' ), 'input' => 'html', 'html' => $html, ); return $form_fields; } /** * Saving the new meta for the compression level of the attachment. * * @since 6.0.6 * * @param int $attachment_id ID of the attachment. * * @return bool|string Status code of the compression. */ public function custom_attachment_compression_level( $attachment_id ) { if ( ! isset( $_REQUEST['compression_level'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return $attachment_id; } // Update the attachment's meta. update_post_meta( $attachment_id, 'siteground_optimizer_compression_level', $_REQUEST['compression_level'] ); // phpcs:ignore // Get attachment's filepath. $filepath = get_attached_file( $attachment_id ); // Find backup image path. $backup_filepath = preg_replace( '~.(png|jpg|jpeg|gif)$~', '.bak.$1', $filepath ); // Check if backup file exists, if so, replace the file with the original one. if ( file_exists( $backup_filepath ) ) { copy( $backup_filepath, $filepath ); } // Compress the image only if the compression level is different than none. if ( 0 !== intval( $_REQUEST['compression_level'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended // Optimize the image with the new compression level. return $this->execute_optimization_command( $filepath, intval( $_REQUEST['compression_level'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } } /** * Retrieves default sizes and sets the selected value. * * @since 7.1.1 * * @return array Array with the labels, values and selected properties. */ public function prepare_max_width_sizes() { // Get set option for the resize, using 2560 for default. $image_resize_option = (int) get_option( 'siteground_optimizer_resize_images', 2560 ); // Retrieve local array. $sizes = $this->default_max_width_sizes; // Iterate and set the correct selected value. foreach ( $sizes as $index => $size ) { if ( $image_resize_option === $sizes[ $index ]['value'] ) { $sizes[ $index ]['selected'] = 1; } } // Returns the modified array. return $sizes; } /** * Reset the restored images original filesize in the metadata. * * @since 7.3.2 */ public function reset_images_filesize_meta() { // Get all images with backup filesize metadata available. $images = get_posts( array( 'post_type' => 'attachment', 'post_mime_type' => 'image', 'posts_per_page' => -1, 'fields' => 'ids', 'meta_query' => array( array( 'key' => 'siteground_optimizer_original_filesize', 'compare' => 'EXISTS', ), ), ) ); // Bail if we have no images with backup filesize metadata. if ( empty( $images ) ) { return; } // Restore the filesize metadata. foreach( $images as $image_id ) { // Get the image metadata. $metadata = wp_get_attachment_metadata( $image_id ); // Restore the original filesize metdata. $metadata['filesize'] = get_post_meta( $image_id, 'siteground_optimizer_original_filesize', true ); // Update the attachment metadata. wp_update_attachment_metadata( $image_id, $metadata ); } } }
Save
Cancel