diff --git a/imagify.php b/imagify.php index 34551e2f5..37dc0bf96 100644 --- a/imagify.php +++ b/imagify.php @@ -3,7 +3,7 @@ * Plugin Name: Imagify * Plugin URI: https://wordpress.org/plugins/imagify/ * Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool. - * Version: 1.7.1 + * Version: 1.7.1.2 * Author: WP Media * Author URI: https://wp-media.me/ * Licence: GPLv2 @@ -17,7 +17,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' ); // Imagify defines. -define( 'IMAGIFY_VERSION' , '1.7.1' ); +define( 'IMAGIFY_VERSION' , '1.7.1.2' ); define( 'IMAGIFY_SLUG' , 'imagify' ); define( 'IMAGIFY_FILE' , __FILE__ ); define( 'IMAGIFY_PATH' , realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' ); diff --git a/inc/admin/custom-folders.php b/inc/admin/custom-folders.php index 0ad55e570..d422793ed 100644 --- a/inc/admin/custom-folders.php +++ b/inc/admin/custom-folders.php @@ -3,14 +3,15 @@ add_filter( 'upgrader_post_install', 'imagify_sync_theme_plugin_files_on_update', IMAGIFY_INT_MAX, 3 ); /** - * Sync files after a theme or plugin has been updated. + * Sync files right after a theme or plugin has been updated. * * @since 1.7 * @author Grégory Viguier * - * @param bool $response Installation response. - * @param array $hook_extra Extra arguments passed to hooked filters. - * @param array $result Installation result data. + * @param bool $response Installation response. + * @param array $hook_extra Extra arguments passed to hooked filters. + * @param array $result Installation result data. + * @return bool */ function imagify_sync_theme_plugin_files_on_update( $response, $hook_extra, $result ) { global $wpdb; @@ -19,46 +20,66 @@ function imagify_sync_theme_plugin_files_on_update( $response, $hook_extra, $res return $response; } - $folders_db = Imagify_Folders_DB::get_instance(); - $files_db = Imagify_Files_DB::get_instance(); + $folders_to_sync = get_site_transient( 'imagify_themes_plugins_to_sync' ); + $folders_to_sync = is_array( $folders_to_sync ) ? $folders_to_sync : array(); - if ( ! $folders_db->can_operate() || ! $files_db->can_operate() ) { - return; - } + $folders_to_sync[] = $result['destination']; - if ( ! Imagify_Requirements::is_api_key_valid() ) { - return; - } + set_site_transient( 'imagify_themes_plugins_to_sync', $folders_to_sync, DAY_IN_SECONDS ); + + return $response; +} + +add_action( 'admin_init', 'imagify_sync_theme_plugin_files_after_update' ); +/** + * Sync files after some themes or plugins have been updated. + * + * @since 1.7.1.2 + * @author Grégory Viguier + */ +function imagify_sync_theme_plugin_files_after_update() { + global $wpdb; - if ( Imagify_Requirements::is_over_quota() ) { + $folders_to_sync = get_site_transient( 'imagify_themes_plugins_to_sync' ); + + if ( ! $folders_to_sync || ! is_array( $folders_to_sync ) ) { return; } - $folder_path = trailingslashit( $result['destination'] ); + delete_site_transient( 'imagify_themes_plugins_to_sync' ); - if ( Imagify_Files_Scan::is_path_forbidden( $folder_path ) ) { - // This theme or plugin must not be optimized. - return $response; + $folders_db = Imagify_Folders_DB::get_instance(); + $files_db = Imagify_Files_DB::get_instance(); + + if ( ! $folders_db->can_operate() || ! $files_db->can_operate() ) { + return; } - // Get the related folder. - $placeholder = Imagify_Files_Scan::add_placeholder( $folder_path ); - $folder = Imagify_Folders_DB::get_instance()->get_in( 'path', $placeholder ); + foreach ( $folders_to_sync as $folder_path ) { + $folder_path = trailingslashit( $folder_path ); - if ( ! $folder ) { - // This theme or plugin is not in the database. - return $response; - } + if ( Imagify_Files_Scan::is_path_forbidden( $folder_path ) ) { + // This theme or plugin must not be optimized. + continue; + } - // Sync the folder files. - Imagify_Custom_Folders::synchronize_files_from_folders( array( - $folder['folder_id'] => array( - 'folder_id' => $folder['folder_id'], - 'path' => $placeholder, - 'active' => $folder['active'], - 'folder_path' => $folder_path, - ), - ) ); + // Get the related folder. + $placeholder = Imagify_Files_Scan::add_placeholder( $folder_path ); + $folder = Imagify_Folders_DB::get_instance()->get_in( 'path', $placeholder ); - return $response; + if ( ! $folder ) { + // This theme or plugin is not in the database. + continue; + } + + // Sync the folder files. + Imagify_Custom_Folders::synchronize_files_from_folders( array( + $folder['folder_id'] => array( + 'folder_id' => $folder['folder_id'], + 'path' => $placeholder, + 'active' => $folder['active'], + 'folder_path' => $folder_path, + ), + ) ); + } } diff --git a/inc/admin/upgrader.php b/inc/admin/upgrader.php index d316bdef7..0e0742470 100755 --- a/inc/admin/upgrader.php +++ b/inc/admin/upgrader.php @@ -270,3 +270,59 @@ function _imagify_new_upgrade( $network_version, $site_version ) { delete_option( $wpdb->prefix . 'ngg_imagify_data_db_version' ); } } + +add_action( 'upgrader_process_complete', 'imagify_maybe_reset_opcache', 20, 2 ); +/** + * Maybe reset opcache after Imagify update. + * + * @since 1.7.1.2 + * @author Grégory Viguier + * + * @param object $wp_upgrader Plugin_Upgrader instance. + * @param array $hook_extra { + * Array of bulk item update data. + * + * @type string $action Type of action. Default 'update'. + * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'. + * @type bool $bulk Whether the update process is a bulk update. Default true. + * @type array $plugins Array of the basename paths of the plugins' main files. + * } + */ +function imagify_maybe_reset_opcache( $wp_upgrader, $hook_extra ) { + static $imagify_path; + static $can_reset; + + if ( ! isset( $hook_extra['action'], $hook_extra['type'], $hook_extra['plugins'] ) ) { + return; + } + + if ( 'update' !== $hook_extra['action'] || 'plugin' !== $hook_extra['type'] || ! is_array( $hook_extra['plugins'] ) ) { + return; + } + + $plugins = array_flip( $hook_extra['plugins'] ); + + if ( ! isset( $imagify_path ) ) { + $imagify_path = plugin_basename( IMAGIFY_FILE ); + } + + if ( ! isset( $plugins[ $imagify_path ] ) ) { + return; + } + + if ( ! isset( $can_reset ) ) { + $can_reset = true; + + if ( ! function_exists( 'opcache_reset' ) ) { + $can_reset = false; + } + + if ( ! empty( ini_get( 'opcache.restrict_api' ) ) && strpos( __FILE__, ini_get( 'opcache.restrict_api' ) ) !== 0 ) { + $can_reset = false; + } + } + + if ( $can_reset ) { + opcache_reset(); + } +} diff --git a/inc/classes/class-imagify-admin-ajax-post.php b/inc/classes/class-imagify-admin-ajax-post.php index f8e881ae4..eb1f75a9f 100755 --- a/inc/classes/class-imagify-admin-ajax-post.php +++ b/inc/classes/class-imagify-admin-ajax-post.php @@ -688,7 +688,9 @@ public function imagify_get_unoptimized_attachment_ids_callback() { $mime_types = Imagify_DB::get_mime_types(); $statuses = Imagify_DB::get_post_statuses(); $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause(); - $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause(); + $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause( array( + 'prepared' => true, + ) ); $ids = $wpdb->get_col( $wpdb->prepare( // WPCS: unprepared SQL ok. " SELECT p.ID diff --git a/inc/classes/class-imagify-db.php b/inc/classes/class-imagify-db.php index ad1680a5c..8ad3f9762 100644 --- a/inc/classes/class-imagify-db.php +++ b/inc/classes/class-imagify-db.php @@ -194,37 +194,55 @@ public static function get_required_wp_metadata_join_clause( $id_field = 'p.ID', * It returns an empty string if the database has no attachments without the required metadada. * * @since 1.7 + * @since 1.7.1.2 Use a single $arg parameter instead of 3. New $prepared parameter. * @access public * @author Grégory Viguier * - * @param string $aliases The aliases to use for the meta values. - * @param bool $matching Set to false to get a query to fetch invalid metas. - * @param bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway. - * @return string A query. + * @param array $args { + * Optional. An array of arguments. + * + * string $aliases The aliases to use for the meta values. + * bool $matching Set to false to get a query to fetch invalid metas. + * bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway. + * bool $prepared Set to true if the query will be prepared with using $wpdb->prepare(). + * }. + * @return string A query. */ - public static function get_required_wp_metadata_where_clause( $aliases = array(), $matching = true, $test = true ) { + public static function get_required_wp_metadata_where_clause( $args = array() ) { static $query = array(); + $args = imagify_merge_intersect( $args, array( + 'aliases' => array(), + 'matching' => true, + 'test' => true, + 'prepared' => false, + ) ); + + list( $aliases, $matching, $test, $prepared ) = array_values( $args ); + if ( $test && ! imagify_has_attachments_without_required_metadata() ) { return ''; } - if ( is_string( $aliases ) ) { + if ( $aliases && is_string( $aliases ) ) { $aliases = array( '_wp_attached_file' => $aliases, ); + } elseif ( ! is_array( $aliases ) ) { + $aliases = array(); } $aliases = imagify_merge_intersect( $aliases, self::get_required_wp_metadata_aliases() ); $key = implode( '|', $aliases ) . '|' . (int) $matching; if ( isset( $query[ $key ] ) ) { - return $query[ $key ]; + return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ]; } + unset( $args['prepared'] ); $alias_1 = $aliases['_wp_attached_file']; $alias_2 = $aliases['_wp_attachment_metadata']; - $extensions = self::get_extensions_where_clause( $alias_1, $matching, $test ); + $extensions = self::get_extensions_where_clause( $args ); if ( $matching ) { $query[ $key ] = "AND $alias_1.meta_value NOT LIKE '%://%' AND $alias_1.meta_value NOT LIKE '_:\\\\\%' $extensions"; @@ -232,7 +250,7 @@ public static function get_required_wp_metadata_where_clause( $aliases = array() $query[ $key ] = "AND ( $alias_2.meta_value IS NULL OR $alias_1.meta_value IS NULL OR $alias_1.meta_value LIKE '%://%' OR $alias_1.meta_value LIKE '_:\\\\\%' $extensions )"; } - return $query[ $key ]; + return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ]; } /** @@ -240,18 +258,33 @@ public static function get_required_wp_metadata_where_clause( $aliases = array() * It returns an empty string if the database has no attachments without the required metadada. * * @since 1.7 + * @since 1.7.1.2 Use a single $arg parameter instead of 3. New $prepared parameter. * @access public * @author Grégory Viguier * - * @param string $alias The alias to use for the meta value. - * @param bool $matching Set to false to get a query to fetch metas NOT matching the file extensions. - * @param bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway. - * @return string A query. + * @param array $args { + * Optional. An array of arguments. + * + * string $alias The alias to use for the meta value. + * bool $matching Set to false to get a query to fetch metas NOT matching the file extensions. + * bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway. + * bool $prepared Set to true if the query will be prepared with using $wpdb->prepare(). + * }. + * @return string A query. */ - public static function get_extensions_where_clause( $alias = false, $matching = true, $test = true ) { + public static function get_extensions_where_clause( $args = false ) { static $extensions; static $query = array(); + $args = imagify_merge_intersect( $args, array( + 'alias' => array(), + 'matching' => true, + 'test' => true, + 'prepared' => false, + ) ); + + list( $alias, $matching, $test, $prepared ) = array_values( $args ); + if ( $test && ! imagify_has_attachments_without_required_metadata() ) { return ''; } @@ -270,7 +303,7 @@ public static function get_extensions_where_clause( $alias = false, $matching = $key = $alias . '|' . (int) $matching; if ( isset( $query[ $key ] ) ) { - return $query[ $key ]; + return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ]; } if ( $matching ) { @@ -279,7 +312,7 @@ public static function get_extensions_where_clause( $alias = false, $matching = $query[ $key ] = "OR ( LOWER( $alias.meta_value ) NOT LIKE '%." . implode( "' AND LOWER( $alias.meta_value ) NOT LIKE '%.", $extensions ) . "' )"; } - return $query[ $key ]; + return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ]; } /** diff --git a/inc/classes/class-imagify.php b/inc/classes/class-imagify.php index f912ac224..140f95b8c 100644 --- a/inc/classes/class-imagify.php +++ b/inc/classes/class-imagify.php @@ -11,7 +11,7 @@ class Imagify extends Imagify_Deprecated { * * @var string */ - const VERSION = '1.1.1'; + const VERSION = '1.1.2'; /** * The Imagify API endpoint. * @@ -63,6 +63,11 @@ class Imagify extends Imagify_Deprecated { * The constructor. */ protected function __construct() { + if ( ! class_exists( 'Imagify_Filesystem' ) ) { + // Dirty patch used when updating from 1.7. + include_once IMAGIFY_CLASSES_PATH . 'class-imagify-filesystem.php'; + } + $this->api_key = get_imagify_option( 'api_key' ); $this->filesystem = Imagify_Filesystem::get_instance(); @@ -98,13 +103,21 @@ public static function get_instance() { */ public function get_user() { static $user; + global $wp_current_filter; + + if ( isset( $user ) ) { + return $user; + } - if ( ! isset( $user ) ) { + if ( ! in_array( 'upgrader_post_install', (array) $wp_current_filter, true ) ) { $this->headers = $this->all_headers; $user = $this->http_call( 'users/me/', array( 'timeout' => 10, ) ); + } else { + // Dirty patch used when updating from 1.7. + $user = new WP_Error(); } return $user; diff --git a/inc/functions/attachments.php b/inc/functions/attachments.php index 7a253b476..d98f3888d 100755 --- a/inc/functions/attachments.php +++ b/inc/functions/attachments.php @@ -124,7 +124,10 @@ function imagify_has_attachments_without_required_metadata() { $mime_types = Imagify_DB::get_mime_types(); $statuses = Imagify_DB::get_post_statuses(); $nodata_join = Imagify_DB::get_required_wp_metadata_join_clause( 'p.ID', false, false ); - $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause( array(), false, false ); + $nodata_where = Imagify_DB::get_required_wp_metadata_where_clause( array( + 'matching' => false, + 'test' => false, + ) ); $has = (bool) $wpdb->get_var( // WPCS: unprepared SQL ok. " SELECT p.ID diff --git a/package.json b/package.json index 216934c70..c6cc5882a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "imagify", "description": "Imagify Image Optimizer. Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.", - "version": "1.7.1", + "version": "1.7.1.2", "homepage": "https://wordpress.org/plugins/imagify/", "license": "GPL-2.0", "private": true, diff --git a/readme.txt b/readme.txt index 374879806..27e5a20c1 100755 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: wp_media, GregLone Tags: compress image, images, performance, optimization, photos, upload, resize, gif, png, jpg, reduce image size, retina Requires at least: 3.7.0 Tested up to: 4.9.5 -Stable tag: 1.7.1 +Stable tag: 1.7.1.2 Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth. @@ -138,6 +138,11 @@ When the plugin is disabled, your existing images remain optimized. Backups of t 4. Other Media Page == Changelog == += 1.7.1.2 - 2018/04/12 = +* Improvement: reset OPcache after Imagify being updated. +* Bug Fix: a fatal error upon Imagify update. +* Bug Fix: a case where the bulk optimizer wrongly says that all images are already optimized. + = 1.7.1 - 2018/04/10 = * New: compatibility with Regenerate Thumbnails (v3) plugin. * Improvement: better performance of the bulk optimization on sites with huge media library. This is done by not updating the statistics display periodically, but only when the job is done. diff --git a/uninstall.php b/uninstall.php index 7589b90c8..83c8af625 100755 --- a/uninstall.php +++ b/uninstall.php @@ -18,6 +18,7 @@ // Delete all transients. delete_site_transient( 'imagify_check_licence_1' ); delete_site_transient( 'imagify_user' ); +delete_site_transient( 'imagify_themes_plugins_to_sync' ); delete_transient( 'imagify_bulk_optimization_level' ); delete_transient( 'imagify_bulk_optimization_infos' ); delete_transient( 'imagify_large_library' );