Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 48 additions & 9 deletions src/Symfony/Component/Cache/Traits/PhpFilesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ public function prune()
{
$time = time();
$pruned = true;
$getExpiry = true;

set_error_handler($this->includeHandler);
try {
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
try {
list($expiresAt) = include $file;
if (\is_array($expiresAt = include $file)) {
$expiresAt = $expiresAt[0];
}
} catch (\ErrorException $e) {
$expiresAt = $time;
}
Expand Down Expand Up @@ -87,15 +90,21 @@ protected function doFetch(array $ids)
$values = [];

begin:
$getExpiry = false;

foreach ($ids as $id) {
if (null === $value = $this->values[$id] ?? null) {
$missingIds[] = $id;
} elseif ('N;' === $value) {
$values[$id] = null;
} elseif ($value instanceof \Closure) {
$values[$id] = $value();
} else {
} elseif (!\is_object($value)) {
$values[$id] = $value;
} elseif (!$value instanceof LazyValue) {
// calling a Closure is for @deprecated BC and should be removed in Symfony 5.0
$values[$id] = $value();
} elseif (false === $values[$id] = include $value->file) {
unset($values[$id], $this->values[$id]);
$missingIds[] = $id;
}
if (!$this->appendOnly) {
unset($this->values[$id]);
Expand All @@ -108,10 +117,18 @@ protected function doFetch(array $ids)

set_error_handler($this->includeHandler);
try {
$getExpiry = true;

foreach ($missingIds as $k => $id) {
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
list($expiresAt, $this->values[$id]) = include $file;

if (\is_array($expiresAt = include $file)) {
[$expiresAt, $this->values[$id]] = $expiresAt;
} elseif ($now < $expiresAt) {
$this->values[$id] = new LazyValue($file);
}

if ($now >= $expiresAt) {
unset($this->values[$id], $missingIds[$k]);
}
Expand Down Expand Up @@ -140,7 +157,13 @@ protected function doHave($id)
set_error_handler($this->includeHandler);
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
list($expiresAt, $value) = include $file;
$getExpiry = true;

if (\is_array($expiresAt = include $file)) {
[$expiresAt, $value] = $expiresAt;
} elseif ($this->appendOnly) {
$value = new LazyValue($file);
}
} catch (\ErrorException $e) {
return false;
} finally {
Expand Down Expand Up @@ -189,13 +212,16 @@ protected function doSave(array $values, $lifetime)
}

if (!$isStaticValue) {
$value = str_replace("\n", "\n ", $value);
$value = "static function () {\n\n return {$value};\n\n}";
// We cannot use a closure here because of https://bugs.php.net/76982
$value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value);
$value = "<?php\n\nnamespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};\n";
} else {
$value = "<?php return [{$expiry}, {$value}];\n";
}

$file = $this->files[$key] = $this->getFile($key, true);
// Since OPcache only compiles files older than the script execution start, set the file's mtime in the past
$ok = $this->write($file, "<?php return [{$expiry}, {$value}];\n", self::$startTime - 10) && $ok;
$ok = $this->write($file, $value, self::$startTime - 10) && $ok;

if ($allowCompile) {
@opcache_invalidate($file, true);
Expand Down Expand Up @@ -241,3 +267,16 @@ protected function doUnlink($file)
return @unlink($file);
}
}

/**
* @internal
*/
class LazyValue
{
public $file;

public function __construct($file)
{
$this->file = $file;
}
}