From 7cf9f5ea0abc4e2d7a48806c3c3372bd618a8137 Mon Sep 17 00:00:00 2001 From: Henric Nylund Date: Fri, 11 Dec 2020 09:34:31 +0100 Subject: [PATCH 1/4] feat: PHP 8 support - Test changes - Migrates tests from Prophecy to PHPUnit native mock objects - Do not use deprecated assertions (e.g. `assertInternalType()`) - Dependencies - Adds `~8.0.0` to the list of PHP constraints - Bumps the minimum supported PHP version to 7.3 - Bumps the minimum supported PHPUnit version to 9.3 - Removes conflict for prophecy (no longer used) - Travis config - Adds PHP 8.0 jobs to the Travis job matrix Signed-off-by: Henric Nylund --- .gitignore | 1 + .travis.yml | 16 +- composer.json | 7 +- phpunit.xml.dist | 21 ++- test/ConfigProviderTest.php | 9 +- test/FlashMessageMiddlewareTest.php | 78 ++++++---- test/FlashMessagesTest.php | 221 +++++++++++++++++++--------- 7 files changed, 225 insertions(+), 128 deletions(-) diff --git a/.gitignore b/.gitignore index 87904ec..46466ef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.phpunit.result.cache /clover.xml /composer.lock /coveralls-upload.json diff --git a/.travis.yml b/.travis.yml index e810782..b1b39a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,30 +6,30 @@ cache: env: global: - - COMPOSER_ARGS="--no-interaction" + - COMPOSER_ARGS="--no-interaction --ignore-platform-reqs" - COVERAGE_DEPS="php-coveralls/php-coveralls" matrix: fast_finish: true include: - - php: 7.1 + - php: 7.3 env: - DEPS=lowest - - php: 7.1 + - php: 7.3 env: - DEPS=latest - CS_CHECK=true - TEST_COVERAGE=true - - php: 7.2 + - php: 7.4 env: - DEPS=lowest - - php: 7.2 + - php: 7.4 env: - DEPS=latest - - php: 7.3 + - php: 8.0 env: - DEPS=lowest - - php: 7.3 + - php: 8.0 env: - DEPS=latest @@ -44,7 +44,7 @@ install: - stty cols 120 && composer show script: - - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then composer XDEBUG_MODE=coverage test-coverage ; else composer test ; fi - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi after_script: diff --git a/composer.json b/composer.json index 827ff13..cb7a7d9 100644 --- a/composer.json +++ b/composer.json @@ -29,17 +29,14 @@ } }, "require": { - "php": "^7.1", + "php": "^7.3 || ~8.0.0", "laminas/laminas-zendframework-bridge": "^1.0", "mezzio/mezzio-session": "^1.0", "psr/http-server-middleware": "^1.0" }, "require-dev": { "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^7.0.2" - }, - "conflict": { - "phpspec/prophecy": "<1.7.2" + "phpunit/phpunit": "^9.3" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b6d1f38..ed14e16 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,15 +3,14 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true"> - - - ./test - - - - - - ./src - - + + + ./src + + + + + ./test + + diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php index 9e1b05e..cb4b732 100644 --- a/test/ConfigProviderTest.php +++ b/test/ConfigProviderTest.php @@ -15,7 +15,10 @@ class ConfigProviderTest extends TestCase { - public function setUp() + /** @var ConfigProvider */ + private $provider; + + public function setUp(): void { $this->provider = new ConfigProvider(); } @@ -23,7 +26,7 @@ public function setUp() public function testInvocationReturnsArray() { $config = ($this->provider)(); - $this->assertInternalType('array', $config); + $this->assertIsArray($config); return $config; } @@ -33,6 +36,6 @@ public function testInvocationReturnsArray() public function testReturnedArrayContainsDependencies(array $config) { $this->assertArrayHasKey('dependencies', $config); - $this->assertInternalType('array', $config['dependencies']); + $this->assertIsArray($config['dependencies']); } } diff --git a/test/FlashMessageMiddlewareTest.php b/test/FlashMessageMiddlewareTest.php index 00f3a6d..3d35412 100644 --- a/test/FlashMessageMiddlewareTest.php +++ b/test/FlashMessageMiddlewareTest.php @@ -16,7 +16,6 @@ use Mezzio\Session\SessionInterface; use Mezzio\Session\SessionMiddleware; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -40,43 +39,64 @@ public function testConstructorRaisesExceptionIfFlashMessagesClassDoesNotImpleme public function testProcessRaisesExceptionIfRequestSessionAttributeDoesNotReturnSessionInterface() { - $request = $this->prophesize(ServerRequestInterface::class); - $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE, false)->willReturn(false); - $request->withAttribute( - FlashMessageMiddleware::FLASH_ATTRIBUTE, - Argument::type(FlashMessagesInterface::class) - )->shouldNotBeCalled(); - - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle(Argument::type(ServerRequestInterface::class))->shouldNotBeCalled(); + $request = $this->createMock(ServerRequestInterface::class); + $request + ->expects($this->once()) + ->method('getAttribute') + ->with(SessionMiddleware::SESSION_ATTRIBUTE, false) + ->willReturn(false); + $request + ->expects($this->never()) + ->method('withAttribute') + ->with( + FlashMessageMiddleware::FLASH_ATTRIBUTE, + $this->isInstanceOf(FlashMessagesInterface::class) + ); + + $handler = $this->createMock(RequestHandlerInterface::class); + $handler + ->expects($this->never()) + ->method('handle') + ->with($this->isInstanceOf(ServerRequestInterface::class)); $middleware = new FlashMessageMiddleware(); $this->expectException(Exception\MissingSessionException::class); $this->expectExceptionMessage(FlashMessageMiddleware::class); - $middleware->process($request->reveal(), $handler->reveal()); + $middleware->process($request, $handler); } public function testProcessUsesConfiguredClassAndSessionKeyAndAttributeKeyToCreateFlashMessagesAndPassToHandler() { - $session = $this->prophesize(SessionInterface::class)->reveal(); - - $request = $this->prophesize(ServerRequestInterface::class); - $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE, false)->willReturn($session); - $request->withAttribute( - 'non-standard-flash-attr', - Argument::that(function (TestAsset\FlashMessages $flash) use ($session) { - $this->assertSame($session, $flash->session); - $this->assertSame('non-standard-flash-next', $flash->sessionKey); - return $flash; - }) - )->will([$request, 'reveal']); - - $response = $this->prophesize(ResponseInterface::class)->reveal(); - - $handler = $this->prophesize(RequestHandlerInterface::class); - $handler->handle(Argument::that([$request, 'reveal']))->willReturn($response); + $session = $this->createMock(SessionInterface::class); + + $request = $this->createMock(ServerRequestInterface::class); + $request + ->expects($this->once()) + ->method('getAttribute') + ->with(SessionMiddleware::SESSION_ATTRIBUTE, false) + ->willReturn($session); + $request + ->expects($this->once()) + ->method('withAttribute') + ->with( + 'non-standard-flash-attr', + $this->callback(function (TestAsset\FlashMessages $flash) use ($session) { + $this->assertSame($session, $flash->session); + $this->assertSame('non-standard-flash-next', $flash->sessionKey); + return true; + }) + )->will($this->returnSelf()); + + $response = $this->createMock(ResponseInterface::class); + + $handler = $this->createMock(RequestHandlerInterface::class); + $handler + ->expects($this->once()) + ->method('handle') + ->with($request) + ->willReturn($response); $middleware = new FlashMessageMiddleware( TestAsset\FlashMessages::class, @@ -86,7 +106,7 @@ public function testProcessUsesConfiguredClassAndSessionKeyAndAttributeKeyToCrea $this->assertSame( $response, - $middleware->process($request->reveal(), $handler->reveal()) + $middleware->process($request, $handler) ); } } diff --git a/test/FlashMessagesTest.php b/test/FlashMessagesTest.php index 81ae495..0c53172 100644 --- a/test/FlashMessagesTest.php +++ b/test/FlashMessagesTest.php @@ -13,23 +13,34 @@ use Mezzio\Flash\FlashMessages; use Mezzio\Flash\FlashMessagesInterface; use Mezzio\Session\SessionInterface; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class FlashMessagesTest extends TestCase { - public function setUp() + /** @var SessionInterface|MockObject */ + private $session; + + public function setUp(): void { - $this->session = $this->prophesize(SessionInterface::class); + $this->session = $this->createMock(SessionInterface::class); } public function testCreationAggregatesNothingIfNoMessagesExistUnderSpecifiedSessionKey() { - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(false); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->shouldNotBeCalled(); + $this->session + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(false); + $this->session + ->expects($this->never()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); - $this->assertAttributeSame([], 'currentMessages', $flash); + $this->assertSame([], $flash->getFlashes()); } public function testCreationAggregatesItemsMarkedNextAndRemovesThemFromSession() @@ -45,11 +56,22 @@ public function testCreationAggregatesItemsMarkedNextAndRemovesThemFromSession() ], ]; - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(true); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->willReturn($messages); - $this->session->unset(FlashMessagesInterface::FLASH_NEXT)->shouldBeCalled(); + $this->session + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(true); + $this->session + ->expects($this->once()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn($messages); + $this->session + ->expects($this->once()) + ->method('unset') + ->with(FlashMessagesInterface::FLASH_NEXT); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); $this->assertSame('value1', $flash->getFlash('test')); @@ -73,16 +95,25 @@ public function testCreationAggregatesPersistsItemsWithMultipleHopsInSessionWith $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(true); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->willReturn($messages); $this->session - ->set( + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(true); + $this->session + ->expects($this->once()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn($messages); + $this->session + ->expects($this->once()) + ->method('set') + ->with( FlashMessagesInterface::FLASH_NEXT, $messagesExpected - ) - ->shouldBeCalled(); + ); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); $this->assertSame('value1', $flash->getFlash('test')); @@ -92,11 +123,20 @@ public function testCreationAggregatesPersistsItemsWithMultipleHopsInSessionWith public function testFlashingAValueMakesItAvailableInNextSessionButNotFlashMessages() { - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(false); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->shouldNotBeCalled(); - $this->session->get(FlashMessagesInterface::FLASH_NEXT, [])->willReturn([]); $this->session - ->set( + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(false); + $this->session + ->expects($this->once()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT, []) + ->willReturn([]); + $this->session + ->expects($this->once()) + ->method('set') + ->with( FlashMessagesInterface::FLASH_NEXT, [ 'test' => [ @@ -104,10 +144,9 @@ public function testFlashingAValueMakesItAvailableInNextSessionButNotFlashMessag 'hops' => 1, ], ] - ) - ->shouldBeCalled(); + ); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $flash->flash('test', 'value'); $this->assertNull($flash->getFlash('test')); @@ -116,11 +155,20 @@ public function testFlashingAValueMakesItAvailableInNextSessionButNotFlashMessag public function testFlashNowMakesValueAvailableBothInNextSessionAndCurrentFlashMessages() { - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(false); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->shouldNotBeCalled(); - $this->session->get(FlashMessagesInterface::FLASH_NEXT, [])->willReturn([]); $this->session - ->set( + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(false); + $this->session + ->expects($this->once()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT, []) + ->willReturn([]); + $this->session + ->expects($this->once()) + ->method('set') + ->with( FlashMessagesInterface::FLASH_NEXT, [ 'test' => [ @@ -128,10 +176,9 @@ public function testFlashNowMakesValueAvailableBothInNextSessionAndCurrentFlashM 'hops' => 1, ], ] - ) - ->shouldBeCalled(); + ); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $flash->flashNow('test', 'value'); $this->assertSame('value', $flash->getFlash('test')); @@ -151,36 +198,47 @@ public function testProlongFlashAddsCurrentMessagesToNextSession() ], ]; - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(true); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->willReturn($messages); - $this->session->unset(FlashMessagesInterface::FLASH_NEXT)->shouldBeCalled(); - - $this->session->get(FlashMessagesInterface::FLASH_NEXT, [])->willReturn([]); - $this->session - ->set( - FlashMessagesInterface::FLASH_NEXT, - [ - 'test' => [ - 'value' => 'value1', - 'hops' => 1, - ], - ] + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(true); + $this->session + ->method('get') + ->withConsecutive( + [FlashMessagesInterface::FLASH_NEXT], + [FlashMessagesInterface::FLASH_NEXT, []] ) - ->shouldBeCalled(); + ->willReturnOnConsecutiveCalls($messages, []); $this->session - ->set( - FlashMessagesInterface::FLASH_NEXT, + ->expects($this->once()) + ->method('unset') + ->with(FlashMessagesInterface::FLASH_NEXT); + + $this->session + ->method('set') + ->withConsecutive( [ - 'test-2' => [ - 'value' => 'value2', - 'hops' => 1, - ], + FlashMessagesInterface::FLASH_NEXT, + [ + 'test' => [ + 'value' => 'value1', + 'hops' => 1, + ], + ] + ], + [ + FlashMessagesInterface::FLASH_NEXT, + [ + 'test-2' => [ + 'value' => 'value2', + 'hops' => 1, + ], + ] ] - ) - ->shouldBeCalled(); + ); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); $this->assertSame('value1', $flash->getFlash('test')); @@ -206,21 +264,28 @@ public function testProlongFlashDoesNotReFlashMessagesThatAlreadyHaveMoreHops() $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(true); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->willReturn($messages); $this->session - ->set( - FlashMessagesInterface::FLASH_NEXT, - $messagesExpected + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(true); + $this->session + ->expects($this->atMost(2)) + ->method('get') + ->withConsecutive( + [FlashMessagesInterface::FLASH_NEXT], + [FlashMessagesInterface::FLASH_NEXT, []] ) - ->shouldBeCalledTimes(1); - + ->willReturnOnConsecutiveCalls($messages, $messagesExpected); $this->session - ->get(FlashMessagesInterface::FLASH_NEXT, []) - ->willReturn($messagesExpected) - ->shouldBeCalledTimes(1); + ->expects($this->once()) + ->method('set') + ->with( + FlashMessagesInterface::FLASH_NEXT, + $messagesExpected + ); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); $this->assertSame('value1', $flash->getFlash('test')); @@ -246,17 +311,29 @@ public function testClearFlashShouldRemoveAnyUnexpiredMessages() $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; - $this->session->has(FlashMessagesInterface::FLASH_NEXT)->willReturn(true); - $this->session->get(FlashMessagesInterface::FLASH_NEXT)->willReturn($messages); $this->session - ->set( + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(true); + $this->session + ->expects($this->once()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn($messages); + $this->session + ->expects($this->once()) + ->method('set') + ->with( FlashMessagesInterface::FLASH_NEXT, $messagesExpected - ) - ->shouldBeCalled(); - $this->session->unset(FlashMessagesInterface::FLASH_NEXT)->shouldBeCalled(); + ); + $this->session + ->expects($this->once()) + ->method('unset') + ->with(FlashMessagesInterface::FLASH_NEXT); - $flash = FlashMessages::createFromSession($this->session->reveal()); + $flash = FlashMessages::createFromSession($this->session); $this->assertInstanceOf(FlashMessages::class, $flash); $this->assertSame('value1', $flash->getFlash('test')); From 96e3afe20a1a23ef4faf5a26a34bb8b5ff0d2ef3 Mon Sep 17 00:00:00 2001 From: Henric Nylund Date: Fri, 11 Dec 2020 23:03:57 +0100 Subject: [PATCH 2/4] qa: bump laminas-coding-standard to 2.1 Applies fixes based on phpcbf and phpcs. Signed-off-by: Henric Nylund --- .gitignore | 1 + composer.json | 2 +- phpcs.xml | 16 ++++++++-- src/ConfigProvider.php | 6 ++-- ...idFlashMessagesImplementationException.php | 2 +- src/Exception/InvalidHopsValueException.php | 2 +- src/Exception/MissingSessionException.php | 2 +- src/FlashMessageMiddleware.php | 21 +++++------- src/FlashMessages.php | 32 ++++++++----------- src/FlashMessagesInterface.php | 12 +++---- test/ConfigProviderTest.php | 2 +- test/FlashMessagesTest.php | 32 +++++++++---------- test/TestAsset/FlashMessages.php | 26 +++++++++++---- 13 files changed, 85 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 46466ef..30e934c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.phpcs-cache /.phpunit.result.cache /clover.xml /composer.lock diff --git a/composer.json b/composer.json index cb7a7d9..cdd96e4 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "psr/http-server-middleware": "^1.0" }, "require-dev": { - "laminas/laminas-coding-standard": "~1.0.0", + "laminas/laminas-coding-standard": "~2.1.0", "phpunit/phpunit": "^9.3" }, "autoload": { diff --git a/phpcs.xml b/phpcs.xml index 4da1eed..1efe663 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,8 +1,20 @@ - - + + + + + + + + + + src test + + + diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 6c51d7a..f8a2651 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -12,18 +12,18 @@ class ConfigProvider { - public function __invoke() : array + public function __invoke(): array { return [ 'dependencies' => $this->getDependencies(), ]; } - public function getDependencies() : array + public function getDependencies(): array { return [ // Legacy Zend Framework aliases - 'aliases' => [ + 'aliases' => [ \Zend\Expressive\Flash\FlashMessageMiddleware::class => FlashMessageMiddleware::class, ], 'invokables' => [ diff --git a/src/Exception/InvalidFlashMessagesImplementationException.php b/src/Exception/InvalidFlashMessagesImplementationException.php index 37400ee..0882e63 100644 --- a/src/Exception/InvalidFlashMessagesImplementationException.php +++ b/src/Exception/InvalidFlashMessagesImplementationException.php @@ -18,7 +18,7 @@ class InvalidFlashMessagesImplementationException extends InvalidArgumentException implements ExceptionInterface { - public static function forClass(string $class) : self + public static function forClass(string $class): self { return new self(sprintf( 'Cannot use "%s" within %s; does not implement %s', diff --git a/src/Exception/InvalidHopsValueException.php b/src/Exception/InvalidHopsValueException.php index a317a69..77d64a6 100644 --- a/src/Exception/InvalidHopsValueException.php +++ b/src/Exception/InvalidHopsValueException.php @@ -16,7 +16,7 @@ class InvalidHopsValueException extends InvalidArgumentException implements ExceptionInterface { - public static function valueTooLow(string $key, int $hops) : self + public static function valueTooLow(string $key, int $hops): self { return new self(sprintf( 'Hops value specified for flash message "%s" was too low; must be greater than 0, received %d', diff --git a/src/Exception/MissingSessionException.php b/src/Exception/MissingSessionException.php index 924f6d5..41d75cd 100644 --- a/src/Exception/MissingSessionException.php +++ b/src/Exception/MissingSessionException.php @@ -18,7 +18,7 @@ class MissingSessionException extends RuntimeException implements ExceptionInterface { - public static function forMiddleware(MiddlewareInterface $middleware) + public static function forMiddleware(MiddlewareInterface $middleware): MissingSessionException { return new self(sprintf( 'Unable to create flash messages in %s; missing session attribute', diff --git a/src/FlashMessageMiddleware.php b/src/FlashMessageMiddleware.php index b11ed76..62fafd0 100644 --- a/src/FlashMessageMiddleware.php +++ b/src/FlashMessageMiddleware.php @@ -25,19 +25,13 @@ class FlashMessageMiddleware implements MiddlewareInterface { public const FLASH_ATTRIBUTE = 'flash'; - /** - * @var string - */ + /** @var string */ private $attributeKey; - /** - * @var callable - */ + /** @var callable */ private $flashMessageFactory; - /** - * @var string - */ + /** @var string */ private $sessionKey; public function __construct( @@ -45,18 +39,19 @@ public function __construct( string $sessionKey = FlashMessagesInterface::FLASH_NEXT, string $attributeKey = self::FLASH_ATTRIBUTE ) { - if (! class_exists($flashMessagesClass) + if ( + ! class_exists($flashMessagesClass) || ! in_array(FlashMessagesInterface::class, class_implements($flashMessagesClass), true) ) { throw Exception\InvalidFlashMessagesImplementationException::forClass($flashMessagesClass); } $this->flashMessageFactory = [$flashMessagesClass, 'createFromSession']; - $this->sessionKey = $sessionKey; - $this->attributeKey = $attributeKey; + $this->sessionKey = $sessionKey; + $this->attributeKey = $attributeKey; } - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE, false); if (! $session instanceof SessionInterface) { diff --git a/src/FlashMessages.php b/src/FlashMessages.php index 9ecf1ab..c2d65ec 100644 --- a/src/FlashMessages.php +++ b/src/FlashMessages.php @@ -35,24 +35,18 @@ */ class FlashMessages implements FlashMessagesInterface { - /** - * @var array - */ + /** @var array */ private $currentMessages = []; - /** - * @var SessionInterface - */ + /** @var SessionInterface */ private $session; - /** - * @var string - */ + /** @var string */ private $sessionKey; private function __construct(SessionInterface $session, string $sessionKey) { - $this->session = $session; + $this->session = $session; $this->sessionKey = $sessionKey; $this->prepareMessages($session, $sessionKey); } @@ -63,7 +57,7 @@ private function __construct(SessionInterface $session, string $sessionKey) public static function createFromSession( SessionInterface $session, string $sessionKey = FlashMessagesInterface::FLASH_NEXT - ) : FlashMessagesInterface { + ): FlashMessagesInterface { return new self($session, $sessionKey); } @@ -77,13 +71,13 @@ public static function createFromSession( * @param mixed $value * @throws Exception\InvalidHopsValueException */ - public function flash(string $key, $value, int $hops = 1) : void + public function flash(string $key, $value, int $hops = 1): void { if ($hops < 1) { throw Exception\InvalidHopsValueException::valueTooLow($key, $hops); } - $messages = $this->session->get($this->sessionKey, []); + $messages = $this->session->get($this->sessionKey, []); $messages[$key] = [ 'value' => $value, 'hops' => $hops, @@ -100,7 +94,7 @@ public function flash(string $key, $value, int $hops = 1) : void * * @param mixed $value */ - public function flashNow(string $key, $value, int $hops = 1) : void + public function flashNow(string $key, $value, int $hops = 1): void { $this->currentMessages[$key] = $value; $this->flash($key, $value, $hops); @@ -132,7 +126,7 @@ public function getFlash(string $key, $default = null) * * @return array */ - public function getFlashes() : array + public function getFlashes(): array { return $this->currentMessages; } @@ -142,7 +136,7 @@ public function getFlashes() : array * * Affects the next and subsequent requests. */ - public function clearFlash() : void + public function clearFlash(): void { $this->session->unset($this->sessionKey); } @@ -150,7 +144,7 @@ public function clearFlash() : void /** * Prolongs any current flash messages for one more hop. */ - public function prolongFlash() : void + public function prolongFlash(): void { $messages = $this->session->get($this->sessionKey, []); foreach ($this->currentMessages as $key => $value) { @@ -162,7 +156,7 @@ public function prolongFlash() : void } } - public function prepareMessages(SessionInterface $session, string $sessionKey) : void + public function prepareMessages(SessionInterface $session, string $sessionKey): void { if (! $session->has($sessionKey)) { return; @@ -180,7 +174,7 @@ public function prepareMessages(SessionInterface $session, string $sessionKey) : continue; } - $data['hops'] -= 1; + $data['hops'] -= 1; $sessionMessages[$key] = $data; } diff --git a/src/FlashMessagesInterface.php b/src/FlashMessagesInterface.php index 00e55b8..dfc1ceb 100644 --- a/src/FlashMessagesInterface.php +++ b/src/FlashMessagesInterface.php @@ -28,7 +28,7 @@ interface FlashMessagesInterface public static function createFromSession( SessionInterface $session, string $sessionKey = self::FLASH_NEXT - ) : FlashMessagesInterface; + ): FlashMessagesInterface; /** * Set a flash value with the given key. @@ -39,7 +39,7 @@ public static function createFromSession( * * @param mixed $value */ - public function flash(string $key, $value, int $hops = 1) : void; + public function flash(string $key, $value, int $hops = 1): void; /** * Set a flash value with the given key, but allow access during this request. @@ -50,7 +50,7 @@ public function flash(string $key, $value, int $hops = 1) : void; * * @param mixed $value */ - public function flashNow(string $key, $value, int $hops = 1) : void; + public function flashNow(string $key, $value, int $hops = 1): void; /** * Retrieve a flash value. @@ -75,17 +75,17 @@ public function getFlash(string $key, $default = null); * * @return array */ - public function getFlashes() : array; + public function getFlashes(): array; /** * Clear all flash values. * * Affects the next and subsequent requests. */ - public function clearFlash() : void; + public function clearFlash(): void; /** * Prolongs any current flash messages for one more hop. */ - public function prolongFlash() : void; + public function prolongFlash(): void; } diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php index cb4b732..dbbdae5 100644 --- a/test/ConfigProviderTest.php +++ b/test/ConfigProviderTest.php @@ -23,7 +23,7 @@ public function setUp(): void $this->provider = new ConfigProvider(); } - public function testInvocationReturnsArray() + public function testInvocationReturnsArray(): array { $config = ($this->provider)(); $this->assertIsArray($config); diff --git a/test/FlashMessagesTest.php b/test/FlashMessagesTest.php index 0c53172..d04e489 100644 --- a/test/FlashMessagesTest.php +++ b/test/FlashMessagesTest.php @@ -46,7 +46,7 @@ public function testCreationAggregatesNothingIfNoMessagesExistUnderSpecifiedSess public function testCreationAggregatesItemsMarkedNextAndRemovesThemFromSession() { $messages = [ - 'test' => [ + 'test' => [ 'hops' => 1, 'value' => 'value1', ], @@ -81,8 +81,8 @@ public function testCreationAggregatesItemsMarkedNextAndRemovesThemFromSession() public function testCreationAggregatesPersistsItemsWithMultipleHopsInSessionWithDecrementedHops() { - $messages = [ - 'test' => [ + $messages = [ + 'test' => [ 'hops' => 3, 'value' => 'value1', ], @@ -91,8 +91,8 @@ public function testCreationAggregatesPersistsItemsWithMultipleHopsInSessionWith 'value' => 'value2', ], ]; - $messagesExpected = $messages; - $messagesExpected['test']['hops'] = 2; + $messagesExpected = $messages; + $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; $this->session @@ -188,7 +188,7 @@ public function testFlashNowMakesValueAvailableBothInNextSessionAndCurrentFlashM public function testProlongFlashAddsCurrentMessagesToNextSession() { $messages = [ - 'test' => [ + 'test' => [ 'hops' => 1, 'value' => 'value1', ], @@ -225,7 +225,7 @@ public function testProlongFlashAddsCurrentMessagesToNextSession() 'value' => 'value1', 'hops' => 1, ], - ] + ], ], [ FlashMessagesInterface::FLASH_NEXT, @@ -234,7 +234,7 @@ public function testProlongFlashAddsCurrentMessagesToNextSession() 'value' => 'value2', 'hops' => 1, ], - ] + ], ] ); @@ -250,8 +250,8 @@ public function testProlongFlashAddsCurrentMessagesToNextSession() public function testProlongFlashDoesNotReFlashMessagesThatAlreadyHaveMoreHops() { - $messages = [ - 'test' => [ + $messages = [ + 'test' => [ 'hops' => 3, 'value' => 'value1', ], @@ -260,8 +260,8 @@ public function testProlongFlashDoesNotReFlashMessagesThatAlreadyHaveMoreHops() 'value' => 'value2', ], ]; - $messagesExpected = $messages; - $messagesExpected['test']['hops'] = 2; + $messagesExpected = $messages; + $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; $this->session @@ -297,8 +297,8 @@ public function testProlongFlashDoesNotReFlashMessagesThatAlreadyHaveMoreHops() public function testClearFlashShouldRemoveAnyUnexpiredMessages() { - $messages = [ - 'test' => [ + $messages = [ + 'test' => [ 'hops' => 3, 'value' => 'value1', ], @@ -307,8 +307,8 @@ public function testClearFlashShouldRemoveAnyUnexpiredMessages() 'value' => 'value2', ], ]; - $messagesExpected = $messages; - $messagesExpected['test']['hops'] = 2; + $messagesExpected = $messages; + $messagesExpected['test']['hops'] = 2; $messagesExpected['test-2']['hops'] = 1; $this->session diff --git a/test/TestAsset/FlashMessages.php b/test/TestAsset/FlashMessages.php index 0205524..292d9f5 100644 --- a/test/TestAsset/FlashMessages.php +++ b/test/TestAsset/FlashMessages.php @@ -15,44 +15,56 @@ class FlashMessages implements FlashMessagesInterface { + /** @var SessionInterface */ public $session; + /** @var string */ public $sessionKey; public function __construct(SessionInterface $session, string $sessionKey) { - $this->session = $session; + $this->session = $session; $this->sessionKey = $sessionKey; } public static function createFromSession( SessionInterface $session, string $sessionKey = 'this-should-not-be-used' - ) : FlashMessagesInterface { + ): FlashMessagesInterface { return new self($session, $sessionKey); } - public function flash(string $key, $value, int $hops = 1) : void + /** + * @param mixed $value + */ + public function flash(string $key, $value, int $hops = 1): void { } - public function flashNow(string $key, $value, int $hops = 1) : void + /** + * @param mixed $value + */ + public function flashNow(string $key, $value, int $hops = 1): void { } + /** + * @param null $default + * @return mixed|void + */ public function getFlash(string $key, $default = null) { } - public function getFlashes() : array + public function getFlashes(): array { return []; } - public function clearFlash() : void + public function clearFlash(): void { } - public function prolongFlash() : void + public function prolongFlash(): void { } } From e418860f8d12da883479588915b11a9a7e8c36cb Mon Sep 17 00:00:00 2001 From: Henric Nylund Date: Sat, 12 Dec 2020 02:22:37 +0100 Subject: [PATCH 3/4] qa: supplementary test - Add a test to assert that InvalidHopsValueException is thrown if 0 hops is passed to flash(). Obvious fix. Signed-off-by: Henric Nylund --- test/FlashMessagesTest.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/FlashMessagesTest.php b/test/FlashMessagesTest.php index d04e489..530f9bc 100644 --- a/test/FlashMessagesTest.php +++ b/test/FlashMessagesTest.php @@ -10,6 +10,7 @@ namespace MezzioTest\Flash; +use Mezzio\Flash\Exception\InvalidHopsValueException; use Mezzio\Flash\FlashMessages; use Mezzio\Flash\FlashMessagesInterface; use Mezzio\Session\SessionInterface; @@ -341,4 +342,30 @@ public function testClearFlashShouldRemoveAnyUnexpiredMessages() $this->assertSame(['test' => 'value1', 'test-2' => 'value2'], $flash->getFlashes()); $flash->clearFlash(); } + + public function testCreationAggregatesThrowsExceptionIfInvalidNumberOfHops() + { + $this->expectException(InvalidHopsValueException::class); + + $this->session + ->expects($this->once()) + ->method('has') + ->with(FlashMessagesInterface::FLASH_NEXT) + ->willReturn(false); + $this->session + ->expects($this->never()) + ->method('get') + ->with(FlashMessagesInterface::FLASH_NEXT, []) + ->willReturn([]); + $this->session + ->expects($this->never()) + ->method('set') + ->with( + $this->anything(), + $this->anything() + ); + + $flash = FlashMessages::createFromSession($this->session); + $flash->flashNow('test', 'value', 0); + } } From 0322ee9f7e06807eb82ac41053dff17e6e04f390 Mon Sep 17 00:00:00 2001 From: Henric Nylund Date: Sat, 12 Dec 2020 02:35:57 +0100 Subject: [PATCH 4/4] fix: argument order for coverage in CI file Signed-off-by: Henric Nylund --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1b39a9..863f0ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ cache: env: global: - - COMPOSER_ARGS="--no-interaction --ignore-platform-reqs" + - COMPOSER_ARGS="--no-interaction" - COVERAGE_DEPS="php-coveralls/php-coveralls" matrix: @@ -29,9 +29,11 @@ matrix: - php: 8.0 env: - DEPS=lowest + - COMPOSER_ARGS="--no-interaction --ignore-platform-reqs" - php: 8.0 env: - DEPS=latest + - COMPOSER_ARGS="--no-interaction --ignore-platform-reqs" before_install: - if [[ $TEST_COVERAGE != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi @@ -44,7 +46,7 @@ install: - stty cols 120 && composer show script: - - if [[ $TEST_COVERAGE == 'true' ]]; then composer XDEBUG_MODE=coverage test-coverage ; else composer test ; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then XDEBUG_MODE=coverage composer test-coverage ; else composer test ; fi - if [[ $CS_CHECK == 'true' ]]; then composer cs-check ; fi after_script: