From e8641d822e520c31eee8e3b7254ad4e0e2d6723e Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 5 Dec 2023 22:12:13 +0100 Subject: [PATCH 01/12] CacheExtension, FileStorage: checks whether directory is absolute --- src/Bridges/CacheDI/CacheExtension.php | 15 ++++++++------- src/Caching/Storages/FileStorage.php | 4 ++-- tests/Storages/FileStorage.exceptions.phpt | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Bridges/CacheDI/CacheExtension.php b/src/Bridges/CacheDI/CacheExtension.php index a221646d..7acb7d26 100644 --- a/src/Bridges/CacheDI/CacheExtension.php +++ b/src/Bridges/CacheDI/CacheExtension.php @@ -10,6 +10,7 @@ namespace Nette\Bridges\CacheDI; use Nette; +use Nette\Utils\FileSystem; /** @@ -17,19 +18,19 @@ */ final class CacheExtension extends Nette\DI\CompilerExtension { - private string $tempDir; - - - public function __construct(string $tempDir) - { - $this->tempDir = $tempDir; + public function __construct( + private string $tempDir, + ) { } public function loadConfiguration() { + if (!FileSystem::isAbsolute($this->tempDir)) { + throw new Nette\InvalidArgumentException("Cache directory must be absolute, '$this->tempDir' given."); + } $dir = $this->tempDir . '/cache'; - Nette\Utils\FileSystem::createDir($dir); + FileSystem::createDir($dir); if (!is_writable($dir)) { throw new Nette\InvalidStateException("Make directory '$dir' writable."); } diff --git a/src/Caching/Storages/FileStorage.php b/src/Caching/Storages/FileStorage.php index d0e48c6c..2c24d5bb 100644 --- a/src/Caching/Storages/FileStorage.php +++ b/src/Caching/Storages/FileStorage.php @@ -57,8 +57,8 @@ class FileStorage implements Nette\Caching\Storage public function __construct(string $dir, ?Journal $journal = null) { - if (!is_dir($dir)) { - throw new Nette\DirectoryNotFoundException("Directory '$dir' not found."); + if (!is_dir($dir) || !Nette\Utils\FileSystem::isAbsolute($dir)) { + throw new Nette\DirectoryNotFoundException("Directory '$dir' not found or is not absolute."); } $this->dir = $dir; diff --git a/tests/Storages/FileStorage.exceptions.phpt b/tests/Storages/FileStorage.exceptions.phpt index e3d91059..9af92cd3 100644 --- a/tests/Storages/FileStorage.exceptions.phpt +++ b/tests/Storages/FileStorage.exceptions.phpt @@ -17,7 +17,7 @@ require __DIR__ . '/../bootstrap.php'; Assert::exception( fn() => new FileStorage(getTempDir() . '/missing'), Nette\DirectoryNotFoundException::class, - "Directory '%a%' not found.", + "Directory '%a%' not found or is not absolute.", ); From 21c2b5f4e71e2d23134789d3fb132fe4be5bde6b Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Wed, 8 Nov 2023 22:39:40 +0100 Subject: [PATCH 02/12] Latte: sets Tag::$node --- composer.json | 5 ++++- src/Bridges/CacheLatte/Nodes/CacheNode.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 8b5b7d84..c1bd8179 100644 --- a/composer.json +++ b/composer.json @@ -22,10 +22,13 @@ "require-dev": { "nette/tester": "^2.4", "nette/di": "^3.1 || ^4.0", - "latte/latte": "^2.11 || ^3.0", + "latte/latte": "^2.11 || ^3.0.12", "tracy/tracy": "^2.9", "phpstan/phpstan": "^1.0" }, + "conflict": { + "latte/latte": ">=3.0.0 <3.0.12" + }, "suggest": { "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" }, diff --git a/src/Bridges/CacheLatte/Nodes/CacheNode.php b/src/Bridges/CacheLatte/Nodes/CacheNode.php index 02e029ff..5e41a7e1 100644 --- a/src/Bridges/CacheLatte/Nodes/CacheNode.php +++ b/src/Bridges/CacheLatte/Nodes/CacheNode.php @@ -30,7 +30,7 @@ class CacheNode extends StatementNode /** @return \Generator<int, ?array, array{AreaNode, ?Tag}, static> */ public static function create(Tag $tag): \Generator { - $node = new static; + $node = $tag->node = new static; $node->args = $tag->parser->parseArguments(); [$node->content, $endTag] = yield; $node->endLine = $endTag?->position; From 4217032412fc6336c3b613b249785f657e984ec8 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Tue, 29 Aug 2023 13:52:27 +0200 Subject: [PATCH 03/12] removed Nette\SmartObject --- src/Caching/Cache.php | 2 -- src/Caching/OutputHelper.php | 2 -- src/Caching/Storages/DevNullStorage.php | 2 -- src/Caching/Storages/FileStorage.php | 2 -- src/Caching/Storages/MemcachedStorage.php | 2 -- src/Caching/Storages/MemoryStorage.php | 2 -- src/Caching/Storages/SQLiteJournal.php | 2 -- src/Caching/Storages/SQLiteStorage.php | 2 -- 8 files changed, 16 deletions(-) diff --git a/src/Caching/Cache.php b/src/Caching/Cache.php index b9ee6dba..eda389e3 100644 --- a/src/Caching/Cache.php +++ b/src/Caching/Cache.php @@ -17,8 +17,6 @@ */ class Cache { - use Nette\SmartObject; - /** dependency */ public const Priority = 'priority', diff --git a/src/Caching/OutputHelper.php b/src/Caching/OutputHelper.php index 5019c24d..2256a9bb 100644 --- a/src/Caching/OutputHelper.php +++ b/src/Caching/OutputHelper.php @@ -17,8 +17,6 @@ */ class OutputHelper { - use Nette\SmartObject; - public array $dependencies = []; private ?Cache $cache; private mixed $key; diff --git a/src/Caching/Storages/DevNullStorage.php b/src/Caching/Storages/DevNullStorage.php index 3106a212..aceea163 100644 --- a/src/Caching/Storages/DevNullStorage.php +++ b/src/Caching/Storages/DevNullStorage.php @@ -17,8 +17,6 @@ */ class DevNullStorage implements Nette\Caching\Storage { - use Nette\SmartObject; - public function read(string $key): mixed { return null; diff --git a/src/Caching/Storages/FileStorage.php b/src/Caching/Storages/FileStorage.php index 2c24d5bb..f0400135 100644 --- a/src/Caching/Storages/FileStorage.php +++ b/src/Caching/Storages/FileStorage.php @@ -18,8 +18,6 @@ */ class FileStorage implements Nette\Caching\Storage { - use Nette\SmartObject; - /** * Atomic thread safe logic: * diff --git a/src/Caching/Storages/MemcachedStorage.php b/src/Caching/Storages/MemcachedStorage.php index e59582ee..03af23b3 100644 --- a/src/Caching/Storages/MemcachedStorage.php +++ b/src/Caching/Storages/MemcachedStorage.php @@ -18,8 +18,6 @@ */ class MemcachedStorage implements Nette\Caching\Storage, Nette\Caching\BulkReader { - use Nette\SmartObject; - /** @internal cache structure */ private const MetaCallbacks = 'callbacks', diff --git a/src/Caching/Storages/MemoryStorage.php b/src/Caching/Storages/MemoryStorage.php index 9f92d772..55abc051 100644 --- a/src/Caching/Storages/MemoryStorage.php +++ b/src/Caching/Storages/MemoryStorage.php @@ -17,8 +17,6 @@ */ class MemoryStorage implements Nette\Caching\Storage { - use Nette\SmartObject; - private array $data = []; diff --git a/src/Caching/Storages/SQLiteJournal.php b/src/Caching/Storages/SQLiteJournal.php index b3be748a..26747834 100644 --- a/src/Caching/Storages/SQLiteJournal.php +++ b/src/Caching/Storages/SQLiteJournal.php @@ -18,8 +18,6 @@ */ class SQLiteJournal implements Journal { - use Nette\SmartObject; - /** @string */ private $path; private \PDO $pdo; diff --git a/src/Caching/Storages/SQLiteStorage.php b/src/Caching/Storages/SQLiteStorage.php index 4baf770a..5301a4e7 100644 --- a/src/Caching/Storages/SQLiteStorage.php +++ b/src/Caching/Storages/SQLiteStorage.php @@ -18,8 +18,6 @@ */ class SQLiteStorage implements Nette\Caching\Storage, Nette\Caching\BulkReader { - use Nette\SmartObject; - private \PDO $pdo; From 559874b7189aec399d6eaa884893d75f4c155b4e Mon Sep 17 00:00:00 2001 From: g-battaglia <battaglia.giacomo@icloud.com> Date: Wed, 11 Oct 2023 15:46:46 +0200 Subject: [PATCH 04/12] typo --- src/Bridges/CacheDI/CacheExtension.php | 2 +- src/Caching/Cache.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bridges/CacheDI/CacheExtension.php b/src/Bridges/CacheDI/CacheExtension.php index 7acb7d26..05b41ae7 100644 --- a/src/Bridges/CacheDI/CacheExtension.php +++ b/src/Bridges/CacheDI/CacheExtension.php @@ -24,7 +24,7 @@ public function __construct( } - public function loadConfiguration() + public function loadConfiguration(): void { if (!FileSystem::isAbsolute($this->tempDir)) { throw new Nette\InvalidArgumentException("Cache directory must be absolute, '$this->tempDir' given."); diff --git a/src/Caching/Cache.php b/src/Caching/Cache.php index eda389e3..69ff331f 100644 --- a/src/Caching/Cache.php +++ b/src/Caching/Cache.php @@ -179,7 +179,7 @@ public function bulkLoad(array $keys, ?callable $generator = null): array * Writes item into the cache. * Dependencies are: * - Cache::Priority => (int) priority - * - Cache::Expire => (timestamp) expiration + * - Cache::Expire => (timestamp) expiration, infinite if null * - Cache::Sliding => (bool) use sliding expiration? * - Cache::Tags => (array) tags * - Cache::Files => (array|string) file names From 9a09321d468f0851d0a1ed4f7069b508289d53cb Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 1 Mar 2021 15:27:42 +0100 Subject: [PATCH 05/12] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c1bd8179..4f1abbba 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.0-dev" } } } From bf8b8d2c073f48e40020b65725cfd21f999542b4 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 13 Jan 2023 04:41:49 +0100 Subject: [PATCH 06/12] composer: updated dependencies --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4f1abbba..546caccc 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,7 @@ ], "require": { "php": "8.0 - 8.3", - "nette/finder": "^2.4 || ^3.0", - "nette/utils": "^3.2 || ~4.0.0" + "nette/utils": "^4.0" }, "require-dev": { "nette/tester": "^2.4", From 80ae66acb4141ba848d056b1f4fec1e02b558c6a Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 13 Jan 2023 04:41:43 +0100 Subject: [PATCH 07/12] Storage::read() added return typehint (BC break) --- src/Caching/Storage.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Caching/Storage.php b/src/Caching/Storage.php index e9565d8b..16b80942 100644 --- a/src/Caching/Storage.php +++ b/src/Caching/Storage.php @@ -17,9 +17,8 @@ interface Storage { /** * Read from cache. - * @return mixed */ - function read(string $key); + function read(string $key): mixed; /** * Prevents item reading and writing. Lock is released by write() or remove(). From 40dfe7a0392c7abd8b48e112d7cb8c094b38d3d2 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Fri, 13 Jan 2023 04:48:57 +0100 Subject: [PATCH 08/12] deprecated stuff --- src/Caching/Cache.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Caching/Cache.php b/src/Caching/Cache.php index 69ff331f..245836b5 100644 --- a/src/Caching/Cache.php +++ b/src/Caching/Cache.php @@ -64,9 +64,7 @@ class Cache public const ALL = self::All; /** @internal */ - public const - NamespaceSeparator = "\x00", - NAMESPACE_SEPARATOR = self::NamespaceSeparator; + public const NamespaceSeparator = "\x00"; private Storage $storage; private string $namespace; @@ -346,6 +344,7 @@ public function capture(mixed $key): ?OutputHelper */ public function start($key): ?OutputHelper { + trigger_error(__METHOD__ . '() was renamed to capture()', E_USER_DEPRECATED); return $this->capture($key); } From 5080f06f33a96c762df55e1c659f237189c9efe0 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Mon, 14 Aug 2023 21:27:06 +0200 Subject: [PATCH 09/12] removed support for Latte 2 --- composer.json | 4 +- src/Bridges/CacheLatte/CacheMacro.php | 168 ------------------ tests/Bridges.Latte2/CacheMacro.cache.phpt | 48 ----- .../CacheMacro.createCache.phpt | 49 ----- .../expected/CacheMacro.cache.html | 8 - .../expected/CacheMacro.cache.inc.php | 12 -- .../expected/CacheMacro.cache.php | 28 --- tests/Bridges.Latte2/templates/cache.latte | 9 - .../templates/include.cache.latte | 5 - tests/Bridges.Latte3/Runtime.phpt | 4 - tests/Bridges.Latte3/{cache}.phpt | 4 - 11 files changed, 2 insertions(+), 337 deletions(-) delete mode 100644 src/Bridges/CacheLatte/CacheMacro.php delete mode 100644 tests/Bridges.Latte2/CacheMacro.cache.phpt delete mode 100644 tests/Bridges.Latte2/CacheMacro.createCache.phpt delete mode 100644 tests/Bridges.Latte2/expected/CacheMacro.cache.html delete mode 100644 tests/Bridges.Latte2/expected/CacheMacro.cache.inc.php delete mode 100644 tests/Bridges.Latte2/expected/CacheMacro.cache.php delete mode 100644 tests/Bridges.Latte2/templates/cache.latte delete mode 100644 tests/Bridges.Latte2/templates/include.cache.latte diff --git a/composer.json b/composer.json index 546caccc..fddef604 100644 --- a/composer.json +++ b/composer.json @@ -21,12 +21,12 @@ "require-dev": { "nette/tester": "^2.4", "nette/di": "^3.1 || ^4.0", - "latte/latte": "^2.11 || ^3.0.12", + "latte/latte": "^3.0.12", "tracy/tracy": "^2.9", "phpstan/phpstan": "^1.0" }, "conflict": { - "latte/latte": ">=3.0.0 <3.0.12" + "latte/latte": "<3.0.12" }, "suggest": { "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" diff --git a/src/Bridges/CacheLatte/CacheMacro.php b/src/Bridges/CacheLatte/CacheMacro.php deleted file mode 100644 index d6aeb5db..00000000 --- a/src/Bridges/CacheLatte/CacheMacro.php +++ /dev/null @@ -1,168 +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 Nette\Bridges\CacheLatte; - -use Latte; -use Nette; -use Nette\Caching\Cache; - - -/** - * Macro {cache} ... {/cache} for Latte v2 - */ -final class CacheMacro implements Latte\IMacro -{ - use Nette\SmartObject; - - private bool $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(Latte\MacroNode $node) - { - if ($node->modifiers) { - throw new Latte\CompileException('Modifiers are not allowed in ' . $node->getNotation()); - } - - $this->used = true; - $node->empty = false; - $node->openingCode = Latte\PhpWriter::using($node) - ->write( - '<?php if (Nette\Bridges\CacheLatte\CacheMacro::createCache($this->global->cacheStorage, %var, $this->global->cacheStack, %node.array?)) /* line %var */ try { ?>', - Nette\Utils\Random::generate(), - $node->startLine, - ); - } - - - /** - * Node is closed. - * @return void - */ - public function nodeClosed(Latte\MacroNode $node) - { - $node->closingCode = 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(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[Cache::Files][] = $file; - } - } - } - - - /** - * Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started. - */ - public static function createCache( - Nette\Caching\Storage $cacheStorage, - string $key, - ?array &$parents, - ?array $args = null, - ): Nette\Caching\OutputHelper|\stdClass|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[Cache::Items][] = $key; - } - - $cache = new Cache($cacheStorage, 'Nette.Templating.Cache'); - if ($helper = $cache->capture($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 Nette\Caching\OutputHelper) { - return; - } - - if (isset($args['dependencies'])) { - $args += $args['dependencies'](); - } - - if (isset($args['expire'])) { - $args['expiration'] = $args['expire']; // back compatibility - } - - $helper->dependencies[Cache::Tags] = $args['tags'] ?? null; - $helper->dependencies[Cache::Expire] = $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 Nette\Caching\OutputHelper) { - $helper->rollback(); - } - } -} diff --git a/tests/Bridges.Latte2/CacheMacro.cache.phpt b/tests/Bridges.Latte2/CacheMacro.cache.phpt deleted file mode 100644 index 8dfa099f..00000000 --- a/tests/Bridges.Latte2/CacheMacro.cache.phpt +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -/** - * Test: {cache ...} - */ - -declare(strict_types=1); - -use Nette\Bridges\CacheLatte\CacheMacro; -use Tester\Assert; - -require __DIR__ . '/../bootstrap.php'; - -if (version_compare(Latte\Engine::VERSION, '3', '>')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -$latte = new Latte\Engine; -$latte->setTempDirectory(getTempDir()); -$latte->addMacro('cache', new CacheMacro($latte->getCompiler())); -$latte->addProvider('cacheStorage', new Nette\Caching\Storages\MemoryStorage); - -$params['title'] = 'Hello'; -$params['id'] = 456; - -Assert::matchFile( - __DIR__ . '/expected/CacheMacro.cache.php', - $latte->compile(__DIR__ . '/templates/cache.latte'), -); -Assert::matchFile( - __DIR__ . '/expected/CacheMacro.cache.html', - $latte->renderToString( - __DIR__ . '/templates/cache.latte', - $params, - ), -); -Assert::matchFile( - __DIR__ . '/expected/CacheMacro.cache.html', - $latte->renderToString( - __DIR__ . '/templates/cache.latte', - $params, - ), -); -Assert::matchFile( - __DIR__ . '/expected/CacheMacro.cache.inc.php', - file_get_contents($latte->getCacheFile(__DIR__ . strtr('/templates/include.cache.latte', '/', DIRECTORY_SEPARATOR))), -); diff --git a/tests/Bridges.Latte2/CacheMacro.createCache.phpt b/tests/Bridges.Latte2/CacheMacro.createCache.phpt deleted file mode 100644 index 5cd26089..00000000 --- a/tests/Bridges.Latte2/CacheMacro.createCache.phpt +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -/** - * Test: Nette\Bridges\CacheLatte\CacheMacro createCache() - */ - -declare(strict_types=1); - -use Nette\Bridges\CacheLatte\CacheMacro; -use Nette\Caching\Cache; -use Nette\Caching\Storages\DevNullStorage; -use Tester\Assert; - -require __DIR__ . '/../bootstrap.php'; - -if (version_compare(Latte\Engine::VERSION, '3', '>')) { - Tester\Environment::skip('Test for Latte 2'); -} - - -test('', function () { - $parents = []; - $dp = [Cache::Tags => ['rum', 'cola']]; - $outputHelper = CacheMacro::createCache(new DevNullStorage, 'test', $parents); - Assert::type(Nette\Caching\OutputHelper::class, $outputHelper); - CacheMacro::endCache($parents, $dp); - Assert::same($dp + [Cache::Expire => '+ 7 days'], $outputHelper->dependencies); -}); - -test('', function () { - $parents = []; - $dp = [Cache::Tags => ['rum', 'cola']]; - $dpFallback = fn() => $dp; - $outputHelper = CacheMacro::createCache(new DevNullStorage, 'test', $parents); - CacheMacro::endCache($parents, ['dependencies' => $dpFallback]); - Assert::same($dp + [Cache::Expire => '+ 7 days'], $outputHelper->dependencies); -}); - -test('', function () { - $parents = []; - $dp = [ - Cache::Tags => ['rum', 'cola'], - Cache::Expire => '+ 1 days', - ]; - $dpFallback = fn() => $dp; - $outputHelper = CacheMacro::createCache(new DevNullStorage, 'test', $parents); - CacheMacro::endCache($parents, ['dependencies' => $dpFallback]); - Assert::same($dp, $outputHelper->dependencies); -}); diff --git a/tests/Bridges.Latte2/expected/CacheMacro.cache.html b/tests/Bridges.Latte2/expected/CacheMacro.cache.html deleted file mode 100644 index 0fe8eebc..00000000 --- a/tests/Bridges.Latte2/expected/CacheMacro.cache.html +++ /dev/null @@ -1,8 +0,0 @@ -Noncached content - - -<h1>HELLO</h1> - -<p>Included file (11)</p> - - hello diff --git a/tests/Bridges.Latte2/expected/CacheMacro.cache.inc.php b/tests/Bridges.Latte2/expected/CacheMacro.cache.inc.php deleted file mode 100644 index af95b58b..00000000 --- a/tests/Bridges.Latte2/expected/CacheMacro.cache.inc.php +++ /dev/null @@ -1,12 +0,0 @@ -<?php -%A% - if (Nette\Bridges\CacheLatte\CacheMacro::createCache($this->global->cacheStorage, '%[\w]+%', $this->global->cacheStack)) /* line %d% */ try { - echo ' '; - echo LR\Filters::escapeHtmlText(($this->filters->lower)($title)) /* line %d% */; - echo "\n"; - Nette\Bridges\CacheLatte\CacheMacro::endCache($this->global->cacheStack) /* line %d% */; - } catch (\Throwable $ʟ_e) { - Nette\Bridges\CacheLatte\CacheMacro::rollback($this->global->cacheStack); - throw $ʟ_e; - } -%A% diff --git a/tests/Bridges.Latte2/expected/CacheMacro.cache.php b/tests/Bridges.Latte2/expected/CacheMacro.cache.php deleted file mode 100644 index 491297ec..00000000 --- a/tests/Bridges.Latte2/expected/CacheMacro.cache.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -%A% - echo 'Noncached content - -'; - if (Nette\Bridges\CacheLatte\CacheMacro::createCache($this->global->cacheStorage, '%[\w]+%', $this->global->cacheStack, [$id, 'tags' => 'mytag'])) /* line %d% */ try { - echo ' -<h1>'; - echo LR\Filters::escapeHtmlText(($this->filters->upper)($title)) /* line %d% */; - echo '</h1> - -'; - $this->createTemplate('include.cache.latte', ['localvar' => 11] + $this->params, 'include')->renderToContentType('html') /* line %d% */; - echo "\n"; - Nette\Bridges\CacheLatte\CacheMacro::endCache($this->global->cacheStack, [$id, 'tags' => 'mytag']) /* line %d% */; - } catch (\Throwable $ʟ_e) { - Nette\Bridges\CacheLatte\CacheMacro::rollback($this->global->cacheStack); - throw $ʟ_e; - } -%A% - } - - - public function prepare(): void - { -%A% - Nette\Bridges\CacheLatte\CacheMacro::initRuntime($this); -%A% diff --git a/tests/Bridges.Latte2/templates/cache.latte b/tests/Bridges.Latte2/templates/cache.latte deleted file mode 100644 index 5155ee77..00000000 --- a/tests/Bridges.Latte2/templates/cache.latte +++ /dev/null @@ -1,9 +0,0 @@ -Noncached content - -{cache $id, tags => 'mytag'} - -<h1>{$title|upper}</h1> - -{include 'include.cache.latte', 'localvar' => 11} - -{/cache} diff --git a/tests/Bridges.Latte2/templates/include.cache.latte b/tests/Bridges.Latte2/templates/include.cache.latte deleted file mode 100644 index 595329b6..00000000 --- a/tests/Bridges.Latte2/templates/include.cache.latte +++ /dev/null @@ -1,5 +0,0 @@ -<p>Included file ({$localvar})</p> - -{cache} - {$title|lower} -{/cache} diff --git a/tests/Bridges.Latte3/Runtime.phpt b/tests/Bridges.Latte3/Runtime.phpt index 83a5121b..2360125e 100644 --- a/tests/Bridges.Latte3/Runtime.phpt +++ b/tests/Bridges.Latte3/Runtime.phpt @@ -9,10 +9,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - test('', function () { $runtime = new Runtime(new DevNullStorage); diff --git a/tests/Bridges.Latte3/{cache}.phpt b/tests/Bridges.Latte3/{cache}.phpt index e275b259..cb5ea876 100644 --- a/tests/Bridges.Latte3/{cache}.phpt +++ b/tests/Bridges.Latte3/{cache}.phpt @@ -11,10 +11,6 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -if (version_compare(Latte\Engine::VERSION, '3', '<')) { - Tester\Environment::skip('Test for Latte 3'); -} - $latte = new Latte\Engine; $latte->setTempDirectory(getTempDir()); From 0c542ec90822253d6f7bd7b4ae0482e5b76a3d39 Mon Sep 17 00:00:00 2001 From: David Grudl <david@grudl.com> Date: Sun, 27 Aug 2023 13:41:56 +0200 Subject: [PATCH 10/12] removed legacy services names --- src/Bridges/CacheDI/CacheExtension.php | 8 -------- tests/Bridges.DI/CacheExtension.phpt | 4 ---- 2 files changed, 12 deletions(-) diff --git a/src/Bridges/CacheDI/CacheExtension.php b/src/Bridges/CacheDI/CacheExtension.php index 05b41ae7..d398de39 100644 --- a/src/Bridges/CacheDI/CacheExtension.php +++ b/src/Bridges/CacheDI/CacheExtension.php @@ -46,13 +46,5 @@ public function loadConfiguration(): void $builder->addDefinition($this->prefix('storage')) ->setType(Nette\Caching\Storage::class) ->setFactory(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')); - } } } diff --git a/tests/Bridges.DI/CacheExtension.phpt b/tests/Bridges.DI/CacheExtension.phpt index cc735739..9f4c4703 100644 --- a/tests/Bridges.DI/CacheExtension.phpt +++ b/tests/Bridges.DI/CacheExtension.phpt @@ -28,8 +28,4 @@ test('', function () { $storage = $container->getService('cache.storage'); Assert::type(Nette\Caching\Storages\FileStorage::class, $storage); - - // aliases - Assert::same($journal, $container->getService('nette.cacheJournal')); - Assert::same($storage, $container->getService('cacheStorage')); }); From 48ba8dcba5a23a0469038f23ae54f8ef5ee026b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Km=C3=ADnek?= <m@kminet.eu> Date: Thu, 4 Jan 2024 11:26:58 +0100 Subject: [PATCH 11/12] feat: Implement ability to drop cache keys using combination of OR and AND logic --- src/Caching/Cache.php | 4 +-- src/Caching/CacheSelector.php | 34 ++++++++++++++++++++++++++ src/Caching/Storages/SQLiteJournal.php | 18 +++++++++++--- 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/Caching/CacheSelector.php diff --git a/src/Caching/Cache.php b/src/Caching/Cache.php index 245836b5..4b20a7ad 100644 --- a/src/Caching/Cache.php +++ b/src/Caching/Cache.php @@ -277,13 +277,13 @@ public function remove(mixed $key): void * Removes items from the cache by conditions. * Conditions are: * - Cache::Priority => (int) priority - * - Cache::Tags => (array) tags + * - Cache::Tags => (array) tags | CacheSelector * - Cache::All => true */ public function clean(?array $conditions = null): void { $conditions = (array) $conditions; - if (isset($conditions[self::Tags])) { + if (isset($conditions[self::Tags]) && !$conditions[self::Tags] instanceof CacheSelector) { $conditions[self::Tags] = array_values((array) $conditions[self::Tags]); } diff --git a/src/Caching/CacheSelector.php b/src/Caching/CacheSelector.php new file mode 100644 index 00000000..b554c7db --- /dev/null +++ b/src/Caching/CacheSelector.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +namespace Nette\Caching; + +class CacheSelector +{ + private array $conditions; + + + /** + * Adds where condition, more calls appends with AND. + * Pass tags as array to append with OR. + * + * Example: + * (new CacheSelector())->where("animal")->where("dog")->where(["brown", "white"]) + * Creates condition looking for entities having tags animal and dog and (brown / white). Will not match entity, tagged animal, dog, black. + * + * @param string|array $tags tag names to select + */ + public function where(string|array $tags): static + { + $this->conditions[] = $tags; + + return $this; + } + + + public function getConditions(): array + { + return $this->conditions; + } +} diff --git a/src/Caching/Storages/SQLiteJournal.php b/src/Caching/Storages/SQLiteJournal.php index 26747834..d2b9e97b 100644 --- a/src/Caching/Storages/SQLiteJournal.php +++ b/src/Caching/Storages/SQLiteJournal.php @@ -11,6 +11,7 @@ use Nette; use Nette\Caching\Cache; +use Nette\Caching\CacheSelector; /** @@ -109,9 +110,20 @@ public function clean(array $conditions): ?array $unions = $args = []; if (!empty($conditions[Cache::Tags])) { - $tags = (array) $conditions[Cache::Tags]; - $unions[] = 'SELECT DISTINCT key FROM tags WHERE tag IN (?' . str_repeat(', ?', count($tags) - 1) . ')'; - $args = $tags; + if ($conditions[Cache::Tags] instanceof CacheSelector) { + $intersects = []; + foreach ($conditions[Cache::Tags]->getConditions() as $condition) { + $intersects[] = 'SELECT `key` FROM `tags` WHERE `tag` IN (?' . str_repeat(', ?', count((array) $condition) - 1) . ')'; + is_array($condition) + ? array_push($args, ...$condition) + : array_push($args, $condition); + } + $unions[] = implode(' INTERSECT ', $intersects); + } else { + $tags = (array) $conditions[Cache::Tags]; + $unions[] = 'SELECT DISTINCT key FROM tags WHERE tag IN (?' . str_repeat(', ?', count($tags) - 1) . ')'; + $args = $tags; + } } if (!empty($conditions[Cache::Priority])) { From c071f017fa15c81ffcdd5de97bfdafdd301764e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Km=C3=ADnek?= <m@kminet.eu> Date: Thu, 4 Jan 2024 14:34:37 +0100 Subject: [PATCH 12/12] feat: Add missing DISTINCT statements --- src/Caching/Storages/SQLiteJournal.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Caching/Storages/SQLiteJournal.php b/src/Caching/Storages/SQLiteJournal.php index d2b9e97b..592d39b1 100644 --- a/src/Caching/Storages/SQLiteJournal.php +++ b/src/Caching/Storages/SQLiteJournal.php @@ -113,7 +113,7 @@ public function clean(array $conditions): ?array if ($conditions[Cache::Tags] instanceof CacheSelector) { $intersects = []; foreach ($conditions[Cache::Tags]->getConditions() as $condition) { - $intersects[] = 'SELECT `key` FROM `tags` WHERE `tag` IN (?' . str_repeat(', ?', count((array) $condition) - 1) . ')'; + $intersects[] = 'SELECT DISTINCT key FROM tags WHERE tag IN (?' . str_repeat(', ?', count((array) $condition) - 1) . ')'; is_array($condition) ? array_push($args, ...$condition) : array_push($args, $condition);