laipower/wp-content/plugins/gp-premium/library/image-processing-queue/includes/class-image-processing-queue.php
2020-04-07 13:03:04 +00:00

278 lines
7.0 KiB
PHP

<?php
/**
* Image Processing Queue
*
* @package Image-Processing-Queue
*/
if ( ! class_exists( 'Image_Processing_Queue' ) ) {
/**
* Image Processing Queue
*/
class Image_Processing_Queue {
/**
* Singleton
*
* @var Image_Processing_Queue|null
*/
protected static $instance = null;
/**
* Whether or not we're updating the backup sizes
*
* @var bool
*/
private $is_updating_backup_sizes = false;
/**
* Instance of the background process class
*
* @var IPQ_Process|null
*/
public $process = null;
/**
* Singleton
*
* @return Image_Processing_Queue|null
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Image_Processing_Queue constructor.
*/
public function __construct() {
$this->process = new IPQ_Process();
add_filter( 'update_post_metadata', array( $this, 'filter_update_post_metadata' ), 10, 5 );
}
/**
* Filter the post meta data for backup sizes
*
* Unfortunately WordPress core is lacking hooks in its image resizing functions so we are reduced
* to this hackery to detect when images are resized and previous versions are relegated to backup sizes.
*
* @param bool $check
* @param int $object_id
* @param string $meta_key
* @param mixed $meta_value
* @param mixed $prev_value
* @return bool
*/
public function filter_update_post_metadata( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
if ( '_wp_attachment_backup_sizes' !== $meta_key ) {
return $check;
}
$current_value = get_post_meta( $object_id, $meta_key, true );
if ( ! $current_value ) {
$current_value = array();
}
$diff = array_diff_key( $meta_value, $current_value );
if ( ! $diff ) {
return $check;
}
$key = key( $diff );
$suffix = substr( $key, strrpos( $key, '-' ) + 1 );
$image_meta = self::get_image_meta( $object_id );
foreach ( $image_meta['sizes'] as $size_name => $size ) {
if ( 0 !== strpos( $size_name, 'ipq-' ) ) {
continue;
}
$meta_value[ $size_name . '-' . $suffix ] = $size;
unset( $image_meta['sizes'][ $size_name ] );
}
if ( ! $this->is_updating_backup_sizes ) {
$this->is_updating_backup_sizes = true;
update_post_meta( $object_id, '_wp_attachment_backup_sizes', $meta_value );
wp_update_attachment_metadata( $object_id, $image_meta );
return true;
}
$this->is_updating_backup_sizes = false;
return $check;
}
/**
* Check if the image sizes exist and push them to the queue if not.
*
* @param int $post_id
* @param array $sizes
*/
protected function process_image( $post_id, $sizes ) {
$new_item = false;
foreach ( $sizes as $size ) {
if ( self::does_size_already_exist_for_image( $post_id, $size ) ) {
continue;
}
if ( self::is_size_larger_than_original( $post_id, $size ) ) {
continue;
}
$item = array(
'post_id' => $post_id,
'width' => $size[0],
'height' => $size[1],
'crop' => $size[2],
);
$this->process->push_to_queue( $item );
$new_item = true;
}
if ( $new_item ) {
$this->process->save()->dispatch();
}
}
/**
* Get image HTML for a specific context in a theme, specifying the exact sizes
* for the image. The first image size is always used as the `src` and the other
* sizes are used in the `srcset` if they're the same aspect ratio as the original
* image. If any of the image sizes don't currently exist, they are queued for
* creation by a background process. Example:
*
* echo ipq_get_theme_image( 1353, array(
* array( 600, 400, false ),
* array( 1280, 720, false ),
* array( 1600, 1067, false ),
* ),
* array(
* 'class' => 'header-banner'
* )
* );
*
* @param int $post_id Image attachment ID.
* @param array $sizes Array of arrays of sizes in the format array(width,height,crop).
* @param string $attr Optional. Attributes for the image markup. Default empty.
* @return string HTML img element or empty string on failure.
*/
public function get_image( $post_id, $sizes, $attr = '' ) {
$this->process_image( $post_id, $sizes );
return wp_get_attachment_image( $post_id, array( $sizes[0][0], $sizes[0][1] ), false, $attr );
}
/**
* Get image URL for a specific context in a theme, specifying the exact size
* for the image. If the image size does not currently exist, it is queued for
* creation by a background process. Example:
*
* echo ipq_get_theme_image_url( 1353, array( 600, 400, false ) );
*
* @param int $post_id
* @param array $size
*
* @return string
*/
public function get_image_url( $post_id, $size ) {
$this->process_image( $post_id, array( $size ) );
$size = self::get_size_name( $size );
$src = wp_get_attachment_image_src( $post_id, $size );
if ( isset( $src[0] ) ) {
return $src[0];
}
return '';
}
/**
* Get array index name for image size.
*
* @param array $size array in format array(width,height,crop).
* @return string Image size name.
*/
public static function get_size_name( $size ) {
$crop = $size[2] ? 'true' : 'false';
return 'ipq-' . $size[0] . 'x' . $size[1] . '-' . $crop;
}
/**
* Get an image's file path.
*
* @param int $post_id ID of the image post.
* @return false|string
*/
public static function get_image_path( $post_id ) {
return get_attached_file( $post_id );
}
/**
* Get an image's post meta data.
*
* @param int $post_id ID of the image post.
* @return mixed Post meta field. False on failure.
*/
public static function get_image_meta( $post_id ) {
return wp_get_attachment_metadata( $post_id );
}
/**
* Update meta data for an image
*
* @param int $post_id Image ID.
* @param array $data Image data.
* @return bool|int False if $post is invalid.
*/
public static function update_image_meta( $post_id, $data ) {
return wp_update_attachment_metadata( $post_id, $data );
}
/**
* Checks if an image size already exists for an image
*
* @param int $post_id Image ID.
* @param array $size array in format array(width,height,crop).
* @return bool
*/
public static function does_size_already_exist_for_image( $post_id, $size ) {
$image_meta = self::get_image_meta( $post_id );
$size_name = self::get_size_name( $size );
return isset( $image_meta['sizes'][ $size_name ] );
}
/**
* Check if an image size is larger than the original.
*
* @param int $post_id Image ID.
* @param array $size array in format array(width,height,crop).
*
* @return bool
*/
public static function is_size_larger_than_original( $post_id, $size ) {
$image_meta = self::get_image_meta( $post_id );
if ( ! isset( $image_meta['width'] ) || ! isset( $image_meta['height'] ) ) {
return true;
}
if ( $size[0] > $image_meta['width'] || $size[1] > $image_meta['height'] ) {
return true;
}
return false;
}
}
}