[Cache] Optimize & wire PhpFilesAdapter
This commit is contained in:
parent
14bcd799c7
commit
8983e83d91
@ -47,6 +47,7 @@ before_install:
|
|||||||
- if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
|
- if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
|
||||||
- if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
|
- if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
|
||||||
- if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
|
- if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
|
||||||
|
- if [[ ! $skip ]]; then echo opcache.enable_cli = 1 >> $INI_FILE; fi
|
||||||
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
|
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
|
||||||
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi
|
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi
|
||||||
- if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi
|
- if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi
|
||||||
|
@ -35,6 +35,8 @@ install:
|
|||||||
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini-min
|
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini-min
|
||||||
- IF %PHP%==1 echo extension_dir=ext >> php.ini-min
|
- IF %PHP%==1 echo extension_dir=ext >> php.ini-min
|
||||||
- IF %PHP%==1 copy /Y php.ini-min php.ini-max
|
- IF %PHP%==1 copy /Y php.ini-min php.ini-max
|
||||||
|
- IF %PHP%==1 echo zend_extension=php_opcache.dll >> php.ini-max
|
||||||
|
- IF %PHP%==1 echo opcache.enable_cli=1 >> php.ini-max
|
||||||
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini-max
|
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini-max
|
||||||
- IF %PHP%==1 echo extension=php_apcu.dll >> php.ini-max
|
- IF %PHP%==1 echo extension=php_apcu.dll >> php.ini-max
|
||||||
- IF %PHP%==1 echo apc.enable_cli=1 >> php.ini-max
|
- IF %PHP%==1 echo apc.enable_cli=1 >> php.ini-max
|
||||||
|
@ -70,6 +70,15 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
|
|||||||
|
|
||||||
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
|
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
|
if (!ApcuAdapter::isSupported() && PhpFilesAdapter::isSupported()) {
|
||||||
|
$opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory);
|
||||||
|
if (null !== $logger) {
|
||||||
|
$opcache->setLogger($logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $opcache;
|
||||||
|
}
|
||||||
|
|
||||||
$fs = new FilesystemAdapter($namespace, $defaultLifetime, $directory);
|
$fs = new FilesystemAdapter($namespace, $defaultLifetime, $directory);
|
||||||
if (null !== $logger) {
|
if (null !== $logger) {
|
||||||
$fs->setLogger($logger);
|
$fs->setLogger($logger);
|
||||||
|
@ -11,27 +11,17 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Cache\Adapter;
|
namespace Symfony\Component\Cache\Adapter;
|
||||||
|
|
||||||
use Symfony\Component\Cache\Adapter\Helper\FilesCacheHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
*/
|
*/
|
||||||
class FilesystemAdapter extends AbstractAdapter
|
class FilesystemAdapter extends AbstractAdapter
|
||||||
{
|
{
|
||||||
/**
|
use FilesystemAdapterTrait;
|
||||||
* @var FilesCacheHelper
|
|
||||||
*/
|
|
||||||
protected $filesCacheHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $namespace Cache namespace
|
|
||||||
* @param int $defaultLifetime Default lifetime for cache items
|
|
||||||
* @param null $directory Path where cache items should be stored, defaults to sys_get_temp_dir().'/symfony-cache'
|
|
||||||
*/
|
|
||||||
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
|
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
|
||||||
{
|
{
|
||||||
parent::__construct($namespace, $defaultLifetime);
|
parent::__construct('', $defaultLifetime);
|
||||||
$this->filesCacheHelper = new FilesCacheHelper($directory, $namespace);
|
$this->init($namespace, $directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +33,7 @@ class FilesystemAdapter extends AbstractAdapter
|
|||||||
$now = time();
|
$now = time();
|
||||||
|
|
||||||
foreach ($ids as $id) {
|
foreach ($ids as $id) {
|
||||||
$file = $this->filesCacheHelper->getFilePath($id);
|
$file = $this->getFile($id);
|
||||||
if (!$h = @fopen($file, 'rb')) {
|
if (!$h = @fopen($file, 'rb')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -70,41 +60,11 @@ class FilesystemAdapter extends AbstractAdapter
|
|||||||
*/
|
*/
|
||||||
protected function doHave($id)
|
protected function doHave($id)
|
||||||
{
|
{
|
||||||
$file = $this->filesCacheHelper->getFilePath($id);
|
$file = $this->getFile($id);
|
||||||
|
|
||||||
return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
|
return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function doClear($namespace)
|
|
||||||
{
|
|
||||||
$ok = true;
|
|
||||||
$directory = $this->filesCacheHelper->getDirectory();
|
|
||||||
|
|
||||||
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
|
|
||||||
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function doDelete(array $ids)
|
|
||||||
{
|
|
||||||
$ok = true;
|
|
||||||
|
|
||||||
foreach ($ids as $id) {
|
|
||||||
$file = $this->filesCacheHelper->getFilePath($id);
|
|
||||||
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -114,22 +74,9 @@ class FilesystemAdapter extends AbstractAdapter
|
|||||||
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
|
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
|
||||||
|
|
||||||
foreach ($values as $id => $value) {
|
foreach ($values as $id => $value) {
|
||||||
$fileContent = $this->createCacheFileContent($id, $value, $expiresAt);
|
$ok = $this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok;
|
||||||
$ok = $this->filesCacheHelper->saveFileForId($id, $fileContent, $expiresAt) && $ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ok;
|
return $ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $id
|
|
||||||
* @param mixed $value
|
|
||||||
* @param int $expiresAt
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function createCacheFileContent($id, $value, $expiresAt)
|
|
||||||
{
|
|
||||||
return $expiresAt."\n".rawurlencode($id)."\n".serialize($value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
110
src/Symfony/Component/Cache/Adapter/FilesystemAdapterTrait.php
Normal file
110
src/Symfony/Component/Cache/Adapter/FilesystemAdapterTrait.php
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Cache\Adapter;
|
||||||
|
|
||||||
|
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
trait FilesystemAdapterTrait
|
||||||
|
{
|
||||||
|
private $directory;
|
||||||
|
private $tmp;
|
||||||
|
|
||||||
|
private function init($namespace, $directory)
|
||||||
|
{
|
||||||
|
if (!isset($directory[0])) {
|
||||||
|
$directory = sys_get_temp_dir().'/symfony-cache';
|
||||||
|
}
|
||||||
|
if (isset($namespace[0])) {
|
||||||
|
if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
|
||||||
|
}
|
||||||
|
$directory .= '/'.$namespace;
|
||||||
|
}
|
||||||
|
if (!file_exists($dir = $directory.'/.')) {
|
||||||
|
@mkdir($directory, 0777, true);
|
||||||
|
}
|
||||||
|
if (false === $dir = realpath($dir)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Cache directory does not exist (%s)', $directory));
|
||||||
|
}
|
||||||
|
if (!is_writable($dir .= DIRECTORY_SEPARATOR)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Cache directory is not writable (%s)', $directory));
|
||||||
|
}
|
||||||
|
// On Windows the whole path is limited to 258 chars
|
||||||
|
if ('\\' === DIRECTORY_SEPARATOR && strlen($dir) > 234) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->directory = $dir;
|
||||||
|
$this->tmp = $this->directory.uniqid('', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function doClear($namespace)
|
||||||
|
{
|
||||||
|
$ok = true;
|
||||||
|
|
||||||
|
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
|
||||||
|
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function doDelete(array $ids)
|
||||||
|
{
|
||||||
|
$ok = true;
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$file = $this->getFile($id);
|
||||||
|
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function write($file, $data, $expiresAt = null)
|
||||||
|
{
|
||||||
|
if (false === @file_put_contents($this->tmp, $data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $expiresAt) {
|
||||||
|
@touch($this->tmp, $expiresAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@rename($this->tmp, $file)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@unlink($this->tmp);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFile($id, $mkdir = false)
|
||||||
|
{
|
||||||
|
$hash = str_replace('/', '-', base64_encode(md5(static::class.$id, true)));
|
||||||
|
$dir = $this->directory.$hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
if ($mkdir && !file_exists($dir)) {
|
||||||
|
@mkdir($dir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dir.substr($hash, 2, -2);
|
||||||
|
}
|
||||||
|
}
|
@ -1,137 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Cache\Adapter\Helper;
|
|
||||||
|
|
||||||
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
|
||||||
|
|
||||||
class FilesCacheHelper
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $fileSuffix;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $directory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $directory Path where cache items should be stored, defaults to sys_get_temp_dir().'/symfony-cache'
|
|
||||||
* @param string $namespace Cache namespace
|
|
||||||
* @param string $version Version (works the same way as namespace)
|
|
||||||
* @param string $fileSuffix Suffix that will be appended to all file names
|
|
||||||
*/
|
|
||||||
public function __construct($directory = null, $namespace = null, $version = null, $fileSuffix = '')
|
|
||||||
{
|
|
||||||
if (!isset($directory[0])) {
|
|
||||||
$directory = sys_get_temp_dir().'/symfony-cache';
|
|
||||||
}
|
|
||||||
if (isset($namespace[0])) {
|
|
||||||
if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Cache namespace for filesystem cache contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
|
|
||||||
}
|
|
||||||
$directory .= '/'.$namespace;
|
|
||||||
}
|
|
||||||
if (isset($version[0])) {
|
|
||||||
if (preg_match('#[^-+_.A-Za-z0-9]#', $version, $match)) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Cache version contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
|
|
||||||
}
|
|
||||||
$directory .= '/'.$version;
|
|
||||||
}
|
|
||||||
if (!file_exists($dir = $directory.'/.')) {
|
|
||||||
@mkdir($directory, 0777, true);
|
|
||||||
}
|
|
||||||
if (false === $dir = realpath($dir)) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Cache directory does not exist (%s)', $directory));
|
|
||||||
}
|
|
||||||
if (!is_writable($dir .= DIRECTORY_SEPARATOR)) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Cache directory is not writable (%s)', $directory));
|
|
||||||
}
|
|
||||||
// On Windows the whole path is limited to 258 chars
|
|
||||||
if ('\\' === DIRECTORY_SEPARATOR && strlen($dir) + strlen($fileSuffix) > 234) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->fileSuffix = $fileSuffix;
|
|
||||||
$this->directory = $dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns root cache directory.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDirectory()
|
|
||||||
{
|
|
||||||
return $this->directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves entry in cache.
|
|
||||||
*
|
|
||||||
* @param string $id Id of the cache entry (used for obtaining file path to write to).
|
|
||||||
* @param string $fileContent Content to write to cache file
|
|
||||||
* @param int|null $modificationTime If this is not-null it will be passed to touch()
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function saveFileForId($id, $fileContent, $modificationTime = null)
|
|
||||||
{
|
|
||||||
$file = $this->getFilePath($id, true);
|
|
||||||
|
|
||||||
return $this->saveFile($file, $fileContent, $modificationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves entry in cache.
|
|
||||||
*
|
|
||||||
* @param string $file File path to cache entry.
|
|
||||||
* @param string $fileContent Content to write to cache file
|
|
||||||
* @param int|null $modificationTime If this is not-null it will be passed to touch()
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function saveFile($file, $fileContent, $modificationTime = null)
|
|
||||||
{
|
|
||||||
$temporaryFile = $this->directory.uniqid('', true);
|
|
||||||
if (false === @file_put_contents($temporaryFile, $fileContent)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $modificationTime) {
|
|
||||||
@touch($temporaryFile, $modificationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
return @rename($temporaryFile, $file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns file path to cache entry.
|
|
||||||
*
|
|
||||||
* @param string $id Cache entry id.
|
|
||||||
* @param bool $mkdir Whether to create necessary directories before returning file path.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getFilePath($id, $mkdir = false)
|
|
||||||
{
|
|
||||||
$hash = str_replace('/', '-', base64_encode(md5($id, true)));
|
|
||||||
$dir = $this->directory.$hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR;
|
|
||||||
|
|
||||||
if ($mkdir && !file_exists($dir)) {
|
|
||||||
@mkdir($dir, 0777, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $dir.substr($hash, 2, -2).$this->fileSuffix;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,25 +11,34 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Cache\Adapter;
|
namespace Symfony\Component\Cache\Adapter;
|
||||||
|
|
||||||
use Symfony\Component\Cache\Adapter\Helper\FilesCacheHelper;
|
use Symfony\Component\Cache\Exception\CacheException;
|
||||||
|
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Piotr Stankowski <git@trakos.pl>
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
class PhpFilesAdapter extends AbstractAdapter
|
class PhpFilesAdapter extends AbstractAdapter
|
||||||
{
|
{
|
||||||
/**
|
use FilesystemAdapterTrait;
|
||||||
* @var FilesCacheHelper
|
|
||||||
*/
|
|
||||||
protected $filesCacheHelper;
|
|
||||||
|
|
||||||
/**
|
private $includeHandler;
|
||||||
* @param string $namespace Cache namespace
|
|
||||||
* @param int $defaultLifetime Default lifetime for cache items
|
public static function isSupported()
|
||||||
* @param null $directory Path where cache items should be stored, defaults to sys_get_temp_dir().'/symfony-cache'
|
|
||||||
* @param string $version Version (works the same way as namespace)
|
|
||||||
*/
|
|
||||||
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null, $version = null)
|
|
||||||
{
|
{
|
||||||
parent::__construct($namespace, $defaultLifetime);
|
return function_exists('opcache_compile_file') && ini_get('opcache.enable');
|
||||||
$this->filesCacheHelper = new FilesCacheHelper($directory, $namespace, $version, '.php');
|
}
|
||||||
|
|
||||||
|
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
|
||||||
|
{
|
||||||
|
if (!static::isSupported()) {
|
||||||
|
throw new CacheException('OPcache is not enabled');
|
||||||
|
}
|
||||||
|
parent::__construct('', $defaultLifetime);
|
||||||
|
$this->init($namespace, $directory);
|
||||||
|
|
||||||
|
$e = new \Exception();
|
||||||
|
$this->includeHandler = function () use ($e) { throw $e; };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,13 +47,31 @@ class PhpFilesAdapter extends AbstractAdapter
|
|||||||
protected function doFetch(array $ids)
|
protected function doFetch(array $ids)
|
||||||
{
|
{
|
||||||
$values = array();
|
$values = array();
|
||||||
|
$now = time();
|
||||||
|
|
||||||
foreach ($ids as $id) {
|
set_error_handler($this->includeHandler);
|
||||||
$valueArray = $this->includeCacheFile($this->filesCacheHelper->getFilePath($id));
|
try {
|
||||||
if (!is_array($valueArray)) {
|
foreach ($ids as $id) {
|
||||||
continue;
|
try {
|
||||||
|
$file = $this->getFile($id);
|
||||||
|
list($expiresAt, $values[$id]) = include $file;
|
||||||
|
if ($now >= $expiresAt) {
|
||||||
|
unset($values[$id]);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
restore_error_handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($values as $id => $value) {
|
||||||
|
if ('N;' === $value) {
|
||||||
|
$values[$id] = null;
|
||||||
|
} elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) {
|
||||||
|
$values[$id] = unserialize($value);
|
||||||
}
|
}
|
||||||
$values[$id] = $valueArray[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $values;
|
return $values;
|
||||||
@ -55,32 +82,7 @@ class PhpFilesAdapter extends AbstractAdapter
|
|||||||
*/
|
*/
|
||||||
protected function doHave($id)
|
protected function doHave($id)
|
||||||
{
|
{
|
||||||
return 0 !== count($this->doFetch(array($id)));
|
return (bool) $this->doFetch(array($id));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function doClear($namespace)
|
|
||||||
{
|
|
||||||
$directory = $this->filesCacheHelper->getDirectory();
|
|
||||||
|
|
||||||
return !(new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS))->valid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function doDelete(array $ids)
|
|
||||||
{
|
|
||||||
foreach ($ids as $id) {
|
|
||||||
$file = $this->filesCacheHelper->getFilePath($id);
|
|
||||||
if (@file_exists($file)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,69 +91,33 @@ class PhpFilesAdapter extends AbstractAdapter
|
|||||||
protected function doSave(array $values, $lifetime)
|
protected function doSave(array $values, $lifetime)
|
||||||
{
|
{
|
||||||
$ok = true;
|
$ok = true;
|
||||||
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
|
$data = array($lifetime ? time() + $lifetime : PHP_INT_MAX, '');
|
||||||
|
|
||||||
foreach ($values as $id => $value) {
|
foreach ($values as $id => $value) {
|
||||||
$file = $this->filesCacheHelper->getFilePath($id, true);
|
if (null === $value || is_object($value)) {
|
||||||
if (file_exists($file)) {
|
$value = serialize($value);
|
||||||
$ok = false;
|
} elseif (is_array($value)) {
|
||||||
} else {
|
$serialized = serialize($value);
|
||||||
$ok = $this->saveCacheFile($file, $value, $expiresAt) && $ok;
|
$unserialized = unserialize($serialized);
|
||||||
|
// Store arrays serialized if they contain any objects or references
|
||||||
|
if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) {
|
||||||
|
$value = $serialized;
|
||||||
|
}
|
||||||
|
} elseif (is_string($value)) {
|
||||||
|
// Serialize strings if they could be confused with serialized objects or arrays
|
||||||
|
if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) {
|
||||||
|
$value = serialize($value);
|
||||||
|
}
|
||||||
|
} elseif (!is_scalar($value)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Value of type "%s" is not serializable', $key, gettype($value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$data[1] = $value;
|
||||||
|
$file = $this->getFile($id, true);
|
||||||
|
$ok = $this->write($file, '<?php return '.var_export($data, true).';') && $ok;
|
||||||
|
@opcache_compile_file($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ok;
|
return $ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $file
|
|
||||||
* @param mixed $value
|
|
||||||
* @param int $expiresAt
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function saveCacheFile($file, $value, $expiresAt)
|
|
||||||
{
|
|
||||||
$fileContent = $this->createCacheFileContent($value, $expiresAt);
|
|
||||||
|
|
||||||
return $this->filesCacheHelper->saveFile($file, $fileContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $file File path
|
|
||||||
*
|
|
||||||
* @return array|null unserialized value wrapped in array or null
|
|
||||||
*/
|
|
||||||
private function includeCacheFile($file)
|
|
||||||
{
|
|
||||||
$valueArray = @include $file;
|
|
||||||
if (!is_array($valueArray) || 2 !== count($valueArray)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($serializedValue, $expiresAt) = $valueArray;
|
|
||||||
if (time() > (int) $expiresAt) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$unserializedValueInArray = unserialize($serializedValue);
|
|
||||||
if (!is_array($unserializedValueInArray)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unserializedValueInArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $value
|
|
||||||
* @param int $expiresAt
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function createCacheFileContent($value, $expiresAt)
|
|
||||||
{
|
|
||||||
$exportedValue = var_export(array(serialize([$value]), $expiresAt), true);
|
|
||||||
|
|
||||||
return '<?php return '.$exportedValue.';';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,260 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
|
||||||
|
|
||||||
use Cache\IntegrationTests\CachePoolTest;
|
|
||||||
use Psr\Cache\CacheItemInterface;
|
|
||||||
use Psr\Cache\CacheItemPoolInterface;
|
|
||||||
|
|
||||||
abstract class AbstractAppendOnlyAdapterTest extends CachePoolTest
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
private $cacheVersion;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var CacheItemPoolInterface
|
|
||||||
*/
|
|
||||||
private $cache;
|
|
||||||
|
|
||||||
protected function setUp()
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
$this->cacheVersion = $this->createRandomCachePoolVersion();
|
|
||||||
$this->cache = $this->createVersionedCachePool($this->cacheVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createCachePool()
|
|
||||||
{
|
|
||||||
$cacheVersion = $this->createRandomCachePoolVersion();
|
|
||||||
|
|
||||||
return $this->createVersionedCachePool($cacheVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return mixed cache version that will be used by this adapter
|
|
||||||
*/
|
|
||||||
abstract public function createRandomCachePoolVersion();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return CacheItemPoolInterface that is used in the tests that need to recreate the same cache pool
|
|
||||||
*/
|
|
||||||
abstract public function createVersionedCachePool($cacheVersion);
|
|
||||||
|
|
||||||
public function testBasicUsage()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('4711');
|
|
||||||
$this->cache->save($item);
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key2');
|
|
||||||
$item->set('4712');
|
|
||||||
$this->cache->save($item);
|
|
||||||
|
|
||||||
$fooItem = $this->cache->getItem('key');
|
|
||||||
$this->assertTrue($fooItem->isHit());
|
|
||||||
$this->assertEquals('4711', $fooItem->get());
|
|
||||||
|
|
||||||
$barItem = $this->cache->getItem('key2');
|
|
||||||
$this->assertTrue($barItem->isHit());
|
|
||||||
$this->assertEquals('4712', $barItem->get());
|
|
||||||
|
|
||||||
// Removing must always return false
|
|
||||||
$this->assertFalse($this->cache->deleteItem('key'));
|
|
||||||
$this->assertTrue($this->cache->getItem('key')->isHit());
|
|
||||||
$this->assertTrue($this->cache->getItem('key2')->isHit());
|
|
||||||
|
|
||||||
// Remove everything
|
|
||||||
$this->assertFalse($this->cache->clear());
|
|
||||||
$this->assertTrue($this->cache->getItem('key')->isHit());
|
|
||||||
$this->assertTrue($this->cache->getItem('key2')->isHit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testClear()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$return = $this->cache->clear();
|
|
||||||
$this->assertTrue($return, 'clear() should return true when no items are in a cache');
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('value');
|
|
||||||
$this->cache->save($item);
|
|
||||||
|
|
||||||
$return = $this->cache->clear();
|
|
||||||
|
|
||||||
$this->assertFalse($return, 'clear() must return false for append-only cache when not empty.');
|
|
||||||
$this->assertTrue($this->cache->getItem('key')->isHit(), 'Item should still be in an append-only cache, even after clear.');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDeleteItem()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('value');
|
|
||||||
$this->cache->save($item);
|
|
||||||
|
|
||||||
$this->assertFalse($this->cache->deleteItem('key'));
|
|
||||||
$this->assertTrue($this->cache->getItem('key')->isHit(), 'A deleted item should still be a hit in an append-only cache.');
|
|
||||||
$this->assertTrue($this->cache->hasItem('key'), 'A deleted item should still be a hit in an append-only cache.');
|
|
||||||
|
|
||||||
$this->assertTrue($this->cache->deleteItem('key2'), 'Deleting an item that does not exist should return true.');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDeleteItems()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$items = $this->cache->getItems(['foo', 'bar', 'baz']);
|
|
||||||
|
|
||||||
/** @var CacheItemInterface $item */
|
|
||||||
foreach ($items as $idx => $item) {
|
|
||||||
$item->set($idx);
|
|
||||||
$this->cache->save($item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// All should be a hit but 'biz'
|
|
||||||
$this->assertTrue($this->cache->getItem('foo')->isHit());
|
|
||||||
$this->assertTrue($this->cache->getItem('bar')->isHit());
|
|
||||||
$this->assertTrue($this->cache->getItem('baz')->isHit());
|
|
||||||
$this->assertFalse($this->cache->getItem('biz')->isHit());
|
|
||||||
|
|
||||||
$return = $this->cache->deleteItems(['foo', 'bar', 'biz']);
|
|
||||||
$this->assertFalse($return, 'Deleting should return false in append-only cache');
|
|
||||||
|
|
||||||
$this->assertTrue($this->cache->getItem('foo')->isHit(), 'Deleting shouldn\'t work for append-only cache');
|
|
||||||
$this->assertTrue($this->cache->getItem('bar')->isHit(), 'Deleting shouldn\'t work for append-only cache');
|
|
||||||
$this->assertTrue($this->cache->getItem('baz')->isHit(), 'Deleting shouldn\'t work for append-only cache');
|
|
||||||
$this->assertFalse($this->cache->getItem('biz')->isHit());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSaveExpired()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('value');
|
|
||||||
$item->expiresAt(\DateTime::createFromFormat('U', time() - 1));
|
|
||||||
$this->cache->save($item);
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$this->assertFalse($item->isHit(), 'Cache should not return expired items');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSaveWithoutExpire()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('test_ttl_null');
|
|
||||||
$item->set('data');
|
|
||||||
$this->cache->save($item);
|
|
||||||
|
|
||||||
// Use a new pool instance to ensure that we don't it any caches
|
|
||||||
$pool = $this->createVersionedCachePool($this->cacheVersion);
|
|
||||||
$item = $pool->getItem('test_ttl_null');
|
|
||||||
|
|
||||||
$this->assertTrue($item->isHit(), 'Cache should have retrieved the items');
|
|
||||||
$this->assertEquals('data', $item->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDeleteDeferredItem()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('4711');
|
|
||||||
$this->cache->saveDeferred($item);
|
|
||||||
|
|
||||||
$this->cache->deleteItem('key');
|
|
||||||
$this->assertFalse($this->cache->hasItem('key'), 'You must be able to delete a deferred item before committed. ');
|
|
||||||
$this->assertFalse($this->cache->getItem('key')->isHit(), 'You must be able to delete a deferred item before committed. ');
|
|
||||||
|
|
||||||
$this->cache->commit();
|
|
||||||
$this->assertFalse($this->cache->hasItem('key'), 'A deleted item should not reappear after commit. ');
|
|
||||||
$this->assertFalse($this->cache->getItem('key')->isHit(), 'A deleted item should not reappear after commit. ');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDeferredSaveWithoutCommit()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->prepareDeferredSaveWithoutCommit();
|
|
||||||
gc_collect_cycles();
|
|
||||||
|
|
||||||
$cache = $this->createVersionedCachePool($this->cacheVersion);
|
|
||||||
$this->assertTrue($cache->getItem('key')->isHit(), 'A deferred item should automatically be committed on CachePool::__destruct().');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSaveDeferredOverwrite()
|
|
||||||
{
|
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
|
||||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$item->set('value');
|
|
||||||
$this->cache->saveDeferred($item);
|
|
||||||
$item->set('new value');
|
|
||||||
$this->cache->saveDeferred($item);
|
|
||||||
|
|
||||||
$this->cache->commit();
|
|
||||||
$item = $this->cache->getItem('key');
|
|
||||||
$this->assertEquals('new value', $item->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function prepareDeferredSaveWithoutCommit()
|
|
||||||
{
|
|
||||||
$cache = $this->cache;
|
|
||||||
$this->cache = null;
|
|
||||||
|
|
||||||
$item = $cache->getItem('key');
|
|
||||||
$item->set('4711');
|
|
||||||
$cache->saveDeferred($item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,6 +19,15 @@ use Symfony\Component\Cache\Adapter\FilesystemAdapter;
|
|||||||
*/
|
*/
|
||||||
class FilesystemAdapterTest extends CachePoolTest
|
class FilesystemAdapterTest extends CachePoolTest
|
||||||
{
|
{
|
||||||
|
public function createCachePool()
|
||||||
|
{
|
||||||
|
if (defined('HHVM_VERSION')) {
|
||||||
|
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FilesystemAdapter('sf-cache');
|
||||||
|
}
|
||||||
|
|
||||||
public static function tearDownAfterClass()
|
public static function tearDownAfterClass()
|
||||||
{
|
{
|
||||||
self::rmdir(sys_get_temp_dir().'/symfony-cache');
|
self::rmdir(sys_get_temp_dir().'/symfony-cache');
|
||||||
@ -45,13 +54,4 @@ class FilesystemAdapterTest extends CachePoolTest
|
|||||||
}
|
}
|
||||||
rmdir($dir);
|
rmdir($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createCachePool()
|
|
||||||
{
|
|
||||||
if (defined('HHVM_VERSION')) {
|
|
||||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FilesystemAdapter('sf-cache');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,60 +11,28 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Cache\Tests\Adapter;
|
namespace Symfony\Component\Cache\Tests\Adapter;
|
||||||
|
|
||||||
use Psr\Cache\CacheItemPoolInterface;
|
use Cache\IntegrationTests\CachePoolTest;
|
||||||
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
|
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group time-sensitive
|
* @group time-sensitive
|
||||||
*/
|
*/
|
||||||
class PhpFilesAdapterTest extends AbstractAppendOnlyAdapterTest
|
class PhpFilesAdapterTest extends CachePoolTest
|
||||||
{
|
{
|
||||||
public static function tearDownAfterClass()
|
public function createCachePool()
|
||||||
{
|
|
||||||
self::rmdir(sys_get_temp_dir().'/symfony-cache');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function rmdir($dir)
|
|
||||||
{
|
|
||||||
if (!file_exists($dir)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!$dir || 0 !== strpos(dirname($dir), sys_get_temp_dir())) {
|
|
||||||
throw new \Exception(__METHOD__."() operates only on subdirs of system's temp dir");
|
|
||||||
}
|
|
||||||
$children = new \RecursiveIteratorIterator(
|
|
||||||
new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
|
|
||||||
\RecursiveIteratorIterator::CHILD_FIRST
|
|
||||||
);
|
|
||||||
foreach ($children as $child) {
|
|
||||||
if ($child->isDir()) {
|
|
||||||
rmdir($child);
|
|
||||||
} else {
|
|
||||||
unlink($child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rmdir($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $cacheVersion
|
|
||||||
*
|
|
||||||
* @return CacheItemPoolInterface that is used in the tests that need to recreate the same cache pool
|
|
||||||
*/
|
|
||||||
public function createVersionedCachePool($cacheVersion)
|
|
||||||
{
|
{
|
||||||
if (defined('HHVM_VERSION')) {
|
if (defined('HHVM_VERSION')) {
|
||||||
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
|
||||||
}
|
}
|
||||||
|
if (!PhpFilesAdapter::isSupported()) {
|
||||||
|
$this->markTestSkipped('OPcache extension is not enabled.');
|
||||||
|
}
|
||||||
|
|
||||||
return new PhpFilesAdapter('sf-cache', 0, null, $cacheVersion);
|
return new PhpFilesAdapter('sf-cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function tearDownAfterClass()
|
||||||
* @return mixed cache version that will be used by this adapter
|
|
||||||
*/
|
|
||||||
public function createRandomCachePoolVersion()
|
|
||||||
{
|
{
|
||||||
return substr(str_replace('/', '-', base64_encode(md5(uniqid(mt_rand(), true), true))), 0, -2);
|
FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user