From fca9f93c6900f6780cbd2eba7e597d069e878496 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 17:23:38 +0200 Subject: [PATCH 01/11] Scope cache activation Until now, the cache tagging/invalidation was active by default, and you could disable and enable it again. From now on, the cache tagging/invalidation is inactive by default. It will be enabled for certain scopes automatically: - in console mode it will be activated via a `ConsoleEvents::COMMAND` listener, so basically nothing changes here - in HTTP mode, users can switch between "request" and "controller" modes - the "request" mode is basically the previous behavior - the "controller" mode scopes the cache to be only active once the controller gets called, so it ignores everything "generic" that happens before The "controller" mode is the new default, as it skips tagging of elements that are loaded *before* the request-specific stuff happens, which means that e.g., - the parent documents don't get tagged anymore if you call a document route (as Pimcore may load all of them to determine e.g., the document's language) - the root document doesn't get tagged anymore if you call a non-document route (as Pimcore loads it as a "fallback" document automatically) --- config/services.php | 34 +- doc/8-disable-caching-behavior.md | 5 +- .../OnlyWhenActiveCacheInvalidator.php | 6 +- .../OnlyWhenActiveResponseTagger.php | 6 +- src/CacheActivator.php | 21 +- src/CacheScope.php | 46 ++ src/DependencyInjection/Configuration.php | 16 +- .../NeustaPimcoreHttpCacheExtension.php | 4 + .../ConsoleCacheScopeListener.php | 25 ++ src/EventListener/HttpCacheScopeListener.php | 96 ++++ .../CollectConfigurationDataTest.php | 6 +- .../Integration/Helpers/ArrangeCacheTest.php | 31 -- .../Invalidation/CancelInvalidationTest.php | 14 +- .../InvalidateAdditionalTagTest.php | 43 +- .../Invalidation/InvalidateAssetTest.php | 10 +- .../Invalidation/InvalidateDocumentTest.php | 12 +- .../Invalidation/InvalidateObjectTest.php | 10 +- .../Tagging/CollectTagsDataTest.php | 28 +- .../Tagging/TagAdditionalTagTest.php | 18 +- tests/Integration/Tagging/TagAssetTest.php | 16 +- tests/Integration/Tagging/TagDocumentTest.php | 50 +-- tests/Integration/Tagging/TagObjectTest.php | 20 +- .../OnlyWhenActiveCacheInvalidatorTest.php | 14 +- .../OnlyWhenActiveResponseTaggerTest.php | 14 +- tests/Unit/CacheActivatorTest.php | 45 -- tests/Unit/CacheScopeTest.php | 84 ++++ .../HttpCacheScopeListenerTest.php | 425 ++++++++++++++++++ tests/app/config/services.php | 3 - 28 files changed, 862 insertions(+), 240 deletions(-) create mode 100644 src/CacheScope.php create mode 100644 src/EventListener/ConsoleCacheScopeListener.php create mode 100644 src/EventListener/HttpCacheScopeListener.php delete mode 100644 tests/Integration/Helpers/ArrangeCacheTest.php delete mode 100644 tests/Unit/CacheActivatorTest.php create mode 100644 tests/Unit/CacheScopeTest.php create mode 100644 tests/Unit/EventListener/HttpCacheScopeListenerTest.php diff --git a/config/services.php b/config/services.php index 3c06ca5..f285814 100644 --- a/config/services.php +++ b/config/services.php @@ -1,4 +1,4 @@ -services(); $services->set('neusta_pimcore_http_cache.cache_activator', CacheActivator::class) - ->alias(CacheActivator::class, 'neusta_pimcore_http_cache.cache_activator'); + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%service_id%" is deprecated, use "neusta_pimcore_http_cache.cache_scope" instead.') + ->alias(CacheActivator::class, 'neusta_pimcore_http_cache.cache_activator') + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "' . CacheScope::class . '" instead.'); + + $services->set('neusta_pimcore_http_cache.cache_scope', CacheScope::class) + ->tag('kernel.reset', ['method' => 'reset']) + ->alias(CacheScope::class, 'neusta_pimcore_http_cache.cache_scope'); + + $services->set('neusta_pimcore_http_cache.cache_scope.console_listener', ConsoleCacheScopeListener::class) + ->arg('$cacheScope', service('neusta_pimcore_http_cache.cache_scope')) + ->autoconfigure(); + + $services->set('neusta_pimcore_http_cache.cache_scope.http_listener', HttpCacheScopeListener::class) + ->arg('$cacheScope', service('neusta_pimcore_http_cache.cache_scope')) + ->arg('$responseTagger', service('neusta_pimcore_http_cache.response_tagger')) + ->arg('$contextResolver', service(PimcoreContextResolver::class)) + ->arg('$documentResolver', service(DocumentResolver::class)) + ->arg('$collectFromRequest', abstract_arg('Set in the extension')) + ->arg('$tagFallbackDocument', abstract_arg('Set in the extension')) + ->autoconfigure(); $services->set('neusta_pimcore_http_cache.cache_invalidator', CacheInvalidatorAdapter::class) ->arg('$invalidator', service(CacheManager::class)); @@ -40,7 +64,7 @@ $services->set(null, OnlyWhenActiveCacheInvalidator::class) ->decorate('neusta_pimcore_http_cache.cache_invalidator', null, -100) - ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_activator')]); + ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_scope')]); $services->alias(CacheInvalidator::class, 'neusta_pimcore_http_cache.cache_invalidator'); @@ -53,7 +77,7 @@ $services->set(null, OnlyWhenActiveResponseTagger::class) ->decorate('neusta_pimcore_http_cache.response_tagger', null, -100) - ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_activator')]); + ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_scope')]); $services->set('.neusta_pimcore_http_cache.response_tagger.traceable', TraceableResponseTagger::class) ->decorate('neusta_pimcore_http_cache.response_tagger', null, 100) diff --git a/doc/8-disable-caching-behavior.md b/doc/8-disable-caching-behavior.md index 02771f2..9e11cb5 100644 --- a/doc/8-disable-caching-behavior.md +++ b/doc/8-disable-caching-behavior.md @@ -2,7 +2,7 @@ You may encounter situations where you need to disable the default caching behavior for specific requests. This is especially useful for testing purposes. -To achieve this, you can use the `CacheActivator` to disable tagging and invalidation behavior entirely. +To achieve this, you can use the `CacheScope` to disable tagging and invalidation behavior entirely. ### Example for disabling caching behavior in a specific test case ```php @@ -11,11 +11,10 @@ To achieve this, you can use the `CacheActivator` to disable tagging and invalid public function my_awesome_test_case(): void { // Disable the caching behavior - self::getContainer()->get(CacheActivator::class)->deactivateCaching(); + self::getContainer()->get(CacheScope::class)->disable(); // Your test code here self::assertSame('this is amazing!', $result); } ``` - diff --git a/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php b/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php index aeba428..90caca1 100644 --- a/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php +++ b/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php @@ -4,19 +4,19 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; final class OnlyWhenActiveCacheInvalidator implements CacheInvalidator { public function __construct( private readonly CacheInvalidator $inner, - private readonly CacheActivator $cacheActivator, + private readonly CacheScope $cacheScope, ) { } public function invalidate(CacheTags $tags): void { - if ($this->cacheActivator->isCachingActive()) { + if ($this->cacheScope->isActive()) { $this->inner->invalidate($tags); } } diff --git a/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php b/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php index 249fea4..3200178 100644 --- a/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php +++ b/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php @@ -4,19 +4,19 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; final class OnlyWhenActiveResponseTagger implements ResponseTagger { public function __construct( private readonly ResponseTagger $inner, - private readonly CacheActivator $cacheActivator, + private readonly CacheScope $cacheScope, ) { } public function tag(CacheTags $tags): void { - if ($this->cacheActivator->isCachingActive()) { + if ($this->cacheScope->isActive()) { $this->inner->tag($tags); } } diff --git a/src/CacheActivator.php b/src/CacheActivator.php index d875317..4c068f2 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -2,22 +2,31 @@ namespace Neusta\Pimcore\HttpCacheBundle; -final class CacheActivator +/** + * @deprecated since version 0.7, use {@see CacheScope} instead. + * + * @phpstan-ignore class.extendsFinalByPhpDoc + */ +final class CacheActivator extends CacheScope { - private bool $isCachingActive = true; - public function isCachingActive(): bool { - return $this->isCachingActive; + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + + return $this->isActive(); } public function activateCaching(): void { - $this->isCachingActive = true; + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + + $this->enable(); } public function deactivateCaching(): void { - $this->isCachingActive = false; + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + + $this->disable(); } } diff --git a/src/CacheScope.php b/src/CacheScope.php new file mode 100644 index 0000000..367106a --- /dev/null +++ b/src/CacheScope.php @@ -0,0 +1,46 @@ +active = true; + } + + /** + * Permanently disables the tag collection for the current request. + * + * Survives {@see enable()} calls. + */ + public function disable(): void + { + $this->disabled = true; + } + + public function isActive(): bool + { + return $this->active && !$this->disabled; + } + + public function reset(): void + { + $this->active = false; + $this->disabled = false; + } +} diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 6f93ccb..d6d6908 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -16,7 +16,17 @@ public function getConfigTreeBuilder(): TreeBuilder ->fixXmlConfig('element') ->fixXmlConfig('cache_type') ->children() + ->enumNode('scope') + ->info('When to start collecting cache tags. "controller" (default): only from kernel.controller onwards, elements loaded before (e.g. in kernel.request listeners) are not tagged. "request": collect from the very beginning of the request.') + ->values(['controller', 'request']) + ->defaultValue('controller') + ->end() + ->booleanNode('tag_fallback_document') + ->info('Whether to tag the response with the document found in the request (DynamicRouter::CONTENT_KEY) when it is only a fallback, i.e. it was not resolved by the matched route itself but is merely the nearest document by path. Default: false.') + ->defaultFalse() + ->end() ->arrayNode('elements') + ->info('Controls which element types are tracked.') ->addDefaultsIfNotSet() ->fixXmlConfig('asset') ->fixXmlConfig('document') @@ -30,7 +40,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayNode('types') ->info('Enable/disable cache handling for asset types.') ->beforeNormalization() - ->always(fn ($v) => $v + ['folder' => false]) + ->always(static fn ($v) => $v + ['folder' => false]) ->end() ->normalizeKeys(false) ->useAttributeAsKey('type') @@ -47,7 +57,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayNode('types') ->info('Enable/disable cache handling for document types.') ->beforeNormalization() - ->always(fn ($v) => $v + ['email' => false, 'folder' => false, 'hardlink' => false]) + ->always(static fn ($v) => $v + ['email' => false, 'folder' => false, 'hardlink' => false]) ->end() ->normalizeKeys(false) ->useAttributeAsKey('type') @@ -65,7 +75,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayNode('types') ->info('Enable/disable cache handling for data object types.') ->beforeNormalization() - ->always(fn ($v) => $v + ['folder' => false]) + ->always(static fn ($v) => $v + ['folder' => false]) ->end() ->normalizeKeys(false) ->useAttributeAsKey('type') diff --git a/src/DependencyInjection/NeustaPimcoreHttpCacheExtension.php b/src/DependencyInjection/NeustaPimcoreHttpCacheExtension.php index b1dd629..9124b8d 100644 --- a/src/DependencyInjection/NeustaPimcoreHttpCacheExtension.php +++ b/src/DependencyInjection/NeustaPimcoreHttpCacheExtension.php @@ -24,6 +24,10 @@ public function loadInternal(array $mergedConfig, ContainerBuilder $container): $container->getDefinition('neusta_pimcore_http_cache.cache_tag_checker') ->setArgument('$types', $mergedConfig['cache_types']); + $container->getDefinition('neusta_pimcore_http_cache.cache_scope.http_listener') + ->setArgument('$collectFromRequest', 'request' === ($mergedConfig['scope'] ?? 'controller')) + ->setArgument('$tagFallbackDocument', $mergedConfig['tag_fallback_document'] ?? false); + $this->registerElements($container, $mergedConfig['elements']); } diff --git a/src/EventListener/ConsoleCacheScopeListener.php b/src/EventListener/ConsoleCacheScopeListener.php new file mode 100644 index 0000000..4fbfe07 --- /dev/null +++ b/src/EventListener/ConsoleCacheScopeListener.php @@ -0,0 +1,25 @@ +cacheScope->enable(); + } +} diff --git a/src/EventListener/HttpCacheScopeListener.php b/src/EventListener/HttpCacheScopeListener.php new file mode 100644 index 0000000..6be8be5 --- /dev/null +++ b/src/EventListener/HttpCacheScopeListener.php @@ -0,0 +1,96 @@ +collectFromRequest || !$event->isMainRequest() || !$this->isCacheable($event->getRequest())) { + return; + } + + $this->cacheScope->enable(); + } + + #[AsEventListener] + public function onKernelController(ControllerEvent $event): void + { + if (!$event->isMainRequest()) { + return; + } + + $request = $event->getRequest(); + + if (!$this->collectFromRequest) { + if (!$this->isCacheable($request)) { + return; + } + + $this->cacheScope->enable(); + } + + $route = $request->attributes->get(DynamicRouter::ROUTE_KEY); + $routeElement = match (true) { + $route instanceof DocumentRoute => $route->getDocument(), + $route instanceof DataObjectRoute => $route->getObject(), + default => null, + }; + + if (null !== $routeElement) { + $this->responseTagger->tag(CacheTags::fromElement($routeElement)); + } + + if (!$routeElement instanceof Document && $this->tagFallbackDocument) { + $content = $this->documentResolver->getDocument($request); + + // If the route itself didn't resolve to a Document, the $content can only be a fallback document + // (e.g., the nearest document by path for a custom route), rather than something that the route matched. + if ($content instanceof Document) { + $this->responseTagger->tag(CacheTags::fromElement($content)); + } + } + } + + private function isCacheable(Request $request): bool + { + if (!$request->isMethodCacheable()) { + return false; + } + + if ($this->contextResolver->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN)) { + return false; + } + + return true; + } +} diff --git a/tests/Integration/Configuration/CollectConfigurationDataTest.php b/tests/Integration/Configuration/CollectConfigurationDataTest.php index 222e8a7..2cfad8a 100644 --- a/tests/Integration/Configuration/CollectConfigurationDataTest.php +++ b/tests/Integration/Configuration/CollectConfigurationDataTest.php @@ -3,7 +3,6 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Configuration; use Neusta\Pimcore\HttpCacheBundle\DataCollector; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -19,7 +18,6 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] final class CollectConfigurationDataTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -40,7 +38,7 @@ protected function setUp(): void ])] public function collects_configuration_data(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage())->save(); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); $this->client->enableProfiler(); @@ -65,7 +63,7 @@ public function collects_configuration_data(): void ])] public function does_not_collect_configuration_data_when_profiler_is_disabled(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage())->save(); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); $this->client->enableProfiler(); diff --git a/tests/Integration/Helpers/ArrangeCacheTest.php b/tests/Integration/Helpers/ArrangeCacheTest.php deleted file mode 100644 index bedd907..0000000 --- a/tests/Integration/Helpers/ArrangeCacheTest.php +++ /dev/null @@ -1,31 +0,0 @@ -get('test.cache_activator'); - \assert($cacheActivator instanceof CacheActivator); - - $wasActive = $cacheActivator->isCachingActive(); - $cacheActivator->deactivateCaching(); - try { - return $arrange(); - } finally { - $wasActive && $cacheActivator->activateCaching(); - } - } -} diff --git a/tests/Integration/Invalidation/CancelInvalidationTest.php b/tests/Integration/Invalidation/CancelInvalidationTest.php index dd661f7..08cdb3e 100644 --- a/tests/Integration/Invalidation/CancelInvalidationTest.php +++ b/tests/Integration/Invalidation/CancelInvalidationTest.php @@ -4,7 +4,6 @@ use FOS\HttpCacheBundle\CacheManager; use Neusta\Pimcore\HttpCacheBundle\Element\ElementInvalidationEvent; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -17,7 +16,6 @@ final class CancelInvalidationTest extends ConfigurableKernelTestCase { - use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -45,7 +43,7 @@ protected function setUp(): void ])] public function cancel_invalidation_on_object_update(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); $object->setContent('Updated test content')->save(); @@ -62,7 +60,7 @@ public function cancel_invalidation_on_object_update(): void ])] public function cancel_invalidation_on_document_update(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); $document->setKey('updated_test_document_page')->save(); @@ -79,7 +77,7 @@ public function cancel_invalidation_on_document_update(): void ])] public function cancel_invalidation_on_asset_update(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); $asset->setData('Updated test content')->save(); @@ -96,7 +94,7 @@ public function cancel_invalidation_on_asset_update(): void ])] public function cancel_invalidation_on_object_delete(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); $object->delete(); @@ -113,7 +111,7 @@ public function cancel_invalidation_on_object_delete(): void ])] public function cancel_invalidation_on_document_delete(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); $document->delete(); @@ -130,7 +128,7 @@ public function cancel_invalidation_on_document_delete(): void ])] public function cancel_invalidation_on_asset_delete(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); $asset->delete(); diff --git a/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php b/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php index fd76afa..942fea4 100644 --- a/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php +++ b/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php @@ -5,8 +5,8 @@ use FOS\HttpCacheBundle\CacheManager; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTag; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheType\CustomCacheType; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\Element\ElementInvalidationEvent; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -19,15 +19,18 @@ final class InvalidateAdditionalTagTest extends ConfigurableKernelTestCase { - use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; + private CacheScope $cacheScope; + /** @var ObjectProphecy */ private ObjectProphecy $cacheManager; protected function setUp(): void { + $this->cacheScope = self::getContainer()->get('neusta_pimcore_http_cache.cache_scope'); + $this->cacheManager = $this->prophesize(CacheManager::class); $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); @@ -53,8 +56,9 @@ protected function setUp(): void ])] public function invalidate_additional_tag_on_object_update(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); + $this->cacheScope->enable(); $object->setContent('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -73,8 +77,9 @@ public function invalidate_additional_tag_on_object_update(): void ])] public function does_not_invalidate_additional_tag_on_object_update_when_cache_type_is_disabled(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); + $this->cacheScope->enable(); $object->setKey('updated_test_object')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -93,8 +98,9 @@ public function does_not_invalidate_additional_tag_on_object_update_when_cache_t ])] public function invalidate_additional_tag_on_document_update(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); + $this->cacheScope->enable(); $document->setKey('updated_test_document_page')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -113,8 +119,9 @@ public function invalidate_additional_tag_on_document_update(): void ])] public function does_not_invalidate_additional_tag_on_document_update_when_cache_type_is_disabled(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); + $this->cacheScope->enable(); $document->setKey('updated_test_document_page')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -133,8 +140,9 @@ public function does_not_invalidate_additional_tag_on_document_update_when_cache ])] public function invalidate_additional_tag_on_asset_update(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); + $this->cacheScope->enable(); $asset->setData('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -153,8 +161,9 @@ public function invalidate_additional_tag_on_asset_update(): void ])] public function does_not_invalidate_additional_tag_on_asset_update_when_cache_type_is_disabled(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); + $this->cacheScope->enable(); $asset->setData('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -173,8 +182,9 @@ public function does_not_invalidate_additional_tag_on_asset_update_when_cache_ty ])] public function invalidate_additional_tag_on_object_deletion(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); + $this->cacheScope->enable(); $object->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -193,8 +203,9 @@ public function invalidate_additional_tag_on_object_deletion(): void ])] public function does_not_invalidate_additional_tag_on_object_deletion_when_cache_type_is_disabled(): void { - $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + $object = TestObjectFactory::simpleObject()->save(); + $this->cacheScope->enable(); $object->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -213,8 +224,9 @@ public function does_not_invalidate_additional_tag_on_object_deletion_when_cache ])] public function invalidate_additional_tag_on_asset_deletion(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); + $this->cacheScope->enable(); $asset->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -233,8 +245,9 @@ public function invalidate_additional_tag_on_asset_deletion(): void ])] public function does_not_invalidate_additional_tag_on_asset_deletion_when_cache_type_is_disabled(): void { - $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + $asset = TestAssetFactory::simpleAsset()->save(); + $this->cacheScope->enable(); $asset->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -253,8 +266,9 @@ public function does_not_invalidate_additional_tag_on_asset_deletion_when_cache_ ])] public function invalidate_additional_tag_on_document_deletion(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); + $this->cacheScope->enable(); $document->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -273,8 +287,9 @@ public function invalidate_additional_tag_on_document_deletion(): void ])] public function does_not_invalidate_additional_tag_on_document_deletion_when_cache_type_was_disabled(): void { - $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + $document = TestDocumentFactory::simplePage()->save(); + $this->cacheScope->enable(); $document->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldNotHaveBeenCalled(); diff --git a/tests/Integration/Invalidation/InvalidateAssetTest.php b/tests/Integration/Invalidation/InvalidateAssetTest.php index 486af18..6de5ed4 100644 --- a/tests/Integration/Invalidation/InvalidateAssetTest.php +++ b/tests/Integration/Invalidation/InvalidateAssetTest.php @@ -3,7 +3,6 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -15,7 +14,6 @@ final class InvalidateAssetTest extends ConfigurableKernelTestCase { - use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -34,9 +32,11 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - $this->folder = self::arrange(static fn () => TestAssetFactory::simpleFolder()->save()); - $this->image = self::arrange(static fn () => TestAssetFactory::simpleImage()->save()); + $this->asset = TestAssetFactory::simpleAsset()->save(); + $this->folder = TestAssetFactory::simpleFolder()->save(); + $this->image = TestAssetFactory::simpleImage()->save(); + + self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); } /** diff --git a/tests/Integration/Invalidation/InvalidateDocumentTest.php b/tests/Integration/Invalidation/InvalidateDocumentTest.php index 4586097..1bf47dc 100644 --- a/tests/Integration/Invalidation/InvalidateDocumentTest.php +++ b/tests/Integration/Invalidation/InvalidateDocumentTest.php @@ -3,7 +3,6 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -15,7 +14,6 @@ final class InvalidateDocumentTest extends ConfigurableKernelTestCase { - use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -36,10 +34,12 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - $this->hardlink = self::arrange(static fn () => TestDocumentFactory::simpleHardLink()->save()); - $this->email = self::arrange(static fn () => TestDocumentFactory::simpleEmail()->save()); - $this->folder = self::arrange(static fn () => TestDocumentFactory::simpleFolder()->save()); + $this->document = TestDocumentFactory::simplePage()->save(); + $this->hardlink = TestDocumentFactory::simpleHardLink()->save(); + $this->email = TestDocumentFactory::simpleEmail()->save(); + $this->folder = TestDocumentFactory::simpleFolder()->save(); + + self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); } /** diff --git a/tests/Integration/Invalidation/InvalidateObjectTest.php b/tests/Integration/Invalidation/InvalidateObjectTest.php index b553d66..eeaafdd 100644 --- a/tests/Integration/Invalidation/InvalidateObjectTest.php +++ b/tests/Integration/Invalidation/InvalidateObjectTest.php @@ -3,7 +3,6 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -16,7 +15,6 @@ final class InvalidateObjectTest extends ConfigurableKernelTestCase { - use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -35,9 +33,11 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - $this->folder = self::arrange(static fn () => TestObjectFactory::simpleFolder()->save()); - $this->variant = self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); + $this->object = TestObjectFactory::simpleObject()->save(); + $this->folder = TestObjectFactory::simpleFolder()->save(); + $this->variant = TestObjectFactory::simpleVariant()->save(); + + self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); } /** diff --git a/tests/Integration/Tagging/CollectTagsDataTest.php b/tests/Integration/Tagging/CollectTagsDataTest.php index 1434735..5052cbd 100644 --- a/tests/Integration/Tagging/CollectTagsDataTest.php +++ b/tests/Integration/Tagging/CollectTagsDataTest.php @@ -4,10 +4,9 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTag; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheType\CustomCacheType; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\DataCollector; use Neusta\Pimcore\HttpCacheBundle\Element\ElementTaggingEvent; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -25,7 +24,6 @@ ])] final class CollectTagsDataTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -46,7 +44,7 @@ protected function setUp(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] public function collect_tags_for_type_document(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage())->save(); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); $this->client->enableProfiler(); @@ -55,7 +53,7 @@ public function collect_tags_for_type_document(): void self::assertInstanceOf(DataCollector::class, $dataCollector); self::assertSame( - [['tag' => 'd1', 'type' => 'document'], ['tag' => 'd42', 'type' => 'document']], + [['tag' => 'd42', 'type' => 'document']], $dataCollector->getTags(), ); } @@ -71,7 +69,7 @@ public function collect_tags_for_type_document(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function collect_tags_for_type_object(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -96,7 +94,7 @@ public function collect_tags_for_type_object(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_asset_route.php')] public function collect_tags_of_type_asset(): void { - self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + TestAssetFactory::simpleAsset()->save(); $this->client->request('GET', '/get-asset?id=42'); $this->client->enableProfiler(); @@ -124,7 +122,7 @@ public function collect_tags_of_type_asset(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function collect_tags_of_type_custom(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -156,7 +154,7 @@ public function collect_tags_of_type_custom(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_type_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -178,8 +176,8 @@ public function does_not_collect_tags_when_type_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_caching_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - self::getContainer()->get(CacheActivator::class)->deactivateCaching(); + TestObjectFactory::simpleObject()->save(); + self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -206,7 +204,7 @@ public function does_not_collect_tags_when_caching_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_object_type_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); + TestObjectFactory::simpleVariant()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -233,7 +231,7 @@ public function does_not_collect_tags_when_object_type_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_object_class_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -261,7 +259,7 @@ public function does_not_collect_tags_when_object_class_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_profiler_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -278,7 +276,7 @@ public function does_not_collect_tags_when_profiler_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_collect_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); diff --git a/tests/Integration/Tagging/TagAdditionalTagTest.php b/tests/Integration/Tagging/TagAdditionalTagTest.php index 0a7fc0f..958c9a1 100644 --- a/tests/Integration/Tagging/TagAdditionalTagTest.php +++ b/tests/Integration/Tagging/TagAdditionalTagTest.php @@ -7,7 +7,6 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheType\ElementCacheType; use Neusta\Pimcore\HttpCacheBundle\Element\ElementTaggingEvent; use Neusta\Pimcore\HttpCacheBundle\Element\ElementType; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -22,7 +21,6 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] final class TagAdditionalTagTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -42,8 +40,8 @@ protected function setUp(): void ])] public function response_is_tagged_with_additional_tag_when_asset_is_loaded(): void { - self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - self::arrange(static fn () => TestAssetFactory::simpleImage()->save()); + TestAssetFactory::simpleAsset()->save(); + TestAssetFactory::simpleImage()->save(); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -72,8 +70,8 @@ public function response_is_tagged_with_additional_tag_when_asset_is_loaded(): v ])] public function response_is_tagged_with_additional_tag_when_document_is_loaded(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - self::arrange(static fn () => TestDocumentFactory::simpleSnippet()->save()); + TestDocumentFactory::simplePage()->save(); + TestDocumentFactory::simpleSnippet()->save(); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -82,7 +80,7 @@ public function response_is_tagged_with_additional_tag_when_document_is_loaded() ), ); - $this->client->request('GET', '/test_document_page'); + $this->client->request('GET', '/get-document?id=42'); $response = $this->client->getResponse(); self::assertSame('Document with key: test_document_page', $response->getContent()); @@ -102,8 +100,8 @@ public function response_is_tagged_with_additional_tag_when_document_is_loaded() ])] public function response_is_tagged_with_additional_tag_when_object_is_loaded(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); + TestObjectFactory::simpleObject()->save(); + TestObjectFactory::simpleVariant()->save(); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -135,7 +133,7 @@ public function response_is_tagged_with_additional_tag_when_object_is_loaded(): ])] public function response_is_tagged_with_custom_tag_when_element_is_loaded(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, diff --git a/tests/Integration/Tagging/TagAssetTest.php b/tests/Integration/Tagging/TagAssetTest.php index f44a946..4ce9d74 100644 --- a/tests/Integration/Tagging/TagAssetTest.php +++ b/tests/Integration/Tagging/TagAssetTest.php @@ -2,8 +2,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -14,7 +13,6 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_asset_route.php')] final class TagAssetTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -34,7 +32,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_asset_is_loaded(): void { - self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + TestAssetFactory::simpleAsset()->save(); $this->client->request('GET', '/get-asset?id=42'); @@ -56,7 +54,7 @@ public function response_is_tagged_with_expected_tags_when_asset_is_loaded(): vo ])] public function response_is_not_tagged_when_assets_is_not_enabled(): void { - self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); + TestAssetFactory::simpleAsset()->save(); $this->client->request('GET', '/get-asset?id=42'); @@ -78,8 +76,8 @@ public function response_is_not_tagged_when_assets_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - self::getContainer()->get(CacheActivator::class)->deactivateCaching(); + TestAssetFactory::simpleAsset()->save(); + self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-asset?id=42'); @@ -101,7 +99,7 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void ])] public function response_is_not_tagged_when_asset_is_of_type_folder(): void { - self::arrange(static fn () => TestAssetFactory::simpleFolder()->save()); + TestAssetFactory::simpleFolder()->save(); $this->client->request('GET', '/get-asset?id=23'); @@ -128,7 +126,7 @@ public function response_is_not_tagged_when_asset_is_of_type_folder(): void ])] public function response_is_not_tagged_for_specified_asset_type(): void { - self::arrange(static fn () => TestAssetFactory::simpleImage()->save()); + TestAssetFactory::simpleImage()->save(); $this->client->request('GET', '/get-asset?id=17'); diff --git a/tests/Integration/Tagging/TagDocumentTest.php b/tests/Integration/Tagging/TagDocumentTest.php index 10b464a..36c087d 100644 --- a/tests/Integration/Tagging/TagDocumentTest.php +++ b/tests/Integration/Tagging/TagDocumentTest.php @@ -2,8 +2,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -14,7 +13,6 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] final class TagDocumentTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -34,7 +32,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_page_is_loaded(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); @@ -56,7 +54,7 @@ public function response_is_tagged_with_expected_tags_when_page_is_loaded(): voi ])] public function response_is_tagged_with_expected_tags_when_snippet_is_loaded(): void { - self::arrange(static fn () => TestDocumentFactory::simpleSnippet()->save()); + TestDocumentFactory::simpleSnippet()->save(); $this->client->request('GET', '/get-document?id=23'); @@ -78,7 +76,7 @@ public function response_is_tagged_with_expected_tags_when_snippet_is_loaded(): ])] public function response_is_not_tagged_when_document_type_is_email(): void { - self::arrange(static fn () => TestDocumentFactory::simpleEmail()->save()); + TestDocumentFactory::simpleEmail()->save(); $this->client->request('GET', '/get-document?id=17'); @@ -87,7 +85,7 @@ public function response_is_not_tagged_when_document_type_is_email(): void self::assertSame(200, $response->getStatusCode()); self::assertTrue($response->headers->getCacheControlDirective('public')); self::assertSame('3600', $response->headers->getCacheControlDirective('s-maxage')); - self::assertStringNotContainsString('d17', $response->headers->get('X-Cache-Tags')); + self::assertStringNotContainsString('d17', $response->headers->get('X-Cache-Tags', '')); } /** @@ -100,7 +98,7 @@ public function response_is_not_tagged_when_document_type_is_email(): void ])] public function response_is_not_tagged_when_document_type_is_hard_link(): void { - self::arrange(static fn () => TestDocumentFactory::simpleHardLink()->save()); + TestDocumentFactory::simpleHardLink()->save(); $this->client->request('GET', '/get-document?id=33'); @@ -109,7 +107,7 @@ public function response_is_not_tagged_when_document_type_is_hard_link(): void self::assertSame(200, $response->getStatusCode()); self::assertTrue($response->headers->getCacheControlDirective('public')); self::assertSame('3600', $response->headers->getCacheControlDirective('s-maxage')); - self::assertStringNotContainsString('d33', $response->headers->get('X-Cache-Tags')); + self::assertStringNotContainsString('d33', $response->headers->get('X-Cache-Tags', '')); } /** @@ -122,7 +120,7 @@ public function response_is_not_tagged_when_document_type_is_hard_link(): void ])] public function response_is_not_tagged_when_document_type_is_folder(): void { - self::arrange(static fn () => TestDocumentFactory::simpleFolder()->save()); + TestDocumentFactory::simpleFolder()->save(); $this->client->request('GET', '/get-document?id=97'); @@ -131,7 +129,7 @@ public function response_is_not_tagged_when_document_type_is_folder(): void self::assertSame(200, $response->getStatusCode()); self::assertTrue($response->headers->getCacheControlDirective('public')); self::assertSame('3600', $response->headers->getCacheControlDirective('s-maxage')); - self::assertStringNotContainsString('d97', $response->headers->get('X-Cache-Tags')); + self::assertStringNotContainsString('d97', $response->headers->get('X-Cache-Tags', '')); } /** @@ -144,7 +142,7 @@ public function response_is_not_tagged_when_document_type_is_folder(): void ])] public function response_is_not_tagged_when_documents_is_not_enabled(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); @@ -166,8 +164,8 @@ public function response_is_not_tagged_when_documents_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - self::getContainer()->get(CacheActivator::class)->deactivateCaching(); + TestDocumentFactory::simplePage()->save(); + self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/test_document_page'); @@ -179,28 +177,6 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void self::assertNull($response->headers->get('X-Cache-Tags')); } - /** - * @test - */ - #[ConfigureExtension('neusta_pimcore_http_cache', [ - 'elements' => [ - 'documents' => true, - ], - ])] - public function response_is_tagged_with_root_document_tag_when_loaded(): void - { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - - $this->client->request('GET', '/test_document_page'); - - $response = $this->client->getResponse(); - self::assertSame('Document with key: test_document_page', $response->getContent()); - self::assertSame(200, $response->getStatusCode()); - self::assertTrue($response->headers->getCacheControlDirective('public')); - self::assertSame('3600', $response->headers->getCacheControlDirective('s-maxage')); - self::assertStringContainsString('d1', $response->headers->get('X-Cache-Tags')); - } - /** * @test */ @@ -215,7 +191,7 @@ public function response_is_tagged_with_root_document_tag_when_loaded(): void ])] public function response_is_not_tagged_when_type_is_disabled(): void { - self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + TestDocumentFactory::simplePage()->save(); $this->client->request('GET', '/test_document_page'); diff --git a/tests/Integration/Tagging/TagObjectTest.php b/tests/Integration/Tagging/TagObjectTest.php index 039a573..1fce50f 100644 --- a/tests/Integration/Tagging/TagObjectTest.php +++ b/tests/Integration/Tagging/TagObjectTest.php @@ -2,8 +2,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; -use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -14,7 +13,6 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] final class TagObjectTest extends ConfigurableWebTestcase { - use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -34,7 +32,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_object_is_loaded(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); @@ -56,7 +54,7 @@ public function response_is_tagged_with_expected_tags_when_object_is_loaded(): v ])] public function response_is_not_tagged_when_objects_is_not_enabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); @@ -78,8 +76,8 @@ public function response_is_not_tagged_when_objects_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - self::getContainer()->get(CacheActivator::class)->deactivateCaching(); + TestObjectFactory::simpleObject()->save(); + self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-object?id=42'); @@ -106,7 +104,7 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void ])] public function response_is_not_tagged_when_object_type_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); + TestObjectFactory::simpleVariant()->save(); $this->client->request('GET', '/get-object?id=17'); @@ -133,7 +131,7 @@ public function response_is_not_tagged_when_object_type_is_disabled(): void ])] public function response_ist_tagged_when_object_type_is_enabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); + TestObjectFactory::simpleVariant()->save(); $this->client->request('GET', '/get-object?id=17'); @@ -160,7 +158,7 @@ public function response_ist_tagged_when_object_type_is_enabled(): void ])] public function response_is_not_tagged_when_object_class_is_disabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); @@ -187,7 +185,7 @@ public function response_is_not_tagged_when_object_class_is_disabled(): void ])] public function response_is_tagged_when_object_class_is_enabled(): void { - self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + TestObjectFactory::simpleObject()->save(); $this->client->request('GET', '/get-object?id=42'); diff --git a/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php b/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php index 9f9de17..066e061 100644 --- a/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php +++ b/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php @@ -5,7 +5,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenActiveCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; @@ -20,16 +20,16 @@ final class OnlyWhenActiveCacheInvalidatorTest extends TestCase /** @var ObjectProphecy */ private ObjectProphecy $decorated; - /** @var ObjectProphecy */ - private ObjectProphecy $cacheActivator; + /** @var ObjectProphecy */ + private ObjectProphecy $cacheScope; protected function setUp(): void { $this->decorated = $this->prophesize(CacheInvalidator::class); - $this->cacheActivator = $this->prophesize(CacheActivator::class); + $this->cacheScope = $this->prophesize(CacheScope::class); $this->subject = new OnlyWhenActiveCacheInvalidator( $this->decorated->reveal(), - $this->cacheActivator->reveal(), + $this->cacheScope->reveal(), ); } @@ -40,7 +40,7 @@ public function it_should_invalidate_tags_when_caching_is_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheActivator->isCachingActive()->willReturn(true); + $this->cacheScope->isActive()->willReturn(true); $this->subject->invalidate($tags); @@ -54,7 +54,7 @@ public function it_should_not_invalidate_tags_when_caching_is_not_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheActivator->isCachingActive()->willReturn(false); + $this->cacheScope->isActive()->willReturn(false); $this->subject->invalidate($tags); diff --git a/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php b/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php index 3512462..ec7ccc9 100644 --- a/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php +++ b/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php @@ -5,7 +5,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\OnlyWhenActiveResponseTagger; -use Neusta\Pimcore\HttpCacheBundle\CacheActivator; +use Neusta\Pimcore\HttpCacheBundle\CacheScope; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; @@ -20,16 +20,16 @@ final class OnlyWhenActiveResponseTaggerTest extends TestCase /** @var ObjectProphecy */ private ObjectProphecy $decorated; - /** @var ObjectProphecy */ - private ObjectProphecy $cacheActivator; + /** @var ObjectProphecy */ + private ObjectProphecy $cacheScope; protected function setUp(): void { $this->decorated = $this->prophesize(ResponseTagger::class); - $this->cacheActivator = $this->prophesize(CacheActivator::class); + $this->cacheScope = $this->prophesize(CacheScope::class); $this->subject = new OnlyWhenActiveResponseTagger( $this->decorated->reveal(), - $this->cacheActivator->reveal(), + $this->cacheScope->reveal(), ); } @@ -40,7 +40,7 @@ public function it_should_invalidate_tags_when_caching_is_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheActivator->isCachingActive()->willReturn(true); + $this->cacheScope->isActive()->willReturn(true); $this->subject->tag($tags); @@ -54,7 +54,7 @@ public function it_should_not_invalidate_tags_when_caching_is_not_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheActivator->isCachingActive()->willReturn(false); + $this->cacheScope->isActive()->willReturn(false); $this->subject->tag($tags); diff --git a/tests/Unit/CacheActivatorTest.php b/tests/Unit/CacheActivatorTest.php deleted file mode 100644 index c0084e5..0000000 --- a/tests/Unit/CacheActivatorTest.php +++ /dev/null @@ -1,45 +0,0 @@ -cacheActivator = new CacheActivator(); - } - - /** - * @test - */ - public function it_must_be_activated_by_default(): void - { - self::assertTrue($this->cacheActivator->isCachingActive()); - } - - /** - * @test - */ - public function it_must_be_deactivated_after_deactivateCaching_is_called(): void - { - $this->cacheActivator->deactivateCaching(); - - self::assertFalse($this->cacheActivator->isCachingActive()); - } - - /** - * @test - */ - public function it_must_be_activated_after_activateCaching_is_called(): void - { - $this->cacheActivator->deactivateCaching(); - $this->cacheActivator->activateCaching(); - - self::assertTrue($this->cacheActivator->isCachingActive()); - } -} diff --git a/tests/Unit/CacheScopeTest.php b/tests/Unit/CacheScopeTest.php new file mode 100644 index 0000000..83ec104 --- /dev/null +++ b/tests/Unit/CacheScopeTest.php @@ -0,0 +1,84 @@ +isActive()); + } + + /** + * @test + */ + public function enable_activates_the_scope(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->enable(); + + self::assertTrue($cacheScope->isActive()); + } + + /** + * @test + */ + public function disable_deactivates_the_scope(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->enable(); + $cacheScope->disable(); + + self::assertFalse($cacheScope->isActive()); + } + + /** + * @test + */ + public function disable_survives_later_enable_calls(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->disable(); + $cacheScope->enable(); + + self::assertFalse($cacheScope->isActive()); + } + + /** + * @test + */ + public function reset_deactivates_the_scope(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->enable(); + $cacheScope->reset(); + + self::assertFalse($cacheScope->isActive()); + } + + /** + * @test + */ + public function reset_clears_disabled_state_so_scope_can_be_enabled_again(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->disable(); + $cacheScope->reset(); + $cacheScope->enable(); + + self::assertTrue($cacheScope->isActive()); + } +} diff --git a/tests/Unit/EventListener/HttpCacheScopeListenerTest.php b/tests/Unit/EventListener/HttpCacheScopeListenerTest.php new file mode 100644 index 0000000..09f7f22 --- /dev/null +++ b/tests/Unit/EventListener/HttpCacheScopeListenerTest.php @@ -0,0 +1,425 @@ + */ + private ObjectProphecy $cacheScope; + + /** @var ObjectProphecy */ + private ObjectProphecy $responseTagger; + + /** @var ObjectProphecy */ + private ObjectProphecy $contextResolver; + + /** @var ObjectProphecy */ + private ObjectProphecy $documentResolver; + + /** @var ObjectProphecy */ + private ObjectProphecy $kernel; + + protected function setUp(): void + { + $this->cacheScope = $this->prophesize(CacheScope::class); + $this->responseTagger = $this->prophesize(ResponseTagger::class); + $this->contextResolver = $this->prophesize(PimcoreContextResolver::class); + $this->documentResolver = $this->prophesize(DocumentResolver::class); + $this->kernel = $this->prophesize(HttpKernelInterface::class); + } + + /** + * @test + */ + public function onKernelRequest_does_not_activate_caching_when_collecting_from_request_is_disabled(): void + { + $subject = $this->createSubject(collectFromRequest: false); + + $subject->onKernelRequest($this->createRequestEvent(new Request())); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->contextResolver->matchesPimcoreContext(Argument::cetera())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelRequest_does_not_activate_caching_for_sub_request(): void + { + $subject = $this->createSubject(collectFromRequest: true); + + $subject->onKernelRequest($this->createRequestEvent(new Request(), HttpKernelInterface::SUB_REQUEST)); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->contextResolver->matchesPimcoreContext(Argument::cetera())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelRequest_does_not_activate_caching_for_non_cacheable_method(): void + { + $subject = $this->createSubject(collectFromRequest: true); + + $subject->onKernelRequest($this->createRequestEvent(Request::create('/', 'POST'))); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->contextResolver->matchesPimcoreContext(Argument::cetera())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelRequest_does_not_activate_caching_for_admin_context(): void + { + $subject = $this->createSubject(collectFromRequest: true); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(true); + + $subject->onKernelRequest($this->createRequestEvent($request)); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelRequest_activates_caching_for_cacheable_main_request_outside_admin_context(): void + { + $subject = $this->createSubject(collectFromRequest: true); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $subject->onKernelRequest($this->createRequestEvent($request)); + + $this->cacheScope->enable()->shouldHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_nothing_for_sub_request(): void + { + $subject = $this->createSubject(); + + $subject->onKernelController($this->createControllerEvent(new Request(), HttpKernelInterface::SUB_REQUEST)); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->responseTagger->tag(Argument::any())->shouldNotHaveBeenCalled(); + $this->documentResolver->getDocument(Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_not_activate_or_tag_for_non_cacheable_method_when_collecting_from_controller(): void + { + $subject = $this->createSubject(collectFromRequest: false); + + $subject->onKernelController($this->createControllerEvent(Request::create('/', 'POST'))); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->responseTagger->tag(Argument::any())->shouldNotHaveBeenCalled(); + $this->documentResolver->getDocument(Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_not_activate_or_tag_for_admin_context_when_collecting_from_controller(): void + { + $subject = $this->createSubject(collectFromRequest: false); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(true); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + $this->responseTagger->tag(Argument::any())->shouldNotHaveBeenCalled(); + $this->documentResolver->getDocument(Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_activates_caching_when_collecting_from_controller(): void + { + $subject = $this->createSubject(collectFromRequest: false); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $this->documentResolver + ->getDocument($request) + ->willReturn(null); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->cacheScope->enable()->shouldHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_not_activate_caching_when_already_collecting_from_request(): void + { + $subject = $this->createSubject(collectFromRequest: true); + $request = new Request(); + + $this->documentResolver + ->getDocument($request) + ->willReturn(null); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->contextResolver->matchesPimcoreContext(Argument::cetera())->shouldNotHaveBeenCalled(); + $this->cacheScope->enable()->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_tags_document_from_document_route(): void + { + $subject = $this->createSubject(); + $document = $this->createDocument(123); + $route = $this->prophesize(DocumentRoute::class); + $request = new Request(); + + $request->attributes->set(DynamicRouter::ROUTE_KEY, $route->reveal()); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $route + ->getDocument() + ->willReturn($document); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['d123'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + + $this->documentResolver->getDocument(Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_tags_object_from_data_object_route(): void + { + $subject = $this->createSubject(); + $object = $this->createDataObject(456); + $route = $this->prophesize(DataObjectRoute::class); + $request = new Request(); + + $request->attributes->set(DynamicRouter::ROUTE_KEY, $route->reveal()); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $route + ->getObject() + ->willReturn($object); + + $this->documentResolver + ->getDocument($request) + ->willReturn(null); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['o456'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_not_tag_fallback_document_when_disabled(): void + { + $subject = $this->createSubject(tagFallbackDocument: false); + $object = $this->createDataObject(456); + $route = $this->prophesize(DataObjectRoute::class); + $request = new Request(); + + $request->attributes->set(DynamicRouter::ROUTE_KEY, $route->reveal()); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $route + ->getObject() + ->willReturn($object); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['o456'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + + $this->documentResolver->getDocument(Argument::any())->shouldNotHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_tags_fallback_document_when_route_element_is_not_document(): void + { + $subject = $this->createSubject(tagFallbackDocument: true); + $object = $this->createDataObject(456); + $fallbackDocument = $this->createDocument(789); + $route = $this->prophesize(DataObjectRoute::class); + $request = new Request(); + + $request->attributes->set(DynamicRouter::ROUTE_KEY, $route->reveal()); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $route + ->getObject() + ->willReturn($object); + + $this->documentResolver + ->getDocument($request) + ->willReturn($fallbackDocument); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['o456'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['d789'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_tags_only_fallback_document_when_route_is_unknown(): void + { + $subject = $this->createSubject(tagFallbackDocument: true); + $fallbackDocument = $this->createDocument(789); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $this->documentResolver + ->getDocument($request) + ->willReturn($fallbackDocument); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger + ->tag(Argument::that(static fn (CacheTags $tags): bool => ['d789'] === $tags->toArray())) + ->shouldHaveBeenCalled(); + } + + /** + * @test + */ + public function onKernelController_does_not_tag_anything_when_route_is_unknown_and_no_fallback_document_exists(): void + { + $subject = $this->createSubject(tagFallbackDocument: true); + $request = new Request(); + + $this->contextResolver + ->matchesPimcoreContext($request, PimcoreContextResolver::CONTEXT_ADMIN) + ->willReturn(false); + + $this->documentResolver + ->getDocument($request) + ->willReturn(null); + + $subject->onKernelController($this->createControllerEvent($request)); + + $this->responseTagger->tag(Argument::any())->shouldNotHaveBeenCalled(); + } + + private function createSubject( + bool $collectFromRequest = false, + bool $tagFallbackDocument = false, + ): HttpCacheScopeListener { + return new HttpCacheScopeListener( + $this->cacheScope->reveal(), + $this->responseTagger->reveal(), + $this->contextResolver->reveal(), + $this->documentResolver->reveal(), + $collectFromRequest, + $tagFallbackDocument, + ); + } + + private function createRequestEvent( + Request $request, + int $requestType = HttpKernelInterface::MAIN_REQUEST, + ): RequestEvent { + return new RequestEvent($this->kernel->reveal(), $request, $requestType); + } + + private function createControllerEvent( + Request $request, + int $requestType = HttpKernelInterface::MAIN_REQUEST, + ): ControllerEvent { + return new ControllerEvent($this->kernel->reveal(), static fn () => null, $request, $requestType); + } + + private function createDocument(int $id): Document + { + $document = $this->prophesize(Document::class); + $document->getId()->willReturn($id); + + return $document->reveal(); + } + + private function createDataObject(int $id): Concrete + { + $object = $this->prophesize(Concrete::class); + $object->getId()->willReturn($id); + + return $object->reveal(); + } +} diff --git a/tests/app/config/services.php b/tests/app/config/services.php index 76ef43d..df2f8ba 100644 --- a/tests/app/config/services.php +++ b/tests/app/config/services.php @@ -23,7 +23,4 @@ ->tag('kernel.event_listener', ['event' => DataObjectEvents::POST_DELETE]) ->tag('kernel.event_listener', ['event' => DocumentEvents::POST_UPDATE]) ->tag('kernel.event_listener', ['event' => DocumentEvents::POST_DELETE]); - - $services->alias('test.cache_activator', 'neusta_pimcore_http_cache.cache_activator') - ->public(); }; From 8f7817a98f51bb83ce404750f4337c7a59f6b3b9 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 18:00:12 +0200 Subject: [PATCH 02/11] Add tests for document tagging in request scope, including parent and ancestor tags --- .../Tagging/CollectTagsDataTest.php | 31 +++++++++++++++++++ tests/Integration/Tagging/TagDocumentTest.php | 26 ++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/tests/Integration/Tagging/CollectTagsDataTest.php b/tests/Integration/Tagging/CollectTagsDataTest.php index 5052cbd..ad84957 100644 --- a/tests/Integration/Tagging/CollectTagsDataTest.php +++ b/tests/Integration/Tagging/CollectTagsDataTest.php @@ -58,6 +58,37 @@ public function collect_tags_for_type_document(): void ); } + /** + * @test + */ + #[ConfigureExtension('neusta_pimcore_http_cache', [ + 'scope' => 'request', + 'elements' => [ + 'documents' => true, + ], + ])] + #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] + public function collect_tags_for_type_document_in_request_scope(): void + { + $parent = TestDocumentFactory::simplePage()->save(); + TestDocumentFactory::simpleSnippet()->setParent($parent)->save(); + + $this->client->request('GET', '/test_document_page/test_document_snippet'); + $this->client->enableProfiler(); + + $dataCollector = $this->client->getProfile()->getCollector('pimcore_http_cache'); + + self::assertInstanceOf(DataCollector::class, $dataCollector); + self::assertSame( + [ + ['tag' => 'd23', 'type' => 'document'], // The document itself + ['tag' => 'd42', 'type' => 'document'], // The document's parent + ['tag' => 'd1', 'type' => 'document'], // The document's parent's parent + ], + $dataCollector->getTags(), + ); + } + /** * @test */ diff --git a/tests/Integration/Tagging/TagDocumentTest.php b/tests/Integration/Tagging/TagDocumentTest.php index 36c087d..1dc7919 100644 --- a/tests/Integration/Tagging/TagDocumentTest.php +++ b/tests/Integration/Tagging/TagDocumentTest.php @@ -177,6 +177,32 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void self::assertNull($response->headers->get('X-Cache-Tags')); } + /** + * @test + */ + #[ConfigureExtension('neusta_pimcore_http_cache', [ + 'scope' => 'request', + 'elements' => [ + 'documents' => true, + ], + ])] + public function response_is_tagged_with_the_document_parents_when_in_request_scope(): void + { + $parent = TestDocumentFactory::simplePage()->save(); + TestDocumentFactory::simpleSnippet()->setParent($parent)->save(); + + $this->client->request('GET', '/test_document_page/test_document_snippet'); + + $response = $this->client->getResponse(); + self::assertSame('Document with key: test_document_snippet', $response->getContent()); + self::assertSame(200, $response->getStatusCode()); + self::assertTrue($response->headers->getCacheControlDirective('public')); + self::assertSame('3600', $response->headers->getCacheControlDirective('s-maxage')); + self::assertStringContainsString('d23', $response->headers->get('X-Cache-Tags')); // The document itself + self::assertStringContainsString('d42', $response->headers->get('X-Cache-Tags')); // The document's parent + self::assertStringContainsString('d1', $response->headers->get('X-Cache-Tags')); // The document's parent's parent + } + /** * @test */ From 8ef02fa7f9586127733139667413e07f01f42e89 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 18:33:35 +0200 Subject: [PATCH 03/11] Restore CacheActivator's previous behavior --- src/CacheActivator.php | 1 + tests/Unit/CacheActivatorTest.php | 51 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/Unit/CacheActivatorTest.php diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 4c068f2..11a7231 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -20,6 +20,7 @@ public function activateCaching(): void { trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + $this->reset(); $this->enable(); } diff --git a/tests/Unit/CacheActivatorTest.php b/tests/Unit/CacheActivatorTest.php new file mode 100644 index 0000000..fb137eb --- /dev/null +++ b/tests/Unit/CacheActivatorTest.php @@ -0,0 +1,51 @@ +cacheActivator = new CacheActivator(); + } + + /** + * @test + */ + public function it_must_be_activated_after_activateCaching_is_called(): void + { + $this->cacheActivator->activateCaching(); + + self::assertTrue($this->cacheActivator->isCachingActive()); + } + + /** + * @test + */ + public function it_must_be_deactivated_after_deactivateCaching_is_called(): void + { + $this->cacheActivator->activateCaching(); + $this->cacheActivator->deactivateCaching(); + + self::assertFalse($this->cacheActivator->isCachingActive()); + } + + /** + * @test + */ + public function it_can_be_deactivated_and_activated_again(): void + { + $this->cacheActivator->deactivateCaching(); + + self::assertFalse($this->cacheActivator->isCachingActive()); + + $this->cacheActivator->activateCaching(); + + self::assertTrue($this->cacheActivator->isCachingActive()); + } +} From e4ccc29967cf9b9f7dd036022499e3dc9712aa37 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 18:45:03 +0200 Subject: [PATCH 04/11] Improve deprecation messages --- src/CacheActivator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 11a7231..7c34fe3 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -11,14 +11,14 @@ final class CacheActivator extends CacheScope { public function isCachingActive(): bool { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::isActive()" instead.', __METHOD__, CacheScope::class); return $this->isActive(); } public function activateCaching(): void { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::enable()" instead.', __METHOD__, CacheScope::class); $this->reset(); $this->enable(); @@ -26,7 +26,7 @@ public function activateCaching(): void public function deactivateCaching(): void { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s" is deprecated, use "%s" instead.', self::class, CacheScope::class); + trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::disable()" instead.', __METHOD__, CacheScope::class); $this->disable(); } From 4886e2674e728600eb2c8ed29c251f2bc71bb2c6 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 19:35:49 +0200 Subject: [PATCH 05/11] Enable cache scope in `CancelInvalidationTest` setup --- tests/Integration/Invalidation/CancelInvalidationTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Integration/Invalidation/CancelInvalidationTest.php b/tests/Integration/Invalidation/CancelInvalidationTest.php index 08cdb3e..9559ce1 100644 --- a/tests/Integration/Invalidation/CancelInvalidationTest.php +++ b/tests/Integration/Invalidation/CancelInvalidationTest.php @@ -31,6 +31,8 @@ protected function setUp(): void ElementInvalidationEvent::class, static fn ($event) => $event->cancel = true, ); + + self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); } /** From 154a718c4fcdcca8874abf29da86cf46905e4d47 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 6 Jul 2026 19:36:43 +0200 Subject: [PATCH 06/11] Make `neusta_pimcore_http_cache.cache_scope` and `neusta_pimcore_http_cache.cache_activator` point to the same service --- config/services.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/services.php b/config/services.php index f285814..0e68f1d 100644 --- a/config/services.php +++ b/config/services.php @@ -33,15 +33,15 @@ return static function (ContainerConfigurator $configurator) { $services = $configurator->services(); - $services->set('neusta_pimcore_http_cache.cache_activator', CacheActivator::class) - ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%service_id%" is deprecated, use "neusta_pimcore_http_cache.cache_scope" instead.') - ->alias(CacheActivator::class, 'neusta_pimcore_http_cache.cache_activator') - ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "' . CacheScope::class . '" instead.'); - - $services->set('neusta_pimcore_http_cache.cache_scope', CacheScope::class) + $services->set('neusta_pimcore_http_cache.cache_scope', CacheActivator::class) ->tag('kernel.reset', ['method' => 'reset']) ->alias(CacheScope::class, 'neusta_pimcore_http_cache.cache_scope'); + $services->alias('neusta_pimcore_http_cache.cache_activator', 'neusta_pimcore_http_cache.cache_scope') + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "neusta_pimcore_http_cache.cache_scope" instead.') + ->alias(CacheActivator::class, 'neusta_pimcore_http_cache.cache_activator') + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "' . CacheScope::class . '" instead.'); + $services->set('neusta_pimcore_http_cache.cache_scope.console_listener', ConsoleCacheScopeListener::class) ->arg('$cacheScope', service('neusta_pimcore_http_cache.cache_scope')) ->autoconfigure(); From 9fd3192cb4dcd0a180cd50ffb05ceab5912cb71f Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Wed, 8 Jul 2026 17:14:38 +0200 Subject: [PATCH 07/11] Add docs --- CHANGELOG.md | 12 ++++- README.md | 8 +-- ...error-handling.md => 10-error-handling.md} | 0 doc/{10-profiling.md => 11-profiling.md} | 0 ...{11-contribution.md => 12-contribution.md} | 0 doc/2-configuration.md | 8 +++ doc/8-cache-scope.md | 51 +++++++++++++++++++ ...avior.md => 9-disable-caching-behavior.md} | 4 ++ 8 files changed, 79 insertions(+), 4 deletions(-) rename doc/{9-error-handling.md => 10-error-handling.md} (100%) rename doc/{10-profiling.md => 11-profiling.md} (100%) rename doc/{11-contribution.md => 12-contribution.md} (100%) create mode 100644 doc/8-cache-scope.md rename doc/{8-disable-caching-behavior.md => 9-disable-caching-behavior.md} (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e0cc0..73150e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog -## Version 1.0.0 +## Version 0.8.0 + +- feature: Introduced `CacheScope` service for controlling when and whether cache tags are collected +- feature: New `scope` configuration option (`controller` / `request`) to control when tag collection begins within a request +- feature: New `tag_fallback_document` configuration option to tag responses with fallback documents +- deprecation: `CacheActivator` is deprecated; use `CacheScope` instead +- deprecation: `CacheActivator::isCachingActive()` is deprecated; use `CacheScope::isActive()` instead +- deprecation: `CacheActivator::activateCaching()` is deprecated; use `CacheScope::enable()` instead +- deprecation: `CacheActivator::deactivateCaching()` is deprecated; use `CacheScope::disable()` instead + +## Version 0.7.0 - feature: Initial Release diff --git a/README.md b/README.md index b2e6395..f899a1d 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,11 @@ You will find the detailed documentation in the following links: * [Additional tags](doc/5-additional-tags.md) * [Cancel caching behavior](doc/6-cancel-caching-behavior.md) * [Custom cache types](doc/7-custom-cache-types.md) -* [Disabling caching behavior](doc/8-disable-caching-behavior.md) -* [Error handling](doc/9-error-handling.md) -* [Contribution](doc/10-contribution.md) +* [Cache scope](doc/8-cache-scope.md) +* [Disabling caching behavior](doc/9-disable-caching-behavior.md) +* [Error handling](doc/10-error-handling.md) +* [Profiling](doc/11-profiling.md) +* [Contribution](doc/12-contribution.md) We hope you will enjoy this bundle as much as we do. If you have any questions or suggestions, please feel free to open an issue on GitHub. This repository is maintained by [neusta](https://www.team-neusta.de/). diff --git a/doc/9-error-handling.md b/doc/10-error-handling.md similarity index 100% rename from doc/9-error-handling.md rename to doc/10-error-handling.md diff --git a/doc/10-profiling.md b/doc/11-profiling.md similarity index 100% rename from doc/10-profiling.md rename to doc/11-profiling.md diff --git a/doc/11-contribution.md b/doc/12-contribution.md similarity index 100% rename from doc/11-contribution.md rename to doc/12-contribution.md diff --git a/doc/2-configuration.md b/doc/2-configuration.md index c8d1cdc..b69b3db 100644 --- a/doc/2-configuration.md +++ b/doc/2-configuration.md @@ -4,6 +4,14 @@ This bundle is configured via the `neusta_pimcore_http_cache` key in your `confi ```yaml neusta_pimcore_http_cache: + # When to start collecting cache tags: "controller" (default) or "request" + # See doc/8-cache-scope.md for details + scope: controller + + # Tag the response with a fallback document when the matched route is not a document route + # (i.e. the nearest document resolved by path rather than the route itself) + tag_fallback_document: false + # Enable/disable cache handling for certain element types elements: assets: diff --git a/doc/8-cache-scope.md b/doc/8-cache-scope.md new file mode 100644 index 0000000..8cd047c --- /dev/null +++ b/doc/8-cache-scope.md @@ -0,0 +1,51 @@ +## Cache Scope + +The cache scope controls whether and from which point in the request lifecycle cache tags are collected. +Tags are only collected while the scope is **active**. If the scope is inactive, all tagging and invalidation is skipped. + +### Automatic activation + +The bundle activates the scope automatically in two contexts: + +- **HTTP requests**: The scope is activated for every cacheable request (`GET` or `HEAD`, non-admin context). + When it is activated depends on the [`scope` configuration option](#scope-option). +- **Console commands**: The scope is activated at the start of every console command. + +### Scope option + +The `scope` option controls at which point in the request lifecycle the scope is activated for HTTP requests: + +- `controller` (default): The scope is activated during the `kernel.controller` event. + Elements loaded earlier — e.g. in `kernel.request` event listeners — are **not** tagged. +- `request`: The scope is activated during the `kernel.request` event, i.e. from the very beginning of the request. + Use this if you need to tag elements that are loaded in `kernel.request` listeners. + +```yaml +neusta_pimcore_http_cache: + scope: controller # or "request" +``` + +### Manual access + +You can inject `CacheScope` directly to check or modify the scope state at runtime: + +```php +use Neusta\Pimcore\HttpCacheBundle\CacheScope; + +final class MyService +{ + public function __construct( + private readonly CacheScope $cacheScope, + ) { + } + + public function doSomething(): void + { + if ($this->cacheScope->isActive()) { + // cache tags are currently being collected + } + } +} +``` + +To **disable** cache tag collection for the current request (e.g. in tests), see [Disabling caching behavior](9-disable-caching-behavior.md). diff --git a/doc/8-disable-caching-behavior.md b/doc/9-disable-caching-behavior.md similarity index 75% rename from doc/8-disable-caching-behavior.md rename to doc/9-disable-caching-behavior.md index 9e11cb5..21e1f79 100644 --- a/doc/8-disable-caching-behavior.md +++ b/doc/9-disable-caching-behavior.md @@ -4,6 +4,10 @@ You may encounter situations where you need to disable the default caching behav This is especially useful for testing purposes. To achieve this, you can use the `CacheScope` to disable tagging and invalidation behavior entirely. +> [!IMPORTANT] +> Once disabled, the cache scope cannot be re-enabled during the same request or command. +> Calling `enable()` afterward has no effect; the disabled state is only cleared when the scope is reset. + ### Example for disabling caching behavior in a specific test case ```php From 884148d8e36f4be7acb7b05b41483fdb25aedb14 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Fri, 10 Jul 2026 18:55:15 +0200 Subject: [PATCH 08/11] Rename `CacheScope::isActive()` to `isEnabled()` Rename `Active` references to `Enabled` throughout codebase Rename `disableForRequest` method to `disable` again Update the docs Refactor `CacheScopeTest` to improve readability and ensure consistent spacing Replace `enable` and `disable` methods with `startCollecting` and `disableForRequest` --- config/services.php | 8 +++--- doc/2-configuration.md | 2 +- doc/8-cache-scope.md | 14 ++++++---- ...hp => OnlyWhenEnabledCacheInvalidator.php} | 4 +-- ....php => OnlyWhenEnabledResponseTagger.php} | 4 +-- src/CacheActivator.php | 2 +- src/CacheScope.php | 19 ++++++++------ ...> OnlyWhenEnabledCacheInvalidatorTest.php} | 16 ++++++------ ... => OnlyWhenEnabledResponseTaggerTest.php} | 12 ++++----- tests/Unit/CacheScopeTest.php | 26 +++++++++---------- 10 files changed, 57 insertions(+), 50 deletions(-) rename src/Cache/CacheInvalidator/{OnlyWhenActiveCacheInvalidator.php => OnlyWhenEnabledCacheInvalidator.php} (81%) rename src/Cache/ResponseTagger/{OnlyWhenActiveResponseTagger.php => OnlyWhenEnabledResponseTagger.php} (81%) rename tests/Unit/Cache/CacheInvalidator/{OnlyWhenActiveCacheInvalidatorTest.php => OnlyWhenEnabledCacheInvalidatorTest.php} (77%) rename tests/Unit/Cache/ResponseTagger/{OnlyWhenActiveResponseTaggerTest.php => OnlyWhenEnabledResponseTaggerTest.php} (82%) diff --git a/config/services.php b/config/services.php index 0e68f1d..5cfc5de 100644 --- a/config/services.php +++ b/config/services.php @@ -4,7 +4,7 @@ use Neusta\Pimcore\HttpCacheBundle\Adapter\FOSHttpCache\CacheInvalidatorAdapter; use Neusta\Pimcore\HttpCacheBundle\Adapter\FOSHttpCache\ResponseTaggerAdapter; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; -use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenActiveCacheInvalidator; +use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenEnabledCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\RemoveDisabledTagsCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\Element\AssetCacheTagChecker; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\Element\DocumentCacheTagChecker; @@ -12,7 +12,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\ElementCacheTagChecker; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\StaticCacheTagChecker; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger; -use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\OnlyWhenActiveResponseTagger; +use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\OnlyWhenEnabledResponseTagger; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\RemoveDisabledTagsResponseTagger; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\TraceableResponseTagger; use Neusta\Pimcore\HttpCacheBundle\CacheActivator; @@ -62,7 +62,7 @@ ->decorate('neusta_pimcore_http_cache.cache_invalidator', null, -99) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_tag_checker')]); - $services->set(null, OnlyWhenActiveCacheInvalidator::class) + $services->set(null, OnlyWhenEnabledCacheInvalidator::class) ->decorate('neusta_pimcore_http_cache.cache_invalidator', null, -100) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_scope')]); @@ -75,7 +75,7 @@ ->decorate('neusta_pimcore_http_cache.response_tagger', null, -99) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_tag_checker')]); - $services->set(null, OnlyWhenActiveResponseTagger::class) + $services->set(null, OnlyWhenEnabledResponseTagger::class) ->decorate('neusta_pimcore_http_cache.response_tagger', null, -100) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_scope')]); diff --git a/doc/2-configuration.md b/doc/2-configuration.md index b69b3db..f6c82c6 100644 --- a/doc/2-configuration.md +++ b/doc/2-configuration.md @@ -4,7 +4,7 @@ This bundle is configured via the `neusta_pimcore_http_cache` key in your `confi ```yaml neusta_pimcore_http_cache: - # When to start collecting cache tags: "controller" (default) or "request" + # When to enable the cache scope for collecting cache tags: "controller" (default) or "request" # See doc/8-cache-scope.md for details scope: controller diff --git a/doc/8-cache-scope.md b/doc/8-cache-scope.md index 8cd047c..4cde574 100644 --- a/doc/8-cache-scope.md +++ b/doc/8-cache-scope.md @@ -1,7 +1,7 @@ ## Cache Scope -The cache scope controls whether and from which point in the request lifecycle cache tags are collected. -Tags are only collected while the scope is **active**. If the scope is inactive, all tagging and invalidation is skipped. +The cache scope controls whether and from which point in the request lifecycle cache-related behavior is enabled. +Tags are only collected while the scope is **enabled**. If the scope is disabled, all tagging and invalidation is skipped. ### Automatic activation @@ -41,11 +41,15 @@ final class MyService public function doSomething(): void { - if ($this->cacheScope->isActive()) { - // cache tags are currently being collected + if ($this->cacheScope->isEnabled()) { + // cache-related behavior is currently enabled } + + $this->cacheScope->disable(); + // cache-related behavior is disabled from now on } } ``` -To **disable** cache tag collection for the current request (e.g. in tests), see [Disabling caching behavior](9-disable-caching-behavior.md). +To disable cache-related behavior for the current request or command, see +[Disabling caching behavior](9-disable-caching-behavior.md). diff --git a/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php b/src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php similarity index 81% rename from src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php rename to src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php index 90caca1..fd17715 100644 --- a/src/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidator.php +++ b/src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php @@ -6,7 +6,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\CacheScope; -final class OnlyWhenActiveCacheInvalidator implements CacheInvalidator +final class OnlyWhenEnabledCacheInvalidator implements CacheInvalidator { public function __construct( private readonly CacheInvalidator $inner, @@ -16,7 +16,7 @@ public function __construct( public function invalidate(CacheTags $tags): void { - if ($this->cacheScope->isActive()) { + if ($this->cacheScope->isEnabled()) { $this->inner->invalidate($tags); } } diff --git a/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php b/src/Cache/ResponseTagger/OnlyWhenEnabledResponseTagger.php similarity index 81% rename from src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php rename to src/Cache/ResponseTagger/OnlyWhenEnabledResponseTagger.php index 3200178..8b012fa 100644 --- a/src/Cache/ResponseTagger/OnlyWhenActiveResponseTagger.php +++ b/src/Cache/ResponseTagger/OnlyWhenEnabledResponseTagger.php @@ -6,7 +6,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger; use Neusta\Pimcore\HttpCacheBundle\CacheScope; -final class OnlyWhenActiveResponseTagger implements ResponseTagger +final class OnlyWhenEnabledResponseTagger implements ResponseTagger { public function __construct( private readonly ResponseTagger $inner, @@ -16,7 +16,7 @@ public function __construct( public function tag(CacheTags $tags): void { - if ($this->cacheScope->isActive()) { + if ($this->cacheScope->isEnabled()) { $this->inner->tag($tags); } } diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 7c34fe3..3000af7 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -13,7 +13,7 @@ public function isCachingActive(): bool { trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::isActive()" instead.', __METHOD__, CacheScope::class); - return $this->isActive(); + return $this->isEnabled(); } public function activateCaching(): void diff --git a/src/CacheScope.php b/src/CacheScope.php index 367106a..40101e4 100644 --- a/src/CacheScope.php +++ b/src/CacheScope.php @@ -10,21 +10,21 @@ */ class CacheScope implements ResetInterface { - private bool $active = false; + private bool $enabled = false; private bool $disabled = false; /** - * Activates the tag collection. + * Enables cache-related behavior until the scope is reset. * - * Has no effect if {@see disable()] was already called. + * Has no effect if {@see disable()} was already called. */ public function enable(): void { - $this->active = true; + $this->enabled = true; } /** - * Permanently disables the tag collection for the current request. + * Disables cache-related behavior until the scope is reset. * * Survives {@see enable()} calls. */ @@ -33,14 +33,17 @@ public function disable(): void $this->disabled = true; } - public function isActive(): bool + /** + * Whether cache-related behavior is currently enabled. + */ + public function isEnabled(): bool { - return $this->active && !$this->disabled; + return $this->enabled && !$this->disabled; } public function reset(): void { - $this->active = false; + $this->enabled = false; $this->disabled = false; } } diff --git a/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php b/tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php similarity index 77% rename from tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php rename to tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php index 066e061..ffbcdb4 100644 --- a/tests/Unit/Cache/CacheInvalidator/OnlyWhenActiveCacheInvalidatorTest.php +++ b/tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php @@ -3,7 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Unit\Cache\CacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; -use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenActiveCacheInvalidator; +use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenEnabledCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\CacheScope; use PHPUnit\Framework\TestCase; @@ -11,11 +11,11 @@ use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; -final class OnlyWhenActiveCacheInvalidatorTest extends TestCase +final class OnlyWhenEnabledCacheInvalidatorTest extends TestCase { use ProphecyTrait; - private OnlyWhenActiveCacheInvalidator $subject; + private OnlyWhenEnabledCacheInvalidator $subject; /** @var ObjectProphecy */ private ObjectProphecy $decorated; @@ -27,7 +27,7 @@ protected function setUp(): void { $this->decorated = $this->prophesize(CacheInvalidator::class); $this->cacheScope = $this->prophesize(CacheScope::class); - $this->subject = new OnlyWhenActiveCacheInvalidator( + $this->subject = new OnlyWhenEnabledCacheInvalidator( $this->decorated->reveal(), $this->cacheScope->reveal(), ); @@ -36,11 +36,11 @@ protected function setUp(): void /** * @test */ - public function it_should_invalidate_tags_when_caching_is_active(): void + public function it_should_invalidate_tags_when_caching_is_enabled(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isActive()->willReturn(true); + $this->cacheScope->isEnabled()->willReturn(true); $this->subject->invalidate($tags); @@ -50,11 +50,11 @@ public function it_should_invalidate_tags_when_caching_is_active(): void /** * @test */ - public function it_should_not_invalidate_tags_when_caching_is_not_active(): void + public function it_should_not_invalidate_tags_when_caching_is_not_enabled(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isActive()->willReturn(false); + $this->cacheScope->isEnabled()->willReturn(false); $this->subject->invalidate($tags); diff --git a/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php b/tests/Unit/Cache/ResponseTagger/OnlyWhenEnabledResponseTaggerTest.php similarity index 82% rename from tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php rename to tests/Unit/Cache/ResponseTagger/OnlyWhenEnabledResponseTaggerTest.php index ec7ccc9..1d1ce08 100644 --- a/tests/Unit/Cache/ResponseTagger/OnlyWhenActiveResponseTaggerTest.php +++ b/tests/Unit/Cache/ResponseTagger/OnlyWhenEnabledResponseTaggerTest.php @@ -4,18 +4,18 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger; -use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\OnlyWhenActiveResponseTagger; +use Neusta\Pimcore\HttpCacheBundle\Cache\ResponseTagger\OnlyWhenEnabledResponseTagger; use Neusta\Pimcore\HttpCacheBundle\CacheScope; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; -final class OnlyWhenActiveResponseTaggerTest extends TestCase +final class OnlyWhenEnabledResponseTaggerTest extends TestCase { use ProphecyTrait; - private OnlyWhenActiveResponseTagger $subject; + private OnlyWhenEnabledResponseTagger $subject; /** @var ObjectProphecy */ private ObjectProphecy $decorated; @@ -27,7 +27,7 @@ protected function setUp(): void { $this->decorated = $this->prophesize(ResponseTagger::class); $this->cacheScope = $this->prophesize(CacheScope::class); - $this->subject = new OnlyWhenActiveResponseTagger( + $this->subject = new OnlyWhenEnabledResponseTagger( $this->decorated->reveal(), $this->cacheScope->reveal(), ); @@ -40,7 +40,7 @@ public function it_should_invalidate_tags_when_caching_is_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isActive()->willReturn(true); + $this->cacheScope->isEnabled()->willReturn(true); $this->subject->tag($tags); @@ -54,7 +54,7 @@ public function it_should_not_invalidate_tags_when_caching_is_not_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isActive()->willReturn(false); + $this->cacheScope->isEnabled()->willReturn(false); $this->subject->tag($tags); diff --git a/tests/Unit/CacheScopeTest.php b/tests/Unit/CacheScopeTest.php index 83ec104..5a34643 100644 --- a/tests/Unit/CacheScopeTest.php +++ b/tests/Unit/CacheScopeTest.php @@ -10,36 +10,36 @@ final class CacheScopeTest extends TestCase /** * @test */ - public function it_is_inactive_by_default(): void + public function it_is_disabled_by_default(): void { $cacheScope = new CacheScope(); - self::assertFalse($cacheScope->isActive()); + self::assertFalse($cacheScope->isEnabled()); } /** * @test */ - public function enable_activates_the_scope(): void + public function enable_enables_the_scope(): void { $cacheScope = new CacheScope(); $cacheScope->enable(); - self::assertTrue($cacheScope->isActive()); + self::assertTrue($cacheScope->isEnabled()); } /** * @test */ - public function disable_deactivates_the_scope(): void + public function disable_disables_scope_and_collection(): void { $cacheScope = new CacheScope(); - $cacheScope->enable(); + $cacheScope->disable(); - self::assertFalse($cacheScope->isActive()); + self::assertFalse($cacheScope->isEnabled()); } /** @@ -48,11 +48,11 @@ public function disable_deactivates_the_scope(): void public function disable_survives_later_enable_calls(): void { $cacheScope = new CacheScope(); - $cacheScope->disable(); + $cacheScope->enable(); - self::assertFalse($cacheScope->isActive()); + self::assertFalse($cacheScope->isEnabled()); } /** @@ -61,11 +61,11 @@ public function disable_survives_later_enable_calls(): void public function reset_deactivates_the_scope(): void { $cacheScope = new CacheScope(); - $cacheScope->enable(); + $cacheScope->reset(); - self::assertFalse($cacheScope->isActive()); + self::assertFalse($cacheScope->isEnabled()); } /** @@ -74,11 +74,11 @@ public function reset_deactivates_the_scope(): void public function reset_clears_disabled_state_so_scope_can_be_enabled_again(): void { $cacheScope = new CacheScope(); - $cacheScope->disable(); + $cacheScope->reset(); $cacheScope->enable(); - self::assertTrue($cacheScope->isActive()); + self::assertTrue($cacheScope->isEnabled()); } } From 6764e22912a681d7ba25e365ec540af7391f0da0 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 31 Aug 2026 00:56:40 +0200 Subject: [PATCH 09/11] Fix deprecation message inaccuracies in CacheActivator isCachingActive() pointed to a nonexistent CacheScope::isActive(), the trigger_deprecation() package name was missing the "team" prefix, and the deprecation version was stamped 0.7 even though 0.7.0/0.7.1 already shipped without it. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 2 +- config/services.php | 4 ++-- src/CacheActivator.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73150e9..4f7aeb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ - feature: New `scope` configuration option (`controller` / `request`) to control when tag collection begins within a request - feature: New `tag_fallback_document` configuration option to tag responses with fallback documents - deprecation: `CacheActivator` is deprecated; use `CacheScope` instead -- deprecation: `CacheActivator::isCachingActive()` is deprecated; use `CacheScope::isActive()` instead +- deprecation: `CacheActivator::isCachingActive()` is deprecated; use `CacheScope::isEnabled()` instead - deprecation: `CacheActivator::activateCaching()` is deprecated; use `CacheScope::enable()` instead - deprecation: `CacheActivator::deactivateCaching()` is deprecated; use `CacheScope::disable()` instead diff --git a/config/services.php b/config/services.php index 5cfc5de..8b85e96 100644 --- a/config/services.php +++ b/config/services.php @@ -38,9 +38,9 @@ ->alias(CacheScope::class, 'neusta_pimcore_http_cache.cache_scope'); $services->alias('neusta_pimcore_http_cache.cache_activator', 'neusta_pimcore_http_cache.cache_scope') - ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "neusta_pimcore_http_cache.cache_scope" instead.') + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.8', 'The "%alias_id%" alias is deprecated, use "neusta_pimcore_http_cache.cache_scope" instead.') ->alias(CacheActivator::class, 'neusta_pimcore_http_cache.cache_activator') - ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.7', 'The "%alias_id%" alias is deprecated, use "' . CacheScope::class . '" instead.'); + ->deprecate('teamneusta/pimcore-http-cache-bundle', '0.8', 'The "%alias_id%" alias is deprecated, use "' . CacheScope::class . '" instead.'); $services->set('neusta_pimcore_http_cache.cache_scope.console_listener', ConsoleCacheScopeListener::class) ->arg('$cacheScope', service('neusta_pimcore_http_cache.cache_scope')) diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 3000af7..46d617e 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -3,7 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle; /** - * @deprecated since version 0.7, use {@see CacheScope} instead. + * @deprecated since version 0.8, use {@see CacheScope} instead. * * @phpstan-ignore class.extendsFinalByPhpDoc */ @@ -11,14 +11,14 @@ final class CacheActivator extends CacheScope { public function isCachingActive(): bool { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::isActive()" instead.', __METHOD__, CacheScope::class); + trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::isEnabled()" instead.', __METHOD__, CacheScope::class); return $this->isEnabled(); } public function activateCaching(): void { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::enable()" instead.', __METHOD__, CacheScope::class); + trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::enable()" instead.', __METHOD__, CacheScope::class); $this->reset(); $this->enable(); @@ -26,7 +26,7 @@ public function activateCaching(): void public function deactivateCaching(): void { - trigger_deprecation('neusta/pimcore-http-cache-bundle', '0.7', '"%s()" is deprecated, use "%s::disable()" instead.', __METHOD__, CacheScope::class); + trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::disable()" instead.', __METHOD__, CacheScope::class); $this->disable(); } From 77642a78b67f72d95642ffbbdc224129da428979 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 31 Aug 2026 09:37:51 +0200 Subject: [PATCH 10/11] Decouple cache invalidation from the tagging scope CacheScope::isEnabled() gated both tag collection and invalidation, but HttpCacheScopeListener only enables it for cacheable, non-admin GET/HEAD requests. That meant invalidation was silently skipped for exactly the requests that trigger it most (an admin-UI save, or any non-GET endpoint). Add CacheScope::isInvalidating(), which is active by default everywhere and only stops once disable() is called, independently of whether tag collection is enabled for the current request. Wire the invalidator chain to it (OnlyWhenEnabledCacheInvalidator -> OnlyWhenInvalidatingCacheInvalidator) and map the deprecated CacheActivator::isCachingActive() to it, restoring the pre-0.7 CacheActivator default. Revive the pre-rewrite ArrangeCacheTest test helper: now that invalidation runs unconditionally, fixture creation in integration tests needs to suppress it explicitly, the same way it did before CacheScope existed. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 4 +- config/services.php | 4 +- doc/8-cache-scope.md | 21 ++++++- ... OnlyWhenInvalidatingCacheInvalidator.php} | 4 +- src/CacheActivator.php | 4 +- src/CacheScope.php | 12 ++++ .../Fixtures/update_object_route.php | 10 +++ .../Integration/Helpers/ArrangeCacheTest.php | 30 +++++++++ .../Invalidation/CancelInvalidationTest.php | 16 ++--- .../InvalidateAdditionalTagTest.php | 43 +++++-------- .../Invalidation/InvalidateAssetTest.php | 12 ++-- .../Invalidation/InvalidateDocumentTest.php | 14 +++-- .../InvalidateFromNonCacheableRequestTest.php | 61 +++++++++++++++++++ .../Invalidation/InvalidateObjectTest.php | 12 ++-- .../Tagging/CollectTagsDataTest.php | 26 ++++---- .../Tagging/TagAdditionalTagTest.php | 22 ++++--- tests/Integration/Tagging/TagAssetTest.php | 12 ++-- tests/Integration/Tagging/TagDocumentTest.php | 22 ++++--- tests/Integration/Tagging/TagObjectTest.php | 16 ++--- ...yWhenInvalidatingCacheInvalidatorTest.php} | 16 ++--- tests/Unit/CacheActivatorTest.php | 8 +++ tests/Unit/CacheScopeTest.php | 46 ++++++++++++++ .../src/Controller/UpdateObjectController.php | 21 +++++++ 23 files changed, 323 insertions(+), 113 deletions(-) rename src/Cache/CacheInvalidator/{OnlyWhenEnabledCacheInvalidator.php => OnlyWhenInvalidatingCacheInvalidator.php} (80%) create mode 100644 tests/Integration/Fixtures/update_object_route.php create mode 100644 tests/Integration/Helpers/ArrangeCacheTest.php create mode 100644 tests/Integration/Invalidation/InvalidateFromNonCacheableRequestTest.php rename tests/Unit/Cache/CacheInvalidator/{OnlyWhenEnabledCacheInvalidatorTest.php => OnlyWhenInvalidatingCacheInvalidatorTest.php} (72%) create mode 100644 tests/app/src/Controller/UpdateObjectController.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f7aeb3..6946dd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,11 @@ ## Version 0.8.0 -- feature: Introduced `CacheScope` service for controlling when and whether cache tags are collected +- feature: Introduced `CacheScope` service for controlling when and whether cache tags are collected. Cache invalidation is active by default everywhere (including non-cacheable and admin-context requests) and only stops once `CacheScope::disable()` is called; tag collection instead requires the scope to be explicitly enabled for the current request - feature: New `scope` configuration option (`controller` / `request`) to control when tag collection begins within a request - feature: New `tag_fallback_document` configuration option to tag responses with fallback documents - deprecation: `CacheActivator` is deprecated; use `CacheScope` instead -- deprecation: `CacheActivator::isCachingActive()` is deprecated; use `CacheScope::isEnabled()` instead +- deprecation: `CacheActivator::isCachingActive()` is deprecated; use `CacheScope::isInvalidating()` instead - deprecation: `CacheActivator::activateCaching()` is deprecated; use `CacheScope::enable()` instead - deprecation: `CacheActivator::deactivateCaching()` is deprecated; use `CacheScope::disable()` instead diff --git a/config/services.php b/config/services.php index 8b85e96..8786b75 100644 --- a/config/services.php +++ b/config/services.php @@ -4,7 +4,7 @@ use Neusta\Pimcore\HttpCacheBundle\Adapter\FOSHttpCache\CacheInvalidatorAdapter; use Neusta\Pimcore\HttpCacheBundle\Adapter\FOSHttpCache\ResponseTaggerAdapter; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; -use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenEnabledCacheInvalidator; +use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenInvalidatingCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\RemoveDisabledTagsCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\Element\AssetCacheTagChecker; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTagChecker\Element\DocumentCacheTagChecker; @@ -62,7 +62,7 @@ ->decorate('neusta_pimcore_http_cache.cache_invalidator', null, -99) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_tag_checker')]); - $services->set(null, OnlyWhenEnabledCacheInvalidator::class) + $services->set(null, OnlyWhenInvalidatingCacheInvalidator::class) ->decorate('neusta_pimcore_http_cache.cache_invalidator', null, -100) ->args([service('.inner'), service('neusta_pimcore_http_cache.cache_scope')]); diff --git a/doc/8-cache-scope.md b/doc/8-cache-scope.md index 4cde574..898e7ee 100644 --- a/doc/8-cache-scope.md +++ b/doc/8-cache-scope.md @@ -1,7 +1,16 @@ ## Cache Scope The cache scope controls whether and from which point in the request lifecycle cache-related behavior is enabled. -Tags are only collected while the scope is **enabled**. If the scope is disabled, all tagging and invalidation is skipped. + +Tagging and invalidation are gated independently: + +- **Tagging** only happens while the scope is **enabled**. Tagging only ever makes sense for a request whose response + can actually be cached, so the scope must be explicitly activated (see [Automatic activation](#automatic-activation)). +- **Invalidation** is active by default — everywhere, including non-cacheable requests such as an admin-UI save or a + custom `POST` endpoint — and only stops once `disable()` has been called. Invalidation does not depend on the scope + being enabled. + +Calling `disable()` always stops both tagging and invalidation, regardless of the above. ### Automatic activation @@ -11,6 +20,8 @@ The bundle activates the scope automatically in two contexts: When it is activated depends on the [`scope` configuration option](#scope-option). - **Console commands**: The scope is activated at the start of every console command. +This only affects tagging; invalidation runs regardless of whether the current request or command activates the scope. + ### Scope option The `scope` option controls at which point in the request lifecycle the scope is activated for HTTP requests: @@ -42,11 +53,15 @@ final class MyService public function doSomething(): void { if ($this->cacheScope->isEnabled()) { - // cache-related behavior is currently enabled + // tagging is currently enabled + } + + if ($this->cacheScope->isInvalidating()) { + // invalidation is currently active } $this->cacheScope->disable(); - // cache-related behavior is disabled from now on + // both tagging and invalidation are disabled from now on } } ``` diff --git a/src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php b/src/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidator.php similarity index 80% rename from src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php rename to src/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidator.php index fd17715..3228035 100644 --- a/src/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidator.php +++ b/src/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidator.php @@ -6,7 +6,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\CacheScope; -final class OnlyWhenEnabledCacheInvalidator implements CacheInvalidator +final class OnlyWhenInvalidatingCacheInvalidator implements CacheInvalidator { public function __construct( private readonly CacheInvalidator $inner, @@ -16,7 +16,7 @@ public function __construct( public function invalidate(CacheTags $tags): void { - if ($this->cacheScope->isEnabled()) { + if ($this->cacheScope->isInvalidating()) { $this->inner->invalidate($tags); } } diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 46d617e..936d44e 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -11,9 +11,9 @@ final class CacheActivator extends CacheScope { public function isCachingActive(): bool { - trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::isEnabled()" instead.', __METHOD__, CacheScope::class); + trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::isInvalidating()" instead.', __METHOD__, CacheScope::class); - return $this->isEnabled(); + return $this->isInvalidating(); } public function activateCaching(): void diff --git a/src/CacheScope.php b/src/CacheScope.php index 40101e4..4a0f89d 100644 --- a/src/CacheScope.php +++ b/src/CacheScope.php @@ -41,6 +41,18 @@ public function isEnabled(): bool return $this->enabled && !$this->disabled; } + /** + * Whether cache invalidation is currently active. + * + * Unlike {@see isEnabled()}, invalidation is active by default and only + * stops once {@see disable()} has been called; it does not require an + * explicit {@see enable()} call. + */ + public function isInvalidating(): bool + { + return !$this->disabled; + } + public function reset(): void { $this->enabled = false; diff --git a/tests/Integration/Fixtures/update_object_route.php b/tests/Integration/Fixtures/update_object_route.php new file mode 100644 index 0000000..e01668c --- /dev/null +++ b/tests/Integration/Fixtures/update_object_route.php @@ -0,0 +1,10 @@ +add('update_object', '/update-object') + ->controller(UpdateObjectController::class) + ->methods(['POST']); +}; diff --git a/tests/Integration/Helpers/ArrangeCacheTest.php b/tests/Integration/Helpers/ArrangeCacheTest.php new file mode 100644 index 0000000..fd1c5e4 --- /dev/null +++ b/tests/Integration/Helpers/ArrangeCacheTest.php @@ -0,0 +1,30 @@ +get('neusta_pimcore_http_cache.cache_scope'); + \assert($cacheScope instanceof CacheScope); + + $cacheScope->disable(); + try { + return $arrange(); + } finally { + $cacheScope->reset(); + } + } +} diff --git a/tests/Integration/Invalidation/CancelInvalidationTest.php b/tests/Integration/Invalidation/CancelInvalidationTest.php index 9559ce1..dd661f7 100644 --- a/tests/Integration/Invalidation/CancelInvalidationTest.php +++ b/tests/Integration/Invalidation/CancelInvalidationTest.php @@ -4,6 +4,7 @@ use FOS\HttpCacheBundle\CacheManager; use Neusta\Pimcore\HttpCacheBundle\Element\ElementInvalidationEvent; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -16,6 +17,7 @@ final class CancelInvalidationTest extends ConfigurableKernelTestCase { + use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -31,8 +33,6 @@ protected function setUp(): void ElementInvalidationEvent::class, static fn ($event) => $event->cancel = true, ); - - self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); } /** @@ -45,7 +45,7 @@ protected function setUp(): void ])] public function cancel_invalidation_on_object_update(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $object->setContent('Updated test content')->save(); @@ -62,7 +62,7 @@ public function cancel_invalidation_on_object_update(): void ])] public function cancel_invalidation_on_document_update(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $document->setKey('updated_test_document_page')->save(); @@ -79,7 +79,7 @@ public function cancel_invalidation_on_document_update(): void ])] public function cancel_invalidation_on_asset_update(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); $asset->setData('Updated test content')->save(); @@ -96,7 +96,7 @@ public function cancel_invalidation_on_asset_update(): void ])] public function cancel_invalidation_on_object_delete(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $object->delete(); @@ -113,7 +113,7 @@ public function cancel_invalidation_on_object_delete(): void ])] public function cancel_invalidation_on_document_delete(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $document->delete(); @@ -130,7 +130,7 @@ public function cancel_invalidation_on_document_delete(): void ])] public function cancel_invalidation_on_asset_delete(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); $asset->delete(); diff --git a/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php b/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php index 942fea4..fd76afa 100644 --- a/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php +++ b/tests/Integration/Invalidation/InvalidateAdditionalTagTest.php @@ -5,8 +5,8 @@ use FOS\HttpCacheBundle\CacheManager; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTag; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheType\CustomCacheType; -use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\Element\ElementInvalidationEvent; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -19,18 +19,15 @@ final class InvalidateAdditionalTagTest extends ConfigurableKernelTestCase { + use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; - private CacheScope $cacheScope; - /** @var ObjectProphecy */ private ObjectProphecy $cacheManager; protected function setUp(): void { - $this->cacheScope = self::getContainer()->get('neusta_pimcore_http_cache.cache_scope'); - $this->cacheManager = $this->prophesize(CacheManager::class); $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); @@ -56,9 +53,8 @@ protected function setUp(): void ])] public function invalidate_additional_tag_on_object_update(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - $this->cacheScope->enable(); $object->setContent('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -77,9 +73,8 @@ public function invalidate_additional_tag_on_object_update(): void ])] public function does_not_invalidate_additional_tag_on_object_update_when_cache_type_is_disabled(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - $this->cacheScope->enable(); $object->setKey('updated_test_object')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -98,9 +93,8 @@ public function does_not_invalidate_additional_tag_on_object_update_when_cache_t ])] public function invalidate_additional_tag_on_document_update(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - $this->cacheScope->enable(); $document->setKey('updated_test_document_page')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -119,9 +113,8 @@ public function invalidate_additional_tag_on_document_update(): void ])] public function does_not_invalidate_additional_tag_on_document_update_when_cache_type_is_disabled(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - $this->cacheScope->enable(); $document->setKey('updated_test_document_page')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -140,9 +133,8 @@ public function does_not_invalidate_additional_tag_on_document_update_when_cache ])] public function invalidate_additional_tag_on_asset_update(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - $this->cacheScope->enable(); $asset->setData('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -161,9 +153,8 @@ public function invalidate_additional_tag_on_asset_update(): void ])] public function does_not_invalidate_additional_tag_on_asset_update_when_cache_type_is_disabled(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - $this->cacheScope->enable(); $asset->setData('Updated test content')->save(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -182,9 +173,8 @@ public function does_not_invalidate_additional_tag_on_asset_update_when_cache_ty ])] public function invalidate_additional_tag_on_object_deletion(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - $this->cacheScope->enable(); $object->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -203,9 +193,8 @@ public function invalidate_additional_tag_on_object_deletion(): void ])] public function does_not_invalidate_additional_tag_on_object_deletion_when_cache_type_is_disabled(): void { - $object = TestObjectFactory::simpleObject()->save(); + $object = self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); - $this->cacheScope->enable(); $object->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('o42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -224,9 +213,8 @@ public function does_not_invalidate_additional_tag_on_object_deletion_when_cache ])] public function invalidate_additional_tag_on_asset_deletion(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - $this->cacheScope->enable(); $asset->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -245,9 +233,8 @@ public function invalidate_additional_tag_on_asset_deletion(): void ])] public function does_not_invalidate_additional_tag_on_asset_deletion_when_cache_type_is_disabled(): void { - $asset = TestAssetFactory::simpleAsset()->save(); + $asset = self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); - $this->cacheScope->enable(); $asset->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('a42', 'foo-bar')))->shouldNotHaveBeenCalled(); @@ -266,9 +253,8 @@ public function does_not_invalidate_additional_tag_on_asset_deletion_when_cache_ ])] public function invalidate_additional_tag_on_document_deletion(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - $this->cacheScope->enable(); $document->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldHaveBeenCalledTimes(1); @@ -287,9 +273,8 @@ public function invalidate_additional_tag_on_document_deletion(): void ])] public function does_not_invalidate_additional_tag_on_document_deletion_when_cache_type_was_disabled(): void { - $document = TestDocumentFactory::simplePage()->save(); + $document = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); - $this->cacheScope->enable(); $document->delete(); $this->cacheManager->invalidateTags(Argument::that($this->hasTags('d42', 'foo-bar')))->shouldNotHaveBeenCalled(); diff --git a/tests/Integration/Invalidation/InvalidateAssetTest.php b/tests/Integration/Invalidation/InvalidateAssetTest.php index 6de5ed4..f1efd82 100644 --- a/tests/Integration/Invalidation/InvalidateAssetTest.php +++ b/tests/Integration/Invalidation/InvalidateAssetTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -14,6 +15,7 @@ final class InvalidateAssetTest extends ConfigurableKernelTestCase { + use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -32,11 +34,11 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->asset = TestAssetFactory::simpleAsset()->save(); - $this->folder = TestAssetFactory::simpleFolder()->save(); - $this->image = TestAssetFactory::simpleImage()->save(); - - self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); + self::arrange(function (): void { + $this->asset = TestAssetFactory::simpleAsset()->save(); + $this->folder = TestAssetFactory::simpleFolder()->save(); + $this->image = TestAssetFactory::simpleImage()->save(); + }); } /** diff --git a/tests/Integration/Invalidation/InvalidateDocumentTest.php b/tests/Integration/Invalidation/InvalidateDocumentTest.php index 1bf47dc..0653570 100644 --- a/tests/Integration/Invalidation/InvalidateDocumentTest.php +++ b/tests/Integration/Invalidation/InvalidateDocumentTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -14,6 +15,7 @@ final class InvalidateDocumentTest extends ConfigurableKernelTestCase { + use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -34,12 +36,12 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->document = TestDocumentFactory::simplePage()->save(); - $this->hardlink = TestDocumentFactory::simpleHardLink()->save(); - $this->email = TestDocumentFactory::simpleEmail()->save(); - $this->folder = TestDocumentFactory::simpleFolder()->save(); - - self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); + self::arrange(function (): void { + $this->document = TestDocumentFactory::simplePage()->save(); + $this->hardlink = TestDocumentFactory::simpleHardLink()->save(); + $this->email = TestDocumentFactory::simpleEmail()->save(); + $this->folder = TestDocumentFactory::simpleFolder()->save(); + }); } /** diff --git a/tests/Integration/Invalidation/InvalidateFromNonCacheableRequestTest.php b/tests/Integration/Invalidation/InvalidateFromNonCacheableRequestTest.php new file mode 100644 index 0000000..17e6155 --- /dev/null +++ b/tests/Integration/Invalidation/InvalidateFromNonCacheableRequestTest.php @@ -0,0 +1,61 @@ + */ + private ObjectProphecy $cacheManager; + + protected function setUp(): void + { + $this->client = self::createClient(); + + $this->cacheManager = $this->prophesize(CacheManager::class); + $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); + $this->cacheManager->flush()->willReturn(0); + self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); + } + + /** + * @test + */ + #[ConfigureExtension('neusta_pimcore_http_cache', [ + 'elements' => [ + 'objects' => true, + ], + ])] + public function response_is_invalidated_when_object_is_updated_via_a_post_request(): void + { + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); + + $this->client->request('POST', '/update-object?id=42', ['content' => 'Updated test content']); + + self::assertSame(200, $this->client->getResponse()->getStatusCode()); + $this->cacheManager->invalidateTags(['o42'])->shouldHaveBeenCalledTimes(1); + } +} diff --git a/tests/Integration/Invalidation/InvalidateObjectTest.php b/tests/Integration/Invalidation/InvalidateObjectTest.php index eeaafdd..6e2b2b9 100644 --- a/tests/Integration/Invalidation/InvalidateObjectTest.php +++ b/tests/Integration/Invalidation/InvalidateObjectTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Invalidation; use FOS\HttpCacheBundle\CacheManager; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -15,6 +16,7 @@ final class InvalidateObjectTest extends ConfigurableKernelTestCase { + use ArrangeCacheTest; use ProphecyTrait; use ResetDatabase; @@ -33,11 +35,11 @@ protected function setUp(): void $this->cacheManager->invalidateTags(Argument::any())->willReturn($this->cacheManager->reveal()); self::getContainer()->set('fos_http_cache.cache_manager', $this->cacheManager->reveal()); - $this->object = TestObjectFactory::simpleObject()->save(); - $this->folder = TestObjectFactory::simpleFolder()->save(); - $this->variant = TestObjectFactory::simpleVariant()->save(); - - self::getContainer()->get('neusta_pimcore_http_cache.cache_scope')->enable(); + self::arrange(function (): void { + $this->object = TestObjectFactory::simpleObject()->save(); + $this->folder = TestObjectFactory::simpleFolder()->save(); + $this->variant = TestObjectFactory::simpleVariant()->save(); + }); } /** diff --git a/tests/Integration/Tagging/CollectTagsDataTest.php b/tests/Integration/Tagging/CollectTagsDataTest.php index ad84957..0ebbed0 100644 --- a/tests/Integration/Tagging/CollectTagsDataTest.php +++ b/tests/Integration/Tagging/CollectTagsDataTest.php @@ -7,6 +7,7 @@ use Neusta\Pimcore\HttpCacheBundle\CacheScope; use Neusta\Pimcore\HttpCacheBundle\DataCollector; use Neusta\Pimcore\HttpCacheBundle\Element\ElementTaggingEvent; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -24,6 +25,7 @@ ])] final class CollectTagsDataTest extends ConfigurableWebTestcase { + use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -44,7 +46,7 @@ protected function setUp(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] public function collect_tags_for_type_document(): void { - TestDocumentFactory::simplePage()->save(); + self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $this->client->request('GET', '/test_document_page'); $this->client->enableProfiler(); @@ -70,8 +72,8 @@ public function collect_tags_for_type_document(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] public function collect_tags_for_type_document_in_request_scope(): void { - $parent = TestDocumentFactory::simplePage()->save(); - TestDocumentFactory::simpleSnippet()->setParent($parent)->save(); + $parent = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + self::arrange(static fn () => TestDocumentFactory::simpleSnippet()->setParent($parent)->save()); $this->client->request('GET', '/test_document_page/test_document_snippet'); $this->client->enableProfiler(); @@ -100,7 +102,7 @@ public function collect_tags_for_type_document_in_request_scope(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function collect_tags_for_type_object(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -125,7 +127,7 @@ public function collect_tags_for_type_object(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_asset_route.php')] public function collect_tags_of_type_asset(): void { - TestAssetFactory::simpleAsset()->save(); + self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); $this->client->request('GET', '/get-asset?id=42'); $this->client->enableProfiler(); @@ -153,7 +155,7 @@ public function collect_tags_of_type_asset(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function collect_tags_of_type_custom(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -185,7 +187,7 @@ public function collect_tags_of_type_custom(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_type_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -207,7 +209,7 @@ public function does_not_collect_tags_when_type_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_caching_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-object?id=42'); @@ -235,7 +237,7 @@ public function does_not_collect_tags_when_caching_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_object_type_is_disabled(): void { - TestObjectFactory::simpleVariant()->save(); + self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -262,7 +264,7 @@ public function does_not_collect_tags_when_object_type_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_object_class_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -290,7 +292,7 @@ public function does_not_collect_tags_when_object_class_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_profiler_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); @@ -307,7 +309,7 @@ public function does_not_collect_tags_when_profiler_is_disabled(): void #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] public function does_not_collect_tags_when_collect_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); $this->client->enableProfiler(); diff --git a/tests/Integration/Tagging/TagAdditionalTagTest.php b/tests/Integration/Tagging/TagAdditionalTagTest.php index 958c9a1..c387b15 100644 --- a/tests/Integration/Tagging/TagAdditionalTagTest.php +++ b/tests/Integration/Tagging/TagAdditionalTagTest.php @@ -7,6 +7,7 @@ use Neusta\Pimcore\HttpCacheBundle\Cache\CacheType\ElementCacheType; use Neusta\Pimcore\HttpCacheBundle\Element\ElementTaggingEvent; use Neusta\Pimcore\HttpCacheBundle\Element\ElementType; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; @@ -21,6 +22,7 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] final class TagAdditionalTagTest extends ConfigurableWebTestcase { + use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -40,8 +42,10 @@ protected function setUp(): void ])] public function response_is_tagged_with_additional_tag_when_asset_is_loaded(): void { - TestAssetFactory::simpleAsset()->save(); - TestAssetFactory::simpleImage()->save(); + self::arrange(static function (): void { + TestAssetFactory::simpleAsset()->save(); + TestAssetFactory::simpleImage()->save(); + }); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -70,8 +74,10 @@ public function response_is_tagged_with_additional_tag_when_asset_is_loaded(): v ])] public function response_is_tagged_with_additional_tag_when_document_is_loaded(): void { - TestDocumentFactory::simplePage()->save(); - TestDocumentFactory::simpleSnippet()->save(); + self::arrange(static function (): void { + TestDocumentFactory::simplePage()->save(); + TestDocumentFactory::simpleSnippet()->save(); + }); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -100,8 +106,10 @@ public function response_is_tagged_with_additional_tag_when_document_is_loaded() ])] public function response_is_tagged_with_additional_tag_when_object_is_loaded(): void { - TestObjectFactory::simpleObject()->save(); - TestObjectFactory::simpleVariant()->save(); + self::arrange(static function (): void { + TestObjectFactory::simpleObject()->save(); + TestObjectFactory::simpleVariant()->save(); + }); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, @@ -133,7 +141,7 @@ public function response_is_tagged_with_additional_tag_when_object_is_loaded(): ])] public function response_is_tagged_with_custom_tag_when_element_is_loaded(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); self::getContainer()->get('event_dispatcher')->addListener( ElementTaggingEvent::class, diff --git a/tests/Integration/Tagging/TagAssetTest.php b/tests/Integration/Tagging/TagAssetTest.php index 4ce9d74..fa345e3 100644 --- a/tests/Integration/Tagging/TagAssetTest.php +++ b/tests/Integration/Tagging/TagAssetTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; use Neusta\Pimcore\HttpCacheBundle\CacheScope; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestAssetFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -13,6 +14,7 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_asset_route.php')] final class TagAssetTest extends ConfigurableWebTestcase { + use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -32,7 +34,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_asset_is_loaded(): void { - TestAssetFactory::simpleAsset()->save(); + self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); $this->client->request('GET', '/get-asset?id=42'); @@ -54,7 +56,7 @@ public function response_is_tagged_with_expected_tags_when_asset_is_loaded(): vo ])] public function response_is_not_tagged_when_assets_is_not_enabled(): void { - TestAssetFactory::simpleAsset()->save(); + self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); $this->client->request('GET', '/get-asset?id=42'); @@ -76,7 +78,7 @@ public function response_is_not_tagged_when_assets_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - TestAssetFactory::simpleAsset()->save(); + self::arrange(static fn () => TestAssetFactory::simpleAsset()->save()); self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-asset?id=42'); @@ -99,7 +101,7 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void ])] public function response_is_not_tagged_when_asset_is_of_type_folder(): void { - TestAssetFactory::simpleFolder()->save(); + self::arrange(static fn () => TestAssetFactory::simpleFolder()->save()); $this->client->request('GET', '/get-asset?id=23'); @@ -126,7 +128,7 @@ public function response_is_not_tagged_when_asset_is_of_type_folder(): void ])] public function response_is_not_tagged_for_specified_asset_type(): void { - TestAssetFactory::simpleImage()->save(); + self::arrange(static fn () => TestAssetFactory::simpleImage()->save()); $this->client->request('GET', '/get-asset?id=17'); diff --git a/tests/Integration/Tagging/TagDocumentTest.php b/tests/Integration/Tagging/TagDocumentTest.php index 1dc7919..67f4e3d 100644 --- a/tests/Integration/Tagging/TagDocumentTest.php +++ b/tests/Integration/Tagging/TagDocumentTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; use Neusta\Pimcore\HttpCacheBundle\CacheScope; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestDocumentFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -13,6 +14,7 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_document_route.php')] final class TagDocumentTest extends ConfigurableWebTestcase { + use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -32,7 +34,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_page_is_loaded(): void { - TestDocumentFactory::simplePage()->save(); + self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $this->client->request('GET', '/test_document_page'); @@ -54,7 +56,7 @@ public function response_is_tagged_with_expected_tags_when_page_is_loaded(): voi ])] public function response_is_tagged_with_expected_tags_when_snippet_is_loaded(): void { - TestDocumentFactory::simpleSnippet()->save(); + self::arrange(static fn () => TestDocumentFactory::simpleSnippet()->save()); $this->client->request('GET', '/get-document?id=23'); @@ -76,7 +78,7 @@ public function response_is_tagged_with_expected_tags_when_snippet_is_loaded(): ])] public function response_is_not_tagged_when_document_type_is_email(): void { - TestDocumentFactory::simpleEmail()->save(); + self::arrange(static fn () => TestDocumentFactory::simpleEmail()->save()); $this->client->request('GET', '/get-document?id=17'); @@ -98,7 +100,7 @@ public function response_is_not_tagged_when_document_type_is_email(): void ])] public function response_is_not_tagged_when_document_type_is_hard_link(): void { - TestDocumentFactory::simpleHardLink()->save(); + self::arrange(static fn () => TestDocumentFactory::simpleHardLink()->save()); $this->client->request('GET', '/get-document?id=33'); @@ -120,7 +122,7 @@ public function response_is_not_tagged_when_document_type_is_hard_link(): void ])] public function response_is_not_tagged_when_document_type_is_folder(): void { - TestDocumentFactory::simpleFolder()->save(); + self::arrange(static fn () => TestDocumentFactory::simpleFolder()->save()); $this->client->request('GET', '/get-document?id=97'); @@ -142,7 +144,7 @@ public function response_is_not_tagged_when_document_type_is_folder(): void ])] public function response_is_not_tagged_when_documents_is_not_enabled(): void { - TestDocumentFactory::simplePage()->save(); + self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $this->client->request('GET', '/test_document_page'); @@ -164,7 +166,7 @@ public function response_is_not_tagged_when_documents_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - TestDocumentFactory::simplePage()->save(); + self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/test_document_page'); @@ -188,8 +190,8 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void ])] public function response_is_tagged_with_the_document_parents_when_in_request_scope(): void { - $parent = TestDocumentFactory::simplePage()->save(); - TestDocumentFactory::simpleSnippet()->setParent($parent)->save(); + $parent = self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); + self::arrange(static fn () => TestDocumentFactory::simpleSnippet()->setParent($parent)->save()); $this->client->request('GET', '/test_document_page/test_document_snippet'); @@ -217,7 +219,7 @@ public function response_is_tagged_with_the_document_parents_when_in_request_sco ])] public function response_is_not_tagged_when_type_is_disabled(): void { - TestDocumentFactory::simplePage()->save(); + self::arrange(static fn () => TestDocumentFactory::simplePage()->save()); $this->client->request('GET', '/test_document_page'); diff --git a/tests/Integration/Tagging/TagObjectTest.php b/tests/Integration/Tagging/TagObjectTest.php index 1fce50f..92d7c64 100644 --- a/tests/Integration/Tagging/TagObjectTest.php +++ b/tests/Integration/Tagging/TagObjectTest.php @@ -3,6 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Tagging; use Neusta\Pimcore\HttpCacheBundle\CacheScope; +use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\ArrangeCacheTest; use Neusta\Pimcore\HttpCacheBundle\Tests\Integration\Helpers\TestObjectFactory; use Neusta\Pimcore\TestingFramework\Database\ResetDatabase; use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; @@ -13,6 +14,7 @@ #[ConfigureRoute(__DIR__ . '/../Fixtures/get_object_route.php')] final class TagObjectTest extends ConfigurableWebTestcase { + use ArrangeCacheTest; use ResetDatabase; private KernelBrowser $client; @@ -32,7 +34,7 @@ protected function setUp(): void ])] public function response_is_tagged_with_expected_tags_when_object_is_loaded(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); @@ -54,7 +56,7 @@ public function response_is_tagged_with_expected_tags_when_object_is_loaded(): v ])] public function response_is_not_tagged_when_objects_is_not_enabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); @@ -76,7 +78,7 @@ public function response_is_not_tagged_when_objects_is_not_enabled(): void ])] public function response_is_not_tagged_when_caching_is_deactivated(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); self::getContainer()->get(CacheScope::class)->disable(); $this->client->request('GET', '/get-object?id=42'); @@ -104,7 +106,7 @@ public function response_is_not_tagged_when_caching_is_deactivated(): void ])] public function response_is_not_tagged_when_object_type_is_disabled(): void { - TestObjectFactory::simpleVariant()->save(); + self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); $this->client->request('GET', '/get-object?id=17'); @@ -131,7 +133,7 @@ public function response_is_not_tagged_when_object_type_is_disabled(): void ])] public function response_ist_tagged_when_object_type_is_enabled(): void { - TestObjectFactory::simpleVariant()->save(); + self::arrange(static fn () => TestObjectFactory::simpleVariant()->save()); $this->client->request('GET', '/get-object?id=17'); @@ -158,7 +160,7 @@ public function response_ist_tagged_when_object_type_is_enabled(): void ])] public function response_is_not_tagged_when_object_class_is_disabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); @@ -185,7 +187,7 @@ public function response_is_not_tagged_when_object_class_is_disabled(): void ])] public function response_is_tagged_when_object_class_is_enabled(): void { - TestObjectFactory::simpleObject()->save(); + self::arrange(static fn () => TestObjectFactory::simpleObject()->save()); $this->client->request('GET', '/get-object?id=42'); diff --git a/tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php b/tests/Unit/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidatorTest.php similarity index 72% rename from tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php rename to tests/Unit/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidatorTest.php index ffbcdb4..bc66a28 100644 --- a/tests/Unit/Cache/CacheInvalidator/OnlyWhenEnabledCacheInvalidatorTest.php +++ b/tests/Unit/Cache/CacheInvalidator/OnlyWhenInvalidatingCacheInvalidatorTest.php @@ -3,7 +3,7 @@ namespace Neusta\Pimcore\HttpCacheBundle\Tests\Unit\Cache\CacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator; -use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenEnabledCacheInvalidator; +use Neusta\Pimcore\HttpCacheBundle\Cache\CacheInvalidator\OnlyWhenInvalidatingCacheInvalidator; use Neusta\Pimcore\HttpCacheBundle\Cache\CacheTags; use Neusta\Pimcore\HttpCacheBundle\CacheScope; use PHPUnit\Framework\TestCase; @@ -11,11 +11,11 @@ use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; -final class OnlyWhenEnabledCacheInvalidatorTest extends TestCase +final class OnlyWhenInvalidatingCacheInvalidatorTest extends TestCase { use ProphecyTrait; - private OnlyWhenEnabledCacheInvalidator $subject; + private OnlyWhenInvalidatingCacheInvalidator $subject; /** @var ObjectProphecy */ private ObjectProphecy $decorated; @@ -27,7 +27,7 @@ protected function setUp(): void { $this->decorated = $this->prophesize(CacheInvalidator::class); $this->cacheScope = $this->prophesize(CacheScope::class); - $this->subject = new OnlyWhenEnabledCacheInvalidator( + $this->subject = new OnlyWhenInvalidatingCacheInvalidator( $this->decorated->reveal(), $this->cacheScope->reveal(), ); @@ -36,11 +36,11 @@ protected function setUp(): void /** * @test */ - public function it_should_invalidate_tags_when_caching_is_enabled(): void + public function it_should_invalidate_tags_when_invalidation_is_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isEnabled()->willReturn(true); + $this->cacheScope->isInvalidating()->willReturn(true); $this->subject->invalidate($tags); @@ -50,11 +50,11 @@ public function it_should_invalidate_tags_when_caching_is_enabled(): void /** * @test */ - public function it_should_not_invalidate_tags_when_caching_is_not_enabled(): void + public function it_should_not_invalidate_tags_when_invalidation_is_not_active(): void { $tags = CacheTags::fromStrings(['tag1', 'tag2']); - $this->cacheScope->isEnabled()->willReturn(false); + $this->cacheScope->isInvalidating()->willReturn(false); $this->subject->invalidate($tags); diff --git a/tests/Unit/CacheActivatorTest.php b/tests/Unit/CacheActivatorTest.php index fb137eb..256cb3d 100644 --- a/tests/Unit/CacheActivatorTest.php +++ b/tests/Unit/CacheActivatorTest.php @@ -14,6 +14,14 @@ protected function setUp(): void $this->cacheActivator = new CacheActivator(); } + /** + * @test + */ + public function it_is_caching_active_by_default(): void + { + self::assertTrue($this->cacheActivator->isCachingActive()); + } + /** * @test */ diff --git a/tests/Unit/CacheScopeTest.php b/tests/Unit/CacheScopeTest.php index 5a34643..d4b43af 100644 --- a/tests/Unit/CacheScopeTest.php +++ b/tests/Unit/CacheScopeTest.php @@ -81,4 +81,50 @@ public function reset_clears_disabled_state_so_scope_can_be_enabled_again(): voi self::assertTrue($cacheScope->isEnabled()); } + + /** + * @test + */ + public function it_is_invalidating_by_default(): void + { + $cacheScope = new CacheScope(); + + self::assertTrue($cacheScope->isInvalidating()); + } + + /** + * @test + */ + public function it_is_invalidating_even_when_not_explicitly_enabled(): void + { + $cacheScope = new CacheScope(); + $cacheScope->enable(); + + self::assertTrue($cacheScope->isInvalidating()); + } + + /** + * @test + */ + public function disable_stops_invalidation(): void + { + $cacheScope = new CacheScope(); + + $cacheScope->disable(); + + self::assertFalse($cacheScope->isInvalidating()); + } + + /** + * @test + */ + public function reset_clears_disabled_state_so_invalidation_resumes(): void + { + $cacheScope = new CacheScope(); + $cacheScope->disable(); + + $cacheScope->reset(); + + self::assertTrue($cacheScope->isInvalidating()); + } } diff --git a/tests/app/src/Controller/UpdateObjectController.php b/tests/app/src/Controller/UpdateObjectController.php new file mode 100644 index 0000000..b879f3c --- /dev/null +++ b/tests/app/src/Controller/UpdateObjectController.php @@ -0,0 +1,21 @@ +query->getInt('id'))) { + return new Response('Object not found', Response::HTTP_NOT_FOUND); + } + + $object->setContent($request->request->getString('content'))->save(); + + return new Response('Object updated'); + } +} From 001d2db19d6dd6413392f880af92b715139877ee Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Mon, 31 Aug 2026 10:24:33 +0200 Subject: [PATCH 11/11] Document that CacheActivator::activateCaching() can clear a disable() reset() runs before enable() to preserve the legacy CacheActivator semantics (deactivate then reactivate always works, per the BC test), but it also clears a prior CacheScope::disable() on the same instance since "disabled" carries no information about which API set it. This can't be fixed without breaking one of the two behaviors, so it's called out instead: don't mix this deprecated API with CacheScope on the same instance. Co-Authored-By: Claude Sonnet 5 --- src/CacheActivator.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CacheActivator.php b/src/CacheActivator.php index 936d44e..0cc76f1 100644 --- a/src/CacheActivator.php +++ b/src/CacheActivator.php @@ -16,6 +16,11 @@ public function isCachingActive(): bool return $this->isInvalidating(); } + /** + * @deprecated Calls {@see CacheScope::reset()} before enabling, which also clears a prior + * {@see CacheScope::disable()} call. Do not mix this deprecated API with the {@see CacheScope} API on + * the same instance; the two do not compose safely. + */ public function activateCaching(): void { trigger_deprecation('teamneusta/pimcore-http-cache-bundle', '0.8', '"%s()" is deprecated, use "%s::enable()" instead.', __METHOD__, CacheScope::class);