Files
SIGE-WEB-snapshot/ambiente-de-test/wp-content/plugins/document-gallery/inc/class-thumb.php

422 lines
14 KiB
PHP

<?php
/**
* Holds data specific to a specific thumbnail
*
* @author drossiter
*/
class DG_Thumb {
/**
* TODO: Replace w/ https://codex.wordpress.org/Class_Reference/WP_Object_Cache
* @var DG_Thumb[] The cached copy of thumbs.
*/
private static $thumbs = null;
/**
* @var string The meta key identifying DG thumbs.
*/
private static $meta_key = '_dg_thumbnail';
/**
* @var int The DB row ID.
*/
private $meta_id;
/**
* @var int The post (attachment) ID.
*/
private $post_id;
/**
* @return int The post ID.
*/
public function getPostId() {
return $this->post_id;
}
/**
* @param $post_id int The post ID.
*/
public function setPostId($post_id) {
$this->post_id = $post_id;
}
/**
* @var string The thumb dimensions (format: WIDTHxHEIGHT).
*/
private $dimensions = '';
/**
* @return string The dimensions (WIDTHxHEIGHT).
*/
public function getDimensions() {
return $this->dimensions;
}
/**
* @param $dimensions string The dimensions (WIDTHxHEIGHT).
*/
public function setDimensions($dimensions) {
$this->dimensions = $dimensions;
}
/**
* @var string The path relative to the WP uploads directory.
*/
private $relative_path = '';
/**
* @return string The path relative to the WP uploads directory.
*/
public function getRelativePath() {
return $this->relative_path;
}
/**
* @param $relative_path string The path relative to the WP uploads directory.
*/
public function setRelativePath($relative_path) {
$this->relative_path = $relative_path;
}
/**
* @var int The time when thumbnail was generated.
*/
private $timestamp;
/**
* @return int The time when thumbnail was generated.
*/
public function getTimestamp() {
return $this->timestamp;
}
/**
* @param $timestamp int The time when thumbnail was generated.
*/
public function setTimestamp($timestamp) {
$this->timestamp = $timestamp;
}
/**
* @var string The function used in generating this thumb.
*/
private $generator = '';
/**
* @return string The function used in generating this thumb.
*/
public function getGenerator() {
return $this->generator;
}
/**
* @param $generator string The function used in generating this thumb.
*/
public function setGenerator($generator) {
$this->generator = $generator;
}
/**
* DG_Thumb constructor.
* @param $db_row object The result of querying WP postmeta.
*/
public function __construct($db_row = null) {
if ( is_null ($db_row) ) return;
$this->meta_id = $db_row->meta_id;
$this->post_id = $db_row->post_id;
$this->setMetaValue( $db_row->meta_value );
}
/**
* Meta value is in the following format: [width]x[height]:[timestamp]:[path]:[generator].
* Note that generator may contain colons, so parsing of this field must be done carefully.
*
* @param $meta_value string Populates the dimensions and path from meta_value.
*/
private function setMetaValue($meta_value) {
$split = explode( ':', $meta_value, 4 );
$this->dimensions = $split[0];
$this->timestamp = absint( $split[1] );
$this->relative_path = $split[2];
$this->generator = $split[3];
}
/**
* Meta value is in the following format: [width]x[height]:[timestamp]:[path]:[generator].
*
* @return string The meta_value generated from the dimensions & path fields.
*/
private function getMetaValue() {
return $this->dimensions . ':' . $this->timestamp . ':' . $this->relative_path . ':' . $this->generator;
}
/**
* @return int Parses dimensions string pulling out the width.
*/
public function getWidth() {
$split = explode( 'x', $this->dimensions, 2 );
return absint( $split[0] );
}
/**
* @return int Parses dimensions string pulling out the height.
*/
public function getHeight() {
$split = explode( 'x', $this->dimensions, 2 );
return absint( $split[1] );
}
/**
* @return string Get fully-qualified URL pointing to this thumb.
*/
public function getUrl() {
$upload_dir = wp_upload_dir();
return $upload_dir['baseurl'] . '/' . $this->relative_path;
}
/**
* @return string Get fully-qualified system path pointing to this thumb.
*/
public function getPath() {
$upload_dir = wp_upload_dir();
return $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $this->relative_path;
}
/**
* @return bool Whether this instance represents a successful thumb generation.
*/
public function isSuccess() {
return ! empty( $this->relative_path ) && ! DG_Util::startsWith( $this->getPath(), DG_PATH );
}
/**
* Saves thumb to DB. Either an UPDATE or an INSERT is performed depending on whether meta_id isset and
* updates the instance meta_id if INSERT is performed.
*/
public function save() {
global $wpdb;
// thumbs are immutable -- once created they can only be read or deleted
if ( isset( $this->meta_id ) ) return;
// don't re-save identical thumb
if ( isset( self::$thumbs[$this->post_id][$this->dimensions] ) &&
$this == self::$thumbs[$this->post_id][$this->dimensions] ) return;
// post_id + dimensions must be unique so purge the old entry if one exists
$old_thumb = self::getThumb( $this->post_id, $this->dimensions );
if ( ! is_null( $old_thumb ) ) {
$old_thumb->delete( $old_thumb->relative_path != $this->relative_path );
}
DG_Logger::writeLog( DG_LogLevel::Detail, 'Saving thumb with post_id = ' . $this->post_id );
// perform save to DB
$values = array( 'post_id' => $this->post_id, 'meta_key' => self::$meta_key, 'meta_value' => $this->getMetaValue() );
$value_formats = array( '%d', '%s', '%s' );
$wpdb->insert( $wpdb->postmeta, $values, $value_formats );
$this->meta_id = $wpdb->insert_id;
self::initThumbs();
if ( ! isset( self::$thumbs[$this->post_id] ) ) {
self::$thumbs[$this->post_id] = array();
}
self::$thumbs[$this->post_id][$this->dimensions] = $this;
}
/**
* Deletes the current instances from the DB and filesystem.
*
* @param $delete_files bool Whether files for the thumb should be deleted.
*/
public function delete( $delete_files = true ) {
if ( ! isset( $this->meta_id ) ) return;
DG_Logger::writeLog( DG_LogLevel::Detail, 'Deleting thumb with post_id = ' . $this->post_id );
global $wpdb;
$wpdb->delete( $wpdb->postmeta, array( 'meta_id' => $this->meta_id ), array( '%d' ) );
self::cleanupThumbFiles( $this );
unset( $this->meta_id );
if ( 1 === sizeof( self::$thumbs[$this->post_id] ) ) {
unset( self::$thumbs[$this->post_id] );
} else {
unset( self::$thumbs[$this->post_id][$this->dimensions] );
}
}
/**
* Whether the given attachment has a thumb graphic.
*
* @param $ID int The id of the attachment to be checked.
* @param $dimensions string Optional. The dimensions for the thumbnail we're seeking.
* @param $success_matters bool Optional. Whether return value should be false when DG_Thumb exists, but is not successful.
* @return bool Whether the given attachment has a thumbnail image.
*/
public static function thumbExists($ID, $dimensions = null, $success_matters = true) {
$thumb = self::getThumb( $ID, $dimensions );
return ! is_null( $thumb ) && ( ! $success_matters || $thumb->isSuccess() );
}
/**
* Whether the given attachment has a thumb graphic.
*
* @param $ID int The id of the attachment to be checked.
* @param $dimensions string The dimensions for the thumbnail we're seeking.
* @return DG_Thumb|null The thumbnail at the requested dimensions.
*/
public static function getThumb($ID, $dimensions = null) {
$thumbs = self::getThumbs();
$ret = null;
if ( isset( $thumbs[$ID] ) && ( is_null( $dimensions ) || isset( $thumbs[$ID][$dimensions] ) ) ) {
$ret = ! is_null( $dimensions ) ? $thumbs[$ID][$dimensions] : reset( $thumbs[$ID] );
}
return $ret;
}
/**
* Initializes the thumbs variable if not already initialized.
*/
private static function initThumbs() {
if ( !isset( self::$thumbs ) ) {
DG_Logger::writeLog( DG_LogLevel::Detail, 'Populating thumbnail cache.' );
global $wpdb;
self::$thumbs = array();
$meta_key = self::$meta_key;
$sql = "SELECT post_id, meta_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '$meta_key'";
foreach ( $wpdb->get_results( $sql ) as $row ) {
$key = $row->post_id;
$new = new DG_Thumb( $row );
if ( ! isset( self::$thumbs[$key] ) ) {
self::$thumbs[$key] = array();
} elseif ( isset( self::$thumbs[$key][$new->dimensions] ) ) {
// it is possible to end up with duplicate thumbnails -- cleanup here
$old = self::$thumbs[$key][$new->dimensions];
if ( $old->timestamp < $new->timestamp ) {
$old->delete();
} else {
$new->delete();
continue;
}
}
self::$thumbs[$key][$new->dimensions] = $new;
}
}
}
/**
* Gets either a nested associative array mapping ID to dimension to thumb or an associative array mapping ID to thumb.
*
* @param $dimensions string WIDTHxHEIGHT
* @return DG_Thumb[]|DG_Thumb[][] The matched thumbs.
*/
public static function getThumbs($dimensions = null) {
self::initThumbs();
if ( is_null( $dimensions ) ) {
$ret = self::$thumbs;
} else {
$ret = array();
foreach ( self::$thumbs as $thumbs ) {
if ( isset( $thumbs[$dimensions] ) ) {
$thumb = $thumbs[$dimensions];
$ret[$thumb->post_id] = $thumb;
}
}
}
return $ret;
}
/**
* Removes thumbs from the DB.
* @param $ids int[]|int|null Optional. The post IDs to be purged. If not given then all are purged.
* @param $blog_id null|int Optional. The blog to purge from. Defaults to active blog.
* @param $delete_files bool Whether files for the thumb should be deleted.
*/
public static function purgeThumbs( $ids = null, $blog_id = null, $delete_files = true ) {
global $wpdb;
if ( ! is_null( $ids ) ) {
$ids = (array)$ids;
}
$postmeta = $wpdb->get_blog_prefix( $blog_id ) . 'postmeta';
$meta_key = self::$meta_key;
self::initThumbs();
if ( ! is_array( $ids ) ) {
$sql = "DELETE FROM $postmeta WHERE meta_key = '$meta_key'";
$result = $wpdb->query( $sql );
if ( $result ) {
// cleanup filesystem
if ( $delete_files ) {
foreach ( self::$thumbs as $thumbs ) {
self::cleanupThumbFiles( $thumbs );
}
}
self::$thumbs = null;
}
} else if ( !empty( $ids ) ) {
$sql = "DELETE FROM $postmeta WHERE meta_key = '$meta_key' AND post_id IN(" . rtrim( str_repeat( '%d,', sizeof( $ids ) ), ',' ) . ")";
$result = $wpdb->query( $wpdb->prepare( $sql, $ids ) );
if ( $result ) {
foreach ( $ids as $id ) {
if ( isset( self::$thumbs[$id] ) ) {
self::cleanupThumbFiles( self::$thumbs[$id] );
unset( self::$thumbs[$id] );
}
}
}
}
}
/**
* Delete all thumb entries that do not have an actual image associated with them due to failed generation.
*/
public static function purgeFailedThumbs() {
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '" . self::$meta_key . "' AND meta_value LIKE '%:%::'" );
// force re-query next time
self::$thumbs = null;
}
/**
* Removes meta data associated w/ attachment.
*
* @param $id int The post ID.
*/
public static function cleanupAttachmentMeta($id) {
$thumb = self::getThumb( $id );
if ( ! is_null( $thumb ) ) {
self::cleanupThumbFiles($thumb);
}
}
/**
* @param $thumbs DG_Thumb[]|DG_Thumb Removes files associated with given thumb(s).
*/
private static function cleanupThumbFiles($thumbs) {
if ( is_a( $thumbs, __CLASS__ ) ) {
$thumbs = array( $thumbs );
}
foreach ( $thumbs as $thumb ) {
if ( isset( $thumb->relative_path ) ) {
@unlink( $thumb->getPath() );
}
}
}
}