File "wp-short-pixel.php"
Full path: /home/kosmetik/public_html/wp-content/plugins/shortpixel-image-optimiser/class/wp-short-pixel.php
File
size: 141.64 B
MIME-type: text/x-php
Charset: utf-8
Download Open Edit Advanced Editor Back
<?php
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
use ShortPixel\Notices\NoticeController as Notices;
use ShortPixel\Model\FileModel as FileModel;
use ShortPixel\Model\Directorymodel as DirectoryModel;
use ShortPixel\Model\ImageModel as ImageModel;
use ShortPixel\Controller\AdminNoticesController as AdminNoticesController;
class WPShortPixel
{
const BULK_EMPTY_QUEUE = 0;
private $_apiInterface = null;
private $_settings = null;
private $prioQ = null;
private $view = null;
private $thumbnailsRegenerating = array();
private $spMetaDao = null;
private $jsSuffix = '.min.js';
private $timer;
public static $PROCESSABLE_EXTENSIONS = array('jpg', 'jpeg', 'gif', 'png', 'pdf');
private static $first_run = false;
public function __construct()
{
$this->timer = time();
if (Log::debugIsActive()) {
$this->jsSuffix = '.js';
}
load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname(SHORTPIXEL_PLUGIN_FILE)) . '/lang');
$isAdminUser = current_user_can('manage_options');
$this->_settings = new WPShortPixelSettings();
$this->_apiInterface = new ShortPixelAPI($this->_settings);
$this->spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $this->_settings->excludePatterns);
$this->prioQ = !defined('SHORTPIXEL_NOFLOCK') ? new ShortPixelQueue($this, $this->_settings) : new ShortPixelQueueDB($this, $this->_settings);
$this->view = new ShortPixelView($this);
}
public function loadHooks()
{
self::$first_run = true;
load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname(SHORTPIXEL_PLUGIN_FILE)) . '/lang');
$isAdminUser = current_user_can('manage_options');
define('QUOTA_EXCEEDED', $this->view->getQuotaExceededHTML());
if (!defined('SHORTPIXEL_CUSTOM_THUMB_SUFFIXES')) {
if (is_plugin_active('envira-gallery/envira-gallery.php') || is_plugin_active('soliloquy-lite/soliloquy-lite.php') || is_plugin_active('soliloquy/soliloquy.php')) {
define('SHORTPIXEL_CUSTOM_THUMB_SUFFIXES', '_c,_tl,_tr,_br,_bl');
} elseif (defined('SHORTPIXEL_CUSTOM_THUMB_SUFFIX')) {
define('SHORTPIXEL_CUSTOM_THUMB_SUFFIXES', SHORTPIXEL_CUSTOM_THUMB_SUFFIX);
}
}
$this->setDefaultViewModeList();
add_filter('plugin_action_links_' . plugin_basename(SHORTPIXEL_PLUGIN_FILE), array(&$this, 'generatePluginLinks'));
add_filter('manage_media_columns', array(&$this, 'columns'));
add_action('manage_media_custom_column', array(&$this, 'generateCustomColumn'), 10, 2);
add_filter('manage_upload_sortable_columns', array(&$this, 'columnRegisterSortable'));
add_filter('request', array(&$this, 'columnOrderFilterBy'));
add_action('restrict_manage_posts', array(&$this, 'mediaAddFilterDropdown'));
add_action('add_meta_boxes', array(&$this, 'shortpixelInfoBox'));
add_action('delete_attachment', array(&$this, 'onDeleteImage'));
add_action('mime_types', array($this, 'addWebpMime'));
add_action('mime_types', array($this, 'addAvifMime'));
add_action('wplr_update_media', array(&$this, 'onWpLrUpdateMedia'), 10, 2);
add_action('shortpixel-optimize-now', array(&$this, 'optimizeNowHook'), 10, 1);
add_filter('shortpixel_get_backup', array(&$this, 'shortpixelGetBackupFilter'), 10, 1);
if ($isAdminUser) {
add_action('wp_ajax_shortpixel_browse_content', array(&$this, 'browseContent'));
add_action('wp_ajax_shortpixel_get_backup_size', array(&$this, 'getBackupSize'));
add_action('wp_ajax_shortpixel_get_comparer_data', array(&$this, 'getComparerData'));
add_action('wp_ajax_shortpixel_new_api_key', array(&$this, 'newApiKey'));
add_action('wp_ajax_shortpixel_propose_upgrade', array(&$this, 'proposeUpgrade'));
add_action('delete_attachment', array(&$this, 'handleDeleteAttachmentInBackup'));
add_action('load-upload.php', array(&$this, 'handleCustomBulk'));
add_action('admin_action_shortpixel_restore_backup', array(&$this, 'handleRestoreBackup'));
add_action('wp_ajax_shortpixel_redo', array(&$this, 'handleRedo'));
add_action('wp_ajax_shortpixel_optimize_thumbs', array(&$this, 'handleOptimizeThumbs'));
add_action('admin_bar_menu', array(&$this, 'toolbar_shortpixel_processing'), 999);
add_action('admin_post_shortpixel_deactivate_plugin', array(&$this, 'deactivatePlugin'));
$stats = $this->_settings->currentStats;
$totalCredits = isset($stats["APICallsQuotaNumeric"]) ? $stats['APICallsQuotaNumeric'] + $stats['APICallsQuotaOneTimeNumeric'] : 0;
if (true || !$this->_settings->verifiedKey || $totalCredits < 4000) {
require_once 'view/shortpixel-feedback.php';
new ShortPixelFeedback(SHORTPIXEL_PLUGIN_FILE, 'shortpixel-image-optimiser', $this->_settings->apiKey, $this);
}
}
add_action('wp_ajax_shortpixel_image_processing', array(&$this, 'handleImageProcessing'));
add_action('wp_ajax_shortpixel_manual_optimization', array(&$this, 'handleManualOptimization'));
add_action('wp_ajax_shortpixel_check_status', array(&$this, 'checkStatus'));
add_action('wp_ajax_shortpixel_dismiss_notice', array(&$this, 'dismissAdminNotice'));
add_action('wp_ajax_shortpixel_dismiss_media_alert', array($this, 'dismissMediaAlert'));
add_action('wp_ajax_shortpixel_dismissFileError', array($this, 'dismissFileError'));
add_action('wp_ajax_shortpixel_check_quota', array(&$this, 'handleCheckQuota'));
add_action('admin_action_shortpixel_check_quota', array(&$this, 'handleCheckQuota'));
add_action('admin_enqueue_scripts', array($this, 'shortPixelJS'));
add_action('admin_footer', array($this, 'admin_footer_js'));
add_action('admin_notices', array(&$this, 'displayAdminNotices'));
$this->migrateBackupFolder();
}
public function displayAdminNotices()
{
}
public function dismissAdminNotice()
{
$noticeId = preg_replace('|[^a-z0-9]|i', '', $_GET['notice_id']);
$dismissed = $this->_settings->dismissedNotices ? $this->_settings->dismissedNotices : array();
$dismissed[$noticeId] = true;
$this->_settings->dismissedNotices = $dismissed;
if ($_GET['notice_id'] == 'unlisted' && isset($_GET['notice_data']) && $_GET['notice_data'] == 'true') {
$this->_settings->optimizeUnlisted = 1;
}
die(json_encode(array("Status" => 'success', "Message" => 'Notice ID: ' . $noticeId . ' dismissed')));
}
public function dismissMediaAlert()
{
$this->_settings->mediaAlert = 1;
die(json_encode(array("Status" => 'success', "Message" => __('Media alert dismissed', 'shortpixel-image-optimiser'))));
}
public function dismissFileError()
{
$this->_settings->bulkLastStatus = null;
die(json_encode(array("Status" => 'success', "Message" => __('Error dismissed', 'shortpixel-image-optimiser'))));
}
public function setDefaultViewModeList()
{
if ($this->_settings->mediaLibraryViewMode === false) {
$this->_settings->mediaLibraryViewMode = 1;
$currentUserID = false;
if (function_exists('wp_get_current_user')) {
$current_user = wp_get_current_user();
$currentUserID = $current_user->ID;
update_user_meta($currentUserID, "wp_media_library_mode", "list");
}
}
}
static function log($message, $force = false)
{
Log::addInfo($message);
}
protected static function doLog($message, $force = false)
{
Log::addInfo($message);
}
function shortPixelJS()
{
$is_front = wpSPIO()->env()->is_front ? true : false;
wp_enqueue_style('short-pixel-bar.min.css', plugins_url('/res/css/short-pixel-bar.min.css', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
if (\wpSPIO()->env()->is_our_screen) {
wp_enqueue_style('short-pixel.min.css', plugins_url('/res/css/short-pixel.min.css', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
wp_enqueue_style('short-pixel-modal.min.css', plugins_url('/res/css/short-pixel-modal.min.css', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
wp_register_style('shortpixel-admin', plugins_url('/res/css/shortpixel-admin.css', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
wp_enqueue_style('shortpixel-admin');
}
wp_register_script('shortpixel', plugins_url('/res/js/shortpixel' . $this->jsSuffix, SHORTPIXEL_PLUGIN_FILE), array('jquery', 'jquery.knob.min.js'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
$cacheControl = new \ShortPixel\Controller\CacheController();
$bulkSecret = $cacheControl->getItem('bulk-secret');
$secretKey = !is_null($bulkSecret->getValue()) ? $bulkSecret->getValue() : false;
$keyControl = \ShortPixel\Controller\ApiKeyController::getInstance();
$apikey = $keyControl->getKeyForDisplay();
$ShortPixelConstants = array(array('STATUS_SUCCESS' => ShortPixelAPI::STATUS_SUCCESS, 'STATUS_EMPTY_QUEUE' => self::BULK_EMPTY_QUEUE, 'STATUS_ERROR' => ShortPixelAPI::STATUS_ERROR, 'STATUS_FAIL' => ShortPixelAPI::STATUS_FAIL, 'STATUS_QUOTA_EXCEEDED' => ShortPixelAPI::STATUS_QUOTA_EXCEEDED, 'STATUS_SKIP' => ShortPixelAPI::STATUS_SKIP, 'STATUS_NO_KEY' => ShortPixelAPI::STATUS_NO_KEY, 'STATUS_RETRY' => ShortPixelAPI::STATUS_RETRY, 'STATUS_QUEUE_FULL' => ShortPixelAPI::STATUS_QUEUE_FULL, 'STATUS_MAINTENANCE' => ShortPixelAPI::STATUS_MAINTENANCE, 'STATUS_SEARCHING' => ShortPixelAPI::STATUS_SEARCHING, 'WP_PLUGIN_URL' => plugins_url('', SHORTPIXEL_PLUGIN_FILE), 'WP_ADMIN_URL' => admin_url(), 'API_IS_ACTIVE' => $keyControl->keyIsVerified(), 'DEFAULT_COMPRESSION' => 0 + intval($this->_settings->compressionType), 'MEDIA_ALERT' => $this->_settings->mediaAlert ? "done" : "todo", 'FRONT_BOOTSTRAP' => $this->_settings->frontBootstrap && (!isset($this->_settings->lastBackAction) || time() - $this->_settings->lastBackAction > 600) ? 1 : 0, 'AJAX_URL' => admin_url('admin-ajax.php'), 'BULK_SECRET' => $secretKey));
if (Log::isManualDebug()) {
Log::addInfo('Ajax Manual Debug Mode');
$logLevel = Log::getLogLevel();
$ShortPixelConstants[0]['AJAX_URL'] = admin_url('admin-ajax.php?SHORTPIXEL_DEBUG=' . $logLevel);
}
$jsTranslation = array('optimizeWithSP' => __('Optimize with ShortPixel', 'shortpixel-image-optimiser'), 'redoLossy' => __('Re-optimize Lossy', 'shortpixel-image-optimiser'), 'redoGlossy' => __('Re-optimize Glossy', 'shortpixel-image-optimiser'), 'redoLossless' => __('Re-optimize Lossless', 'shortpixel-image-optimiser'), 'restoreOriginal' => __('Restore Originals', 'shortpixel-image-optimiser'), 'changeMLToListMode' => __('In order to access the ShortPixel Optimization actions and info, please change to {0}List View{1}List View{2}Dismiss{3}', 'shortpixel-image-optimiser'), 'alertOnlyAppliesToNewImages' => __('This type of optimization will apply to new uploaded images. Images that were already processed will not be re-optimized unless you restart the bulk process.', 'shortpixel-image-optimiser'), 'areYouSureStopOptimizing' => __('Are you sure you want to stop optimizing the folder {0}?', 'shortpixel-image-optimiser'), 'reducedBy' => __('Reduced by', 'shortpixel-image-optimiser'), 'bonusProcessing' => __('Bonus processing', 'shortpixel-image-optimiser'), 'plusXthumbsOpt' => __('+{0} thumbnails optimized', 'shortpixel-image-optimiser'), 'plusXretinasOpt' => __('+{0} Retina images optimized', 'shortpixel-image-optimiser'), 'optXThumbs' => __('Optimize {0} thumbnails', 'shortpixel-image-optimiser'), 'reOptimizeAs' => __('Reoptimize {0}', 'shortpixel-image-optimiser'), 'restoreBackup' => __('Restore backup', 'shortpixel-image-optimiser'), 'getApiKey' => __('Get API Key', 'shortpixel-image-optimiser'), 'extendQuota' => __('Extend Quota', 'shortpixel-image-optimiser'), 'check__Quota' => __('Check Quota', 'shortpixel-image-optimiser'), 'retry' => __('Retry', 'shortpixel-image-optimiser'), 'thisContentNotProcessable' => __('This content is not processable.', 'shortpixel-image-optimiser'), 'imageWaitOptThumbs' => __('Image waiting to optimize thumbnails', 'shortpixel-image-optimiser'), 'pleaseDoNotSetLesserSize' => __("Please do not set a {0} less than the {1} of the largest thumbnail which is {2}, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser'), 'pleaseDoNotSetLesser1024' => __("Please do not set a {0} less than 1024, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser'), 'confirmBulkRestore' => __("Are you sure you want to restore from backup all the images in your Media Library optimized with ShortPixel?", 'shortpixel-image-optimiser'), 'confirmBulkCleanup' => __("Are you sure you want to cleanup the ShortPixel metadata info for the images in your Media Library optimized with ShortPixel? This will make ShortPixel 'forget' that it optimized them and will optimize them again if you re-run the Bulk Optimization process.", 'shortpixel-image-optimiser'), 'confirmBulkCleanupPending' => __("Are you sure you want to cleanup the pending metadata?", 'shortpixel-image-optimiser'), 'alertDeliverWebPAltered' => __("Warning: Using this method alters the structure of the rendered HTML code (IMG tags get included in PICTURE tags),\nwhich in some rare cases can lead to CSS/JS inconsistencies.\n\nPlease test this functionality thoroughly after activating!\n\nIf you notice any issue, just deactivate it and the HTML will will revert to the previous state.", 'shortpixel-image-optimiser'), 'alertDeliverWebPUnaltered' => __('This option will serve both WebP and the original image using the same URL, based on the web browser capabilities, please make sure you\'re serving the images from your server and not using a CDN which caches the images.', 'shortpixel-image-optimiser'), 'originalImage' => __('Original image', 'shortpixel-image-optimiser'), 'optimizedImage' => __('Optimized image', 'shortpixel-image-optimiser'), 'loading' => __('Loading...', 'shortpixel-image-optimiser'));
$actions = array('nonce_check_quota' => wp_create_nonce('check_quota'));
wp_localize_script('shortpixel', '_spTr', $jsTranslation);
wp_localize_script('shortpixel', 'ShortPixelConstants', $ShortPixelConstants);
wp_localize_script('shortpixel', 'ShortPixelActions', $actions);
wp_register_script('jquery.knob.min.js', plugins_url('/res/js/jquery.knob.min.js', SHORTPIXEL_PLUGIN_FILE));
wp_register_script('jquery.tooltip.min.js', plugins_url('/res/js/jquery.tooltip.min.js', SHORTPIXEL_PLUGIN_FILE));
if (!\wpSPIO()->env()->is_screen_to_use) {
if (!wpSPIO()->env()->is_front) {
return;
}
}
wp_enqueue_script('shortpixel');
wp_enqueue_script('jquery.knob.min.js');
wp_enqueue_script('jquery.tooltip.min.js');
wp_enqueue_script('punycode.min.js', plugins_url('/res/js/punycode.min.js', SHORTPIXEL_PLUGIN_FILE));
}
public function admin_footer_js()
{
if (!\wpSPIO()->env()->is_screen_to_use) {
return;
}
if (function_exists('get_current_screen')) {
$screen = get_current_screen();
if (is_object($screen)) {
if (in_array($screen->id, array('attachment', 'upload', 'media_page_wp-short-pixel-custom'))) {
$this->view->outputComparerHTML();
$this->view->renderListCell("__SP_ID__", 'imgOptimized', true, "__SP_THUMBS_TOTAL__", true, true, array("__SP_FIRST_TYPE__", "__SP_SECOND_TYPE__"), "__SP_CELL_MESSAGE__", 'sp-column-actions-template');
}
}
}
?>
<script type="text/javascript" >
//check after 10 seconds if ShortPixel initialized OK, if not, force the init (could happen if a JS error somewhere else stopped the JS execution).
function delayedInit() {
if(typeof ShortPixel !== "undefined") {
ShortPixel.init();
} else {
setTimeout(delayedInit, 10000);
}
}
setTimeout(delayedInit, 10000);
</script>
<?php
}
function toolbar_shortpixel_processing($wp_admin_bar)
{
if (!\wpSPIO()->env()->is_screen_to_use) {
return;
}
$extraClasses = " shortpixel-hide";
$id = 'short-pixel-notice-toolbar';
$tooltip = __('ShortPixel optimizing...', 'shortpixel-image-optimiser') . " " . __('Please do not close this admin page.', 'shortpixel-image-optimiser');
$icon = "shortpixel.png";
$successLink = $link = admin_url(current_user_can('edit_others_posts') ? 'upload.php?page=wp-short-pixel-bulk' : 'upload.php');
$blank = "";
if ($this->prioQ->processing()) {
$extraClasses = " shortpixel-processing";
}
if ($this->_settings->quotaExceeded && !isset($this->_settings->dismissedNotices['exceed'])) {
$extraClasses = " shortpixel-alert shortpixel-quota-exceeded";
$id = 'short-pixel-notice-exceed';
$tooltip = '';
$exceedTooltip = __('ShortPixel quota exceeded. Click for details.', 'shortpixel-image-optimiser');
$link = "options-general.php?page=wp-shortpixel-settings";
}
$lastStatus = $this->_settings->bulkLastStatus;
if ($lastStatus && $lastStatus['Status'] !== ShortPixelAPI::STATUS_SUCCESS) {
$extraClasses = " shortpixel-alert shortpixel-processing";
$tooltip = '';
$link = '';
if (admin_url(current_user_can('edit_others_posts'))) {
$link = 'post.php?post=' . $lastStatus['ImageID'] . '&action=edit';
} else {
$link = 'upload.php';
}
$successLink = $link;
$wp_admin_bar->add_node(array('id' => 'shortpixel_processing-title', 'parent' => 'shortpixel_processing', 'title' => $lastStatus['Message'], 'href' => $successLink));
$wp_admin_bar->add_node(array('id' => 'shortpixel_processing-dismiss', 'parent' => 'shortpixel_processing', 'title' => '<div style="text-align: right;">Dismiss</div>', 'href' => "#", 'meta' => array('onclick' => 'dismissFileError(event)')));
}
$args = array('id' => 'shortpixel_processing', 'title' => '<div id="' . $id . '" title="' . $tooltip . '" ><img alt="' . __('ShortPixel icon', 'shortpixel-image-optimiser') . '" src="' . plugins_url('res/img/' . $icon, SHORTPIXEL_PLUGIN_FILE) . '" success-url="' . $successLink . '"><span class="shp-alert">!</span>' . '<div class="cssload-container"><div class="cssload-speeding-wheel"></div></div></div>', 'href' => $link, 'meta' => array('target' => $blank, 'class' => 'shortpixel-toolbar-processing' . $extraClasses));
$wp_admin_bar->add_node($args);
if ($this->_settings->quotaExceeded && !isset($this->_settings->dismissedNotices['exceed'])) {
$wp_admin_bar->add_node(array('id' => 'shortpixel_processing-title', 'parent' => 'shortpixel_processing', 'title' => $exceedTooltip, 'href' => $link));
}
}
public function handleCustomBulk()
{
$wp_list_table = _get_list_table('WP_Media_List_Table');
$action = $wp_list_table->current_action();
if (strpos($action, 'short-pixel-bulk') === 0) {
check_admin_referer('bulk-media');
if (!is_array($_GET['media'])) {
return;
}
$mediaIds = array_reverse($_GET['media']);
}
switch ($action) {
case 'short-pixel-bulk':
foreach ($mediaIds as $ID) {
$meta = wp_get_attachment_metadata($ID);
if (!is_array($meta)) {
self::log('CUSTOM BULK META NOT AN ARRAY: ' . json_encode($meta));
$meta = ShortPixelMetaFacade::sanitizeMeta($meta, false);
if (isset($meta['previous_meta'])) {
self::log('COULDN\'T SANITIZE PROPERLY.');
continue;
} else {
self::log('SANITIZED.');
}
}
if (!is_array($meta)) {
continue;
}
if ((!isset($meta['ShortPixel']) || isset($meta['ShortPixel']['WaitingProcessing']) && $meta['ShortPixel']['WaitingProcessing'] == true) && (!isset($meta['ShortPixelImprovement']) || $meta['ShortPixelImprovement'] == __('Optimization N/A', 'shortpixel-image-optimiser'))) {
$this->prioQ->push($ID);
if (!isset($meta['ShortPixel'])) {
$meta['ShortPixel'] = array();
}
$meta['ShortPixel']['WaitingProcessing'] = true;
update_post_meta($ID, '_wp_attachment_metadata', $meta);
ShortPixelMetaFacade::optimizationStarted($ID);
}
}
break;
case 'short-pixel-bulk-lossy':
$this->restoreAndQueueList($mediaIds, 'lossy');
break;
case 'short-pixel-bulk-glossy':
$this->restoreAndQueueList($mediaIds, 'glossy');
break;
case 'short-pixel-bulk-lossless':
$this->restoreAndQueueList($mediaIds, 'lossless');
break;
case 'short-pixel-bulk-restore':
foreach ($mediaIds as $ID) {
$this->doRestore($ID);
}
break;
}
}
protected function restoreAndQueueList($mediaIds, $type)
{
foreach ($mediaIds as $ID) {
$meta = wp_get_attachment_metadata($ID);
if (isset($meta['ShortPixel']['type']) && $meta['ShortPixel']['type'] !== $type) {
$meta = $this->doRestore($ID);
if ($meta) {
$meta['ShortPixel'] = array("type" => $type, 'WaitingProcessing' => true);
update_post_meta($ID, '_wp_attachment_metadata', $meta);
$this->prioQ->push($ID);
}
}
}
}
public function handleMediaLibraryImageUpload($meta, $ID = null)
{
if (!$this->_settings->verifiedKey) {
return $meta;
}
$fs = \wpSPIO()->filesystem();
$dbMeta = wp_get_attachment_metadata($ID);
$currentFile = $fs->getAttachedFile($ID);
$refresh = false;
if (isset($dbMeta['ShortPixelImprovement'])) {
return $meta;
}
if (isset($this->thumbnailsRegenerating[$ID])) {
return $meta;
}
Log::addDebug("Handle Media Library Image Upload #{$ID}", $currentFile->exists());
if (!$this->_settings->optimizePdfs && 'pdf' === $currentFile->getExtension()) {
return $meta;
} elseif (!$currentFile->exists() && isset($meta['file']) && in_array(strtolower(pathinfo($meta['file'], PATHINFO_EXTENSION)), self::$PROCESSABLE_EXTENSIONS)) {
$this->prioQ->push($ID);
$meta['ShortPixel'] = array('WaitingProcessing' => true);
} elseif (self::_isProcessable($ID, array(), $this->_settings->excludePatterns, $meta) == false) {
$meta['ShortPixelImprovement'] = __('Optimization N/A', 'shortpixel-image-optimiser');
return $meta;
} else {
$this->prioQ->push($ID);
$itemHandler = new ShortPixelMetaFacade($ID);
$itemHandler->setRawMeta($meta);
include_once ABSPATH . 'wp-admin/includes/plugin.php';
if (!is_plugin_active('image-watermark/image-watermark.php') && !is_plugin_active('amazon-s3-and-cloudfront/wordpress-s3.php') && !is_plugin_active('amazon-s3-and-cloudfront-pro/amazon-s3-and-cloudfront-pro.php') && !is_plugin_active('easy-watermark/easy-watermark.php')) {
try {
$URLsAndPATHs = $this->getURLsAndPATHs($itemHandler);
$this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler, false, $refresh);
} catch (Exception $e) {
Log::addWarn('Handle Media Library Image Exceptions', $e);
$meta['ShortPixelImprovement'] = $e->getMessage();
return $meta;
}
}
$meta['ShortPixel']['WaitingProcessing'] = true;
if ($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
$imagePath = $itemHandler->getMeta()->getPath();
if (isset($this->_settings->convertedPng2Jpg[$imagePath])) {
$conv = $this->_settings->convertedPng2Jpg;
$params = $conv[$imagePath];
unset($conv[$imagePath]);
$this->_settings->convertedPng2Jpg == $conv;
$meta['ShortPixelPng2Jpg'] = array('originalFile' => $params['pngFile'], 'originalSizes' => array(), 'backup' => $params['backup'], 'optimizationPercent' => $params['optimizationPercent']);
}
}
return $meta;
}
}
public function maybeDumpFromProcessedOnServer($itemHandler, $urlsAndPaths)
{
$meta = $itemHandler->getMeta();
$doDump = false;
if ($meta->getStatus() <= 0) {
$doDump = true;
} else {
if (time() - strtotime($meta->getTsOptimized()) < 3600) {
$doDump = true;
}
}
if ($doDump) {
$this->_apiInterface->doDumpRequests($urlsAndPaths["URLs"]);
}
}
public function convertPng2Jpg($params)
{
$converter = new ShortPixelPng2Jpg($this->_settings);
return $converter->convertPng2Jpg($params);
}
public function checkConvertMediaPng2Jpg($itemHandler)
{
$converter = new ShortPixelPng2Jpg($this->_settings);
return $converter->checkConvertMediaPng2Jpg($itemHandler);
}
public function addPathToCustomFolder($imageFsPath, $folderId, $pid)
{
$existing = $this->spMetaDao->getMetaForPath($imageFsPath);
if ($existing) {
return $existing;
}
$pathParts = explode('/', trim($imageFsPath));
$meta = new ShortPixelMeta();
$meta->setPath($imageFsPath);
$meta->setName($pathParts[count($pathParts) - 1]);
$meta->setFolderId($folderId);
$meta->setExtMetaId($pid);
$meta->setCompressionType($this->_settings->compressionType);
$meta->setKeepExif($this->_settings->keepExif);
$meta->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
$meta->setResize($this->_settings->resizeImages);
$meta->setResizeWidth($this->_settings->resizeWidth);
$meta->setResizeHeight($this->_settings->resizeHeight);
$meta->setTsAdded(date("Y-m-d H:i:s"));
$ID = $this->spMetaDao->addImage($meta);
$meta->setId($ID);
if ($this->_settings->autoMediaLibrary) {
$this->prioQ->push('C-' . $ID);
}
$pathParts[] = "thumbs_" . $pathParts[count($pathParts) - 1];
$pathParts[count($pathParts) - 2] = "thumbs";
$thumbPath = implode('/', $pathParts);
if (file_exists($thumbPath)) {
$metaThumb = new ShortPixelMeta();
$metaThumb->setPath($thumbPath);
$metaThumb->setName($pathParts[count($pathParts) - 1]);
$metaThumb->setFolderId($folderId);
$metaThumb->setCompressionType($this->_settings->compressionType);
$metaThumb->setKeepExif($this->_settings->keepExif);
$metaThumb->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
$metaThumb->setResize($this->_settings->resizeImages);
$metaThumb->setResizeWidth($this->_settings->resizeWidth);
$metaThumb->setResizeHeight($this->_settings->resizeHeight);
$metaThumb->setTsAdded(date("Y-m-d H:i:s"));
$ID = $this->spMetaDao->addImage($metaThumb);
$metaThumb->setId($ID);
if ($this->_settings->autoMediaLibrary) {
$this->prioQ->push('C-' . $ID);
}
}
return $meta;
}
public function optimizeCustomImage($id)
{
$itemHandler = new ShortPixelMetaFacade('C-' . $id);
$meta = $itemHandler->getMeta();
if ($meta->getStatus() <= 0) {
$URLsAndPATHs = $itemHandler->getURLsAndPATHs(false);
$this->maybeDumpFromProcessedOnServer($itemHandler, $URLsAndPATHs);
}
if ($meta->getStatus() != ShortPixelMeta::FILE_STATUS_SUCCESS) {
$meta->setStatus(ShortPixelMeta::FILE_STATUS_PENDING);
$meta->setRetries(0);
$meta->setCompressionType($this->_settings->compressionType);
$meta->setKeepExif($this->_settings->keepExif);
$meta->setCmyk2rgb($this->_settings->CMYKtoRGBconversion);
$meta->setResize($this->_settings->resizeImages);
$meta->setResizeWidth($this->_settings->resizeWidth);
$meta->setResizeHeight($this->_settings->resizeHeight);
$this->spMetaDao->update($meta);
$this->prioQ->push('C-' . $id);
}
}
public function bulkRestore()
{
global $wpdb;
$startQueryID = $crtStartQueryID = $this->prioQ->getStartBulkId();
$endQueryID = $this->prioQ->getStopBulkId();
Log::addDebug('Bulk Restore' . $startQueryID . ' ' . $endQueryID);
if ($startQueryID <= $endQueryID) {
return false;
}
$this->prioQ->resetPrio();
$startTime = time();
$maxTime = min(30, is_numeric(SHORTPIXEL_MAX_EXECUTION_TIME) && SHORTPIXEL_MAX_EXECUTION_TIME > 10 ? SHORTPIXEL_MAX_EXECUTION_TIME - 5 : 25);
$maxResults = SHORTPIXEL_MAX_RESULTS_QUERY * 2;
if (in_array($this->prioQ->getBulkType(), array(ShortPixelQueue::BULK_TYPE_CLEANUP, ShortPixelQueue::BULK_TYPE_CLEANUP_PENDING))) {
$maxResults *= 20;
}
$restored = array();
while ($crtStartQueryID >= $endQueryID && time() - $startTime < $maxTime) {
$crtStartQueryID = $this->prioQ->getStartBulkId();
$resultsPostMeta = WpShortPixelMediaLbraryAdapter::getPostMetaSlice($crtStartQueryID, $endQueryID, $maxResults);
if (empty($resultsPostMeta)) {
$pendingCustomMeta = $this->spMetaDao->getPendingBulkRestore(SHORTPIXEL_MAX_RESULTS_QUERY * 2);
if (count($pendingCustomMeta) > 0) {
foreach ($pendingCustomMeta as $cObj) {
$this->doCustomRestore($cObj->id);
}
} else {
$crtStartQueryID -= $maxResults;
$startQueryID = $crtStartQueryID;
$this->prioQ->setStartBulkId($startQueryID);
continue;
}
}
foreach ($resultsPostMeta as $itemMetaData) {
$crtStartQueryID = $itemMetaData->post_id;
$item = new ShortPixelMetaFacade($crtStartQueryID);
$meta = $item->getMeta();
if ($meta->getStatus() == ShortPixelMeta::FILE_STATUS_SUCCESS || $meta->getStatus() == ShortPixelMeta::FILE_STATUS_PENDING) {
if ($meta->getStatus() == ShortPixelMeta::FILE_STATUS_SUCCESS && $this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_RESTORE) {
$res = $this->doRestore($crtStartQueryID);
$item->cleanupMeta($this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_CLEANUP_PENDING);
} else {
$item->cleanupMeta($this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_CLEANUP_PENDING);
$res = true;
}
$restored[] = array('id' => $crtStartQueryID, 'status' => $res ? 'success' : 'fail');
}
if ($meta->getStatus() < 0) {
$item->cleanupMeta();
}
}
$this->advanceBulk($crtStartQueryID);
}
return $restored;
}
public function getBulkItemsFromDb()
{
global $wpdb;
$startQueryID = $this->prioQ->getStartBulkId();
$endQueryID = $this->prioQ->getStopBulkId();
$skippedAlreadyProcessed = 0;
if ($startQueryID <= $endQueryID) {
return false;
}
$idList = array();
$itemList = array();
$timeoutMinThreshold = SHORTPIXEL_MAX_EXECUTION_TIME < 10 ? 2 : (SHORTPIXEL_MAX_EXECUTION_TIME < 30 ? 3 : 5);
$maxTime = min(SHORTPIXEL_MAX_EXECUTION_TIME, 90);
$timeoutThreshold = 5;
$passTime = time();
for ($sanityCheck = 0, $crtStartQueryID = $startQueryID; $crtStartQueryID >= $endQueryID && count($itemList) < SHORTPIXEL_PRESEND_ITEMS && $sanityCheck < 150 && time() - $this->timer < $maxTime - $timeoutThreshold; $sanityCheck++) {
$timeoutThreshold = max($timeoutThreshold, $timeoutMinThreshold + time() - $passTime);
$passTime = time();
$maxResults = $timeoutThreshold > 15 ? SHORTPIXEL_MAX_RESULTS_QUERY / 3 : ($timeoutThreshold > 10 ? SHORTPIXEL_MAX_RESULTS_QUERY / 2 : SHORTPIXEL_MAX_RESULTS_QUERY);
Log::addInfo("GETDB: pass {$sanityCheck} current StartID: {$crtStartQueryID} Threshold: {$timeoutThreshold}, MaxResults: {$maxResults}");
$resultsPosts = WpShortPixelMediaLbraryAdapter::getPostsJoinLessReverse($crtStartQueryID, $endQueryID, $maxResults);
if (time() - $this->timer >= 60) {
Log::addWarn("GETDB is SLOW. Got meta slice.");
}
if (empty($resultsPosts)) {
$crtStartQueryID -= SHORTPIXEL_MAX_RESULTS_QUERY;
$startQueryID = $crtStartQueryID;
if (!count($idList)) {
Log::addInfo("GETDB: empty slice. setStartBulkID to {$startQueryID}");
$this->prioQ->setStartBulkId($startQueryID);
}
continue;
}
if ($timeoutThreshold > 10) {
Log::addInfo("GETDB is SLOW. Meta slice has " . count($resultsPosts) . ' items.');
}
$counter = 0;
foreach ($resultsPosts as $index => $post_id) {
$crtStartQueryID = $post_id;
if (time() - $this->timer >= 60) {
Log::addInfo("GETDB is SO SLOW. Check processable for {$crtStartQueryID}.");
}
if (time() - $this->timer >= $maxTime - $timeoutThreshold) {
if ($counter == 0 && \wpSPIO()->env()->is_function_usable('set_time_limit') && set_time_limit(30)) {
self::log("GETDB is SO SLOW. Increasing time limit by 30 sec succeeded.");
$maxTime += 30 - $timeoutThreshold;
} else {
self::log("GETDB is SO SLOW. Breaking after processing {$counter} items. Time limit is over: " . ($maxTime - $timeoutThreshold));
break;
}
}
$counter++;
if (!in_array($crtStartQueryID, $idList) && $this->isProcessable($crtStartQueryID, $this->_settings->optimizePdfs ? array() : array('pdf'))) {
$item = new ShortPixelMetaFacade($crtStartQueryID);
if ($timeoutThreshold > 15) {
Log::addInfo("GETDB is SO SLOW. Get meta for {$crtStartQueryID}.");
}
$meta = $item->getMeta();
if ($timeoutThreshold > 15) {
Log::addInfo("GETDB is SO SLOW. Got meta.");
}
if ($meta->getStatus() != ShortPixelMeta::FILE_STATUS_SUCCESS) {
$addIt = strpos($meta->getMessage(), __('Image files are missing.', 'shortpixel-image-optimiser')) === false;
if (!$addIt) {
if (!$this->doRestore($crtStartQueryID)) {
delete_transient("shortpixel_thrown_notice");
}
$addIt = true;
$item = new ShortPixelMetaFacade($crtStartQueryID);
}
if ($addIt) {
$itemList[] = $item;
$idList[] = $crtStartQueryID;
if (count($itemList) > SHORTPIXEL_PRESEND_ITEMS) {
break;
}
}
} elseif ($meta->getCompressionType() !== null && $meta->getCompressionType() != $this->_settings->compressionType) {
if ($this->doRestore($crtStartQueryID)) {
$itemList[] = $item = new ShortPixelMetaFacade($crtStartQueryID);
$idList[] = $crtStartQueryID;
if (count($itemList) > SHORTPIXEL_PRESEND_ITEMS) {
break;
}
} else {
$skippedAlreadyProcessed++;
}
} elseif ($this->_settings->processThumbnails && $meta->getThumbsOpt() !== null && ($meta->getThumbsOpt() == 0 && count($meta->getThumbs()) > 0 || is_array($meta->getThumbsOptList()) && count(array_diff(array_keys(WpShortPixelMediaLbraryAdapter::getSizesNotExcluded($meta->getThumbs(), $this->_settings->excludeSizes)), $meta->getThumbsOptList())) || $this->_settings->optimizeUnlisted && count(array_diff(WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath()), $meta->getThumbsOptList())))) {
$item->searchUnlistedFiles();
$URLsAndPATHs = $item->getURLsAndPATHs(true, true, $this->_settings->optimizeRetina, $this->_settings->excludeSizes);
Log::addDebug('Gathering URLS AND PATHS', array($URLsAndPATHs));
if (count($URLsAndPATHs["URLs"])) {
$meta->setThumbsTodo(true);
$item->updateMeta($meta);
$itemList[] = $item;
$idList[] = $crtStartQueryID;
if (count($itemList) > SHORTPIXEL_PRESEND_ITEMS) {
break;
}
}
}
}
}
if (!count($idList) && $crtStartQueryID <= $startQueryID) {
$leapStart = $this->prioQ->getStartBulkId();
$crtStartQueryID = $startQueryID = $post_id - 1;
$res = WpShortPixelMediaLbraryAdapter::countAllProcessableFiles($this->_settings, $leapStart, $crtStartQueryID);
$skippedAlreadyProcessed += $res["mainProcessedFiles"] - $res["mainProc" . ($this->getCompressionType() == 1 ? "Lossy" : "Lossless") . "Files"];
Log::addInfo("GETDB: empty list. setStartBulkID to {$startQueryID}");
$this->prioQ->setStartBulkId($startQueryID);
} else {
$crtStartQueryID--;
Log::addInfo("GETDB just decrementing. Crt: {$crtStartQueryID} Start: {$startQueryID}, list: " . json_encode($idList));
}
}
$ret = array("items" => $itemList, "skipped" => $skippedAlreadyProcessed, "searching" => $sanityCheck >= 150 || time() - $this->timer >= $maxTime - $timeoutThreshold);
self::log('GETDB returns ' . json_encode($ret));
return $ret;
}
public function getFromPrioAndCheck($limit = PHP_INT_MAX)
{
$items = array();
$i = 1;
foreach ($this->prioQ->getFromPrioAndCheck() as $id) {
$items[] = new ShortPixelMetaFacade($id);
if ($i++ > $limit) {
break;
}
}
return $items;
}
private function checkKey($ID)
{
if ($this->_settings->verifiedKey == false) {
if ($ID == null) {
$ids = $this->getFromPrioAndCheck(1);
$itemHandler = count($ids) > 0 ? $ids[0] : null;
}
$response = array("Status" => ShortPixelAPI::STATUS_NO_KEY, "ImageID" => $itemHandler ? $itemHandler->getId() : "-1", "Message" => __('Missing API Key', 'shortpixel-image-optimiser'));
$this->_settings->bulkLastStatus = $response;
die(json_encode($response));
}
}
private function sendEmptyQueue()
{
$avg = $this->getAverageCompression();
$fileCount = $this->_settings->fileCount;
if ($this->prioQ->bulkRunning()) {
$bulkstatus = '1';
} elseif ($this->prioQ->bulkPaused()) {
$bulkstatus = '2';
} else {
$bulkstatus = '0';
}
$response = array("Status" => self::BULK_EMPTY_QUEUE, "Message" => __('Empty queue ', 'shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(), "BulkStatus" => $bulkstatus, "AverageCompression" => $avg, "FileCount" => $fileCount, "BulkPercent" => $this->prioQ->getBulkPercent());
die(json_encode($response));
}
public function handleImageProcessing($ID = null)
{
$this->checkKey($ID);
if ($this->_settings->frontBootstrap && is_admin() && !ShortPixelTools::requestIsFrontendAjax()) {
$this->_settings->lastBackAction = time();
}
if (isset($_POST['bulk-secret'])) {
$secret = sanitize_text_field($_POST['bulk-secret']);
$cacheControl = new \ShortPixel\Controller\CacheController();
$cachedObj = $cacheControl->getItem('bulk-secret');
if (!$cachedObj->exists()) {
$cachedObj->setValue($secret);
$cachedObj->setExpires(3 * MINUTE_IN_SECONDS);
$cacheControl->storeItemObject($cachedObj);
}
}
$rawPrioQ = $this->prioQ->get();
if (count($rawPrioQ)) {
Log::addInfo("HIP: 0 Priority Queue: " . json_encode($rawPrioQ));
}
Log::addInfo("HIP: 0 Bulk running? " . $this->prioQ->bulkRunning() . " START " . $this->_settings->startBulkId . " STOP " . $this->_settings->stopBulkId . " MaxTime: " . SHORTPIXEL_MAX_EXECUTION_TIME);
Log::addDebug('Bulk Running', array($this->prioQ->bulkRunning()));
if ($this->prioQ->bulkRunning() && ($this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_RESTORE || $this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_CLEANUP || $this->prioQ->getBulkType() == ShortPixelQueue::BULK_TYPE_CLEANUP_PENDING)) {
$res = $this->bulkRestore();
if ($res === false) {
$this->sendEmptyQueue();
} else {
die(json_encode(array("Status" => ShortPixelAPI::STATUS_RETRY, "Message" => __('Restoring images... ', 'shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId(), "BulkPercent" => $this->prioQ->getBulkPercent(), "Restored" => $res)));
}
}
$ids = $this->getFromPrioAndCheck(SHORTPIXEL_PRESEND_ITEMS);
if (count($ids) < SHORTPIXEL_PRESEND_ITEMS) {
if ($this->prioQ->bulkRunning()) {
$res = $this->getBulkItemsFromDb();
$bulkItems = $res['items'];
if ($bulkItems) {
foreach ($bulkItems as $bi) {
$add = true;
foreach ($ids as $pi) {
if ($pi->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE && $bi->getId() == $pi->getId()) {
$add = false;
}
}
$ids[] = $bi;
}
}
}
}
$customIds = false;
if (count($ids) < SHORTPIXEL_PRESEND_ITEMS && $this->prioQ->bulkRan() && $this->_settings->hasCustomFolders && (!$this->_settings->cancelPointer || $this->_settings->skipToCustom) && !$this->_settings->customBulkPaused) {
$otherMedia = new \ShortPixel\Controller\OtherMediaController();
$otherMedia->refreshFolders();
$customIds = $this->spMetaDao->getPendingMetas(SHORTPIXEL_PRESEND_ITEMS - count($ids));
if (is_array($customIds)) {
$ids = array_merge($ids, array_map(array('ShortPixelMetaFacade', 'getNewFromRow'), $customIds));
}
}
if (count($ids)) {
$idl = '';
foreach ($ids as $i) {
$idl .= $i->getId() . ' ';
}
Log::addInfo("HIP: 1 Selected IDs: {$idl}");
}
for ($i = 0, $itemHandler = false; $ids !== false && $i < min(SHORTPIXEL_PRESEND_ITEMS, count($ids)); $i++) {
$crtItemHandler = $ids[$i];
$tmpMeta = $crtItemHandler->getMeta();
$compType = $tmpMeta->getCompressionType() !== null ? $tmpMeta->getCompressionType() : $this->_settings->compressionType;
try {
self::log("HIP: 1 sendToProcessing: " . $crtItemHandler->getId());
$URLsAndPATHs = $this->sendToProcessing($crtItemHandler, $compType, $tmpMeta->getThumbsTodo());
if (!$itemHandler) {
$itemHandler = $ids[$i];
$firstUrlAndPaths = $URLsAndPATHs;
}
} catch (Exception $e) {
if ($tmpMeta->getStatus() != 2) {
$crtItemHandler->incrementRetries(1, $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::ERR_FILE_NOT_FOUND, $e->getMessage());
}
if (!$this->prioQ->remove($crtItemHandler->getQueuedId())) {
$this->advanceBulk($crtItemHandler->getId());
$res['searching'] = true;
}
}
}
if (!$itemHandler) {
if (isset($res['searching']) && $res['searching']) {
die(json_encode(array("Status" => ShortPixelAPI::STATUS_SEARCHING, "Message" => __('Searching images to optimize... ', 'shortpixel-image-optimiser') . $this->prioQ->getStartBulkId() . '->' . $this->prioQ->getStopBulkId())));
}
Log::addDebug("HIP: 1 STOP BULK");
$bulkEverRan = $this->prioQ->stopBulk();
$this->sendEmptyQueue();
}
self::log("HIP: 2 Prio Queue: " . json_encode($this->prioQ->get()));
$itemId = $itemHandler->getQueuedId();
self::log("HIP: 2 Process Image: " . json_encode($itemHandler->getId()));
$result = $this->_apiInterface->processImage($firstUrlAndPaths['URLs'], $firstUrlAndPaths['PATHs'], $itemHandler);
$result["ImageID"] = $itemId;
$meta = $itemHandler->getMeta();
$result["Filename"] = ShortPixelAPI::MB_basename($meta->getPath());
self::log("HIP: 3 Prio Queue: " . json_encode($this->prioQ->get()));
if ($result["Status"] == ShortPixelAPI::STATUS_SUCCESS) {
self::log("HIP: Image ID " . $itemId . " optimized successfully: " . json_encode($result));
$prio = $this->prioQ->remove($itemId);
$prio = $this->prioQ->removeFromFailed($itemId);
$result["Type"] = $meta->getCompressionType() !== null ? ShortPixelAPI::getCompressionTypeName($meta->getCompressionType()) : '';
$result["ThumbsTotal"] = $meta->getThumbs() && is_array($meta->getThumbs()) ? WpShortPixelMediaLbraryAdapter::countSizesNotExcluded($meta->getThumbs()) : 0;
$miss = $meta->getThumbsMissing();
$result["ThumbsTotal"] -= is_array($miss) ? count($miss) : 0;
$result["ThumbsCount"] = $meta->getThumbsOpt() ? $meta->getThumbsOpt() : ($this->_settings->processThumbnails ? $result["ThumbsTotal"] : 0);
$result["RetinasCount"] = $meta->getRetinasOpt();
$result["BackupEnabled"] = $this->getBackupFolderAny($meta->getPath(), $meta->getThumbs()) ? true : false;
$tsOptimized = $meta->getTsOptimized();
if (!is_null($tsOptimized)) {
$tsOptObj = new DateTime($tsOptimized);
if ($tsOptObj) {
$result['TsOptimized'] = ShortPixelTools::format_nice_date($tsOptObj);
}
}
if (!$prio && $itemId <= $this->prioQ->getStartBulkId()) {
$this->advanceBulk($itemId);
$this->setBulkInfo($itemId, $result);
}
$result["AverageCompression"] = $this->getAverageCompression();
if ($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
$thumb = $bkThumb = "";
$percent = $meta->getImprovementPercent();
if ($percent) {
$filePath = explode("/", $meta->getPath());
$sizes = $meta->getThumbs();
if ('pdf' == strtolower(pathinfo($result["Filename"], PATHINFO_EXTENSION))) {
$thumb = wpSPIO()->plugin_url('res/img/logo-pdf.png');
$bkThumb = '';
} else {
if (count($sizes)) {
$exclude = $this->_settings->excludeSizes;
$exclude = is_array($exclude) ? $exclude : array();
$thumb = isset($sizes["medium"]) && !in_array("medium", $exclude) ? $sizes["medium"]["file"] : (isset($sizes["thumbnail"]) && !in_array("thumbnail", $exclude) ? $sizes["thumbnail"]["file"] : "");
if (!strlen($thumb)) {
foreach ($sizes as $sizeName => $sizeVal) {
$exclude = $this->_settings->excludeSizes;
if (!in_array($sizeName, $exclude)) {
$thumb = isset($sizeVal['file']) ? $sizeVal['file'] : '';
break;
}
}
}
}
if (!strlen($thumb)) {
$thumb = is_array($filePath) ? $filePath[count($filePath) - 1] : $filePath;
}
if (strlen($thumb) && $this->_settings->backupImages && $this->_settings->processThumbnails) {
$backupUrl = SHORTPIXEL_BACKUP_URL . "/";
$urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
$bkThumb = $backupUrl . $urlBkPath . $thumb;
}
if (strlen($thumb)) {
if ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE) {
$uploadsUrl = ShortPixelMetaFacade::getHomeUrl();
$urlPath = ShortPixelMetaFacade::returnSubDir($meta->getPath());
$thumb = $uploadsUrl . $urlPath . $thumb;
} else {
try {
$mainUrl = ShortPixelMetaFacade::safeGetAttachmentUrl($itemHandler->getId());
} catch (Exception $e) {
Log::addError('Attachment seems corrupted!', array($e->getMessage()));
$mainUrl = null;
}
$thumb = dirname($mainUrl) . '/' . $thumb;
}
}
}
$result["Thumb"] = $thumb;
$result["BkThumb"] = $bkThumb;
}
} elseif (is_array($customIds)) {
foreach ($customIds as $customId) {
$rootUrl = ShortPixelMetaFacade::getHomeUrl();
if ($customId->id == $itemHandler->getId()) {
if ('pdf' == strtolower(pathinfo($meta->getName(), PATHINFO_EXTENSION))) {
$result["Thumb"] = plugins_url('shortpixel-image-optimiser/res/img/logo-pdf.png');
$result["BkThumb"] = "";
} else {
$result["Thumb"] = $thumb = $rootUrl . $meta->getWebPath();
if ($this->_settings->backupImages) {
$result["BkThumb"] = str_replace($rootUrl, $rootUrl . "/" . basename(dirname(dirname(SHORTPIXEL_BACKUP_FOLDER))) . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/", $thumb);
}
}
$this->setBulkInfo($itemId, $result);
break;
}
}
}
} elseif ($result["Status"] == ShortPixelAPI::STATUS_ERROR) {
if ($meta->getRetries() > SHORTPIXEL_MAX_ERR_RETRIES) {
if (!$this->prioQ->remove($itemId)) {
self::log("HIP RES: advanceBulk - too many retries for {$itemId} - skipping.");
$this->advanceBulk($meta->getId());
}
if ($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
$itemHandler->deleteMeta();
}
$result["Status"] = ShortPixelAPI::STATUS_SKIP;
$result["Message"] .= __(' Retry limit reached. Skipping file ID ', 'shortpixel-image-optimiser') . $itemId . ".";
$itemHandler->setError(isset($result['Code']) ? $result['Code'] : ShortPixelAPI::ERR_INCORRECT_FILE_SIZE, $result["Message"]);
} else {
if (isset($result['Code'])) {
$itemHandler->incrementRetries(1, $result['Code'], $result["Message"]);
} else {
$itemHandler->incrementRetries(1, ShortPixelAPI::ERR_UNKNOWN, "Connection error (" . $result["Message"] . ")");
}
}
} elseif ($result["Status"] == ShortPixelAPI::STATUS_SKIP || $result["Status"] == ShortPixelAPI::STATUS_FAIL) {
$meta = $itemHandler->getMeta();
$prio = $this->prioQ->remove($itemId);
if (isset($result["Code"]) && (in_array($result["Code"], array("write-fail", "backup-fail")) || in_array(0 + $result["Code"], array(-201)) && $meta->getRetries() >= 3)) {
$prio = $this->prioQ->addToFailed($itemHandler->getQueuedId());
}
if (isset($result['Code'])) {
$itemHandler->incrementRetries(1, $result['Code'], $result["Message"]);
} else {
$itemHandler->incrementRetries(1, ShortPixelAPI::ERR_UNKNOWN, "Connection error (" . $result["Message"] . ")");
}
self::log("HIP RES: skipping {$itemId}");
$this->advanceBulk($meta->getId());
if ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE) {
$result["CustomImageLink"] = ShortPixelMetaFacade::getHomeUrl() . $meta->getWebPath();
}
} elseif ($result["Status"] == ShortPixelAPI::STATUS_QUEUE_FULL) {
} elseif ($result["Status"] == ShortPixelAPI::STATUS_MAINTENANCE) {
} elseif ($this->prioQ->isPrio($itemId) && $result["Status"] == ShortPixelAPI::STATUS_QUOTA_EXCEEDED) {
if (!$this->prioQ->skippedCount()) {
$this->prioQ->reverse();
}
if ($this->prioQ->allSkipped()) {
$result["Stop"] = true;
} else {
$result["Stop"] = false;
$this->prioQ->skip($itemId);
}
self::log("HIP: 5 Prio Skipped: " . json_encode($this->prioQ->getSkipped()));
} elseif ($result["Status"] == ShortPixelAPI::STATUS_RETRY && is_array($customIds)) {
$result["CustomImageLink"] = $thumb = ShortPixelMetaFacade::getHomeUrl() . $meta->getWebPath();
}
if ($result["Status"] !== ShortPixelAPI::STATUS_RETRY) {
$this->_settings->bulkLastStatus = null;
$this->_settings->bulkLastStatus = $result;
}
if ($itemHandler->getType() == ShortPixelMetaFacade::CUSTOM_TYPE) {
$othermediaView = new \ShortPixel\Controller\View\OtherMediaViewController();
$othermediaView->setShortPixel($this);
$result['actions'] = $othermediaView->renderNewActions(substr($itemId, 2));
}
$ret = json_encode($result);
self::log("HIP RET " . $ret);
die($ret);
}
private function advanceBulk($processedID)
{
if ($processedID <= $this->prioQ->getStartBulkId()) {
$this->prioQ->setStartBulkId($processedID - 1);
$this->prioQ->logBulkProgress();
}
}
private function setBulkInfo($processedID, &$result)
{
$deltaBulkPercent = $this->prioQ->getDeltaBulkPercent();
$minutesRemaining = $this->prioQ->getTimeRemaining();
$pendingMeta = $this->_settings->hasCustomFolders ? $this->spMetaDao->getPendingMetaCount() : 0;
$percent = $this->prioQ->getBulkPercent();
if (0 + $pendingMeta > 0) {
$customMeta = $this->spMetaDao->getCustomMetaCount();
$crtTotalFiles = is_array($this->_settings->currentStats) ? $this->_settings->currentStats['totalFiles'] : $this->_settings->currentStats;
$totalPercent = round(($percent * $crtTotalFiles + ($customMeta - $pendingMeta) * 100) / ($crtTotalFiles + $customMeta));
$minutesRemaining = round($minutesRemaining * (100 - $totalPercent) / max(1, 100 - $percent));
$percent = $totalPercent;
}
$result["BulkPercent"] = $percent;
$result["BulkMsg"] = $this->bulkProgressMessage($deltaBulkPercent, $minutesRemaining);
}
private function sendToProcessing($itemHandler, $compressionType = false, $onlyThumbs = false)
{
if ($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
$rawMeta = $this->checkConvertMediaPng2Jpg($itemHandler);
if (isset($rawMeta['type']) && $rawMeta['type'] == 'image/jpeg') {
$itemHandler->getMeta(true);
}
}
$URLsAndPATHs = $this->getURLsAndPATHs($itemHandler, NULL, $onlyThumbs);
Log::addDebug('Send to PRocessing - URLS -', array($URLsAndPATHs));
$result = WpShortPixelMediaLbraryAdapter::checkRequestLimiter($URLsAndPATHs['URLs']);
if (!$result) {
Log::addDebug('Preventing sentToProcessing. Reported as already sent');
return $URLsAndPATHs;
}
$meta = $itemHandler->getMeta();
$itemHandler->searchUnlistedFiles();
$miss = $meta->getThumbsMissing();
if (is_numeric($miss)) {
$miss = array();
}
if (isset($URLsAndPATHs['sizesMissing']) && count($URLsAndPATHs['sizesMissing']) && (null === $miss || count(array_diff_key($miss, array_merge($URLsAndPATHs['sizesMissing'], $miss))))) {
$meta->setThumbsMissing($URLsAndPATHs['sizesMissing']);
$itemHandler->updateMeta();
}
$original_status = $meta->getStatus();
$refresh = $meta->getStatus() === ShortPixelAPI::ERR_INCORRECT_FILE_SIZE;
$itemHandler->setWaitingProcessing();
if ($original_status < 0 && count($URLsAndPATHs['URLs']) == 0) {
if (!is_array($meta->getThumbsMissing()) || count($meta->getThumbsMissing()) == 0) {
$meta->setStatus(ShortPixelAPI::STATUS_SUCCESS);
$meta->setMessage(0);
$meta->setThumbsTodo(0);
$itemHandler->updateMeta($meta);
Log::addWarn('Processing override, no URLS, no jobs, something was incorrect - ');
return $URLsAndPATHs;
}
}
$thumbObtList = $meta->getThumbsOptList();
$missing = $meta->getThumbsMissing();
try {
$this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler, $compressionType === false ? $this->_settings->compressionType : $compressionType, $refresh);
} catch (Exception $e) {
Log::addError('Api DoRequest Thrown ' . $e->getMessage());
}
return $URLsAndPATHs;
}
public function handleManualOptimization()
{
$imageId = intval($_GET['image_id']);
Log::addInfo("Handle Manual Optimization #{$imageId}");
switch (substr($imageId, 0, 2)) {
case "N-":
return "Add the gallery to the custom folders list in ShortPixel settings.";
if (class_exists("C_Image_Mapper")) {
$image_mapper = C_Image_Mapper::get_instance();
$image = $image_mapper->find(intval(substr($imageId, 2)));
if ($image) {
$this->handleNextGenImageUpload($image, true);
return array("Status" => ShortPixelAPI::STATUS_SUCCESS, "message" => "");
}
}
return array("Status" => ShortPixelAPI::STATUS_FAIL, "message" => __('NextGen image not found', 'shortpixel-image-optimiser'));
break;
case "C-":
Log::addError("Throw: HandleManualOptimization for custom images not implemented");
throw new Exception("HandleManualOptimization for custom images not implemented");
default:
$this->optimizeNowHook(intval($imageId), true);
break;
}
}
public function checkStatus()
{
$itemHandler = new ShortPixelMetaFacade(intval($_GET['image_id']));
$meta = $itemHandler->getMeta();
die(json_encode(array("Status" => $meta->getStatus(), "Message" => $meta->getMessage())));
}
public function optimizeNowHook($imageId, $manual = false)
{
if ($this->isProcessable($imageId)) {
$this->prioQ->push($imageId);
$itemHandler = new ShortPixelMetaFacade($imageId);
$itemFile = \wpSPIO()->filesystem()->getAttachedFile($imageId);
if ($manual) {
$meta = $itemHandler->getMeta();
$meta->setRetries(0);
$meta->setStatus(\ShortPixelMeta::FILE_STATUS_PENDING);
$itemHandler->updateMeta($meta);
}
if (!$manual && 'pdf' === $itemFile->getExtension() && !$this->_settings->optimizePdfs) {
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
} else {
try {
$this->sendToProcessing($itemHandler, false, $itemHandler->getMeta()->getThumbsTodo());
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
} catch (Exception $e) {
$itemHandler->getMeta();
$errCode = $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::ERR_FILE_NOT_FOUND;
$itemHandler->setError($errCode, $e->getMessage());
$ret = array("Status" => ShortPixelAPI::STATUS_FAIL, "Message" => $e->getMessage());
}
}
} else {
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
}
die(json_encode($ret));
}
public function thumbnailsBeforeRegenerateHook($postId)
{
$this->thumbnailsRegenerating[$postId] = true;
}
public function thumbnailsRegeneratedHook($postId, $originalMeta, $regeneratedSizes = array(), $bulk = false)
{
$fs = \wpSPIO()->filesystem();
$settings = \wpSPIO()->settings();
if (isset($originalMeta["ShortPixelImprovement"]) && is_numeric($originalMeta["ShortPixelImprovement"])) {
$shortPixelMeta = $originalMeta["ShortPixel"];
unset($shortPixelMeta['thumbsMissing']);
if (count($regeneratedSizes) == 0 || !isset($shortPixelMeta["thumbsOptList"])) {
$shortPixelMeta["thumbsOpt"] = 0;
$shortPixelMeta["thumbsOptList"] = array();
$shortPixelMeta["retinasOpt"] = 0;
} else {
$regeneratedThumbs = array();
$mainFile = $fs->getAttachedFile($postId);
foreach ($regeneratedSizes as $size) {
if (isset($size['file']) && in_array($size['file'], $shortPixelMeta["thumbsOptList"])) {
$regeneratedThumbs[] = $size['file'];
$fileObj = $fs->getFile((string) $mainFile->getFileDir() . $size['file']);
if ($settings->createWebp) {
if (SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION) {
$webpObj = $fs->getFile((string) $fileObj->getFileDir() . $fileObj->getFileName() . '.webp');
} else {
$webpObj = $fs->getFile((string) $fileObj->getFileDir() . $fileObj->getFileBase() . '.webp');
}
if ($webpObj->exists()) {
$webpObj->delete();
}
}
if ($settings->createAvif) {
$avifObj = $fs->getFile((string) $fileObj->getFileDir() . $fileObj->getFileBase() . '.avif');
if ($avifObj->exists()) {
$avifObj->delete();
}
}
$shortPixelMeta["thumbsOpt"] = max(0, $shortPixelMeta["thumbsOpt"] - 1);
$shortPixelMeta["retinasOpt"] = max(0, $shortPixelMeta["retinasOpt"] - 1);
}
}
$shortPixelMeta["thumbsOptList"] = array_diff($shortPixelMeta["thumbsOptList"], $regeneratedThumbs);
}
$meta = wp_get_attachment_metadata($postId);
$meta["ShortPixel"] = $shortPixelMeta;
$meta["ShortPixelImprovement"] = $originalMeta["ShortPixelImprovement"];
if (isset($originalMeta["ShortPixelPng2Jpg"])) {
$meta["ShortPixelPng2Jpg"] = $originalMeta["ShortPixelPng2Jpg"];
}
update_post_meta($postId, '_wp_attachment_metadata', $meta);
if (!$bulk) {
$this->prioQ->push($postId);
}
}
unset($this->thumbnailsRegenerating[$postId]);
}
public function shortpixelGetBackupFilter($imagePath)
{
$backup = str_replace(dirname(dirname(dirname(SHORTPIXEL_BACKUP_FOLDER))), SHORTPIXEL_BACKUP_FOLDER, $imagePath);
return file_exists($backup) ? $backup : false;
}
public function onWpLrUpdateMedia($imageId, $galleryIdsUnused)
{
$meta = wp_get_attachment_metadata($imageId);
if (is_array($meta)) {
unset($meta['ShortPixel']);
$meta['ShortPixel'] = array();
$meta['ShortPixel']['WaitingProcessing'] = true;
$this->prioQ->push($imageId);
update_post_meta($imageId, '_wp_attachment_metadata', $meta);
ShortPixelMetaFacade::optimizationStarted($imageId);
}
}
public function getBackupFolder($file)
{
$fs = \wpSPIO()->filesystem();
$fsFile = $fs->getFile($file);
$directory = $this->getBackupFolderInternal($fsFile);
if ($directory !== false) {
return $directory->getPath();
} else {
return false;
}
}
private function getBackupFolderInternal(FileModel $file)
{
$fs = \wpSPIO()->filesystem();
$settings = \wpSPIO()->settings();
$SubDir = ShortPixelMetaFacade::returnSubDir($file);
$SubDirOld = ShortPixelMetaFacade::returnSubDirOld($file);
$basename = $file->getFileName();
$backupFile = $file->getBackupFile();
if ($backupFile) {
$backupFolder = $backupFile->getFileDir();
return $backupFolder;
}
$backupFile = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . '/' . $basename);
if ($backupFile->exists()) {
return $backupFile->getFileDir();
}
$backupFile = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDirOld . '/' . $basename);
if ($backupFile->exists()) {
return $backupFile->getFileDir();
}
$backupFile = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . '/' . date("Y") . "/" . date("m") . '/' . $basename);
if ($backupFile->exists()) {
return $backupFile->getFileDir();
}
Log::addError('Backup Directory could not be established! ', array($file->getFullPath(), $SubDir, $SubDirOld, $basename));
return false;
}
public function getBackupFolderAny($file, $thumbs)
{
$ret = $this->getBackupFolder($file);
if (!$ret && isset($thumbs)) {
foreach ($thumbs as $size) {
$backup = $this->getBackupFolder(trailingslashit(dirname($file)) . $size['file']);
if ($backup) {
$ret = $backup;
break;
}
}
}
return apply_filters("shortpixel_backup_folder", $ret, $file, $thumbs);
}
protected function setFilePerms($file)
{
$perms = @fileperms($file);
if ($perms & 0x100 && $perms & 0x80) {
return true;
}
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
$owner = fileowner($file);
if ($owner !== false && function_exists('posix_getuid') && $owner != posix_getuid()) {
return false;
}
}
if (!@chmod($file, $perms | 0x100 | 0x80)) {
return false;
}
return true;
}
protected function doRestore($attachmentID, $rawMeta = null)
{
do_action("shortpixel_before_restore_image", $attachmentID);
$fs = \wpSPIO()->filesystem();
$imageObj = new ImageModel();
$imageObj->setbyPostID($attachmentID);
$fsFile = $imageObj->getFile();
$filePath = (string) $fsFile->getFileDir();
$itemHandler = $imageObj->getFacade();
if ($rawMeta) {
$itemHandler->setRawMeta($rawMeta);
} else {
$itemHandler->getMeta();
$rawMeta = $itemHandler->getRawMeta();
}
try {
$toUnlink = $itemHandler->getURLsAndPATHs(true, false, true, array(), true);
} catch (Exception $e) {
return false;
}
do_action('shortpixel_restore_after_pathget', $attachmentID);
$sizes = isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array();
$oldBackupFolder = $this->getBackupFolderAny($fsFile->getFullPath(), $sizes);
if (!$oldBackupFolder) {
$notice = Notices::addWarning(__("Not all backup files found. Restore not performed on these files ", 'shortpixel-image-optimiser'), true);
Notices::addDetail($notice, (string) $bkFile);
Log::addError('No Backup Files Found: ' . $bkFile);
return false;
} else {
$bkFolder = $fs->getDirectory($oldBackupFolder);
$bkFile = $fs->getFile($bkFolder->getPath() . $fsFile->getFileName());
}
Log::addDebug('Restore, Backup File -- ', array($bkFile->getFullPath(), $fsFile->getFullPath()));
$png2jpgMain = isset($rawMeta['ShortPixelPng2Jpg']['originalFile']) ? $rawMeta['ShortPixelPng2Jpg']['originalFile'] : false;
$toReplace = array();
if ($png2jpgMain) {
$png2jpgSizes = $png2jpgMain ? $rawMeta['ShortPixelPng2Jpg']['originalSizes'] : array();
$image = $rawMeta['file'];
$imageUrl = wp_get_attachment_url($attachmentID);
Log::addDebug('PHP2JPG - OriginFile -- ' . $fsFile->getFullPath());
$imageName = $fsFile->getFileName();
$baseUrl = str_replace($fsFile->getFileName(), '', $imageUrl);
$baseUrl = ShortPixelPng2Jpg::removeUrlProtocol($baseUrl);
$backupFileDir = $bkFile->getFileDir();
if ($bkFile->exists()) {
$toUnlink['PATHs'][] = $bkFile->getFullPath();
}
$baseRelPath = '';
$toReplace[ShortPixelPng2Jpg::removeUrlProtocol($imageUrl)] = $baseUrl . $baseRelPath . wp_basename($png2jpgMain);
foreach ($sizes as $key => $size) {
if (isset($png2jpgSizes[$key])) {
$toReplace[$baseUrl . $baseRelPath . $size['file']] = $baseUrl . $baseRelPath . wp_basename($png2jpgSizes[$key]['file']);
}
$backuppedSize = $fs->getFile($backupFileDir . $size['file']);
Log::addDebug('Checking for PNG Backup at - ', $backuppedSize->getFullPath());
if ($backuppedSize->exists()) {
$toUnlink['PATHs'][] = $backuppedSize->getFullPath();
}
}
$sizes = $png2jpgSizes;
$fsFile = $fs->getFile($png2jpgMain);
$bkFile = $fs->getFile($bkFolder->getPath() . $fsFile->getFileName());
wp_update_post(array('ID' => $attachmentID, 'post_mime_type' => 'image/png'));
}
$bkCount = 0;
if (isset($rawMeta["ShortPixel"]['ErrCode'])) {
$lastStatus = $this->_settings->bulkLastStatus;
if (isset($lastStatus['ImageID']) && $lastStatus['ImageID'] == $attachmentID) {
$this->_settings->bulkLastStatus = null;
}
}
if ($bkFile->exists()) {
if (!$bkFile->is_readable() || $fsFile->exists() && !$fsFile->is_writable()) {
$this->throwNotice('generic-err', sprintf(__("File %s cannot be restored due to lack of permissions, please contact your hosting provider to assist you in fixing this.", 'shortpixel-image-optimiser'), $fsFile->getFullPath()));
Log::addError('DoRestore could not restore file', array($bkFile->getFullPath(), $fsFile->getFullPath(), $fsFile->exists(), $bkFile->is_readable(), $fsFile->is_writable()));
return false;
}
$bkCount++;
$main = true;
}
$thumbsPaths = array();
if ($bkFolder->exists() && !empty($rawMeta['file']) && count($sizes)) {
foreach ($sizes as $size => $imageData) {
$destination = $fs->getFile($filePath . $imageData['file']);
$source = $fs->getFile($bkFolder->getPath() . $imageData['file']);
if (!$source->exists()) {
continue;
}
if (!$source->is_readable() || $destination->exists() && !$destination->is_writable()) {
$failedFile = $destination->is_writable() ? $source->getFullPath() : $destination->getFullPath();
$this->throwNotice('generic-err', sprintf(__("The file %s cannot be restored due to lack of permissions, please contact your hosting provider to assist you in fixing this.", 'shortpixel-image-optimiser'), "{$failedFile} (current permissions: " . sprintf("%o", fileperms($failedFile)) . ")"));
return false;
}
$bkCount++;
$thumbsPaths[$destination->getFileName()] = array('source' => $source, 'destination' => $destination);
}
}
if (!$bkCount) {
$notice = Notices::addWarning(__("Not all backup files found. Restore not performed on these files ", 'shortpixel-image-optimiser'), true);
Notices::addDetail($notice, (string) $bkFile);
Log::addError('No Backup Files Found: ' . $bkFile);
return false;
}
try {
$width = false;
if ($bkCount) {
if ($main) {
$origFile = $imageObj->has_original();
if (is_object($origFile)) {
$bkOrigFile = $origFile->getBackUpFile();
if ($bkOrigFile && $bkOrigFile->exists()) {
$bkOrigFile->move($origFile);
Log::addDebug('Restore result - Backup original file', array($bkOrigFile->getFullPath(), $origFile->getFullPath()));
}
}
if (!$bkFile->move($fsFile)) {
Log::addError('DoRestore failed restoring backup', array($bkFile->getFullPath(), $fsFile->getFullPath()));
}
$retinaBK = $fs->getFile($bkFile->getFileDir()->getPath() . $bkFile->getFileBase() . '@2x' . $bkFile->getExtension());
if ($retinaBK->exists()) {
$retinaDest = $fs->getFile($fsFile->getFileDir()->getPath() . $fsFile->getFileBase() . '@2x' . $fsFile->getExtension());
if (!$retinaBK->move($retinaDest)) {
Log::addError('DoRestore failed restoring retina backup', array($retinaBK->getFullPath(), $retinaDest->getFullPath()));
}
}
}
if ($fsFile->exists()) {
$size = getimagesize($fsFile->getFullPath());
$width = $size[0];
$height = $size[1];
}
foreach ($thumbsPaths as $index => $data) {
$source = $data['source'];
$destination = $data['destination'];
if (!$source->move($destination)) {
Log::addError('DoRestore failed restoring backup', array($source->getFullPath(), $destination->getFullPath()));
}
$retinaBK = $fs->getFile($source->getFileDir()->getPath() . $source->getFileBase() . '@2x' . $source->getExtension());
if ($retinaBK->exists()) {
$retinaDest = $fs->getFile($destination->getFileDir()->getPath() . $destination->getFileBase() . '@2x' . $destination->getExtension());
if (!$retinaBK->move($retinaDest)) {
Log::addError('DoRestore failed restoring retina backup', array($retinaBK->getFullPath(), $retinaDest->getFullPath()));
}
}
}
}
$duplicates = ShortPixelMetaFacade::getWPMLDuplicates($attachmentID);
foreach ($duplicates as $ID) {
$facade = new ShortPixelMetaFacade($ID);
if ($attachmentID == $ID) {
$crtMeta = ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($ID));
} else {
$crtMeta = $rawMeta;
}
if (isset($crtMeta['previous_meta'])) {
continue;
}
if (isset($crtMeta["ShortPixelImprovement"]) && is_numeric($crtMeta["ShortPixelImprovement"]) && 0 + $crtMeta["ShortPixelImprovement"] < 5 && $this->_settings->under5Percent > 0) {
$this->_settings->under5Percent = $this->_settings->under5Percent - 1;
}
unset($crtMeta["ShortPixelImprovement"]);
unset($crtMeta['ShortPixel']);
unset($crtMeta['ShortPixelPng2Jpg']);
delete_post_meta($ID, '_shortpixel_status');
if ($width && $height) {
$crtMeta['width'] = $width;
$crtMeta['height'] = $height;
}
if ($png2jpgMain) {
$dirname = dirname($crtMeta['file']);
if ($dirname == '.') {
$dirname = '';
} else {
$dirname = trailingslashit($dirname);
}
$crtMeta['file'] = $dirname . $fsFile->getFileName();
update_attached_file($ID, $crtMeta['file']);
if ($png2jpgSizes && count($png2jpgSizes)) {
$crtMeta['sizes'] = $png2jpgSizes;
} else {
$admin = \ShortPixel\Controller\AdminController::getInstance();
$test = remove_filter('wp_generate_attachment_metadata', array($admin, 'handleImageUploadHook'), 10);
if (!$test) {
Log::addWarn('Wp generate Attachment metadta filter not removed');
}
$crtMeta = wp_generate_attachment_metadata($ID, $png2jpgMain);
add_filter('wp_generate_attachment_metadata', array($admin, 'handleImageUploadHook'), 10, 2);
}
}
update_post_meta($ID, '_wp_attachment_metadata', $crtMeta);
if ($attachmentID == $ID) {
$rawMeta = $crtMeta;
}
}
if ($png2jpgMain) {
$spPng2Jpg = new ShortPixelPng2Jpg($this->_settings);
$spPng2Jpg->png2JpgUpdateUrls(array(), $toReplace);
}
if (isset($toUnlink['PATHs'])) {
foreach ($toUnlink['PATHs'] as $unlink) {
if ($png2jpgMain) {
Log::addDebug("PNG2JPG unlink {$unlink}");
$unlinkFile = $fs->getFile($unlink);
$unlinkFile->delete();
}
$unlinkWebpSymlink = trailingslashit(dirname($unlink)) . wp_basename($unlink, '.' . pathinfo($unlink, PATHINFO_EXTENSION)) . '.webp';
$unlinkWebp = $unlink . '.webp';
$unlinkFile = $fs->getFile($unlinkWebpSymlink);
if ($unlinkFile->exists()) {
Log::addDebug('DoRestore, Deleting Webp - ', $unlinkWebpSymlink);
$unlinkFile->delete();
}
$unlinkFileDoubleExt = $fs->getFile($unlinkWebp);
if ($unlinkFileDoubleExt->exists()) {
Log::addDebug('DoRestore, Deleting DoubleWebp - ', $unlinkWebp);
$unlinkFileDoubleExt->delete();
}
$unlinkAvif = $fs->getFile($unlinkFile->getFileDir() . $unlinkFile->getFileBase() . '.avif');
if ($unlinkAvif->exists()) {
$unlinkAvif->delete();
Log::addDebug('DoRestore, Deleting Avif :' . $unlinkAvif->getFullPath());
}
}
}
} catch (Exception $e) {
$this->throwNotice('generic-err', $e->getMessage());
return false;
}
$this->maybeDumpFromProcessedOnServer($itemHandler, $toUnlink);
$itemHandler->deleteItemCache();
$rawMeta = $itemHandler->getRawMeta();
do_action("shortpixel_after_restore_image", $attachmentID);
return $rawMeta;
}
public function throwNotice($when = 'activate', $extra = '')
{
Notices::addError($extra);
}
public function doCustomRestore($ID)
{
$itemHandler = new ShortPixelMetaFacade('C-' . $ID);
$meta = $itemHandler->getMeta();
$URLsAndPATHs = $itemHandler->getURLsAndPATHs(false);
$this->maybeDumpFromProcessedOnServer($itemHandler, $URLsAndPATHs);
if (!$meta || $meta->getStatus() != shortPixelMeta::FILE_STATUS_SUCCESS && $meta->getStatus() != shortpixelMeta::FILE_STATUS_TORESTORE) {
return false;
}
$file = $meta->getPath();
$fullSubDir = str_replace(get_home_path(), "", dirname($file)) . '/';
$bkFile = SHORTPIXEL_BACKUP_FOLDER . '/' . $fullSubDir . ShortPixelAPI::MB_basename($file);
$fs = \wpSPIO()->fileSystem();
$fileObj = $fs->getFile($file);
$backupFile = $fileObj->getBackupFile();
if ($backupFile === false) {
Log::addWarn("Custom File {$ID} - {$file} does not have a backup");
$notice = Notices::addWarning(__('Not able to restore file(s). Could not find backup', 'shortpixel-image-optimiser'), true);
Notices::addDetail($notice, (string) $file);
return false;
} elseif ($backupFile->copy($fileObj)) {
$backupFile->delete();
} else {
Log::addError('Could not restore back to source' . $backupFile->getFullPath());
$notice = Notices::addError('These file(s) could not be restored from backup. Plugin could not copy backup back to original location. Check file permissions. ', 'shortpixel-image-optimiser');
Notices::addDetail($notice, (string) $backupFile);
return false;
}
$meta->setTsOptimized(0);
$meta->setCompressedSize(0);
$meta->setCompressionType(0);
$meta->setKeepExif(0);
$meta->setCmyk2rgb(0);
$meta->setMessage('');
$meta->setRetries(0);
$meta->setBackup(0);
$meta->setResizeWidth(0);
$meta->setResizeHeight(0);
$meta->setResize(0);
$meta->setStatus(3);
$this->spMetaDao->update($meta);
$itemHandler->deleteItemCache();
return $meta;
}
public function handleRestoreBackup()
{
$attachmentID = intval($_GET['attachment_ID']);
self::log("Handle Restore Backup #{$attachmentID}");
$this->doRestore($attachmentID);
$sendback = wp_get_referer();
$sendback = preg_replace('|[^a-z0-9-~+_.?#=&;,/:]|i', '', $sendback);
wp_redirect($sendback);
}
public function handleRedo()
{
Log::addDebug("Handle Redo #{$_GET['attachment_ID']} type {$_GET['type']}");
$attach_id = intval($_GET['attachment_ID']);
$type = sanitize_text_field($_GET['type']);
die(json_encode($this->redo($attach_id, $type)));
}
public function redo($qID, $type = false)
{
$compressionType = $type == 'lossless' ? 'lossless' : ($type == 'glossy' ? 'glossy' : 'lossy');
if (ShortPixelMetaFacade::isCustomQueuedId($qID)) {
$ID = ShortPixelMetaFacade::stripQueuedIdType($qID);
$meta = $this->spMetaDao->getMeta($ID);
$path = $meta->getPath();
$folder_id = $meta->getFolderId();
$this->doCustomRestore($ID);
if ($meta) {
$meta->setCompressionType(ShortPixelAPI::getCompressionTypeCode($compressionType));
$meta->setStatus(1);
$this->spMetaDao->update($meta);
$this->prioQ->push($qID);
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
} else {
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => __('Could not restore from backup: ', 'shortpixel-image-optimiser') . $qID);
}
} else {
$ID = intval($qID);
$meta = $this->doRestore($ID);
if ($meta) {
$meta['ShortPixel'] = array("type" => $compressionType);
update_post_meta($ID, '_wp_attachment_metadata', $meta);
try {
$this->sendToProcessing(new ShortPixelMetaFacade($ID), ShortPixelAPI::getCompressionTypeCode($compressionType));
$this->prioQ->push($ID);
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
} catch (Exception $e) {
$meta['ShortPixelImprovement'] = $e->getMessage();
$meta['ShortPixel']['ErrCode'] = $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::STATUS_FAIL;
unset($meta['ShortPixel']['WaitingProcessing']);
update_post_meta($ID, '_wp_attachment_metadata', $meta);
$ret = array("Status" => ShortPixelAPI::STATUS_FAIL, "Message" => $e->getMessage());
}
} else {
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => __('Could not restore from backup: ', 'shortpixel-image-optimiser') . $ID);
}
}
return $ret;
}
public function handleOptimizeThumbs()
{
$ID = intval($_GET['attachment_ID']);
$meta = wp_get_attachment_metadata($ID);
$fs = \wpSPIO()->filesystem();
$error = array('Status' => ShortPixelAPI::STATUS_SKIP, 'message' => __('Unspecified Error on Thumbnails for: ') . $ID);
$optFile = $fs->getAttachedFile($ID);
list($includedSizes, $thumbsCount) = $this->getThumbsToOptimize($meta, $optFile->getFullPath());
$thumbsCount = count($includedSizes);
if (!isset($meta['ShortPixelImprovement'])) {
$error['message'] = __('Please optimize image for ID: ', 'shortpixel-image-optimiser') . $ID;
die(json_encode($error));
}
if (!isset($meta['sizes']) || count($meta['sizes']) == 0) {
$error['message'] = __('No thumbnails to optimize for ID: ', 'shortpixel-image-optimiser') . $ID;
die(json_encode($error));
}
if (isset($meta['ShortPixel']['thumbsOptList']) && is_array($meta['ShortPixel']['thumbsOptList'])) {
$thumbList = array();
foreach ($meta['ShortPixel']['thumbsOptList'] as $fileName) {
if (isset($includedSizes[$fileName])) {
$thumbList[] = $fileName;
}
}
$meta['ShortPixel']['thumbsOptList'] = $thumbList;
}
if ($thumbsCount && (isset($meta['sizes']) && isset($meta['ShortPixel']['thumbsOptList']) && count($meta['ShortPixel']['thumbsOptList']) < $thumbsCount)) {
$meta['ShortPixel']['thumbsTodo'] = true;
update_post_meta($ID, '_wp_attachment_metadata', $meta);
$this->prioQ->push($ID);
try {
$this->sendToProcessing(new ShortPixelMetaFacade($ID), false, true);
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "message" => "");
} catch (Exception $e) {
if (!isset($meta['ShortPixelImprovement']) || !is_numeric($meta['ShortPixelImprovement'])) {
$meta['ShortPixelImprovement'] = $e->getMessage();
$meta['ShortPixel']['ErrCode'] = $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::STATUS_FAIL;
unset($meta['ShortPixel']['WaitingProcessing']);
update_post_meta($ID, '_wp_attachment_metadata', $meta);
}
$ret = array("Status" => ShortPixelAPI::STATUS_FAIL, "Message" => $e->getMessage());
}
} else {
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "message" => (isset($meta['ShortPixelImprovement']) ? __('No thumbnails to optimize for ID: ', 'shortpixel-image-optimiser') : __('Please optimize image for ID: ', 'shortpixel-image-optimiser')) . $ID);
}
die(json_encode($ret));
}
public function handleCheckQuota()
{
$return_json = isset($_POST['return_json']) ? true : false;
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'check_quota')) {
Log::addError('Handle Check Quota, No nonce');
exit('no nonce');
}
$result = $this->getQuotaInformation();
AdminNoticesController::resetQuotaNotices();
$sendback = wp_get_referer();
$sendback = preg_replace('|[^a-z0-9-~+_.?#=&;,/:]|i', '', $sendback);
if ($return_json) {
$result = array('status' => 'no-quota', 'redirect' => $sendback);
if (!$this->_settings->quotaExceeded) {
$result['status'] = 'has-quota';
} else {
Notices::addWarning(__('You have no available image credits. If you just bought a package, please note that sometimes it takes a few minutes for the payment confirmation to be sent to us by the payment processor.', 'shortpixel-image-optimiser'));
}
wp_send_json($result);
} else {
wp_redirect($sendback);
}
}
public function handleDeleteAttachmentInBackup($ID)
{
$fileObj = \wpSPIO()->filesystem()->getAttachedFile($ID);
$file = $fileObj->getFullPath();
$meta = wp_get_attachment_metadata($ID);
if (self::_isProcessable($ID) != false) {
try {
$SubDir = ShortPixelMetaFacade::returnSubDir($file);
if (file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file))) {
@unlink(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file));
}
if (!empty($meta['file'])) {
$filesPath = SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir;
if (isset($meta["sizes"])) {
foreach ($meta["sizes"] as $size => $imageData) {
if (file_exists($filesPath . ShortPixelAPI::MB_basename($imageData['file']))) {
@unlink($filesPath . ShortPixelAPI::MB_basename($imageData['file']));
}
}
}
}
} catch (Exception $e) {
}
}
}
public function deactivatePlugin()
{
if (!wp_verify_nonce($_GET['_wpnonce'], 'sp_deactivate_plugin_nonce')) {
wp_nonce_ays('');
}
$referrer_url = wp_get_referer();
$conflict = \ShortPixelTools::getConflictingPlugins();
foreach ($conflict as $c => $value) {
$conflictingString = $value['page'];
if ($conflictingString != null && strpos($referrer_url, $conflictingString) !== false) {
$this->deactivateAndRedirect(get_dashboard_url());
break;
}
}
$this->deactivateAndRedirect(wp_get_referer());
}
protected function deactivateAndRedirect($url)
{
deactivate_plugins(sanitize_text_field($_GET['plugin']));
wp_safe_redirect($url);
die;
}
public function countAllIfNeeded($quotaData, $time)
{
if (!(defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG === true) && is_array($this->_settings->currentStats) && $this->_settings->currentStats['optimizePdfs'] == $this->_settings->optimizePdfs && isset($this->_settings->currentStats['time']) && time() - $this->_settings->currentStats['time'] < $time) {
Log::addDebug("CURRENT STATS FROM CACHE (not older than {$time} sec., currently " . (time() - $this->_settings->currentStats['time']) . ' sec. old)');
return $this->_settings->currentStats;
} else {
Log::addDebug("CURRENT STATS (not older than {$time}) ARE BEING CALCULATED...");
if (!is_array($quotaData)) {
$quotaData = array();
}
$imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessable($this->_settings);
$quotaData['time'] = time();
$quotaData['optimizePdfs'] = $this->_settings->optimizePdfs;
foreach ($imageCount as $key => $val) {
$quotaData[$key] = $val;
}
if ($this->_settings->hasCustomFolders) {
$customImageCount = $this->spMetaDao->countAllProcessableFiles();
foreach ($customImageCount as $key => $val) {
$quotaData[$key] = isset($quotaData[$key]) ? is_array($quotaData[$key]) ? array_merge($quotaData[$key], $val) : (is_numeric($quotaData[$key]) ? $quotaData[$key] + $val : $quotaData[$key] . ", " . $val) : $val;
}
}
$this->_settings->currentStats = $quotaData;
return $quotaData;
}
}
public function checkQuotaAndAlert($quotaData = null, $recheck = false, $refreshFiles = 300)
{
if (!$quotaData) {
$quotaData = $this->getQuotaInformation();
}
if (!$quotaData['APIKeyValid']) {
if (strlen($this->_settings->apiKey)) {
Notices::addError(sprintf(__('Shortpixel Remote API Error: %s', 'shortpixel-image-optimiser'), $quotaData['Message']));
}
return $quotaData;
}
$quotaData = $this->countAllIfNeeded($quotaData, $refreshFiles);
if ($quotaData['APICallsQuotaNumeric'] + $quotaData['APICallsQuotaOneTimeNumeric'] > $quotaData['APICallsMadeNumeric'] + $quotaData['APICallsMadeOneTimeNumeric']) {
$this->_settings->quotaExceeded = '0';
$this->_settings->prioritySkip = NULL;
Log::addInfo("CHECK QUOTA: Skipped: " . json_encode($this->prioQ->getSkipped()));
?><script>var shortPixelQuotaExceeded = 0;</script><?php
} else {
?><script>var shortPixelQuotaExceeded = 1;</script><?php
}
return $quotaData;
}
public function isValidMetaId($id)
{
return substr($id, 0, 2) == "C-" ? $this->spMetaDao->getMeta(substr($id, 2)) : wp_get_attachment_url($id);
}
public function getPercent($quotaData)
{
if ($this->_settings->processThumbnails) {
return $quotaData["totalFiles"] ? min(99, round($quotaData["totalProcessedFiles"] * 100.0 / $quotaData["totalFiles"])) : 0;
} else {
return $quotaData["mainFiles"] ? min(99, round($quotaData["mainProcessedFiles"] * 100.0 / $quotaData["mainFiles"])) : 0;
}
}
public function bulkProgressMessage($percent, $minutes)
{
$timeEst = "";
self::log("bulkProgressMessage(): percent: " . $percent);
if ($percent < 1 || $minutes == 0) {
$timeEst = "";
} elseif ($minutes > 2880) {
$timeEst = "~ " . round($minutes / 1440) . " days left";
} elseif ($minutes > 240) {
$timeEst = "~ " . round($minutes / 60) . " hours left";
} elseif ($minutes > 60) {
$hours = round($minutes / 60);
$minutes = round(max(0, $minutes - $hours * 60) / 10) * 10;
$timeEst = "~ " . $hours . " hours " . ($minutes > 0 ? $minutes . " min." : "") . " left";
} elseif ($minutes > 20) {
$timeEst = "~ " . round($minutes / 10) * 10 . " minutes left";
} else {
$timeEst = "~ " . $minutes . " minutes left";
}
return $timeEst;
}
public function emptyBackup()
{
if (file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
$this->deleteDir(SHORTPIXEL_BACKUP_FOLDER);
}
}
public function backupFolderIsEmpty()
{
if (file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
return count(scandir(SHORTPIXEL_BACKUP_FOLDER)) > 2 ? false : true;
}
}
public function getBackupSize()
{
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'shortpixel-image-optimiser'));
}
die(self::formatBytes(self::folderSize(SHORTPIXEL_BACKUP_FOLDER)));
}
public function browseContent()
{
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'shortpixel-image-optimiser'));
}
$root = self::getCustomFolderBase();
$fs = \wpSPIO()->filesystem();
$postDir = rawurldecode($root . (isset($_POST['dir']) ? trim($_POST['dir']) : null));
$checkbox = isset($_POST['multiSelect']) && $_POST['multiSelect'] == 'true' ? "<input type='checkbox' />" : null;
$onlyFolders = $_POST['dir'] == '/' || isset($_POST['onlyFolders']) && $_POST['onlyFolders'] == 'true' ? true : false;
$onlyFiles = isset($_POST['onlyFiles']) && $_POST['onlyFiles'] == 'true' ? true : false;
if (file_exists($postDir)) {
$dir = $fs->getDirectory($postDir);
$files = $dir->getFiles();
$subdirs = $fs->sortFiles($dir->getSubDirectories());
$returnDir = substr($postDir, strlen($root));
foreach ($subdirs as $index => $dir) {
$dirname = $dir->getName();
if ($dirname == 'ShortpixelBackups' || ShortPixelMetaFacade::isMediaSubfolder($dirname, false)) {
unset($subdirs[$index]);
}
}
if (count($subdirs) > 0) {
echo "<ul class='jqueryFileTree'>";
foreach ($subdirs as $dir) {
$dirpath = $dir->getPath();
$dirname = $dir->getName();
$htmlRel = str_replace("'", "'", $returnDir . $dirname);
$htmlName = htmlentities($dirname);
if ($dir->exists()) {
echo "<li class='directory collapsed'>{$checkbox}<a rel=' " . $htmlRel . "/'>" . $htmlName . "</a></li>";
}
}
echo "</ul>";
} elseif ($_POST['dir'] == '/') {
echo "<ul class='jqueryFileTree'>";
_e('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
echo "</ul>";
}
}
die;
}
public function getComparerData()
{
if (!isset($_POST['id']) || !current_user_can('upload_files') && !current_user_can('edit_posts')) {
wp_die(json_encode((object) array('origUrl' => false, 'optUrl' => false, 'width' => 0, 'height' => 0)));
}
$ret = array();
$fs = \wpSPIO()->filesystem();
$imageObj = new ImageModel();
$imageObj->setByPostID(sanitize_text_field($_POST['id']));
$file = $imageObj->getFile();
$backupFile = $file->getBackupFile();
if (!$backupFile && $imageObj->has_original()) {
$file = $imageObj->has_original();
$backupFile = $file->getBackupFile();
}
$backup_url = $fs->pathToUrl($backupFile);
$meta = $imageObj->getMeta();
$ret['origUrl'] = $backup_url;
$ret['optUrl'] = $fs->pathToUrl($file);
$ret['width'] = $meta->getActualWidth();
$ret['height'] = $meta->getActualHeight();
if (is_null($ret['width'])) {
$imageSizes = getimagesize($meta->getPath());
if ($imageSizes) {
$ret['width'] = $imageSizes[0];
$ret['height'] = $imageSizes[1];
}
}
die(json_encode((object) $ret));
}
public function newApiKey()
{
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'shortpixel-image-optimiser'));
}
if ($this->_settings->verifiedKey) {
die(json_encode((object) array('Status' => 'success', 'Details' => $this->_settings->apiKey)));
}
$params = array('method' => 'POST', 'timeout' => 10, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => true, 'sslverify' => false, 'headers' => array(), 'body' => array('plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION, 'email' => isset($_POST['email']) ? trim($_POST['email']) : null, 'ip' => isset($_SERVER["HTTP_X_FORWARDED_FOR"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : $_SERVER['REMOTE_ADDR']));
$newKeyResponse = wp_remote_post("https://shortpixel.com/free-sign-up-plugin", $params);
if (is_object($newKeyResponse) && get_class($newKeyResponse) == 'WP_Error') {
die(json_encode((object) array('Status' => 'fail', 'Details' => '503')));
} elseif (isset($newKeyResponse['response']['code']) && $newKeyResponse['response']['code'] != 200) {
die(json_encode((object) array('Status' => 'fail', 'Details' => $newKeyResponse['response']['code'])));
}
$body = (object) $this->_apiInterface->parseResponse($newKeyResponse);
if ($body->Status == 'success') {
$key = trim($body->Details);
$validityData = $this->getQuotaInformation($key, true, true);
if ($validityData['APIKeyValid']) {
$this->_settings->apiKey = $key;
$this->_settings->verifiedKey = true;
\ShortPixel\Controller\AdminNoticesController::resetAPINotices();
Notices::addSuccess(__('Great, you successfully claimed your API Key! Please take a few moments to review the plugin settings below before starting to optimize your images.', 'shortpixel-image-optimiser'));
}
}
die(json_encode($body));
}
public function proposeUpgrade()
{
if (!current_user_can('manage_options')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'shortpixel-image-optimiser'));
}
$stats = $this->countAllIfNeeded($this->_settings->currentStats, 300);
$proposal = wp_remote_post("https://shortpixel.com/propose-upgrade-frag", array('method' => 'POST', 'timeout' => 10, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => true, 'headers' => array(), 'body' => array("params" => json_encode(array('plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION, 'key' => $this->_settings->apiKey, 'm1' => $stats['totalM1'], 'm2' => $stats['totalM2'], 'm3' => $stats['totalM3'], 'm4' => $stats['totalM4'], 'filesTodo' => $stats['totalFiles'] - $stats['totalProcessedFiles'], 'estimated' => $this->_settings->optimizeUnlisted || $this->_settings->optimizeRetina ? 'true' : 'false', 'iconsUrl' => base64_encode(wpSPIO()->plugin_url('res/img'))))), 'cookies' => array()));
if (is_wp_error($proposal)) {
$proposal = array('body' => '');
}
die($proposal['body']);
}
public static function getCustomFolderBase()
{
Log::addDebug('Call to legacy function getCustomFolderBase');
$fs = \wpSPIO()->filesystem();
$dir = $fs->getWPFileBase();
return $dir->getPath();
}
public static function alterHtaccess($webp = false, $avif = false)
{
if (!function_exists('insert_with_markers')) {
Log::addWarn('AlterHtaccess Called before WP init');
return;
}
$upload_dir = wp_upload_dir();
$upload_base = trailingslashit($upload_dir['basedir']);
if (!$webp && !$avif) {
insert_with_markers(get_home_path() . '.htaccess', 'ShortPixelWebp', '');
insert_with_markers($upload_base . '.htaccess', 'ShortPixelWebp', '');
insert_with_markers(trailingslashit(WP_CONTENT_DIR) . '.htaccess', 'ShortPixelWebp', '');
} else {
$avif_rules = '
<IfModule mod_rewrite.c>
RewriteEngine On
##### IF try the file with replaced extension (test.avif) #####
RewriteCond %{HTTP_ACCEPT} image/avif
# AND is the request a jpg or png? (also grab the basepath %1 to match in the next rule)
RewriteCond %{REQUEST_URI} ^(.+)\\.(?:jpe?g|png)$
# AND does a .avif image exist?
RewriteCond %{DOCUMENT_ROOT}/%1.avif -f
# THEN send the webp image and set the env var avif
RewriteRule (.+)\\.(?:jpe?g|png)$ $1.avif [NC,T=image/avif,E=avif,L]
</IfModule>
<IfModule mod_headers.c>
# If REDIRECT_webp env var exists, append Accept to the Vary header
Header append Vary Accept env=REDIRECT_avif
</IfModule>
<IfModule mod_mime.c>
AddType image/avif .avif
</IfModule>
';
$webp_rules = '
<IfModule mod_rewrite.c>
RewriteEngine On
##### TRY FIRST the file appended with .webp (ex. test.jpg.webp) #####
# Does browser explicitly support webp?
RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
# OR Is request from Page Speed
RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
# OR does this browser explicitly support webp
RewriteCond %{HTTP_ACCEPT} image/webp
# AND NOT MS EDGE 42/17 - doesnt work.
RewriteCond %{HTTP_USER_AGENT} !Edge/17
# AND is the request a jpg or png?
RewriteCond %{REQUEST_URI} ^(.+)\\.(?:jpe?g|png)$
# AND does a .ext.webp image exist?
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.webp -f
# THEN send the webp image and set the env var webp
RewriteRule ^(.+)$ $1.webp [NC,T=image/webp,E=webp,L]
##### IF NOT, try the file with replaced extension (test.webp) #####
RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{HTTP_USER_AGENT} !Edge/17
# AND is the request a jpg or png? (also grab the basepath %1 to match in the next rule)
RewriteCond %{REQUEST_URI} ^(.+)\\.(?:jpe?g|png)$
# AND does a .ext.webp image exist?
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
# THEN send the webp image and set the env var webp
RewriteRule (.+)\\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]
</IfModule>
<IfModule mod_headers.c>
# If REDIRECT_webp env var exists, append Accept to the Vary header
Header append Vary Accept env=REDIRECT_webp
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
';
$rules = '';
$rules .= $avif_rules;
$rules .= $webp_rules;
insert_with_markers(get_home_path() . '.htaccess', 'ShortPixelWebp', $rules);
$rules = str_replace('RewriteEngine On', 'RewriteEngine On' . PHP_EOL . 'RewriteOptions Inherit', $rules);
insert_with_markers($upload_base . '.htaccess', 'ShortPixelWebp', $rules);
insert_with_markers(trailingslashit(WP_CONTENT_DIR) . '.htaccess', 'ShortPixelWebp', $rules);
}
}
public function getAverageCompression()
{
return $this->_settings->totalOptimized > 0 ? round((1 - $this->_settings->totalOptimized / $this->_settings->totalOriginal) * 100, 2) : 0;
}
public function addWebpMime($mimes)
{
if ($this->_settings->createWebp) {
if (!isset($mimes['webp'])) {
$mimes['webp'] = 'image/webp';
}
}
return $mimes;
}
public function addAvifMime($mimes)
{
if ($this->_settings->createAvif) {
if (!isset($mimes['avif'])) {
$mimes['webp'] = 'image/avif';
}
}
return $mimes;
}
public function getQuotaInformation($apiKey = null, $appendUserAgent = false, $validate = false, $settings = false)
{
if (is_null($apiKey)) {
$apiKey = $this->_settings->apiKey;
}
if ($this->_settings->httpProto != 'https' && $this->_settings->httpProto != 'http') {
$this->_settings->httpProto = 'https';
}
$requestURL = $this->_settings->httpProto . '://' . SHORTPIXEL_API . '/v2/api-status.php';
$args = array('timeout' => SHORTPIXEL_VALIDATE_MAX_TIMEOUT, 'body' => array('key' => $apiKey));
$argsStr = "?key=" . $apiKey;
if ($appendUserAgent) {
$args['body']['useragent'] = "Agent" . urlencode($_SERVER['HTTP_USER_AGENT']);
$argsStr .= "&useragent=Agent" . $args['body']['useragent'];
}
if ($validate) {
$args['body']['DomainCheck'] = get_site_url();
$args['body']['Info'] = get_bloginfo('version') . '|' . phpversion();
$imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessable($this->_settings);
$args['body']['ImagesCount'] = $imageCount['mainFiles'];
$args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
$argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
}
$args['body']['host'] = parse_url(get_site_url(), PHP_URL_HOST);
$argsStr .= "&host={$args['body']['host']}";
if (strlen($this->_settings->siteAuthUser)) {
$args['body']['user'] = stripslashes($this->_settings->siteAuthUser);
$args['body']['pass'] = stripslashes($this->_settings->siteAuthPass);
$argsStr .= '&user=' . urlencode($args['body']['user']) . '&pass=' . urlencode($args['body']['pass']);
}
if ($settings !== false) {
$args['body']['Settings'] = $settings;
}
$time = microtime(true);
$comm = array();
if ($this->_settings->httpProto === 'https') {
$args['sslverify'] = false;
}
$response = wp_remote_post($requestURL, $args);
$comm['A: ' . number_format(microtime(true) - $time, 2)] = array("sent" => "POST: " . $requestURL, "args" => $args, "received" => $response);
if (is_wp_error($response)) {
$requestURL = $this->_settings->httpProto == 'https' ? str_replace('https://', 'http://', $requestURL) : str_replace('http://', 'https://', $requestURL);
if ($this->_settings->httpProto === 'http') {
$args['sslverify'] = false;
} else {
unset($args['sslverify']);
}
$response = wp_remote_post($requestURL, $args);
$comm['B: ' . number_format(microtime(true) - $time, 2)] = array("sent" => "POST: " . $requestURL, "args" => $args, "received" => $response);
if (!is_wp_error($response)) {
$this->_settings->httpProto = $this->_settings->httpProto == 'https' ? 'http' : 'https';
} else {
}
}
if (is_wp_error($response)) {
$args['body'] = null;
$requestURL .= $argsStr;
$response = wp_remote_get($requestURL, $args);
$comm['C: ' . number_format(microtime(true) - $time, 2)] = array("sent" => "POST: " . $requestURL, "args" => $args, "received" => $response);
}
Log::addInfo("API STATUS COMM: " . json_encode($comm));
$defaultData = array("APIKeyValid" => false, "Message" => __('API Key could not be validated due to a connectivity error.<BR>Your firewall may be blocking us. Please contact your hosting provider and ask them to allow connections from your site to api.shortpixel.com (IP 176.9.21.94).<BR> If you still cannot validate your API Key after this, please <a href="https://shortpixel.com/contact" target="_blank">contact us</a> and we will try to help. ', 'shortpixel-image-optimiser'), "APICallsMade" => __('Information unavailable. Please check your API key.', 'shortpixel-image-optimiser'), "APICallsQuota" => __('Information unavailable. Please check your API key.', 'shortpixel-image-optimiser'), "APICallsMadeOneTime" => 0, "APICallsQuotaOneTime" => 0, "APICallsMadeNumeric" => 0, "APICallsQuotaNumeric" => 0, "APICallsMadeOneTimeNumeric" => 0, "APICallsQuotaOneTimeNumeric" => 0, "APICallsRemaining" => 0, "APILastRenewalDate" => 0, "DomainCheck" => 'NOT Accessible');
$defaultData = is_array($this->_settings->currentStats) ? array_merge($this->_settings->currentStats, $defaultData) : $defaultData;
if (is_object($response) && get_class($response) == 'WP_Error') {
$urlElements = parse_url($requestURL);
$portConnect = @fsockopen($urlElements['host'], 8, $errno, $errstr, 15);
if (!$portConnect) {
$defaultData['Message'] .= "<BR>Debug info: <i>{$errstr}</i>";
}
return $defaultData;
}
if ($response['response']['code'] != 200) {
return $defaultData;
}
$data = $response['body'];
$data = json_decode($data);
if (empty($data)) {
return $defaultData;
}
if ($data->Status->Code != 2) {
$defaultData['Message'] = $data->Status->Message;
return $defaultData;
}
if ($data->APICallsMade + $data->APICallsMadeOneTime < $data->APICallsQuota + $data->APICallsQuotaOneTime) {
$this->resetQuotaExceeded();
} else {
$this->_settings->quotaExceeded = 1;
}
$lastStatus = $this->_settings->bulkLastStatus;
if ($lastStatus && $lastStatus['Status'] == ShortPixelAPI::STATUS_NO_KEY) {
$this->_settings->bulkLastStatus = null;
}
$dataArray = array("APIKeyValid" => true, "APICallsMade" => number_format($data->APICallsMade) . __(' images', 'shortpixel-image-optimiser'), "APICallsQuota" => number_format($data->APICallsQuota) . __(' images', 'shortpixel-image-optimiser'), "APICallsMadeOneTime" => number_format($data->APICallsMadeOneTime) . __(' images', 'shortpixel-image-optimiser'), "APICallsQuotaOneTime" => number_format($data->APICallsQuotaOneTime) . __(' images', 'shortpixel-image-optimiser'), "APICallsMadeNumeric" => $data->APICallsMade, "APICallsQuotaNumeric" => $data->APICallsQuota, "APICallsMadeOneTimeNumeric" => $data->APICallsMadeOneTime, "APICallsQuotaOneTimeNumeric" => $data->APICallsQuotaOneTime, "APICallsRemaining" => $data->APICallsQuota + $data->APICallsQuotaOneTime - $data->APICallsMade - $data->APICallsMadeOneTime, "APILastRenewalDate" => $data->DateSubscription, "DomainCheck" => isset($data->DomainCheck) ? $data->DomainCheck : null);
$crtStats = is_array($this->_settings->currentStats) ? array_merge($this->_settings->currentStats, $dataArray) : $dataArray;
$crtStats['optimizePdfs'] = $this->_settings->optimizePdfs;
$this->_settings->currentStats = $crtStats;
Log::addDebug('GetQuotaInformation Result ', $dataArray);
return $dataArray;
}
public function resetQuotaExceeded()
{
if ($this->_settings->quotaExceeded == 1) {
$dismissed = $this->_settings->dismissedNotices ? $this->_settings->dismissedNotices : array();
$this->_settings->prioritySkip = array();
$this->_settings->dismissedNotices = $dismissed;
\ShortPixel\Controller\adminNoticesController::resetAPINotices();
\ShortPixel\Controller\adminNoticesController::resetQuotaNotices();
}
$this->_settings->quotaExceeded = 0;
}
public function generateCustomColumn($column_name, $id, $extended = false)
{
if ('wp-shortPixel' == $column_name) {
if (!$this->isProcessable($id)) {
$renderData['status'] = 'n/a';
$this->view->renderCustomColumn($id, $renderData, $extended);
return;
}
$fs = \wpSPIO()->filesystem();
$file = $fs->getAttachedFile($id);
$data = ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($id));
$itemHandler = new ShortPixelMetaFacade($id);
$meta = $itemHandler->getMeta();
$fileExtension = strtolower($file->getExtension());
$invalidKey = !$this->_settings->verifiedKey;
$quotaExceeded = $this->_settings->quotaExceeded;
$renderData = array("id" => $id, "showActions" => current_user_can('manage_options') || current_user_can('upload_files') || current_user_can('edit_posts'));
if ($invalidKey) {
$renderData['status'] = 'invalidKey';
$this->view->renderCustomColumn($id, $renderData, $extended);
return;
} elseif (empty($data)) {
if ($fileExtension == "pdf") {
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
$renderData['message'] = __('PDF not processed.', 'shortpixel-image-optimiser');
} else {
$renderData['status'] = 'n/a';
}
$this->view->renderCustomColumn($id, $renderData, $extended);
return;
}
if (!isset($data['ShortPixelImprovement'])) {
$data['ShortPixelImprovement'] = '';
}
if (is_numeric($data['ShortPixelImprovement']) && !($data['ShortPixelImprovement'] == 0 && isset($data['ShortPixel']['WaitingProcessing']))) {
$thumbsOptList = isset($data['ShortPixel']['thumbsOptList']) ? $data['ShortPixel']['thumbsOptList'] : array();
list($thumbsToOptimizeList, $sizesCount) = $this->getThumbsToOptimize($data, $file->getFullPath());
$renderData['status'] = $fileExtension == "pdf" ? 'pdfOptimized' : 'imgOptimized';
$renderData['percent'] = $this->optimizationPercentIfPng2Jpg($data);
$renderData['bonus'] = $data['ShortPixelImprovement'] < 5;
$renderData['backup'] = $this->getBackupFolderAny($file->getFullPath(), $sizesCount ? $data['sizes'] : array());
$renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
$renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionTypes(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
$renderData['thumbsTotal'] = $sizesCount;
$renderData['thumbsOpt'] = isset($data['ShortPixel']['thumbsOpt']) ? $data['ShortPixel']['thumbsOpt'] : $sizesCount;
$renderData['thumbsToOptimize'] = is_array($thumbsToOptimizeList) ? count($thumbsToOptimizeList) : 0;
$renderData['thumbsToOptimizeList'] = $thumbsToOptimizeList;
$renderData['thumbsOptList'] = $thumbsOptList;
$renderData['excludeSizes'] = isset($data['ShortPixel']['excludeSizes']) ? $data['ShortPixel']['excludeSizes'] : null;
$renderData['thumbsMissing'] = isset($data['ShortPixel']['thumbsMissing']) ? $data['ShortPixel']['thumbsMissing'] : array();
$renderData['retinasOpt'] = isset($data['ShortPixel']['retinasOpt']) ? $data['ShortPixel']['retinasOpt'] : null;
$renderData['exifKept'] = isset($data['ShortPixel']['exifKept']) ? $data['ShortPixel']['exifKept'] : null;
$renderData['png2jpg'] = isset($data['ShortPixelPng2Jpg']) ? $data['ShortPixelPng2Jpg'] : 0;
$renderData['date'] = isset($data['ShortPixel']['date']) ? $data['ShortPixel']['date'] : null;
$renderData['quotaExceeded'] = $quotaExceeded;
$webP = 0;
$avif = 0;
if ($extended) {
if (file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($file->getFullPath(), '.' . $fileExtension) . '.webp')) {
$webP++;
} elseif (file_exists($file->getFullPath() . '.webp')) {
$webP++;
}
if (file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($file->getFullPath(), '.' . $fileExtension) . '.avif')) {
$avif++;
}
if (isset($data['sizes'])) {
foreach ($data['sizes'] as $key => $size) {
if (strpos($key, ShortPixelMeta::WEBP_THUMB_PREFIX) === 0) {
continue;
}
$sizeName = $size['file'];
if (file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($sizeName, '.' . $fileExtension) . '.webp')) {
$webP++;
} elseif (file_exists(dirname($file->getFullPath()) . '/' . $sizeName . '.webp')) {
$webP++;
}
if (file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($sizeName, '.' . $fileExtension) . '.avif')) {
$avif++;
}
}
}
}
$renderData['webpCount'] = $webP;
$renderData['avifCount'] = $avif;
} elseif (trim(strip_tags($data['ShortPixelImprovement'])) == __("Cannot write optimized file", 'shortpixel-image-optimiser')) {
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'retry';
$renderData['message'] = __("Cannot write optimized file", 'shortpixel-image-optimiser') . " - <a href='https://shortpixel.com/faq#cannot-write-optimized-file' target='_blank'>" . __("Why?", 'shortpixel-image-optimiser') . "</a>";
} elseif (strlen(trim(strip_tags($data['ShortPixelImprovement']))) > 0) {
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'retry';
$renderData['message'] = $data['ShortPixelImprovement'];
if (strpos($renderData['message'], __('The file(s) do not exist on disk: ', 'shortpixel-image-optimiser')) !== false) {
$renderData['cleanup'] = true;
}
} elseif (isset($data['ShortPixel']['NoFileOnDisk'])) {
$renderData['status'] = 'notFound';
$renderData['message'] = __('Image does not exist', 'shortpixel-image-optimiser');
} elseif (isset($data['ShortPixel']['WaitingProcessing'])) {
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'waiting';
$renderData['message'] = "<img src=\"" . plugins_url('res/img/loading.gif', SHORTPIXEL_PLUGIN_FILE) . "\" class='sp-loading-small'> " . __("Image waiting to be processed.", 'shortpixel-image-optimiser');
if ($this->_settings->autoMediaLibrary && !$quotaExceeded && ($id > $this->prioQ->getFlagBulkId() || !$this->prioQ->bulkRunning())) {
$this->prioQ->unskip($id);
$this->prioQ->push($id);
}
} else {
$renderData['status'] = $quotaExceeded ? 'quotaExceeded' : 'optimizeNow';
$sizes = isset($data['sizes']) ? WpShortPixelMediaLbraryAdapter::countSizesNotExcluded($data['sizes']) : 0;
$renderData['thumbsTotal'] = $sizes;
$renderData['message'] = ($fileExtension == "pdf" ? 'PDF' : __('Image', 'shortpixel-image-optimiser')) . __(' not processed.', 'shortpixel-image-optimiser') . ' (<a href="https://shortpixel.com/image-compression-test?site-url=' . urlencode(ShortPixelMetaFacade::safeGetAttachmentUrl($id)) . '" target="_blank">' . __('Test for free', 'shortpixel-image-optimiser') . '</a>)';
}
$this->view->renderCustomColumn($id, $renderData, $extended);
}
}
function getThumbsToOptimize($data, $filepath)
{
return WpShortPixelMediaLbraryAdapter::getThumbsToOptimize($data, $filepath);
}
function columnRegisterSortable($columns)
{
$columns['wp-shortPixel'] = 'ShortPixel Compression';
return $columns;
}
function columnOrderFilterBy($vars)
{
if (isset($vars['orderby']) && 'ShortPixel Compression' == $vars['orderby']) {
$vars = array_merge($vars, array('meta_key' => '_shortpixel_status', 'orderby' => 'meta_value_num'));
}
if ('upload.php' == $GLOBALS['pagenow'] && isset($_GET['shortpixel_status'])) {
$status = sanitize_text_field($_GET['shortpixel_status']);
$metaKey = '_shortpixel_status';
if ($status == 'all') {
return $vars;
}
switch ($status) {
case "opt":
$status = ShortPixelMeta::FILE_STATUS_SUCCESS;
$metaCompare = ">=";
break;
case "unopt":
$status = ShortPixelMeta::FILE_STATUS_UNPROCESSED;
$metaCompare = "NOT EXISTS";
break;
case "pending":
$status = ShortPixelMeta::FILE_STATUS_PENDING;
$metaCompare = "=";
break;
case "error":
$status = -1;
$metaCompare = "<=";
break;
}
$vars = array_merge($vars, array('meta_query' => array(array('key' => $metaKey, 'value' => $status, 'compare' => $metaCompare))));
}
return $vars;
}
function mediaAddFilterDropdown()
{
$scr = get_current_screen();
if ($scr->base !== 'upload') {
return;
}
$status = filter_input(INPUT_GET, 'shortpixel_status', FILTER_SANITIZE_STRING);
$options = array('all' => __('All Images', 'shortpixel-image-optimiser'), 'opt' => __('Optimized', 'shortpixel-image-optimiser'), 'unopt' => __('Unoptimized', 'shortpixel-image-optimiser'));
echo "<select name='shortpixel_status' id='shortpixel_status'>\n";
foreach ($options as $optname => $optval) {
$selected = $status == $optname ? 'selected' : '';
echo "<option value='" . $optname . "' {$selected}>" . $optval . "</option>\n";
}
echo "</select>";
}
function optimizationPercentIfPng2Jpg($meta)
{
$png2jpgPercent = isset($meta['ShortPixelPng2Jpg']['optimizationPercent']) ? $meta['ShortPixelPng2Jpg']['optimizationPercent'] : 0;
return number_format(100.0 - (100.0 - $png2jpgPercent) * (100.0 - $meta['ShortPixelImprovement']) / 100.0, 2);
}
function shortpixelInfoBox()
{
if (get_post_type() == 'attachment') {
add_meta_box('shortpixel_info_box', __('ShortPixel Info', 'shortpixel-image-optimiser'), array(&$this, 'shortpixelInfoBoxContent'), null, 'side');
}
}
function shortpixelInfoBoxContent($post)
{
$this->generateCustomColumn('wp-shortPixel', $post->ID, true);
}
public function onDeleteImage($post_id)
{
Log::addDebug('onDeleteImage - Image Removal Detected ' . $post_id);
$result = null;
try {
$imageObj = new ImageModel();
$imageObj->setbyPostID($post_id);
$result = $imageObj->delete();
} catch (Exception $e) {
Log::addError('OndeleteImage triggered an error. ' . $e->getMessage(), $e);
}
return $result;
}
public function deleteBackupsAndWebPs($paths)
{
if (apply_filters('shortpixel_skip_delete_backups_and_webps', false, $paths)) {
return;
}
$fs = \wpSPIO()->filesystem();
$backupFolder = trailingslashit($this->getBackupFolder($paths[0]));
Log::addDebug('Removing from Backup Folder - ' . $backupFolder);
foreach ($paths as $path) {
$pos = strrpos($path, ".");
$pathFile = $fs->getFile($path);
if ($pos !== false) {
$file = $fs->getFile(substr($path, 0, $pos) . ".webp");
$file->delete();
$file = $fs->getFile(substr($path, 0, $pos) . "@2x.webp");
$file->delete();
$file = $fs->getFile($path . '.webp');
$file->delete();
$file = $fs->getFile($path . '.@2xwebp');
$file->delete();
$file = $fs->getFile($path . '.avif');
if ($file->exists()) {
$file->delete();
}
}
$fileName = $pathFile->getFileName();
$extension = $pathFile->getExtension();
$backupFile = $fs->getFile($backupFolder . $fileName);
if ($backupFile->exists()) {
$backupFile->delete();
}
$backupFile = $fs->getFile($backupFolder . preg_replace("/\\." . $extension . "\$/i", '@2x.' . $extension, $fileName));
if ($backupFile->exists() && $backupFile->is_file()) {
$backupFile->delete();
}
}
}
public function columns($defaults)
{
$defaults['wp-shortPixel'] = __('ShortPixel Compression', 'shortpixel-image-optimiser');
if (current_user_can('manage_options')) {
$defaults['wp-shortPixel'] .= ' <a href="options-general.php?page=wp-shortpixel-settings&part=stats" title="' . __('ShortPixel Statistics', 'shortpixel-image-optimiser') . '"><span class="dashicons dashicons-dashboard"></span></a>';
}
return $defaults;
}
public function generatePluginLinks($links)
{
$in = '<a href="options-general.php?page=wp-shortpixel-settings">Settings</a>';
array_unshift($links, $in);
return $links;
}
public static function formatBytes($bytes, $precision = 2)
{
Log::addDebug('Deprecated function called: formatBytes');
return \ShortPixelTools::formatBytes($bytes, $precision);
}
public function isProcessable($ID, $excludeExtensions = array())
{
$excludePatterns = $this->_settings->excludePatterns;
return self::_isProcessable($ID, $excludeExtensions, $excludePatterns);
}
public function isProcessablePath($path, $excludeExtensions = array())
{
$excludePatterns = $this->_settings->excludePatterns;
return self::_isProcessablePath($path, $excludeExtensions, $excludePatterns);
}
public static function _isProcessable($ID, $excludeExtensions = array(), $excludePatterns = array(), $meta = false)
{
$file = \wpSPIO()->filesystem()->getAttachedFile($ID);
$path = $file->getFullPath();
if (isset($excludePatterns) && is_array($excludePatterns)) {
foreach ($excludePatterns as $excludePattern) {
$type = $excludePattern["type"];
if ($type == "size") {
$meta = $meta ? $meta : wp_get_attachment_metadata($ID);
if (isset($meta["width"]) && isset($meta["height"]) && self::isProcessableSize($meta["width"], $meta["height"], $excludePattern["value"]) === false) {
return false;
}
}
}
}
return $path ? self::_isProcessablePath($path, $excludeExtensions, $excludePatterns) : false;
}
public static function _isProcessablePath($path, $excludeExtensions = array(), $excludePatterns = array())
{
$pathParts = pathinfo($path);
$ext = isset($pathParts['extension']) ? $pathParts['extension'] : false;
if ($ext && in_array(strtolower($ext), array_diff(self::$PROCESSABLE_EXTENSIONS, $excludeExtensions))) {
if (!$excludePatterns || !is_array($excludePatterns)) {
return true;
}
foreach ($excludePatterns as $item) {
$type = trim($item["type"]);
if (in_array($type, array("name", "path"))) {
$pattern = trim($item["value"]);
$target = $type == "name" ? ShortPixelAPI::MB_basename($path) : $path;
if (self::matchExcludePattern($target, $pattern)) {
return false;
}
}
}
return true;
} else {
return false;
}
}
public static function isProcessableSize($width, $height, $excludePattern)
{
$ranges = preg_split("/(x|×)/", $excludePattern);
$widthBounds = explode("-", $ranges[0]);
if (!isset($widthBounds[1])) {
$widthBounds[1] = $widthBounds[0];
}
$heightBounds = isset($ranges[1]) ? explode("-", $ranges[1]) : false;
if (!isset($heightBounds[1])) {
$heightBounds[1] = $heightBounds[0];
}
if ($width >= 0 + $widthBounds[0] && $width <= 0 + $widthBounds[1] && ($heightBounds === false || $height >= 0 + $heightBounds[0] && $height <= 0 + $heightBounds[1])) {
return false;
}
return true;
}
public static function matchExcludePattern($target, $pattern)
{
if (strlen($pattern) == 0) {
return false;
}
$first = substr($pattern, 0, 1);
if ($first == '/') {
if (@preg_match($pattern, false) !== false) {
$m = preg_match($pattern, $target);
if ($m !== false && $m > 0) {
return true;
}
}
} else {
if (strpos($target, $pattern) !== false) {
return true;
}
}
return false;
}
public function getURLsAndPATHs($itemHandler, $meta = NULL, $onlyThumbs = false)
{
return $itemHandler->getURLsAndPATHs($this->_settings->processThumbnails, $onlyThumbs, $this->_settings->optimizeRetina, $this->_settings->excludeSizes);
}
public static function deleteDir($dirPath)
{
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
$dirPath .= '/';
}
$files = glob($dirPath . '*', GLOB_MARK);
foreach ($files as $file) {
if (is_dir($file)) {
self::deleteDir($file);
@rmdir($file);
} else {
@unlink($file);
}
}
}
public static function folderSize($path)
{
$total_size = 0;
$fs = wpSPIO()->filesystem();
$dir = $fs->getDirectory($path);
$files = $subdirs = array();
if ($dir->exists()) {
$files = $dir->getFiles();
$subdirs = $dir->getSubDirectories();
} else {
return $total_size;
}
if ($files) {
foreach ($files as $file) {
$total_size += $file->getFileSize();
}
}
if ($subdirs) {
foreach ($subdirs as $dir) {
$total_size += self::folderSize($dir->getPath());
}
}
return $total_size;
return $total_size;
}
public function migrateBackupFolder()
{
$oldBackupFolder = WP_CONTENT_DIR . '/' . SHORTPIXEL_BACKUP;
if (file_exists($oldBackupFolder)) {
if (!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
if (!ShortPixelFolder::createBackUpFolder()) {
return;
}
}
$scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
foreach ($scannedDirectory as $file) {
@rename($oldBackupFolder . '/' . $file, SHORTPIXEL_BACKUP_FOLDER . '/' . $file);
}
$scannedDirectory = array_diff(scandir($oldBackupFolder), array('..', '.'));
if (empty($scannedDirectory)) {
@rmdir($oldBackupFolder);
}
}
if (!is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . SHORTPIXEL_UPLOADS_NAME) && !is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
@rename(SHORTPIXEL_BACKUP_FOLDER, SHORTPIXEL_BACKUP_FOLDER . "_tmp");
ShortPixelFolder::createBackUpFolder();
@rename(SHORTPIXEL_BACKUP_FOLDER . "_tmp", SHORTPIXEL_BACKUP_FOLDER . '/' . SHORTPIXEL_UPLOADS_NAME);
if (!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
@rename(SHORTPIXEL_BACKUP_FOLDER . "_tmp", SHORTPIXEL_BACKUP_FOLDER);
}
}
if (!is_dir(SHORTPIXEL_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR))) {
@rename(SHORTPIXEL_BACKUP_FOLDER, SHORTPIXEL_BACKUP_FOLDER . "_tmp");
ShortPixelFolder::createBackUpFolder();
@rename(SHORTPIXEL_BACKUP_FOLDER . "_tmp", SHORTPIXEL_BACKUP_FOLDER . '/' . basename(WP_CONTENT_DIR));
if (!file_exists(SHORTPIXEL_BACKUP_FOLDER)) {
@rename(SHORTPIXEL_BACKUP_FOLDER . "_tmp", SHORTPIXEL_BACKUP_FOLDER);
}
}
if (!file_exists(trailingslashit(SHORTPIXEL_BACKUP_FOLDER) . '.htaccess')) {
ShortPixelFolder::protectDirectoryListing(SHORTPIXEL_BACKUP_FOLDER);
}
return;
}
function getAllThumbnailSizes()
{
global $_wp_additional_image_sizes;
$sizes_names = get_intermediate_image_sizes();
$sizes = array();
foreach ($sizes_names as $size) {
$sizes[$size]['width'] = intval(get_option("{$size}_size_w"));
$sizes[$size]['height'] = intval(get_option("{$size}_size_h"));
$sizes[$size]['crop'] = get_option("{$size}_crop") ? get_option("{$size}_crop") : false;
}
if (function_exists('wp_get_additional_image_sizes')) {
$sizes = array_merge($sizes, wp_get_additional_image_sizes());
} elseif (is_array($_wp_additional_image_sizes)) {
$sizes = array_merge($sizes, $_wp_additional_image_sizes);
}
$sizes = apply_filters('shortpixel/settings/image_sizes', $sizes);
return $sizes;
}
function getMaxIntermediateImageSize()
{
global $_wp_additional_image_sizes;
$width = 0;
$height = 0;
$get_intermediate_image_sizes = get_intermediate_image_sizes();
if (is_array($get_intermediate_image_sizes)) {
foreach ($get_intermediate_image_sizes as $_size) {
if (in_array($_size, array('thumbnail', 'medium', 'large'))) {
$width = max($width, get_option($_size . '_size_w'));
$height = max($height, get_option($_size . '_size_h'));
} elseif (isset($_wp_additional_image_sizes[$_size])) {
$width = max($width, $_wp_additional_image_sizes[$_size]['width']);
$height = max($height, $_wp_additional_image_sizes[$_size]['height']);
}
}
}
return array('width' => max(100, $width), 'height' => max(100, $height));
}
public function getOtherCompressionTypes($compressionType = false)
{
return array_values(array_diff(array(0, 1, 2), array(0 + $compressionType)));
}
public function validateFeedback($params)
{
if (isset($params['keep-settings'])) {
$this->_settings->removeSettingsOnDeletePlugin = 1 - $params['keep-settings'];
}
return $params;
}
public function getApiKey()
{
return $this->_settings->apiKey;
}
public function getPrioQ()
{
return $this->prioQ;
}
public function backupImages()
{
return $this->_settings->backupImages;
}
public function processThumbnails()
{
return $this->_settings->processThumbnails;
}
public function getCMYKtoRGBconversion()
{
return $this->_settings->CMYKtoRGBconversion;
}
public function getSettings()
{
return $this->_settings;
}
public function getResizeImages()
{
return $this->_settings->resizeImages;
}
public function getResizeWidth()
{
return $this->_settings->resizeWidth;
}
public function getResizeHeight()
{
return $this->_settings->resizeHeight;
}
public static function getAffiliateSufix()
{
Log::addDebug('Function call - getAffiliateSufix should be removed');
return "";
}
public function getVerifiedKey()
{
return $this->_settings->verifiedKey;
}
public function getCompressionType()
{
return $this->_settings->compressionType;
}
public function getSpMetaDao()
{
return $this->spMetaDao;
}
public function fetch_cloudflare_api_email()
{
return $this->_settings->cloudflareEmail;
}
public function fetch_cloudflare_api_key()
{
return $this->_settings->cloudflareAuthKey;
}
public function fetch_cloudflare_api_zoneid()
{
return $this->_settings->cloudflareZoneID;
}
}