diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml new file mode 100644 index 0000000..d2ff329 --- /dev/null +++ b/.github/workflows/dependencies.yml @@ -0,0 +1,35 @@ +name: Dependencies + +permissions: + contents: read + +on: + push: + branches: + - master + pull_request: + +env: + PHP_VERSION: 7.4 + +jobs: + composer-require-checker: + name: Check missing composer requirements + runs-on: ubuntu-20.04 + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.PHP_VERSION }} + tools: composer:v2 + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: vendor + key: composer-${{ runner.os }}-${{ env.PHP_VERSION }}-${{ hashFiles('composer.json') }} + restore-keys: | + composer-${{ runner.os }}-${{ env.PHP_VERSION }}- + composer-${{ runner.os }}- + - run: | + composer install --no-interaction --no-progress --ansi --no-scripts + composer show + - uses: docker://webfactory/composer-require-checker:3.2.0 diff --git a/.github/workflows/fix-cs-php.yml b/.github/workflows/fix-cs-php.yml index d6104aa..51cc369 100644 --- a/.github/workflows/fix-cs-php.yml +++ b/.github/workflows/fix-cs-php.yml @@ -1,6 +1,3 @@ -# Update this by running -# curl https://gist.githubusercontent.com/mpdude/ca93a185bcbf56eb7e341632ad4f8263/raw/fix-cs-php.yml > .github/workflows/fix-cs-php.yml - on: push: branches: @@ -13,7 +10,6 @@ jobs: open-pr-for-cs-violations: name: PHP-CS-Fixer runs-on: ubuntu-20.04 - if: github.actor != 'dependabot[bot]' steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/.github/workflows/lock-symfony-version.sh b/.github/workflows/lock-symfony-version.sh new file mode 100755 index 0000000..01405b2 --- /dev/null +++ b/.github/workflows/lock-symfony-version.sh @@ -0,0 +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 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..c856e59 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,40 @@ +name: Tests + +on: + push: + branches: + - master + pull_request: + +env: + SYMFONY_DEPRECATIONS_HELPER: weak + +jobs: + PHPUnit: + runs-on: ubuntu-20.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 } + name: PHPUnit (PHP ${{matrix.php-version}}, Symfony Version Lock ${{ matrix.symfony-locked-version }}, ${{ matrix.dependency-version }}) + steps: + - uses: actions/checkout@v2 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + tools: composer:v2 + - uses: actions/cache@v2 + with: + path: vendor + key: composer-${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.symfony-locked-version }}-${{ matrix.dependency-version }}-${{ hashFiles('composer.json') }} + restore-keys: | + composer-${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.symfony-locked-version }}-${{ matrix.dependency-version }}- + - run: VERSION=${{ matrix.symfony-locked-version }} .github/workflows/lock-symfony-version.sh + if: matrix.symfony-locked-version != 'none' + - run: composer update --${{ matrix.dependency-version }} --no-interaction --no-scripts --no-progress --ansi + - run: composer show + - run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index de5b49d..326e565 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ vendor/ .php_cs.cache +.phpunit.result.cache +composer.lock diff --git a/composer.json b/composer.json index b6fab8d..2bbfe68 100644 --- a/composer.json +++ b/composer.json @@ -1,43 +1,49 @@ { - "name": "webfactory/http-cache-bundle", - "description": "Symfony bundle to ease HTTP cache validation via last modified header", - "keywords": [ - "caching", - "http", - "304", - "notmodified", - "ifnotmodifiedsince" - ], - "license": "MIT", - "authors": [ - { - "name": "webfactory GmbH", - "email": "info@webfactory.de", - "homepage": "http://www.webfactory.de", - "role": "Developer" - } - ], + "name": "webfactory/http-cache-bundle", + "description": "Symfony bundle to ease HTTP cache validation via last modified header", + "keywords": [ + "caching", + "http", + "304", + "notmodified", + "ifnotmodifiedsince" + ], + "license": "MIT", + "authors": [ + { + "name": "webfactory GmbH", + "email": "info@webfactory.de", + "homepage": "http://www.webfactory.de", + "role": "Developer" + } + ], - "require": { - "php": "^7.1", - "symfony/config": "^2.8 || ^3.0 || ^4.0", - "symfony/dependency-injection": "^2.8 || ^3.0 || ^4.0", - "symfony/http-foundation": "^2.8 || ^3.0 || ^4.0", - "symfony/http-kernel": "^2.8 || ^3.0 || ^4.0", - "doctrine/annotations": "^1.0" - }, + "require": { + "php": "^7.1|8.0.*|8.1.*", + "symfony/config": "^4.4 | ^5.0", + "symfony/dependency-injection": "^4.4 | ^5.0", + "symfony/http-foundation": "^4.4 | ^5.0", + "symfony/http-kernel": "^4.4 | ^5.0", + "doctrine/annotations": "^1.0" + }, - "require-dev": { - "phpunit/phpunit": "^4.8.0" - }, + "require-dev": { + "phpunit/phpunit": "^8.5|^9.0", + "symfony/phpunit-bridge": ">=5.0" + }, - "suggest": { - "webfactory/wfdmeta-bundle": "Invalidate caches based on meta data tracked with wfDynamic" - }, + "suggest": { + "webfactory/wfdmeta-bundle": "Invalidate caches based on meta data tracked with wfDynamic" + }, - "autoload": { - "psr-4": { - "Webfactory\\HttpCacheBundle\\": "" + "autoload": { + "psr-4": { + "Webfactory\\HttpCacheBundle\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Webfactory\\HttpCacheBundle\\Tests\\": "tests" + } } - } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 8c665d6..b6cf515 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,7 +4,7 @@ xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"> - Tests + tests @@ -12,10 +12,10 @@ src/ - - vendor - Tests - + + + + diff --git a/DependencyInjection/WebfactoryHttpCacheExtension.php b/src/DependencyInjection/WebfactoryHttpCacheExtension.php similarity index 100% rename from DependencyInjection/WebfactoryHttpCacheExtension.php rename to src/DependencyInjection/WebfactoryHttpCacheExtension.php diff --git a/NotModified/Annotation/ReplaceWithNotModifiedResponse.php b/src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php similarity index 100% rename from NotModified/Annotation/ReplaceWithNotModifiedResponse.php rename to src/NotModified/Annotation/ReplaceWithNotModifiedResponse.php diff --git a/NotModified/EventListener.php b/src/NotModified/EventListener.php similarity index 94% rename from NotModified/EventListener.php rename to src/NotModified/EventListener.php index 5110e00..24d7ddf 100644 --- a/NotModified/EventListener.php +++ b/src/NotModified/EventListener.php @@ -14,8 +14,8 @@ use SplObjectStorage; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\FilterControllerEvent; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Webfactory\HttpCacheBundle\NotModified\Annotation\ReplaceWithNotModifiedResponse; /** @@ -58,7 +58,7 @@ public function __construct(Reader $reader, ContainerInterface $container, bool * header in the request, replace the determined controller action with a minimal action that just returns an * "empty" response with a 304 Not Modified HTTP status code. */ - public function onKernelController(FilterControllerEvent $event) + public function onKernelController(ControllerEvent $event) { $annotation = $this->findAnnotation($event->getController()); if (!$annotation) { @@ -94,7 +94,7 @@ public function onKernelController(FilterControllerEvent $event) * If a last modified date was determined for the current (master or sub) request, set it to the response so the * client can use it for the "If-Modified-Since" header in subsequent requests. */ - public function onKernelResponse(FilterResponseEvent $event) + public function onKernelResponse(ResponseEvent $event) { $request = $event->getRequest(); $response = $event->getResponse(); diff --git a/NotModified/LastModifiedDeterminator.php b/src/NotModified/LastModifiedDeterminator.php similarity index 100% rename from NotModified/LastModifiedDeterminator.php rename to src/NotModified/LastModifiedDeterminator.php diff --git a/NotModified/services.xml b/src/NotModified/services.xml similarity index 100% rename from NotModified/services.xml rename to src/NotModified/services.xml diff --git a/WebfactoryHttpCacheBundle.php b/src/WebfactoryHttpCacheBundle.php similarity index 100% rename from WebfactoryHttpCacheBundle.php rename to src/WebfactoryHttpCacheBundle.php diff --git a/Tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php b/tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php similarity index 76% rename from Tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php rename to tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php index 3053528..70ed4b3 100644 --- a/Tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php +++ b/tests/NotModified/Annotation/ReplaceWithNotModifiedResponseTest.php @@ -10,8 +10,8 @@ namespace Webfactory\HttpCacheBundle\Tests\NotModified\Annotation; use DateTime; +use PHPUnit\Framework\TestCase; use PHPUnit_Framework_MockObject_MockObject; -use PHPUnit_Framework_TestCase; use RuntimeException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -21,24 +21,24 @@ /** * Tests for the ReplaceWithNotModifiedResponse annotation. */ -final class ReplaceWithNotModifiedResponseTest extends PHPUnit_Framework_TestCase +final class ReplaceWithNotModifiedResponseTest extends TestCase { /** * @test */ public function lastModifiedDescriptionsCannotBeEmpty() { - $this->setExpectedException(RuntimeException::class); + $this->expectException(RuntimeException::class); $annotation = new ReplaceWithNotModifiedResponse(['value' => []]); $annotation->determineLastModified(new Request()); } /** * @test + * @doesNotPerformAssertions */ public function stringAsSimpleLastModifiedDescription() { - $this->setExpectedException(null); $annotation = new ReplaceWithNotModifiedResponse(['value' => [MyLastModifedDeterminator::class]]); $annotation->determineLastModified(new Request()); } @@ -49,7 +49,7 @@ public function stringAsSimpleLastModifiedDescription() public function serviceNameAsLastModifiedDescription() { /** @var ContainerInterface|PHPUnit_Framework_MockObject_MockObject $container */ - $container = $this->getMock(ContainerInterface::class); + $container = $this->createMock(ContainerInterface::class); $container->expects($this->once()) ->method('get') ->with('my.service') @@ -58,16 +58,15 @@ public function serviceNameAsLastModifiedDescription() $annotation = new ReplaceWithNotModifiedResponse(['value' => ['@my.service']]); $annotation->setContainer($container); - $this->setExpectedException(null); $annotation->determineLastModified(new Request()); } /** * @test + * @doesNotPerformAssertions */ public function arrayAslastModifiedDeterminatorDescriptionWithConstructorArguments() { - $this->setExpectedException(null); $annotation = new ReplaceWithNotModifiedResponse(['value' => [[MyLastModifedDeterminator::class => new DateTime('2000-01-01')]]]); $annotation->determineLastModified(new Request()); } @@ -77,23 +76,22 @@ public function arrayAslastModifiedDeterminatorDescriptionWithConstructorArgumen */ public function lastModifiedDeterminatorsHaveToImplementInterface() { - $this->setExpectedException(RuntimeException::class); + $this->expectException(RuntimeException::class); $annotation = new ReplaceWithNotModifiedResponse(['value' => [FakeLastModifiedDeterminatorWithoutInterface::class]]); $annotation->determineLastModified(new Request()); } /** * @test + * @group time-sensitive */ public function determineLastModifiedDeterminesLastModifiedOfOneDeterminator() { $annotation = new ReplaceWithNotModifiedResponse(['value' => [MyLastModifedDeterminator::class]]); - $this->assertEquals( - new DateTime(), - $annotation->determineLastModified(new Request()), - '', - $allowedDeltaInSeconds = 3 - ); + + $lastModified = $annotation->determineLastModified(new Request()); + + self::assertEquals(DateTime::createFromFormat('U', time()), $lastModified); } /** @@ -101,11 +99,13 @@ 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')], - ]]); + $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')], + ], + ]); $this->assertEquals(new DateTime('2003-01-01'), $annotation->determineLastModified(new Request())); } } @@ -121,7 +121,7 @@ final class MyLastModifedDeterminator implements LastModifiedDeterminator public function __construct(DateTime $lastModified = null) { - $this->lastModified = $lastModified ?: new DateTime(); + $this->lastModified = $lastModified ?: DateTime::createFromFormat('U', time()); } public function getLastModified(Request $request) diff --git a/Tests/NotModified/EventListenerTest.php b/tests/NotModified/EventListenerTest.php similarity index 62% rename from Tests/NotModified/EventListenerTest.php rename to tests/NotModified/EventListenerTest.php index f0a7a85..cf9e8ba 100644 --- a/Tests/NotModified/EventListenerTest.php +++ b/tests/NotModified/EventListenerTest.php @@ -9,23 +9,28 @@ namespace Webfactory\HttpCacheBundle\Tests\NotModified; +use Closure; use DateTime; use Doctrine\Common\Annotations\Reader; -use PHPUnit_Framework_MockObject_MockObject; -use PHPUnit_Framework_TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\FilterControllerEvent; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +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\EventListener; use Webfactory\HttpCacheBundle\NotModified\LastModifiedDeterminator; /** * Tests for the EventListener. + * + * @group time-sensitive */ -final class EventListenerTest extends PHPUnit_Framework_TestCase +final class EventListenerTest extends TestCase { /** * System under test. @@ -34,13 +39,13 @@ final class EventListenerTest extends PHPUnit_Framework_TestCase */ private $eventListener; - /** @var Reader|PHPUnit_Framework_MockObject_MockObject */ + /** @var Reader|MockObject */ private $reader; - /** @var ContainerInterface|PHPUnit_Framework_MockObject_MockObject */ + /** @var ContainerInterface|MockObject */ private $container; - /** @var FilterControllerEvent|PHPUnit_Framework_MockObject_MockObject */ + /** @var ControllerEvent|MockObject */ private $filterControllerEvent; /** @var Request */ @@ -49,87 +54,105 @@ final class EventListenerTest extends PHPUnit_Framework_TestCase /** @var Response */ private $response; + private $callable; + + /** @var KernelInterface|MockObject */ + private $kernel; + /** * @see \PHPUnit_Framework_TestCase::setUp() */ - protected function 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 = $this->getMockBuilder(FilterControllerEvent::class)->disableOriginalConstructor()->getMock(); - $this->filterControllerEvent->expects($this->any()) - ->method('getController') - ->willReturn([DummyController::class, 'action']); - $this->filterControllerEvent->expects($this->any()) - ->method('getRequest') - ->willReturn($this->request); - - $this->reader = $this->getMock(Reader::class); - $this->container = $this->getMock(ContainerInterface::class); + $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); } /** @test */ - public function onKernelControllerDoesNoHarmForMissingAnnotation() + public function onKernelControllerDoesNoHarmForMissingAnnotation(): void { - $this->expectRegularControllerResponse(); $this->setUpAnnotationReaderToReturn(null); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertRegularControllerResponse(); } /** @test */ - public function onKernelControllerDoesNoHarmForNoDeterminedLastModified() + public function onKernelControllerDoesNoHarmForNoDeterminedLastModified(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [AbstainingLastModifiedDeterminator::class]])); - $this->expectRegularControllerResponse(); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertRegularControllerResponse(); } /** @test */ - public function onKernelControllerDoesNoHarmIfNotModifiedSinceHeaderIsNotInRequest() + public function onKernelControllerDoesNoHarmIfNotModifiedSinceHeaderIsNotInRequest(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); - $this->expectRegularControllerResponse(); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertRegularControllerResponse(); } /** @test */ - public function onKernelControllerSkipsToModifiedResponseIfLastModifiedIsSmallerThanIfNotModifiedSinceHeader() + public function onKernelControllerSkipsToModifiedResponseIfLastModifiedIsSmallerThanIfNotModifiedSinceHeader(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '-1 hour'); - $this->expectNotModifiedResponse(); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertNotModifiedResponse(); } /** @test */ - public function onKernelControllerSkipsToNotModifiedResponseIfLastModifiedIsEqualToIfNotModifiedSinceHeader() + public function onKernelControllerAlwaysRunsControllerInKernelDebugMode(): void + { + $this->eventListener = new EventListener($this->reader, $this->container, true); + $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); + $this->request->headers->set('If-Modified-Since', '-1 hour'); + + $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertRegularControllerResponse(); + } + + /** @test */ + public function onKernelControllerSkipsToNotModifiedResponseIfLastModifiedIsEqualToIfNotModifiedSinceHeader(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [FixedDateAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '2000-01-01'); - $this->expectNotModifiedResponse(); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertNotModifiedResponse(); } /** @test */ - public function onKernelControllerDoesNotReplaceDeterminedControllerIfLastModifiedIsGreaterThanIfNotModifiedSinceHeader() + public function onKernelControllerDoesNotReplaceDeterminedControllerIfLastModifiedIsGreaterThanIfNotModifiedSinceHeader(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->request->headers->set('If-Modified-Since', '-2 day'); - $this->expectRegularControllerResponse(); $this->eventListener->onKernelController($this->filterControllerEvent); + + $this->assertRegularControllerResponse(); } /** * @test */ - public function onKernelResponseSetsLastModifiedHeaderToResponseIfAvailable() + public function onKernelResponseSetsLastModifiedHeaderToResponseIfAvailable(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->eventListener->onKernelController($this->filterControllerEvent); @@ -137,11 +160,11 @@ public function onKernelResponseSetsLastModifiedHeaderToResponseIfAvailable() $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); $this->eventListener->onKernelResponse($filterResponseEvent); - $this->assertNotNull($this->response->getLastModified()); + self::assertEquals(DateTime::createFromFormat('U', time() - 86400), $this->response->getLastModified()); } /** @test */ - public function onKernelResponseDoesNotSetLastModifiedHeaderToResponseIfNotAvailable() + public function onKernelResponseDoesNotSetLastModifiedHeaderToResponseIfNotAvailable(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [AbstainingLastModifiedDeterminator::class]])); $this->eventListener->onKernelController($this->filterControllerEvent); @@ -149,11 +172,11 @@ public function onKernelResponseDoesNotSetLastModifiedHeaderToResponseIfNotAvail $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); $this->eventListener->onKernelResponse($filterResponseEvent); - $this->assertNull($this->response->getLastModified()); + self::assertNull($this->response->getLastModified()); } /** @test */ - public function eventListenerDifferentiatesBetweenMultipleRequests() + public function eventListenerDifferentiatesBetweenMultipleRequests(): void { $this->setUpAnnotationReaderToReturn(new ReplaceWithNotModifiedResponse(['value' => [OneDayAgoModifiedLastModifiedDeterminator::class]])); $this->eventListener->onKernelController($this->filterControllerEvent); @@ -161,58 +184,49 @@ public function eventListenerDifferentiatesBetweenMultipleRequests() // first request - should get a last modified $filterResponseEvent = $this->createFilterResponseEvent($this->filterControllerEvent->getRequest(), $this->response); $this->eventListener->onKernelResponse($filterResponseEvent); - $this->assertNotNull($this->response->getLastModified()); + self::assertNotNull($this->response->getLastModified()); // event for another request - it's response should not get a last modified $anotherRequest = new Request(); $anotherResponse = new Response(); $anotherFilterResponseEvent = $this->createFilterResponseEvent($anotherRequest, $anotherResponse); $this->eventListener->onKernelResponse($anotherFilterResponseEvent); - $this->assertNull($anotherResponse->getLastModified()); + self::assertNull($anotherResponse->getLastModified()); } /** * @param object|null $annotation */ - private function setUpAnnotationReaderToReturn($annotation = null) + private function setUpAnnotationReaderToReturn($annotation = null): void { - $this->reader->expects($this->any()) - ->method('getMethodAnnotation') - ->willReturn($annotation); + $this->reader->method('getMethodAnnotation')->willReturn($annotation); } - private function expectRegularControllerResponse() + private function assertRegularControllerResponse(): void { - $this->filterControllerEvent->expects($this->never()) - ->method('setController'); + self::assertSame($this->callable, $this->filterControllerEvent->getController()); } - private function expectNotModifiedResponse() + private function assertNotModifiedResponse(): void { - $this->filterControllerEvent->expects($this->once()) - ->method('setController'); + $closure = $this->filterControllerEvent->getController(); + + self::assertInstanceOf(Closure::class, $closure); + + $response = $closure(); + self::assertInstanceOf(Response::class, $response); + self::assertSame(304, $response->getStatusCode()); } - /** - * @return PHPUnit_Framework_MockObject_MockObject|FilterResponseEvent - */ - private function createFilterResponseEvent(Request $request, Response $response) + private function createFilterResponseEvent(Request $request, Response $response): ResponseEvent { - $filterResponseEvent = $this->getMockBuilder(FilterResponseEvent::class)->disableOriginalConstructor()->getMock(); - $filterResponseEvent->expects($this->any()) - ->method('getRequest') - ->willReturn($request); - $filterResponseEvent->expects($this->any()) - ->method('getResponse') - ->willReturn($response); - - return $filterResponseEvent; + return new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); } } final class DummyController { - public function action() + public static function action(): Response { return new Response(); } @@ -220,7 +234,7 @@ public function action() final class AbstainingLastModifiedDeterminator implements LastModifiedDeterminator { - public function getLastModified(Request $request) + public function getLastModified(Request $request): ?DateTime { return null; } @@ -228,15 +242,15 @@ public function getLastModified(Request $request) final class OneDayAgoModifiedLastModifiedDeterminator implements LastModifiedDeterminator { - public function getLastModified(Request $request) + public function getLastModified(Request $request): DateTime { - return new DateTime('-1 day'); + return DateTime::createFromFormat('U', time() - 86400); } } final class FixedDateAgoModifiedLastModifiedDeterminator implements LastModifiedDeterminator { - public function getLastModified(Request $request) + public function getLastModified(Request $request): DateTime { return new DateTime('2000-01-01'); }