From 255f58485f202634adabb7c45b1809af8c6a9227 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Thu, 28 Mar 2024 19:29:08 +0100 Subject: [PATCH] Remove annotations support to gain Symfony 7 compatibility (#11) This removes the annotation that has been deprecated in 1.4.0. Thus, we get rid of the `doctrine/annotations` dependency and the `annotation_reader` service, clearing the path towards Symfony 7 compatibility. The PHP 8.1 minimum requirement effectively limits usage with Symfony < 5. --- .github/workflows/dependencies.yml | 29 +++---- .github/workflows/fix-cs-php.yml | 2 +- .github/workflows/lock-symfony-version.sh | 2 +- .github/workflows/tests.yml | 9 +-- README.md | 4 +- UPGRADING.md | 4 + composer.json | 15 ++-- .../WebfactoryHttpCacheExtension.php | 9 +-- .../ReplaceWithNotModifiedResponse.php | 33 -------- .../ReplaceWithNotModifiedResponse.php | 4 +- src/NotModified/EventListener.php | 32 ++------ src/NotModified/services.xml | 1 - src/WebfactoryHttpCacheBundle.php | 3 - .../ReplaceWithNotModifiedResponseTest.php | 48 ++++++----- tests/NotModified/EventListenerTest.php | 81 +++++++++---------- 15 files changed, 104 insertions(+), 172 deletions(-) delete mode 100644 src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php rename tests/NotModified/{Annotation => Attribute}/ReplaceWithNotModifiedResponseTest.php (55%) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 33ea837..dfd6bdf 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -1,8 +1,5 @@ name: Dependencies -permissions: - contents: read - on: push: branches: @@ -10,27 +7,31 @@ on: pull_request: env: - PHP_VERSION: 7.4 + PHP_VERSION: 8.1 jobs: composer-require-checker: name: Check missing composer requirements - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: shivammathur/setup-php@v2 + - uses: actions/checkout@v3 + - name: Konfiguriere PHP-Version und -Einstellungen im Worker-Node + uses: shivammathur/setup-php@v2 with: php-version: ${{ env.PHP_VERSION }} coverage: none tools: composer:v2 - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + ini-values: variables_order=EGPCS, date.timezone=Europe/Berlin + - name: Cache Composer Dependencies + uses: actions/cache@v1 with: - path: vendor - key: composer-${{ runner.os }}-${{ env.PHP_VERSION }}-${{ hashFiles('composer.json') }} + path: vendor/ + key: composer-${{ env.PHP_VERSION }}-${{ hashFiles('composer.*') }} restore-keys: | - composer-${{ runner.os }}-${{ env.PHP_VERSION }}- - composer-${{ runner.os }}- + composer-${{ env.PHP_VERSION }}-${{ github.ref }} + composer-${{ env.PHP_VERSION }}- - run: | - composer install --no-interaction --no-progress --ansi --no-scripts + composer install --no-interaction --no-scripts --no-progress --no-suggest composer show - - uses: docker://webfactory/composer-require-checker:3.2.0 + - name: ComposerRequireChecker + uses: docker://ghcr.io/webfactory/composer-require-checker:4.8.0 diff --git a/.github/workflows/fix-cs-php.yml b/.github/workflows/fix-cs-php.yml index 00b8eee..9aad709 100644 --- a/.github/workflows/fix-cs-php.yml +++ b/.github/workflows/fix-cs-php.yml @@ -9,7 +9,7 @@ name: Coding Standards jobs: open-pr-for-cs-violations: name: PHP-CS-Fixer - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v3 diff --git a/.github/workflows/lock-symfony-version.sh b/.github/workflows/lock-symfony-version.sh index 01405b2..64bf1c2 100755 --- a/.github/workflows/lock-symfony-version.sh +++ b/.github/workflows/lock-symfony-version.sh @@ -1,3 +1,3 @@ #!/bin/bash -cat <<< $(jq --arg version $VERSION '.require |= with_entries(if ((.key|test("^symfony/"))) then .value=$version else . end)' < composer.json) > composer.json +cat <<< $(jq --arg version $VERSION '.require |= with_entries(if ((.key|test("^symfony/deprecation-contracts")|not) and (.key|test("^symfony/"))) then .value=$version else . end)' < composer.json) > composer.json diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2536336..5ccbb18 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,15 +11,14 @@ env: jobs: PHPUnit: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - - { php-version: 7.2, symfony-locked-version: none, dependency-version: prefer-lowest } - - { php-version: 7.4, symfony-locked-version: none, dependency-version: prefer-lowest } - - { php-version: 7.4, symfony-locked-version: none, dependency-version: prefer-stable } - - { php-version: 8.1, symfony-locked-version: none, dependency-version: prefer-stable } + - { php-version: 8.1, symfony-locked-version: none, dependency-version: prefer-lowest } + - { php-version: 8.2, symfony-locked-version: 6.4.*, dependency-version: prefer-stable } + - { php-version: 8.3, symfony-locked-version: none, dependency-version: prefer-stable } name: PHPUnit (PHP ${{matrix.php-version}}, Symfony Version Lock ${{ matrix.symfony-locked-version }}, ${{ matrix.dependency-version }}) steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index d98297d..dd0a295 100644 --- a/README.md +++ b/README.md @@ -144,11 +144,11 @@ services: - @repository_post ` -and note the service name to the Annotation: +and put the service name into the attribute: #[ReplaceWithNotModifiedResponse(["@app_caching_latest_posts"])] -To combine multiple LastModifiedDeterminators, simply add all of them to the annotation: +To combine multiple LastModifiedDeterminators, simply add all of them to the attribute: #[ReplaceWithNotModifiedResponse([ "@app_caching_latest_posts", diff --git a/UPGRADING.md b/UPGRADING.md index e0eb4c3..de2ee2e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,9 @@ # Upgrade notes for `WebfactoryHttpCacheBundle` +## Version 2.0.0 + +* Annotations support and the `\Webfactory\HttpCacheBundle\NotModified\Annotation\ReplaceWithNotModifiedResponse` class have been removed. + ## Version 1.4.0 * The `\Webfactory\HttpCacheBundle\NotModified\Annotation\ReplaceWithNotModifiedResponse` annotation has been deprecated. Use the diff --git a/composer.json b/composer.json index 40dc77d..34e09a6 100644 --- a/composer.json +++ b/composer.json @@ -19,18 +19,17 @@ ], "require": { - "php": "^7.1|8.0.*|8.1.*", - "doctrine/annotations": "^1.0", - "symfony/config": "^4.4 | ^5.0 | ^6.0", - "symfony/dependency-injection": "^4.4 | ^5.0 | ^6.0", + "php": "^8.1", + "symfony/config": "^5.0 | ^6.0 | ^7.0", + "symfony/dependency-injection": "^5.0 | ^6.0 | ^7.0", "symfony/deprecation-contracts": "^2.0|^3.0", - "symfony/http-foundation": "^4.4 | ^5.0 | ^6.0", - "symfony/http-kernel": "^4.4 | ^5.0 | ^6.0" + "symfony/http-foundation": "^5.0 | ^6.0 | ^7.0", + "symfony/http-kernel": "^5.3 | ^6.0 | ^7.0" }, "require-dev": { - "phpunit/phpunit": "^8.5|^9.0", - "symfony/phpunit-bridge": "^5.0 | ^6.0" + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.0 | ^7.0" }, "suggest": { diff --git a/src/DependencyInjection/WebfactoryHttpCacheExtension.php b/src/DependencyInjection/WebfactoryHttpCacheExtension.php index ab2bcbd..04a3b65 100644 --- a/src/DependencyInjection/WebfactoryHttpCacheExtension.php +++ b/src/DependencyInjection/WebfactoryHttpCacheExtension.php @@ -7,15 +7,12 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\HttpKernel\DependencyInjection\Extension; -/** - * Symfony Bundle Extension class. - */ class WebfactoryHttpCacheExtension extends Extension { - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $locator = new FileLocator(__DIR__.'/../NotModified'); - $yamlLoader = new XmlFileLoader($container, $locator); - $yamlLoader->load('services.xml'); + $loader = new XmlFileLoader($container, $locator); + $loader->load('services.xml'); } } diff --git a/src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php b/src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php deleted file mode 100644 index 0cd1f3a..0000000 --- a/src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Webfactory\HttpCacheBundle\NotModified\Annotation; - -use Webfactory\HttpCacheBundle\NotModified\Attribute; - -/** - * @Annotation - * - * @deprecated, to be replaced by attribute-based configuration - */ -final class ReplaceWithNotModifiedResponse extends Attribute\ReplaceWithNotModifiedResponse -{ - public function __construct(array $parameters) - { - trigger_deprecation( - 'webfactory/http-cache-bundle', - '1.4.0', - 'The %s annotation has been deprecated, use the %s attribute instead.', - __CLASS__, - Attribute\ReplaceWithNotModifiedResponse::class - ); - - parent::__construct($parameters['value']); - } -} diff --git a/src/NotModified/Attribute/ReplaceWithNotModifiedResponse.php b/src/NotModified/Attribute/ReplaceWithNotModifiedResponse.php index c1fa370..2767abc 100644 --- a/src/NotModified/Attribute/ReplaceWithNotModifiedResponse.php +++ b/src/NotModified/Attribute/ReplaceWithNotModifiedResponse.php @@ -20,11 +20,9 @@ * This attribute determines the latest last modified date over all of its LastModifiedDeterminators. This date is used * by the \Webfactory\HttpCacheBundle\NotModified\EventListener to possibly replace the execution of a controller with * sending a Not Modified HTTP response. - * - * @final */ #[Attribute(Attribute::TARGET_METHOD)] -class ReplaceWithNotModifiedResponse +final class ReplaceWithNotModifiedResponse { /** @var array */ private $parameters; diff --git a/src/NotModified/EventListener.php b/src/NotModified/EventListener.php index f6f63e5..6d41933 100644 --- a/src/NotModified/EventListener.php +++ b/src/NotModified/EventListener.php @@ -9,14 +9,13 @@ namespace Webfactory\HttpCacheBundle\NotModified; -use Doctrine\Common\Annotations\Reader; use ReflectionMethod; use SplObjectStorage; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ControllerEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Webfactory\HttpCacheBundle\NotModified; +use Webfactory\HttpCacheBundle\NotModified\Attribute\ReplaceWithNotModifiedResponse; /** * Symfony EventListener for adding a "last modified" header to the response on the one hand. On the other hand, it @@ -25,9 +24,6 @@ */ final class EventListener { - /** @var Reader */ - private $reader; - /** @var ContainerInterface */ private $container; @@ -44,9 +40,8 @@ final class EventListener */ private $debug; - public function __construct(Reader $reader, ContainerInterface $container, bool $debug = false) + public function __construct(ContainerInterface $container, bool $debug = false) { - $this->reader = $reader; $this->container = $container; $this->lastModified = new SplObjectStorage(); $this->debug = $debug; @@ -107,7 +102,7 @@ public function onKernelResponse(ResponseEvent $event) /** * @param $controllerCallable callable PHP callback pointing to the method to reflect on. * - * @return ReplaceWithNotModifiedResponse|null The annotation, if found. Null otherwise. + * @return ?ReplaceWithNotModifiedResponse The annotation, if found. Null otherwise. */ private function findAnnotation(callable $controllerCallable) { @@ -118,25 +113,8 @@ private function findAnnotation(callable $controllerCallable) [$class, $methodName] = $controllerCallable; $method = new ReflectionMethod($class, $methodName); - if (PHP_MAJOR_VERSION >= 8) { - $attributes = $method->getAttributes(NotModified\Attribute\ReplaceWithNotModifiedResponse::class); - - if ($attributes) { - return $attributes[0]->newInstance(); - } - } - - /** @var ReplaceWithNotModifiedResponse|null $annotation */ - $annotation = $this->reader->getMethodAnnotation($method, NotModified\Annotation\ReplaceWithNotModifiedResponse::class); - - if ($annotation) { - trigger_deprecation( - 'webfactory/http-cache-bundle', - '1.4.0', - 'Configuring webfactory/http-cache-bundle with annotations is deprecated, use attributes instead.' - ); - } + $attributes = $method->getAttributes(ReplaceWithNotModifiedResponse::class); - return $annotation; + return $attributes ? $attributes[0]->newInstance() : null; } } diff --git a/src/NotModified/services.xml b/src/NotModified/services.xml index d7e3454..2380789 100644 --- a/src/NotModified/services.xml +++ b/src/NotModified/services.xml @@ -5,7 +5,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - %kernel.debug% diff --git a/src/WebfactoryHttpCacheBundle.php b/src/WebfactoryHttpCacheBundle.php index 86e3abc..3291bc2 100644 --- a/src/WebfactoryHttpCacheBundle.php +++ b/src/WebfactoryHttpCacheBundle.php @@ -4,9 +4,6 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; -/** - * Symfony Bundle class. - */ class WebfactoryHttpCacheBundle extends Bundle { } diff --git a/tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php b/tests/NotModified/Attribute/ReplaceWithNotModifiedResponseTest.php similarity index 55% rename from tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php rename to tests/NotModified/Attribute/ReplaceWithNotModifiedResponseTest.php index 3276471..57f1841 100644 --- a/tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php +++ b/tests/NotModified/Attribute/ReplaceWithNotModifiedResponseTest.php @@ -7,19 +7,19 @@ * file that was distributed with this source code. */ -namespace Webfactory\HttpCacheBundle\Tests\NotModified\Annotation; +namespace Webfactory\HttpCacheBundle\Tests\NotModified\Attribute; use DateTime; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use PHPUnit_Framework_MockObject_MockObject; use RuntimeException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; -use Webfactory\HttpCacheBundle\NotModified\Annotation\ReplaceWithNotModifiedResponse; +use Webfactory\HttpCacheBundle\NotModified\Attribute\ReplaceWithNotModifiedResponse; use Webfactory\HttpCacheBundle\NotModified\LastModifiedDeterminator; /** - * Tests for the ReplaceWithNotModifiedResponse annotation. + * Tests for the ReplaceWithNotModifiedResponse attribute. */ final class ReplaceWithNotModifiedResponseTest extends TestCase { @@ -29,8 +29,8 @@ final class ReplaceWithNotModifiedResponseTest extends TestCase public function lastModifiedDescriptionsCannotBeEmpty() { $this->expectException(RuntimeException::class); - $annotation = new ReplaceWithNotModifiedResponse(['value' => []]); - $annotation->determineLastModified(new Request()); + $attribute = new ReplaceWithNotModifiedResponse([]); + $attribute->determineLastModified(new Request()); } /** @@ -40,8 +40,8 @@ public function lastModifiedDescriptionsCannotBeEmpty() */ public function stringAsSimpleLastModifiedDescription() { - $annotation = new ReplaceWithNotModifiedResponse(['value' => [MyLastModifedDeterminator::class]]); - $annotation->determineLastModified(new Request()); + $attribute = new ReplaceWithNotModifiedResponse([MyLastModifedDeterminator::class]); + $attribute->determineLastModified(new Request()); } /** @@ -49,17 +49,17 @@ public function stringAsSimpleLastModifiedDescription() */ public function serviceNameAsLastModifiedDescription() { - /** @var ContainerInterface|PHPUnit_Framework_MockObject_MockObject $container */ + /** @var ContainerInterface|MockObject $container */ $container = $this->createMock(ContainerInterface::class); $container->expects($this->once()) ->method('get') ->with('my.service') ->willReturn(new MyLastModifedDeterminator()); - $annotation = new ReplaceWithNotModifiedResponse(['value' => ['@my.service']]); - $annotation->setContainer($container); + $attribute = new ReplaceWithNotModifiedResponse(['@my.service']); + $attribute->setContainer($container); - $annotation->determineLastModified(new Request()); + $attribute->determineLastModified(new Request()); } /** @@ -69,8 +69,8 @@ public function serviceNameAsLastModifiedDescription() */ public function arrayAslastModifiedDeterminatorDescriptionWithConstructorArguments() { - $annotation = new ReplaceWithNotModifiedResponse(['value' => [[MyLastModifedDeterminator::class => new DateTime('2000-01-01')]]]); - $annotation->determineLastModified(new Request()); + $attribute = new ReplaceWithNotModifiedResponse([[MyLastModifedDeterminator::class => new DateTime('2000-01-01')]]); + $attribute->determineLastModified(new Request()); } /** @@ -79,8 +79,8 @@ public function arrayAslastModifiedDeterminatorDescriptionWithConstructorArgumen public function lastModifiedDeterminatorsHaveToImplementInterface() { $this->expectException(RuntimeException::class); - $annotation = new ReplaceWithNotModifiedResponse(['value' => [FakeLastModifiedDeterminatorWithoutInterface::class]]); - $annotation->determineLastModified(new Request()); + $attribute = new ReplaceWithNotModifiedResponse([FakeLastModifiedDeterminatorWithoutInterface::class]); + $attribute->determineLastModified(new Request()); } /** @@ -90,9 +90,9 @@ public function lastModifiedDeterminatorsHaveToImplementInterface() */ public function determineLastModifiedDeterminesLastModifiedOfOneDeterminator() { - $annotation = new ReplaceWithNotModifiedResponse(['value' => [MyLastModifedDeterminator::class]]); + $attribute = new ReplaceWithNotModifiedResponse([MyLastModifedDeterminator::class]); - $lastModified = $annotation->determineLastModified(new Request()); + $lastModified = $attribute->determineLastModified(new Request()); self::assertEquals(DateTime::createFromFormat('U', time()), $lastModified); } @@ -102,14 +102,12 @@ public function determineLastModifiedDeterminesLastModifiedOfOneDeterminator() */ public function determineLastModifiedDeterminesLastModifiedOfMultipleDeterminators() { - $annotation = new ReplaceWithNotModifiedResponse([ - 'value' => [ - [MyLastModifedDeterminator::class => new DateTime('2001-01-01')], - [MyLastModifedDeterminator::class => new DateTime('2003-01-01')], - [MyLastModifedDeterminator::class => new DateTime('2002-01-01')], - ], + $attribute = new ReplaceWithNotModifiedResponse([ + [MyLastModifedDeterminator::class => new DateTime('2001-01-01')], + [MyLastModifedDeterminator::class => new DateTime('2003-01-01')], + [MyLastModifedDeterminator::class => new DateTime('2002-01-01')], ]); - $this->assertEquals(new DateTime('2003-01-01'), $annotation->determineLastModified(new Request())); + $this->assertEquals(new DateTime('2003-01-01'), $attribute->determineLastModified(new Request())); } } diff --git a/tests/NotModified/EventListenerTest.php b/tests/NotModified/EventListenerTest.php index cf9e8ba..2ee28ca 100644 --- a/tests/NotModified/EventListenerTest.php +++ b/tests/NotModified/EventListenerTest.php @@ -11,7 +11,6 @@ use Closure; use DateTime; -use Doctrine\Common\Annotations\Reader; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -21,7 +20,7 @@ use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelInterface; -use Webfactory\HttpCacheBundle\NotModified\Annotation\ReplaceWithNotModifiedResponse; +use Webfactory\HttpCacheBundle\NotModified\Attribute\ReplaceWithNotModifiedResponse; use Webfactory\HttpCacheBundle\NotModified\EventListener; use Webfactory\HttpCacheBundle\NotModified\LastModifiedDeterminator; @@ -39,9 +38,6 @@ final class EventListenerTest extends TestCase */ private $eventListener; - /** @var Reader|MockObject */ - private $reader; - /** @var ContainerInterface|MockObject */ private $container; @@ -59,27 +55,19 @@ final class EventListenerTest extends TestCase /** @var KernelInterface|MockObject */ private $kernel; - /** - * @see \PHPUnit_Framework_TestCase::setUp() - */ protected function setUp(): void { $this->kernel = $this->createMock(KernelInterface::class); - $this->callable = [DummyController::class, 'action']; $this->request = new Request(); $this->response = new Response(); - $this->filterControllerEvent = new ControllerEvent($this->kernel, $this->callable, $this->request, HttpKernelInterface::MASTER_REQUEST); - $this->reader = $this->createMock(Reader::class); $this->container = $this->createMock(ContainerInterface::class); - $this->eventListener = new EventListener($this->reader, $this->container); + $this->eventListener = new EventListener($this->container); } /** @test */ public function onKernelControllerDoesNoHarmForMissingAnnotation(): void { - $this->setUpAnnotationReaderToReturn(null); - - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'plainAction']); $this->assertRegularControllerResponse(); } @@ -87,9 +75,7 @@ public function onKernelControllerDoesNoHarmForMissingAnnotation(): void /** @test */ public function onKernelControllerDoesNoHarmForNoDeterminedLastModified(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [AbstainingLastModifiedDeterminator::class]])); - - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'abstainingLastModifiedAction']); $this->assertRegularControllerResponse(); } @@ -97,9 +83,7 @@ public function onKernelControllerDoesNoHarmForNoDeterminedLastModified(): void /** @test */ public function onKernelControllerDoesNoHarmIfNotModifiedSinceHeaderIsNotInRequest(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); - - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); $this->assertRegularControllerResponse(); } @@ -107,10 +91,9 @@ public function onKernelControllerDoesNoHarmIfNotModifiedSinceHeaderIsNotInReque /** @test */ public function onKernelControllerSkipsToModifiedResponseIfLastModifiedIsSmallerThanIfNotModifiedSinceHeader(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '-1 hour'); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); $this->assertNotModifiedResponse(); } @@ -118,11 +101,10 @@ public function onKernelControllerSkipsToModifiedResponseIfLastModifiedIsSmaller /** @test */ public function onKernelControllerAlwaysRunsControllerInKernelDebugMode(): void { - $this->eventListener = new EventListener($this->reader, $this->container, true); - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); + $this->eventListener = new EventListener($this->container, true); $this->request->headers->set('If-Modified-Since', '-1 hour'); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); $this->assertRegularControllerResponse(); } @@ -130,10 +112,9 @@ public function onKernelControllerAlwaysRunsControllerInKernelDebugMode(): void /** @test */ public function onKernelControllerSkipsToNotModifiedResponseIfLastModifiedIsEqualToIfNotModifiedSinceHeader(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [FixedDateAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '2000-01-01'); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'fixedDateAgoModifiedLastModifiedDeterminatorAction']); $this->assertNotModifiedResponse(); } @@ -141,10 +122,9 @@ public function onKernelControllerSkipsToNotModifiedResponseIfLastModifiedIsEqua /** @test */ public function onKernelControllerDoesNotReplaceDeterminedControllerIfLastModifiedIsGreaterThanIfNotModifiedSinceHeader(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '-2 day'); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); $this->assertRegularControllerResponse(); } @@ -154,8 +134,7 @@ public function onKernelControllerDoesNotReplaceDeterminedControllerIfLastModifi */ public function onKernelResponseSetsLastModifiedHeaderToResponseIfAvailable(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); $this->eventListener->onKernelResponse($filterResponseEvent); @@ -166,8 +145,7 @@ public function onKernelResponseSetsLastModifiedHeaderToResponseIfAvailable(): v /** @test */ public function onKernelResponseDoesNotSetLastModifiedHeaderToResponseIfNotAvailable(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [AbstainingLastModifiedDeterminator::class]])); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'abstainingLastModifiedAction']); $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); $this->eventListener->onKernelResponse($filterResponseEvent); @@ -178,8 +156,7 @@ public function onKernelResponseDoesNotSetLastModifiedHeaderToResponseIfNotAvail /** @test */ public function eventListenerDifferentiatesBetweenMultipleRequests(): void { - $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); - $this->eventListener->onKernelController($this->filterControllerEvent); + $this->exerciseOnKernelController([DummyController::class, 'oneDayAgoModifiedLastModifiedAction']); // first request - should get a last modified $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); @@ -194,12 +171,12 @@ public function eventListenerDifferentiatesBetweenMultipleRequests(): void self::assertNull($anotherResponse->getLastModified()); } - /** - * @param object|null $annotation - */ - private function setUpAnnotationReaderToReturn($annotation = null): void + private function exerciseOnKernelController(array $callable): void { - $this->reader->method('getMethodAnnotation')->willReturn($annotation); + $this->callable = $callable; + $this->filterControllerEvent = new ControllerEvent($this->kernel, $this->callable, $this->request, HttpKernelInterface::MAIN_REQUEST); + + $this->eventListener->onKernelController($this->filterControllerEvent); } private function assertRegularControllerResponse(): void @@ -220,13 +197,31 @@ private function assertNotModifiedResponse(): void private function createFilterResponseEvent(Request $request, Response $response): ResponseEvent { - return new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + return new ResponseEvent($this->kernel, $request, HttpKernelInterface::MAIN_REQUEST, $response); } } final class DummyController { - public static function action(): Response + public static function plainAction(): Response + { + return new Response(); + } + + #[ReplaceWithNotModifiedResponse([AbstainingLastModifiedDeterminator::class])] + public static function abstainingLastModifiedAction(): Response + { + return new Response(); + } + + #[ReplaceWithNotModifiedResponse([OneDayAgoModifiedLastModifiedDeterminator::class])] + public static function oneDayAgoModifiedLastModifiedAction(): Response + { + return new Response(); + } + + #[ReplaceWithNotModifiedResponse([FixedDateAgoModifiedLastModifiedDeterminator::class])] + public static function fixedDateAgoModifiedLastModifiedDeterminatorAction(): Response { return new Response(); }