1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
<?php
namespace Doctrine\Common\Cache;
use function is_object;
use function method_exists;
use function restore_error_handler;
use function serialize;
use function set_error_handler;
use function sprintf;
use function time;
use function var_export;
/**
* Php file cache driver.
*/
class PhpFileCache extends FileCache
{
public const EXTENSION = '.doctrinecache.php';
/**
* @var callable
*
* This is cached in a local static variable to avoid instantiating a closure each time we need an empty handler
*/
private static $emptyErrorHandler;
/**
* {@inheritdoc}
*/
public function __construct($directory, $extension = self::EXTENSION, $umask = 0002)
{
parent::__construct($directory, $extension, $umask);
self::$emptyErrorHandler = static function () {
};
}
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
$value = $this->includeFileForId($id);
if ($value === null) {
return false;
}
if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) {
return false;
}
return $value['data'];
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
$value = $this->includeFileForId($id);
if ($value === null) {
return false;
}
return $value['lifetime'] === 0 || $value['lifetime'] > time();
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 0) {
$lifeTime = time() + $lifeTime;
}
$filename = $this->getFilename($id);
$value = [
'lifetime' => $lifeTime,
'data' => $data,
];
if (is_object($data) && method_exists($data, '__set_state')) {
$value = var_export($value, true);
$code = sprintf('<?php return %s;', $value);
} else {
$value = var_export(serialize($value), true);
$code = sprintf('<?php return unserialize(%s, [\'allowed_classes\' => false]);', $value);
}
return $this->writeFile($filename, $code);
}
/**
* @return array|null
*/
private function includeFileForId(string $id) : ?array
{
$fileName = $this->getFilename($id);
// note: error suppression is still faster than `file_exists`, `is_file` and `is_readable`
set_error_handler(self::$emptyErrorHandler);
$value = include $fileName;
restore_error_handler();
if (! isset($value['lifetime'])) {
return null;
}
return $value;
}
}
|