diff --git a/packages/Caching/ValueObject/Storage/FileCacheStorage.php b/packages/Caching/ValueObject/Storage/FileCacheStorage.php index 6ecdcd1532f..8bcf099d875 100644 --- a/packages/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/packages/Caching/ValueObject/Storage/FileCacheStorage.php @@ -5,15 +5,14 @@ namespace Rector\Caching\ValueObject\Storage; use Nette\Utils\Random; -use Nette\Utils\Strings; use Rector\Caching\ValueObject\CacheFilePaths; use Rector\Caching\ValueObject\CacheItem; -use Symplify\EasyCodingStandard\Caching\Exception\CachingException; +use PHPStan\File\FileWriter; use Symplify\SmartFileSystem\SmartFileSystem; +use Symplify\EasyCodingStandard\Caching\Exception\CachingException; /** - * Inspired by - * https://github.com/phpstan/phpstan-src/commit/4df7342f3a0aaef4bcd85456dd20ca88d38dd90d#diff-6dc14f6222bf150e6840ca44a7126653052a1cedc6a149b4e5c1e1a2c80eacdc + * Inspired by https://github.com/phpstan/phpstan-src/blob/1e7ceae933f07e5a250b61ed94799e6c2ea8daa2/src/Cache/FileCacheStorage.php */ final class FileCacheStorage { @@ -24,59 +23,60 @@ public function __construct( } /** + * @param string $key + * @param string $variableKey * @return mixed|null */ public function load(string $key, string $variableKey) { - $cacheFilePaths = $this->getCacheFilePaths($key); - - $filePath = $cacheFilePaths->getFilePath(); - if (! is_file($filePath)) { - return null; - } - - $cacheItem = require $filePath; - if (! $cacheItem instanceof CacheItem) { - return null; - } - - if (! $cacheItem->isVariableKeyValid($variableKey)) { - return null; - } - - return $cacheItem->getData(); + return (function (string $key, string $variableKey) { + $cacheFilePaths = $this->getCacheFilePaths($key); + + $filePath = $cacheFilePaths->getFilePath(); + if (!\is_file($filePath)) { + return null; + } + $cacheItem = (require $filePath); + if (!$cacheItem instanceof CacheItem) { + return null; + } + if (!$cacheItem->isVariableKeyValid($variableKey)) { + return null; + } + return $cacheItem->getData(); + })($key, $variableKey); } /** + * @param string $key + * @param string $variableKey * @param mixed $data + * @return void */ - public function save(string $key, string $variableKey, $data): void + public function save(string $key, string $variableKey, $data) : void { $cacheFilePaths = $this->getCacheFilePaths($key); - $this->smartFileSystem->mkdir($cacheFilePaths->getFirstDirectory()); $this->smartFileSystem->mkdir($cacheFilePaths->getSecondDirectory()); + $path = $cacheFilePaths->getFilePath(); - $tmpPath = sprintf('%s/%s.tmp', $this->directory, Random::generate()); - $errorBefore = error_get_last(); - $exported = @var_export(new CacheItem($variableKey, $data), true); - $errorAfter = error_get_last(); - + $tmpPath = \sprintf('%s/%s.tmp', $this->directory, Random::generate()); + $errorBefore = \error_get_last(); + $exported = @\var_export(new CacheItem($variableKey, $data), true); + $errorAfter = \error_get_last(); if ($errorAfter !== null && $errorBefore !== $errorAfter) { - $errorMessage = sprintf( - 'Error occurred while saving item "%s" ("%s") to cache: "%s"', - $key, - $variableKey, - $errorAfter['message'] - ); - throw new CachingException($errorMessage); + throw new CachingException(\sprintf('Error occurred while saving item %s (%s) to cache: %s', $key, $variableKey, $errorAfter['message'])); + } + // for performance reasons we don't use SmartFileSystem + FileWriter::write($tmpPath, \sprintf("smartFileSystem->dumpFile($tmpPath, $variableFileContent); - - $this->smartFileSystem->rename($tmpPath, $cacheFilePaths->getFilePath(), true); - $this->smartFileSystem->remove($tmpPath); } public function clean(string $cacheKey): void @@ -98,8 +98,8 @@ public function clear(): void private function getCacheFilePaths(string $key): CacheFilePaths { $keyHash = sha1($key); - $firstDirectory = sprintf('%s/%s', $this->directory, Strings::substring($keyHash, 0, 2)); - $secondDirectory = sprintf('%s/%s', $firstDirectory, Strings::substring($keyHash, 2, 2)); + $firstDirectory = sprintf('%s/%s', $this->directory, substr($keyHash, 0, 2)); + $secondDirectory = sprintf('%s/%s', $firstDirectory, substr($keyHash, 2, 2)); $filePath = sprintf('%s/%s.php', $secondDirectory, $keyHash); return new CacheFilePaths($firstDirectory, $secondDirectory, $filePath); diff --git a/phpstan.neon b/phpstan.neon index 1a7a0100b49..4a8e16e6551 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -459,8 +459,6 @@ parameters: message: '#Access to an undefined property PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode\:\:\$value#' path: packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php #348 - - '#"@var_export\(new \\Rector\\Caching\\ValueObject\\CacheItem\(\$variableKey, \$data\), true\)" is forbidden to use#' - - message: '#Class with base "StaticTypeMapper" name is already used in "Rector\\PHPStanStaticTypeMapper\\TypeMapper\\StaticTypeMapper", "Rector\\StaticTypeMapper\\StaticTypeMapper"\. Use unique name to make classes easy to recognize#' path: packages/StaticTypeMapper/StaticTypeMapper.php #31 @@ -528,3 +526,27 @@ parameters: - '#Method "refactorParamType\(\)" returns bool type, so the name should start with is/has/was#' - '#Method "decorateReturnWithSpecificType\(\)" returns bool type, so the name should start with is/has/was#' - '#Method "resolveObjectType\(\)" returns bool type, so the name should start with is/has/was#' + + # resolve later + - + message: '#Use explicit names over dynamic ones#' + paths: + - packages/Caching/ValueObject/Storage/FileCacheStorage.php + + # native filesystem calls, required for performance reasons + - + message: '#"@\\unlink\(\$tmpPath\)" is forbidden to use#' + paths: + - packages/Caching/ValueObject/Storage/FileCacheStorage.php + - + message: '#"@\\rename\(\$tmpPath, \$path\)" is forbidden to use#' + paths: + - packages/Caching/ValueObject/Storage/FileCacheStorage.php + - + message: '#"%s" in sprintf\(\) format must be quoted#' + paths: + - packages/Caching/ValueObject/Storage/FileCacheStorage.php + - + message: '#"@\\var_export\(new \\Rector\\Caching\\ValueObject\\CacheItem\(\$variableKey, \$data\), true\)" is forbidden to use#' + paths: + - packages/Caching/ValueObject/Storage/FileCacheStorage.php