first
This commit is contained in:
@ -0,0 +1,684 @@
|
||||
<?php
|
||||
namespace ShortPixel\Model\Image;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
||||
use ShortPixel\Controller\OptimizeController as OptimizeController;
|
||||
use ShortPixel\Helper\UtilHelper as UtilHelper;
|
||||
|
||||
use ShortPixel\Controller\ApiController as API;
|
||||
|
||||
|
||||
// @todo Custom Model for adding files, instead of meta DAO.
|
||||
class CustomImageModel extends \ShortPixel\Model\Image\ImageModel
|
||||
{
|
||||
|
||||
protected $folder_id;
|
||||
protected $path_md5;
|
||||
|
||||
protected $type = 'custom';
|
||||
|
||||
protected $thumbnails = array(); // placeholder, should return empty.
|
||||
protected $retinas = array(); // placeholder, should return empty.
|
||||
|
||||
protected $in_db = false;
|
||||
protected $is_stub = false;
|
||||
|
||||
protected $is_main_file = true;
|
||||
|
||||
/** @var array */
|
||||
protected $forceSettings = array(); // option derives from setting or otherwise, request to be forced upon via UI to use specific value.
|
||||
|
||||
|
||||
// @param int $id
|
||||
public function __construct($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
if ($id > 0)
|
||||
{
|
||||
$bool = $this->loadMeta();
|
||||
/*if ($bool)
|
||||
{
|
||||
$this->setWebp();
|
||||
$this->setAvif();
|
||||
} */
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->fullpath = ''; // stub
|
||||
$this->image_meta = new ImageMeta();
|
||||
$this->is_stub = true;
|
||||
}
|
||||
parent::__construct($this->fullpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $folder_id;
|
||||
*/
|
||||
public function setFolderId($folder_id)
|
||||
{
|
||||
$this->folder_id = $folder_id;
|
||||
}
|
||||
|
||||
|
||||
public function getOptimizeUrls()
|
||||
{
|
||||
|
||||
$data = $this->getOptimizeData();
|
||||
return array_values($data['urls']);
|
||||
|
||||
}
|
||||
|
||||
protected function getExcludePatterns()
|
||||
{
|
||||
$args = array(
|
||||
'filter' => true,
|
||||
'is_custom' => true,
|
||||
);
|
||||
|
||||
$patterns = UtilHelper::getExclusions($args);
|
||||
return $patterns;
|
||||
}
|
||||
|
||||
public function getOptimizeData()
|
||||
{
|
||||
$parameters = array(
|
||||
'urls' => array(),
|
||||
'params' => array(),
|
||||
'returnParams' => array(),
|
||||
);
|
||||
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
if ($this->is_virtual())
|
||||
$url = $this->getFullPath();
|
||||
else
|
||||
$url = $this->getURL();
|
||||
|
||||
$settings = \wpSPIO()->settings();
|
||||
$isSmartCrop = ($settings->useSmartcrop == true && $this->getExtension() !== 'pdf') ? true : false;
|
||||
$paramListArgs = array(); // args for the params, yes.
|
||||
|
||||
if (isset($this->forceSettings['smartcrop']) && $this->getExtension() !== 'pdf')
|
||||
{
|
||||
$isSmartCrop = ($this->forceSettings['smartcrop'] == ImageModel::ACTION_SMARTCROP) ? true : false;
|
||||
}
|
||||
$paramListArgs['smartcrop'] = $isSmartCrop;
|
||||
$paramListArgs['main_url'] = $url;
|
||||
$paramListArgs['url'] = $url;
|
||||
|
||||
if ($this->isProcessable(true) || $this->isProcessableAnyFileType())
|
||||
{
|
||||
$parameters['urls'][0] = $url;
|
||||
$parameters['paths'][0] = $this->getFullPath();
|
||||
$parameters['params'][0] = $this->createParamList($paramListArgs);
|
||||
$parameters['returnParams']['sizes'][0] = $this->getFileName();
|
||||
|
||||
if ($isSmartCrop )
|
||||
{
|
||||
$parameters['returnParams']['fileSizes'][0] = $this->getFileSize();
|
||||
}
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
public function doSetting($setting, $value)
|
||||
{
|
||||
$this->forceSettings[$setting] = $value;
|
||||
}
|
||||
|
||||
public function getURL()
|
||||
{
|
||||
return \wpSPIO()->filesystem()->pathToUrl($this);
|
||||
}
|
||||
|
||||
public function count($type)
|
||||
{
|
||||
// everything is 1 on 1 in the customModel
|
||||
switch($type)
|
||||
{
|
||||
case 'thumbnails':
|
||||
return 0;
|
||||
break;
|
||||
case 'webps':
|
||||
$count = count($this->getWebps());
|
||||
break;
|
||||
case 'avifs':
|
||||
$count = count($this->getAvifs());
|
||||
break;
|
||||
case 'retinas':
|
||||
$count = count($this->getRetinas());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $count; // 0 or 1
|
||||
}
|
||||
|
||||
/* Check if an image in theory could be processed. Check only exclusions, don't check status etc */
|
||||
public function isProcessable($strict = false)
|
||||
{
|
||||
$bool = parent::isProcessable();
|
||||
|
||||
if($strict)
|
||||
{
|
||||
return $bool;
|
||||
}
|
||||
|
||||
// The exclude size on the image - via regex - if fails, prevents the whole thing from optimization.
|
||||
if ($this->processable_status == ImageModel::P_EXCLUDE_SIZE || $this->processable_status == ImageModel::P_EXCLUDE_PATH)
|
||||
{
|
||||
return $bool;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* if ($bool === false && $strict === false)
|
||||
{
|
||||
// Todo check if Webp / Acif is active, check for unoptimized items
|
||||
if ($this->isProcessableFileType('webp'))
|
||||
{
|
||||
$bool = true;
|
||||
}
|
||||
if ($this->isProcessableFileType('avif'))
|
||||
{
|
||||
$bool = true;
|
||||
}
|
||||
|
||||
} */
|
||||
|
||||
// From above to below was implemented because it could not detect file not writable / directory not writable issues if there was any option to generate webp in the settings. Should check for all those file issues first.
|
||||
|
||||
// First test if this file isn't unprocessable for any other reason, then check.
|
||||
if (($this->isProcessable(true) || $this->isOptimized() ) && $this->isProcessableAnyFileType() === true)
|
||||
{
|
||||
if (false === $this->is_directory_writable())
|
||||
{
|
||||
$bool = false;
|
||||
}
|
||||
else {
|
||||
$bool = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $bool;
|
||||
}
|
||||
|
||||
public function isRestorable()
|
||||
{
|
||||
|
||||
$bool = parent::isRestorable();
|
||||
|
||||
// If fine, all fine.
|
||||
if ($bool == true)
|
||||
{
|
||||
return $bool;
|
||||
}
|
||||
|
||||
// If not, check this..
|
||||
if ($this->hasBackup() && $this->getMeta('status') == self::FILE_STATUS_PREVENT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $bool;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getWebps()
|
||||
{
|
||||
$webp = array($this->getWebp());
|
||||
return array_filter($webp);
|
||||
}
|
||||
|
||||
protected function getAvifs()
|
||||
{
|
||||
$avif = array($this->getAvif());
|
||||
return array_filter($avif);
|
||||
}
|
||||
|
||||
/** Get FileTypes that might be optimized. Checking for setting should go via isProcessableFileType! */
|
||||
public function getOptimizeFileType($type = 'webp')
|
||||
{
|
||||
// Pdf files can't have special images.
|
||||
if ($this->getExtension() == 'pdf')
|
||||
return array();
|
||||
|
||||
if ($type == 'webp')
|
||||
{
|
||||
$types = $this->getWebps();
|
||||
}
|
||||
elseif ($type == 'avif')
|
||||
{
|
||||
$types = $this->getAvifs();
|
||||
}
|
||||
|
||||
$toOptimize = array();
|
||||
$fs = \WPSPIO()->filesystem();
|
||||
|
||||
// The file must not exist yet.
|
||||
if (count($types) == 0 && ($this->isProcessable(true) || $this->isOptimized()) )
|
||||
return array($fs->pathToUrl($this));
|
||||
else
|
||||
return array();
|
||||
|
||||
}
|
||||
|
||||
public function restore($args = array())
|
||||
{
|
||||
do_action('shortpixel_before_restore_image', $this->get('id'));
|
||||
do_action('shortpixel/image/before_restore', $this);
|
||||
|
||||
$defaults = array(
|
||||
'keep_in_queue' => false, // used for bulk restore.
|
||||
);
|
||||
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
$bool = parent::restore();
|
||||
|
||||
$return = true;
|
||||
if ($bool)
|
||||
{
|
||||
$this->setMeta('status', ImageModel::FILE_STATUS_UNPROCESSED);
|
||||
$this->setMeta('compressedSize', 0);
|
||||
$this->setMeta('compressionType', null);
|
||||
|
||||
|
||||
$this->saveMeta();
|
||||
|
||||
$webps = $this->getWebps();
|
||||
foreach($webps as $webpFile)
|
||||
$webpFile->delete();
|
||||
|
||||
$avifs = $this->getAvifs();
|
||||
foreach($avifs as $avifFile)
|
||||
$avifFile->delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
$return = false;
|
||||
}
|
||||
|
||||
if ($args['keep_in_queue'] === false)
|
||||
{
|
||||
$this->dropFromQueue();
|
||||
}
|
||||
do_action('shortpixel/image/after_restore', $this, $this->id, $bool);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function handleOptimized($optimizeData, $args = array())
|
||||
{
|
||||
$bool = true;
|
||||
|
||||
if (isset($optimizeData['files']) && isset($optimizeData['data']))
|
||||
{
|
||||
$files = $optimizeData['files'];
|
||||
$data = $optimizeData['data'];
|
||||
}
|
||||
else {
|
||||
Log::addError('Something went wrong with handleOptimized', $optimizeData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (! $this->isOptimized() ) // main file might not be contained in results
|
||||
{
|
||||
$bool = parent::handleOptimized($files[0]);
|
||||
}
|
||||
|
||||
$this->handleOptimizedFileType($files[0]);
|
||||
|
||||
if ($bool)
|
||||
{
|
||||
$this->setMeta('customImprovement', parent::getImprovement());
|
||||
$this->saveMeta();
|
||||
}
|
||||
|
||||
// $this->deleteTempFiles($files);
|
||||
|
||||
return $bool;
|
||||
}
|
||||
|
||||
public function loadMeta()
|
||||
{
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$sql = 'SELECT * FROM ' . $wpdb->prefix . 'shortpixel_meta where id = %d';
|
||||
$sql = $wpdb->prepare($sql, $this->id);
|
||||
|
||||
$imagerow = $wpdb->get_row($sql);
|
||||
|
||||
$metaObj = new ImageMeta();
|
||||
$this->image_meta = $metaObj; // even if not found, load an empty imageMeta.
|
||||
|
||||
if (! is_object($imagerow))
|
||||
return false;
|
||||
|
||||
$this->in_db = true; // record found.
|
||||
|
||||
$this->fullpath = $imagerow->path;
|
||||
$this->folder_id = $imagerow->folder_id;
|
||||
$this->path_md5 = $imagerow->path_md5;
|
||||
|
||||
$status = intval($imagerow->status);
|
||||
$metaObj->status = $status;
|
||||
|
||||
if ($status == ImageModel::FILE_STATUS_SUCCESS)
|
||||
{
|
||||
$metaObj->customImprovement = $imagerow->message;
|
||||
}
|
||||
|
||||
|
||||
$metaObj->compressedSize = intval($imagerow->compressed_size);
|
||||
// The null check is important, otherwise it will always optimize wrongly.
|
||||
$metaObj->compressionType = (is_null($imagerow->compression_type)) ? null : intval($imagerow->compression_type);
|
||||
|
||||
if (! is_numeric($imagerow->message) && ! is_null($imagerow->message))
|
||||
$metaObj->errorMessage = $imagerow->message;
|
||||
|
||||
$metaObj->did_keepExif = (intval($imagerow->keep_exif) == 1) ? true : false;
|
||||
|
||||
$metaObj->did_cmyk2rgb = (intval($imagerow->cmyk2rgb) == 1) ? true : false;
|
||||
|
||||
$metaObj->resize = (intval($imagerow->resize) > 1) ? true : false;
|
||||
|
||||
if (intval($imagerow->resize_width) > 0)
|
||||
$metaObj->resizeWidth = intval($imagerow->resize_width);
|
||||
|
||||
if (intval($imagerow->resize_height) > 0)
|
||||
$metaObj->resizeHeight = intval($imagerow->resize_height);
|
||||
|
||||
//$metaObj->has_backup = (intval($imagerow->backup) == 1) ? true : false;
|
||||
|
||||
$addedDate = UtilHelper::DBtoTimestamp($imagerow->ts_added);
|
||||
$metaObj->tsAdded = $addedDate;
|
||||
|
||||
$optimizedDate = UtilHelper::DBtoTimestamp($imagerow->ts_optimized);
|
||||
$metaObj->tsOptimized = $optimizedDate;
|
||||
|
||||
$extraInfo = property_exists($imagerow, 'extra_info') ? $imagerow->extra_info : null;
|
||||
|
||||
if (! is_null($extraInfo))
|
||||
{
|
||||
$data = json_decode($extraInfo, true);
|
||||
|
||||
if (isset($data['webpStatus']))
|
||||
{
|
||||
$this->setMeta('webp', $data['webpStatus']);
|
||||
}
|
||||
if (isset($data['avifStatus']))
|
||||
{
|
||||
$this->setMeta('avif', $data['avifStatus']);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$this->image_meta = $metaObj;
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return false; // no parents here
|
||||
}
|
||||
|
||||
/** Load a CustomImageModel as Stub ( to be added ) . Checks if the image is already added as well
|
||||
*
|
||||
* @param String $path
|
||||
* @param Boolean $load
|
||||
*/
|
||||
public function setStub($path, $load = true)
|
||||
{
|
||||
$this->fullpath = $path;
|
||||
$this->path_md5 = md5($this->fullpath);
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$sql = 'SELECT id from ' . $wpdb->prefix . 'shortpixel_meta where path = %s';
|
||||
$sql = $wpdb->prepare($sql, $path);
|
||||
|
||||
$result = $wpdb->get_var($sql);
|
||||
if ( ! is_null($result) )
|
||||
{
|
||||
$this->in_db = true;
|
||||
$this->id = $result;
|
||||
if ($load)
|
||||
$this->loadMeta();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->image_meta = new ImageMeta();
|
||||
$this->image_meta->compressedSize = 0;
|
||||
$this->image_meta->tsOptimized = 0;
|
||||
$this->image_meta->tsAdded = time();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function preventNextTry($reason = '', $status = self::FILE_STATUS_PREVENT)
|
||||
{
|
||||
$this->setMeta('errorMessage', $reason);
|
||||
$this->setMeta('status', $status);
|
||||
$this->saveMeta();
|
||||
}
|
||||
|
||||
public function markCompleted($reason, $status)
|
||||
{
|
||||
return $this->preventNextTry($reason, $status);
|
||||
}
|
||||
|
||||
public function isOptimizePrevented()
|
||||
{
|
||||
$status = $this->getMeta('status');
|
||||
|
||||
if ($status == self::FILE_STATUS_PREVENT || $status == self::FILE_STATUS_MARKED_DONE )
|
||||
{
|
||||
$this->processable_status = self::P_OPTIMIZE_PREVENTED;
|
||||
$this->optimizePreventedReason = $this->getMeta('errorMessage');
|
||||
|
||||
return $this->getMeta('errorMessage');
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only one item for now, so it's equal
|
||||
public function isSomethingOptimized()
|
||||
{
|
||||
return $this->isOptimized();
|
||||
}
|
||||
|
||||
public function resetPrevent()
|
||||
{
|
||||
|
||||
if ($this->hasBackup())
|
||||
$this->setMeta('status', self::FILE_STATUS_SUCCESS);
|
||||
else
|
||||
$this->setMeta('status', self::FILE_STATUS_UNPROCESSED);
|
||||
|
||||
$this->setMeta('errorMessage', '');
|
||||
$this->saveMeta();
|
||||
}
|
||||
|
||||
public function saveMeta()
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
$table = $wpdb->prefix . 'shortpixel_meta';
|
||||
$where = array('id' => $this->id);
|
||||
|
||||
$metaObj = $this->image_meta;
|
||||
|
||||
if (! is_null($metaObj->customImprovement) && is_numeric($metaObj->customImprovement))
|
||||
$message = $metaObj->customImprovement;
|
||||
elseif (! is_null($metaObj->errorMessage))
|
||||
$message = $metaObj->errorMessage;
|
||||
else
|
||||
$message = null;
|
||||
|
||||
$optimized = new \DateTime();
|
||||
$optimized->setTimestamp($metaObj->tsOptimized);
|
||||
|
||||
$added = new \DateTime();
|
||||
$added->setTimeStamp($metaObj->tsAdded);
|
||||
|
||||
$extra_info = array();
|
||||
if ($this->getMeta('webp') === self::FILETYPE_BIGGER)
|
||||
{
|
||||
$extra_info['webpStatus'] = self::FILETYPE_BIGGER;
|
||||
}
|
||||
if ($this->getMeta('avif') === self::FILETYPE_BIGGER)
|
||||
{
|
||||
$extra_info['avifStatus'] = self::FILETYPE_BIGGER;
|
||||
}
|
||||
|
||||
if (count($extra_info) > 0)
|
||||
{
|
||||
$extra_info = json_encode($extra_info);
|
||||
}
|
||||
else {
|
||||
$extra_info = null;
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'folder_id' => $this->folder_id,
|
||||
'compressed_size' => $metaObj->compressedSize,
|
||||
'compression_type' => $metaObj->compressionType,
|
||||
'keep_exif' => ($metaObj->did_keepExif) ? 1 : 0,
|
||||
'cmyk2rgb' => ($metaObj->did_cmyk2rgb) ? 1 : 0,
|
||||
'resize' => ($metaObj->resize) ? 1 : 0,
|
||||
'resize_width' => $metaObj->resizeWidth,
|
||||
'resize_height' => $metaObj->resizeHeight,
|
||||
'backup' => ($this->hasBackup()) ? 1 : 0,
|
||||
'status' => $metaObj->status,
|
||||
'retries' => 0, // this is unused / legacy
|
||||
'message' => $message, // this is used for improvement line.
|
||||
'ts_added' => UtilHelper::timestampToDB($metaObj->tsAdded),
|
||||
'ts_optimized' => UtilHelper::timestampToDB($metaObj->tsOptimized),
|
||||
'path' => $this->getFullPath(),
|
||||
'name' => $this->getFileName(),
|
||||
'path_md5' => md5($this->getFullPath()), // this is legacy
|
||||
'extra_info' => $extra_info,
|
||||
);
|
||||
// The keys are just for readability.
|
||||
$format = array(
|
||||
'folder_id' => '%d',
|
||||
'compressed_size' => '%d',
|
||||
'compression_type' => '%d' ,
|
||||
'keep_exif' => '%d' ,
|
||||
'cmyk2rgb' => '%d' ,
|
||||
'resize' => '%d' ,
|
||||
'resize_width' => '%d',
|
||||
'resize_height' => '%d',
|
||||
'backup' => '%d',
|
||||
'status' => '%d',
|
||||
'retries' => '%d', // this is unused / legacy
|
||||
'message' => '%s', // this is used for improvement line.
|
||||
'ts_added' => '%s',
|
||||
'ts_optimized' => '%s' ,
|
||||
'path' => '%s',
|
||||
'name' => '%s',
|
||||
'path_md5' => '%s' , // this is legacy
|
||||
'extra_info' => '%s',
|
||||
);
|
||||
|
||||
|
||||
$is_new = false;
|
||||
|
||||
if ($this->in_db)
|
||||
{
|
||||
$res = $wpdb->update($table, $data, $where, $format); // result is amount rows updated.
|
||||
}
|
||||
else
|
||||
{
|
||||
$is_new = true;
|
||||
$res = $wpdb->insert($table, $data, $format); // result is new inserted id
|
||||
}
|
||||
|
||||
if ($is_new)
|
||||
{
|
||||
$this->id = $wpdb->insert_id;
|
||||
}
|
||||
|
||||
if ($res !== false)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public function deleteMeta()
|
||||
{
|
||||
global $wpdb;
|
||||
$table = $wpdb->prefix . 'shortpixel_meta';
|
||||
$where = array('id' => $this->id);
|
||||
|
||||
$result = $wpdb->delete($table, $where, array('%d'));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function onDelete()
|
||||
{
|
||||
parent::onDelete();
|
||||
$this->deleteMeta();
|
||||
$this->dropfromQueue();
|
||||
}
|
||||
|
||||
public function dropFromQueue()
|
||||
{
|
||||
$optimizeController = new OptimizeController();
|
||||
|
||||
$q = $optimizeController->getQueue($this->type);
|
||||
$q->dropItem($this->get('id'));
|
||||
|
||||
// Drop also from bulk if there.
|
||||
|
||||
$optimizeController->setBulk(true);
|
||||
|
||||
$q = $optimizeController->getQueue($this->type);
|
||||
$q->dropItem($this->get('id'));
|
||||
}
|
||||
|
||||
public function getImprovement($int = false)
|
||||
{
|
||||
return $this->getMeta('customImprovement');
|
||||
}
|
||||
|
||||
public function getImprovements()
|
||||
{
|
||||
$improvements = array();
|
||||
/*$totalsize = $totalperc = $count = 0;
|
||||
if ($this->isOptimized())
|
||||
{
|
||||
$perc = $this->getImprovement();
|
||||
$size = $this->getImprovement(true);
|
||||
$totalsize += $size;
|
||||
$totalperc += $perc;
|
||||
$improvements['main'] = array($perc, $size);
|
||||
$count++;
|
||||
} */
|
||||
$improvement = $this->getImprovement();
|
||||
if (is_null($improvement)) // getImprovement can return null.
|
||||
{
|
||||
$improvement = 0;
|
||||
}
|
||||
$improvements['main'] = array($improvement, 0);
|
||||
$improvements['totalpercentage'] = round($improvement); // the same.
|
||||
|
||||
return $improvements;
|
||||
|
||||
// return $improvements; // we have no thumbnails.
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
namespace ShortPixel\Model\Image;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
||||
|
||||
class ImageConvertMeta
|
||||
{
|
||||
|
||||
protected $fileFormat; // png / heic etc
|
||||
protected $isConverted = false;
|
||||
protected $placeholder = false;
|
||||
protected $replacementImageBase = false;
|
||||
// protected $doConversion = false;
|
||||
protected $triedConversion = false;
|
||||
protected $errorReason = false;
|
||||
protected $omitBackup = true; // Don't backup the converted image (again), keeping only the original format. if not, make a backup of the converted file and treat that as the default backup/restore
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function isConverted()
|
||||
{
|
||||
return $this->isConverted;
|
||||
}
|
||||
|
||||
public function didTry()
|
||||
{
|
||||
return $this->triedConversion;
|
||||
}
|
||||
|
||||
public function setTried($value)
|
||||
{
|
||||
$this->triedConversion = $value;
|
||||
}
|
||||
|
||||
public function setConversionDone($omitBackup = true)
|
||||
{
|
||||
$this->isConverted = true;
|
||||
$this->omitBackup = $omitBackup;
|
||||
}
|
||||
|
||||
public function setError($code)
|
||||
{
|
||||
$this->errorReason = $code;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
{
|
||||
return $this->errorReason;
|
||||
}
|
||||
|
||||
public function setFileFormat($ext)
|
||||
{
|
||||
if (is_null($this->fileFormat))
|
||||
$this->fileFormat = $ext;
|
||||
}
|
||||
|
||||
public function getFileFormat()
|
||||
{
|
||||
return $this->fileFormat;
|
||||
}
|
||||
|
||||
public function omitBackup()
|
||||
{
|
||||
return $this->omitBackup;
|
||||
}
|
||||
|
||||
// bool for now, otherwise if needed.
|
||||
public function setPlaceHolder($placeholder = true)
|
||||
{
|
||||
$this->placeholder = $placeholder;
|
||||
}
|
||||
|
||||
public function hasPlaceHolder()
|
||||
{
|
||||
return $this->placeholder;
|
||||
}
|
||||
|
||||
public function setReplacementImageBase($name)
|
||||
{
|
||||
$this->replacementImageBase = $name;
|
||||
|
||||
}
|
||||
|
||||
public function getReplacementImageBase()
|
||||
{
|
||||
return $this->replacementImageBase;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function fromClass($object)
|
||||
{
|
||||
foreach($object as $property => $value)
|
||||
{
|
||||
if (property_exists($this, $property))
|
||||
{
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function toClass()
|
||||
{
|
||||
$class = new \stdClass;
|
||||
$vars = get_object_vars($this);
|
||||
|
||||
foreach($vars as $property => $value) // only used by media library.
|
||||
{
|
||||
$class->$property = $this->$property;
|
||||
}
|
||||
return $class;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace ShortPixel\Model\Image;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
// Base Class for ImageMeta
|
||||
class ImageMeta extends ImageThumbnailMeta
|
||||
{
|
||||
|
||||
public $errorMessage;
|
||||
public $wasConverted = false; // Was converted from legacy format
|
||||
|
||||
protected $convertMeta;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->convertMeta = new ImageConvertMeta();
|
||||
|
||||
}
|
||||
|
||||
public function fromClass($object)
|
||||
{
|
||||
if (property_exists($object, 'convertMeta'))
|
||||
{
|
||||
|
||||
$this->convertMeta->fromClass($object->convertMeta);
|
||||
unset($object->convertMeta);
|
||||
}
|
||||
// legacy.
|
||||
if (property_exists($object, 'tried_png2jpg') && $object->tried_png2jpg)
|
||||
{
|
||||
$this->convertMeta()->setTried($object->tried_png2jpg);
|
||||
}
|
||||
elseif (property_exists($object, 'did_png2jpg') && $object->did_png2jpg)
|
||||
{
|
||||
$this->convertMeta()->setFileFormat('png');
|
||||
$this->convertMeta()->setConversionDone();
|
||||
|
||||
}
|
||||
|
||||
parent::fromClass($object);
|
||||
}
|
||||
|
||||
|
||||
public function convertMeta()
|
||||
{
|
||||
return $this->convertMeta;
|
||||
}
|
||||
|
||||
} // class
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
namespace ShortPixel\Model\Image;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
||||
|
||||
class ImageThumbnailMeta
|
||||
{
|
||||
/** @var int */
|
||||
public $databaseID = null;
|
||||
/** @var int */
|
||||
public $status = 0;
|
||||
/** @var int */
|
||||
public $compressionType;
|
||||
/** @var int */
|
||||
public $compressedSize;
|
||||
/** @var int */
|
||||
public $originalSize;
|
||||
// public $improvement;
|
||||
|
||||
/** @var boolean */
|
||||
public $did_keepExif = false;
|
||||
|
||||
/** @var boolean */
|
||||
public $did_cmyk2rgb = false;
|
||||
|
||||
/** @var int */
|
||||
public $resize;
|
||||
/** @var int */
|
||||
public $resizeWidth;
|
||||
/** @var int */
|
||||
public $resizeHeight;
|
||||
/** @var int */
|
||||
public $resizeType;
|
||||
/** @var int */
|
||||
public $originalWidth;
|
||||
/** @var int */
|
||||
public $originalHeight;
|
||||
|
||||
public $tsAdded;
|
||||
public $tsOptimized;
|
||||
public $webp;
|
||||
public $avif;
|
||||
|
||||
public $file; // **Only for unlisted images. This defines an unlisted image */
|
||||
|
||||
// Only for customImageModel! Exception to prevent having to create a whole class. Second var here, warrants a subclass.
|
||||
public $customImprovement;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->tsAdded = time(); // default
|
||||
}
|
||||
|
||||
|
||||
/** Load data from basic class to prevent issues when class definitions changes over time */
|
||||
public function fromClass($object)
|
||||
{
|
||||
|
||||
foreach($object as $property => $value)
|
||||
{
|
||||
if ($property == 'customImprovement')
|
||||
{ continue; }
|
||||
|
||||
|
||||
if (property_exists($this, $property))
|
||||
{
|
||||
$this->$property = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Save data as basic class to prevent issues when class definitions changes over time */
|
||||
public function toClass()
|
||||
{
|
||||
$class = new \stdClass;
|
||||
$vars = get_object_vars($this);
|
||||
|
||||
foreach($vars as $property => $value) // only used by media library.
|
||||
{
|
||||
if ($property == 'customImprovement')
|
||||
{ continue; }
|
||||
|
||||
if ($property == 'convertMeta' && is_null($this->convertMeta))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elseif ($property == 'convertMeta') {
|
||||
$class->$property = $this->$property->toClass();
|
||||
continue;
|
||||
}
|
||||
// if (is_null($value)) // don't save default / values without init.
|
||||
// continue;
|
||||
|
||||
|
||||
$class->$property = $this->$property;
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,591 @@
|
||||
<?php
|
||||
namespace ShortPixel\Model\Image;
|
||||
|
||||
use ShortPixel\Helper\DownloadHelper as DownloadHelper;
|
||||
use ShortPixel\Helper\UtilHelper as UtilHelper;
|
||||
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
||||
|
||||
use \ShortPixel\Model\File\FileModel as FileModel;
|
||||
|
||||
// Represent a thumbnail image / limited image in mediaLibrary.
|
||||
class MediaLibraryThumbnailModel extends \ShortPixel\Model\Image\ImageModel
|
||||
{
|
||||
|
||||
public $name;
|
||||
|
||||
/* public $width;
|
||||
public $height;
|
||||
public $mime; */
|
||||
protected $prevent_next_try = false;
|
||||
protected $is_main_file = false;
|
||||
protected $is_retina = false; // diffentiate from thumbnail / retina.
|
||||
protected $id; // this is the parent attachment id
|
||||
protected $size; // size name of image in WP, if applicable.
|
||||
protected $sizeDefinition; // size width / height / crop according to WordPress
|
||||
|
||||
public function __construct($path, $id, $size)
|
||||
{
|
||||
|
||||
parent::__construct($path);
|
||||
$this->image_meta = new ImageThumbnailMeta();
|
||||
$this->id = $id;
|
||||
$this->imageType = self::IMAGE_TYPE_THUMB;
|
||||
$this->size = $size;
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected function loadMeta()
|
||||
{
|
||||
}
|
||||
|
||||
protected function saveMeta()
|
||||
{
|
||||
}
|
||||
|
||||
public function __debugInfo() {
|
||||
return array(
|
||||
'image_meta' => $this->image_meta,
|
||||
'name' => $this->name,
|
||||
'path' => $this->getFullPath(),
|
||||
'size' => $this->size,
|
||||
'width' => $this->get('width'),
|
||||
'height' => $this->get('height'),
|
||||
'exists' => ($this->exists()) ? 'yes' : 'no',
|
||||
'is_virtual' => ($this->is_virtual()) ? 'yes' : 'no',
|
||||
'wordpress_size' => $this->sizeDefinition,
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/** Set the meta name of thumbnail. */
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function setSizeDefinition($sizedef)
|
||||
{
|
||||
$this->sizeDefinition = $sizedef;
|
||||
}
|
||||
|
||||
public function setImageType($type)
|
||||
{
|
||||
$this->imageType = $type;
|
||||
}
|
||||
|
||||
public function getRetina()
|
||||
{
|
||||
if ($this->is_virtual())
|
||||
{
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
$filepath = apply_filters('shortpixel/file/virtual/translate', $this->getFullPath(), $this);
|
||||
$virtualFile = $fs->getFile($filepath);
|
||||
|
||||
$filebase = $virtualFile->getFileBase();
|
||||
$filepath = (string) $virtualFile->getFileDir();
|
||||
$extension = $virtualFile->getExtension();
|
||||
|
||||
// This function needs an hard check on file exists, which might not be wanted.
|
||||
if (false === \wpSPIO()->env()->useVirtualHeavyFunctions())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
$filebase = $this->getFileBase();
|
||||
$filepath = (string) $this->getFileDir();
|
||||
$extension = $this->getExtension();
|
||||
}
|
||||
|
||||
$retina = new MediaLibraryThumbnailModel($filepath . $filebase . '@2x.' . $extension, $this->id, $this->size); // mind the dot in after 2x
|
||||
$retina->setName($this->size);
|
||||
$retina->setImageType(self::IMAGE_TYPE_RETINA);
|
||||
|
||||
$retina->is_retina = true;
|
||||
|
||||
$forceCheck = true;
|
||||
if ($retina->exists($forceCheck))
|
||||
return $retina;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isFileTypeNeeded($type = 'webp')
|
||||
{
|
||||
// pdf extension can be optimized, but don't come with these filetypes
|
||||
if ($this->getExtension() == 'pdf')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($type == 'webp')
|
||||
$file = $this->getWebp();
|
||||
elseif ($type == 'avif')
|
||||
$file = $this->getAvif();
|
||||
|
||||
if ( ($this->isThumbnailProcessable() || $this->isOptimized()) && $file === false) // if no file, it can be optimized.
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// @param FileDelete can be false. I.e. multilang duplicates might need removal of metadata, but not images.
|
||||
public function onDelete($fileDelete = true)
|
||||
{
|
||||
if ($fileDelete == true)
|
||||
$bool = parent::onDelete();
|
||||
else {
|
||||
$bool = true;
|
||||
}
|
||||
|
||||
// minimally reset all the metadata.
|
||||
if ($this->is_main_file)
|
||||
{
|
||||
$this->image_meta = new ImageMeta();
|
||||
}
|
||||
else {
|
||||
$this->image_meta = new ImageThumbnailMeta();
|
||||
}
|
||||
|
||||
return $bool;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function setMetaObj($metaObj)
|
||||
{
|
||||
$this->image_meta = clone $metaObj;
|
||||
}
|
||||
|
||||
protected function getMetaObj()
|
||||
{
|
||||
return $this->image_meta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get_path param see MediaLibraryModel
|
||||
// This should be unused at the moment!
|
||||
public function getOptimizeUrls()
|
||||
{
|
||||
if (! $this->isProcessable() )
|
||||
return false;
|
||||
|
||||
$url = $this->getURL();
|
||||
|
||||
if (! $url)
|
||||
{
|
||||
return false; //nothing
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function getURL()
|
||||
{
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
|
||||
if ($this->size == 'original' && ! $this->get('is_retina'))
|
||||
{
|
||||
$url = wp_get_original_image_url($this->id);
|
||||
}
|
||||
elseif ($this->isUnlisted())
|
||||
{
|
||||
$url = $fs->pathToUrl($this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can't trust higher lever function, or any WP functions. I.e. Woocommerce messes with the URL's if they like so.
|
||||
// So get it from intermediate and if that doesn't work, default to pathToUrl - better than nothing.
|
||||
// https://app.asana.com/0/1200110778640816/1202589533659780
|
||||
$size_array = image_get_intermediate_size($this->id, $this->size);
|
||||
|
||||
if ($size_array === false || ! isset($size_array['url']))
|
||||
{
|
||||
$url = $fs->pathToUrl($this);
|
||||
}
|
||||
elseif (isset($size_array['url']))
|
||||
{
|
||||
$url = $size_array['url'];
|
||||
// Even this can go wrong :/
|
||||
if (strpos($url, $this->getFileName() ) === false)
|
||||
{
|
||||
// Taken from image_get_intermediate_size if somebody still messes with the filters.
|
||||
$mainurl = wp_get_attachment_url( $this->id);
|
||||
$url = path_join( dirname( $mainurl ), $this->getFileName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->fs()->checkURL($url);
|
||||
}
|
||||
|
||||
// Just a placeholder for abstract, shouldn't do anything.
|
||||
public function getImprovements()
|
||||
{
|
||||
return parent::getImprovements();
|
||||
}
|
||||
|
||||
|
||||
public function getBackupFileName()
|
||||
{
|
||||
$mainFile = ($this->is_main_file) ? $this : $this->getMainFile();
|
||||
if (false == $mainFile)
|
||||
{
|
||||
return parent::getBackupFileName();
|
||||
}
|
||||
|
||||
if ($mainFile->getMeta()->convertMeta()->getReplacementImageBase() !== false)
|
||||
{
|
||||
if ($this->is_main_file)
|
||||
return $mainFile->getMeta()->convertMeta()->getReplacementImageBase() . '.' . $this->getExtension();
|
||||
else {
|
||||
// $fileBaseNoSize =
|
||||
$name = str_replace($mainFile->getFileBase(), $mainFile->getMeta()->convertMeta()->getReplacementImageBase(), $this->getFileName());
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getBackupFileName();
|
||||
}
|
||||
|
||||
|
||||
protected function preventNextTry($reason = '')
|
||||
{
|
||||
$this->prevent_next_try = $reason;
|
||||
}
|
||||
|
||||
// Don't ask thumbnails this, only the main image
|
||||
public function isOptimizePrevented()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't ask thumbnails this, only the main image
|
||||
public function resetPrevent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function isThumbnailProcessable()
|
||||
{
|
||||
// if thumbnail processing is off, thumbs are never processable.
|
||||
// This is also used by main file, so check for that!
|
||||
|
||||
if ( $this->excludeThumbnails() && $this->is_main_file === false && $this->get('imageType') !== self::IMAGE_TYPE_ORIGINAL)
|
||||
{
|
||||
$this->processable_status = self::P_EXCLUDE_SIZE;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$bool = parent::isProcessable();
|
||||
|
||||
return $bool;
|
||||
}
|
||||
}
|
||||
|
||||
/** Function to check if said thumbnail is a WP-native or something SPIO added as unlisted
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected function isUnlisted()
|
||||
{
|
||||
if (! is_null($this->getMeta('file')))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// !Important . This doubles as checking excluded image sizes.
|
||||
protected function isSizeExcluded()
|
||||
{
|
||||
|
||||
$excludeSizes = \wpSPIO()->settings()->excludeSizes;
|
||||
|
||||
if (is_array($excludeSizes) && in_array($this->name, $excludeSizes))
|
||||
{
|
||||
$this->processable_status = self::P_EXCLUDE_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
$bool = parent::isSizeExcluded();
|
||||
|
||||
return $bool;
|
||||
}
|
||||
|
||||
public function isProcessableFileType($type = 'webp')
|
||||
{
|
||||
// Prevent webp / avif processing for thumbnails if this is off. Exclude main file
|
||||
if ($this->excludeThumbnails() === true && $this->is_main_file === false )
|
||||
return false;
|
||||
|
||||
return parent::isProcessableFileType($type);
|
||||
}
|
||||
|
||||
protected function getExcludePatterns()
|
||||
{
|
||||
$args = array(
|
||||
'filter' => true,
|
||||
'thumbname' => $this->name,
|
||||
'is_thumbnail' => (true === $this->is_main_file) ? false : true,
|
||||
);
|
||||
|
||||
// @todo Find a way to cache IsProcessable perhaps due to amount of checks being done. Should be release in flushOptimizeCache or elsewhere (?)
|
||||
|
||||
// $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
|
||||
|
||||
$patterns = UtilHelper::getExclusions($args);
|
||||
// echo "<PRE>"; print_r($args); print_r($patterns); echo "</PRE>";
|
||||
return $patterns;
|
||||
}
|
||||
|
||||
protected function excludeThumbnails()
|
||||
{
|
||||
return (! \wpSPIO()->settings()->processThumbnails);
|
||||
}
|
||||
|
||||
public function hasBackup($args = array())
|
||||
{
|
||||
$defaults = array(
|
||||
'forceConverted' => false,
|
||||
'noConversionCheck' => false, // do not check on mainfile, this loops when used in loadMeta / legacyConversion
|
||||
);
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
// @todo This can probably go.
|
||||
if (true === $args['noConversionCheck'])
|
||||
{
|
||||
return parent::hasBackup();
|
||||
}
|
||||
|
||||
$mainFile = ($this->is_main_file) ? $this : $this->getMainFile();
|
||||
if (false == $mainFile)
|
||||
{
|
||||
return parent::hasBackup();
|
||||
|
||||
}
|
||||
|
||||
// When main file and converted and omitBackup is true ( only original backup ) and not forced.
|
||||
$loadRegular= (false === $mainFile->getMeta()->convertMeta()->isConverted() ||
|
||||
false === $mainFile->getMeta()->convertMeta()->omitBackup()) && false === $args['forceConverted'];
|
||||
|
||||
if (true === $loadRegular)
|
||||
{
|
||||
return parent::hasBackup();
|
||||
}
|
||||
else
|
||||
{
|
||||
$directory = $this->getBackupDirectory();
|
||||
$converted_ext = $mainFile->getMeta()->convertMeta()->getFileFormat();
|
||||
|
||||
if (! $directory)
|
||||
return false;
|
||||
|
||||
|
||||
$backupFile = $directory . $this->getFileBase() . '.' . $converted_ext;
|
||||
|
||||
// Issue with PNG not being scaled on the main file.
|
||||
if (! file_exists($backupFile) && $mainFile->isScaled())
|
||||
{
|
||||
$backupFile = $directory . $mainFile->getOriginalFile()->getFileBase() . '.' . $converted_ext;
|
||||
}
|
||||
if (file_exists($backupFile) && ! is_dir($backupFile) )
|
||||
return true;
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function hasDBRecord()
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
$sql = 'SELECT id FROM ' . $wpdb->prefix . 'shortpixel_postmeta WHERE attach_id = %d AND size = %s';
|
||||
$sql = $wpdb->prepare($sql, $this->id, $this->size);
|
||||
|
||||
$id = $wpdb->get_var($sql);
|
||||
|
||||
if (is_null($id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
elseif (is_numeric($id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function restore()
|
||||
{
|
||||
if ($this->is_virtual())
|
||||
{
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
$filepath = apply_filters('shortpixel/file/virtual/translate', $this->getFullPath(), $this);
|
||||
|
||||
$this->setVirtualToReal($filepath);
|
||||
}
|
||||
|
||||
$bool = parent::restore();
|
||||
|
||||
if ($bool === true)
|
||||
{
|
||||
if ($this->is_main_file)
|
||||
{
|
||||
// If item is converted and will not be moved back to original format ( but converted ) , keep the convert metadata
|
||||
if (true === $this->getMeta()->convertMeta()->isConverted() && false === $this->getMeta()->convertMeta()->omitBackup() )
|
||||
{
|
||||
$convertMeta = clone $this->getMeta()->convertMeta();
|
||||
$imageMeta = new ImageMeta();
|
||||
$imageMeta->convertMeta()->fromClass($convertMeta);
|
||||
$bool = false; // Prevent cleanRestore from deleting the metadata.
|
||||
}
|
||||
else {
|
||||
$imageMeta = new ImageMeta();
|
||||
}
|
||||
|
||||
$this->image_meta = $imageMeta;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->image_meta = new ImageThumbNailMeta();
|
||||
}
|
||||
}
|
||||
|
||||
return $bool;
|
||||
}
|
||||
|
||||
/** Tries to retrieve an *existing* BackupFile. Returns false if not present.
|
||||
* This file might not be writable.
|
||||
* To get writable directory reference to backup, use FileSystemController
|
||||
*/
|
||||
public function getBackupFile($args = array())
|
||||
{
|
||||
|
||||
$defaults = array(
|
||||
'forceConverted' => false,
|
||||
'noConversionCheck' => false, // do not check on mainfile, this loops when used in loadMeta / legacyConversion
|
||||
);
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
if (true === $args['noConversionCheck'])
|
||||
{
|
||||
return parent::getBackupFile();
|
||||
}
|
||||
|
||||
$mainFile = ($this->is_main_file) ? $this : $this->getMainFile();
|
||||
if (false == $mainFile)
|
||||
{
|
||||
return parent::getBackupFile();
|
||||
|
||||
}
|
||||
// When main file and converted and omitBackup is true ( only original backup ) and not forced.
|
||||
$loadRegular= (false === $mainFile->getMeta()->convertMeta()->isConverted() ||
|
||||
false === $mainFile->getMeta()->convertMeta()->omitBackup()) && false === $args['forceConverted'];
|
||||
|
||||
if (true === $loadRegular )
|
||||
{
|
||||
return parent::getBackupFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->hasBackup($args))
|
||||
{
|
||||
|
||||
$directory = $this->getBackupDirectory();
|
||||
$converted_ext = $mainFile->getMeta()->convertMeta()->getFileFormat();
|
||||
|
||||
$backupFile = $directory . $this->getFileBase() . '.' . $converted_ext;
|
||||
|
||||
/* Because WP doesn't support big PNG with scaled for some reason, it's possible it doesn't create them. Which means we end up with a scaled images without backup */
|
||||
if (! file_exists($backupFile) && $mainFile->isScaled())
|
||||
{
|
||||
$backupFile = $directory . $mainFile->getOriginalFile()->getFileBase() . '.' . $converted_ext;
|
||||
}
|
||||
|
||||
return new FileModel($backupFile);
|
||||
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function createBackup()
|
||||
{
|
||||
if ($this->is_virtual()) // download remote file to backup.
|
||||
{
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
$filepath = apply_filters('shortpixel/file/virtual/translate', $this->getFullPath(), $this);
|
||||
|
||||
$result = false;
|
||||
if ($this->virtual_status == self::$VIRTUAL_REMOTE)
|
||||
{
|
||||
// filepath is translated. Check if this exists as a local copy, if not remotely download.
|
||||
if ($filepath !== $this->getFullPath())
|
||||
{
|
||||
$fileObj = $fs->getFile($filepath);
|
||||
$fileExists = $fileObj->exists();
|
||||
}
|
||||
else {
|
||||
$fileExists = false;
|
||||
}
|
||||
|
||||
if (false === $fileExists)
|
||||
{
|
||||
$downloadHelper = DownloadHelper::getInstance();
|
||||
$url = $this->getURL();
|
||||
$result = $downloadHelper->downloadFile($url, array('destinationPath' => $filepath));
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($this->virtual_status == self::$VIRTUAL_STATELESS)
|
||||
{
|
||||
$result = $filepath;
|
||||
}
|
||||
else {
|
||||
Log::addWarning('Virtual Status not set. Trying to blindly download vv DownloadHelper');
|
||||
$downloadHelper = DownloadHelper::getInstance();
|
||||
$url = $this->getURL();
|
||||
$result = $downloadHelper->downloadFile($url, array('destinationPath' => $filepath));
|
||||
}
|
||||
|
||||
if ($result == false)
|
||||
{
|
||||
$this->preventNextTry(__('Fatal Issue: Remote virtual file could not be downloaded for backup', 'shortpixel-image-optimiser'));
|
||||
Log::addError('Remote file download failed from : ' . $url . ' to: ' . $filepath, $this->getURL());
|
||||
$this->error_message = __('Remote file could not be downloaded' . $this->getFullPath(), 'shortpixel-image-optimiser');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setVirtualToReal($filepath);
|
||||
}
|
||||
|
||||
return parent::createBackup();
|
||||
}
|
||||
|
||||
// @todo This is a breach of pattern to realize checking for changes to the main image path on conversion / duplicates.
|
||||
private function getMainFile()
|
||||
{
|
||||
$fs = \wpSPIO()->filesystem();
|
||||
return $fs->getMediaImage($this->id, true, true);
|
||||
}
|
||||
|
||||
} // class
|
Reference in New Issue
Block a user