From c5c4e47a314804267a2d58d7b62e4a7011a69d07 Mon Sep 17 00:00:00 2001 From: matdave Date: Thu, 29 Jun 2023 18:20:14 -0500 Subject: [PATCH] refactoring driver and updating with newest release --- _build/gpm.json | 2 +- assets/components/fred/web/elfinder/main.js | 2 +- .../src/Endpoint/ElFinder/Driver/Driver.php | 795 ++++++++++-------- 3 files changed, 435 insertions(+), 364 deletions(-) diff --git a/_build/gpm.json b/_build/gpm.json index 8d03d5df..c2aa5952 100644 --- a/_build/gpm.json +++ b/_build/gpm.json @@ -3,7 +3,7 @@ "lowCaseName": "fred", "description": "Frontend Editor", "author": "John Peca", - "version": "2.1.1-pl", + "version": "2.1.2-pl", "menus": [ { "text": "fred.menu.fred", diff --git a/assets/components/fred/web/elfinder/main.js b/assets/components/fred/web/elfinder/main.js index b8c7ee40..9ab72352 100644 --- a/assets/components/fred/web/elfinder/main.js +++ b/assets/components/fred/web/elfinder/main.js @@ -72,7 +72,7 @@ })(), opts = { - cssAutoLoad : ['../elfinder-themes/material/css/theme-gray.css'], + cssAutoLoad : ['../vendor/elfinder-themes/material/css/theme-gray.css'], getFileCallback : function(file, fm) { if (type === 'folder') { if (file.mime === 'directory') { diff --git a/core/components/fred/src/Endpoint/ElFinder/Driver/Driver.php b/core/components/fred/src/Endpoint/ElFinder/Driver/Driver.php index 6c0cba6a..d98175c7 100644 --- a/core/components/fred/src/Endpoint/ElFinder/Driver/Driver.php +++ b/core/components/fred/src/Endpoint/ElFinder/Driver/Driver.php @@ -2,18 +2,33 @@ namespace Fred\Endpoint\ElFinder\Driver; +use elFinderVolumeDriver; +use Fred\Endpoint\ElFinder\Driver\Utils; use Intervention\Image\ImageManager; +use League\Flysystem\Cached\CachedAdapter; +use League\Flysystem\Cached\CacheInterface; +use League\Flysystem\DirectoryAttributes; +use League\Flysystem\FileAttributes; use League\Flysystem\Filesystem; -use League\Flysystem\FilesystemException; - +use League\Flysystem\FilesystemOperator; +use League\Flysystem\StorageAttributes; +use League\Flysystem\UnableToCopyFile; +use League\Flysystem\UnableToCreateDirectory; +use League\Flysystem\UnableToDeleteDirectory; +use League\Flysystem\UnableToDeleteFile; +use League\Flysystem\UnableToMoveFile; +use League\Flysystem\UnableToWriteFile; +use League\Flysystem\Util; +use League\Flysystem\FilesystemInterface; +use League\Flysystem\WhitespacePathNormalizer; +use League\Glide\Urls\UrlBuilderFactory; /** * elFinder driver for Flysytem (https://github.com/thephpleague/flysystem) * * @author Barry vd. Heuvel * */ -class Driver extends \elFinderVolumeDriver +class Driver extends elFinderVolumeDriver { - /** * Driver id * Must be started from letter and contains [a-z0-9] @@ -23,13 +38,18 @@ class Driver extends \elFinderVolumeDriver **/ protected $driverId = 'fls'; - /** @var Filesystem $fs */ + /** @var FilesystemOperator $fs */ protected $fs; + /** @var UrlBuilder $urlBuilder */ + protected $urlBuilder = null; /** @var ImageManager $imageManager */ protected $imageManager = null; + /** @var StorageAttributes $attributes */ + protected $attributeCache = []; + /** * Constructor * Extend options with required fields @@ -37,15 +57,27 @@ class Driver extends \elFinderVolumeDriver **/ public function __construct() { - $opts = [ - 'filesystem' => null, - 'imageManager' => null, + $opts = array( + 'filesystem' => null, + 'URLCallback' => null, + 'glideURL' => null, + 'glideKey' => null, + 'imageManager' => null, + 'cache' => 'session', // 'session', 'memory' or false 'checkSubfolders' => false, // Disable for performance - ]; + ); $this->options = array_merge($this->options, $opts); } + protected function clearcache() + { + parent::clearcache(); + + // clear cached attributes + $this->attributeCache = []; + } + public function mount(array $opts) { // If path is not set, use the root @@ -56,141 +88,17 @@ public function mount(array $opts) return parent::mount($opts); } - public function upload($fp, $dst, $name, $tmpname, $hashes = []) - { - return parent::upload($fp, $dst, $name, $tmpname, $hashes); - } - - /** - * Resize image - * - * @param string $hash image file - * @param int $width new width - * @param int $height new height - * @param int $x X start poistion for crop - * @param int $y Y start poistion for crop - * @param string $mode action how to mainpulate image - * @param string $bg background color - * @param int $degree rotete degree - * @param int $jpgQuality JEPG quality (1-100) - * - * @return array|false - * @author Dmitry (dio) Levashov - * @author Alexey Sukhotin - * @author nao-pon - * @author Troex Nevelin - **/ - public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0, $jpgQuality = null) - { - if ($this->commandDisabled('resize')) { - return $this->setError(\elFinder::ERROR_PERM_DENIED); - } - - if (($file = $this->file($hash)) == false) { - return $this->setError(\elFinder::ERROR_FILE_NOT_FOUND); - } - - if (!$file['write'] || !$file['read']) { - return $this->setError(\elFinder::ERROR_PERM_DENIED); - } - - $path = $this->decode($hash); - if (!$this->canResize($path, $file)) { - return $this->setError(\elFinder::ERROR_UNSUPPORT_TYPE); - } - - if (!$image = $this->imageManager->make($this->_getContents($path))) { - return false; - } - - switch ($mode) { - case 'propresize': - $image->resize($width, $height, function ($constraint) { - $constraint->aspectRatio(); - }); - break; - - case 'crop': - $image->crop($width, $height, $x, $y); - break; - - case 'fitsquare': - $image->fit($width, $height, null, 'center'); - break; - - case 'rotate': - $image->rotate($degree); - break; - - default: - $image->resize($width, $height); - break; - } - - if ($jpgQuality && $image->mime() === 'image/jpeg') { - $result = (string)$image->encode('jpg', $jpgQuality); - } else { - $result = (string)$image->encode(); - } - if ($result && $this->_filePutContents($path, $result)) { - $this->rmTmb($file); - $this->clearstatcache(); - $stat = $this->stat($path); - $stat['width'] = $image->width(); - $stat['height'] = $image->height(); - return $stat; - } - - return false; - } - - /** - * Write a string to a file - * - * @param string $path file path - * @param string $content new file content - * - * @return bool - **/ - protected function _filePutContents($path, $content) - { - $this->fs->write($path, $content); - return true; - } - /** - * Return content URL - * - * @param string $hash file hash - * @param array $options options + * Return the icon * * @return string - **/ - public function getContentUrl($hash, $options = []) + */ + protected function getIcon() { - if (!empty($options['onetime']) && $this->options['onetimeUrl']) { - // use parent method to make onetime URL - return parent::getContentUrl($hash, $options); - } - if (!empty($options['temporary'])) { - // try make temporary file - $url = parent::getContentUrl($hash, $options); - if ($url) { - return $url; - } - } - if (($file = $this->file($hash)) == false || !isset($file['url']) || !$file['url'] || $file['url'] == 1) { - if ($file && !empty($file['url']) && !empty($options['temporary'])) { - return parent::getContentUrl($hash, $options); - } - return parent::getContentUrl($hash, $options); - } - return $file['url']; - } + $icon = 'volume_icon_ftp.png'; - protected function clearcache() - { - parent::clearcache(); + $parentUrl = defined('ELFINDER_IMG_PARENT_URL') ? (rtrim(ELFINDER_IMG_PARENT_URL, '/') . '/') : ''; + return $parentUrl . 'img/' . $icon; } /** @@ -202,14 +110,17 @@ protected function clearcache() protected function init() { $this->fs = $this->options['filesystem']; - if (!($this->fs instanceof Filesystem)) { - return $this->setError('A filesystem instance is required'); + if (!($this->fs instanceof FilesystemOperator)) { + return $this->setError('A FilesystemOperator instance is required'); } - $this->options['icon'] = $this->options['icon'] - ?: (empty($this->options['rootCssClass']) ? $this->getIcon() : ''); + $this->options['icon'] = $this->options['icon'] ?: (empty($this->options['rootCssClass'])? $this->getIcon() : ''); $this->root = $this->options['path']; + if ($this->options['glideURL']) { + $this->urlBuilder = UrlBuilderFactory::create($this->options['glideURL'], $this->options['glideKey']); + } + if ($this->options['imageManager']) { $this->imageManager = $this->options['imageManager']; } else { @@ -218,55 +129,28 @@ protected function init() // enable command archive $this->options['useRemoteArchive'] = true; + $this->options['tmbURL'] = 'self'; return true; } - /** - * Find the icon based on the used Adapter - * - * @return string - */ - protected function getIcon() - { - // Can't get adapter on v2 - // try { - // $adapter = $this->fs->getAdapter(); - // } catch (\Exception $e) { - // $adapter = null; - // } - - // if ($adapter instanceof CachedAdapter) { - // $adapter = $adapter->getAdapter(); - // } - - $icon = 'volume_icon_local.png'; - - // if ($adapter instanceof League\Flysystem\Adapter\AbstractFtpAdapter) { - // $icon = 'volume_icon_ftp.png'; - // } elseif ($adapter instanceof League\Flysystem\Dropbox\DropboxAdapter) { - // $icon = 'volume_icon_dropbox.png'; - // } - - $parentUrl = defined('ELFINDER_IMG_PARENT_URL') ? (rtrim(ELFINDER_IMG_PARENT_URL, '/') . '/') : ''; - return $parentUrl . 'img/' . $icon; - } /** - * Configure after successful mount. + * Return parent directory path * - * @return void + * @param string $path file path + * @return string **/ - protected function configure() + protected function _dirname($path) { - parent::configure(); + $dirname = dirname($path); + return $dirname === '.' ? '/' : $dirname; } /** * Return normalized path * - * @param string $path path - * + * @param string $path path * @return string **/ protected function _normpath($path) @@ -274,14 +158,10 @@ protected function _normpath($path) return $path; } - /***************** file stat ********************/ - /** - * Check if the directory exists in the parent directory. Needed because not all drives handle directories - * correctly. - * - * @param string $path path + * Check if the directory exists in the parent directory. Needed because not all drives handle directories correctly. * + * @param string $path path * @return boolean **/ protected function _dirExists($path) @@ -289,8 +169,9 @@ protected function _dirExists($path) $dir = $this->_dirname($path); $basename = basename($path); - foreach ($this->fs->listContents($dir) as $meta) { - if ($meta && $meta['type'] !== 'file' && $meta['basename'] == $basename) { + /** @var StorageAttributes $meta */ + foreach ($this->listContents($dir) as $attribute) { + if ($attribute->isDir() && $this->_basename($attribute->path()) == $basename) { return true; } } @@ -298,20 +179,6 @@ protected function _dirExists($path) return false; } - /** - * Return parent directory path - * - * @param string $path file path - * - * @return string - **/ - protected function _dirname($path) - { - return Utils::dirname($path) ?: '/'; - } - - /******************** file/dir content *********************/ - /** * Return stat for given path. * Stat contains following fields: @@ -327,21 +194,20 @@ protected function _dirname($path) * * If file does not exists - returns empty array or false. * - * @param string $path file path - * + * @param string $path file path * @return array|false **/ protected function _stat($path) { - $stat = [ - 'size' => 0, - 'ts' => time(), - 'read' => true, - 'write' => true, + $stat = array( + 'size' => 0, + 'ts' => time(), + 'read' => true, + 'write' => true, 'locked' => false, 'hidden' => false, - 'mime' => 'directory', - ]; + 'mime' => 'directory', + ); // If root, just return from above if ($this->root == $path) { @@ -349,143 +215,178 @@ protected function _stat($path) return $stat; } - try { - $file = $this->fs->fileExists($path); - $mimeType = $this->fs->mimeType($path); + if (isset($this->attributeCache[$path])) { + /** @var StorageAttributes $attributes */ + $attributes = $this->attributeCache[$path]; + + $meta = [ + 'mimetype' => $attributes->type(), + 'extension' => null, + 'size' => null, + 'timestamp' => $attributes->lastModified(), + 'type' => $attributes->isFile() ? 'file' : 'dir', + ]; - if (!$file && $mimeType !== 'directory') { - return []; + if ($attributes instanceof FileAttributes) { + $meta['mimetype'] = $attributes->mimeType(); + $meta['size'] = $attributes->fileSize(); } - } catch (FilesystemException $e) { - return []; - } + } else { + // If not exists, return empty + if (!$this->has($path)) { - $name = explode(DIRECTORY_SEPARATOR, $path); - $stat['name'] = array_pop($name); + // Check if the parent doesn't have this path + if ($this->_dirExists($path)) { + return $stat; + } - try { - // Get timestamp/size if available - $stat['ts'] = $this->fs->lastModified($path); - } catch (FilesystemException $e) { + // Neither a file or directory exist, return empty + return array(); + } + + try { + $meta = [ + 'mimetype' => null, + 'extension' => null, + 'size' => null, + 'type' => $this->fs->fileExists($path) ? 'file' : 'dir', + ]; + + if ($meta['type'] === 'file') { + $meta['mimetype'] = $this->fs->mimeType($path); + $meta['timestamp'] = $this->fs->lastModified($path); + $meta['size'] = $this->fs->fileSize($path); + } + } catch (\Exception $e) { + return array(); + } } - try { - $stat['size'] = $this->fs->fileSize($path); - } catch (FilesystemException $e) { + if(false === $meta) { + return $stat; } - try { - $stat['mime'] = $this->fs->mimeType($path); - } catch (FilesystemException $e) { + // Set item filename.extension to `name` if exists + if (isset($meta['filename']) && isset($meta['extension'])) { + $stat['name'] = $meta['filename']; + if ($meta['extension'] !== '') { + $stat['name'] .= '.' . $meta['extension']; + } + } + + // Get timestamp/size if available + if (isset($meta['timestamp'])) { + $stat['ts'] = $meta['timestamp']; + } + if (isset($meta['size'])) { + $stat['size'] = $meta['size']; } // Check if file, if so, check mimetype when available - if ($stat['mime'] !== 'directory') { - $imgMimes = ['image/jpeg', 'image/png', 'image/gif']; + if ($meta['type'] == 'file') { + if(isset($meta['mimetype'])) { + $stat['mime'] = $meta['mimetype']; + } else { + $stat['mime'] = null; + } - if (in_array($stat['mime'], $imgMimes)) { - $stat['tmb'] = $this->URL . $path; + $imgMimes = ['image/jpeg', 'image/png', 'image/gif']; + if ($this->urlBuilder && in_array($stat['mime'], $imgMimes)) { + $stat['url'] = $this->urlBuilder->getUrl($path, [ + 'ts' => $stat['ts'] + ]); + $stat['tmb'] = $this->urlBuilder->getUrl($path, [ + 'ts' => $stat['ts'], + 'w' => $this->tmbSize, + 'h' => $this->tmbSize, + 'fit' => $this->options['tmbCrop'] ? 'crop' : 'contain', + ]); } } + if ($this->options['URLCallback'] && is_callable($this->options['URLCallback'])) { + $stat['url'] = $this->options['URLCallback']($path); + } + return $stat; } + /** + * @param $path + * @return array|StorageAttributes[] + * @throws \League\Flysystem\FilesystemException + */ + protected function listContents($path): array + { + $contents = $this->fs->listContents($path)->toArray(); + + /** @var StorageAttributes $item */ + foreach ($contents as $item) { + $this->attributeCache[$item['path']] = $item; + } + + return $contents; + } + + /***************** file stat ********************/ + /** * Return true if path is dir and has at least one childs directory * - * @param string $path dir path - * + * @param string $path dir path * @return bool **/ protected function _subdirs($path) { - $contents = $this->fs->listContents($path); - foreach ($contents as $content) { - if ($content['type'] === 'dir') { - return true; - } - } + $contents = array_filter($this->listContents($path), function (StorageAttributes $item) { + return $item->isDir(); + }); - return false; + return !empty($contents); } /** * Return object width and height * Usually used for images, but can be realize for video etc... * - * @param string $path file path - * @param string $mime file mime type - * + * @param string $path file path + * @param string $mime file mime type * @return string **/ protected function _dimensions($path, $mime) { - try { - $imgsize = $this->getImageSize($path, $mime); - } catch (\Exception $e) { - return false; - } - - if (!$imgsize) { - return false; - } - - return $imgsize['dimensions']; - } - - /******************** file/dir manipulations *************************/ - - public function getImageSize($path, $mime = '') - { - $size = false; - if ($mime === '' || strtolower(substr($mime, 0, 5)) === 'image') { - if ($data = $this->_getContents($path)) { - if ($size = @getimagesizefromstring($data)) { - $size['dimensions'] = $size[0] . 'x' . $size[1]; - } - } + $ret = false; + if ($imgsize = $this->getImageSize($path, $mime)) { + $ret = $imgsize['dimensions']; } - return $size; + return $ret; } - /** - * Get file contents - * - * @param string $path file path - * - * @return string|false - **/ - protected function _getContents($path) - { - return $this->fs->read($path); - } + /******************** file/dir content *********************/ /** * Return files list in directory * - * @param string $path dir path - * + * @param string $path dir path * @return array **/ protected function _scandir($path) { - $paths = []; - foreach ($this->fs->listContents($path, false) as $object) { + $paths = array(); + + foreach ($this->listContents($path, false) as $object) { if ($object) { - $paths[] = $object->path(); + $paths[] = $object['path']; } } - return $paths; } /** * Open file and return file pointer * - * @param string $path file path - * @param string $mode - * + * @param string $path file path + * @param string $mode * @return resource|false **/ protected function _fopen($path, $mode = "rb") @@ -496,9 +397,8 @@ protected function _fopen($path, $mode = "rb") /** * Close opened file * - * @param resource $fp file pointer - * @param string $path file path - * + * @param resource $fp file pointer + * @param string $path file path * @return bool **/ protected function _fclose($fp, $path = '') @@ -506,52 +406,42 @@ protected function _fclose($fp, $path = '') return @fclose($fp); } + /******************** file/dir manipulations *************************/ + /** * Create dir and return created dir path or false on failed * - * @param string $path parent dir path - * @param string $name new directory name - * + * @param string $path parent dir path + * @param string $name new directory name * @return string|bool **/ protected function _mkdir($path, $name) { $path = $this->_joinPath($path, $name); - if ($this->fs->createDirectory($path) === false) { + try { + $this->fs->createDirectory($path); + } catch (UnableToCreateDirectory $e) { return false; } return $path; } - /** - * Join dir name and file name and return full path - * - * @param string $dir - * @param string $name - * - * @return string - * @author Dmitry (dio) Levashov - **/ - protected function _joinPath($dir, $name) - { - return Utils::normalizePath($dir . $this->separator . $name); - } - /** * Create file and return it's path or false on failed * - * @param string $path parent dir path - * @param string $name new file name - * + * @param string $path parent dir path + * @param string $name new file name * @return string|bool **/ protected function _mkfile($path, $name) { $path = $this->_joinPath($path, $name); - if ($this->fs->write($path, '') === false) { + try { + $this->fs->write($path, ''); + } catch (UnableToWriteFile $e) { return false; } @@ -561,40 +451,40 @@ protected function _mkfile($path, $name) /** * Copy file into another file * - * @param string $source source file path - * @param string $target target directory path - * @param string $name new file name - * + * @param string $source source file path + * @param string $target target directory path + * @param string $name new file name * @return string|bool **/ protected function _copy($source, $target, $name) { $path = $this->_joinPath($target, $name); - if ($this->fs->copy($source, $path) === false) { + try { + $this->fs->copy($source, $path); + } catch (UnableToCopyFile $e) { return false; } return $path; } - /*********************** paths/urls *************************/ - /** * Move file into another parent dir. * Return new file path or false. * - * @param string $source source file path - * @param string $target target dir path - * @param string $name file name - * + * @param string $source source file path + * @param string $target target dir path + * @param string $name file name * @return string|bool **/ protected function _move($source, $target, $name) { $path = $this->_joinPath($target, $name); - if ($this->fs->move($source, $path) === false) { + try { + $this->fs->move($source, $path); + } catch (UnableToMoveFile $e) { return false; } @@ -604,26 +494,34 @@ protected function _move($source, $target, $name) /** * Remove file * - * @param string $path file path - * + * @param string $path file path * @return bool **/ protected function _unlink($path) { - $this->fs->delete($path); + try { + $this->fs->delete($path); + } catch (UnableToDeleteFile $e) { + return false; + } + return true; } /** * Remove dir * - * @param string $path dir path - * + * @param string $path dir path * @return bool **/ protected function _rmdir($path) { - $this->fs->deleteDirectory($path); + try { + $this->fs->deleteDirectory($path); + } catch (UnableToDeleteDirectory $e) { + return false; + } + return true; } @@ -631,11 +529,10 @@ protected function _rmdir($path) * Create new file and write into it from file pointer. * Return new file path or false on error. * - * @param resource $fp file pointer - * @param string $dir target dir path - * @param string $name file name - * @param array $stat file stat (required by some virtual fs) - * + * @param resource $fp file pointer + * @param string $dir target dir path + * @param string $name file name + * @param array $stat file stat (required by some virtual fs) * @return bool|string **/ protected function _save($fp, $dir, $name, $stat) @@ -652,7 +549,9 @@ protected function _save($fp, $dir, $name, $stat) $config['visibility'] = $this->options['visibility']; } - if ($this->fs->writeStream($path, $fp, $config) === false) { + try { + $this->fs->writeStream($path, $fp, $config); + } catch (UnableToWriteFile $e) { return false; } @@ -660,10 +559,40 @@ protected function _save($fp, $dir, $name, $stat) } /** - * Return file name + * Get file contents * - * @param string $path file path + * @param string $path file path + * @return string|false + **/ + protected function _getContents($path) + { + return $this->fs->read($path); + } + + /** + * Write a string to a file * + * @param string $path file path + * @param string $content new file content + * @return bool + **/ + protected function _filePutContents($path, $content) + { + try { + $this->fs->write($path, $content); + } catch (UnableToWriteFile $e) { + return false; + } + return true; + } + + /*********************** paths/urls *************************/ + + + /** + * Return file name + * + * @param string $path file path * @return string * @author Dmitry (dio) Levashov **/ @@ -673,10 +602,22 @@ protected function _basename($path) } /** - * Return file path related to root dir + * Join dir name and file name and return full path * - * @param string $path file path + * @param string $dir + * @param string $name + * @return string + * @author Dmitry (dio) Levashov + **/ + protected function _joinPath($dir, $name) + { + return (new WhitespacePathNormalizer())->normalizePath($dir . $this->separator . $name); + } + + /** + * Return file path related to root dir * + * @param string $path file path * @return string **/ protected function _relpath($path) @@ -687,8 +628,7 @@ protected function _relpath($path) /** * Convert path related to root dir into real path * - * @param string $path file path - * + * @param string $path file path * @return string **/ protected function _abspath($path) @@ -699,8 +639,7 @@ protected function _abspath($path) /** * Return fake path started from root dir * - * @param string $path file path - * + * @param string $path file path * @return string **/ protected function _path($path) @@ -711,9 +650,8 @@ protected function _path($path) /** * Return true if $path is children of $parent * - * @param string $path path to check - * @param string $parent parent path - * + * @param string $path path to check + * @param string $parent parent path * @return bool * @author Dmitry (dio) Levashov **/ @@ -725,10 +663,9 @@ protected function _inpath($path, $parent) /** * Create symlink * - * @param string $source file to link to - * @param string $targetDir folder to create link in - * @param string $name symlink name - * + * @param string $source file to link to + * @param string $targetDir folder to create link in + * @param string $name symlink name * @return bool **/ protected function _symlink($source, $targetDir, $name) @@ -739,9 +676,8 @@ protected function _symlink($source, $targetDir, $name) /** * Extract files from archive * - * @param string $path file path - * @param array $arc archiver options - * + * @param string $path file path + * @param array $arc archiver options * @return bool **/ protected function _extract($path, $arc) @@ -752,11 +688,10 @@ protected function _extract($path, $arc) /** * Create archive and return its path * - * @param string $dir target dir - * @param array $files files names list - * @param string $name archive name - * @param array $arc archiver options - * + * @param string $dir target dir + * @param array $files files names list + * @param string $name archive name + * @param array $arc archiver options * @return string|bool **/ protected function _archive($dir, $files, $name, $arc) @@ -784,4 +719,140 @@ protected function _chmod($path, $mode) return false; } + /** + * Resize image + * + * @param string $hash image file + * @param int $width new width + * @param int $height new height + * @param int $x X start poistion for crop + * @param int $y Y start poistion for crop + * @param string $mode action how to mainpulate image + * @param string $bg background color + * @param int $degree rotete degree + * @param int $jpgQuality JEPG quality (1-100) + * @return array|false + * @author Dmitry (dio) Levashov + * @author Alexey Sukhotin + * @author nao-pon + * @author Troex Nevelin + **/ + public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0, $jpgQuality = null) + { + if ($this->commandDisabled('resize')) { + return $this->setError(elFinder::ERROR_PERM_DENIED); + } + + if (($file = $this->file($hash)) == false) { + return $this->setError(elFinder::ERROR_FILE_NOT_FOUND); + } + + if (!$file['write'] || !$file['read']) { + return $this->setError(elFinder::ERROR_PERM_DENIED); + } + + $path = $this->decode($hash); + if (!$this->canResize($path, $file)) { + return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE); + } + + if (!$image = $this->imageManager->make($this->_getContents($path))) { + return false; + } + + switch ($mode) { + case 'propresize': + $image->resize($width, $height, function ($constraint) { + $constraint->aspectRatio(); + }); + break; + + case 'crop': + $image->crop($width, $height, $x, $y); + break; + + case 'fitsquare': + $image->fit($width, $height, null, 'center'); + break; + + case 'rotate': + $image->rotate($degree); + break; + + default: + $image->resize($width, $height); + break; + } + + if ($jpgQuality && $image->mime() === 'image/jpeg') { + $result = (string)$image->encode('jpg', $jpgQuality); + } else { + $result = (string)$image->encode(); + } + if ($result && $this->_filePutContents($path, $result)) { + $this->rmTmb($file); + $this->clearstatcache(); + $stat = $this->stat($path); + $stat['width'] = $image->width(); + $stat['height'] = $image->height(); + return $stat; + } + + return false; + } + + public function getImageSize($path, $mime = '') + { + $size = false; + if ($mime === '' || strtolower(substr($mime, 0, 5)) === 'image') { + if ($data = $this->_getContents($path)) { + if ($size = @getimagesizefromstring($data)) { + $size['dimensions'] = $size[0] . 'x' . $size[1]; + } + } + } + return $size; + } + + /** + * Return content URL + * + * @param string $hash file hash + * @param array $options options + * @return string + **/ + public function getContentUrl($hash, $options = array()) + { + if (! empty($options['onetime']) && $this->options['onetimeUrl']) { + // use parent method to make onetime URL + return parent::getContentUrl($hash, $options); + } + if (!empty($options['temporary'])) { + // try make temporary file + $url = parent::getContentUrl($hash, $options); + if ($url) { + return $url; + } + } + + if (($file = $this->file($hash)) == false || !isset($file['url']) || !$file['url'] || $file['url'] == 1) { + if ($file && !empty($file['url']) && !empty($options['temporary'])) { + return parent::getContentUrl($hash, $options); + } + $path = $this->decode($hash); + + if ($this->options['URLCallback'] && is_callable($this->options['URLCallback'])) { + return $this->options['URLCallback']($path); + } + + return parent::getContentUrl($hash, $options); + } + return $file['url']; + } + public function has(string $location): bool + { + $path = Utils::normalizePath($location); + + return $this->fs->fileExists($path) ; + } }