597 lines
16 KiB
PHP
597 lines
16 KiB
PHP
<?php
|
|
namespace ShortPixel\Controller;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
|
use ShortPixel\Notices\NoticeController as Notices;
|
|
|
|
use ShortPixel\Model\File\DirectoryOtherMediaModel as DirectoryOtherMediaModel;
|
|
use ShortPixel\Model\File\DirectoryModel as DirectoryModel;
|
|
|
|
use ShortPixel\Controller\OptimizeController as OptimizeController;
|
|
|
|
use ShortPixel\Helper\InstallHelper as InstallHelper;
|
|
use ShortPixel\Helper\UtilHelper as UtilHelper;
|
|
|
|
|
|
// Future contoller for the edit media metabox view.
|
|
class OtherMediaController extends \ShortPixel\Controller
|
|
{
|
|
private $folderIDCache;
|
|
private static $hasFoldersTable;
|
|
private static $hasCustomImages;
|
|
|
|
|
|
protected static $instance;
|
|
|
|
public function __construct()
|
|
{
|
|
parent::__construct();
|
|
}
|
|
|
|
public static function getInstance()
|
|
{
|
|
if (is_null(self::$instance))
|
|
self::$instance = new OtherMediaController();
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public function getFolderTable()
|
|
{
|
|
global $wpdb;
|
|
return $wpdb->prefix . 'shortpixel_folders';
|
|
}
|
|
|
|
public function getMetaTable()
|
|
{
|
|
global $wpdb;
|
|
return $wpdb->prefix . 'shortpixel_meta';
|
|
}
|
|
|
|
// Get CustomFolder for usage.
|
|
public function getAllFolders()
|
|
{
|
|
$folders = $this->getFolders();
|
|
return $this->loadFoldersFromResult($folders);
|
|
//return $folders;
|
|
}
|
|
|
|
public function getActiveFolders()
|
|
{
|
|
$folders = $this->getFolders(array('remove_hidden' => true));
|
|
return $this->loadFoldersFromResult($folders);
|
|
}
|
|
|
|
private function loadFoldersFromResult($folders)
|
|
{
|
|
$dirFolders = array();
|
|
foreach($folders as $result)
|
|
{
|
|
$dirObj = new DirectoryOtherMediaModel($result);
|
|
$dirFolders[] = $dirObj;
|
|
}
|
|
return $dirFolders;
|
|
}
|
|
|
|
public function getActiveDirectoryIDS()
|
|
{
|
|
if (! is_null($this->folderIDCache))
|
|
return $this->folderIDCache;
|
|
|
|
global $wpdb;
|
|
|
|
$sql = 'SELECT id from ' . $wpdb->prefix .'shortpixel_folders where status <> -1';
|
|
$results = $wpdb->get_col($sql);
|
|
|
|
$this->folderIDCache = $results;
|
|
return $this->folderIDCache;
|
|
}
|
|
|
|
public function getHiddenDirectoryIDS()
|
|
{
|
|
global $wpdb;
|
|
|
|
$sql = 'SELECT id from ' . $wpdb->prefix .'shortpixel_folders where status = -1';
|
|
$results = $wpdb->get_col($sql);
|
|
|
|
return $results;
|
|
}
|
|
|
|
public function getFolderByID($id)
|
|
{
|
|
$folders = $this->getFolders(array('id' => $id));
|
|
|
|
if (count($folders) > 0)
|
|
{
|
|
$folders = $this->loadFoldersFromResult($folders);
|
|
return array_pop($folders);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function getFolderByPath($path)
|
|
{
|
|
$folder = new DirectoryOtherMediaModel($path);
|
|
return $folder;
|
|
}
|
|
|
|
public function getCustomImageByPath($path)
|
|
{
|
|
global $wpdb;
|
|
$sql = 'SELECT id FROM ' . $this->getMetaTable() . ' WHERE path = %s';
|
|
$sql = $wpdb->prepare($sql, $path);
|
|
|
|
$custom_id = $wpdb->get_var($sql);
|
|
$fs = \wpSPIO()->filesystem();
|
|
|
|
if (! is_null($custom_id))
|
|
{
|
|
return $fs->getImage($custom_id, 'custom');
|
|
}
|
|
else
|
|
return $fs->getCustomStub($path); // stub
|
|
}
|
|
|
|
/* Check if installation has custom image, or anything. To show interface */
|
|
public function hasCustomImages()
|
|
{
|
|
if (! is_null(self::$hasCustomImages)) // prevent repeat
|
|
return self::$hasCustomImages;
|
|
|
|
if (InstallHelper::checkTableExists('shortpixel_meta') === false)
|
|
$count = 0;
|
|
else
|
|
{
|
|
global $wpdb;
|
|
|
|
$sql = 'SELECT count(id) as count from ' . $wpdb->prefix . 'shortpixel_meta';
|
|
$count = $wpdb->get_var($sql); //$this->getFolders(['only_count' => true, 'remove_hidden' => true]);
|
|
}
|
|
if ($count == 0)
|
|
$result = false;
|
|
else
|
|
$result = true;
|
|
|
|
self::$hasCustomImages = $result;
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function showMenuItem()
|
|
{
|
|
$settings = \wpSPIO()->settings();
|
|
if ( $settings->showCustomMedia)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function addDirectory($path)
|
|
{
|
|
$fs = \wpSPIO()->filesystem();
|
|
$directory = new DirectoryOtherMediaModel($path);
|
|
|
|
// Check if this directory is allowed.
|
|
if ($this->checkDirectoryRecursive($directory) === false)
|
|
{
|
|
Log::addDebug('Check Recursive Directory not allowed');
|
|
return false;
|
|
}
|
|
|
|
if (! $directory->get('in_db'))
|
|
{
|
|
if ($directory->save())
|
|
{
|
|
$this->folderIDCache = null;
|
|
$directory->refreshFolder(true);
|
|
$directory->updateFileContentChange();
|
|
}
|
|
}
|
|
else // if directory is already added, fail silently, but still refresh it.
|
|
{
|
|
if ($directory->isRemoved())
|
|
{
|
|
$this->folderIDCache = null;
|
|
$directory->set('status', DirectoryOtherMediaModel::DIRECTORY_STATUS_NORMAL);
|
|
$directory->refreshFolder(true);
|
|
$directory->updateFileContentChange(); // does a save. Dunno if that's wise.
|
|
}
|
|
else
|
|
$directory->refreshFolder(false);
|
|
}
|
|
|
|
if ($directory->exists() && $directory->get('id') > 0)
|
|
return $directory;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Recursive check if any of the directories is not addable. If so cancel the whole thing.
|
|
public function checkDirectoryRecursive($directory)
|
|
{
|
|
if ($directory->checkDirectory() === false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$subDirs = $directory->getSubDirectories();
|
|
foreach($subDirs as $subDir)
|
|
{
|
|
if ($subDir->checkDirectory(true) === false)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
$result = $this->checkDirectoryRecursive($subDir);
|
|
if ($result === false)
|
|
{
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Main function to add a path to the Custom Media.
|
|
public function addImage($path_or_file, $args = array())
|
|
{
|
|
$defaults = array(
|
|
'is_nextgen' => false,
|
|
);
|
|
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
$fs = \wpSPIO()->filesystem();
|
|
|
|
if (is_object($path_or_file)) // assume fileObject
|
|
{
|
|
$file = $path_or_file;
|
|
}
|
|
else
|
|
{
|
|
$file = $fs->getFile($path_or_file);
|
|
}
|
|
$folder = $this->getFolderByPath( (string) $file->getFileDir());
|
|
|
|
if ($folder->get('in_db') === false)
|
|
{
|
|
if ($args['is_nextgen'] == true)
|
|
{
|
|
$folder->set('status', DirectoryOtherMediaModel::DIRECTORY_STATUS_NEXTGEN );
|
|
}
|
|
$folder->save();
|
|
}
|
|
|
|
$folder->addImages(array($file));
|
|
|
|
}
|
|
|
|
/* New structure for folder refresing based on checked value in database + interval. Via Scan interface
|
|
*
|
|
* @param $args Array ( force true / false )
|
|
* @return Array - Should return folder_id, folder_path, amount of new files / result / warning
|
|
*/
|
|
public function doNextRefreshableFolder($args = array())
|
|
{
|
|
$defaults = array(
|
|
'force' => false,
|
|
'interval' => apply_filters('shortpixel/othermedia/refreshfolder_interval', HOUR_IN_SECONDS),
|
|
);
|
|
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
global $wpdb;
|
|
|
|
$folderTable = $this->getFolderTable();
|
|
|
|
$tsInterval = UtilHelper::timestampToDB(time() - $args['interval']);
|
|
$sql = ' SELECT id FROM ' . $folderTable . ' WHERE status >= 0 AND (ts_checked <= %s OR ts_checked IS NULL)';
|
|
|
|
$sql = $wpdb->prepare($sql, $tsInterval);
|
|
|
|
$folder_id = $wpdb->get_var($sql);
|
|
|
|
if (is_null($folder_id))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$directoryObj = $this->getFolderByID($folder_id);
|
|
|
|
$old_count = $directoryObj->get('fileCount');
|
|
|
|
$return = array(
|
|
'folder_id' => $folder_id,
|
|
'old_count' => $old_count,
|
|
'new_count' => null,
|
|
'path' => $directoryObj->getPath(),
|
|
'message' => '',
|
|
);
|
|
|
|
// Always force here since last updated / interval is decided by interal on the above query
|
|
$result = $directoryObj->refreshFolder($args['force']);
|
|
|
|
if (false === $result)
|
|
{
|
|
$directoryObj->set('checked', time()); // preventing loops here in case some wrong
|
|
$directoryObj->save();
|
|
|
|
// Probably should catch some notice here to return @todo
|
|
}
|
|
|
|
$new_count = $directoryObj->get('fileCount');
|
|
$return['new_count'] = $new_count;
|
|
|
|
if ($old_count == $new_count)
|
|
{
|
|
$message = __('No new files added', 'shortpixel-image-optimiser');
|
|
}
|
|
elseif ($old_count < $new_count)
|
|
{
|
|
$message = print_f(__(' %s files added', 'shortpixel-image-optimiser'), ($new_count-$old_count));
|
|
}
|
|
else {
|
|
$message = print_f(__(' %s files removed', 'shortpixel-image-optimiser'), ($old_count-$new_count));
|
|
}
|
|
|
|
$return['message'] = $message;
|
|
|
|
return $return;
|
|
}
|
|
|
|
public function resetCheckedTimestamps()
|
|
{
|
|
global $wpdb;
|
|
$folderTable = $this->getFolderTable();
|
|
|
|
$sql = 'UPDATE ' . $folderTable . ' set ts_checked = NULL ';
|
|
$wpdb->query($sql);
|
|
|
|
}
|
|
|
|
/**
|
|
* Function to clean the folders and meta from unused stuff
|
|
*/
|
|
protected function cleanUp()
|
|
{
|
|
global $wpdb;
|
|
$folderTable = $this->getFolderTable();
|
|
$metaTable = $this->getMetaTable();
|
|
|
|
// Remove folders that are removed, and have no images in MetaTable.
|
|
$sql = " DELETE FROM $folderTable WHERE status < 0 AND id NOT IN ( SELECT DISTINCT folder_id FROM $metaTable)";
|
|
$result = $wpdb->query($sql);
|
|
|
|
}
|
|
|
|
/* Check if this directory is part of the MediaLibrary */
|
|
public function checkifMediaLibrary(DirectoryModel $directory)
|
|
{
|
|
$fs = \wpSPIO()->filesystem();
|
|
$uploadDir = $fs->getWPUploadBase();
|
|
$wpUploadDir = wp_upload_dir(null, false);
|
|
|
|
$is_year_based = (isset($wpUploadDir['subdir']) && strlen(trim($wpUploadDir['subdir'])) > 0) ? true : false;
|
|
|
|
// if it's the uploads base dir, check if the library is year-based, then allow. If all files are in uploads root, don't allow.
|
|
if ($directory->getPath() == $uploadDir->getPath() )
|
|
{
|
|
if ($is_year_based)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
elseif (! $directory->isSubFolderOf($uploadDir))// The easy check. No subdir of uploads, no problem.
|
|
{
|
|
return false;
|
|
}
|
|
elseif ($directory->isSubFolderOf($uploadDir)) // upload subdirs come in variation of year or month, both numeric. Exclude the WP-based years
|
|
{
|
|
// Only check if direct subdir of /uploads/ is a number-based directory name. Don't bother with deeply nested dirs with accidental year.
|
|
if ($directory->getParent()->getPath() !== $uploadDir->getPath())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$name = $directory->getName();
|
|
if (is_numeric($name) && strlen($name) == 4) // exclude year based stuff.
|
|
{
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public function browseFolder($postDir)
|
|
{
|
|
$error = array('is_error' => true, 'message' => '');
|
|
|
|
if ( ! $this->userIsAllowed ) {
|
|
$error['message'] = __('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser');
|
|
return $error;
|
|
}
|
|
|
|
$fs = \wpSPIO()->filesystem();
|
|
$rootDirObj = $fs->getWPFileBase();
|
|
$path = $rootDirObj->getPath();
|
|
|
|
$folders = array();
|
|
|
|
if (! is_null($postDir) && strlen($postDir) > 0)
|
|
{
|
|
$postDir = rawurldecode($postDir);
|
|
$children = explode('/', $postDir );
|
|
|
|
foreach($children as $child)
|
|
{
|
|
if ($child == '.' || $child == '..')
|
|
continue;
|
|
|
|
$path .= '/' . $child;
|
|
}
|
|
}
|
|
|
|
$dirObj = $fs->getDirectory($path);
|
|
if ($dirObj->getPath() !== $rootDirObj->getPath() && ! $dirObj->isSubFolderOf($rootDirObj))
|
|
{
|
|
$error['message'] = __('This directory seems not part of WordPress', 'shortpixel-image-optimiser');
|
|
return $error;
|
|
}
|
|
|
|
if( $dirObj->exists() ) {
|
|
|
|
//$dir = $fs->getDirectory($postDir);
|
|
// $files = $dirObj->getFiles();
|
|
$subdirs = $fs->sortFiles($dirObj->getSubDirectories()); // runs through FS sort.
|
|
|
|
|
|
foreach($subdirs as $index => $dir) // weed out the media library subdirectories.
|
|
{
|
|
$dirname = $dir->getName();
|
|
// @todo This should probably be checked via getBackupDirectory or so, not hardcoded ShortipxelBackups
|
|
if($dirname == 'ShortpixelBackups' || $this->checkifMediaLibrary($dir) )
|
|
{
|
|
unset($subdirs[$index]);
|
|
}
|
|
}
|
|
|
|
if( count($subdirs) > 0 ) {
|
|
|
|
// echo "<ul class='jqueryFileTree'>";
|
|
foreach($subdirs as $dir ) {
|
|
|
|
$returnDir = substr($dir->getPath(), strlen($rootDirObj->getPath())); // relative to root.
|
|
|
|
$dirpath = $dir->getPath();
|
|
$dirname = $dir->getName();
|
|
|
|
$folderObj = $this->getFolderByPath($dirpath);
|
|
|
|
$htmlRel = str_replace("'", "'", $returnDir );
|
|
$htmlName = htmlentities($dirname);
|
|
//$ext = preg_replace('/^.*\./', '', $file);
|
|
|
|
if( $dir->exists() ) {
|
|
//KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
|
|
// echo "<li class='directory collapsed'><a rel=' " .esc_attr($htmlRel) . "'>" . esc_html($htmlName) . "</a></li>";
|
|
$htmlRel = esc_attr($htmlRel);
|
|
$folders[] = array(
|
|
'relpath' => $htmlRel,
|
|
'name' => esc_html($htmlName),
|
|
'type' => 'folder',
|
|
'is_active' => (true === $folderObj->get('in_db') && false === $folderObj->isRemoved()),
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
// echo "</ul>";
|
|
}
|
|
elseif ($_POST['dir'] == '/')
|
|
{
|
|
$error['message'] = __('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
|
|
return $error;
|
|
/* echo "<ul class='jqueryFileTree'>";
|
|
esc_html_e('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
|
|
echo "</ul>"; */
|
|
}
|
|
else {
|
|
$error['message'] = 'Nothing found';
|
|
return $error;
|
|
}
|
|
}
|
|
else {
|
|
$error['message'] = 'Dir not existing';
|
|
return $error;
|
|
}
|
|
|
|
return $folders;
|
|
}
|
|
|
|
/* Get the custom Folders from DB, put them in model
|
|
@return Array Array database result
|
|
@todo Has been replaced by getItems in FoldersViewController
|
|
*/
|
|
private function getFolders($args = array())
|
|
{
|
|
global $wpdb;
|
|
$defaults = array(
|
|
'id' => false, // Get folder by Id
|
|
'remove_hidden' => true, // Query only active folders
|
|
'path' => false,
|
|
'only_count' => false,
|
|
'limit' => false,
|
|
'offset' => false,
|
|
);
|
|
|
|
$args = wp_parse_args($args, $defaults);
|
|
|
|
if (! $this->hasFoldersTable())
|
|
{
|
|
if ($args['only_count'])
|
|
return 0;
|
|
else
|
|
return array();
|
|
}
|
|
$fs = \wpSPIO()->fileSystem();
|
|
|
|
if ($args['only_count'])
|
|
$selector = 'count(id) as id';
|
|
else
|
|
$selector = '*';
|
|
|
|
$sql = "SELECT " . $selector . " FROM " . $wpdb->prefix . "shortpixel_folders WHERE 1=1 ";
|
|
$prepare = array();
|
|
// $mask = array();
|
|
|
|
if ($args['id'] !== false && $args['id'] > 0)
|
|
{
|
|
$sql .= ' AND id = %d';
|
|
$prepare[] = $args['id'];
|
|
|
|
}
|
|
elseif($args['path'] !== false && strlen($args['path']) > 0)
|
|
{
|
|
$sql .= ' AND path = %s';
|
|
$prepare[] = $args['path'];
|
|
}
|
|
|
|
if ($args['remove_hidden'])
|
|
{
|
|
$sql .= " AND status <> -1";
|
|
}
|
|
|
|
if (count($prepare) > 0)
|
|
$sql = $wpdb->prepare($sql, $prepare);
|
|
|
|
if ($args['only_count'])
|
|
$results = intval($wpdb->get_var($sql));
|
|
else
|
|
$results = $wpdb->get_results($sql);
|
|
|
|
|
|
return $results;
|
|
}
|
|
|
|
|
|
private function hasFoldersTable()
|
|
{
|
|
return InstallHelper::checkTableExists('shortpixel_folders');
|
|
}
|
|
|
|
|
|
|
|
} // Class
|