Plugins
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Plugins.
|
||||
*/
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/amazon-s3-and-cloudfront/amazon-s3-and-cloudfront.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/amp/amp.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/enable-media-replace/enable-media-replace.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/formidable-pro/formidable-pro.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/nextgen-gallery.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/regenerate-thumbnails/regenerate-thumbnails.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/screets-lc.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/wp-real-media-library.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/wp-cloudflare-super-page-cache.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/wp-rocket/wp-rocket.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/yoast-seo.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/WooCommerce/class-woocommerce.php';
|
||||
|
||||
/**
|
||||
* Hosting.
|
||||
*/
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/hosting/flywheel.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/hosting/pressable.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/hosting/siteground.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/hosting/wordpress-com.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/hosting/wpengine.php';
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\WooCommerce;
|
||||
|
||||
/**
|
||||
* Compatibility for WooCommerce.
|
||||
*
|
||||
* @since 1.10.0
|
||||
*/
|
||||
class WooCommerce {
|
||||
/**
|
||||
* Initialize compatibility functionality.
|
||||
*
|
||||
* @since 1.10.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init() {
|
||||
add_action( 'woocommerce_single_product_summary', [ $this, 'variable_products_nextgen_compat' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Variable Products Next-gen images Compatibility.
|
||||
*
|
||||
* @since 1.10.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function variable_products_nextgen_compat() {
|
||||
global $product;
|
||||
|
||||
if ( ! isset( $product ) || ! $product->is_type( 'variable' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'imagify_picture_attributes', [ $this, 'remove_wp_post_image_class' ], 10, 2 );
|
||||
add_filter(
|
||||
'imagify_picture_source_attributes',
|
||||
[ $this, 'maybe_add_wp_post_image_class_on_picture_internal_tags' ],
|
||||
10,
|
||||
2
|
||||
);
|
||||
add_filter(
|
||||
'imagify_picture_img_attributes',
|
||||
[ $this, 'maybe_add_wp_post_image_class_on_picture_internal_tags' ],
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove wp-post-image class from picture tags.
|
||||
*
|
||||
* @since 1.10.0
|
||||
*
|
||||
* @param array $attributes The picture tag attributes.
|
||||
*
|
||||
* @return array The picture tage attributes with modified or removed 'class'.
|
||||
*/
|
||||
public function remove_wp_post_image_class( $attributes ) {
|
||||
if ( isset( $attributes['class'] ) ) {
|
||||
$attributes['class'] = str_replace( 'wp-post-image', '', $attributes['class'] );
|
||||
}
|
||||
|
||||
if ( empty( $attributes['class'] ) ) {
|
||||
unset( $attributes['class'] );
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add wp-post-image class to source and image tags internal to a picture tag.
|
||||
*
|
||||
* @since 1.10.0
|
||||
*
|
||||
* @param array $attributes The source or img tag attributes.
|
||||
* @param array $image The original image tag data.
|
||||
*
|
||||
* @return array Source or image tag attributes with modified 'class'.
|
||||
*/
|
||||
public function maybe_add_wp_post_image_class_on_picture_internal_tags( $attributes, $image ) {
|
||||
if (
|
||||
! empty( $image['attributes']['class'] )
|
||||
&& strpos( $image['attributes']['class'], 'wp-post-image' ) !== false
|
||||
) {
|
||||
$attributes['class'] = isset( $attributes['class'] )
|
||||
? $attributes['class'] . ' wp-post-image'
|
||||
: 'wp-post-image';
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
|
||||
( new WooCommerce() )->init();
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Tell if WP Offload S3 compatibility is loaded.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function imagify_load_as3cf_compat() {
|
||||
if ( function_exists( 'as3cf_init' ) ) {
|
||||
// WP Offload S3 Lite.
|
||||
$version = ! empty( $GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] ) ? $GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] : false;
|
||||
|
||||
if ( ! $version ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'amazon_web_services_init' ) && version_compare( $version, '1.3' ) < 0 ) {
|
||||
// Old version, plugin Amazon Web Services is required.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( version_compare( $version, '2.3' ) >= 0 ) {
|
||||
// A new version that removes a punlic method.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( function_exists( 'as3cf_pro_init' ) ) {
|
||||
// WP Offload S3 Pro.
|
||||
$version = ! empty( $GLOBALS['aws_meta']['amazon-s3-and-cloudfront-pro']['version'] ) ? $GLOBALS['aws_meta']['amazon-s3-and-cloudfront-pro']['version'] : false;
|
||||
|
||||
if ( ! $version ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'amazon_web_services_init' ) && version_compare( $version, '1.6' ) < 0 ) {
|
||||
// Old version, plugin Amazon Web Services is required.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( version_compare( $version, '2.3' ) >= 0 ) {
|
||||
// A new version that removes a punlic method.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( imagify_load_as3cf_compat() ) :
|
||||
|
||||
class_alias( '\\Imagify\\ThirdParty\\AS3CF\\Main', '\\Imagify_AS3CF' );
|
||||
|
||||
add_action( 'imagify_loaded', [ \Imagify\ThirdParty\AS3CF\Main::get_instance(), 'init' ], 1 );
|
||||
|
||||
endif;
|
||||
@@ -1,513 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\AS3CF\CDN\WP;
|
||||
|
||||
use Imagify\CDN\PushCDNInterface;
|
||||
use Imagify\Context\ContextInterface;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* AS3 CDN for WP context.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class AS3 implements PushCDNInterface {
|
||||
|
||||
/**
|
||||
* The media ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Filesystem object.
|
||||
*
|
||||
* @var object Imagify_Filesystem
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* Tell if we’re playing in WP 5.3’s garden.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.9.8
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $is_wp53;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $media_id The media ID.
|
||||
*/
|
||||
public function __construct( $media_id ) {
|
||||
$this->id = (int) $media_id;
|
||||
$this->filesystem = \Imagify_Filesystem::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if the CDN is ready (not necessarily reachable).
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_ready() {
|
||||
global $as3cf;
|
||||
static $is;
|
||||
|
||||
if ( ! isset( $is ) ) {
|
||||
$is = $as3cf && $as3cf->is_plugin_setup();
|
||||
}
|
||||
|
||||
return $is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if the media is on the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function media_is_on_cdn() {
|
||||
return (bool) $this->get_cdn_info();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files from the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $file_paths A list of file paths.
|
||||
* @return bool|\WP_Error True on success. A \WP_error object on failure.
|
||||
*/
|
||||
public function get_files_from_cdn( $file_paths ) {
|
||||
global $as3cf;
|
||||
|
||||
if ( ! $this->is_ready() ) {
|
||||
return new \WP_Error( 'not_ready', __( 'CDN is not set up.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$cdn_info = $this->get_cdn_info();
|
||||
|
||||
if ( ! $cdn_info ) {
|
||||
// The media is not on the CDN.
|
||||
return new \WP_Error( 'not_on_cdn', __( 'This media could not be found on the CDN.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$directory = $this->filesystem->dir_path( $cdn_info['key'] );
|
||||
$directory = $this->filesystem->is_root( $directory ) ? '' : $directory;
|
||||
$new_method = method_exists( $as3cf->plugin_compat, 'copy_s3_file_to_server' );
|
||||
$errors = [];
|
||||
|
||||
foreach ( $file_paths as $file_path ) {
|
||||
$cdn_info['key'] = $directory . $this->filesystem->file_name( $file_path );
|
||||
|
||||
// Retrieve file from the CDN.
|
||||
if ( $new_method ) {
|
||||
$as3cf->plugin_compat->copy_s3_file_to_server( $cdn_info, $file_path );
|
||||
} else {
|
||||
$as3cf->plugin_compat->copy_provider_file_to_server( $cdn_info, $file_path );
|
||||
}
|
||||
|
||||
if ( ! $this->filesystem->exists( $file_path ) ) {
|
||||
$errors[] = $file_path;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $errors ) {
|
||||
$nbr_errors = count( $errors );
|
||||
$errors_txt = array_map( [ $this->filesystem, 'make_path_relative' ], $errors );
|
||||
$errors_txt = wp_sprintf_l( '%l', $errors_txt );
|
||||
|
||||
return new \WP_Error(
|
||||
'not_retrieved',
|
||||
sprintf(
|
||||
/* translators: %s is a list of file paths. */
|
||||
_n( 'The following file could not be retrieved from the CDN: %s.', 'The following files could not be retrieved from the CDN: %s.', $nbr_errors, 'imagify' ),
|
||||
$errors_txt
|
||||
),
|
||||
$errors
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove files from the CDN.
|
||||
* Don't use this to empty a folder.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $file_paths A list of file paths. Those paths are not necessary absolute, and can be also file names.
|
||||
* @return bool|\WP_Error True on success. A \WP_error object on failure.
|
||||
*/
|
||||
public function remove_files_from_cdn( $file_paths ) {
|
||||
global $as3cf;
|
||||
|
||||
if ( ! $this->is_ready() ) {
|
||||
return new \WP_Error( 'not_ready', __( 'CDN is not set up.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$cdn_info = $this->get_cdn_info();
|
||||
|
||||
if ( ! $cdn_info ) {
|
||||
// The media is not on the CDN.
|
||||
return new \WP_Error( 'not_on_cdn', __( 'This media could not be found on the CDN.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$directory = $this->filesystem->dir_path( $cdn_info['key'] );
|
||||
$directory = $this->filesystem->is_root( $directory ) ? '' : $directory;
|
||||
|
||||
if ( method_exists( $as3cf, 'get_s3object_region' ) ) {
|
||||
$region = $as3cf->get_s3object_region( $cdn_info );
|
||||
} else {
|
||||
$region = $as3cf->get_provider_object_region( $cdn_info );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $region ) ) {
|
||||
$region = '';
|
||||
}
|
||||
|
||||
$to_remove = [];
|
||||
|
||||
foreach ( $file_paths as $file_path ) {
|
||||
$to_remove[] = [
|
||||
'Key' => $directory . $this->filesystem->file_name( $file_path ),
|
||||
];
|
||||
}
|
||||
|
||||
if ( method_exists( $as3cf, 'delete_s3_objects' ) ) {
|
||||
$result = $as3cf->delete_s3_objects( $region, $cdn_info['bucket'], $to_remove, false, false, false );
|
||||
} else {
|
||||
$result = $as3cf->delete_objects( $region, $cdn_info['bucket'], $to_remove, false, false, false );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return new \WP_Error( 'deletion_failed', __( 'File(s) could not be removed from the CDN.', 'imagify' ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all files from a media to the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $is_new_upload Tell if the current media is a new upload. If not, it means it's a media being regenerated, restored, etc.
|
||||
* @return bool|\WP_Error True/False if sent or not. A \WP_error object on failure.
|
||||
*/
|
||||
public function send_to_cdn( $is_new_upload ) {
|
||||
global $as3cf;
|
||||
|
||||
if ( ! $this->is_ready() ) {
|
||||
return new \WP_Error( 'not_ready', __( 'CDN is not set up.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( ! $this->can_send_to_cdn( $is_new_upload ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the missing files from the CDN: we must send all of them at once, even those that have not been modified.
|
||||
$file_paths = \AS3CF_Utils::get_attachment_file_paths( $this->id, false );
|
||||
|
||||
if ( $file_paths ) {
|
||||
foreach ( $file_paths as $size => $file_path ) {
|
||||
if ( $this->filesystem->exists( $file_path ) ) {
|
||||
// Keep only the files that don't exist.
|
||||
unset( $file_paths[ $size ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $file_paths ) {
|
||||
$result = $this->get_files_from_cdn( $file_paths );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
$remove_local_files = $this->should_delete_files( $is_new_upload );
|
||||
|
||||
if ( ! $is_new_upload ) {
|
||||
if ( $remove_local_files ) {
|
||||
// Force files deletion when not a new media.
|
||||
add_filter( 'as3cf_get_setting', [ $this, 'force_local_file_removal_setting' ], 100, 2 );
|
||||
add_filter( 'as3cf_setting_remove-local-file', 'imagify_return_true', 100 );
|
||||
} else {
|
||||
// Force to keep the files when not a new media.
|
||||
add_filter( 'as3cf_get_setting', [ $this, 'force_local_file_keep_setting' ], 100, 2 );
|
||||
add_filter( 'as3cf_setting_remove-local-file', 'imagify_return_false', 100 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( method_exists( $as3cf, 'upload_attachment_to_s3' ) ) {
|
||||
$result = $as3cf->upload_attachment_to_s3( $this->id, null, null, false, $remove_local_files );
|
||||
} else {
|
||||
$result = $as3cf->upload_attachment( $this->id, null, null, false, $remove_local_files );
|
||||
}
|
||||
|
||||
if ( ! $is_new_upload ) {
|
||||
if ( $remove_local_files ) {
|
||||
remove_filter( 'as3cf_get_setting', [ $this, 'force_local_file_removal_setting' ], 100 );
|
||||
remove_filter( 'as3cf_setting_remove-local-file', 'imagify_return_true', 100 );
|
||||
} else {
|
||||
remove_filter( 'as3cf_get_setting', [ $this, 'force_local_file_keep_setting' ], 100 );
|
||||
remove_filter( 'as3cf_setting_remove-local-file', 'imagify_return_false', 100 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file URL.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $file_name Name of the file. Leave empty for the full size file.
|
||||
* @return string URL to the file.
|
||||
*/
|
||||
public function get_file_url( $file_name = false ) {
|
||||
$file_url = wp_get_attachment_url( $this->id );
|
||||
|
||||
if ( $file_name ) {
|
||||
// It's not the full size.
|
||||
$file_url = $this->filesystem->dir_path( $file_url ) . $file_name;
|
||||
}
|
||||
|
||||
return $file_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a file path.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $file_name Name of the file. Leave empty for the full size file. Use 'original' to get the path to the original file.
|
||||
* @return string Path to the file.
|
||||
*/
|
||||
public function get_file_path( $file_name = false ) {
|
||||
if ( ! $file_name ) {
|
||||
// Full size.
|
||||
return get_attached_file( $this->id, true );
|
||||
}
|
||||
|
||||
if ( 'original' === $file_name ) {
|
||||
// Original file.
|
||||
if ( $this->is_wp_53() ) {
|
||||
// `wp_get_original_image_path()` may return false.
|
||||
$file_path = wp_get_original_image_path( $this->id );
|
||||
} else {
|
||||
$file_path = false;
|
||||
}
|
||||
|
||||
if ( ! $file_path ) {
|
||||
$file_path = get_attached_file( $this->id, true );
|
||||
}
|
||||
|
||||
return $file_path;
|
||||
}
|
||||
|
||||
// Thumbnail.
|
||||
$file_path = get_attached_file( $this->id, true );
|
||||
$file_path = $this->filesystem->dir_path( $file_path ) . $file_name;
|
||||
|
||||
return $file_path;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** INTERNAL TOOLS ========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Filter the CDN setting 'remove-local-file': this is used to force deletion when the media is not a new one.
|
||||
* Caution to not use $this->should_delete_files() when this filter is used!
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $setting The setting value.
|
||||
* @param string $key The setting name.
|
||||
* @return bool
|
||||
*/
|
||||
public function force_local_file_removal_setting( $setting, $key ) {
|
||||
if ( 'remove-local-file' === $key ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the CDN setting 'remove-local-file': this is used to force not-deletion when the media is not a new one.
|
||||
* Caution to not use $this->should_delete_files() when this filter is used!
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $setting The setting value.
|
||||
* @param string $key The setting name.
|
||||
* @return bool
|
||||
*/
|
||||
public function force_local_file_keep_setting( $setting, $key ) {
|
||||
if ( 'remove-local-file' === $key ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if a media is stored on the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array|bool The CDN info on success. False if the media is not on the CDN.
|
||||
*/
|
||||
protected function get_cdn_info() {
|
||||
global $as3cf;
|
||||
|
||||
if ( ! $as3cf ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( method_exists( $as3cf, 'get_attachment_s3_info' ) ) {
|
||||
return $as3cf->get_attachment_s3_info( $this->id );
|
||||
}
|
||||
|
||||
return $as3cf->get_attachment_provider_info( $this->id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if a media can (and should) be sent to the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $is_new_upload Tell if the current media is a new upload. If not, it means it's a media being regenerated, restored, etc.
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_send_to_cdn( $is_new_upload ) {
|
||||
global $as3cf;
|
||||
static $can = [];
|
||||
static $cdn_setting;
|
||||
|
||||
if ( isset( $can[ $this->id ] ) ) {
|
||||
return $can[ $this->id ];
|
||||
}
|
||||
|
||||
if ( ! $this->is_ready() ) {
|
||||
$can[ $this->id ] = false;
|
||||
return $can[ $this->id ];
|
||||
}
|
||||
|
||||
if ( ! isset( $cdn_setting ) ) {
|
||||
$cdn_setting = $as3cf && $as3cf->get_setting( 'copy-to-s3' );
|
||||
}
|
||||
|
||||
// The CDN is set up: test if the media is on it.
|
||||
$can[ $this->id ] = $this->media_is_on_cdn();
|
||||
|
||||
if ( $can[ $this->id ] && $is_new_upload ) {
|
||||
// Use the CDN setting to tell if we're allowed to send the files (should be true since it's a new upload and it's already there).
|
||||
$can[ $this->id ] = $cdn_setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if a media can (and should) be sent to the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $can True if the media can be sent. False otherwize.
|
||||
* @param PushCDNInterface $cdn The CDN instance.
|
||||
* @param bool $cdn_setting CDN setting that tells if a new media can be sent to the CDN.
|
||||
* @param bool $is_new_upload Tell if the current media is a new upload. If not, it means it's a media being regenerated, restored, etc.
|
||||
*/
|
||||
$can[ $this->id ] = (bool) apply_filters( 'imagify_can_send_to_cdn', $can[ $this->id ], $this, $cdn_setting, $is_new_upload );
|
||||
|
||||
return $can[ $this->id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if the files should be deleted after optimization.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $is_new_upload Tell if the current media is a new upload. If not, it means it's a media being regenerated, restored, etc.
|
||||
* @return bool
|
||||
*/
|
||||
protected function should_delete_files( $is_new_upload ) {
|
||||
global $as3cf;
|
||||
|
||||
if ( $is_new_upload ) {
|
||||
return (bool) $as3cf->get_setting( 'remove-local-file' );
|
||||
}
|
||||
|
||||
// If the attachment has a 'filesize' metadata, that means the local files are meant to be deleted.
|
||||
return (bool) get_post_meta( $this->id, 'wpos3_filesize_total', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if we’re playing in WP 5.3’s garden.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_wp_53() {
|
||||
if ( isset( $this->is_wp53 ) ) {
|
||||
return $this->is_wp53;
|
||||
}
|
||||
|
||||
$this->is_wp53 = function_exists( 'wp_get_original_image_path' );
|
||||
|
||||
return $this->is_wp53;
|
||||
}
|
||||
}
|
||||
@@ -1,631 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\AS3CF;
|
||||
|
||||
use \Imagify\Optimization\File;
|
||||
use \Imagify\ThirdParty\AS3CF\CDN\WP\AS3 as CDN;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Imagify WP Offload S3 class.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class Main extends \Imagify_AS3CF_Deprecated {
|
||||
use \Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* AS3CF settings.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $s3_settings;
|
||||
|
||||
/**
|
||||
* Filesystem object.
|
||||
*
|
||||
* @var \Imagify_Filesystem
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* The class constructor.
|
||||
*
|
||||
* @since 1.6.6
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected function __construct() {
|
||||
$this->filesystem = \Imagify_Filesystem::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the hooks.
|
||||
*
|
||||
* @since 1.6.6
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function init() {
|
||||
static $done = false;
|
||||
|
||||
if ( $done ) {
|
||||
return;
|
||||
}
|
||||
$done = true;
|
||||
|
||||
/**
|
||||
* WebP images to display with a <picture> tag.
|
||||
*/
|
||||
add_action( 'as3cf_init', [ $this, 'store_s3_settings' ] );
|
||||
add_filter( 'imagify_webp_picture_process_image', [ $this, 'picture_tag_webp_image' ] );
|
||||
|
||||
/**
|
||||
* Register CDN.
|
||||
*/
|
||||
add_filter( 'imagify_cdn', [ $this, 'register_cdn' ], 8, 3 );
|
||||
|
||||
/**
|
||||
* Optimization process.
|
||||
*/
|
||||
add_filter( 'imagify_before_optimize_size', [ $this, 'maybe_copy_file_from_cdn_before_optimization' ], 8, 6 );
|
||||
add_action( 'imagify_after_optimize', [ $this, 'maybe_send_media_to_cdn_after_optimization' ], 8, 2 );
|
||||
|
||||
/**
|
||||
* Restoration process.
|
||||
*/
|
||||
add_action( 'imagify_after_restore_media', [ $this, 'maybe_send_media_to_cdn_after_restore' ], 8, 4 );
|
||||
|
||||
/**
|
||||
* WebP support.
|
||||
*/
|
||||
add_filter( 'as3cf_attachment_file_paths', [ $this, 'add_webp_images_to_attachment' ], 8, 3 );
|
||||
add_filter( 'mime_types', [ $this, 'add_webp_support' ] );
|
||||
|
||||
/**
|
||||
* Redirections.
|
||||
*/
|
||||
add_filter( 'imagify_redirect_to', [ $this, 'redirect_referrer' ] );
|
||||
|
||||
/**
|
||||
* Stats.
|
||||
*/
|
||||
add_filter( 'imagify_total_attachment_filesize', [ $this, 'add_stats_for_s3_files' ], 8, 4 );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** OPTIMIZATION PROCESS ==================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* On AS3CF init, store its settings.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param \Amazon_S3_And_CloudFront $as3cf AS3CF’s main instance.
|
||||
*/
|
||||
public function store_s3_settings( $as3cf ) {
|
||||
if ( method_exists( $as3cf, 'get_settings' ) ) {
|
||||
$this->store_s3_settings = (array) $as3cf->get_settings();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WebP images to display with a <picture> tag.
|
||||
*
|
||||
* @since 1.9
|
||||
* @see \Imagify\Picture\Display->process_image()
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $data An array of data for this image.
|
||||
* @return array
|
||||
*/
|
||||
public function picture_tag_webp_image( $data ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! empty( $data['src']['webp_path'] ) ) {
|
||||
// The file is local.
|
||||
return $data;
|
||||
}
|
||||
|
||||
$match = $this->is_s3_url( $data['src']['url'] );
|
||||
|
||||
if ( ! $match ) {
|
||||
// The file is not on S3.
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Get the image ID.
|
||||
$post_id = (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s",
|
||||
// We use only year/month + filename, we should not have any subdir between them for the main file.
|
||||
$match['year_month'] . $match['filename']
|
||||
)
|
||||
);
|
||||
|
||||
if ( $post_id <= 0 ) {
|
||||
// Not in the database.
|
||||
return $data;
|
||||
}
|
||||
|
||||
$s3_info = get_post_meta( $post_id, 'amazonS3_info', true );
|
||||
$imagify_data = get_post_meta( $post_id, '_imagify_data', true );
|
||||
|
||||
if ( ! $s3_info || ! $imagify_data ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$webp_size_suffix = constant( imagify_get_optimization_process_class_name( 'wp' ) . '::WEBP_SUFFIX' );
|
||||
$webp_size_name = 'full' . $webp_size_suffix;
|
||||
|
||||
if ( ! empty( $imagify_data['sizes'][ $webp_size_name ]['success'] ) ) {
|
||||
// We have a WebP image.
|
||||
$data['src']['webp_exists'] = true;
|
||||
}
|
||||
|
||||
if ( empty( $data['srcset'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$meta_data = get_post_meta( $post_id, '_wp_attachment_metadata', true );
|
||||
|
||||
if ( empty( $meta_data['sizes'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Ease the search for corresponding file name.
|
||||
$size_files = [];
|
||||
|
||||
foreach ( $meta_data['sizes'] as $size_name => $size_data ) {
|
||||
$size_files[ $size_data['file'] ] = $size_name;
|
||||
}
|
||||
|
||||
// Look for a corresponding size name.
|
||||
foreach ( $data['srcset'] as $i => $srcset_data ) {
|
||||
if ( empty( $srcset_data['webp_url'] ) ) {
|
||||
// Not a supported image format.
|
||||
continue;
|
||||
}
|
||||
if ( ! empty( $srcset_data['webp_path'] ) ) {
|
||||
// The file is local.
|
||||
continue;
|
||||
}
|
||||
|
||||
$match = $this->is_s3_url( $srcset_data['url'] );
|
||||
|
||||
if ( ! $match ) {
|
||||
// Not on S3.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try with no subdirs.
|
||||
$filename = $match['filename'];
|
||||
|
||||
if ( isset( $size_files[ $filename ] ) ) {
|
||||
$size_name = $size_files[ $filename ];
|
||||
} else {
|
||||
// Try with subdirs.
|
||||
$filename = $match['subdirs'] . $match['filename'];
|
||||
|
||||
if ( isset( $size_files[ $filename ] ) ) {
|
||||
$size_name = $size_files[ $filename ];
|
||||
} elseif ( preg_match( '@/\d+/$@', $match['subdirs'] ) ) {
|
||||
// Last try: the subdirs may contain the S3 versioning. If not the case, we can still build a pyramid with this code.
|
||||
$filename = preg_replace( '@/\d+/$@', '/', $match['subdirs'] ) . $match['filename'];
|
||||
|
||||
if ( isset( $size_files[ $filename ] ) ) {
|
||||
$size_name = $size_files[ $filename ];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$webp_size_name = $size_name . $webp_size_suffix;
|
||||
|
||||
if ( ! empty( $imagify_data['sizes'][ $webp_size_name ]['success'] ) ) {
|
||||
// We have a WebP image.
|
||||
$data['srcset'][ $i ]['webp_exists'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The CDN to use for this media.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool|PushCDNInterface $cdn A PushCDNInterface instance. False if no CDN is used.
|
||||
* @param int $media_id The media ID.
|
||||
* @param ContextInterface $context The context object.
|
||||
*/
|
||||
public function register_cdn( $cdn, $media_id, $context ) {
|
||||
if ( 'wp' !== $context->get_name() ) {
|
||||
return $cdn;
|
||||
}
|
||||
if ( $cdn instanceof PushCDNInterface ) {
|
||||
return $cdn;
|
||||
}
|
||||
|
||||
return new CDN( $media_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Before performing a file optimization, download the file from the CDN if it is missing.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param null|\WP_Error $response Null by default.
|
||||
* @param ProcessInterface $process The optimization process instance.
|
||||
* @param File $file The file instance. If $webp is true, $file references the non-webp file.
|
||||
* @param string $thumb_size The media size.
|
||||
* @param int $optimization_level The optimization level (0=normal, 1=aggressive, 2=ultra).
|
||||
* @param bool $webp The image will be converted to WebP.
|
||||
* @return null|\WP_Error Null. A \WP_Error object on error.
|
||||
*/
|
||||
public function maybe_copy_file_from_cdn_before_optimization( $response, $process, $file, $thumb_size, $optimization_level, $webp ) {
|
||||
if ( is_wp_error( $response ) || 'wp' !== $process->get_media()->get_context() ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$media = $process->get_media();
|
||||
$cdn = $media->get_cdn();
|
||||
|
||||
if ( ! $cdn instanceof CDN ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ( $this->filesystem->exists( $file->get_path() ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Get files from the CDN.
|
||||
$result = $cdn->get_files_from_cdn( [ $file->get_path() ] );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* After performing a media optimization:
|
||||
* - Save some data,
|
||||
* - Upload the files to the CDN,
|
||||
* - Maybe delete them from the server.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param ProcessInterface $process The optimization process.
|
||||
* @param array $item The item being processed.
|
||||
*/
|
||||
public function maybe_send_media_to_cdn_after_optimization( $process, $item ) {
|
||||
if ( 'wp' !== $process->get_media()->get_context() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$media = $process->get_media();
|
||||
$cdn = $media->get_cdn();
|
||||
|
||||
if ( ! $cdn instanceof CDN ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cdn->send_to_cdn( ! empty( $item['data']['is_new_upload'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* After restoring a media:
|
||||
* - Save some data,
|
||||
* - Upload the files to the CDN,
|
||||
* - Maybe delete WebP files from the CDN.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param ProcessInterface $process The optimization process.
|
||||
* @param bool|WP_Error $response The result of the operation: true on success, a WP_Error object on failure.
|
||||
* @param array $files The list of files, before restoring them.
|
||||
* @param array $data The optimization data, before deleting it.
|
||||
*/
|
||||
public function maybe_send_media_to_cdn_after_restore( $process, $response, $files, $data ) {
|
||||
if ( 'wp' !== $process->get_media()->get_context() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$media = $process->get_media();
|
||||
$cdn = $media->get_cdn();
|
||||
|
||||
if ( ! $cdn instanceof CDN ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$error_code = $response->get_error_code();
|
||||
|
||||
if ( 'copy_failed' === $error_code ) {
|
||||
// No files have been restored.
|
||||
return;
|
||||
}
|
||||
|
||||
// No thumbnails left?
|
||||
}
|
||||
|
||||
$cdn->send_to_cdn( false );
|
||||
|
||||
// Remove WebP files from CDN.
|
||||
$webp_files = [];
|
||||
|
||||
if ( $files ) {
|
||||
// Get the paths to the WebP files.
|
||||
foreach ( $files as $size_name => $file ) {
|
||||
$webp_size_name = $size_name . $process::WEBP_SUFFIX;
|
||||
|
||||
if ( empty( $data['sizes'][ $webp_size_name ]['success'] ) ) {
|
||||
// This size has no WebP version.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 0 === strpos( $file['mime-type'], 'image/' ) ) {
|
||||
$webp_file = new File( $file['path'] );
|
||||
|
||||
if ( ! $webp_file->is_webp() ) {
|
||||
$webp_files[] = $webp_file->get_path_to_webp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $webp_files ) {
|
||||
$cdn->remove_files_from_cdn( $webp_files );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** OPTIMIZATION PROCESS ==================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Add the WebP files to the list of files that the CDN must handle.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $paths A list of file paths, keyed by size name. 'file' for the full size. Includes a 'backup' size and a 'thumb' size.
|
||||
* @param int $attachment_id The media ID.
|
||||
* @param array $metadata The attachment meta data.
|
||||
* @return array
|
||||
*/
|
||||
public function add_webp_images_to_attachment( $paths, $attachment_id, $metadata ) {
|
||||
if ( ! $paths ) {
|
||||
// ¯\(°_o)/¯.
|
||||
return $paths;
|
||||
}
|
||||
|
||||
$process = imagify_get_optimization_process( $attachment_id, 'wp' );
|
||||
|
||||
if ( ! $process->is_valid() ) {
|
||||
return $paths;
|
||||
}
|
||||
|
||||
$media = $process->get_media();
|
||||
|
||||
if ( ! $media->is_image() ) {
|
||||
return $paths;
|
||||
}
|
||||
|
||||
// Use the optimization data (the files may not be on the server).
|
||||
$data = $process->get_data()->get_optimization_data();
|
||||
|
||||
if ( empty( $data['sizes'] ) ) {
|
||||
return $paths;
|
||||
}
|
||||
|
||||
foreach ( $paths as $size_name => $file_path ) {
|
||||
if ( 'thumb' === $size_name || 'backup' === $size_name || $process->is_size_next_gen( $size_name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'file' === $size_name ) {
|
||||
$size_name = 'full';
|
||||
}
|
||||
|
||||
$webp_size_name = $size_name . $process::WEBP_SUFFIX;
|
||||
|
||||
if ( empty( $data['sizes'][ $webp_size_name ]['success'] ) ) {
|
||||
// This size has no WebP version.
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = new File( $file_path );
|
||||
|
||||
if ( ! $file->is_webp() ) {
|
||||
$paths[ $webp_size_name ] = $file->get_path_to_webp();
|
||||
}
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add WebP format to the list of allowed mime types.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @see get_allowed_mime_types()
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $mime_types A list of mime types.
|
||||
* @return array
|
||||
*/
|
||||
public function add_webp_support( $mime_types ) {
|
||||
$mime_types['webp'] = 'image/webp';
|
||||
return $mime_types;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** VARIOUS HOOKS =========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* After a non-ajax optimization, remove some unnecessary arguments from the referrer used for the redirection.
|
||||
* Those arguments don't break anything, they're just not relevant and display obsolete admin notices.
|
||||
*
|
||||
* @since 1.6.10
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $redirect The URL to redirect to.
|
||||
* @return string
|
||||
*/
|
||||
public function redirect_referrer( $redirect ) {
|
||||
return remove_query_arg( [ 'as3cfpro-action', 'as3cf_id', 'errors', 'count' ], $redirect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the file sizes and the number of thumbnails for files that are only on S3.
|
||||
*
|
||||
* @since 1.6.7
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $size_and_count False by default.
|
||||
* @param int $image_id The attachment ID.
|
||||
* @param array $files An array of file paths with thumbnail sizes as keys.
|
||||
* @param array $image_ids An array of all attachment IDs.
|
||||
* @return bool|array False by default. Provide an array with the keys 'filesize' (containing the total filesize) and 'thumbnails' (containing the number of thumbnails).
|
||||
*/
|
||||
public function add_stats_for_s3_files( $size_and_count, $image_id, $files, $image_ids ) {
|
||||
static $data;
|
||||
|
||||
if ( is_array( $size_and_count ) ) {
|
||||
return $size_and_count;
|
||||
}
|
||||
|
||||
if ( $this->filesystem->exists( $files['full'] ) ) {
|
||||
// If the full size is on the server, that probably means all files are on the server too.
|
||||
return $size_and_count;
|
||||
}
|
||||
|
||||
if ( ! isset( $data ) ) {
|
||||
$data = \Imagify_DB::get_metas( [
|
||||
// Get the filesizes.
|
||||
's3_filesize' => 'wpos3_filesize_total',
|
||||
], $image_ids );
|
||||
|
||||
$data = array_map( 'absint', $data['s3_filesize'] );
|
||||
}
|
||||
|
||||
if ( empty( $data[ $image_id ] ) ) {
|
||||
// The file is not on S3.
|
||||
return $size_and_count;
|
||||
}
|
||||
|
||||
// We can't take the disallowed sizes into account here.
|
||||
return [
|
||||
'filesize' => (int) $data[ $image_id ],
|
||||
'thumbnails' => count( $files ) - 1,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** TOOLS =================================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Tell if an URL is a S3 one.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $url The URL to test.
|
||||
* @return array|bool {
|
||||
* An array if an S3 URL. False otherwise.
|
||||
*
|
||||
* @type string $key Bucket key. Ex: subdir/wp-content/uploads/2019/02/13142432/foobar-480x510.jpg.
|
||||
* @type string $year_month The uploads year/month folders. Ex: 2019/02/.
|
||||
* @type string $subdirs Sub-directories between year/month folders and the filename.
|
||||
* It can be the S3 versioning folder, any folder added by a plugin, or both.
|
||||
* There is no way to know which one it is. Ex: foo/13142432/.
|
||||
* @type string $filename The file name. Ex: foobar-480x510.jpg.
|
||||
* }
|
||||
*/
|
||||
public function is_s3_url( $url ) {
|
||||
static $uploads_dir;
|
||||
static $domain;
|
||||
|
||||
/**
|
||||
* Tell if an URL is a S3 one.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param null|array|bool $is Null by default. Must return an array if an S3 URL, or false if not.
|
||||
* @param string $url The URL to test.
|
||||
*/
|
||||
$is = apply_filters( 'imagify_as3cf_is_s3_url', null, $url );
|
||||
|
||||
if ( false === $is ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( is_array( $is ) ) {
|
||||
return imagify_merge_intersect( $is, [
|
||||
'key' => '',
|
||||
'year_month' => '',
|
||||
'subdirs' => '',
|
||||
'filename' => '',
|
||||
] );
|
||||
}
|
||||
|
||||
if ( ! isset( $uploads_dir ) ) {
|
||||
$uploads_dir = wp_parse_url( $this->filesystem->get_upload_baseurl() );
|
||||
$uploads_dir = trim( $uploads_dir['path'], '/' ) . '/';
|
||||
}
|
||||
|
||||
if ( ! isset( $domain ) ) {
|
||||
if ( ! empty( $this->store_s3_settings['cloudfront'] ) ) {
|
||||
$domain = sanitize_text_field( $this->store_s3_settings['cloudfront'] );
|
||||
$domain = preg_replace( '@^(?:https?:)?//@', '//', $domain );
|
||||
$domain = preg_quote( $domain, '@' );
|
||||
} else {
|
||||
$domain = 's3-.+\.amazonaws\.com/[^/]+/';
|
||||
}
|
||||
}
|
||||
|
||||
$pattern = '@^(?:https?:)?//' . $domain . '/(?<key>' . $uploads_dir . '(?<year_month>\d{4}/\d{2}/)?(?<subdirs>.+/)?(?<filename>[^/]+))$@i';
|
||||
|
||||
if ( ! preg_match( $pattern, $url, $match ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unset( $match[0] );
|
||||
|
||||
return array_merge( [
|
||||
'year_month' => '',
|
||||
'subdirs' => '',
|
||||
], $match );
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Compatibility with AMP plugin from WordPress.com VIP.
|
||||
*/
|
||||
if ( function_exists( 'is_amp_endpoint' ) ) :
|
||||
|
||||
add_filter( 'imagify_allow_picture_tags_for_nextgen', 'imagify_amp_disable_picture_on_endpoint' );
|
||||
/**
|
||||
* Do not use <picture> tags in AMP pages.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @param bool $allow True to allow the use of <picture> tags (default). False to prevent their use.
|
||||
* @return bool
|
||||
*/
|
||||
function imagify_amp_disable_picture_on_endpoint( $allow ) {
|
||||
return $allow && ! is_amp_endpoint();
|
||||
};
|
||||
|
||||
endif;
|
||||
@@ -1,152 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\EnableMediaReplace;
|
||||
|
||||
use Imagify\Traits\InstanceGetterTrait;
|
||||
use Imagify_Enable_Media_Replace_Deprecated;
|
||||
use Imagify_Filesystem;
|
||||
|
||||
/**
|
||||
* Compat class for Enable Media Replace plugin.
|
||||
*
|
||||
* @since 1.6.9
|
||||
*/
|
||||
class Main extends Imagify_Enable_Media_Replace_Deprecated {
|
||||
use InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* The media ID.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.9
|
||||
*/
|
||||
protected $media_id;
|
||||
|
||||
/**
|
||||
* The process instance for the current attachment.
|
||||
*
|
||||
* @var ProcessInterface
|
||||
* @since 1.9
|
||||
*/
|
||||
protected $process;
|
||||
|
||||
/**
|
||||
* The path to the old backup file.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6.9
|
||||
*/
|
||||
protected $old_backup_path;
|
||||
|
||||
/**
|
||||
* List of paths to the old next-gen files.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.9.8
|
||||
*/
|
||||
protected $old_nextgen_paths = [];
|
||||
|
||||
/**
|
||||
* Launch the hooks before the files and data are replaced.
|
||||
*
|
||||
* @since 1.6.9
|
||||
* @since 1.9.10 The parameter changed from boolean to array. The method doesn’t return anything.
|
||||
*
|
||||
* @param array $args An array containing the post ID.
|
||||
*/
|
||||
public function init( $args = [] ) {
|
||||
if ( is_array( $args ) && ! empty( $args['post_id'] ) ) {
|
||||
$this->media_id = $args['post_id'];
|
||||
} else {
|
||||
// Backward compatibility.
|
||||
$this->media_id = (int) filter_input( INPUT_POST, 'ID' );
|
||||
$this->media_id = max( 0, $this->media_id );
|
||||
|
||||
if ( ! $this->media_id ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the old backup file path.
|
||||
$this->get_process();
|
||||
|
||||
if ( ! $this->process ) {
|
||||
$this->media_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->old_backup_path = $this->process->get_media()->get_backup_path();
|
||||
|
||||
if ( ! $this->old_backup_path ) {
|
||||
$this->media_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track of existing next-gen files.
|
||||
*
|
||||
* Whether the user chooses to rename the files or not, we will need to delete the current next-gen files before creating new ones:
|
||||
* - Rename the files: the old ones must be removed, they are useless now.
|
||||
* - Do not rename the files: the thumbnails may still get new names because of the suffix containing the image dimensions, which may differ (for example when thumbnails are scaled, not cropped).
|
||||
* In this last case, the thumbnails with the old dimensions are removed from the drive and from the WP’s post meta, so there is no need of keeping orphan next-gen files that would stay on the drive for ever, even after the attachment is deleted from WP.
|
||||
*/
|
||||
foreach ( $this->process->get_media()->get_media_files() as $media_file ) {
|
||||
foreach ( [ 'avif', 'webp' ] as $format ) {
|
||||
$this->old_nextgen_paths[] = imagify_path_to_nextgen( $media_file['path'], $format );
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the old backup file and old next-gen files.
|
||||
add_action( 'imagify_before_auto_optimization', [ $this, 'delete_backup' ] );
|
||||
add_action( 'imagify_not_optimized_attachment_updated', [ $this, 'delete_backup' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete previous backup file and next-gen files.
|
||||
* This is done after the images have been already replaced by Enable Media Replace.
|
||||
*
|
||||
* @since 1.8.4
|
||||
*
|
||||
* @param int $media_id The attachment ID.
|
||||
*/
|
||||
public function delete_backup( $media_id ) {
|
||||
if ( ! $this->old_backup_path || ! $this->media_id || $media_id !== $this->media_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filesystem = Imagify_Filesystem::get_instance();
|
||||
|
||||
if ( $filesystem->exists( $this->old_backup_path ) ) {
|
||||
// Delete old backup file.
|
||||
$filesystem->delete( $this->old_backup_path );
|
||||
$this->old_backup_path = false;
|
||||
}
|
||||
|
||||
if ( ! empty( $this->old_nextgen_paths ) ) {
|
||||
// Delete old next-gen files.
|
||||
$this->old_nextgen_paths = array_filter( $this->old_nextgen_paths, [ $filesystem, 'exists' ] );
|
||||
array_map( [ $filesystem, 'delete' ], $this->old_nextgen_paths );
|
||||
$this->old_nextgen_paths = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optimization process corresponding to the current media.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @return ProcessInterface|bool False if invalid.
|
||||
*/
|
||||
protected function get_process() {
|
||||
if ( isset( $this->process ) ) {
|
||||
return $this->process;
|
||||
}
|
||||
|
||||
$this->process = imagify_get_optimization_process( $this->media_id, 'wp' );
|
||||
|
||||
if ( ! $this->process->is_valid() ) {
|
||||
$this->process = false;
|
||||
}
|
||||
|
||||
return $this->process;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( function_exists( 'enable_media_replace' ) || class_exists( '\\EnableMediaReplace\\EnableMediaReplacePlugin' ) ) :
|
||||
|
||||
class_alias( '\\Imagify\\ThirdParty\\EnableMediaReplace\\Main', '\\Imagify_Enable_Media_Replace' );
|
||||
|
||||
add_filter( 'wp_handle_replace', [ \Imagify\ThirdParty\EnableMediaReplace\Main::get_instance(), 'init' ] );
|
||||
|
||||
endif;
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\FormidablePro;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Compat class for Formidable Forms Pro plugin.
|
||||
* Each call to `new WP_Query()` made by Imagify must have a `'is_imagify' => true` argument.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class Main {
|
||||
use \Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Class version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '1.1';
|
||||
|
||||
/**
|
||||
* Set to true when the current query comes from Imagify.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $is_imagify;
|
||||
|
||||
/**
|
||||
* Launch the hooks.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function init() {
|
||||
add_action( 'parse_query', array( $this, 'maybe_remove_media_library_filter' ) );
|
||||
add_action( 'posts_selection', array( $this, 'maybe_put_media_library_filter_back' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires before the 'pre_get_posts' hook.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param object $wp_query The WP_Query instance (passed by reference).
|
||||
*/
|
||||
public function maybe_remove_media_library_filter( $wp_query ) {
|
||||
if ( ! empty( $wp_query->query_vars['is_imagify'] ) && class_exists( 'FrmProFileField' ) ) {
|
||||
$this->is_imagify = true;
|
||||
remove_action( 'pre_get_posts', 'FrmProFileField::filter_media_library', 99 );
|
||||
} else {
|
||||
$this->is_imagify = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after the 'pre_get_posts' hook.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function maybe_put_media_library_filter_back() {
|
||||
if ( $this->is_imagify ) {
|
||||
add_action( 'pre_get_posts', 'FrmProFileField::filter_media_library', 99 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
use Imagify\ThirdParty\FormidablePro;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( class_exists( 'FrmProEddController' ) ) :
|
||||
|
||||
class_alias( '\\Imagify\\ThirdParty\\FormidablePro\\Main', '\\Imagify_Formidable_Pro' );
|
||||
|
||||
FormidablePro\Main::get_instance()->init();
|
||||
|
||||
endif;
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'FLYWHEEL_CONFIG_DIR' ) ) :
|
||||
|
||||
add_filter( 'imagify_site_root', 'imagify_flywheel_site_root', IMAGIFY_INT_MAX );
|
||||
/**
|
||||
* Filter the path to the site’s root.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string|null $root_path Path to the site's root. Default is null.
|
||||
* @return string|null
|
||||
*/
|
||||
function imagify_flywheel_site_root( $root_path ) {
|
||||
if ( ! empty( $_SERVER['DOCUMENT_ROOT'] ) ) {
|
||||
return trailingslashit( wp_unslash( $_SERVER['DOCUMENT_ROOT'] ) );
|
||||
}
|
||||
|
||||
$upload_basedir = imagify_get_filesystem()->get_upload_basedir( true );
|
||||
|
||||
if ( strpos( $upload_basedir, '/wp-content/' ) === false ) {
|
||||
// Uh oooooh...
|
||||
return $root_path;
|
||||
}
|
||||
|
||||
$upload_basedir = explode( '/wp-content/', $upload_basedir );
|
||||
$upload_basedir = reset( $upload_basedir );
|
||||
|
||||
return $upload_basedir . '/';
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'IS_PRESSABLE' ) ) :
|
||||
|
||||
add_filter( 'imagify_site_root', 'imagify_pressable_site_root', IMAGIFY_INT_MAX );
|
||||
/**
|
||||
* Filter the path to the site's root.
|
||||
*
|
||||
* @since 1.9.4
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string|null $root_path Path to the site's root. Default is null.
|
||||
* @return string
|
||||
*/
|
||||
function imagify_pressable_site_root( $root_path ) {
|
||||
$upload_basedir = trim( wp_normalize_path( WP_CONTENT_DIR ), '/' );
|
||||
$upload_basedir = explode( '/', $upload_basedir );
|
||||
$upload_basedir = reset( $upload_basedir );
|
||||
|
||||
return '/' . $upload_basedir . '/';
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_filter( 'http_request_args', 'imagify_siteground_change_user_agent', 10, 2 );
|
||||
/**
|
||||
* Filter the arguments used in a HTTP request to change the User Agent for requests "to self", to prevent firewalls to be triggered.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $r An array of HTTP request arguments.
|
||||
* @param string $url The request URL.
|
||||
* @return array
|
||||
*/
|
||||
function imagify_siteground_change_user_agent( $r, $url ) {
|
||||
static $user_agent;
|
||||
static $site_url;
|
||||
|
||||
$url = wp_parse_url( $url );
|
||||
|
||||
if ( empty( $url['path'] ) ) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
$paths = array(
|
||||
'/wp-admin/admin-ajax.php',
|
||||
'/wp-admin/admin-post.php',
|
||||
'/wp-cron.php',
|
||||
);
|
||||
|
||||
if ( ! isset( $site_url ) ) {
|
||||
$site_url = wp_parse_url( site_url( '/' ) );
|
||||
}
|
||||
|
||||
// Limit to requests to self.
|
||||
if ( false === strpos( $url['path'], $site_url['path'] ) && false === strpos( $site_url['path'], $url['path'] ) ) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
// Limit to requests to admin-ajax.php, admin-post.php, and wp-cron.php.
|
||||
foreach ( $paths as $i => $path ) {
|
||||
if ( false !== strpos( $url['path'], $path ) ) {
|
||||
$paths = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $paths ) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
// Randomize the User-Agent.
|
||||
if ( ! isset( $user_agent ) ) {
|
||||
$user_agent = wp_generate_password( 12, false );
|
||||
/**
|
||||
* Filter the User-Agent used for requests "to self".
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $user_agent The User-Agent.
|
||||
* @param array $r An array of HTTP request arguments.
|
||||
* @param array $url The request URL, parsed.
|
||||
*/
|
||||
$user_agent = apply_filters( 'imagify_user_agent_for_internal_requests', $user_agent, $r, $url );
|
||||
}
|
||||
|
||||
$r['user-agent'] = $user_agent;
|
||||
|
||||
return $r;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'WPCOMSH_VERSION' ) ) :
|
||||
|
||||
add_filter( 'imagify_site_root', 'imagify_wpcom_site_root', IMAGIFY_INT_MAX );
|
||||
/**
|
||||
* Filter the path to the site's root.
|
||||
*
|
||||
* @since 1.8.4
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string|null $root_path Path to the site's root. Default is null.
|
||||
* @return string|null
|
||||
*/
|
||||
function imagify_wpcom_site_root( $root_path ) {
|
||||
$upload_basedir = imagify_get_filesystem()->get_upload_basedir( true );
|
||||
|
||||
if ( strpos( $upload_basedir, '/wp-content/' ) === false ) {
|
||||
// Uh oooooh...
|
||||
return $root_path;
|
||||
}
|
||||
|
||||
$upload_basedir = explode( '/wp-content/', $upload_basedir );
|
||||
$upload_basedir = reset( $upload_basedir );
|
||||
|
||||
return $upload_basedir . '/';
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( class_exists( 'WpeCommon' ) ) :
|
||||
|
||||
add_filter( 'imagify_unoptimized_attachment_limit', '_imagify_wpengine_unoptimized_attachment_limit' );
|
||||
add_filter( 'imagify_count_saving_data_limit', '_imagify_wpengine_unoptimized_attachment_limit' );
|
||||
/**
|
||||
* Change the limit for the number of posts: WP Engine limits SQL queries size to 2048 octets (16384 characters).
|
||||
*
|
||||
* @since 1.4.7
|
||||
* @since 1.6.7 Renamed (and deprecated) _imagify_wengine_unoptimized_attachment_limit() into _imagify_wpengine_unoptimized_attachment_limit().
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function _imagify_wpengine_unoptimized_attachment_limit() {
|
||||
return 2500;
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,240 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG\Bulk;
|
||||
|
||||
use C_Gallery_Storage;
|
||||
use Imagify\Bulk\AbstractBulk;
|
||||
use Imagify\ThirdParty\NGG\DB;
|
||||
|
||||
/**
|
||||
* Class to use for bulk for NextGen Gallery.
|
||||
*
|
||||
* @since 1.9
|
||||
*/
|
||||
class NGG extends AbstractBulk {
|
||||
/**
|
||||
* Context "short name".
|
||||
*
|
||||
* @var string
|
||||
* @since 1.9
|
||||
*/
|
||||
protected $context = 'ngg';
|
||||
|
||||
/**
|
||||
* Get all unoptimized media ids.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @param int $optimization_level The optimization level.
|
||||
* @return array A list of unoptimized media IDs.
|
||||
*/
|
||||
public function get_unoptimized_media_ids( $optimization_level ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->set_no_time_limit();
|
||||
|
||||
$storage = C_Gallery_Storage::get_instance();
|
||||
$ngg_table = $wpdb->prefix . 'ngg_pictures';
|
||||
$data = [];
|
||||
$images = $wpdb->get_results( $wpdb->prepare( // WPCS: unprepared SQL ok.
|
||||
"
|
||||
SELECT DISTINCT picture.pid as id, picture.filename, idata.optimization_level, idata.status, idata.data
|
||||
FROM $ngg_table as picture
|
||||
LEFT JOIN $wpdb->ngg_imagify_data as idata
|
||||
ON picture.pid = idata.pid
|
||||
WHERE idata.pid IS NULL
|
||||
OR idata.optimization_level != %d
|
||||
OR idata.status = 'error'
|
||||
LIMIT %d",
|
||||
$optimization_level,
|
||||
imagify_get_unoptimized_attachment_limit()
|
||||
), ARRAY_A );
|
||||
|
||||
if ( ! $images ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ( $images as $image ) {
|
||||
$id = absint( $image['id'] );
|
||||
$file_path = $storage->get_image_abspath( $id );
|
||||
|
||||
if ( ! $file_path || ! $this->filesystem->exists( $file_path ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attachment_data = maybe_unserialize( $image['data'] );
|
||||
$attachment_error = '';
|
||||
|
||||
if ( isset( $attachment_data['sizes']['full']['error'] ) ) {
|
||||
$attachment_error = $attachment_data['sizes']['full']['error'];
|
||||
}
|
||||
|
||||
$attachment_error = trim( $attachment_error );
|
||||
$attachment_status = $image['status'];
|
||||
$attachment_optimization_level = $image['optimization_level'];
|
||||
$attachment_backup_path = get_imagify_ngg_attachment_backup_path( $file_path );
|
||||
|
||||
// Don't try to re-optimize if the optimization level is still the same.
|
||||
if ( $optimization_level === $attachment_optimization_level && is_string( $attachment_error ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't try to re-optimize if there is no backup file.
|
||||
if ( 'success' === $attachment_status && $optimization_level !== $attachment_optimization_level && ! $this->filesystem->exists( $attachment_backup_path ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't try to re-optimize images already compressed.
|
||||
if ( 'already_optimized' === $attachment_status && $attachment_optimization_level >= $optimization_level ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't try to re-optimize images with an empty error message.
|
||||
if ( 'error' === $attachment_status && empty( $attachment_error ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = $id;
|
||||
} // End foreach().
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ids of all optimized media without next-gen versions.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param string $format Format we are looking for. (webp|avif).
|
||||
*
|
||||
* @return array {
|
||||
* @type array $ids A list of media IDs.
|
||||
* @type array $errors {
|
||||
* @type array $no_file_path A list of media IDs.
|
||||
* @type array $no_backup A list of media IDs.
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public function get_optimized_media_ids_without_format( $format ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->set_no_time_limit();
|
||||
|
||||
$storage = C_Gallery_Storage::get_instance();
|
||||
$ngg_table = $wpdb->prefix . 'ngg_pictures';
|
||||
$data_table = DB::get_instance()->get_table_name();
|
||||
$suffix = constant( imagify_get_optimization_process_class_name( 'ngg' ) . '::WEBP_SUFFIX' );
|
||||
|
||||
if ( 'avif' === get_imagify_option( 'optimization_format' ) ) {
|
||||
$suffix = constant( imagify_get_optimization_process_class_name( 'ngg' ) . '::AVIF_SUFFIX' );
|
||||
}
|
||||
|
||||
$files = $wpdb->get_col( $wpdb->prepare( // WPCS: unprepared SQL ok.
|
||||
"
|
||||
SELECT ngg.pid
|
||||
FROM $ngg_table as ngg
|
||||
INNER JOIN $data_table AS data
|
||||
ON ( ngg.pid = data.pid )
|
||||
WHERE
|
||||
( data.status = 'success' OR data.status = 'already_optimized' )
|
||||
AND data.data NOT LIKE %s
|
||||
ORDER BY ngg.pid DESC",
|
||||
'%' . $wpdb->esc_like( $suffix . '";a:4:{s:7:"success";b:1;' ) . '%'
|
||||
) );
|
||||
|
||||
$wpdb->flush();
|
||||
unset( $ngg_table, $data_table, $suffix );
|
||||
|
||||
$data = [
|
||||
'ids' => [],
|
||||
'errors' => [
|
||||
'no_file_path' => [],
|
||||
'no_backup' => [],
|
||||
],
|
||||
];
|
||||
|
||||
if ( ! $files ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ( $files as $file_id ) {
|
||||
$file_id = absint( $file_id );
|
||||
$file_path = $storage->get_image_abspath( $file_id );
|
||||
|
||||
if ( ! $file_path ) {
|
||||
// Problem.
|
||||
$data['errors']['no_file_path'][] = $file_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
$backup_path = get_imagify_ngg_attachment_backup_path( $file_path );
|
||||
|
||||
if ( ! $this->filesystem->exists( $backup_path ) ) {
|
||||
// No backup, no next-gen.
|
||||
$data['errors']['no_backup'][] = $file_id;
|
||||
continue;
|
||||
}
|
||||
|
||||
$data['ids'][] = $file_id;
|
||||
} // End foreach().
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if there are optimized media without next-gen versions.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @return int The number of media.
|
||||
*/
|
||||
public function has_optimized_media_without_nextgen() {
|
||||
global $wpdb;
|
||||
|
||||
$ngg_table = $wpdb->prefix . 'ngg_pictures';
|
||||
$data_table = DB::get_instance()->get_table_name();
|
||||
$suffix = constant( imagify_get_optimization_process_class_name( 'ngg' ) . '::WEBP_SUFFIX' );
|
||||
|
||||
if ( 'avif' === get_imagify_option( 'optimization_format' ) ) {
|
||||
$suffix = constant( imagify_get_optimization_process_class_name( 'ngg' ) . '::AVIF_SUFFIX' );
|
||||
}
|
||||
|
||||
return (int) $wpdb->get_var( $wpdb->prepare( // WPCS: unprepared SQL ok.
|
||||
"
|
||||
SELECT COUNT(ngg.pid)
|
||||
FROM $ngg_table as ngg
|
||||
INNER JOIN $data_table AS data
|
||||
ON ( ngg.pid = data.pid )
|
||||
WHERE
|
||||
( data.status = 'success' OR data.status = 'already_optimized' )
|
||||
AND data.data NOT LIKE %s",
|
||||
'%' . $wpdb->esc_like( $suffix . '";a:4:{s:7:"success";b:1;' ) . '%'
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context data.
|
||||
*
|
||||
* @since 1.9
|
||||
*
|
||||
* @return array {
|
||||
* The formated data.
|
||||
*
|
||||
* @type string $count-optimized Number of media optimized.
|
||||
* @type string $count-errors Number of media having an optimization error, with a link to the page listing the optimization errors.
|
||||
* @type string $optimized-size Optimized filesize.
|
||||
* @type string $original-size Original filesize.
|
||||
* }
|
||||
*/
|
||||
public function get_context_data() {
|
||||
$total_saving_data = imagify_count_saving_data();
|
||||
$data = [
|
||||
'count-optimized' => imagify_ngg_count_optimized_attachments(),
|
||||
'count-errors' => imagify_ngg_count_error_attachments(),
|
||||
'optimized-size' => $total_saving_data['optimized_size'],
|
||||
'original-size' => $total_saving_data['original_size'],
|
||||
'errors_url' => get_imagify_admin_url( 'folder-errors', $this->context ),
|
||||
];
|
||||
|
||||
return $this->format_context_data( $data );
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG\Context;
|
||||
|
||||
use Imagify\Context\AbstractContext;
|
||||
use Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Context class used for the WP media library.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class NGG extends AbstractContext {
|
||||
use InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Context "short name".
|
||||
*
|
||||
* @var string
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $context = 'ngg';
|
||||
|
||||
/**
|
||||
* Type of files this context allows.
|
||||
*
|
||||
* @var string Possible values are:
|
||||
* - 'all' to allow all types.
|
||||
* - 'image' to allow only images.
|
||||
* - 'not-image' to allow only pdf files.
|
||||
* @since 1.9
|
||||
* @see imagify_get_mime_types()
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $allowed_mime_types = 'image';
|
||||
|
||||
/**
|
||||
* The thumbnail sizes for this context, except the full size.
|
||||
*
|
||||
* @var array {
|
||||
* Data for the currently registered thumbnail sizes.
|
||||
* Size names are used as array keys.
|
||||
*
|
||||
* @type int $width The image width.
|
||||
* @type int $height The image height.
|
||||
* @type bool $crop True to crop, false to resize.
|
||||
* @type string $name The size name.
|
||||
* }
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $thumbnail_sizes = [];
|
||||
|
||||
/**
|
||||
* Tell if the optimization process is allowed to backup in this context.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $can_backup = true;
|
||||
|
||||
/**
|
||||
* Get images max width for this context. This is used when resizing.
|
||||
* 0 means to not resize.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_resizing_threshold() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user capacity to operate Imagify in this context.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $describer Capacity describer. Possible values are like 'manage', 'bulk-optimize', 'manual-optimize', 'auto-optimize'.
|
||||
* @return string
|
||||
*/
|
||||
public function get_capacity( $describer = 'manage' ) {
|
||||
switch ( $describer ) {
|
||||
case 'manage':
|
||||
$capacity = 'NextGEN Change options';
|
||||
break;
|
||||
|
||||
case 'bulk-optimize':
|
||||
$capacity = 'NextGEN Manage others gallery';
|
||||
break;
|
||||
|
||||
case 'optimize':
|
||||
case 'restore':
|
||||
case 'manual-optimize':
|
||||
case 'manual-restore':
|
||||
$capacity = 'NextGEN Manage gallery';
|
||||
break;
|
||||
|
||||
case 'auto-optimize':
|
||||
$capacity = 'NextGEN Upload images';
|
||||
break;
|
||||
|
||||
default:
|
||||
$capacity = $describer;
|
||||
}
|
||||
|
||||
return $this->filter_capacity( $capacity, $describer );
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Imagify NextGen Gallery DB class.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
class DB extends \Imagify_Abstract_DB {
|
||||
|
||||
/**
|
||||
* Class version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '1.1.1';
|
||||
|
||||
/**
|
||||
* The single instance of the class.
|
||||
*
|
||||
* @var object
|
||||
* @since 1.5
|
||||
* @access protected
|
||||
*/
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* The suffix used in the name of the database table (so, without the wpdb prefix).
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7
|
||||
* @access protected
|
||||
*/
|
||||
protected $table = 'ngg_imagify_data';
|
||||
|
||||
/**
|
||||
* The version of our database table.
|
||||
*
|
||||
* @var int
|
||||
* @since 1.5
|
||||
* @since 1.7 Not public anymore, now an integer.
|
||||
* @access protected
|
||||
*/
|
||||
protected $table_version = 100;
|
||||
|
||||
/**
|
||||
* Tell if the table is the same for each site of a Multisite.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.7
|
||||
* @access protected
|
||||
*/
|
||||
protected $table_is_global = false;
|
||||
|
||||
/**
|
||||
* The name of the primary column.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.5
|
||||
* @since 1.7 Not public anymore.
|
||||
* @access protected
|
||||
*/
|
||||
protected $primary_key = 'pid';
|
||||
|
||||
/**
|
||||
* Get the main Instance.
|
||||
*
|
||||
* @since 1.6.5
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return object Main instance.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( ! isset( self::$_instance ) ) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whitelist of columns.
|
||||
*
|
||||
* @since 1.5
|
||||
* @access public
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'data_id' => '%d',
|
||||
'pid' => '%d',
|
||||
'optimization_level' => '%s',
|
||||
'status' => '%s',
|
||||
'data' => '%s',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default column values.
|
||||
*
|
||||
* @since 1.5
|
||||
* @access public
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_column_defaults() {
|
||||
return array(
|
||||
'data_id' => 0,
|
||||
'pid' => 0,
|
||||
'optimization_level' => '',
|
||||
'status' => '',
|
||||
'data' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query to create the table fields.
|
||||
*
|
||||
* @since 1.7
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_table_schema() {
|
||||
return "
|
||||
data_id int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
pid int(11) unsigned NOT NULL default 0,
|
||||
optimization_level varchar(1) NOT NULL default '',
|
||||
status varchar(30) NOT NULL default '',
|
||||
data longtext NOT NULL default '',
|
||||
PRIMARY KEY (data_id),
|
||||
KEY pid (pid)";
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Class that handles the optimization of thumbnails dynamically generated.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class DynamicThumbnails {
|
||||
use \Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* The queue containing the sizes, grouped by image ID.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected static $sizes = [];
|
||||
|
||||
/**
|
||||
* A list of NGG image objects, grouped by image ID.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected static $images = [];
|
||||
|
||||
/**
|
||||
* Add a dynamically generated thumbnail to the background process queue.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param object $image A NGG image object.
|
||||
* @param string $size The thumbnail size name.
|
||||
*/
|
||||
public function push_to_queue( $image, $size ) {
|
||||
static $done = false;
|
||||
|
||||
if ( empty( $image->pid ) ) {
|
||||
// WUT?
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( static::$sizes[ $image->pid ] ) ) {
|
||||
static::$sizes[ $image->pid ] = [];
|
||||
}
|
||||
|
||||
static::$sizes[ $image->pid ][] = $size;
|
||||
|
||||
if ( empty( static::$images[ $image->pid ] ) ) {
|
||||
static::$images[ $image->pid ] = $image;
|
||||
}
|
||||
|
||||
if ( $done ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$done = true;
|
||||
|
||||
add_action( 'shutdown', [ $this, 'optimize' ], 555 ); // Must come before 666 (see Imagify_Abstract_Background_Process->init()).
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the optimizations.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function optimize() {
|
||||
if ( empty( static::$sizes ) ) {
|
||||
// ¯\(°_o)/¯
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( static::$sizes as $image_id => $sizes ) {
|
||||
if ( empty( static::$images[ $image_id ] ) ) {
|
||||
// ¯\(°_o)/¯
|
||||
continue;
|
||||
}
|
||||
|
||||
$sizes = array_filter( $sizes );
|
||||
|
||||
if ( empty( $sizes ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$process = imagify_get_optimization_process( static::$images[ $image_id ], 'ngg' );
|
||||
|
||||
if ( ! $process->is_valid() || ! $process->get_media()->is_supported() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $process->get_data();
|
||||
|
||||
if ( ! $data->is_optimized() ) {
|
||||
// The main image is not optimized.
|
||||
continue;
|
||||
}
|
||||
|
||||
$sizes = array_unique( $sizes );
|
||||
|
||||
foreach ( $sizes as $i => $size ) {
|
||||
$size_status = $data->get_size_data( $size, 'success' );
|
||||
|
||||
if ( $size_status ) {
|
||||
// This thumbnail has already been processed.
|
||||
unset( $sizes[ $i ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $sizes ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$optimization_level = $process->get_data()->get_optimization_level();
|
||||
$args = [
|
||||
'hook_suffix' => 'optimize_generated_image',
|
||||
];
|
||||
|
||||
$process->optimize_sizes( $sizes, $optimization_level, $args );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Imagify NextGen Gallery class.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
class Main {
|
||||
use \Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Class version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '1.1';
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @since 1.5
|
||||
* @since 1.6.5 Doesn't launch the hooks anymore.
|
||||
* @since 1.9 Visibility set to public.
|
||||
* @access public
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
public function __construct() {}
|
||||
|
||||
/**
|
||||
* Launch the hooks.
|
||||
*
|
||||
* @since 1.6.5
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function init() {
|
||||
static $done = false;
|
||||
|
||||
if ( $done ) {
|
||||
return;
|
||||
}
|
||||
$done = true;
|
||||
|
||||
add_filter( 'imagify_register_context', [ $this, 'register_context' ] );
|
||||
add_filter( 'imagify_context_class_name', [ $this, 'add_context_class_name' ], 10, 2 );
|
||||
add_filter( 'imagify_process_class_name', [ $this, 'add_process_class_name' ], 10, 2 );
|
||||
add_filter( 'imagify_bulk_class_name', [ $this, 'add_bulk_class_name' ], 10, 2 );
|
||||
add_action( 'init', [ $this, 'add_mixin' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the context used for NGG.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $contexts An array of context names.
|
||||
* @return array
|
||||
*/
|
||||
public function register_context( $contexts ) {
|
||||
$contexts[] = 'ngg';
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the name of the class to use to define a context.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $class_name The class name.
|
||||
* @param string $context The context name.
|
||||
* @return string
|
||||
*/
|
||||
public function add_context_class_name( $class_name, $context ) {
|
||||
if ( 'ngg' === $context ) {
|
||||
return '\\Imagify\\ThirdParty\\NGG\\Context\\NGG';
|
||||
}
|
||||
|
||||
return $class_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the name of the class to use for the optimization.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $class_name The class name.
|
||||
* @param string $context The context name.
|
||||
* @return string
|
||||
*/
|
||||
public function add_process_class_name( $class_name, $context ) {
|
||||
if ( 'ngg' === $context ) {
|
||||
return '\\Imagify\\ThirdParty\\NGG\\Optimization\\Process\\NGG';
|
||||
}
|
||||
|
||||
return $class_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the name of the class to use for the bulk optimization.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $class_name The class name.
|
||||
* @param string $context The context name.
|
||||
* @return string
|
||||
*/
|
||||
public function add_bulk_class_name( $class_name, $context ) {
|
||||
if ( 'ngg' === $context ) {
|
||||
return '\\Imagify\\ThirdParty\\NGG\\Bulk\\NGG';
|
||||
}
|
||||
|
||||
return $class_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom NGG mixin to override its functions.
|
||||
*
|
||||
* @since 1.5
|
||||
* @access public
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
public function add_mixin() {
|
||||
\C_Gallery_Storage::get_instance()->get_wrapped_instance()->add_mixin( '\\Imagify\\ThirdParty\\NGG\\NGGStorage' );
|
||||
}
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG\Media;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Media class for the medias from NextGen Gallery.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class NGG extends \Imagify\Media\AbstractMedia {
|
||||
use \Imagify\Deprecated\Traits\Media\NGGDeprecatedTrait;
|
||||
|
||||
/**
|
||||
* Context (where the media "comes from").
|
||||
*
|
||||
* @var string
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $context = 'ngg';
|
||||
|
||||
/**
|
||||
* The image object.
|
||||
*
|
||||
* @var object A \nggImage object.
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* The storage object used by NGG.
|
||||
*
|
||||
* @var object A \C_Gallery_Storage object (by default).
|
||||
* @since 1.8.
|
||||
* @access protected
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int|\nggImage|\nggdb|\StdClass $id The NGG image ID, \nggImage object, \nggdb object, or an anonym object containing a pid property.
|
||||
*/
|
||||
public function __construct( $id ) {
|
||||
if ( ! static::constructor_accepts( $id ) ) {
|
||||
parent::__construct( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_numeric( $id ) ) {
|
||||
$this->image = \nggdb::find_image( (int) $id );
|
||||
$id = ! empty( $this->image->pid ) ? (int) $this->image->pid : 0;
|
||||
} elseif ( $id instanceof \nggImage ) {
|
||||
$this->image = $id;
|
||||
$id = (int) $id->pid;
|
||||
} elseif ( is_object( $id ) ) {
|
||||
$this->image = \nggdb::find_image( (int) $id->pid );
|
||||
$id = ! empty( $this->image->pid ) ? (int) $this->image->pid : 0;
|
||||
} else {
|
||||
$id = 0;
|
||||
}
|
||||
|
||||
if ( ! $id ) {
|
||||
$this->image = null;
|
||||
|
||||
parent::__construct( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
parent::__construct( $id );
|
||||
|
||||
// NGG storage.
|
||||
if ( ! empty( $this->image->_ngiw ) ) {
|
||||
$this->storage = $this->image->_ngiw->get_storage()->object;
|
||||
} else {
|
||||
$this->storage = \C_Gallery_Storage::get_instance()->object;
|
||||
}
|
||||
|
||||
// Load nggAdmin class.
|
||||
$ngg_admin_functions_path = WP_PLUGIN_DIR . '/' . NGGFOLDER . '/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php';
|
||||
|
||||
if ( ! class_exists( 'nggAdmin' ) && $this->filesystem->exists( $ngg_admin_functions_path ) ) {
|
||||
require_once $ngg_admin_functions_path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if the given entry can be accepted in the constructor.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param mixed $id Whatever.
|
||||
* @return bool
|
||||
*/
|
||||
public static function constructor_accepts( $id ) {
|
||||
if ( ! $id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( is_numeric( $id ) || $id instanceof \nggImage ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return is_object( $id ) && ! empty( $id->pid ) && is_numeric( $id->pid );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** NGG SPECIFICS =========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the NGG image object.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return \nggImage
|
||||
*/
|
||||
public function get_ngg_image() {
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NGG storage object.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return \C_Gallery_Storage
|
||||
*/
|
||||
public function get_ngg_storage() {
|
||||
return $this->storage;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** ORIGINAL FILE =========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the original file path, even if the file doesn't exist.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string|bool The file path. False on failure.
|
||||
*/
|
||||
public function get_raw_original_path() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->get_cdn() ) {
|
||||
return $this->get_cdn()->get_file_path( 'original' );
|
||||
}
|
||||
|
||||
return ! empty( $this->image->imagePath ) ? $this->image->imagePath : false;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** FULL SIZE FILE ========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the URL of the media’s full size file.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string|bool The file URL. False on failure.
|
||||
*/
|
||||
public function get_fullsize_url() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->get_cdn() ) {
|
||||
return $this->get_cdn()->get_file_url();
|
||||
}
|
||||
|
||||
return ! empty( $this->image->imageURL ) ? $this->image->imageURL : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the media’s full size file, even if the file doesn't exist.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string|bool The file path. False on failure.
|
||||
*/
|
||||
public function get_raw_fullsize_path() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->get_cdn() ) {
|
||||
return $this->get_cdn()->get_file_path();
|
||||
}
|
||||
|
||||
return ! empty( $this->image->imagePath ) ? $this->image->imagePath : false;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** BACKUP FILE ============================================================================= */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the backup URL, even if the file doesn't exist.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string|bool The file URL. False on failure.
|
||||
*/
|
||||
public function get_backup_url() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return site_url( '/' . $this->filesystem->make_path_relative( $this->get_raw_backup_path() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backup file path, even if the file doesn't exist.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string|bool The file path. False on failure.
|
||||
*/
|
||||
public function get_raw_backup_path() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get_imagify_ngg_attachment_backup_path( $this->get_raw_original_path() );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** THUMBNAILS ============================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Create the media thumbnails.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool|WP_Error True on success. A \WP_Error instance on failure.
|
||||
*/
|
||||
public function generate_thumbnails() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return new \WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$image_data = $this->storage->_image_mapper->find( $this->get_id() ); // stdClass Object.
|
||||
|
||||
if ( ! $image_data ) {
|
||||
// ¯\(°_o)/¯
|
||||
return new \WP_Error( 'no_ngg_image', __( 'Image not found in NextGen Gallery data.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( empty( $image_data->meta_data['backup'] ) || ! is_array( $image_data->meta_data['backup'] ) ) {
|
||||
$full_path = $this->storage->get_image_abspath( $image_data );
|
||||
|
||||
$image_data->meta_data['backup'] = [
|
||||
'filename' => $this->filesystem->file_name( $full_path ), // Yes, $full_path.
|
||||
'width' => $image_data->meta_data['width'], // Original image width.
|
||||
'height' => $image_data->meta_data['height'], // Original image height.
|
||||
'generated' => microtime(),
|
||||
];
|
||||
}
|
||||
|
||||
$backup_path = $this->storage->get_image_abspath( $image_data, 'backup' );
|
||||
$failed = [];
|
||||
|
||||
foreach ( $this->get_media_files() as $size_name => $size_data ) {
|
||||
if ( 'full' === $size_name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$params = $this->storage->get_image_size_params( $image_data, $size_name );
|
||||
$thumbnail = @$this->storage->generate_image_clone( // Don't remove this @ or the sky will fall.
|
||||
$backup_path,
|
||||
$this->storage->get_image_abspath( $image_data, $size_name ),
|
||||
$params
|
||||
);
|
||||
|
||||
if ( ! $thumbnail ) {
|
||||
// Failed.
|
||||
$failed[] = $size_name;
|
||||
unset( $image_data->meta_data[ $size_name ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$size_meta = [
|
||||
'width' => 0,
|
||||
'height' => 0,
|
||||
'filename' => \M_I18n::mb_basename( $thumbnail->fileName ),
|
||||
'generated' => microtime(),
|
||||
];
|
||||
|
||||
$dimensions = $this->filesystem->get_image_size( $thumbnail->fileName );
|
||||
|
||||
if ( $dimensions ) {
|
||||
$size_meta['width'] = $dimensions['width'];
|
||||
$size_meta['height'] = $dimensions['height'];
|
||||
}
|
||||
|
||||
if ( isset( $params['crop_frame'] ) ) {
|
||||
$size_meta['crop_frame'] = $params['crop_frame'];
|
||||
}
|
||||
|
||||
$image_data->meta_data[ $size_name ] = $size_meta;
|
||||
} // End foreach().
|
||||
|
||||
// Keep our property up to date.
|
||||
$this->image->_ngiw->_cache['meta_data'] = $image_data->meta_data;
|
||||
$this->image->_ngiw->_orig_image = $image_data;
|
||||
|
||||
$post_id = $this->storage->_image_mapper->save( $image_data );
|
||||
|
||||
if ( ! $post_id ) {
|
||||
return new \WP_Error( 'meta_data_not_saved', __( 'Related NextGen Gallery data could not be saved.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( $failed ) {
|
||||
return new \WP_Error(
|
||||
'thumbnail_restore_failed',
|
||||
sprintf( _n( '%n thumbnail could not be restored.', '%n thumbnails could not be restored.', count( $failed ), 'imagify' ), count( $failed ) ),
|
||||
[ 'failed_thumbnails' => $failed ]
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** MEDIA DATA ============================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Tell if the current media has the required data (the data containing the file paths and thumbnails).
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_required_media_data() {
|
||||
static $sizes;
|
||||
|
||||
if ( ! $this->is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $sizes ) ) {
|
||||
$sizes = $this->get_media_files();
|
||||
}
|
||||
|
||||
return $sizes && ! empty( $this->image->imagePath );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of the files of this media, including the full size file.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array {
|
||||
* An array with the size names as keys ('full' is used for the full size file), and arrays of data as values:
|
||||
*
|
||||
* @type string $size The size name.
|
||||
* @type string $path Absolute path to the file.
|
||||
* @type int $width The file width.
|
||||
* @type int $height The file height.
|
||||
* @type string $mime-type The file mime type.
|
||||
* @type bool $disabled True if the size is disabled in the plugin’s settings.
|
||||
* }
|
||||
*/
|
||||
public function get_media_files() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$fullsize_path = $this->get_raw_fullsize_path();
|
||||
|
||||
if ( ! $fullsize_path ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$dimensions = $this->get_dimensions();
|
||||
$all_sizes = [
|
||||
'full' => [
|
||||
'size' => 'full',
|
||||
'path' => $fullsize_path,
|
||||
'width' => $dimensions['width'],
|
||||
'height' => $dimensions['height'],
|
||||
'mime-type' => $this->get_mime_type(),
|
||||
'disabled' => false,
|
||||
],
|
||||
];
|
||||
|
||||
if ( ! $this->is_image() ) {
|
||||
return $this->filter_media_files( $all_sizes );
|
||||
}
|
||||
|
||||
// Remove common values (that have no value for us here, lol). Also remove 'full' and 'backup'.
|
||||
$image_data = array_diff_key( $this->image->meta_data, [
|
||||
'full' => 1,
|
||||
'backup' => 1,
|
||||
'width' => 1,
|
||||
'height' => 1,
|
||||
'md5' => 1,
|
||||
'aperture' => 1,
|
||||
'credit' => 1,
|
||||
'camera' => 1,
|
||||
'caption' => 1,
|
||||
'created_timestamp' => 1,
|
||||
'copyright' => 1,
|
||||
'focal_length' => 1,
|
||||
'iso' => 1,
|
||||
'shutter_speed' => 1,
|
||||
'flash' => 1,
|
||||
'title' => 1,
|
||||
'keywords' => 1,
|
||||
'saved' => 1,
|
||||
] );
|
||||
|
||||
if ( ! $image_data ) {
|
||||
return $this->filter_media_files( $all_sizes );
|
||||
}
|
||||
|
||||
$ngg_data = $this->storage->_image_mapper->find( $this->get_id() );
|
||||
|
||||
foreach ( $image_data as $size => $size_data ) {
|
||||
if ( ! isset( $size_data['width'], $size_data['height'], $size_data['filename'], $size_data['generated'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file_type = (object) wp_check_filetype( $size_data['filename'], $this->get_allowed_mime_types() );
|
||||
|
||||
if ( ! $file_type->type ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$all_sizes[ $size ] = [
|
||||
'size' => $size,
|
||||
'path' => $this->storage->get_image_abspath( $ngg_data, $size ),
|
||||
'width' => (int) $size_data['width'],
|
||||
'height' => (int) $size_data['height'],
|
||||
'mime-type' => $file_type->type,
|
||||
'disabled' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->filter_media_files( $all_sizes );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the media is an image, get its width and height.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_dimensions() {
|
||||
if ( ! $this->is_image() ) {
|
||||
return [
|
||||
'width' => 0,
|
||||
'height' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'width' => ! empty( $this->image->meta_data['width'] ) ? (int) $this->image->meta_data['width'] : 0,
|
||||
'height' => ! empty( $this->image->meta_data['height'] ) ? (int) $this->image->meta_data['height'] : 0,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the media data dimensions.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $dimensions {
|
||||
* An array containing width and height.
|
||||
*
|
||||
* @type int $width The image width.
|
||||
* @type int $height The image height.
|
||||
* }
|
||||
*/
|
||||
protected function update_media_data_dimensions( $dimensions ) {
|
||||
$changed = false;
|
||||
$data = [
|
||||
'width' => $dimensions['width'],
|
||||
'height' => $dimensions['height'],
|
||||
'md5' => md5_file( $this->get_raw_fullsize_path() ),
|
||||
];
|
||||
|
||||
foreach ( $data as $k => $v ) {
|
||||
if ( ! isset( $this->image->meta_data[ $k ] ) || $this->image->meta_data[ $k ] !== $v ) {
|
||||
$this->image->meta_data[ $k ] = $v;
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $changed ) {
|
||||
\nggdb::update_image_meta( $this->id, $this->image->meta_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Imagify NextGen Gallery storage class.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
class NGGStorage extends \Mixin {
|
||||
|
||||
/**
|
||||
* Class version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '1.1';
|
||||
|
||||
/**
|
||||
* Delete a gallery AND all the pictures associated to this gallery!
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param int|object $gallery A gallery ID or object.
|
||||
* @return bool Whetther tha gallery was been deleted or not.
|
||||
*/
|
||||
public function delete_gallery( $gallery ) {
|
||||
$gallery_id = is_numeric( $gallery ) ? $gallery : $gallery->{$gallery->id_field};
|
||||
$images_id = \nggdb::get_ids_from_gallery( $gallery_id );
|
||||
|
||||
foreach ( $images_id as $pid ) {
|
||||
$process = imagify_get_optimization_process( $pid, 'ngg' );
|
||||
|
||||
if ( $process->is_valid() && $process->get_data()->is_optimized() ) {
|
||||
$process->get_data()->delete_optimization_data();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->call_parent( 'delete_gallery', $gallery );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a specific size for an image.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param int|object $image An image ID or NGG object.
|
||||
* @param string $size An image size.
|
||||
* @param array $params An array of parameters.
|
||||
* @param bool $skip_defaults Whatever NGG does with default settings.
|
||||
* @return bool|object An object on success. False on failure.
|
||||
*/
|
||||
public function generate_image_size( $image, $size, $params = null, $skip_defaults = false ) {
|
||||
// $image could be an object or an (int) image ID.
|
||||
if ( is_numeric( $image ) ) {
|
||||
$image = $this->object->_image_mapper->find( $image );
|
||||
}
|
||||
|
||||
// If a user adds a watermark, rotates or resizes an image, we restore it.
|
||||
// TO DO - waiting for a hook to be able to re-optimize the original size after restoring.
|
||||
if ( isset( $image->pid ) && ( true === $params['watermark'] || ( isset( $params['rotation'] ) || isset( $params['flip'] ) ) || ( ! empty( $params['width'] ) || ! empty( $params['height'] ) ) ) ) {
|
||||
$process = imagify_get_optimization_process( $image->pid, 'ngg' );
|
||||
|
||||
if ( $process->is_valid() && $process->get_data()->is_optimized() ) {
|
||||
$process->get_data()->delete_optimization_data();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->call_parent( 'generate_image_size', $image, $size, $params, $skip_defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover image from backup.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param int|object $image An image ID or NGG object.
|
||||
* @return string|bool Result code on success. False on failure.
|
||||
*/
|
||||
public function recover_image( $image ) {
|
||||
// $image could be an object or an (int) image ID.
|
||||
if ( is_numeric( $image ) ) {
|
||||
$image = $this->object->_image_mapper->find( $image );
|
||||
}
|
||||
|
||||
if ( ! $image ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove Imagify data.
|
||||
if ( isset( $image->pid ) ) {
|
||||
$process = imagify_get_optimization_process( $image->pid, 'ngg' );
|
||||
|
||||
if ( $process->is_valid() && $process->get_data()->is_optimized() ) {
|
||||
$process->get_data()->delete_optimization_data();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->call_parent( 'recover_image', $image );
|
||||
}
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG\Optimization\Data;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Optimization data class for the custom folders.
|
||||
* This class constructor accepts:
|
||||
* - A NGG image ID (int).
|
||||
* - A \nggImage object.
|
||||
* - A \nggdb object.
|
||||
* - An anonym object containing a pid property (and everything else).
|
||||
* - A \Imagify\Media\MediaInterface object.
|
||||
*
|
||||
* @since 1.9
|
||||
* @see Imagify\ThirdParty\NGG\Media\NGG
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class NGG extends \Imagify\Optimization\Data\AbstractData {
|
||||
use \Imagify\Traits\MediaRowTrait;
|
||||
|
||||
/**
|
||||
* The attachment SQL DB class.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $db_class_name = '\\Imagify\\ThirdParty\\NGG\\DB';
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param mixed $id An ID, or whatever type the "Media" class constructor accepts.
|
||||
*/
|
||||
public function __construct( $id ) {
|
||||
parent::__construct( $id );
|
||||
|
||||
if ( ! $this->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is required by MediaRowTrait.
|
||||
$this->id = $this->get_media()->get_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the whole media optimization data.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array The data. See parent method for details.
|
||||
*/
|
||||
public function get_optimization_data() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return $this->default_optimization_data;
|
||||
}
|
||||
|
||||
$row = array_merge( $this->get_row_db_instance()->get_column_defaults(), $this->get_row() );
|
||||
$data = $this->default_optimization_data;
|
||||
|
||||
$data['status'] = $row['status'];
|
||||
$data['level'] = $row['optimization_level'];
|
||||
$data['level'] = is_numeric( $data['level'] ) ? (int) $data['level'] : false;
|
||||
$data['stats'] = [
|
||||
'original_size' => 0,
|
||||
'optimized_size' => 0,
|
||||
'percent' => 0,
|
||||
];
|
||||
|
||||
if ( ! empty( $row['data']['sizes'] ) && is_array( $row['data']['sizes'] ) ) {
|
||||
$data['sizes'] = $row['data']['sizes'];
|
||||
$data['sizes'] = array_filter( $data['sizes'], 'is_array' );
|
||||
}
|
||||
|
||||
if ( empty( $data['sizes']['full'] ) ) {
|
||||
if ( 'success' === $row['status'] ) {
|
||||
$data['sizes']['full'] = [
|
||||
'success' => true,
|
||||
'original_size' => 0,
|
||||
'optimized_size' => 0,
|
||||
'percent' => 0,
|
||||
];
|
||||
} elseif ( ! empty( $row['status'] ) ) {
|
||||
$data['sizes']['full'] = [
|
||||
'success' => false,
|
||||
'error' => '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $data['sizes'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ( $data['sizes'] as $size_data ) {
|
||||
// Cast.
|
||||
if ( isset( $size_data['original_size'] ) ) {
|
||||
$size_data['original_size'] = (int) $size_data['original_size'];
|
||||
}
|
||||
if ( isset( $size_data['optimized_size'] ) ) {
|
||||
$size_data['optimized_size'] = (int) $size_data['optimized_size'];
|
||||
}
|
||||
if ( isset( $size_data['percent'] ) ) {
|
||||
$size_data['percent'] = round( $size_data['percent'], 2 );
|
||||
}
|
||||
// Stats.
|
||||
if ( ! empty( $size_data['original_size'] ) && ! empty( $size_data['optimized_size'] ) ) {
|
||||
$data['stats']['original_size'] += $size_data['original_size'];
|
||||
$data['stats']['optimized_size'] += $size_data['optimized_size'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $data['stats']['original_size'] && $data['stats']['optimized_size'] ) {
|
||||
$data['stats']['percent'] = $data['stats']['original_size'] - $data['stats']['optimized_size'];
|
||||
$data['stats']['percent'] = round( $data['stats']['percent'] / $data['stats']['original_size'] * 100, 2 );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the optimization data, level, and status for a size.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $size The size name.
|
||||
* @param array $data The optimization data. See parent method for details.
|
||||
*/
|
||||
public function update_size_optimization_data( $size, array $data ) {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old_data = array_merge( $this->get_reset_data(), $this->get_row() );
|
||||
|
||||
$old_data['data']['sizes'] = ! empty( $old_data['data']['sizes'] ) && is_array( $old_data['data']['sizes'] ) ? $old_data['data']['sizes'] : [];
|
||||
|
||||
if ( 'full' === $size ) {
|
||||
/**
|
||||
* Original file.
|
||||
*/
|
||||
$old_data['optimization_level'] = $data['level'];
|
||||
$old_data['status'] = $data['status'];
|
||||
}
|
||||
|
||||
if ( ! $data['success'] ) {
|
||||
/**
|
||||
* Error.
|
||||
*/
|
||||
$old_data['data']['sizes'][ $size ] = [
|
||||
'success' => false,
|
||||
'error' => $data['error'],
|
||||
];
|
||||
} else {
|
||||
/**
|
||||
* Success.
|
||||
*/
|
||||
$old_data['data']['sizes'][ $size ] = [
|
||||
'success' => true,
|
||||
'original_size' => $data['original_size'],
|
||||
'optimized_size' => $data['optimized_size'],
|
||||
'percent' => round( ( $data['original_size'] - $data['optimized_size'] ) / $data['original_size'] * 100, 2 ),
|
||||
];
|
||||
}
|
||||
|
||||
$this->update_row( $old_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the media optimization data, level, and status.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function delete_optimization_data() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->delete_row();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the optimization data for the given sizes.
|
||||
* If all sizes are removed, all optimization data is deleted.
|
||||
* Status and level are not modified nor removed if the "full" size is removed. This leaves the media in a Schrödinger state.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $sizes A list of sizes to remove.
|
||||
*/
|
||||
public function delete_sizes_optimization_data( array $sizes ) {
|
||||
if ( ! $sizes || ! $this->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = array_merge( $this->get_reset_data(), $this->get_row() );
|
||||
|
||||
$data['data']['sizes'] = ! empty( $data['data']['sizes'] ) && is_array( $data['data']['sizes'] ) ? $data['data']['sizes'] : [];
|
||||
|
||||
if ( ! $data['data']['sizes'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$remaining_sizes_data = array_diff_key( $data['data']['sizes'], array_flip( $sizes ) );
|
||||
|
||||
if ( ! $remaining_sizes_data ) {
|
||||
// All sizes have been removed: delete everything.
|
||||
$this->delete_optimization_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( count( $remaining_sizes_data ) === count( $data['data']['sizes'] ) ) {
|
||||
// Nothing has been removed.
|
||||
return;
|
||||
}
|
||||
|
||||
$data['data']['sizes'] = $remaining_sizes_data;
|
||||
|
||||
$this->update_row( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default values used to reset optimization data.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array {
|
||||
* The default values related to the optimization.
|
||||
*
|
||||
* @type string $optimization_level The optimization level.
|
||||
* @type string $status The status: success, already_optimized, error.
|
||||
* @type array $data Data related to the thumbnails.
|
||||
* }
|
||||
*/
|
||||
protected function get_reset_data() {
|
||||
$db_instance = $this->get_row_db_instance();
|
||||
$primary_key = $db_instance->get_primary_key();
|
||||
$column_defaults = $db_instance->get_column_defaults();
|
||||
|
||||
return array_diff_key( $column_defaults, [
|
||||
'data_id' => 0,
|
||||
$primary_key => 0,
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the row.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $data The data to update.
|
||||
*/
|
||||
public function update_row( $data ) {
|
||||
if ( ! $this->db_class_name || $this->id <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$primary_key = $this->get_row_db_instance()->get_primary_key();
|
||||
// This is needed in case the row doesn't exist yet.
|
||||
$data[ $primary_key ] = $this->id;
|
||||
|
||||
$this->get_row_db_instance()->update( $this->id, $data );
|
||||
|
||||
$this->reset_row_cache();
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\NGG\Optimization\Process;
|
||||
|
||||
use Imagify\Optimization\File;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Optimization class for NextGen Gallery.
|
||||
* This class constructor accepts:
|
||||
* - A NGG image ID (int).
|
||||
* - A \nggImage object.
|
||||
* - A \nggdb object.
|
||||
* - An anonym object containing a pid property (and everything else).
|
||||
* - A \Imagify\Media\MediaInterface object.
|
||||
*
|
||||
* @since 1.9
|
||||
* @see Imagify\ThirdParty\NGG\Media\NGG
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class NGG extends \Imagify\Optimization\Process\AbstractProcess {
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** MISSING THUMBNAILS ====================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the sizes for this media that have not get through optimization.
|
||||
* Since this context doesn't handle this feature, this will always return an empty array, unless an error is triggered.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return array|WP_Error A WP_Error object on failure. An empty array on success: this context has no thumbnails.
|
||||
* The tests are kept for consistency.
|
||||
*/
|
||||
public function get_missing_sizes() {
|
||||
// The media must have been optimized once and have a backup.
|
||||
if ( ! $this->is_valid() ) {
|
||||
return new \WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$media = $this->get_media();
|
||||
|
||||
if ( ! $media->is_supported() ) {
|
||||
return new \WP_Error( 'media_not_supported', __( 'This media is not supported.', 'imagify' ) );
|
||||
}
|
||||
|
||||
$data = $this->get_data();
|
||||
|
||||
if ( ! $data->is_optimized() ) {
|
||||
return new \WP_Error( 'media_not_optimized', __( 'This media is not optimized yet.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( ! $media->has_backup() ) {
|
||||
return new \WP_Error( 'no_backup', __( 'This file has no backup file.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( ! $media->is_image() ) {
|
||||
return new \WP_Error( 'media_not_an_image', __( 'This media is not an image.', 'imagify' ) );
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize missing thumbnail sizes.
|
||||
* Since this context doesn't handle this feature, this will always return a \WP_Error object.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
|
||||
*/
|
||||
public function optimize_missing_thumbnails() {
|
||||
if ( ! $this->is_valid() ) {
|
||||
return new \WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
|
||||
}
|
||||
|
||||
if ( ! $this->get_media()->is_supported() ) {
|
||||
return new \WP_Error( 'media_not_supported', __( 'This media is not supported.', 'imagify' ) );
|
||||
}
|
||||
|
||||
return new \WP_Error( 'no_sizes', __( 'No thumbnails seem to be missing.', 'imagify' ) );
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_filter( 'imagify_bulk_page_types', 'imagify_ngg_bulk_page_types' );
|
||||
/**
|
||||
* Filter the types to display in the bulk optimization page.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $types The folder types displayed on the page. If a folder type is "library", the context should be suffixed after a pipe character. They are passed as array keys.
|
||||
* @return array
|
||||
*/
|
||||
function imagify_ngg_bulk_page_types( $types ) {
|
||||
if ( ! empty( $_GET['page'] ) && imagify_get_ngg_bulk_screen_slug() === $_GET['page'] ) { // WPCS: CSRF ok.
|
||||
$types['library|ngg'] = 1;
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
add_filter( 'imagify_bulk_stats', 'imagify_ngg_bulk_stats', 10, 2 );
|
||||
/**
|
||||
* Filter the generic stats used in the bulk optimization page.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $data The data.
|
||||
* @param array $types The folder types. They are passed as array keys.
|
||||
* @return array
|
||||
*/
|
||||
function imagify_ngg_bulk_stats( $data, $types ) {
|
||||
if ( ! isset( $types['library|ngg'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
add_filter( 'imagify_count_saving_data', 'imagify_ngg_count_saving_data', 8 );
|
||||
$total_saving_data = imagify_count_saving_data();
|
||||
remove_filter( 'imagify_count_saving_data', 'imagify_ngg_count_saving_data', 8 );
|
||||
|
||||
// Global chart.
|
||||
$data['total_attachments'] += imagify_ngg_count_attachments();
|
||||
$data['unoptimized_attachments'] += imagify_ngg_count_unoptimized_attachments();
|
||||
$data['optimized_attachments'] += imagify_ngg_count_optimized_attachments();
|
||||
$data['errors_attachments'] += imagify_ngg_count_error_attachments();
|
||||
// Stats block.
|
||||
$data['already_optimized_attachments'] += $total_saving_data['count'];
|
||||
$data['original_human'] += $total_saving_data['original_size'];
|
||||
$data['optimized_human'] += $total_saving_data['optimized_size'];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
add_filter( 'imagify_bulk_page_data', 'imagify_ngg_bulk_page_data', 10, 2 );
|
||||
/**
|
||||
* Filter the data to use on the bulk optimization page.
|
||||
*
|
||||
* @since 1.7
|
||||
* @since 1.7.1 Added the $types parameter.
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $data The data to use.
|
||||
* @param array $types The folder types displayed on the page. They are passed as array keys.
|
||||
* @return array
|
||||
*/
|
||||
function imagify_ngg_bulk_page_data( $data, $types ) {
|
||||
if ( ! isset( $types['library|ngg'] ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Limits.
|
||||
$data['unoptimized_attachment_limit'] += imagify_get_unoptimized_attachment_limit();
|
||||
// Group.
|
||||
$data['groups']['ngg'] = array(
|
||||
/**
|
||||
* The group_id corresponds to the file names like 'part-bulk-optimization-results-row-{$group_id}'.
|
||||
* It is also used in get_imagify_localize_script_translations().
|
||||
*/
|
||||
'group_id' => 'library',
|
||||
'context' => 'ngg',
|
||||
'title' => __( 'NextGen Galleries', 'imagify' ),
|
||||
/* translators: 1 is the opening of a link, 2 is the closing of this link. */
|
||||
'footer' => sprintf( __( 'You can also re-optimize your images more finely directly in each %1$sgallery%2$s.', 'imagify' ), '<a href="' . esc_url( admin_url( 'admin.php?page=nggallery-manage-gallery' ) ) . '">', '</a>' ),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
add_filter( 'imagify_optimization_errors_url', 'imagify_ngg_optimization_errors_url', 10, 2 );
|
||||
/**
|
||||
* Provide a URL to a page displaying optimization errors for the NGG context.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $url The URL.
|
||||
* @param string $context The context.
|
||||
* @return string
|
||||
*/
|
||||
function imagify_ngg_optimization_errors_url( $url, $context ) {
|
||||
if ( 'ngg' === $context ) {
|
||||
return admin_url( 'admin.php?page=nggallery-manage-gallery' );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_action( 'imagify_assets_enqueued', '_imagify_ngg_admin_print_styles' );
|
||||
/**
|
||||
* Add some CSS and JS for NGG compatibility.
|
||||
*
|
||||
* @since 1.5
|
||||
* @since 1.6.10 Use the new class Imagify_Assets.
|
||||
* @author Jonathan Buttigieg
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
function _imagify_ngg_admin_print_styles() {
|
||||
$assets = Imagify_Assets::get_instance();
|
||||
|
||||
/**
|
||||
* Manage Gallery Images.
|
||||
*/
|
||||
if ( imagify_is_screen( 'nggallery-manage-images' ) || isset( $_GET['gid'] ) && ! empty( $_GET['pid'] ) && imagify_is_screen( 'nggallery-manage-gallery' ) ) { // WPCS: CSRF ok.
|
||||
$assets->enqueue_style( 'admin' )->enqueue_script( 'library' );
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* NGG Bulk Optimization.
|
||||
*/
|
||||
$bulk_screen_id = imagify_get_ngg_bulk_screen_id();
|
||||
|
||||
if ( ! imagify_is_screen( $bulk_screen_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$assets->remove_deferred_localization( 'bulk', 'imagifyBulk' );
|
||||
|
||||
$l10n = $assets->get_localization_data( 'bulk', [
|
||||
'bufferSizes' => [
|
||||
'ngg' => 4,
|
||||
],
|
||||
] );
|
||||
|
||||
/** This filter is documented in inc/functions/i18n.php */
|
||||
$l10n['bufferSizes'] = apply_filters( 'imagify_bulk_buffer_sizes', $l10n['bufferSizes'] );
|
||||
|
||||
$assets->enqueue_assets( [ 'pricing-modal', 'bulk' ] )->localize( 'imagifyBulk', $l10n );
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_filter( 'ngg_manage_images_number_of_columns', '_imagify_ngg_manage_images_number_of_columns' );
|
||||
/**
|
||||
* Add "Imagify" column in admin.php?page=nggallery-manage-gallery.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param int $count Number of columns.
|
||||
* @return int Incremented number of columns.
|
||||
*/
|
||||
function _imagify_ngg_manage_images_number_of_columns( $count ) {
|
||||
$count++;
|
||||
add_filter( 'ngg_manage_images_column_' . $count . '_header', '_imagify_ngg_manage_media_columns' );
|
||||
add_filter( 'ngg_manage_images_column_' . $count . '_content', '_imagify_ngg_manage_media_custom_column', 10, 2 );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column title.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function _imagify_ngg_manage_media_columns() {
|
||||
return 'Imagify';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column content.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param string $output The column content.
|
||||
* @param object $image An NGG Image object.
|
||||
* @return string
|
||||
*/
|
||||
function _imagify_ngg_manage_media_custom_column( $output, $image ) {
|
||||
$process = imagify_get_optimization_process( $image, 'ngg' );
|
||||
|
||||
return get_imagify_media_column_content( $process );
|
||||
}
|
||||
|
||||
add_filter( 'imagify_display_missing_thumbnails_link', '_imagify_ngg_hide_missing_thumbnails_link', 10, 3 );
|
||||
/**
|
||||
* Hide the "Optimize missing thumbnails" link.
|
||||
*
|
||||
* @since 1.6.10
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $display True to display the link. False to not display it.
|
||||
* @param object $attachment The attachement object.
|
||||
* @param string $context The context.
|
||||
* @return bool
|
||||
*/
|
||||
function _imagify_ngg_hide_missing_thumbnails_link( $display, $attachment, $context ) {
|
||||
return 'ngg' === $context ? false : $display;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_action( 'admin_menu', '_imagify_ngg_bulk_optimization_menu' );
|
||||
/**
|
||||
* Add submenu in menu "Media"
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*/
|
||||
function _imagify_ngg_bulk_optimization_menu() {
|
||||
if ( ! defined( 'NGGFOLDER' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$capacity = imagify_get_context( 'ngg' )->get_capacity( 'bulk-optimize' );
|
||||
|
||||
add_submenu_page( NGGFOLDER, __( 'Bulk Optimization', 'imagify' ), __( 'Bulk Optimization', 'imagify' ), $capacity, imagify_get_ngg_bulk_screen_slug(), '_imagify_display_bulk_page' );
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
<?php
|
||||
use \Imagify\Optimization\File;
|
||||
use \Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
add_action( 'ngg_after_new_images_added', '_imagify_ngg_optimize_attachment', IMAGIFY_INT_MAX, 2 );
|
||||
/**
|
||||
* Auto-optimize when a new attachment is added to the database (NGG plugin's table), except for images imported from the library.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param int $gallery_id A Gallery ID.
|
||||
* @param array $image_ids An array of Ids or objects. Ids which are sucessfully added.
|
||||
*/
|
||||
function _imagify_ngg_optimize_attachment( $gallery_id, $image_ids ) {
|
||||
|
||||
if ( ! Imagify_Requirements::is_api_key_valid() || ! get_imagify_option( 'auto_optimize' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$is_maybe_library_import = ! empty( $_POST['action'] ) && 'import_media_library' === $_POST['action'] && ! empty( $_POST['attachment_ids'] ) && is_array( $_POST['attachment_ids'] ); // WPCS: CSRF ok.
|
||||
|
||||
if ( $is_maybe_library_import && ! empty( $_POST['nextgen_upload_image_sec'] ) ) { // WPCS: CSRF ok.
|
||||
/**
|
||||
* The images are imported from the library.
|
||||
* In this case, those images are dealt with in _imagify_ngg_media_library_imported_image_data().
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $is_maybe_library_import && ( ! empty( $_POST['gallery_id'] ) || ! empty( $_POST['gallery_name'] ) ) ) { // WPCS: CSRF ok.
|
||||
/**
|
||||
* Same thing but for NGG 2.0 probably.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $image_ids as $image ) {
|
||||
if ( is_numeric( $image ) ) {
|
||||
$image_id = (int) $image;
|
||||
} elseif ( is_object( $image ) && ! empty( $image->pid ) ) {
|
||||
$image_id = (int) $image->pid;
|
||||
} else {
|
||||
$image_id = 0;
|
||||
}
|
||||
|
||||
if ( ! $image_id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to prevent automatic optimization for a specific NGG gallery image.
|
||||
*
|
||||
* @since 1.6.12
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $optimize True to optimize, false otherwise.
|
||||
* @param int $image_id Image ID.
|
||||
* @param int $gallery_id Gallery ID.
|
||||
*/
|
||||
$optimize = apply_filters( 'imagify_auto_optimize_ngg_gallery_image', true, $image_id, $gallery_id );
|
||||
|
||||
if ( ! $optimize ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$process = imagify_get_optimization_process( $image, 'ngg' );
|
||||
|
||||
if ( ! $process->is_valid() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $process->get_data()->get_optimization_status() ) {
|
||||
// Optimization already attempted.
|
||||
continue;
|
||||
}
|
||||
|
||||
$process->optimize();
|
||||
}
|
||||
}
|
||||
|
||||
add_filter( 'ngg_medialibrary_imported_image', '_imagify_ngg_media_library_imported_image_data', 10, 2 );
|
||||
/**
|
||||
* Import Imagify data from a WordPress image to a new NGG image, and optimize the thumbnails.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param object $image A NGG image object.
|
||||
* @param object $attachment An attachment object.
|
||||
* @return object
|
||||
*/
|
||||
function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
|
||||
$wp_process = imagify_get_optimization_process( $attachment->ID, 'wp' );
|
||||
|
||||
if ( ! $wp_process->is_valid() || ! $wp_process->get_media()->is_supported() ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$wp_data = $wp_process->get_data();
|
||||
|
||||
if ( ! $wp_data->is_optimized() ) {
|
||||
// The main image is not optimized.
|
||||
return $image;
|
||||
}
|
||||
|
||||
// Copy the full size data.
|
||||
$wp_full_size_data = $wp_data->get_size_data();
|
||||
$optimization_level = $wp_data->get_optimization_level();
|
||||
|
||||
NGG\DB::get_instance()->update( $image->pid, [
|
||||
'pid' => $image->pid,
|
||||
'optimization_level' => $optimization_level,
|
||||
'status' => $wp_data->get_optimization_status(),
|
||||
'data' => [
|
||||
'sizes' => [
|
||||
'full' => $wp_full_size_data,
|
||||
],
|
||||
'stats' => [
|
||||
'original_size' => $wp_full_size_data['original_size'],
|
||||
'optimized_size' => $wp_full_size_data['optimized_size'],
|
||||
'percent' => $wp_full_size_data['percent'],
|
||||
],
|
||||
],
|
||||
] );
|
||||
|
||||
$ngg_process = imagify_get_optimization_process( $image->pid, 'ngg' );
|
||||
|
||||
if ( ! $ngg_process->is_valid() ) {
|
||||
// WTF.
|
||||
return $image;
|
||||
}
|
||||
|
||||
// Copy the backup file (we don't want to backup the optimized file if it can be avoided).
|
||||
$ngg_media = $ngg_process->get_media();
|
||||
$wp_media = $wp_process->get_media();
|
||||
$wp_backup_path = $wp_media->get_backup_path();
|
||||
$filesystem = imagify_get_filesystem();
|
||||
$backup_copied = false;
|
||||
|
||||
if ( $wp_backup_path ) {
|
||||
$ngg_backup_path = $ngg_media->get_raw_backup_path();
|
||||
$backup_copied = $filesystem->copy( $wp_backup_path, $ngg_backup_path, true );
|
||||
|
||||
if ( $backup_copied ) {
|
||||
$filesystem->chmod_file( $ngg_backup_path );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Next-gen for the full size.
|
||||
* Look for an existing copy locally:
|
||||
* - if it exists, copy it (and its optimization data),
|
||||
* - if not, add it to the optimization queue.
|
||||
*/
|
||||
$add_full_nextgen = $wp_media->is_image();
|
||||
|
||||
if ( $add_full_nextgen ) {
|
||||
$formats = [
|
||||
'avif' => $wp_process::AVIF_SUFFIX,
|
||||
'webp' => $wp_process::WEBP_SUFFIX,
|
||||
];
|
||||
|
||||
foreach ( $formats as $extension => $suffix ) {
|
||||
$wp_full_path_nextgen = false;
|
||||
$nextgen_size_name = 'full' . $suffix;
|
||||
$wp_nextgen_data = $wp_data->get_size_data( $nextgen_size_name );
|
||||
|
||||
// Get the path to the next-gen image if it exists.
|
||||
$wp_full_path_nextgen = $wp_process->get_fullsize_file()->get_path_to_nextgen( $extension );
|
||||
|
||||
if ( $wp_full_path_nextgen && ! $filesystem->exists( $wp_full_path_nextgen ) ) {
|
||||
$wp_full_path_nextgen = false;
|
||||
}
|
||||
|
||||
if ( $wp_full_path_nextgen ) {
|
||||
// We know we have a next-gen version. Make sure we have the right data.
|
||||
$wp_nextgen_data['success'] = true;
|
||||
|
||||
if ( empty( $wp_nextgen_data['original_size'] ) ) {
|
||||
// The next-gen data is missing.
|
||||
$full_size_weight = $wp_full_size_data['original_size'];
|
||||
|
||||
if ( ! $full_size_weight && $wp_backup_path ) {
|
||||
// For some reason we don't have the original file weight, but we can get it from the backup file.
|
||||
$full_size_weight = $filesystem->size( $wp_backup_path );
|
||||
|
||||
if ( $full_size_weight ) {
|
||||
$wp_nextgen_data['original_size'] = $full_size_weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $wp_nextgen_data['original_size'] ) && empty( $wp_nextgen_data['optimized_size'] ) ) {
|
||||
// The next-gen file size.
|
||||
$wp_nextgen_data['optimized_size'] = $filesystem->size( $wp_full_path_nextgen );
|
||||
}
|
||||
|
||||
if ( empty( $wp_nextgen_data['original_size'] ) || empty( $wp_nextgen_data['optimized_size'] ) ) {
|
||||
// We must have both original and optimized sizes.
|
||||
$wp_nextgen_data = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $wp_full_path_nextgen && $wp_nextgen_data ) {
|
||||
// We have the file and the data.
|
||||
// Copy the file.
|
||||
$ngg_full_file = new File( $ngg_media->get_raw_fullsize_path() );
|
||||
$ngg_full_path_nextgen = $ngg_full_file->get_path_to_nextgen( $extension ); // Destination.
|
||||
|
||||
if ( $ngg_full_path_nextgen ) {
|
||||
$copied = $filesystem->copy( $wp_full_path_nextgen, $ngg_full_path_nextgen, true );
|
||||
|
||||
if ( $copied ) {
|
||||
// Success.
|
||||
$filesystem->chmod_file( $ngg_full_path_nextgen );
|
||||
$add_full_nextgen = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $add_full_nextgen ) {
|
||||
// The next-gen file has been successfully copied: now, copy the data.
|
||||
$ngg_process->get_data()->update_size_optimization_data( $nextgen_size_name, $wp_nextgen_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optimize thumbnails.
|
||||
$sizes = $ngg_media->get_media_files();
|
||||
unset( $sizes['full'] );
|
||||
|
||||
if ( $add_full_nextgen ) {
|
||||
// We could not use a local next-gen copy: ask for a new one.
|
||||
|
||||
$formats = imagify_nextgen_images_formats();
|
||||
|
||||
foreach ( $formats as $format ) {
|
||||
if ( 'webp' === $format ) {
|
||||
$suffix = $wp_process::WEBP_SUFFIX;
|
||||
} elseif ( 'avif' === $format ) {
|
||||
$suffix = $wp_process::AVIF_SUFFIX;
|
||||
}
|
||||
|
||||
$sizes[ 'full' . $suffix ] = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $sizes ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$args = [
|
||||
'hook_suffix' => 'optimize_imported_images',
|
||||
];
|
||||
|
||||
$ngg_process->optimize_sizes( array_keys( $sizes ), $optimization_level, $args );
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
add_action( 'ngg_generated_image', 'imagify_ngg_maybe_add_dynamic_thumbnail_to_background_process', IMAGIFY_INT_MAX, 2 );
|
||||
/**
|
||||
* Add a dynamically generated thumbnail to the background process queue.
|
||||
* Note that this won’t work when images are imported (from WP Library or uploaded), since they are already being processed, and locked.
|
||||
*
|
||||
* @since 1.8
|
||||
* @since 1.9 Doesn't use the class Imagify_NGG_Dynamic_Thumbnails_Background_Process anymore.
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param object $image A NGG image object.
|
||||
* @param string $size The thumbnail size name.
|
||||
*/
|
||||
function imagify_ngg_maybe_add_dynamic_thumbnail_to_background_process( $image, $size ) {
|
||||
NGG\DynamicThumbnails::get_instance()->push_to_queue( $image, $size );
|
||||
}
|
||||
|
||||
add_action( 'ngg_delete_picture', 'imagify_ngg_cleanup_after_media_deletion', 10, 2 );
|
||||
/**
|
||||
* Delete everything when a NGG image is deleted.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $image_id The image ID.
|
||||
* @param object $image A NGG object.
|
||||
*/
|
||||
function imagify_ngg_cleanup_after_media_deletion( $image_id, $image ) {
|
||||
$process = imagify_get_optimization_process( $image, 'ngg' );
|
||||
|
||||
if ( ! $process->is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger a common hook.
|
||||
imagify_trigger_delete_media_hook( $process );
|
||||
|
||||
/**
|
||||
* The backup file has already been deleted by NGG.
|
||||
* Delete the next-gen versions and the optimization data.
|
||||
*/
|
||||
$process->delete_nextgen_files();
|
||||
|
||||
$process->get_data()->delete_optimization_data();
|
||||
}
|
||||
|
||||
add_filter( 'imagify_crop_thumbnail', 'imagify_ngg_should_crop_thumbnail', 10, 4 );
|
||||
/**
|
||||
* In case of a dynamic thumbnail, tell if the image must be croped or resized.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $crop True to crop the thumbnail, false to resize. Null by default.
|
||||
* @param string $size Name of the thumbnail size.
|
||||
* @param array $size_data Data of the thumbnail being processed. Contains at least 'width', 'height', and 'path'.
|
||||
* @param MediaInterface $media The MediaInterface instance corresponding to the image being processed.
|
||||
* @return bool
|
||||
*/
|
||||
function imagify_ngg_should_crop_thumbnail( $crop, $size, $size_data, $media ) {
|
||||
static $data_per_media = [];
|
||||
static $storage_per_media = [];
|
||||
|
||||
if ( 'ngg' !== $media->get_context() ) {
|
||||
return $crop;
|
||||
}
|
||||
|
||||
$media_id = $media->get_id();
|
||||
|
||||
if ( ! isset( $data_per_media[ $media_id ] ) ) {
|
||||
$image = \nggdb::find_image( $media_id );
|
||||
|
||||
if ( ! empty( $image->_ngiw ) ) {
|
||||
$storage_per_media[ $media_id ] = $image->_ngiw->get_storage()->object;
|
||||
} else {
|
||||
$storage_per_media[ $media_id ] = \C_Gallery_Storage::get_instance()->object;
|
||||
}
|
||||
|
||||
$data_per_media[ $media_id ] = $storage_per_media[ $media_id ]->_image_mapper->find( $media_id ); // stdClass Object.
|
||||
}
|
||||
|
||||
$params = $storage_per_media[ $media_id ]->get_image_size_params( $data_per_media[ $media_id ], $size );
|
||||
|
||||
return ! empty( $params['crop'] );
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
<?php
|
||||
use \Imagify\ThirdParty\NGG\DB;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Count number of attachments.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int The number of attachments.
|
||||
*/
|
||||
function imagify_ngg_count_attachments() {
|
||||
global $wpdb;
|
||||
static $count;
|
||||
|
||||
if ( isset( $count ) ) {
|
||||
return $count;
|
||||
}
|
||||
|
||||
$table_name = $wpdb->prefix . 'ngg_pictures';
|
||||
$count = (int) $wpdb->get_var( "SELECT COUNT($table_name.pid) FROM $table_name" ); // WPCS: unprepared SQL ok.
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of optimized attachments with an error.
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int The number of attachments.
|
||||
*/
|
||||
function imagify_ngg_count_error_attachments() {
|
||||
static $count;
|
||||
|
||||
if ( isset( $count ) ) {
|
||||
return $count;
|
||||
}
|
||||
|
||||
$ngg_db = DB::get_instance();
|
||||
$key = $ngg_db->get_primary_key();
|
||||
$count = (int) $ngg_db->get_var_by( "COUNT($key)", 'status', 'error' );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of optimized attachments (by Imagify or an other tool before).
|
||||
*
|
||||
* @since 1.5
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int The number of attachments.
|
||||
*/
|
||||
function imagify_ngg_count_optimized_attachments() {
|
||||
static $count;
|
||||
|
||||
if ( isset( $count ) ) {
|
||||
return $count;
|
||||
}
|
||||
|
||||
$ngg_db = DB::get_instance();
|
||||
$key = $ngg_db->get_primary_key();
|
||||
$count = (int) $ngg_db->get_var_in( "COUNT($key)", 'status', array( 'success', 'already_optimized' ) );
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of unoptimized attachments.
|
||||
*
|
||||
* @since 1.0
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int The number of attachments.
|
||||
*/
|
||||
function imagify_ngg_count_unoptimized_attachments() {
|
||||
return imagify_ngg_count_attachments() - imagify_ngg_count_optimized_attachments() - imagify_ngg_count_error_attachments();
|
||||
}
|
||||
|
||||
/**
|
||||
* Count percent of optimized attachments.
|
||||
*
|
||||
* @since 1.0
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @return int The percent of optimized attachments.
|
||||
*/
|
||||
function imagify_ngg_percent_optimized_attachments() {
|
||||
$total_attachments = imagify_ngg_count_attachments();
|
||||
$total_optimized_attachments = imagify_ngg_count_optimized_attachments();
|
||||
|
||||
if ( ! $total_attachments || ! $total_optimized_attachments ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return min( round( 100 * $total_optimized_attachments / $total_attachments ), 100 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Count percent, original & optimized size of all images optimized by Imagify.
|
||||
*
|
||||
* @since 1.5
|
||||
* @since 1.6.7 Revamped to handle huge libraries.
|
||||
* @author Jonathan Buttigieg
|
||||
*
|
||||
* @param bool|array $attachments An array containing the keys 'count', 'original_size', and 'optimized_size', or an array of attachments (back compat', deprecated), or false.
|
||||
* @return array An array containing the keys 'count', 'original_size', and 'optimized_size'.
|
||||
*/
|
||||
function imagify_ngg_count_saving_data( $attachments ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_array( $attachments ) ) {
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query to get all optimized NGG attachments.
|
||||
* 3rd party will be able to override the result.
|
||||
*
|
||||
* @since 1.6.7
|
||||
*
|
||||
* @param bool|array $attachments An array containing the keys ('count', 'original_size', and 'optimized_size'), or false.
|
||||
*/
|
||||
$attachments = apply_filters( 'imagify_ngg_count_saving_data', false );
|
||||
|
||||
if ( is_array( $attachments ) ) {
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
$original_size = 0;
|
||||
$optimized_size = 0;
|
||||
$count = 0;
|
||||
|
||||
/** This filter is documented in /inc/functions/admin-stats.php */
|
||||
$limit = apply_filters( 'imagify_count_saving_data_limit', 15000 );
|
||||
$limit = absint( $limit );
|
||||
$offset = 0;
|
||||
$query = "
|
||||
SELECT data
|
||||
FROM $wpdb->ngg_imagify_data
|
||||
WHERE status = 'success'
|
||||
LIMIT %d, %d";
|
||||
|
||||
$attachments = $wpdb->get_col( $wpdb->prepare( $query, $offset, $limit ) ); // WPCS: unprepared SQL ok.
|
||||
$wpdb->flush();
|
||||
|
||||
while ( $attachments ) {
|
||||
$attachments = array_map( 'maybe_unserialize', $attachments );
|
||||
|
||||
foreach ( $attachments as $attachment_data ) {
|
||||
if ( ! $attachment_data ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++$count;
|
||||
$original_data = $attachment_data['sizes']['full'];
|
||||
|
||||
// Increment the original sizes.
|
||||
$original_size += $original_data['original_size'] ? $original_data['original_size'] : 0;
|
||||
$optimized_size += $original_data['optimized_size'] ? $original_data['optimized_size'] : 0;
|
||||
|
||||
unset( $attachment_data['sizes']['full'], $original_data );
|
||||
|
||||
// Increment the thumbnails sizes.
|
||||
foreach ( $attachment_data['sizes'] as $size_data ) {
|
||||
if ( ! empty( $size_data['success'] ) ) {
|
||||
$original_size += $size_data['original_size'] ? $size_data['original_size'] : 0;
|
||||
$optimized_size += $size_data['optimized_size'] ? $size_data['optimized_size'] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
unset( $size_data );
|
||||
}
|
||||
|
||||
unset( $attachment_data );
|
||||
|
||||
if ( count( $attachments ) === $limit ) {
|
||||
// Unless we are really unlucky, we still have attachments to fetch.
|
||||
$offset += $limit;
|
||||
|
||||
$attachments = $wpdb->get_col( $wpdb->prepare( $query, $offset, $limit ) ); // WPCS: unprepared SQL ok.
|
||||
$wpdb->flush();
|
||||
} else {
|
||||
// Save one request, don't go back to the beginning of the loop.
|
||||
$attachments = array();
|
||||
}
|
||||
} // End while().
|
||||
|
||||
return array(
|
||||
'count' => $count,
|
||||
'original_size' => $original_size,
|
||||
'optimized_size' => $optimized_size,
|
||||
);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Get the backup path of a specific attachement.
|
||||
*
|
||||
* @since 1.6.8
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $file_path The file path.
|
||||
* @return string|bool The backup path. False on failure.
|
||||
*/
|
||||
function get_imagify_ngg_attachment_backup_path( $file_path ) {
|
||||
$file_path = wp_normalize_path( (string) $file_path );
|
||||
|
||||
if ( ! $file_path ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $file_path . '_backup';
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Get NGG Bulk Optimization screen ID.
|
||||
* Because WP nonsense, the screen ID depends on the menu title, which is translated. So the screen ID changes depending on the administration locale.
|
||||
*
|
||||
* @since 1.6.13
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function imagify_get_ngg_bulk_screen_id() {
|
||||
global $admin_page_hooks;
|
||||
|
||||
$ngg_menu_slug = defined( 'NGGFOLDER' ) ? plugin_basename( NGGFOLDER ) : 'nextgen-gallery';
|
||||
$ngg_menu_slug = isset( $admin_page_hooks[ $ngg_menu_slug ] ) ? $admin_page_hooks[ $ngg_menu_slug ] : 'gallery';
|
||||
|
||||
return $ngg_menu_slug . '_page_' . imagify_get_ngg_bulk_screen_slug();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get NGG Bulk Optimization screen slug.
|
||||
*
|
||||
* @since 1.7
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function imagify_get_ngg_bulk_screen_slug() {
|
||||
return IMAGIFY_SLUG . '-ngg-bulk-optimization';
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
use Imagify\ThirdParty\NGG;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( ! class_exists( 'C_NextGEN_Bootstrap' ) || ! class_exists( 'Mixin' ) || ! get_site_option( 'ngg_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
class_alias( '\\Imagify\\ThirdParty\\NGG\\Main', '\\Imagify_NGG' );
|
||||
class_alias( '\\Imagify\\ThirdParty\\NGG\\DB', '\\Imagify_NGG_DB' );
|
||||
class_alias( '\\Imagify\\ThirdParty\\NGG\\NGGStorage', '\\Imagify_NGG_Storage' );
|
||||
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/functions/admin-stats.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/functions/attachments.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/functions/common.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/common/attachments.php';
|
||||
|
||||
NGG\Main::get_instance()->init();
|
||||
NGG\DB::get_instance()->init();
|
||||
|
||||
if ( is_admin() ) {
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/enqueue.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/menu.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/gallery.php';
|
||||
require IMAGIFY_PATH . 'inc/3rd-party/nextgen-gallery/inc/admin/bulk.php';
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\RegenerateThumbnails;
|
||||
|
||||
use Imagify_Requirements;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
/**
|
||||
* Class that handles compatibility with Regenerate Thumbnails plugin.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
class Main extends \Imagify_Regenerate_Thumbnails_Deprecated {
|
||||
use \Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Class version.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.1
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
const VERSION = '1.2';
|
||||
|
||||
/**
|
||||
* Action used for the ajax callback.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
const HOOK_SUFFIX = 'regenerate_thumbnails';
|
||||
|
||||
/**
|
||||
* List of optimization processes.
|
||||
*
|
||||
* @var array An array of ProcessInterface objects. The array keys are the media IDs.
|
||||
* @since 1.7.1
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $processes = [];
|
||||
|
||||
/**
|
||||
* Tell if we’re playing in WP 5.3’s garden.
|
||||
*
|
||||
* @var bool
|
||||
* @since 1.9.8
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
protected $is_wp53;
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** INIT ==================================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Launch the hooks.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*/
|
||||
public function init() {
|
||||
if ( ! class_exists( '\RegenerateThumbnails_Regenerator' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter( 'rest_dispatch_request', [ $this, 'maybe_init_attachment' ], 4, 4 );
|
||||
add_action( 'imagify_after_' . static::HOOK_SUFFIX, [ $this, 'after_regenerate_thumbnails' ], 8, 2 );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** HOOKS =================================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Filter the REST dispatch request result, to hook before Regenerate Thumbnails starts its magic.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param bool $dispatch_result Dispatch result, will be used if not empty.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
* @param string $route Route matched for the request.
|
||||
* @param array $handler Route handler used for the request.
|
||||
* @return bool
|
||||
*/
|
||||
public function maybe_init_attachment( $dispatch_result, $request, $route = null, $handler = null ) {
|
||||
if ( strpos( $route, static::get_route_prefix() ) === false ) {
|
||||
return $dispatch_result;
|
||||
}
|
||||
|
||||
$media_id = $request->get_param( 'id' );
|
||||
|
||||
if ( ! $this->set_process( $media_id ) ) {
|
||||
return $dispatch_result;
|
||||
}
|
||||
|
||||
$media_id = $this->get_process( $media_id )->get_media()->get_id();
|
||||
|
||||
// The attachment can be regenerated: keep the optimized full-sized file safe, and replace it by the backup file.
|
||||
$this->backup_optimized_file( $media_id );
|
||||
// Prevent automatic optimization.
|
||||
\Imagify_Auto_Optimization::prevent_optimization( $media_id );
|
||||
// Launch the needed hook.
|
||||
add_filter( 'wp_generate_attachment_metadata', [ $this, 'launch_async_optimization' ], IMAGIFY_INT_MAX - 30, 2 );
|
||||
|
||||
return $dispatch_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-optimize after an attachment is regenerated.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $metadata An array of attachment meta data, containing the sizes that have been regenerated.
|
||||
* @param int $media_id Current media ID.
|
||||
* @return array
|
||||
*/
|
||||
public function launch_async_optimization( $metadata, $media_id ) {
|
||||
$process = $this->get_process( $media_id );
|
||||
|
||||
if ( ! $process ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
$sizes = isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : [];
|
||||
$media = $process->get_media();
|
||||
$fullsize_path = $media->get_raw_fullsize_path();
|
||||
|
||||
if ( $fullsize_path ) {
|
||||
$original_path = $media->get_original_path();
|
||||
|
||||
if ( $original_path && $this->is_wp_53() && $original_path !== $fullsize_path ) {
|
||||
/**
|
||||
* The original file and the full-sized file are not the same:
|
||||
* That means wp_generate_attachment_metadata() recreated the full-sized file, based on the original one.
|
||||
* So it must be optimized again now.
|
||||
*/
|
||||
$sizes['full'] = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $sizes ) {
|
||||
// Put the optimized full-sized file back.
|
||||
$this->put_optimized_file_back( $media_id );
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize the sizes that have been regenerated.
|
||||
*/
|
||||
// If the media has next-gen versions, recreate them for the sizes that have been regenerated.
|
||||
$data = $process->get_data();
|
||||
$optimization_data = $data->get_optimization_data();
|
||||
|
||||
if ( ! empty( $optimization_data['sizes'] ) ) {
|
||||
foreach ( $optimization_data['sizes'] as $size_name => $size_data ) {
|
||||
$non_nextgen_size_name = $process->is_size_next_gen( $size_name );
|
||||
|
||||
if ( ! $non_nextgen_size_name || ! isset( $sizes[ $non_nextgen_size_name ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the next-gen size.
|
||||
$sizes[ $size_name ] = [];
|
||||
}
|
||||
}
|
||||
|
||||
$sizes = array_keys( $sizes );
|
||||
$optimization_level = $data->get_optimization_level();
|
||||
$optimization_args = [ 'hook_suffix' => static::HOOK_SUFFIX ];
|
||||
|
||||
// Delete related optimization data or nothing will be optimized.
|
||||
$data->delete_sizes_optimization_data( $sizes );
|
||||
$process->optimize_sizes( $sizes, $optimization_level, $optimization_args );
|
||||
|
||||
$this->unset_process( $media_id );
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after regenerating the thumbnails.
|
||||
* This puts the full-sized optimized file back.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param ProcessInterface $process The optimization process.
|
||||
* @param array $item The item being processed. See $this->task().
|
||||
*/
|
||||
public function after_regenerate_thumbnails( $process, $item ) {
|
||||
$media_id = $process->get_media()->get_id();
|
||||
|
||||
$this->processes[ $media_id ] = $process;
|
||||
|
||||
$this->put_optimized_file_back( $media_id );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** INTERNAL TOOLS ========================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set an optimization process.
|
||||
*
|
||||
* @since 1.9
|
||||
* @author Grégory Viguier
|
||||
* @access protected
|
||||
*
|
||||
* @param int $media_id The media ID.
|
||||
* @return bool
|
||||
*/
|
||||
protected function set_process( $media_id ) {
|
||||
if ( ! $media_id || ! Imagify_Requirements::is_api_key_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$process = imagify_get_optimization_process( $media_id, 'wp' );
|
||||
|
||||
if ( ! $process->is_valid() || ! $process->get_media()->is_image() || ! $process->get_data()->is_optimized() ) {
|
||||
// Invalid, not animage, or no optimization have been attempted yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->processes[ $media_id ] = $process;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset an optimization process.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $media_id The media ID.
|
||||
*/
|
||||
protected function unset_process( $media_id ) {
|
||||
unset( $this->processes[ $media_id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset an optimization process.
|
||||
*
|
||||
* @since 1.9
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $media_id The media ID.
|
||||
* @return ProcessInterface|bool An optimization process object. False on failure.
|
||||
*/
|
||||
protected function get_process( $media_id ) {
|
||||
return ! empty( $this->processes[ $media_id ] ) ? $this->processes[ $media_id ] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup the optimized full-sized file and replace it by the original backup file.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $media_id Media ID.
|
||||
*/
|
||||
protected function backup_optimized_file( $media_id ) {
|
||||
$media = $this->get_process( $media_id )->get_media();
|
||||
$fullsize_path = $media->get_raw_fullsize_path();
|
||||
|
||||
if ( ! $fullsize_path ) {
|
||||
// Uh?
|
||||
return;
|
||||
}
|
||||
|
||||
$original_path = $media->get_original_path();
|
||||
|
||||
if ( $original_path && $this->is_wp_53() && $original_path !== $fullsize_path ) {
|
||||
/**
|
||||
* The original file and the full-sized file are not the same:
|
||||
* That means wp_generate_attachment_metadata() will recreate the full-sized file, based on the original one.
|
||||
* Then, the thumbnails will be created from a newly created (unoptimized) file.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
$backup_path = $media->get_backup_path();
|
||||
|
||||
if ( ! $backup_path ) {
|
||||
// No backup file, too bad.
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the optimized full-sized file by the backup, so any optimization will not use an optimized file, but the original one.
|
||||
* The optimized full-sized file is kept and renamed, and will be put back in place at the end of the optimization process.
|
||||
*/
|
||||
$filesystem = \Imagify_Filesystem::get_instance();
|
||||
|
||||
if ( $filesystem->exists( $fullsize_path ) ) {
|
||||
$tmp_file_path = static::get_temporary_file_path( $fullsize_path );
|
||||
$moved = $filesystem->move( $fullsize_path, $tmp_file_path, true );
|
||||
}
|
||||
|
||||
$filesystem->copy( $backup_path, $fullsize_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the optimized full-sized file back.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @since 1.9 Replaced $attachment parameter by $media_id.
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param int $media_id Media ID.
|
||||
*/
|
||||
protected function put_optimized_file_back( $media_id ) {
|
||||
$file_path = $this->get_process( $media_id )->get_media()->get_raw_fullsize_path();
|
||||
$tmp_file_path = static::get_temporary_file_path( $file_path );
|
||||
$filesystem = \Imagify_Filesystem::get_instance();
|
||||
|
||||
if ( $filesystem->exists( $tmp_file_path ) ) {
|
||||
$moved = $filesystem->move( $tmp_file_path, $file_path, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if we’re playing in WP 5.3’s garden.
|
||||
*
|
||||
* @since 1.9.8
|
||||
* @access protected
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_wp_53() {
|
||||
if ( isset( $this->is_wp53 ) ) {
|
||||
return $this->is_wp53;
|
||||
}
|
||||
|
||||
$this->is_wp53 = function_exists( 'wp_get_original_image_path' );
|
||||
|
||||
return $this->is_wp53;
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** PUBLIC TOOLS ============================================================================ */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get the beginning of the route used to regenerate thumbnails.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_route_prefix() {
|
||||
static $route;
|
||||
|
||||
if ( ! isset( $route ) ) {
|
||||
$regen = \RegenerateThumbnails();
|
||||
|
||||
if ( ( empty( $regen->rest_api ) || ! is_object( $regen->rest_api ) ) && method_exists( $regen, 'rest_api_init' ) ) {
|
||||
$regen->rest_api_init();
|
||||
}
|
||||
|
||||
$route = '/' . trim( $regen->rest_api->namespace, '/' ) . '/regenerate/';
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the temporary file.
|
||||
*
|
||||
* @since 1.7.1
|
||||
* @access public
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param string $file_path The optimized full-sized file path.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_temporary_file_path( $file_path ) {
|
||||
return $file_path . '_backup';
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( ! class_exists( 'RegenerateThumbnails' ) || ! function_exists( 'RegenerateThumbnails' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
class_alias( '\\Imagify\\ThirdParty\\RegenerateThumbnails\\Main', '\\Imagify_Regenerate_Thumbnails' );
|
||||
|
||||
add_action( 'init', [ \Imagify\ThirdParty\RegenerateThumbnails\Main::get_instance(), 'init' ], 20 );
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( function_exists( 'fn_lc_fix_ssl_upload_url' ) && defined( 'SLC_VERSION' ) && version_compare( SLC_VERSION, '2.2.8' ) < 0 ) :
|
||||
|
||||
/**
|
||||
* Fixes a bug in Screets Live Chat plugin (prior version 2.2.8), preventing wp_get_upload_dir() to work properly.
|
||||
*/
|
||||
remove_filter( 'upload_dir', 'fn_lc_fix_ssl_upload_url' );
|
||||
add_filter( 'upload_dir', 'imagify_screets_lc_fix_ssl_upload_url' );
|
||||
/**
|
||||
* Filters the uploads directory data to force https URLs.
|
||||
*
|
||||
* @since 1.6.7
|
||||
* @author Grégory Viguier
|
||||
*
|
||||
* @param array $uploads Array of upload directory data with keys of 'path', 'url', 'subdir, 'basedir', 'baseurl', and 'error'.
|
||||
* @return array
|
||||
*/
|
||||
function imagify_screets_lc_fix_ssl_upload_url( $uploads ) {
|
||||
if ( false !== $uploads['error'] || ! is_ssl() ) {
|
||||
return $uploads;
|
||||
}
|
||||
|
||||
$uploads['url'] = str_replace( 'http://', 'https://', $uploads['url'] );
|
||||
$uploads['baseurl'] = str_replace( 'http://', 'https://', $uploads['baseurl'] );
|
||||
|
||||
return $uploads;
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
|
||||
|
||||
add_action( 'admin_enqueue_scripts', function( $hook_suffix ) {
|
||||
|
||||
$imagify_admin_pages = array(
|
||||
'media_page_imagify-bulk-optimization',
|
||||
'settings_page_imagify',
|
||||
'media_page_imagify-files',
|
||||
'nextgen-gallery_page_imagify-ngg-bulk-optimization',
|
||||
);
|
||||
|
||||
if (
|
||||
! is_admin()
|
||||
||
|
||||
! class_exists( 'SWCFPC_Backend' )
|
||||
||
|
||||
! in_array( $hook_suffix, $imagify_admin_pages, true )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_deregister_script( 'swcfpc_sweetalert_js' );
|
||||
|
||||
}, 100 );
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
use Imagify\Notices\Notices;
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'RML_FILE' ) ) :
|
||||
/**
|
||||
* Dequeue all WP Real Media Library's styles and scripts where we use ours.
|
||||
*
|
||||
* Prevent WP Real Media Library to use its outdated version of SweetAlert where we need ours, and to mess with our CSS styles.
|
||||
*
|
||||
* @since 1.6.13
|
||||
*/
|
||||
function imagify_wprml_init() {
|
||||
static $done = false;
|
||||
|
||||
if ( $done ) {
|
||||
return;
|
||||
}
|
||||
$done = true;
|
||||
|
||||
if ( ! class_exists( '\\MatthiasWeb\\RealMediaLibrary\\general\\Backend' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notices = Notices::get_instance();
|
||||
|
||||
if ( $notices->has_notices() && ( $notices->display_welcome_steps() || $notices->display_wrong_api_key() ) ) {
|
||||
// We display a notice that uses SweetAlert.
|
||||
imagify_wprml_dequeue();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( imagify_is_screen( 'bulk' ) || imagify_is_screen( 'imagify-settings' ) ) {
|
||||
// We display a page that uses SweetAlert.
|
||||
imagify_wprml_dequeue();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( function_exists( 'imagify_get_ngg_bulk_screen_id' ) && imagify_is_screen( imagify_get_ngg_bulk_screen_id() ) ) {
|
||||
// We display the NGG Bulk Optimization page.
|
||||
imagify_wprml_dequeue();
|
||||
}
|
||||
}
|
||||
add_action( 'current_screen', 'imagify_wprml_init' );
|
||||
|
||||
/**
|
||||
* Prevent WP Real Media Library to enqueue its styles and scripts.
|
||||
*
|
||||
* @since 1.6.13
|
||||
*/
|
||||
function imagify_wprml_dequeue() {
|
||||
$instance = \MatthiasWeb\RealMediaLibrary\general\Backend::getInstance();
|
||||
|
||||
remove_action( 'admin_enqueue_scripts', [ $instance, 'admin_enqueue_scripts' ], 0 );
|
||||
remove_action( 'admin_footer', [ $instance, 'admin_footer' ] );
|
||||
|
||||
if ( class_exists( '\\MatthiasWeb\\RealMediaLibrary\\general\\FolderShortcode' ) ) {
|
||||
$instance = \MatthiasWeb\RealMediaLibrary\general\FolderShortcode::getInstance();
|
||||
|
||||
remove_action( 'admin_head', [ $instance, 'admin_head' ] );
|
||||
remove_action( 'admin_enqueue_scripts', [ $instance, 'admin_enqueue_scripts' ] );
|
||||
}
|
||||
|
||||
if ( class_exists( '\\MatthiasWeb\\RealMediaLibrary\\comp\\PageBuilders' ) ) {
|
||||
$instance = \MatthiasWeb\RealMediaLibrary\comp\PageBuilders::getInstance();
|
||||
|
||||
remove_action( 'init', [ $instance, 'init' ] );
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
namespace Imagify\ThirdParty\WPRocket;
|
||||
|
||||
use Imagify\Traits\InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Compat class for WP Rocket plugin.
|
||||
*
|
||||
* @since 1.9.3
|
||||
*/
|
||||
class Main {
|
||||
use InstanceGetterTrait;
|
||||
|
||||
/**
|
||||
* Launch the hooks.
|
||||
*
|
||||
* @since 1.9.3
|
||||
*/
|
||||
public function init() {
|
||||
add_filter( 'imagify_cdn_source', [ $this, 'set_cdn_source' ] );
|
||||
}
|
||||
|
||||
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
/** HOOKS =================================================================================== */
|
||||
/** ----------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Provide a custom CDN source.
|
||||
*
|
||||
* @since 1.9.3
|
||||
*
|
||||
* @param array $source {
|
||||
* An array of arguments.
|
||||
*
|
||||
* @type $name string The name of which provides the URL (plugin name, etc).
|
||||
* @type $url string The CDN URL.
|
||||
* }
|
||||
* @return array
|
||||
*/
|
||||
public function set_cdn_source( $source ) {
|
||||
if ( ! function_exists( 'get_rocket_option' ) ) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
if ( ! get_rocket_option( 'cdn' ) ) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
$container = apply_filters( 'rocket_container', null );
|
||||
|
||||
if ( is_object( $container ) && method_exists( $container, 'get' ) ) {
|
||||
$cdn = $container->get( 'cdn' );
|
||||
|
||||
if ( $cdn && method_exists( $cdn, 'get_cdn_urls' ) ) {
|
||||
$url = $cdn->get_cdn_urls( [ 'all', 'images' ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $url ) && function_exists( 'get_rocket_cdn_cnames' ) ) {
|
||||
$url = get_rocket_cdn_cnames( [ 'all', 'images' ] );
|
||||
}
|
||||
|
||||
if ( empty( $url ) ) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
$url = reset( $url );
|
||||
|
||||
if ( ! $url ) {
|
||||
return $source;
|
||||
}
|
||||
|
||||
if ( ! preg_match( '@^(https?:)?//@i', $url ) ) {
|
||||
$url = '//' . $url;
|
||||
}
|
||||
|
||||
$scheme = wp_parse_url( \Imagify_Filesystem::get_instance()->get_site_root_url() );
|
||||
$scheme = ! empty( $scheme['scheme'] ) ? $scheme['scheme'] : null;
|
||||
$url = set_url_scheme( $url, $scheme );
|
||||
|
||||
$source['name'] = 'WP Rocket';
|
||||
$source['url'] = $url;
|
||||
|
||||
return $source;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'WP_ROCKET_VERSION' ) ) :
|
||||
|
||||
\Imagify\ThirdParty\WPRocket\Main::get_instance()->init();
|
||||
|
||||
endif;
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
if ( defined( 'WPSEO_VERSION' ) && is_admin() && ! wp_doing_ajax() ) :
|
||||
|
||||
add_action( 'wp_print_scripts', '_imagify_dequeue_yoastseo_script' );
|
||||
/**
|
||||
* Remove Yoast SEO bugged script.
|
||||
*
|
||||
* @since 1.4.1
|
||||
*/
|
||||
function _imagify_dequeue_yoastseo_script() {
|
||||
if ( ! function_exists( 'get_current_screen' ) ) {
|
||||
return;
|
||||
}
|
||||
$current_screen = get_current_screen();
|
||||
|
||||
if ( isset( $current_screen ) && 'post' === $current_screen->base && 'attachment' === $current_screen->post_type ) {
|
||||
wp_dequeue_script( 'yoast-seo' );
|
||||
wp_deregister_script( 'yoast-seo' );
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
Reference in New Issue
Block a user