176 lines
7.2 KiB
PHP
176 lines
7.2 KiB
PHP
<?php
|
|
/*************************************************************************************/
|
|
/* */
|
|
/* Thelia */
|
|
/* */
|
|
/* Copyright (c) OpenStudio */
|
|
/* email : info@thelia.net */
|
|
/* web : http://www.thelia.net */
|
|
/* */
|
|
/* This program is free software; you can redistribute it and/or modify */
|
|
/* it under the terms of the GNU General Public License as published by */
|
|
/* the Free Software Foundation; either version 3 of the License */
|
|
/* */
|
|
/* This program is distributed in the hope that it will be useful, */
|
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
/* GNU General Public License for more details. */
|
|
/* */
|
|
/* You should have received a copy of the GNU General Public License */
|
|
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
/* */
|
|
/*************************************************************************************/
|
|
|
|
namespace Thelia\Action;
|
|
|
|
use Thelia\Core\Event\CachedFileEvent;
|
|
use Thelia\Tools\URL;
|
|
|
|
/**
|
|
*
|
|
* Cached file management actions. This class handles file caching in the web space
|
|
*
|
|
* Basically, files are stored outside the web space (by default in local/media/<dirname>),
|
|
* and cached in the web space (by default in web/local/<dirname>).
|
|
*
|
|
* In the file cache directory, a subdirectory for files categories (eg. product, category, folder, etc.) is
|
|
* automatically created, and the cached file is created here. Plugin may use their own subdirectory as required.
|
|
*
|
|
* A copy (or symbolic link, by default) of the original file is created in the cache.
|
|
*
|
|
* @package Thelia\Action
|
|
* @author Franck Allimant <franck@cqfdev.fr>
|
|
*
|
|
*/
|
|
abstract class BaseCachedFile extends BaseAction
|
|
{
|
|
/**
|
|
* @return string root of the file cache directory in web space
|
|
*/
|
|
abstract protected function getCacheDirFromWebRoot();
|
|
|
|
/**
|
|
* Clear the file cache. Is a subdirectory is specified, only this directory is cleared.
|
|
* If no directory is specified, the whole cache is cleared.
|
|
* Only files are deleted, directories will remain.
|
|
*
|
|
* @param CachedFileEvent $event
|
|
*/
|
|
public function clearCache(CachedFileEvent $event)
|
|
{
|
|
$path = $this->getCachePath($event->getCacheSubdirectory(), false);
|
|
|
|
$this->clearDirectory($path);
|
|
}
|
|
|
|
/**
|
|
* Recursively clears the specified directory.
|
|
*
|
|
* @param string $path the directory path
|
|
*/
|
|
protected function clearDirectory($path)
|
|
{
|
|
$iterator = new \DirectoryIterator($path);
|
|
|
|
foreach ($iterator as $fileinfo) {
|
|
|
|
if ($fileinfo->isDot()) continue;
|
|
|
|
if ($fileinfo->isFile() || $fileinfo->isLink()) {
|
|
@unlink($fileinfo->getPathname());
|
|
} elseif ($fileinfo->isDir()) {
|
|
$this->clearDirectory($fileinfo->getPathname());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the absolute URL to the cached file
|
|
*
|
|
* @param string $subdir the subdirectory related to cache base
|
|
* @param string $filename the safe filename, as returned by getCacheFilePath()
|
|
* @return string the absolute URL to the cached file
|
|
*/
|
|
protected function getCacheFileURL($subdir, $safe_filename)
|
|
{
|
|
$path = $this->getCachePathFromWebRoot($subdir);
|
|
|
|
return URL::getInstance()->absoluteUrl(sprintf("%s/%s", $path, $safe_filename), null, URL::PATH_TO_FILE);
|
|
}
|
|
|
|
/**
|
|
* Return the full path of the cached file
|
|
*
|
|
* @param string $subdir the subdirectory related to cache base
|
|
* @param string $filename the filename
|
|
* @param string $hashed_options a hash of transformation options, or null if no transformations have been applied
|
|
* @param boolean $forceOriginalDocument if true, the original file path in the cache dir is returned.
|
|
* @return string the cache directory path relative to Web Root
|
|
*/
|
|
protected function getCacheFilePath($subdir, $filename, $forceOriginalFile = false, $hashed_options = null)
|
|
{
|
|
$path = $this->getCachePath($subdir);
|
|
|
|
$safe_filename = preg_replace("[^:alnum:\-\._]", "-", strtolower(basename($filename)));
|
|
|
|
// Keep original safe name if no tranformations are applied
|
|
if ($forceOriginalFile || $hashed_options == null)
|
|
return sprintf("%s/%s", $path, $safe_filename);
|
|
else
|
|
return sprintf("%s/%s-%s", $path, $hashed_options, $safe_filename);
|
|
}
|
|
|
|
/**
|
|
* Return the cache directory path relative to Web Root
|
|
*
|
|
* @param string $subdir the subdirectory related to cache base, or null to get the cache directory only.
|
|
* @return string the cache directory path relative to Web Root
|
|
*/
|
|
protected function getCachePathFromWebRoot($subdir = null)
|
|
{
|
|
$cache_dir_from_web_root = $this->getCacheDirFromWebRoot();
|
|
|
|
if ($subdir != null) {
|
|
$safe_subdir = basename($subdir);
|
|
|
|
$path = sprintf("%s/%s", $cache_dir_from_web_root, $safe_subdir);
|
|
} else
|
|
$path = $cache_dir_from_web_root;
|
|
|
|
// Check if path is valid, e.g. in the cache dir
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Return the absolute cache directory path
|
|
*
|
|
* @param string $subdir the subdirectory related to cache base, or null to get the cache base directory.
|
|
* @throws \RuntimeException if cache directory cannot be created
|
|
* @return string the absolute cache directory path
|
|
*/
|
|
protected function getCachePath($subdir = null, $create_if_not_exists = true)
|
|
{
|
|
$cache_base = $this->getCachePathFromWebRoot($subdir);
|
|
|
|
$web_root = rtrim(THELIA_WEB_DIR, '/');
|
|
|
|
$path = sprintf("%s/%s", $web_root, $cache_base);
|
|
|
|
// Create directory (recursively) if it does not exists.
|
|
if ($create_if_not_exists && !is_dir($path)) {
|
|
if (!@mkdir($path, 0777, true)) {
|
|
throw new \RuntimeException(sprintf("Failed to create %s/%s file in cache directory", $cache_base));
|
|
}
|
|
}
|
|
|
|
// Check if path is valid, e.g. in the cache dir
|
|
$cache_base = realpath(sprintf("%s/%s", $web_root, $this->getCachePathFromWebRoot()));
|
|
|
|
if (strpos(realpath($path), $cache_base) !== 0) {
|
|
throw new \InvalidArgumentException(sprintf("Invalid cache path %s, with subdirectory %s", $path, $subdir));
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
}
|