2021-06-11 11:03:31 +00:00
< ? php
declare ( strict_types = 1 );
namespace Rector\Caching\ValueObject\Storage ;
2021-08-08 00:26:40 +00:00
use RectorPrefix20210808\Nette\Utils\Random ;
2021-07-26 16:26:09 +00:00
use PHPStan\File\FileWriter ;
2021-08-02 19:35:36 +00:00
use Rector\Caching\Contract\ValueObject\Storage\CacheStorageInterface ;
2021-06-11 11:03:31 +00:00
use Rector\Caching\ValueObject\CacheFilePaths ;
use Rector\Caching\ValueObject\CacheItem ;
2021-08-08 00:26:40 +00:00
use RectorPrefix20210808\Symplify\EasyCodingStandard\Caching\Exception\CachingException ;
use RectorPrefix20210808\Symplify\SmartFileSystem\SmartFileSystem ;
2021-06-11 11:03:31 +00:00
/**
2021-07-26 13:28:02 +00:00
* Inspired by https :// github . com / phpstan / phpstan - src / blob / 1e7 ceae933f07e5a250b61ed94799e6c2ea8daa2 / src / Cache / FileCacheStorage . php
2021-06-11 11:03:31 +00:00
*/
2021-08-02 19:35:36 +00:00
final class FileCacheStorage implements \Rector\Caching\Contract\ValueObject\Storage\CacheStorageInterface
2021-06-11 11:03:31 +00:00
{
/**
* @ var string
*/
private $directory ;
/**
* @ var \Symplify\SmartFileSystem\SmartFileSystem
*/
private $smartFileSystem ;
2021-08-08 00:26:40 +00:00
public function __construct ( string $directory , \RectorPrefix20210808\Symplify\SmartFileSystem\SmartFileSystem $smartFileSystem )
2021-06-11 11:03:31 +00:00
{
$this -> directory = $directory ;
$this -> smartFileSystem = $smartFileSystem ;
}
/**
2021-07-28 07:05:44 +00:00
* @ param string $key
* @ param string $variableKey
2021-06-11 11:03:31 +00:00
*/
2021-07-28 07:05:44 +00:00
public function load ( $key , $variableKey )
2021-06-11 11:03:31 +00:00
{
2021-07-26 13:28:02 +00:00
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 \Rector\Caching\ValueObject\CacheItem ) {
return null ;
}
if ( ! $cacheItem -> isVariableKeyValid ( $variableKey )) {
return null ;
}
return $cacheItem -> getData ();
})( $key , $variableKey );
2021-06-11 11:03:31 +00:00
}
/**
2021-07-28 07:05:44 +00:00
* @ param string $key
* @ param string $variableKey
2021-06-11 11:03:31 +00:00
*/
2021-07-28 07:05:44 +00:00
public function save ( $key , $variableKey , $data ) : void
2021-06-11 11:03:31 +00:00
{
$cacheFilePaths = $this -> getCacheFilePaths ( $key );
$this -> smartFileSystem -> mkdir ( $cacheFilePaths -> getFirstDirectory ());
$this -> smartFileSystem -> mkdir ( $cacheFilePaths -> getSecondDirectory ());
2021-07-26 13:28:02 +00:00
$path = $cacheFilePaths -> getFilePath ();
2021-08-08 00:26:40 +00:00
$tmpPath = \sprintf ( '%s/%s.tmp' , $this -> directory , \RectorPrefix20210808\Nette\Utils\Random :: generate ());
2021-06-11 11:03:31 +00:00
$errorBefore = \error_get_last ();
$exported = @ \var_export ( new \Rector\Caching\ValueObject\CacheItem ( $variableKey , $data ), \true );
$errorAfter = \error_get_last ();
if ( $errorAfter !== null && $errorBefore !== $errorAfter ) {
2021-08-08 00:26:40 +00:00
throw new \RectorPrefix20210808\Symplify\EasyCodingStandard\Caching\Exception\CachingException ( \sprintf ( 'Error occurred while saving item %s (%s) to cache: %s' , $key , $variableKey , $errorAfter [ 'message' ]));
2021-07-26 13:28:02 +00:00
}
// for performance reasons we don't use SmartFileSystem
\PHPStan\File\FileWriter :: write ( $tmpPath , \sprintf ( " <?php declare(strict_types = 1); \n \n return %s; " , $exported ));
$renameSuccess = @ \rename ( $tmpPath , $path );
if ( $renameSuccess ) {
return ;
}
@ \unlink ( $tmpPath );
if ( \DIRECTORY_SEPARATOR === '/' || ! \file_exists ( $path )) {
2021-08-08 00:26:40 +00:00
throw new \RectorPrefix20210808\Symplify\EasyCodingStandard\Caching\Exception\CachingException ( \sprintf ( 'Could not write data to cache file %s.' , $path ));
2021-06-11 11:03:31 +00:00
}
}
2021-07-28 07:05:44 +00:00
/**
* @ param string $key
*/
public function clean ( $key ) : void
2021-06-11 11:03:31 +00:00
{
2021-07-28 07:05:44 +00:00
$cacheFilePaths = $this -> getCacheFilePaths ( $key );
2021-06-11 11:03:31 +00:00
$this -> smartFileSystem -> remove ([ $cacheFilePaths -> getFirstDirectory (), $cacheFilePaths -> getSecondDirectory (), $cacheFilePaths -> getFilePath ()]);
}
public function clear () : void
{
$this -> smartFileSystem -> remove ( $this -> directory );
}
private function getCacheFilePaths ( string $key ) : \Rector\Caching\ValueObject\CacheFilePaths
{
$keyHash = \sha1 ( $key );
2021-07-26 13:28:02 +00:00
$firstDirectory = \sprintf ( '%s/%s' , $this -> directory , \substr ( $keyHash , 0 , 2 ));
$secondDirectory = \sprintf ( '%s/%s' , $firstDirectory , \substr ( $keyHash , 2 , 2 ));
2021-06-11 11:03:31 +00:00
$filePath = \sprintf ( '%s/%s.php' , $secondDirectory , $keyHash );
return new \Rector\Caching\ValueObject\CacheFilePaths ( $firstDirectory , $secondDirectory , $filePath );
}
}