Updated Rector to commit ac81e98fbf

ac81e98fbf move from nette/caching to own cache based on PHPStan (#202)
This commit is contained in:
Tomas Votruba 2021-06-11 11:03:31 +00:00
parent a130d42a04
commit e29462ff33
45 changed files with 293 additions and 2871 deletions

View File

@ -12,6 +12,7 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
__DIR__ . '/../packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php',
__DIR__ . '/../packages/Testing/PHPUnit',
__DIR__ . '/../packages/BetterPhpDocParser/PhpDoc',
__DIR__ . '/../packages/Caching/Cache.php',
__DIR__ . '/../packages/NodeTypeResolver/NodeVisitor/FileNodeVisitor.php',
// used in PHPStan
__DIR__ . '/../packages/NodeTypeResolver/Reflection/BetterReflection/RectorBetterReflectionSourceLocatorFactory.php',

View File

@ -9,7 +9,6 @@ use RectorPrefix20210611\Doctrine\Inflector\Rules\English\InflectorFactory;
use RectorPrefix20210611\Ergebnis\Json\Printer\Printer;
use RectorPrefix20210611\Ergebnis\Json\Printer\PrinterInterface;
use RectorPrefix20210611\Idiosyncratic\EditorConfig\EditorConfig;
use RectorPrefix20210611\Nette\Caching\Cache;
use PhpParser\BuilderFactory;
use PhpParser\Lexer;
use PhpParser\NodeFinder;
@ -27,7 +26,7 @@ use PHPStan\PhpDocParser\Parser\TypeParser;
use PHPStan\Reflection\ReflectionProvider;
use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser;
use Rector\BetterPhpDocParser\PhpDocParser\BetterTypeParser;
use Rector\Caching\Cache\NetteCacheFactory;
use Rector\Caching\CacheFactory;
use Rector\Core\Console\ConsoleApplication;
use Rector\Core\PhpParser\Parser\NikicPhpParserFactory;
use Rector\Core\PhpParser\Parser\PhpParserLexerFactory;
@ -87,7 +86,7 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
// cache
$services->set(\PHPStan\Dependency\DependencyResolver::class)->factory([\RectorPrefix20210611\Symfony\Component\DependencyInjection\Loader\Configurator\service(\Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory::class), 'createDependencyResolver']);
$services->set(\PHPStan\File\FileHelper::class)->factory([\RectorPrefix20210611\Symfony\Component\DependencyInjection\Loader\Configurator\service(\Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory::class), 'createFileHelper']);
$services->set(\RectorPrefix20210611\Nette\Caching\Cache::class)->factory([\RectorPrefix20210611\Symfony\Component\DependencyInjection\Loader\Configurator\service(\Rector\Caching\Cache\NetteCacheFactory::class), 'create']);
$services->set(\Rector\Caching\Cache::class)->factory([\RectorPrefix20210611\Symfony\Component\DependencyInjection\Loader\Configurator\service(\Rector\Caching\CacheFactory::class), 'create']);
// type resolving
$services->set(\Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocator\IntermediateSourceLocator::class);
$services->alias(\PHPStan\PhpDocParser\Parser\TypeParser::class, \Rector\BetterPhpDocParser\PhpDocParser\BetterTypeParser::class);

View File

@ -0,0 +1,39 @@
<?php
declare (strict_types=1);
namespace Rector\Caching;
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
final class Cache
{
/**
* @var \Rector\Caching\ValueObject\Storage\FileCacheStorage
*/
private $fileCacheStorage;
public function __construct(\Rector\Caching\ValueObject\Storage\FileCacheStorage $fileCacheStorage)
{
$this->fileCacheStorage = $fileCacheStorage;
}
/**
* @return mixed|null
*/
public function load(string $key, string $variableKey)
{
return $this->fileCacheStorage->load($key, $variableKey);
}
/**
* @param mixed $data
*/
public function save(string $key, string $variableKey, $data) : void
{
$this->fileCacheStorage->save($key, $variableKey, $data);
}
public function clear() : void
{
$this->fileCacheStorage->clear();
}
public function clean(string $cacheKey) : void
{
$this->fileCacheStorage->clean($cacheKey);
}
}

View File

@ -1,14 +1,13 @@
<?php
declare (strict_types=1);
namespace Rector\Caching\Cache;
namespace Rector\Caching;
use RectorPrefix20210611\Nette\Caching\Cache;
use RectorPrefix20210611\Nette\Caching\Storages\FileStorage;
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Rector\Core\Configuration\Option;
use RectorPrefix20210611\Symplify\PackageBuilder\Parameter\ParameterProvider;
use RectorPrefix20210611\Symplify\SmartFileSystem\SmartFileSystem;
final class NetteCacheFactory
final class CacheFactory
{
/**
* @var \Symplify\PackageBuilder\Parameter\ParameterProvider
@ -23,15 +22,14 @@ final class NetteCacheFactory
$this->parameterProvider = $parameterProvider;
$this->smartFileSystem = $smartFileSystem;
}
public function create() : \RectorPrefix20210611\Nette\Caching\Cache
public function create() : \Rector\Caching\Cache
{
$cacheDirectory = $this->parameterProvider->provideStringParameter(\Rector\Core\Configuration\Option::CACHE_DIR);
// ensure cache directory exists
if (!$this->smartFileSystem->exists($cacheDirectory)) {
$this->smartFileSystem->mkdir($cacheDirectory);
}
$fileStorage = new \RectorPrefix20210611\Nette\Caching\Storages\FileStorage($cacheDirectory);
// namespace is unique per project
return new \RectorPrefix20210611\Nette\Caching\Cache($fileStorage, \getcwd());
$fileCacheStorage = new \Rector\Caching\ValueObject\Storage\FileCacheStorage($cacheDirectory, $this->smartFileSystem);
return new \Rector\Caching\Cache($fileCacheStorage);
}
}

View File

@ -13,7 +13,6 @@ use RectorPrefix20210611\Symfony\Component\DependencyInjection\Loader\PhpFileLoa
use Symplify\SmartFileSystem\SmartFileInfo;
/**
* Inspired by https://github.com/symplify/easy-coding-standard/blob/e598ab54686e416788f28fcfe007fd08e0f371d9/packages/changed-files-detector/src/FileHashComputer.php
* @see \Rector\Caching\Tests\Config\FileHashComputerTest
*/
final class FileHashComputer
{

View File

@ -3,29 +3,27 @@
declare (strict_types=1);
namespace Rector\Caching\Detector;
use RectorPrefix20210611\Nette\Caching\Cache;
use RectorPrefix20210611\Nette\Utils\Strings;
use Rector\Caching\Cache;
use Rector\Caching\Config\FileHashComputer;
use Rector\Caching\Enum\CacheKey;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
* Inspired by https://github.com/symplify/symplify/pull/90/files#diff-72041b2e1029a08930e13d79d298ef11
* @see \Rector\Caching\Tests\Detector\ChangedFilesDetectorTest
*
* @see \Rector\Tests\Caching\Detector\ChangedFilesDetectorTest
*/
final class ChangedFilesDetector
{
/**
* @var string
*/
private const CONFIGURATION_HASH_KEY = 'configuration_hash';
/**
* @var \Rector\Caching\Config\FileHashComputer
*/
private $fileHashComputer;
/**
* @var \Nette\Caching\Cache
* @var \Rector\Caching\Cache
*/
private $cache;
public function __construct(\Rector\Caching\Config\FileHashComputer $fileHashComputer, \RectorPrefix20210611\Nette\Caching\Cache $cache)
public function __construct(\Rector\Caching\Config\FileHashComputer $fileHashComputer, \Rector\Caching\Cache $cache)
{
$this->fileHashComputer = $fileHashComputer;
$this->cache = $cache;
@ -37,24 +35,24 @@ final class ChangedFilesDetector
{
$fileInfoCacheKey = $this->getFileInfoCacheKey($smartFileInfo);
$hash = $this->hashFile($smartFileInfo);
$this->cache->save($fileInfoCacheKey, $hash);
$this->cache->save($fileInfoCacheKey . '_files', $dependentFiles);
$this->cache->save($fileInfoCacheKey, \Rector\Caching\Enum\CacheKey::FILE_HASH_KEY, $hash);
$this->cache->save($fileInfoCacheKey . '_files', \Rector\Caching\Enum\CacheKey::DEPENDENT_FILES_KEY, $dependentFiles);
}
public function hasFileChanged(\Symplify\SmartFileSystem\SmartFileInfo $smartFileInfo) : bool
{
$currentFileHash = $this->hashFile($smartFileInfo);
$fileInfoCacheKey = $this->getFileInfoCacheKey($smartFileInfo);
$cachedValue = $this->cache->load($fileInfoCacheKey);
$cachedValue = $this->cache->load($fileInfoCacheKey, \Rector\Caching\Enum\CacheKey::FILE_HASH_KEY);
return $currentFileHash !== $cachedValue;
}
public function invalidateFile(\Symplify\SmartFileSystem\SmartFileInfo $smartFileInfo) : void
{
$fileInfoCacheKey = $this->getFileInfoCacheKey($smartFileInfo);
$this->cache->remove($fileInfoCacheKey);
$this->cache->clean($fileInfoCacheKey);
}
public function clear() : void
{
$this->cache->clean([\RectorPrefix20210611\Nette\Caching\Cache::ALL => \true]);
$this->cache->clear();
}
/**
* @return SmartFileInfo[]
@ -62,7 +60,7 @@ final class ChangedFilesDetector
public function getDependentFileInfos(\Symplify\SmartFileSystem\SmartFileInfo $fileInfo) : array
{
$fileInfoCacheKey = $this->getFileInfoCacheKey($fileInfo);
$cacheValue = $this->cache->load($fileInfoCacheKey . '_files');
$cacheValue = $this->cache->load($fileInfoCacheKey . '_files', \Rector\Caching\Enum\CacheKey::DEPENDENT_FILES_KEY);
if ($cacheValue === null) {
return [];
}
@ -95,13 +93,13 @@ final class ChangedFilesDetector
}
private function storeConfigurationDataHash(\Symplify\SmartFileSystem\SmartFileInfo $fileInfo, string $configurationHash) : void
{
$key = self::CONFIGURATION_HASH_KEY . '_' . \RectorPrefix20210611\Nette\Utils\Strings::webalize($fileInfo->getRealPath());
$key = \Rector\Caching\Enum\CacheKey::CONFIGURATION_HASH_KEY . '_' . \RectorPrefix20210611\Nette\Utils\Strings::webalize($fileInfo->getRealPath());
$this->invalidateCacheIfConfigurationChanged($key, $configurationHash);
$this->cache->save($key, $configurationHash);
$this->cache->save($key, \Rector\Caching\Enum\CacheKey::CONFIGURATION_HASH_KEY, $configurationHash);
}
private function invalidateCacheIfConfigurationChanged(string $key, string $configurationHash) : void
{
$oldCachedValue = $this->cache->load($key);
$oldCachedValue = $this->cache->load($key, \Rector\Caching\Enum\CacheKey::CONFIGURATION_HASH_KEY);
if ($oldCachedValue === $configurationHash) {
return;
}

View File

@ -0,0 +1,23 @@
<?php
declare (strict_types=1);
namespace Rector\Caching\Enum;
/**
* @enum
*/
final class CacheKey
{
/**
* @var string
*/
public const CONFIGURATION_HASH_KEY = 'configuration_hash';
/**
* @var string
*/
public const FILE_HASH_KEY = 'file_hash';
/**
* @var string
*/
public const DEPENDENT_FILES_KEY = 'dependency_files_key';
}

View File

@ -0,0 +1,38 @@
<?php
declare (strict_types=1);
namespace Rector\Caching\ValueObject;
final class CacheFilePaths
{
/**
* @var string
*/
private $firstDirectory;
/**
* @var string
*/
private $secondDirectory;
/**
* @var string
*/
private $filePath;
public function __construct(string $firstDirectory, string $secondDirectory, string $filePath)
{
$this->firstDirectory = $firstDirectory;
$this->secondDirectory = $secondDirectory;
$this->filePath = $filePath;
}
public function getFirstDirectory() : string
{
return $this->firstDirectory;
}
public function getSecondDirectory() : string
{
return $this->secondDirectory;
}
public function getFilePath() : string
{
return $this->filePath;
}
}

View File

@ -0,0 +1,44 @@
<?php
declare (strict_types=1);
namespace Rector\Caching\ValueObject;
/**
* Inspired by
* https://github.com/phpstan/phpstan-src/commit/eeae2da7999b2e8b7b04542c6175d46f80c6d0b9#diff-6dc14f6222bf150e6840ca44a7126653052a1cedc6a149b4e5c1e1a2c80eacdc
*/
final class CacheItem
{
/**
* @var string
*/
private $variableKey;
private $data;
/**
* @param mixed $data
*/
public function __construct(string $variableKey, $data)
{
$this->variableKey = $variableKey;
$this->data = $data;
}
/**
* @param mixed[] $properties
* @return $this
*/
public static function __set_state(array $properties)
{
return new self($properties['variableKey'], $properties['data']);
}
public function isVariableKeyValid(string $variableKey) : bool
{
return $this->variableKey === $variableKey;
}
/**
* @return mixed
*/
public function getData()
{
return $this->data;
}
}

View File

@ -0,0 +1,88 @@
<?php
declare (strict_types=1);
namespace Rector\Caching\ValueObject\Storage;
use RectorPrefix20210611\Nette\Utils\Random;
use RectorPrefix20210611\Nette\Utils\Strings;
use Rector\Caching\ValueObject\CacheFilePaths;
use Rector\Caching\ValueObject\CacheItem;
use RectorPrefix20210611\Symplify\EasyCodingStandard\Caching\Exception\CachingException;
use RectorPrefix20210611\Symplify\SmartFileSystem\SmartFileSystem;
/**
* Inspired by
* https://github.com/phpstan/phpstan-src/commit/4df7342f3a0aaef4bcd85456dd20ca88d38dd90d#diff-6dc14f6222bf150e6840ca44a7126653052a1cedc6a149b4e5c1e1a2c80eacdc
*/
final class FileCacheStorage
{
/**
* @var string
*/
private $directory;
/**
* @var \Symplify\SmartFileSystem\SmartFileSystem
*/
private $smartFileSystem;
public function __construct(string $directory, \RectorPrefix20210611\Symplify\SmartFileSystem\SmartFileSystem $smartFileSystem)
{
$this->directory = $directory;
$this->smartFileSystem = $smartFileSystem;
}
/**
* @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 \Rector\Caching\ValueObject\CacheItem) {
return null;
}
if (!$cacheItem->isVariableKeyValid($variableKey)) {
return null;
}
return $cacheItem->getData();
}
/**
* @param mixed $data
*/
public function save(string $key, string $variableKey, $data) : void
{
$cacheFilePaths = $this->getCacheFilePaths($key);
$this->smartFileSystem->mkdir($cacheFilePaths->getFirstDirectory());
$this->smartFileSystem->mkdir($cacheFilePaths->getSecondDirectory());
$tmpPath = \sprintf('%s/%s.tmp', $this->directory, \RectorPrefix20210611\Nette\Utils\Random::generate());
$errorBefore = \error_get_last();
$exported = @\var_export(new \Rector\Caching\ValueObject\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 \RectorPrefix20210611\Symplify\EasyCodingStandard\Caching\Exception\CachingException($errorMessage);
}
$variableFileContent = \sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", $exported);
$this->smartFileSystem->dumpFile($tmpPath, $variableFileContent);
$this->smartFileSystem->rename($tmpPath, $cacheFilePaths->getFilePath(), \true);
$this->smartFileSystem->remove($tmpPath);
}
public function clean(string $cacheKey) : void
{
$cacheFilePaths = $this->getCacheFilePaths($cacheKey);
$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);
$firstDirectory = \sprintf('%s/%s', $this->directory, \RectorPrefix20210611\Nette\Utils\Strings::substring($keyHash, 0, 2));
$secondDirectory = \sprintf('%s/%s', $firstDirectory, \RectorPrefix20210611\Nette\Utils\Strings::substring($keyHash, 2, 2));
$filePath = \sprintf('%s/%s.php', $secondDirectory, $keyHash);
return new \Rector\Caching\ValueObject\CacheFilePaths($firstDirectory, $secondDirectory, $filePath);
}
}

View File

@ -6,7 +6,6 @@ namespace Rector\DeadCode\Rector\If_;
use PhpParser\Node;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Instanceof_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\If_;
use PHPStan\Analyser\Scope;
use Rector\Core\NodeManipulator\IfManipulator;

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = '9dea8d8cd82bb640ccad2d583487d1afdd69428d';
public const PACKAGE_VERSION = 'ac81e98fbfb138ffd1b3dd2725ee1c6b7010a22b';
/**
* @var string
*/
public const RELEASE_DATE = '2021-06-11 11:29:21';
public const RELEASE_DATE = '2021-06-11 10:39:28';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20210611\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

View File

@ -3,9 +3,7 @@
declare (strict_types=1);
namespace Rector\Core\FileSystem;
use RectorPrefix20210611\Nette\Caching\Cache;
use RectorPrefix20210611\Nette\Utils\Strings;
use Rector\Core\Configuration\Configuration;
use RectorPrefix20210611\Symfony\Component\Finder\Finder;
use RectorPrefix20210611\Symfony\Component\Finder\SplFileInfo;
use RectorPrefix20210611\Symplify\Skipper\SkipCriteriaResolver\SkippedPathsResolver;
@ -43,22 +41,12 @@ final class FilesFinder
* @var \Symplify\Skipper\SkipCriteriaResolver\SkippedPathsResolver
*/
private $skippedPathsResolver;
/**
* @var \Rector\Core\Configuration\Configuration
*/
private $configuration;
/**
* @var \Nette\Caching\Cache
*/
private $cache;
public function __construct(\Rector\Core\FileSystem\FilesystemTweaker $filesystemTweaker, \RectorPrefix20210611\Symplify\SmartFileSystem\Finder\FinderSanitizer $finderSanitizer, \RectorPrefix20210611\Symplify\SmartFileSystem\FileSystemFilter $fileSystemFilter, \RectorPrefix20210611\Symplify\Skipper\SkipCriteriaResolver\SkippedPathsResolver $skippedPathsResolver, \Rector\Core\Configuration\Configuration $configuration, \RectorPrefix20210611\Nette\Caching\Cache $cache)
public function __construct(\Rector\Core\FileSystem\FilesystemTweaker $filesystemTweaker, \RectorPrefix20210611\Symplify\SmartFileSystem\Finder\FinderSanitizer $finderSanitizer, \RectorPrefix20210611\Symplify\SmartFileSystem\FileSystemFilter $fileSystemFilter, \RectorPrefix20210611\Symplify\Skipper\SkipCriteriaResolver\SkippedPathsResolver $skippedPathsResolver)
{
$this->filesystemTweaker = $filesystemTweaker;
$this->finderSanitizer = $finderSanitizer;
$this->fileSystemFilter = $fileSystemFilter;
$this->skippedPathsResolver = $skippedPathsResolver;
$this->configuration = $configuration;
$this->cache = $cache;
}
/**
* @param string[] $source
@ -66,28 +54,6 @@ final class FilesFinder
* @return SmartFileInfo[]
*/
public function findInDirectoriesAndFiles(array $source, array $suffixes) : array
{
$cacheKey = \md5(\serialize($source) . \serialize($suffixes));
if (!$this->configuration->isCacheEnabled() || $this->configuration->shouldClearCache()) {
$this->cache->clean([\RectorPrefix20210611\Nette\Caching\Cache::ALL => \true]);
return $this->collectFileInfos($source, $suffixes);
}
$loadCache = $this->cache->load($cacheKey);
if ($loadCache) {
$stringFiles = \unserialize($loadCache);
return $this->getSmartFileInfosFromStringFiles($stringFiles);
}
$smartFileInfos = $this->collectFileInfos($source, $suffixes);
$stringFiles = \serialize($this->convertFileInfosToStringFiles($smartFileInfos));
$this->cache->save($cacheKey, $stringFiles);
return $smartFileInfos;
}
/**
* @param string[] $source
* @param string[] $suffixes
* @return SmartFileInfo[]
*/
private function collectFileInfos(array $source, array $suffixes) : array
{
$filesAndDirectories = $this->filesystemTweaker->resolveWithFnmatch($source);
$files = $this->fileSystemFilter->filterFiles($filesAndDirectories);
@ -98,30 +64,6 @@ final class FilesFinder
}
return \array_merge($smartFileInfos, $this->findInDirectories($directories, $suffixes));
}
/**
* @param SmartFileInfo[] $smartFileInfos
* @return string[]
*/
private function convertFileInfosToStringFiles(array $smartFileInfos) : array
{
$files = [];
foreach ($smartFileInfos as $smartFileInfo) {
$files[] = $smartFileInfo->getPathname();
}
return $files;
}
/**
* @param string[] $files
* @return SmartFileInfo[]
*/
private function getSmartFileInfosFromStringFiles(array $files) : array
{
$smartFileInfos = [];
foreach ($files as $file) {
$smartFileInfos[] = new \Symplify\SmartFileSystem\SmartFileInfo($file);
}
return $smartFileInfos;
}
/**
* @param string[] $directories
* @param string[] $suffixes

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9::getLoader();
return ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea::getLoader();

View File

@ -450,23 +450,6 @@ return array(
'RectorPrefix20210611\\Idiosyncratic\\EditorConfig\\Exception\\InvalidValue' => $vendorDir . '/idiosyncratic/editorconfig/src/Exception/InvalidValue.php',
'RectorPrefix20210611\\Idiosyncratic\\EditorConfig\\Section' => $vendorDir . '/idiosyncratic/editorconfig/src/Section.php',
'RectorPrefix20210611\\Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\Bridges\\CacheDI\\CacheExtension' => $vendorDir . '/nette/caching/src/Bridges/CacheDI/CacheExtension.php',
'RectorPrefix20210611\\Nette\\Bridges\\CacheLatte\\CacheMacro' => $vendorDir . '/nette/caching/src/Bridges/CacheLatte/CacheMacro.php',
'RectorPrefix20210611\\Nette\\Caching\\BulkReader' => $vendorDir . '/nette/caching/src/Caching/BulkReader.php',
'RectorPrefix20210611\\Nette\\Caching\\Cache' => $vendorDir . '/nette/caching/src/Caching/Cache.php',
'RectorPrefix20210611\\Nette\\Caching\\IBulkReader' => $vendorDir . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\IStorage' => $vendorDir . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\OutputHelper' => $vendorDir . '/nette/caching/src/Caching/OutputHelper.php',
'RectorPrefix20210611\\Nette\\Caching\\Storage' => $vendorDir . '/nette/caching/src/Caching/Storage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\DevNullStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/DevNullStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\FileStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/FileStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\IJournal' => $vendorDir . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\Journal' => $vendorDir . '/nette/caching/src/Caching/Storages/Journal.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\MemcachedStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/MemcachedStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\MemoryStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/MemoryStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\NewMemcachedStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/NewMemcachedStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\SQLiteJournal' => $vendorDir . '/nette/caching/src/Caching/Storages/SQLiteJournal.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\SQLiteStorage' => $vendorDir . '/nette/caching/src/Caching/Storages/SQLiteStorage.php',
'RectorPrefix20210611\\Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
@ -497,7 +480,6 @@ return array(
'RectorPrefix20210611\\Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php',
'RectorPrefix20210611\\Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php',
'RectorPrefix20210611\\Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php',
'RectorPrefix20210611\\Nette\\Utils\\Finder' => $vendorDir . '/nette/finder/src/Utils/Finder.php',
'RectorPrefix20210611\\Nette\\Utils\\Floats' => $vendorDir . '/nette/utils/src/Utils/Floats.php',
'RectorPrefix20210611\\Nette\\Utils\\Helpers' => $vendorDir . '/nette/utils/src/Utils/Helpers.php',
'RectorPrefix20210611\\Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php',
@ -1579,11 +1561,16 @@ return array(
'Rector\\BetterPhpDocParser\\ValueObject\\Type\\SpacingAwareArrayTypeNode' => $baseDir . '/packages/BetterPhpDocParser/ValueObject/Type/SpacingAwareArrayTypeNode.php',
'Rector\\BetterPhpDocParser\\ValueObject\\Type\\SpacingAwareCallableTypeNode' => $baseDir . '/packages/BetterPhpDocParser/ValueObject/Type/SpacingAwareCallableTypeNode.php',
'Rector\\Caching\\Application\\CachedFileInfoFilterAndReporter' => $baseDir . '/packages/Caching/Application/CachedFileInfoFilterAndReporter.php',
'Rector\\Caching\\Cache\\NetteCacheFactory' => $baseDir . '/packages/Caching/Cache/NetteCacheFactory.php',
'Rector\\Caching\\Cache' => $baseDir . '/packages/Caching/Cache.php',
'Rector\\Caching\\CacheFactory' => $baseDir . '/packages/Caching/CacheFactory.php',
'Rector\\Caching\\Config\\FileHashComputer' => $baseDir . '/packages/Caching/Config/FileHashComputer.php',
'Rector\\Caching\\Detector\\ChangedFilesDetector' => $baseDir . '/packages/Caching/Detector/ChangedFilesDetector.php',
'Rector\\Caching\\Enum\\CacheKey' => $baseDir . '/packages/Caching/Enum/CacheKey.php',
'Rector\\Caching\\FileSystem\\DependencyResolver' => $baseDir . '/packages/Caching/FileSystem/DependencyResolver.php',
'Rector\\Caching\\UnchangedFilesFilter' => $baseDir . '/packages/Caching/UnchangedFilesFilter.php',
'Rector\\Caching\\ValueObject\\CacheFilePaths' => $baseDir . '/packages/Caching/ValueObject/CacheFilePaths.php',
'Rector\\Caching\\ValueObject\\CacheItem' => $baseDir . '/packages/Caching/ValueObject/CacheItem.php',
'Rector\\Caching\\ValueObject\\Storage\\FileCacheStorage' => $baseDir . '/packages/Caching/ValueObject/Storage/FileCacheStorage.php',
'Rector\\CakePHP\\ImplicitNameResolver' => $vendorDir . '/rector/rector-cakephp/src/ImplicitNameResolver.php',
'Rector\\CakePHP\\Naming\\CakePHPFullyQualifiedClassNameResolver' => $vendorDir . '/rector/rector-cakephp/src/Naming/CakePHPFullyQualifiedClassNameResolver.php',
'Rector\\CakePHP\\Rector\\FileWithoutNamespace\\ImplicitShortClassNameUseStatementRector' => $vendorDir . '/rector/rector-cakephp/src/Rector/FileWithoutNamespace/ImplicitShortClassNameUseStatementRector.php',

View File

@ -9,12 +9,12 @@ return array(
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'd507e002f7fce7f0c6dbf1f22edcb902' => $vendorDir . '/tracy/tracy/src/Tracy/functions.php',
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php',
'd507e002f7fce7f0c6dbf1f22edcb902' => $vendorDir . '/tracy/tracy/src/Tracy/functions.php',
'65fec9ebcfbb3cbb4fd0d519687aea01' => $vendorDir . '/danielstjules/stringy/src/Create.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9
class ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit9fbbffeb6d398152232255cef95e7fea::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,19 +42,19 @@ class ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit9fbbffeb6d398152232255cef95e7fea::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequirefd1d68ed85dbe20b26c5f8338bc2c1d9($fileIdentifier, $file);
composerRequire9fbbffeb6d398152232255cef95e7fea($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequirefd1d68ed85dbe20b26c5f8338bc2c1d9($fileIdentifier, $file)
function composerRequire9fbbffeb6d398152232255cef95e7fea($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,18 +4,18 @@
namespace Composer\Autoload;
class ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9
class ComposerStaticInit9fbbffeb6d398152232255cef95e7fea
{
public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'd507e002f7fce7f0c6dbf1f22edcb902' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/functions.php',
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php',
'd507e002f7fce7f0c6dbf1f22edcb902' => __DIR__ . '/..' . '/tracy/tracy/src/Tracy/functions.php',
'65fec9ebcfbb3cbb4fd0d519687aea01' => __DIR__ . '/..' . '/danielstjules/stringy/src/Create.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
@ -805,23 +805,6 @@ class ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9
'RectorPrefix20210611\\Idiosyncratic\\EditorConfig\\Exception\\InvalidValue' => __DIR__ . '/..' . '/idiosyncratic/editorconfig/src/Exception/InvalidValue.php',
'RectorPrefix20210611\\Idiosyncratic\\EditorConfig\\Section' => __DIR__ . '/..' . '/idiosyncratic/editorconfig/src/Section.php',
'RectorPrefix20210611\\Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\Bridges\\CacheDI\\CacheExtension' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheDI/CacheExtension.php',
'RectorPrefix20210611\\Nette\\Bridges\\CacheLatte\\CacheMacro' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheLatte/CacheMacro.php',
'RectorPrefix20210611\\Nette\\Caching\\BulkReader' => __DIR__ . '/..' . '/nette/caching/src/Caching/BulkReader.php',
'RectorPrefix20210611\\Nette\\Caching\\Cache' => __DIR__ . '/..' . '/nette/caching/src/Caching/Cache.php',
'RectorPrefix20210611\\Nette\\Caching\\IBulkReader' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\IStorage' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\OutputHelper' => __DIR__ . '/..' . '/nette/caching/src/Caching/OutputHelper.php',
'RectorPrefix20210611\\Nette\\Caching\\Storage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\DevNullStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/DevNullStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\FileStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/FileStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\IJournal' => __DIR__ . '/..' . '/nette/caching/src/compatibility.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\Journal' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/Journal.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\MemcachedStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/MemcachedStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\MemoryStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/MemoryStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\NewMemcachedStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/NewMemcachedStorage.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\SQLiteJournal' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/SQLiteJournal.php',
'RectorPrefix20210611\\Nette\\Caching\\Storages\\SQLiteStorage' => __DIR__ . '/..' . '/nette/caching/src/Caching/Storages/SQLiteStorage.php',
'RectorPrefix20210611\\Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
'RectorPrefix20210611\\Nette\\FileNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
@ -852,7 +835,6 @@ class ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9
'RectorPrefix20210611\\Nette\\Utils\\Callback' => __DIR__ . '/..' . '/nette/utils/src/Utils/Callback.php',
'RectorPrefix20210611\\Nette\\Utils\\DateTime' => __DIR__ . '/..' . '/nette/utils/src/Utils/DateTime.php',
'RectorPrefix20210611\\Nette\\Utils\\FileSystem' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileSystem.php',
'RectorPrefix20210611\\Nette\\Utils\\Finder' => __DIR__ . '/..' . '/nette/finder/src/Utils/Finder.php',
'RectorPrefix20210611\\Nette\\Utils\\Floats' => __DIR__ . '/..' . '/nette/utils/src/Utils/Floats.php',
'RectorPrefix20210611\\Nette\\Utils\\Helpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/Helpers.php',
'RectorPrefix20210611\\Nette\\Utils\\Html' => __DIR__ . '/..' . '/nette/utils/src/Utils/Html.php',
@ -1934,11 +1916,16 @@ class ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9
'Rector\\BetterPhpDocParser\\ValueObject\\Type\\SpacingAwareArrayTypeNode' => __DIR__ . '/../..' . '/packages/BetterPhpDocParser/ValueObject/Type/SpacingAwareArrayTypeNode.php',
'Rector\\BetterPhpDocParser\\ValueObject\\Type\\SpacingAwareCallableTypeNode' => __DIR__ . '/../..' . '/packages/BetterPhpDocParser/ValueObject/Type/SpacingAwareCallableTypeNode.php',
'Rector\\Caching\\Application\\CachedFileInfoFilterAndReporter' => __DIR__ . '/../..' . '/packages/Caching/Application/CachedFileInfoFilterAndReporter.php',
'Rector\\Caching\\Cache\\NetteCacheFactory' => __DIR__ . '/../..' . '/packages/Caching/Cache/NetteCacheFactory.php',
'Rector\\Caching\\Cache' => __DIR__ . '/../..' . '/packages/Caching/Cache.php',
'Rector\\Caching\\CacheFactory' => __DIR__ . '/../..' . '/packages/Caching/CacheFactory.php',
'Rector\\Caching\\Config\\FileHashComputer' => __DIR__ . '/../..' . '/packages/Caching/Config/FileHashComputer.php',
'Rector\\Caching\\Detector\\ChangedFilesDetector' => __DIR__ . '/../..' . '/packages/Caching/Detector/ChangedFilesDetector.php',
'Rector\\Caching\\Enum\\CacheKey' => __DIR__ . '/../..' . '/packages/Caching/Enum/CacheKey.php',
'Rector\\Caching\\FileSystem\\DependencyResolver' => __DIR__ . '/../..' . '/packages/Caching/FileSystem/DependencyResolver.php',
'Rector\\Caching\\UnchangedFilesFilter' => __DIR__ . '/../..' . '/packages/Caching/UnchangedFilesFilter.php',
'Rector\\Caching\\ValueObject\\CacheFilePaths' => __DIR__ . '/../..' . '/packages/Caching/ValueObject/CacheFilePaths.php',
'Rector\\Caching\\ValueObject\\CacheItem' => __DIR__ . '/../..' . '/packages/Caching/ValueObject/CacheItem.php',
'Rector\\Caching\\ValueObject\\Storage\\FileCacheStorage' => __DIR__ . '/../..' . '/packages/Caching/ValueObject/Storage/FileCacheStorage.php',
'Rector\\CakePHP\\ImplicitNameResolver' => __DIR__ . '/..' . '/rector/rector-cakephp/src/ImplicitNameResolver.php',
'Rector\\CakePHP\\Naming\\CakePHPFullyQualifiedClassNameResolver' => __DIR__ . '/..' . '/rector/rector-cakephp/src/Naming/CakePHPFullyQualifiedClassNameResolver.php',
'Rector\\CakePHP\\Rector\\FileWithoutNamespace\\ImplicitShortClassNameUseStatementRector' => __DIR__ . '/..' . '/rector/rector-cakephp/src/Rector/FileWithoutNamespace/ImplicitShortClassNameUseStatementRector.php',
@ -3876,9 +3863,9 @@ class ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitfd1d68ed85dbe20b26c5f8338bc2c1d9::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit9fbbffeb6d398152232255cef95e7fea::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit9fbbffeb6d398152232255cef95e7fea::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit9fbbffeb6d398152232255cef95e7fea::$classMap;
}, null, ClassLoader::class);
}

View File

@ -500,150 +500,6 @@
},
"install-path": "..\/idiosyncratic\/editorconfig"
},
{
"name": "nette\/caching",
"version": "v3.1.1",
"version_normalized": "3.1.1.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/nette\/caching.git",
"reference": "3e771c589dee414724be473c24ad16dae50c1960"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/nette\/caching\/zipball\/3e771c589dee414724be473c24ad16dae50c1960",
"reference": "3e771c589dee414724be473c24ad16dae50c1960",
"shasum": ""
},
"require": {
"nette\/finder": "^2.4 || ^3.0",
"nette\/utils": "^2.4 || ^3.0",
"php": ">=7.2 <8.1"
},
"require-dev": {
"latte\/latte": "^2.10",
"nette\/di": "^v3.0",
"nette\/tester": "^2.0",
"phpstan\/phpstan": "^0.12",
"tracy\/tracy": "^2.4"
},
"suggest": {
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
},
"time": "2021-03-06T14:07:38+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"installation-source": "dist",
"autoload": {
"classmap": [
"src\/"
]
},
"notification-url": "https:\/\/packagist.org\/downloads\/",
"license": [
"BSD-3-Clause",
"GPL-2.0-only",
"GPL-3.0-only"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https:\/\/davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https:\/\/nette.org\/contributors"
}
],
"description": "\u23f1 Nette Caching: library with easy-to-use API and many cache backends.",
"homepage": "https:\/\/nette.org",
"keywords": [
"cache",
"journal",
"memcached",
"nette",
"sqlite"
],
"support": {
"issues": "https:\/\/github.com\/nette\/caching\/issues",
"source": "https:\/\/github.com\/nette\/caching\/tree\/v3.1.1"
},
"install-path": "..\/nette\/caching"
},
{
"name": "nette\/finder",
"version": "v2.5.2",
"version_normalized": "2.5.2.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/nette\/finder.git",
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/nette\/finder\/zipball\/4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
"shasum": ""
},
"require": {
"nette\/utils": "^2.4 || ^3.0",
"php": ">=7.1"
},
"conflict": {
"nette\/nette": "<2.2"
},
"require-dev": {
"nette\/tester": "^2.0",
"phpstan\/phpstan": "^0.12",
"tracy\/tracy": "^2.3"
},
"time": "2020-01-03T20:35:40+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
}
},
"installation-source": "dist",
"autoload": {
"classmap": [
"src\/"
]
},
"notification-url": "https:\/\/packagist.org\/downloads\/",
"license": [
"BSD-3-Clause",
"GPL-2.0",
"GPL-3.0"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https:\/\/davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https:\/\/nette.org\/contributors"
}
],
"description": "\ud83d\udd0d Nette Finder: find files and directories with an intuitive API.",
"homepage": "https:\/\/nette.org",
"keywords": [
"filesystem",
"glob",
"iterator",
"nette"
],
"support": {
"issues": "https:\/\/github.com\/nette\/finder\/issues",
"source": "https:\/\/github.com\/nette\/finder\/tree\/v2.5.2"
},
"install-path": "..\/nette\/finder"
},
{
"name": "nette\/neon",
"version": "v3.2.2",

File diff suppressed because one or more lines are too long

View File

@ -1,57 +0,0 @@
{
"name": "nette\/caching",
"description": "\u23f1 Nette Caching: library with easy-to-use API and many cache backends.",
"keywords": [
"nette",
"cache",
"journal",
"sqlite",
"memcached"
],
"homepage": "https:\/\/nette.org",
"license": [
"BSD-3-Clause",
"GPL-2.0-only",
"GPL-3.0-only"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https:\/\/davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https:\/\/nette.org\/contributors"
}
],
"require": {
"php": ">=7.2 <8.1",
"nette\/finder": "^2.4 || ^3.0",
"nette\/utils": "^2.4 || ^3.0"
},
"require-dev": {
"nette\/tester": "^2.0",
"nette\/di": "^v3.0",
"latte\/latte": "^2.10",
"tracy\/tracy": "^2.4",
"phpstan\/phpstan": "^0.12"
},
"suggest": {
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
},
"autoload": {
"classmap": [
"src\/"
]
},
"minimum-stability": "dev",
"scripts": {
"phpstan": "phpstan analyse",
"tester": "tester tests -s"
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
}
}

View File

@ -1,33 +0,0 @@
How to contribute & use the issue tracker
=========================================
Nette welcomes your contributions. There are several ways to help out:
* Create an issue on GitHub, if you have found a bug
* Write test cases for open bug issues
* Write fixes for open bug/feature issues, preferably with test cases included
* Contribute to the [documentation](https://nette.org/en/writing)
Issues
------
Please **do not use the issue tracker to ask questions**. We will be happy to help you
on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette).
A good bug report shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report.
**Feature requests** are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature.
Contributing
------------
If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing).
The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them.
Please do not fix whitespace, format code, or make a purely cosmetic patch.
Thanks! :heart:

View File

@ -1,60 +0,0 @@
Licenses
========
Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.
You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.
Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.
New BSD License
---------------
Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of "Nette Framework" nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.
GNU General Public License
--------------------------
GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)

View File

@ -1,390 +0,0 @@
Nette Caching
=============
[![Downloads this Month](https://img.shields.io/packagist/dm/nette/caching.svg)](https://packagist.org/packages/nette/caching)
[![Tests](https://github.com/nette/caching/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/caching/actions)
[![Coverage Status](https://coveralls.io/repos/github/nette/caching/badge.svg?branch=master)](https://coveralls.io/github/nette/caching?branch=master)
[![Latest Stable Version](https://poser.pugx.org/nette/caching/v/stable)](https://github.com/nette/caching/releases)
[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/caching/blob/master/license.md)
Introduction
============
Cache accelerates your application by storing data - once hardly retrieved - for future use.
Documentation can be found on the [website](https://doc.nette.org/caching).
[Support Me](https://github.com/sponsors/dg)
--------------------------------------------
Do you like Nette Caching? Are you looking forward to the new features?
[![Buy me a coffee](https://files.nette.org/icons/donation-3.svg)](https://github.com/sponsors/dg)
Thank you!
Installation
------------
```
composer require nette/caching
```
It requires PHP version 7.2 and supports PHP up to 8.0.
Basic Usage
===========
The center of work with the cache is the object [Nette\Caching\Cache](https://api.nette.org/3.0/Nette/Caching/Cache.html). We create its instance and pass the so-called storage to the constructor as a parameter. Which is an object representing the place where the data will be physically stored (database, Memcached, files on disk, ...). You will find out all the essentials in [section Storages](#Storages).
For the following examples, suppose we have an alias `Cache` and a storage in the variable `$storage`.
```php
use Nette\Caching\Cache;
$storage // instance of Nette\Caching\IStorage
```
The cache is actually a *keyvalue store*, so we read and write data under keys just like associative arrays. Applications consist of a number of independent parts, and if they all used one storage (for idea: one directory on a disk), sooner or later there would be a key collision. The Nette Framework solves the problem by dividing the entire space into namespaces (subdirectories). Each part of the program then uses its own space with a unique name and no collisions can occur.
The name of the space is specified as the second parameter of the constructor of the Cache class:
```php
$cache = new Cache($storage, 'Full Html Pages');
```
We can now use object `$cache` to read and write from the cache. The method `load()` is used for both. The first argument is the key and the second is the PHP callback, which is called when the key is not found in the cache. The callback generates a value, returns it and caches it:
```php
$value = $cache->load($key, function () use ($key) {
$computedValue = ...; // heavy computations
return $computedValue;
});
```
If the second parameter is not specified `$value = $cache->load($key)`, the `null` is returned if the item is not in the cache.
The great thing is that any serializable structures can be cached, not only strings. And the same applies for keys.
The item is cleared from the cache using method `remove()`:
```php
$cache->remove($key);
```
You can also cache an item using method `$cache->save($key, $value, array $dependencies = [])`. However, the above method using `load()` is preferred.
Memoization
===========
Memoization means caching the result of a function or method so you can use it next time instead of calculating the same thing again and again.
Methods and functions can be called memoized using `call(callable $callback, ...$args)`:
```php
$result = $cache->call('gethostbyaddr', $ip);
```
The function `gethostbyaddr()` is called only once for each parameter `$ip` and the next time the value from the cache will be returned.
It is also possible to create a memoized wrapper for a method or function that can be called later:
```php
function factorial($num)
{
return ...;
}
$memoizedFactorial = $cache->wrap('factorial');
$result = $memoizedFactorial(5); // counts it
$result = $memoizedFactorial(5); // returns it from cache
```
Expiration & Invalidation
=========================
With caching, it is necessary to address the question that some of the previously saved data will become invalid over time. Nette Framework provides a mechanism, how to limit the validity of data and how to delete them in a controlled way ("to invalidate them", using the framework's terminology).
The validity of the data is set at the time of saving using the third parameter of the method `save()`, eg:
```php
$cache->save($key, $value, [
Cache::EXPIRE => '20 minutes',
]);
```
Or using the `$dependencies` parameter passed by reference to the callback in the `load()` method, eg:
```php
$value = $cache->load($key, function (&$dependencies) {
$dependencies[Cache::EXPIRE] = '20 minutes';
return ...;
]);
```
In the following examples, we will assume the second variant and thus the existence of a variable `$dependencies`.
Expiration
----------
The simplest exiration is the time limit. Here's how to cache data valid for 20 minutes:
```php
// it also accepts the number of seconds or the UNIX timestamp
$dependencies[Cache::EXPIRE] = '20 minutes';
```
If we want to extend the validity period with each reading, it can be achieved this way, but beware, this will increase the cache overhead:
```php
$dependencies[Cache::SLIDING] = true;
```
The handy option is the ability to let the data expire when a particular file is changed or one of several files. This can be used, for example, for caching data resulting from procession these files. Use absolute paths.
```php
$dependencies[Cache::FILES] = '/path/to/data.yaml';
// nebo
$dependencies[Cache::FILES] = ['/path/to/data1.yaml', '/path/to/data2.yaml'];
```
We can let an item in the cache expired when another item (or one of several others) expires. This can be used when we cache the entire HTML page and fragments of it under other keys. Once the snippet changes, the entire page becomes invalid. If we have fragments stored under keys such as `frag1` and `frag2`, we will use:
```php
$dependencies[Cache::ITEMS] = ['frag1', 'frag2'];
```
Expiration can also be controlled using custom functions or static methods, which always decide when reading whether the item is still valid. For example, we can let the item expire whenever the PHP version changes. We will create a function that compares the current version with the parameter, and when saving we will add an array in the form `[function name, ...arguments]` to the dependencies:
```php
function checkPhpVersion($ver): bool
{
return $ver === PHP_VERSION_ID;
}
$dependencies[Cache::CALLBACKS] = [
['checkPhpVersion', PHP_VERSION_ID] // expire when checkPhpVersion(...) === false
];
```
Of course, all criteria can be combined. The cache then expires when at least one criterion is not met.
```php
$dependencies[Cache::EXPIRE] = '20 minutes';
$dependencies[Cache::FILES] = '/path/to/data.yaml';
```
Invalidation using Tags
-----------------------
Tags are a very useful invalidation tool. We can assign a list of tags, which are arbitrary strings, to each item stored in the cache. For example, suppose we have an HTML page with an article and comments, which we want to cache. So we specify tags when saving to cache:
```php
$dependencies[Cache::TAGS] = ["article/$articleId", "comments/$articleId"];
```
Now, let's move to the administration. Here we have a form for article editing. Together with saving the article to a database, we call the `clean()` command, which will delete cached items by tag:
```php
$cache->clean([
Cache::TAGS => ["article/$articleId"],
]);
```
Likewise, in the place of adding a new comment (or editing a comment), we will not forget to invalidate the relevant tag:
```php
$cache->clean([
Cache::TAGS => ["comments/$articleId"],
]);
```
What have we achieved? That our HTML cache will be invalidated (deleted) whenever the article or comments change. When editing an article with ID = 10, the tag `article/10` is forced to be invalidated and the HTML page carrying the tag is deleted from the cache. The same happens when you insert a new comment under the relevant article.
Tags require [Journal](#Journal).
Invalidation by Priority
------------------------
We can set the priority for individual items in the cache, and it will be possible to delete them in a controlled way when, for example, the cache exceeds a certain size:
```php
$dependencies[Cache::PRIORITY] = 50;
```
Delete all items with a priority equal to or less than 100:
```php
$cache->clean([
Cache::PRIORITY => 100,
]);
```
Priorities require so-called [Journal](#Journal).
Clear Cache
-----------
The `Cache::ALL` parameter clears everything:
```php
$cache->clean([
Cache::ALL => true,
]);
```
Bulk Reading
============
For bulk reading and writing to cache, the `bulkLoad()` method is used, where we pass an array of keys and obtain an array of values:
```php
$values = $cache->bulkLoad($keys);
```
Method `bulkLoad()` works similarly to `load()` with the second callback parameter, to which the key of the generated item is passed:
```php
$values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
$computedValue = ...; // heavy computations
return $computedValue;
});
```
Output Caching
==============
The output can be captured and cached very elegantly:
```php
if ($capture = $cache->start($key)) {
echo ... // printing some data
$capture->end(); // save the output to the cache
}
```
In case that the output is already present in the cache, the `start()` method prints it and returns `null`, so the condition will not be executed. Otherwise, it starts to buffer the output and returns the `$capture` object using which we finally save the data to the cache.
Caching in Latte
================
Caching in templates [Latte](https://latte.nette.org) is very easy, just wrap part of the template with tags `{cache}...{/cache}`. The cache is automatically invalidated when the source template changes (including any included templates within the `{cache}` tags). Tags `{cache}` can be nested, and when a nested block is invalidated (for example, by a tag), the parent block is also invalidated.
In the tag it is possible to specify the keys to which the cache will be bound (here the variable `$id`) and set the expiration and [invalidation tags](#invalidation-using-tags).
```html
{cache $id, expire => '20 minutes', tags => [tag1, tag2]}
...
{/cache}
```
All parameters are optional, so you don't have to specify expiration, tags, or keys.
The use of the cache can also be conditioned by `if` - the content will then be cached only if the condition is met:
```html
{cache $id, if => !$form->isSubmitted()}
{$form}
{/cache}
```
Storages
========
A storage is an object that represents where data is physically stored. We can use a database, a Memcached server, or the most available storage, which are files on disk.
Storage | Description
--------|----------------------
FileStorage | default storage with saving to files on disk
MemcachedStorage | uses the `Memcached` server
MemoryStorage | data are temporarily in memory
SQLiteStorage | data is stored in SQLite database
DevNullStorage | data aren't stored - for testing purposes
FileStorage
-----------
Writes the cache to files on disk. The storage `Nette\Caching\Storages\FileStorage` is very well optimized for performance and above all ensures full atomicity of operations. What does it mean? That when using the cache, it cannot happen that we read a file that has not yet been completely written by another thread, or that someone would delete it "under your hands". The use of the cache is therefore completely safe.
This storage also has an important built-in feature that prevents an extreme increase in CPU usage when the cache is cleared or cold (ie not created). This is [cache stampede](https://en.wikipedia.org/wiki/Cache_stampede) prevention.
It happens that at one moment there are several concurrent requests that want the same thing from the cache (eg the result of an expensive SQL query) and because it is not cached, all processes start executing the same SQL query.
The processor load is multiplied and it can even happen that no thread can respond within the time limit, the cache is not created and the application crashes.
Fortunately, the cache in Nette works in such a way that when there are multiple concurrent requests for one item, it is generated only by the first thread, the others wait and then use the generated result.
Example of creating a FileStorage:
```php
// the storage will be the directory '/path/to/temp' on the disk
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp');
```
MemcachedStorage
----------------
The server [Memcached](https://memcached.org) is a high-performance distributed storage system whose adapter is `Nette\Caching\Storages\MemcachedStorage`.
Requires PHP extension `memcached`.
```php
$storage = new Nette\Caching\Storages\MemcachedStorage('10.0.0.158');
```
MemoryStorage
-------------
`Nette\Caching\Storages\MemoryStorage` is a storage that stores data in a PHP array and is thus lost when the request is terminated.
```php
$storage = new Nette\Caching\Storages\MemoryStorage;
```
SQLiteStorage
-------------
The SQLite database and adapter `Nette\Caching\Storages\SQLiteStorage` offer a way to cache in a single file on disk. The configuration will specify the path to this file.
Requires PHP extensions `pdo` and `pdo_sqlite`.
```php
$storage = new Nette\Caching\Storages\SQLiteStorage('/path/to/cache.sdb');
```
DevNullStorage
--------------
A special implementation of storage is `Nette\Caching\Storages\DevNullStorage`, which does not actually store data at all. It is therefore suitable for testing if we want to eliminate the effect of the cache.
```php
$storage = new Nette\Caching\Storages\DevNullStorage;
```
Journal
=======
Nette stores tags and priorities in a so-called journal. By default, SQLite and file `journal.s3db` are used for this, and **PHP extensions `pdo` and `pdo_sqlite` are required.**
If you like Nette, **[please make a donation now](https://github.com/sponsors/dg)**. Thank you!

View File

@ -1,41 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Bridges\CacheDI;
use RectorPrefix20210611\Nette;
/**
* Cache extension for Nette DI.
*/
final class CacheExtension extends \RectorPrefix20210611\Nette\DI\CompilerExtension
{
/** @var string */
private $tempDir;
public function __construct(string $tempDir)
{
$this->tempDir = $tempDir;
}
public function loadConfiguration()
{
$dir = $this->tempDir . '/cache';
\RectorPrefix20210611\Nette\Utils\FileSystem::createDir($dir);
if (!\is_writable($dir)) {
throw new \RectorPrefix20210611\Nette\InvalidStateException("Make directory '{$dir}' writable.");
}
$builder = $this->getContainerBuilder();
if (\extension_loaded('pdo_sqlite')) {
$builder->addDefinition($this->prefix('journal'))->setType(\RectorPrefix20210611\Nette\Caching\Storages\Journal::class)->setFactory(\RectorPrefix20210611\Nette\Caching\Storages\SQLiteJournal::class, [$dir . '/journal.s3db']);
}
$builder->addDefinition($this->prefix('storage'))->setType(\RectorPrefix20210611\Nette\Caching\Storage::class)->setFactory(\RectorPrefix20210611\Nette\Caching\Storages\FileStorage::class, [$dir]);
if ($this->name === 'cache') {
if (\extension_loaded('pdo_sqlite')) {
$builder->addAlias('nette.cacheJournal', $this->prefix('journal'));
}
$builder->addAlias('cacheStorage', $this->prefix('storage'));
}
}
}

View File

@ -1,127 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Bridges\CacheLatte;
use RectorPrefix20210611\Latte;
use RectorPrefix20210611\Nette;
use RectorPrefix20210611\Nette\Caching\Cache;
/**
* Macro {cache} ... {/cache}
*/
final class CacheMacro implements \RectorPrefix20210611\Latte\IMacro
{
use Nette\SmartObject;
/** @var bool */
private $used;
/**
* Initializes before template parsing.
* @return void
*/
public function initialize()
{
$this->used = \false;
}
/**
* Finishes template parsing.
* @return array(prolog, epilog)
*/
public function finalize()
{
if ($this->used) {
return ['Nette\\Bridges\\CacheLatte\\CacheMacro::initRuntime($this);'];
}
}
/**
* New node is found.
* @return bool
*/
public function nodeOpened(\RectorPrefix20210611\Latte\MacroNode $node)
{
if ($node->modifiers) {
throw new \RectorPrefix20210611\Latte\CompileException('Modifiers are not allowed in ' . $node->getNotation());
}
$this->used = \true;
$node->empty = \false;
$node->openingCode = \RectorPrefix20210611\Latte\PhpWriter::using($node)->write('<?php if (Nette\\Bridges\\CacheLatte\\CacheMacro::createCache($this->global->cacheStorage, %var, $this->global->cacheStack, %node.array?)) /* line %var */ try { ?>', \RectorPrefix20210611\Nette\Utils\Random::generate(), $node->startLine);
}
/**
* Node is closed.
* @return void
*/
public function nodeClosed(\RectorPrefix20210611\Latte\MacroNode $node)
{
$node->closingCode = \RectorPrefix20210611\Latte\PhpWriter::using($node)->write('<?php
Nette\\Bridges\\CacheLatte\\CacheMacro::endCache($this->global->cacheStack, %node.array?) /* line %var */;
} catch (\\Throwable $ʟ_e) {
Nette\\Bridges\\CacheLatte\\CacheMacro::rollback($this->global->cacheStack); throw $ʟ_e;
} ?>', $node->startLine);
}
/********************* run-time helpers ****************d*g**/
public static function initRuntime(\RectorPrefix20210611\Latte\Runtime\Template $template) : void
{
if (!empty($template->global->cacheStack)) {
$file = (new \ReflectionClass($template))->getFileName();
if (@\is_file($file)) {
// @ - may trigger error
\end($template->global->cacheStack)->dependencies[\RectorPrefix20210611\Nette\Caching\Cache::FILES][] = $file;
}
}
}
/**
* Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started.
* @return Nette\Caching\OutputHelper|\stdClass
*/
public static function createCache(\RectorPrefix20210611\Nette\Caching\Storage $cacheStorage, string $key, ?array &$parents, array $args = null)
{
if ($args) {
if (\array_key_exists('if', $args) && !$args['if']) {
return $parents[] = new \stdClass();
}
$key = \array_merge([$key], \array_intersect_key($args, \range(0, \count($args))));
}
if ($parents) {
\end($parents)->dependencies[\RectorPrefix20210611\Nette\Caching\Cache::ITEMS][] = $key;
}
$cache = new \RectorPrefix20210611\Nette\Caching\Cache($cacheStorage, 'Nette.Templating.Cache');
if ($helper = $cache->start($key)) {
$parents[] = $helper;
}
return $helper;
}
/**
* Ends the output cache.
* @param Nette\Caching\OutputHelper[] $parents
*/
public static function endCache(array &$parents, array $args = null) : void
{
$helper = \array_pop($parents);
if (!$helper instanceof \RectorPrefix20210611\Nette\Caching\OutputHelper) {
return;
}
if (isset($args['dependencies'])) {
$args += $args['dependencies']();
}
if (isset($args['expire'])) {
$args['expiration'] = $args['expire'];
// back compatibility
}
$helper->dependencies[\RectorPrefix20210611\Nette\Caching\Cache::TAGS] = $args['tags'] ?? null;
$helper->dependencies[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION] = $args['expiration'] ?? '+ 7 days';
$helper->end();
}
/**
* @param Nette\Caching\OutputHelper[] $parents
*/
public static function rollback(array &$parents) : void
{
$helper = \array_pop($parents);
if ($helper instanceof \RectorPrefix20210611\Nette\Caching\OutputHelper) {
$helper->rollback();
}
}
}

View File

@ -1,21 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching;
/**
* Cache storage with a bulk read support.
*/
interface BulkReader
{
/**
* Reads from cache in bulk.
* @return array key => value pairs, missing items are omitted
*/
function bulkRead(array $keys) : array;
}
\class_exists(\RectorPrefix20210611\Nette\Caching\IBulkReader::class);

View File

@ -1,297 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching;
use RectorPrefix20210611\Nette;
/**
* Implements the cache for a application.
*/
class Cache
{
use Nette\SmartObject;
/** dependency */
public const PRIORITY = 'priority', EXPIRATION = 'expire', EXPIRE = 'expire', SLIDING = 'sliding', TAGS = 'tags', FILES = 'files', ITEMS = 'items', CONSTS = 'consts', CALLBACKS = 'callbacks', NAMESPACES = 'namespaces', ALL = 'all';
/** @internal */
public const NAMESPACE_SEPARATOR = "\0";
/** @var Storage */
private $storage;
/** @var string */
private $namespace;
public function __construct(\RectorPrefix20210611\Nette\Caching\Storage $storage, string $namespace = null)
{
$this->storage = $storage;
$this->namespace = $namespace . self::NAMESPACE_SEPARATOR;
}
/**
* Returns cache storage.
*/
public final function getStorage() : \RectorPrefix20210611\Nette\Caching\Storage
{
return $this->storage;
}
/**
* Returns cache namespace.
*/
public final function getNamespace() : string
{
return (string) \substr($this->namespace, 0, -1);
}
/**
* Returns new nested cache object.
* @return static
*/
public function derive(string $namespace)
{
return new static($this->storage, $this->namespace . $namespace);
}
/**
* Reads the specified item from the cache or generate it.
* @param mixed $key
* @return mixed
*/
public function load($key, callable $generator = null)
{
$storageKey = $this->generateKey($key);
$data = $this->storage->read($storageKey);
if ($data === null && $generator) {
$this->storage->lock($storageKey);
try {
$data = $generator(...[&$dependencies]);
} catch (\Throwable $e) {
$this->storage->remove($storageKey);
throw $e;
}
$this->save($key, $data, $dependencies);
}
return $data;
}
/**
* Reads multiple items from the cache.
*/
public function bulkLoad(array $keys, callable $generator = null) : array
{
if (\count($keys) === 0) {
return [];
}
foreach ($keys as $key) {
if (!\is_scalar($key)) {
throw new \RectorPrefix20210611\Nette\InvalidArgumentException('Only scalar keys are allowed in bulkLoad()');
}
}
$result = [];
if (!$this->storage instanceof \RectorPrefix20210611\Nette\Caching\BulkReader) {
foreach ($keys as $key) {
$result[$key] = $this->load($key, $generator ? function (&$dependencies) use($key, $generator) {
return $generator(...[$key, &$dependencies]);
} : null);
}
return $result;
}
$storageKeys = \array_map([$this, 'generateKey'], $keys);
$cacheData = $this->storage->bulkRead($storageKeys);
foreach ($keys as $i => $key) {
$storageKey = $storageKeys[$i];
if (isset($cacheData[$storageKey])) {
$result[$key] = $cacheData[$storageKey];
} elseif ($generator) {
$result[$key] = $this->load($key, function (&$dependencies) use($key, $generator) {
return $generator(...[$key, &$dependencies]);
});
} else {
$result[$key] = null;
}
}
return $result;
}
/**
* Writes item into the cache.
* Dependencies are:
* - Cache::PRIORITY => (int) priority
* - Cache::EXPIRATION => (timestamp) expiration
* - Cache::SLIDING => (bool) use sliding expiration?
* - Cache::TAGS => (array) tags
* - Cache::FILES => (array|string) file names
* - Cache::ITEMS => (array|string) cache items
* - Cache::CONSTS => (array|string) cache items
*
* @param mixed $key
* @param mixed $data
* @return mixed value itself
* @throws Nette\InvalidArgumentException
*/
public function save($key, $data, array $dependencies = null)
{
$key = $this->generateKey($key);
if ($data instanceof \Closure) {
$this->storage->lock($key);
try {
$data = $data(...[&$dependencies]);
} catch (\Throwable $e) {
$this->storage->remove($key);
throw $e;
}
}
if ($data === null) {
$this->storage->remove($key);
} else {
$dependencies = $this->completeDependencies($dependencies);
if (isset($dependencies[self::EXPIRATION]) && $dependencies[self::EXPIRATION] <= 0) {
$this->storage->remove($key);
} else {
$this->storage->write($key, $data, $dependencies);
}
return $data;
}
}
private function completeDependencies(?array $dp) : array
{
// convert expire into relative amount of seconds
if (isset($dp[self::EXPIRATION])) {
$dp[self::EXPIRATION] = \RectorPrefix20210611\Nette\Utils\DateTime::from($dp[self::EXPIRATION])->format('U') - \time();
}
// make list from TAGS
if (isset($dp[self::TAGS])) {
$dp[self::TAGS] = \array_values((array) $dp[self::TAGS]);
}
// make list from NAMESPACES
if (isset($dp[self::NAMESPACES])) {
$dp[self::NAMESPACES] = \array_values((array) $dp[self::NAMESPACES]);
}
// convert FILES into CALLBACKS
if (isset($dp[self::FILES])) {
foreach (\array_unique((array) $dp[self::FILES]) as $item) {
$dp[self::CALLBACKS][] = [[self::class, 'checkFile'], $item, @\filemtime($item) ?: null];
// @ - stat may fail
}
unset($dp[self::FILES]);
}
// add namespaces to items
if (isset($dp[self::ITEMS])) {
$dp[self::ITEMS] = \array_unique(\array_map([$this, 'generateKey'], (array) $dp[self::ITEMS]));
}
// convert CONSTS into CALLBACKS
if (isset($dp[self::CONSTS])) {
foreach (\array_unique((array) $dp[self::CONSTS]) as $item) {
$dp[self::CALLBACKS][] = [[self::class, 'checkConst'], $item, \constant($item)];
}
unset($dp[self::CONSTS]);
}
if (!\is_array($dp)) {
$dp = [];
}
return $dp;
}
/**
* Removes item from the cache.
* @param mixed $key
*/
public function remove($key) : void
{
$this->save($key, null);
}
/**
* Removes items from the cache by conditions.
* Conditions are:
* - Cache::PRIORITY => (int) priority
* - Cache::TAGS => (array) tags
* - Cache::ALL => true
*/
public function clean(array $conditions = null) : void
{
$conditions = (array) $conditions;
if (isset($conditions[self::TAGS])) {
$conditions[self::TAGS] = \array_values((array) $conditions[self::TAGS]);
}
$this->storage->clean($conditions);
}
/**
* Caches results of function/method calls.
* @return mixed
*/
public function call(callable $function)
{
$key = \func_get_args();
if (\is_array($function) && \is_object($function[0])) {
$key[0][0] = \get_class($function[0]);
}
return $this->load($key, function () use($function, $key) {
return $function(...\array_slice($key, 1));
});
}
/**
* Caches results of function/method calls.
*/
public function wrap(callable $function, array $dependencies = null) : \Closure
{
return function () use($function, $dependencies) {
$key = [$function, $args = \func_get_args()];
if (\is_array($function) && \is_object($function[0])) {
$key[0][0] = \get_class($function[0]);
}
return $this->load($key, function (&$deps) use($function, $args, $dependencies) {
$deps = $dependencies;
return $function(...$args);
});
};
}
/**
* Starts the output cache.
* @param mixed $key
*/
public function capture($key) : ?\RectorPrefix20210611\Nette\Caching\OutputHelper
{
$data = $this->load($key);
if ($data === null) {
return new \RectorPrefix20210611\Nette\Caching\OutputHelper($this, $key);
}
echo $data;
return null;
}
/**
* @deprecated use capture()
*/
public function start($key) : ?\RectorPrefix20210611\Nette\Caching\OutputHelper
{
return $this->capture($key);
}
/**
* Generates internal cache key.
*/
protected function generateKey($key) : string
{
return $this->namespace . \md5(\is_scalar($key) ? (string) $key : \serialize($key));
}
/********************* dependency checkers ****************d*g**/
/**
* Checks CALLBACKS dependencies.
*/
public static function checkCallbacks(array $callbacks) : bool
{
foreach ($callbacks as $callback) {
if (!\array_shift($callback)(...$callback)) {
return \false;
}
}
return \true;
}
/**
* Checks CONSTS dependency.
*/
private static function checkConst(string $const, $value) : bool
{
return \defined($const) && \constant($const) === $value;
}
/**
* Checks FILES dependency.
*/
private static function checkFile(string $file, ?int $time) : bool
{
return @\filemtime($file) == $time;
// @ - stat may fail
}
}

View File

@ -1,48 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching;
use RectorPrefix20210611\Nette;
/**
* Output caching helper.
*/
class OutputHelper
{
use Nette\SmartObject;
/** @var array */
public $dependencies = [];
/** @var Cache|null */
private $cache;
/** @var string */
private $key;
public function __construct(\RectorPrefix20210611\Nette\Caching\Cache $cache, $key)
{
$this->cache = $cache;
$this->key = $key;
\ob_start();
}
/**
* Stops and saves the cache.
*/
public function end(array $dependencies = []) : void
{
if ($this->cache === null) {
throw new \RectorPrefix20210611\Nette\InvalidStateException('Output cache has already been saved.');
}
$this->cache->save($this->key, \ob_get_flush(), $dependencies + $this->dependencies);
$this->cache = null;
}
/**
* Stops and throws away the output.
*/
public function rollback() : void
{
\ob_end_flush();
$this->cache = null;
}
}

View File

@ -1,37 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching;
/**
* Cache storage.
*/
interface Storage
{
/**
* Read from cache.
* @return mixed
*/
function read(string $key);
/**
* Prevents item reading and writing. Lock is released by write() or remove().
*/
function lock(string $key) : void;
/**
* Writes item into the cache.
*/
function write(string $key, $data, array $dependencies) : void;
/**
* Removes item from the cache.
*/
function remove(string $key) : void;
/**
* Removes items from the cache by conditions.
*/
function clean(array $conditions) : void;
}
\class_exists(\RectorPrefix20210611\Nette\Caching\IStorage::class);

View File

@ -1,32 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
/**
* Cache dummy storage.
*/
class DevNullStorage implements \RectorPrefix20210611\Nette\Caching\Storage
{
use Nette\SmartObject;
public function read(string $key)
{
}
public function lock(string $key) : void
{
}
public function write(string $key, $data, array $dependencies) : void
{
}
public function remove(string $key) : void
{
}
public function clean(array $conditions) : void
{
}
}

View File

@ -1,303 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
use RectorPrefix20210611\Nette\Caching\Cache;
/**
* Cache file storage.
*/
class FileStorage implements \RectorPrefix20210611\Nette\Caching\Storage
{
use Nette\SmartObject;
/**
* Atomic thread safe logic:
*
* 1) reading: open(r+b), lock(SH), read
* - delete?: delete*, close
* 2) deleting: delete*
* 3) writing: open(r+b || wb), lock(EX), truncate*, write data, write meta, close
*
* delete* = try unlink, if fails (on NTFS) { lock(EX), truncate, close, unlink } else close (on ext3)
*/
/** @internal cache file structure: meta-struct size + serialized meta-struct + data */
private const META_HEADER_LEN = 6, META_TIME = 'time', META_SERIALIZED = 'serialized', META_EXPIRE = 'expire', META_DELTA = 'delta', META_ITEMS = 'di', META_CALLBACKS = 'callbacks';
// array of callbacks (function, args)
/** additional cache structure */
private const FILE = 'file', HANDLE = 'handle';
/** @var float probability that the clean() routine is started */
public static $gcProbability = 0.001;
/** @deprecated */
public static $useDirectories = \true;
/** @var string */
private $dir;
/** @var Journal */
private $journal;
/** @var array */
private $locks;
public function __construct(string $dir, \RectorPrefix20210611\Nette\Caching\Storages\Journal $journal = null)
{
if (!\is_dir($dir)) {
throw new \RectorPrefix20210611\Nette\DirectoryNotFoundException("Directory '{$dir}' not found.");
}
$this->dir = $dir;
$this->journal = $journal;
if (\mt_rand() / \mt_getrandmax() < static::$gcProbability) {
$this->clean([]);
}
}
public function read(string $key)
{
$meta = $this->readMetaAndLock($this->getCacheFile($key), \LOCK_SH);
return $meta && $this->verify($meta) ? $this->readData($meta) : null;
}
/**
* Verifies dependencies.
*/
private function verify(array $meta) : bool
{
do {
if (!empty($meta[self::META_DELTA])) {
// meta[file] was added by readMetaAndLock()
if (\filemtime($meta[self::FILE]) + $meta[self::META_DELTA] < \time()) {
break;
}
\touch($meta[self::FILE]);
} elseif (!empty($meta[self::META_EXPIRE]) && $meta[self::META_EXPIRE] < \time()) {
break;
}
if (!empty($meta[self::META_CALLBACKS]) && !\RectorPrefix20210611\Nette\Caching\Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
break;
}
if (!empty($meta[self::META_ITEMS])) {
foreach ($meta[self::META_ITEMS] as $depFile => $time) {
$m = $this->readMetaAndLock($depFile, \LOCK_SH);
if (($m[self::META_TIME] ?? null) !== $time || $m && !$this->verify($m)) {
break 2;
}
}
}
return \true;
} while (\false);
$this->delete($meta[self::FILE], $meta[self::HANDLE]);
// meta[handle] & meta[file] was added by readMetaAndLock()
return \false;
}
public function lock(string $key) : void
{
$cacheFile = $this->getCacheFile($key);
if (!\is_dir($dir = \dirname($cacheFile))) {
@\mkdir($dir);
// @ - directory may already exist
}
$handle = \fopen($cacheFile, 'c+b');
if (!$handle) {
return;
}
$this->locks[$key] = $handle;
\flock($handle, \LOCK_EX);
}
public function write(string $key, $data, array $dp) : void
{
$meta = [self::META_TIME => \microtime()];
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION])) {
if (empty($dp[\RectorPrefix20210611\Nette\Caching\Cache::SLIDING])) {
$meta[self::META_EXPIRE] = $dp[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION] + \time();
// absolute time
} else {
$meta[self::META_DELTA] = (int) $dp[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION];
// sliding time
}
}
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::ITEMS])) {
foreach ($dp[\RectorPrefix20210611\Nette\Caching\Cache::ITEMS] as $item) {
$depFile = $this->getCacheFile($item);
$m = $this->readMetaAndLock($depFile, \LOCK_SH);
$meta[self::META_ITEMS][$depFile] = $m[self::META_TIME] ?? null;
unset($m);
}
}
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::CALLBACKS])) {
$meta[self::META_CALLBACKS] = $dp[\RectorPrefix20210611\Nette\Caching\Cache::CALLBACKS];
}
if (!isset($this->locks[$key])) {
$this->lock($key);
if (!isset($this->locks[$key])) {
return;
}
}
$handle = $this->locks[$key];
unset($this->locks[$key]);
$cacheFile = $this->getCacheFile($key);
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::TAGS]) || isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY])) {
if (!$this->journal) {
throw new \RectorPrefix20210611\Nette\InvalidStateException('CacheJournal has not been provided.');
}
$this->journal->write($cacheFile, $dp);
}
\ftruncate($handle, 0);
if (!\is_string($data)) {
$data = \serialize($data);
$meta[self::META_SERIALIZED] = \true;
}
$head = \serialize($meta);
$head = \str_pad((string) \strlen($head), 6, '0', \STR_PAD_LEFT) . $head;
$headLen = \strlen($head);
do {
if (\fwrite($handle, \str_repeat("\0", $headLen)) !== $headLen) {
break;
}
if (\fwrite($handle, $data) !== \strlen($data)) {
break;
}
\fseek($handle, 0);
if (\fwrite($handle, $head) !== $headLen) {
break;
}
\flock($handle, \LOCK_UN);
\fclose($handle);
return;
} while (\false);
$this->delete($cacheFile, $handle);
}
public function remove(string $key) : void
{
unset($this->locks[$key]);
$this->delete($this->getCacheFile($key));
}
public function clean(array $conditions) : void
{
$all = !empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::ALL]);
$collector = empty($conditions);
$namespaces = $conditions[\RectorPrefix20210611\Nette\Caching\Cache::NAMESPACES] ?? null;
// cleaning using file iterator
if ($all || $collector) {
$now = \time();
foreach (\RectorPrefix20210611\Nette\Utils\Finder::find('_*')->from($this->dir)->childFirst() as $entry) {
$path = (string) $entry;
if ($entry->isDir()) {
// collector: remove empty dirs
@\rmdir($path);
// @ - removing dirs is not necessary
continue;
}
if ($all) {
$this->delete($path);
} else {
// collector
$meta = $this->readMetaAndLock($path, \LOCK_SH);
if (!$meta) {
continue;
}
if (!empty($meta[self::META_DELTA]) && \filemtime($meta[self::FILE]) + $meta[self::META_DELTA] < $now || !empty($meta[self::META_EXPIRE]) && $meta[self::META_EXPIRE] < $now) {
$this->delete($path, $meta[self::HANDLE]);
continue;
}
\flock($meta[self::HANDLE], \LOCK_UN);
\fclose($meta[self::HANDLE]);
}
}
if ($this->journal) {
$this->journal->clean($conditions);
}
return;
} elseif ($namespaces) {
foreach ($namespaces as $namespace) {
$dir = $this->dir . '/_' . \urlencode($namespace);
if (!\is_dir($dir)) {
continue;
}
foreach (\RectorPrefix20210611\Nette\Utils\Finder::findFiles('_*')->in($dir) as $entry) {
$this->delete((string) $entry);
}
@\rmdir($dir);
// may already contain new files
}
}
// cleaning using journal
if ($this->journal) {
foreach ($this->journal->clean($conditions) as $file) {
$this->delete($file);
}
}
}
/**
* Reads cache data from disk.
*/
protected function readMetaAndLock(string $file, int $lock) : ?array
{
$handle = @\fopen($file, 'r+b');
// @ - file may not exist
if (!$handle) {
return null;
}
\flock($handle, $lock);
$size = (int) \stream_get_contents($handle, self::META_HEADER_LEN);
if ($size) {
$meta = \stream_get_contents($handle, $size, self::META_HEADER_LEN);
$meta = \unserialize($meta);
$meta[self::FILE] = $file;
$meta[self::HANDLE] = $handle;
return $meta;
}
\flock($handle, \LOCK_UN);
\fclose($handle);
return null;
}
/**
* Reads cache data from disk and closes cache file handle.
* @return mixed
*/
protected function readData(array $meta)
{
$data = \stream_get_contents($meta[self::HANDLE]);
\flock($meta[self::HANDLE], \LOCK_UN);
\fclose($meta[self::HANDLE]);
return empty($meta[self::META_SERIALIZED]) ? $data : \unserialize($data);
}
/**
* Returns file name.
*/
protected function getCacheFile(string $key) : string
{
$file = \urlencode($key);
if ($a = \strrpos($file, '%00')) {
// %00 = urlencode(Nette\Caching\Cache::NAMESPACE_SEPARATOR)
$file = \substr_replace($file, '/_', $a, 3);
}
return $this->dir . '/_' . $file;
}
/**
* Deletes and closes file.
* @param resource $handle
*/
private static function delete(string $file, $handle = null) : void
{
if (@\unlink($file)) {
// @ - file may not already exist
if ($handle) {
\flock($handle, \LOCK_UN);
\fclose($handle);
}
return;
}
if (!$handle) {
$handle = @\fopen($file, 'r+');
// @ - file may not exist
}
if (!$handle) {
return;
}
\flock($handle, \LOCK_EX);
\ftruncate($handle, 0);
\flock($handle, \LOCK_UN);
\fclose($handle);
@\unlink($file);
// @ - file may not already exist
}
}

View File

@ -1,25 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
/**
* Cache journal provider.
*/
interface Journal
{
/**
* Writes entry information into the journal.
*/
function write(string $key, array $dependencies) : void;
/**
* Cleans entries from journal.
* @return array|null of removed items or null when performing a full cleanup
*/
function clean(array $conditions) : ?array;
}
\class_exists(\RectorPrefix20210611\Nette\Caching\Storages\IJournal::class);

View File

@ -1,147 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
use RectorPrefix20210611\Nette\Caching\Cache;
/**
* Memcached storage using memcached extension.
*/
class MemcachedStorage implements \RectorPrefix20210611\Nette\Caching\Storage, \RectorPrefix20210611\Nette\Caching\BulkReader
{
use Nette\SmartObject;
/** @internal cache structure */
private const META_CALLBACKS = 'callbacks', META_DATA = 'data', META_DELTA = 'delta';
/** @var \Memcached */
private $memcached;
/** @var string */
private $prefix;
/** @var Journal */
private $journal;
/**
* Checks if Memcached extension is available.
*/
public static function isAvailable() : bool
{
return \extension_loaded('memcached');
}
public function __construct(string $host = 'localhost', int $port = 11211, string $prefix = '', \RectorPrefix20210611\Nette\Caching\Storages\Journal $journal = null)
{
if (!static::isAvailable()) {
throw new \RectorPrefix20210611\Nette\NotSupportedException("PHP extension 'memcached' is not loaded.");
}
$this->prefix = $prefix;
$this->journal = $journal;
$this->memcached = new \Memcached();
if ($host) {
$this->addServer($host, $port);
}
}
public function addServer(string $host = 'localhost', int $port = 11211) : void
{
if (@$this->memcached->addServer($host, $port, 1) === \false) {
// @ is escalated to exception
$error = \error_get_last();
throw new \RectorPrefix20210611\Nette\InvalidStateException("Memcached::addServer(): {$error['message']}.");
}
}
public function getConnection() : \Memcached
{
return $this->memcached;
}
public function read(string $key)
{
$key = \urlencode($this->prefix . $key);
$meta = $this->memcached->get($key);
if (!$meta) {
return null;
}
// meta structure:
// array(
// data => stored data
// delta => relative (sliding) expiration
// callbacks => array of callbacks (function, args)
// )
// verify dependencies
if (!empty($meta[self::META_CALLBACKS]) && !\RectorPrefix20210611\Nette\Caching\Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
$this->memcached->delete($key, 0);
return null;
}
if (!empty($meta[self::META_DELTA])) {
$this->memcached->replace($key, $meta, $meta[self::META_DELTA] + \time());
}
return $meta[self::META_DATA];
}
public function bulkRead(array $keys) : array
{
$prefixedKeys = \array_map(function ($key) {
return \urlencode($this->prefix . $key);
}, $keys);
$keys = \array_combine($prefixedKeys, $keys);
$metas = $this->memcached->getMulti($prefixedKeys);
$result = [];
$deleteKeys = [];
foreach ($metas as $prefixedKey => $meta) {
if (!empty($meta[self::META_CALLBACKS]) && !\RectorPrefix20210611\Nette\Caching\Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
$deleteKeys[] = $prefixedKey;
} else {
$result[$keys[$prefixedKey]] = $meta[self::META_DATA];
}
if (!empty($meta[self::META_DELTA])) {
$this->memcached->replace($prefixedKey, $meta, $meta[self::META_DELTA] + \time());
}
}
if (!empty($deleteKeys)) {
$this->memcached->deleteMulti($deleteKeys, 0);
}
return $result;
}
public function lock(string $key) : void
{
}
public function write(string $key, $data, array $dp) : void
{
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::ITEMS])) {
throw new \RectorPrefix20210611\Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.');
}
$key = \urlencode($this->prefix . $key);
$meta = [self::META_DATA => $data];
$expire = 0;
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION])) {
$expire = (int) $dp[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION];
if (!empty($dp[\RectorPrefix20210611\Nette\Caching\Cache::SLIDING])) {
$meta[self::META_DELTA] = $expire;
// sliding time
}
}
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::CALLBACKS])) {
$meta[self::META_CALLBACKS] = $dp[\RectorPrefix20210611\Nette\Caching\Cache::CALLBACKS];
}
if (isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::TAGS]) || isset($dp[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY])) {
if (!$this->journal) {
throw new \RectorPrefix20210611\Nette\InvalidStateException('CacheJournal has not been provided.');
}
$this->journal->write($key, $dp);
}
$this->memcached->set($key, $meta, $expire);
}
public function remove(string $key) : void
{
$this->memcached->delete(\urlencode($this->prefix . $key), 0);
}
public function clean(array $conditions) : void
{
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::ALL])) {
$this->memcached->flush();
} elseif ($this->journal) {
foreach ($this->journal->clean($conditions) as $entry) {
$this->memcached->delete($entry, 0);
}
}
}
}

View File

@ -1,40 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
/**
* Memory cache storage.
*/
class MemoryStorage implements \RectorPrefix20210611\Nette\Caching\Storage
{
use Nette\SmartObject;
/** @var array */
private $data = [];
public function read(string $key)
{
return $this->data[$key] ?? null;
}
public function lock(string $key) : void
{
}
public function write(string $key, $data, array $dependencies) : void
{
$this->data[$key] = $data;
}
public function remove(string $key) : void
{
unset($this->data[$key]);
}
public function clean(array $conditions) : void
{
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::ALL])) {
$this->data = [];
}
}
}

View File

@ -1,15 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
/**
* @deprecated
*/
class NewMemcachedStorage extends \RectorPrefix20210611\Nette\Caching\Storages\MemcachedStorage
{
}

View File

@ -1,114 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
use RectorPrefix20210611\Nette\Caching\Cache;
/**
* SQLite based journal.
*/
class SQLiteJournal implements \RectorPrefix20210611\Nette\Caching\Storages\Journal
{
use Nette\SmartObject;
/** @string */
private $path;
/** @var \PDO */
private $pdo;
public function __construct(string $path)
{
if (!\extension_loaded('pdo_sqlite')) {
throw new \RectorPrefix20210611\Nette\NotSupportedException('SQLiteJournal requires PHP extension pdo_sqlite which is not loaded.');
}
$this->path = $path;
}
private function open() : void
{
if ($this->path !== ':memory:' && !\is_file($this->path)) {
\touch($this->path);
// ensures ordinary file permissions
}
$this->pdo = new \PDO('sqlite:' . $this->path);
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('
PRAGMA foreign_keys = OFF;
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS tags (
key BLOB NOT NULL,
tag BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS priorities (
key BLOB NOT NULL,
priority INT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_tags_tag ON tags(tag);
CREATE UNIQUE INDEX IF NOT EXISTS idx_tags_key_tag ON tags(key, tag);
CREATE UNIQUE INDEX IF NOT EXISTS idx_priorities_key ON priorities(key);
CREATE INDEX IF NOT EXISTS idx_priorities_priority ON priorities(priority);
');
}
public function write(string $key, array $dependencies) : void
{
if (!$this->pdo) {
$this->open();
}
$this->pdo->exec('BEGIN');
if (!empty($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::TAGS])) {
$this->pdo->prepare('DELETE FROM tags WHERE key = ?')->execute([$key]);
foreach ($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::TAGS] as $tag) {
$arr[] = $key;
$arr[] = $tag;
}
$this->pdo->prepare('INSERT INTO tags (key, tag) SELECT ?, ?' . \str_repeat('UNION SELECT ?, ?', \count($arr) / 2 - 1))->execute($arr);
}
if (!empty($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY])) {
$this->pdo->prepare('REPLACE INTO priorities (key, priority) VALUES (?, ?)')->execute([$key, (int) $dependencies[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY]]);
}
$this->pdo->exec('COMMIT');
}
public function clean(array $conditions) : ?array
{
if (!$this->pdo) {
$this->open();
}
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::ALL])) {
$this->pdo->exec('
BEGIN;
DELETE FROM tags;
DELETE FROM priorities;
COMMIT;
');
return null;
}
$unions = $args = [];
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::TAGS])) {
$tags = (array) $conditions[\RectorPrefix20210611\Nette\Caching\Cache::TAGS];
$unions[] = 'SELECT DISTINCT key FROM tags WHERE tag IN (?' . \str_repeat(', ?', \count($tags) - 1) . ')';
$args = $tags;
}
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY])) {
$unions[] = 'SELECT DISTINCT key FROM priorities WHERE priority <= ?';
$args[] = (int) $conditions[\RectorPrefix20210611\Nette\Caching\Cache::PRIORITY];
}
if (empty($unions)) {
return [];
}
$unionSql = \implode(' UNION ', $unions);
$this->pdo->exec('BEGIN IMMEDIATE');
$stmt = $this->pdo->prepare($unionSql);
$stmt->execute($args);
$keys = $stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
if (empty($keys)) {
$this->pdo->exec('COMMIT');
return [];
}
$this->pdo->prepare("DELETE FROM tags WHERE key IN ({$unionSql})")->execute($args);
$this->pdo->prepare("DELETE FROM priorities WHERE key IN ({$unionSql})")->execute($args);
$this->pdo->exec('COMMIT');
return $keys;
}
}

View File

@ -1,113 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching\Storages;
use RectorPrefix20210611\Nette;
use RectorPrefix20210611\Nette\Caching\Cache;
/**
* SQLite storage.
*/
class SQLiteStorage implements \RectorPrefix20210611\Nette\Caching\Storage, \RectorPrefix20210611\Nette\Caching\BulkReader
{
use Nette\SmartObject;
/** @var \PDO */
private $pdo;
public function __construct(string $path)
{
if ($path !== ':memory:' && !\is_file($path)) {
\touch($path);
// ensures ordinary file permissions
}
$this->pdo = new \PDO('sqlite:' . $path);
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS cache (
key BLOB NOT NULL PRIMARY KEY,
data BLOB NOT NULL,
expire INTEGER,
slide INTEGER
);
CREATE TABLE IF NOT EXISTS tags (
key BLOB NOT NULL REFERENCES cache ON DELETE CASCADE,
tag BLOB NOT NULL
);
CREATE INDEX IF NOT EXISTS cache_expire ON cache(expire);
CREATE INDEX IF NOT EXISTS tags_key ON tags(key);
CREATE INDEX IF NOT EXISTS tags_tag ON tags(tag);
PRAGMA synchronous = OFF;
');
}
public function read(string $key)
{
$stmt = $this->pdo->prepare('SELECT data, slide FROM cache WHERE key=? AND (expire IS NULL OR expire >= ?)');
$stmt->execute([$key, \time()]);
if (!($row = $stmt->fetch(\PDO::FETCH_ASSOC))) {
return;
}
if ($row['slide'] !== null) {
$this->pdo->prepare('UPDATE cache SET expire = ? + slide WHERE key=?')->execute([\time(), $key]);
}
return \unserialize($row['data']);
}
public function bulkRead(array $keys) : array
{
$stmt = $this->pdo->prepare('SELECT key, data, slide FROM cache WHERE key IN (?' . \str_repeat(',?', \count($keys) - 1) . ') AND (expire IS NULL OR expire >= ?)');
$stmt->execute(\array_merge($keys, [\time()]));
$result = [];
$updateSlide = [];
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
if ($row['slide'] !== null) {
$updateSlide[] = $row['key'];
}
$result[$row['key']] = \unserialize($row['data']);
}
if (!empty($updateSlide)) {
$stmt = $this->pdo->prepare('UPDATE cache SET expire = ? + slide WHERE key IN(?' . \str_repeat(',?', \count($updateSlide) - 1) . ')');
$stmt->execute(\array_merge([\time()], $updateSlide));
}
return $result;
}
public function lock(string $key) : void
{
}
public function write(string $key, $data, array $dependencies) : void
{
$expire = isset($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION]) ? $dependencies[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION] + \time() : null;
$slide = isset($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::SLIDING]) ? $dependencies[\RectorPrefix20210611\Nette\Caching\Cache::EXPIRATION] : null;
$this->pdo->exec('BEGIN TRANSACTION');
$this->pdo->prepare('REPLACE INTO cache (key, data, expire, slide) VALUES (?, ?, ?, ?)')->execute([$key, \serialize($data), $expire, $slide]);
if (!empty($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::TAGS])) {
foreach ($dependencies[\RectorPrefix20210611\Nette\Caching\Cache::TAGS] as $tag) {
$arr[] = $key;
$arr[] = $tag;
}
$this->pdo->prepare('INSERT INTO tags (key, tag) SELECT ?, ?' . \str_repeat('UNION SELECT ?, ?', \count($arr) / 2 - 1))->execute($arr);
}
$this->pdo->exec('COMMIT');
}
public function remove(string $key) : void
{
$this->pdo->prepare('DELETE FROM cache WHERE key=?')->execute([$key]);
}
public function clean(array $conditions) : void
{
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::ALL])) {
$this->pdo->prepare('DELETE FROM cache')->execute();
} else {
$sql = 'DELETE FROM cache WHERE expire < ?';
$args = [\time()];
if (!empty($conditions[\RectorPrefix20210611\Nette\Caching\Cache::TAGS])) {
$tags = $conditions[\RectorPrefix20210611\Nette\Caching\Cache::TAGS];
$sql .= ' OR key IN (SELECT key FROM tags WHERE tag IN (?' . \str_repeat(',?', \count($tags) - 1) . '))';
$args = \array_merge($args, $tags);
}
$this->pdo->prepare($sql)->execute($args);
}
}
}

View File

@ -1,35 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Caching;
if (\false) {
/** @deprecated use Nette\Caching\BulkReader */
interface IBulkReader extends \RectorPrefix20210611\Nette\Caching\BulkReader
{
}
} elseif (!\interface_exists(\RectorPrefix20210611\Nette\Caching\IBulkReader::class)) {
\class_alias(\RectorPrefix20210611\Nette\Caching\BulkReader::class, \RectorPrefix20210611\Nette\Caching\IBulkReader::class);
}
if (\false) {
/** @deprecated use Nette\Caching\Storage */
interface IStorage extends \RectorPrefix20210611\Nette\Caching\Storage
{
}
} elseif (!\interface_exists(\RectorPrefix20210611\Nette\Caching\IStorage::class)) {
\class_alias(\RectorPrefix20210611\Nette\Caching\Storage::class, \RectorPrefix20210611\Nette\Caching\IStorage::class);
}
namespace RectorPrefix20210611\Nette\Caching\Storages;
if (\false) {
/** @deprecated use Nette\Caching\Storages\Journal */
interface IJournal extends \RectorPrefix20210611\Nette\Caching\Storages\Journal
{
}
} elseif (!\interface_exists(\RectorPrefix20210611\Nette\Caching\Storages\IJournal::class)) {
\class_alias(\RectorPrefix20210611\Nette\Caching\Storages\Journal::class, \RectorPrefix20210611\Nette\Caching\Storages\IJournal::class);
}

View File

@ -1,53 +0,0 @@
{
"name": "nette\/finder",
"description": "\ud83d\udd0d Nette Finder: find files and directories with an intuitive API.",
"keywords": [
"nette",
"filesystem",
"iterator",
"glob"
],
"homepage": "https:\/\/nette.org",
"license": [
"BSD-3-Clause",
"GPL-2.0",
"GPL-3.0"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https:\/\/davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https:\/\/nette.org\/contributors"
}
],
"require": {
"php": ">=7.1",
"nette\/utils": "^2.4 || ^3.0"
},
"require-dev": {
"nette\/tester": "^2.0",
"tracy\/tracy": "^2.3",
"phpstan\/phpstan": "^0.12"
},
"conflict": {
"nette\/nette": "<2.2"
},
"autoload": {
"classmap": [
"src\/"
]
},
"minimum-stability": "dev",
"scripts": {
"phpstan": "phpstan analyse --level 5 src",
"tester": "tester tests -s"
},
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
}
}
}

View File

@ -1,33 +0,0 @@
How to contribute & use the issue tracker
=========================================
Nette welcomes your contributions. There are several ways to help out:
* Create an issue on GitHub, if you have found a bug
* Write test cases for open bug issues
* Write fixes for open bug/feature issues, preferably with test cases included
* Contribute to the [documentation](https://nette.org/en/writing)
Issues
------
Please **do not use the issue tracker to ask questions**. We will be happy to help you
on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette).
A good bug report shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report.
**Feature requests** are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the project's developers of the merits of this feature.
Contributing
------------
If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing).
The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them.
Please do not fix whitespace, format code, or make a purely cosmetic patch.
Thanks! :heart:

View File

@ -1,60 +0,0 @@
Licenses
========
Good news! You may use Nette Framework under the terms of either
the New BSD License or the GNU General Public License (GPL) version 2 or 3.
The BSD License is recommended for most projects. It is easy to understand and it
places almost no restrictions on what you can do with the framework. If the GPL
fits better to your project, you can use the framework under this license.
You don't have to notify anyone which license you are using. You can freely
use Nette Framework in commercial projects as long as the copyright header
remains intact.
Please be advised that the name "Nette Framework" is a protected trademark and its
usage has some limitations. So please do not use word "Nette" in the name of your
project or top-level domain, and choose a name that stands on its own merits.
If your stuff is good, it will not take long to establish a reputation for yourselves.
New BSD License
---------------
Copyright (c) 2004, 2014 David Grudl (https://davidgrudl.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of "Nette Framework" nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
This software is provided by the copyright holders and contributors "as is" and
any express or implied warranties, including, but not limited to, the implied
warranties of merchantability and fitness for a particular purpose are
disclaimed. In no event shall the copyright owner or contributors be liable for
any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services;
loss of use, data, or profits; or business interruption) however caused and on
any theory of liability, whether in contract, strict liability, or tort
(including negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.
GNU General Public License
--------------------------
GPL licenses are very very long, so instead of including them here we offer
you URLs with full text:
- [GPL version 2](http://www.gnu.org/licenses/gpl-2.0.html)
- [GPL version 3](http://www.gnu.org/licenses/gpl-3.0.html)

View File

@ -1,181 +0,0 @@
Nette Finder: Files Searching
=============================
[![Downloads this Month](https://img.shields.io/packagist/dm/nette/finder.svg)](https://packagist.org/packages/nette/finder)
[![Build Status](https://travis-ci.org/nette/finder.svg?branch=master)](https://travis-ci.org/nette/finder)
[![Coverage Status](https://coveralls.io/repos/github/nette/finder/badge.svg?branch=master)](https://coveralls.io/github/nette/finder?branch=master)
[![Latest Stable Version](https://poser.pugx.org/nette/finder/v/stable)](https://github.com/nette/finder/releases)
[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/finder/blob/master/license.md)
Introduction
------------
Nette Finder makes browsing the directory structure really easy.
Documentation can be found on the [website](https://doc.nette.org/finder).
If you like Nette, **[please make a donation now](https://nette.org/donate)**. Thank you!
Installation
------------
The recommended way to install is via Composer:
```
composer require nette/finder
```
It requires PHP version 7.1 and supports PHP up to 7.4.
Usage
-----
How to find all `*.txt` files in `$dir` directory without recursing subdirectories?
```php
foreach (Finder::findFiles('*.txt')->in($dir) as $key => $file) {
echo $key; // $key is a string containing absolute filename with path
echo $file; // $file is an instance of SplFileInfo
}
```
As a result, the finder returns instances of `SplFileInfo`.
If the directory does not exist, an `UnexpectedValueException` is thrown.
And what about searching for `*.txt` files in `$dir` including subdirectories? Instead of `in()`, use `from()`:
```php
foreach (Finder::findFiles('*.txt')->from($dir) as $file) {
echo $file;
}
```
Search by more masks, even inside more directories within one iteration:
```php
foreach (Finder::findFiles('*.txt', '*.php')
->in($dir1, $dir2) as $file) {
...
}
```
Parameters can also be arrays:
```php
foreach (Finder::findFiles($masks)->in($dirs) as $file) {
...
}
```
Searching for `*.txt` files containing a number in the name:
```php
foreach (Finder::findFiles('*[0-9]*.txt')->from($dir) as $file) {
...
}
```
Searching for `*.txt` files, except those containing '`X`' in the name:
```php
foreach (Finder::findFiles('*.txt')
->exclude('*X*')->from($dir) as $file) {
...
}
```
`exclude()` is specified just after `findFiles()`, thus it applies to filename.
Directories to omit can be specified using the `exclude` **after** `from` clause:
```php
foreach (Finder::findFiles('*.php')
->from($dir)->exclude('temp', '.git') as $file) {
...
}
```
Here `exclude()` is after `from()`, thus it applies to the directory name.
And now something a bit more complicated: searching for `*.txt` files located in subdirectories starting with '`te`', but not '`temp`':
```php
foreach (Finder::findFiles('te*/*.txt')
->exclude('temp*/*')->from($dir) as $file) {
...
}
```
Depth of search can be limited using the `limitDepth()` method.
Searching for directories
-------------------------
In addition to files, it is possible to search for directories using `Finder::findDirectories('subdir*')`, or to search for files and directories: `Finder::find('file.txt')`.
Filtering
---------
You can also filter results. For example by size. This way we will traverse the files of size between 100B and 200B:
```php
foreach (Finder::findFiles('*.php')->size('>=', 100)->size('<=', 200)
->from($dir) as $file) {
...
}
```
Or files changed in the last two weeks:
```php
foreach (Finder::findFiles('*.php')->date('>', '- 2 weeks')
->from($dir) as $file) {
...
}
```
Here we traverse PHP files with number of lines greater than 1000. As a filter we use a custom callback:
```php
$finder = Finder::findFiles('*.php')->filter(function($file) {
return count(file($file->getPathname())) > 1000;
})->from($dir);
```
Finder, find images larger than 50px × 50px:
```php
foreach (Finder::findFiles('*')
->dimensions('>50', '>50')->from($dir) as $file) {
...
}
```
Connection to Amazon S3
-----------------------
It's possible to use custom streams, for example Zend_Service_Amazon_S3:
```php
$s3 = new Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper('s3');
foreach (Finder::findFiles('photos*')
->size('<=', 1e6)->in('s3://bucket-name') as $file) {
echo $file;
}
```
Handy, right? You will certainly find a use for Finder in your applications.

View File

@ -1,314 +0,0 @@
<?php
/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
declare (strict_types=1);
namespace RectorPrefix20210611\Nette\Utils;
use RectorPrefix20210611\Nette;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
/**
* Finder allows searching through directory trees using iterator.
*
* <code>
* Finder::findFiles('*.php')
* ->size('> 10kB')
* ->from('.')
* ->exclude('temp');
* </code>
*/
class Finder implements \IteratorAggregate, \Countable
{
use Nette\SmartObject;
/** @var callable extension methods */
private static $extMethods = [];
/** @var array */
private $paths = [];
/** @var array of filters */
private $groups = [];
/** @var array filter for recursive traversing */
private $exclude = [];
/** @var int */
private $order = \RecursiveIteratorIterator::SELF_FIRST;
/** @var int */
private $maxDepth = -1;
/** @var array */
private $cursor;
/**
* Begins search for files matching mask and all directories.
* @param string|string[] $masks
* @return static
*/
public static function find(...$masks)
{
$masks = $masks && \is_array($masks[0]) ? $masks[0] : $masks;
return (new static())->select($masks, 'isDir')->select($masks, 'isFile');
}
/**
* Begins search for files matching mask.
* @param string|string[] $masks
* @return static
*/
public static function findFiles(...$masks)
{
$masks = $masks && \is_array($masks[0]) ? $masks[0] : $masks;
return (new static())->select($masks, 'isFile');
}
/**
* Begins search for directories matching mask.
* @param string|string[] $masks
* @return static
*/
public static function findDirectories(...$masks)
{
$masks = $masks && \is_array($masks[0]) ? $masks[0] : $masks;
return (new static())->select($masks, 'isDir');
}
/**
* Creates filtering group by mask & type selector.
* @return static
*/
private function select(array $masks, string $type)
{
$this->cursor =& $this->groups[];
$pattern = self::buildPattern($masks);
$this->filter(function (\RecursiveDirectoryIterator $file) use($type, $pattern) : bool {
return !$file->isDot() && $file->{$type}() && (!$pattern || \preg_match($pattern, '/' . \strtr($file->getSubPathName(), '\\', '/')));
});
return $this;
}
/**
* Searches in the given folder(s).
* @param string|string[] $paths
* @return static
*/
public function in(...$paths)
{
$this->maxDepth = 0;
return $this->from(...$paths);
}
/**
* Searches recursively from the given folder(s).
* @param string|string[] $paths
* @return static
*/
public function from(...$paths)
{
if ($this->paths) {
throw new \RectorPrefix20210611\Nette\InvalidStateException('Directory to search has already been specified.');
}
$this->paths = \is_array($paths[0]) ? $paths[0] : $paths;
$this->cursor =& $this->exclude;
return $this;
}
/**
* Shows folder content prior to the folder.
* @return static
*/
public function childFirst()
{
$this->order = \RecursiveIteratorIterator::CHILD_FIRST;
return $this;
}
/**
* Converts Finder pattern to regular expression.
*/
private static function buildPattern(array $masks) : ?string
{
$pattern = [];
foreach ($masks as $mask) {
$mask = \rtrim(\strtr($mask, '\\', '/'), '/');
$prefix = '';
if ($mask === '') {
continue;
} elseif ($mask === '*') {
return null;
} elseif ($mask[0] === '/') {
// absolute fixing
$mask = \ltrim($mask, '/');
$prefix = '(?<=^/)';
}
$pattern[] = $prefix . \strtr(\preg_quote($mask, '#'), ['\\*\\*' => '.*', '\\*' => '[^/]*', '\\?' => '[^/]', '\\[\\!' => '[^', '\\[' => '[', '\\]' => ']', '\\-' => '-']);
}
return $pattern ? '#/(' . \implode('|', $pattern) . ')$#Di' : null;
}
/********************* iterator generator ****************d*g**/
/**
* Get the number of found files and/or directories.
*/
public function count() : int
{
return \iterator_count($this->getIterator());
}
/**
* Returns iterator.
*/
public function getIterator() : \Iterator
{
if (!$this->paths) {
throw new \RectorPrefix20210611\Nette\InvalidStateException('Call in() or from() to specify directory to search.');
} elseif (\count($this->paths) === 1) {
return $this->buildIterator((string) $this->paths[0]);
} else {
$iterator = new \AppendIterator();
foreach ($this->paths as $path) {
$iterator->append($this->buildIterator((string) $path));
}
return $iterator;
}
}
/**
* Returns per-path iterator.
*/
private function buildIterator(string $path) : \Iterator
{
$iterator = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
if ($this->exclude) {
$iterator = new \RecursiveCallbackFilterIterator($iterator, function ($foo, $bar, \RecursiveDirectoryIterator $file) : bool {
if (!$file->isDot() && !$file->isFile()) {
foreach ($this->exclude as $filter) {
if (!$filter($file)) {
return \false;
}
}
}
return \true;
});
}
if ($this->maxDepth !== 0) {
$iterator = new \RecursiveIteratorIterator($iterator, $this->order);
$iterator->setMaxDepth($this->maxDepth);
}
$iterator = new \CallbackFilterIterator($iterator, function ($foo, $bar, \Iterator $file) : bool {
while ($file instanceof \OuterIterator) {
$file = $file->getInnerIterator();
}
foreach ($this->groups as $filters) {
foreach ($filters as $filter) {
if (!$filter($file)) {
continue 2;
}
}
return \true;
}
return \false;
});
return $iterator;
}
/********************* filtering ****************d*g**/
/**
* Restricts the search using mask.
* Excludes directories from recursive traversing.
* @param string|string[] $masks
* @return static
*/
public function exclude(...$masks)
{
$masks = $masks && \is_array($masks[0]) ? $masks[0] : $masks;
$pattern = self::buildPattern($masks);
if ($pattern) {
$this->filter(function (\RecursiveDirectoryIterator $file) use($pattern) : bool {
return !\preg_match($pattern, '/' . \strtr($file->getSubPathName(), '\\', '/'));
});
}
return $this;
}
/**
* Restricts the search using callback.
* @param callable $callback function (RecursiveDirectoryIterator $file): bool
* @return static
*/
public function filter(callable $callback)
{
$this->cursor[] = $callback;
return $this;
}
/**
* Limits recursion level.
* @return static
*/
public function limitDepth(int $depth)
{
$this->maxDepth = $depth;
return $this;
}
/**
* Restricts the search by size.
* @param string $operator "[operator] [size] [unit]" example: >=10kB
* @return static
*/
public function size(string $operator, int $size = null)
{
if (\func_num_args() === 1) {
// in $operator is predicate
if (!\preg_match('#^(?:([=<>!]=?|<>)\\s*)?((?:\\d*\\.)?\\d+)\\s*(K|M|G|)B?$#Di', $operator, $matches)) {
throw new \RectorPrefix20210611\Nette\InvalidArgumentException('Invalid size predicate format.');
}
[, $operator, $size, $unit] = $matches;
static $units = ['' => 1, 'k' => 1000.0, 'm' => 1000000.0, 'g' => 1000000000.0];
$size *= $units[\strtolower($unit)];
$operator = $operator ?: '=';
}
return $this->filter(function (\RecursiveDirectoryIterator $file) use($operator, $size) : bool {
return self::compare($file->getSize(), $operator, $size);
});
}
/**
* Restricts the search by modified time.
* @param string $operator "[operator] [date]" example: >1978-01-23
* @param string|int|\DateTimeInterface $date
* @return static
*/
public function date(string $operator, $date = null)
{
if (\func_num_args() === 1) {
// in $operator is predicate
if (!\preg_match('#^(?:([=<>!]=?|<>)\\s*)?(.+)$#Di', $operator, $matches)) {
throw new \RectorPrefix20210611\Nette\InvalidArgumentException('Invalid date predicate format.');
}
[, $operator, $date] = $matches;
$operator = $operator ?: '=';
}
$date = \RectorPrefix20210611\Nette\Utils\DateTime::from($date)->format('U');
return $this->filter(function (\RecursiveDirectoryIterator $file) use($operator, $date) : bool {
return self::compare($file->getMTime(), $operator, $date);
});
}
/**
* Compares two values.
*/
public static function compare($l, string $operator, $r) : bool
{
switch ($operator) {
case '>':
return $l > $r;
case '>=':
return $l >= $r;
case '<':
return $l < $r;
case '<=':
return $l <= $r;
case '=':
case '==':
return $l == $r;
case '!':
case '!=':
case '<>':
return $l != $r;
default:
throw new \RectorPrefix20210611\Nette\InvalidArgumentException("Unknown operator {$operator}.");
}
}
/********************* extension methods ****************d*g**/
public function __call(string $name, array $args)
{
return isset(self::$extMethods[$name]) ? self::$extMethods[$name]($this, ...$args) : \RectorPrefix20210611\Nette\Utils\ObjectHelpers::strictCall(\get_class($this), $name, \array_keys(self::$extMethods));
}
public static function extensionMethod(string $name, callable $callback) : void
{
self::$extMethods[$name] = $callback;
}
}

View File

@ -21,8 +21,8 @@ if (!class_exists('SomeTestCase', false) && !interface_exists('SomeTestCase', fa
if (!class_exists('CheckoutEntityFactory', false) && !interface_exists('CheckoutEntityFactory', false) && !trait_exists('CheckoutEntityFactory', false)) {
spl_autoload_call('RectorPrefix20210611\CheckoutEntityFactory');
}
if (!class_exists('ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9', false) && !interface_exists('ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9', false) && !trait_exists('ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9', false)) {
spl_autoload_call('RectorPrefix20210611\ComposerAutoloaderInitfd1d68ed85dbe20b26c5f8338bc2c1d9');
if (!class_exists('ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea', false) && !interface_exists('ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea', false) && !trait_exists('ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea', false)) {
spl_autoload_call('RectorPrefix20210611\ComposerAutoloaderInit9fbbffeb6d398152232255cef95e7fea');
}
if (!class_exists('Doctrine\Inflector\Inflector', false) && !interface_exists('Doctrine\Inflector\Inflector', false) && !trait_exists('Doctrine\Inflector\Inflector', false)) {
spl_autoload_call('RectorPrefix20210611\Doctrine\Inflector\Inflector');
@ -3323,9 +3323,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20210611\print_node(...func_get_args());
}
}
if (!function_exists('composerRequirefd1d68ed85dbe20b26c5f8338bc2c1d9')) {
function composerRequirefd1d68ed85dbe20b26c5f8338bc2c1d9() {
return \RectorPrefix20210611\composerRequirefd1d68ed85dbe20b26c5f8338bc2c1d9(...func_get_args());
if (!function_exists('composerRequire9fbbffeb6d398152232255cef95e7fea')) {
function composerRequire9fbbffeb6d398152232255cef95e7fea() {
return \RectorPrefix20210611\composerRequire9fbbffeb6d398152232255cef95e7fea(...func_get_args());
}
}
if (!function_exists('parseArgs')) {