From 5009cb3083b69edfc52bd438f677903bac62f64e Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Wed, 12 Feb 2020 22:13:29 +0100 Subject: [PATCH 1/9] Update branch-related urls in Readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4e2773f..7421b3c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # [![PGS Software](https://www.pgs-soft.com/pgssoft-logo.png)](https://www.pgs-soft.com) / HashId ![PHP from Packagist](https://img.shields.io/packagist/php-v/symfony/symfony.svg) -[![Build Status](https://travis-ci.org/kjonski/HashId.svg?branch=dev-master)](https://travis-ci.org/kjonski/HashId) -[![Code Coverage](https://scrutinizer-ci.com/g/kjonski/HashId/badges/coverage.png?b=dev-master)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=dev-master) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/kjonski/HashId/badges/quality-score.png?b=dev-master)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=dev-master) +[![Build Status](https://travis-ci.org/kjonski/HashId.svg?branch=2.0)](https://travis-ci.org/kjonski/HashId) +[![Code Coverage](https://scrutinizer-ci.com/g/kjonski/HashId/badges/coverage.png?b=2.0)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=2.0) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/kjonski/HashId/badges/quality-score.png?b=2.0)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=2.0) -Symfony 4 bundle for encoding integer route parameters and decoding request parameters with +Symfony 3.4/4/5 bundle for encoding integer route parameters and decoding request parameters with Replace predictable integer url parameters in easy way: * `/hash-id/demo/decode/216/30` => `/hash-id/demo/decode/X46dBNxd79/30` * `/order/315` => `/order/4w9aA11avM` From 71bd1847f6c6067d995087f69767f8a4bbeeeccf Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Thu, 13 Feb 2020 21:53:36 +0100 Subject: [PATCH 2/9] Set branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e48fbf4..296b15d 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "minimum-stability": "stable", "extra": { "branch-alias": { - "dev-master": "master" + "dev-master": "2.0-dev" } }, "require-dev": { From fe398033715c1414b84599b37f043906fc8f7f6f Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Sun, 1 Mar 2020 22:31:43 +0100 Subject: [PATCH 3/9] Update urls and version info in readme --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7421b3c..d26a2a3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # [![PGS Software](https://www.pgs-soft.com/pgssoft-logo.png)](https://www.pgs-soft.com) / HashId ![PHP from Packagist](https://img.shields.io/packagist/php-v/symfony/symfony.svg) -[![Build Status](https://travis-ci.org/kjonski/HashId.svg?branch=2.0)](https://travis-ci.org/kjonski/HashId) -[![Code Coverage](https://scrutinizer-ci.com/g/kjonski/HashId/badges/coverage.png?b=2.0)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=2.0) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/kjonski/HashId/badges/quality-score.png?b=2.0)](https://scrutinizer-ci.com/g/kjonski/HashId/?branch=2.0) - -Symfony 3.4/4/5 bundle for encoding integer route parameters and decoding request parameters with +[![Build Status](https://travis-ci.org/PGSSoft/HashId.svg?branch=2.0)](https://travis-ci.org/PGSSoft/HashId) +[![Code Coverage](https://scrutinizer-ci.com/g/PGSSoft/HashId/badges/coverage.png?b=2.0)](https://scrutinizer-ci.com/g/PGSSoft/HashId/?branch=2.0) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PGSSoft/HashId/badges/quality-score.png?b=2.0)](https://scrutinizer-ci.com/g/PGSSoft/HashId/?branch=2.0) + +Symfony bundle for encoding integer route parameters and decoding request parameters with +*** +Please use this version with Symfony ≥4.4 and <5.0 +*** Replace predictable integer url parameters in easy way: * `/hash-id/demo/decode/216/30` => `/hash-id/demo/decode/X46dBNxd79/30` * `/order/315` => `/order/4w9aA11avM` From 2b129098a1d078aec12732d5b5822526be6d0d0e Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Thu, 23 Apr 2020 22:36:50 +0200 Subject: [PATCH 4/9] Update configuration documentation to meet configuration structure --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d26a2a3..2bc30f9 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,11 @@ composer require pgs-soft/hashid-bundle # config/packages/pgs_hash_id.yaml pgs_hash_id: - salt: 'my super salt' - min_hash_length: 20 - alphabet: 'qwertyasdzxc098765-' + converter: + hashids: + salt: 'my super salt' + min_hash_length: 20 + alphabet: 'qwertyasdzxc098765-' ``` ## Controller configuration From 2f75e9b7b671a251de17ab16288da2bfb8482ce6 Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Wed, 29 Apr 2020 19:30:33 +0200 Subject: [PATCH 5/9] Handle controller passed by object or closure to DecodeControllerParameters --- src/Service/DecodeControllerParameters.php | 12 ++++- tests/Controller/ControllerMockProvider.php | 13 +++-- .../DecodeControllerParametersTest.php | 50 +++++++++++++------ 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/Service/DecodeControllerParameters.php b/src/Service/DecodeControllerParameters.php index 7823e18..1627f7b 100644 --- a/src/Service/DecodeControllerParameters.php +++ b/src/Service/DecodeControllerParameters.php @@ -23,9 +23,19 @@ public function __construct(DecodeParametersProcessorFactory $parametersProcesso public function decodeControllerParameters(ControllerEvent $event): void { $controller = $event->getController(); + if (is_array($controller)){ + list($controllerObject, $method) = $controller; + } elseif (is_object($controller) && !$controller instanceof \Closure){ + $controllerObject = $controller; + $method = '__invoke'; + } else { + //Controller is a closure + return; + } + $parametersProcessor = $this ->getParametersProcessorFactory() - ->createControllerDecodeParametersProcessor(...$controller); + ->createControllerDecodeParametersProcessor($controllerObject, $method); $this->processRequestParameters($event, $parametersProcessor); $this->processRequestParametersWithParamConverter($event); diff --git a/tests/Controller/ControllerMockProvider.php b/tests/Controller/ControllerMockProvider.php index dccb6f9..c46e10f 100644 --- a/tests/Controller/ControllerMockProvider.php +++ b/tests/Controller/ControllerMockProvider.php @@ -3,13 +3,20 @@ namespace Pgs\HashIdBundle\Tests\Controller; use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class ControllerMockProvider extends TestCase { - public function getTestControllerMock(): Controller + public function getTestControllerMock(): AbstractController { - return $this->getMockBuilder(Controller::class) + return $this->getMockBuilder(AbstractController::class) + ->getMockForAbstractClass(); + } + + public function getTestControllerObjectMock(): AbstractController + { + return $this->getMockBuilder(AbstractController::class) + ->setMethods(['__invoke']) ->getMockForAbstractClass(); } } diff --git a/tests/Service/DecodeControllerParametersTest.php b/tests/Service/DecodeControllerParametersTest.php index 035a1f1..66187d3 100644 --- a/tests/Service/DecodeControllerParametersTest.php +++ b/tests/Service/DecodeControllerParametersTest.php @@ -22,13 +22,12 @@ class DecodeControllerParametersTest extends TestCase protected function setUp() { - $this->controllerMockProvider = new ControllerMockProvider(); $this->parametersProcessorMockProvider = new ParametersProcessorMockProvider(); } public function getControllerMockProvider(): ControllerMockProvider { - return $this->controllerMockProvider; + return $this->controllerMockProvider ?? new ControllerMockProvider(); } public function getParametersProcessorMockProvider(): ParametersProcessorMockProvider @@ -36,7 +35,12 @@ public function getParametersProcessorMockProvider(): ParametersProcessorMockPro return $this->parametersProcessorMockProvider; } - public function testDecodeControllerParameters(): void + /** + * @dataProvider decodeControllerParametersDataProvider + * + * @param mixed $controller + */ + public function testDecodeControllerParameters($controller): void { $decodeParametersProcessorFactory = $this->getDecodeParametersProcessorFactoryMock(); $decodeControllerParameters = new DecodeControllerParameters($decodeParametersProcessorFactory); @@ -50,27 +54,43 @@ public function testDecodeControllerParameters(): void 'id' => 10, 'name' => 'test', ], - ] + ], + $controller ); $decodeControllerParameters->decodeControllerParameters($event); $this->assertSame(10, $event->getRequest()->attributes->all()['id']); } - public function testDecodeControllerParametersWithParamConverter(): void + public function decodeControllerParametersDataProvider() + { + return [ + ['controller as array' => $this->getControllerMockProvider()->getTestControllerMock(), 'demo'], + ]; + } + + /** + * @dataProvider decodeControllerParametersDataProvider + * + * @param $controller + */ + public function testDecodeControllerParametersWithParamConverter($controller): void { $decodeParametersProcessorFactory = $this->getDecodeParametersProcessorFactoryMock(); $decodeControllerParameters = new DecodeControllerParameters($decodeParametersProcessorFactory); $decodeControllerParameters->setParamConverterListener($this->getDoctrineParamConverterListenerMock()); - $event = $this->getEventMock([ - [ - 'id' => 'encoded', - 'name' => 'test', - ], + $event = $this->getEventMock( [ - 'id' => 10, - 'name' => 'test', + [ + 'id' => 'encoded', + 'name' => 'test', + ], + [ + 'id' => 10, + 'name' => 'test', + ], ], - ]); + $controller + ); $decodeControllerParameters->decodeControllerParameters($event); $this->assertSame(10, $event->getRequest()->attributes->all()['id']); } @@ -102,7 +122,7 @@ protected function getDecodeParametersProcessorMock(): Decode /** * @return ControllerEvent|MockObject */ - protected function getEventMock(array $requestConsecutiveCalls): ControllerEvent + protected function getEventMock(array $requestConsecutiveCalls, $controller): ControllerEvent { $mock = $this->getMockBuilder(ControllerEvent::class) ->disableOriginalConstructor() @@ -110,7 +130,7 @@ protected function getEventMock(array $requestConsecutiveCalls): ControllerEvent ->getMock(); $mock->method('getController') - ->willReturn([$this->getControllerMockProvider()->getTestControllerMock(), 'demo']); + ->willReturn($controller); $mock->method('getRequest') ->willReturn($this->getRequestMock($requestConsecutiveCalls)); From c824b5606fdf3ff3b15ac383d4244345a3f0c418 Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Wed, 29 Apr 2020 20:17:42 +0200 Subject: [PATCH 6/9] Follow cs --- src/Service/DecodeControllerParameters.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/DecodeControllerParameters.php b/src/Service/DecodeControllerParameters.php index 1627f7b..6b7d9f0 100644 --- a/src/Service/DecodeControllerParameters.php +++ b/src/Service/DecodeControllerParameters.php @@ -23,9 +23,9 @@ public function __construct(DecodeParametersProcessorFactory $parametersProcesso public function decodeControllerParameters(ControllerEvent $event): void { $controller = $event->getController(); - if (is_array($controller)){ + if (\is_array($controller)) { list($controllerObject, $method) = $controller; - } elseif (is_object($controller) && !$controller instanceof \Closure){ + } elseif (\is_object($controller) && !$controller instanceof \Closure) { $controllerObject = $controller; $method = '__invoke'; } else { From ec8c166e68d87b7c9ff10081133a63f5cb6f1ca1 Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Tue, 26 May 2020 22:37:16 +0200 Subject: [PATCH 7/9] Use locale while searching for route --- src/Controller/DemoController.php | 23 ++++++++++++++++++++ src/Decorator/RouterDecorator.php | 28 +++++++++++++++++-------- src/Resources/routes.yaml | 6 ++++++ tests/Decorator/RouterDecoratorTest.php | 18 ++++++++++++++-- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/Controller/DemoController.php b/src/Controller/DemoController.php index 71fea74..118289a 100644 --- a/src/Controller/DemoController.php +++ b/src/Controller/DemoController.php @@ -55,6 +55,29 @@ public function decodeMore(Request $request, int $id, int $other): Response return new Response($this->getDecodeResponse($request, $id, $other)); } + /** + * @Hash("id") + * + * @param int $id + */ + public function encodeLocalized($id): Response + { + $url1 = $this->generateUrl('pgs_hash_id_demo_encode_localized', ['id' => $id, '_locale' => 'pl']); + $url2 = $this->generateUrl('pgs_hash_id_demo_encode_localized', ['id' => $id]); + + $response = << + + Provided id: $id
+ Localized url with encoded parameter and locale provided: $url1
+ Localized url with encoded parameter: $url2
+ + +EOT; + + return new Response($response); + } + private function getDecodeResponse(Request $request, int $id, int $other): string { $providedId = $this->getRouteParam($request, 'id'); diff --git a/src/Decorator/RouterDecorator.php b/src/Decorator/RouterDecorator.php index e8ac2fb..8c55129 100644 --- a/src/Decorator/RouterDecorator.php +++ b/src/Decorator/RouterDecorator.php @@ -28,19 +28,29 @@ public function getRouter(): RouterInterface return $this->object; } - /** - * @param string $name - * @param array $parameters - * @param int $referenceType - */ - public function generate($name, $parameters = [], $referenceType = RouterInterface::ABSOLUTE_PATH): string - { - $route = $this->getRouter()->getRouteCollection()->get($name); - $this->processParameters($route, $parameters); + public function generate( + $name, + $parameters = [], + $referenceType = RouterInterface::ABSOLUTE_PATH + ): string { + $this->processParameters($this->getRoute($name, $parameters), $parameters); return $this->getRouter()->generate($name, $parameters, $referenceType); } + private function getRoute(string $name, array $parameters): ?Route + { + $routeCollection = $this->getRouter()->getRouteCollection(); + $route = $routeCollection->get($name); + + if (null === $route) { + $locale = $parameters['_locale'] ?? $this->getRouter()->getContext()->getParameter('_locale'); + $route = $routeCollection->get(sprintf('%s.%s', $name, $locale)); + } + + return $route; + } + private function processParameters(?Route $route, array &$parameters): void { if (null !== $route) { diff --git a/src/Resources/routes.yaml b/src/Resources/routes.yaml index cedfc89..f130808 100644 --- a/src/Resources/routes.yaml +++ b/src/Resources/routes.yaml @@ -11,3 +11,9 @@ pgs_hash_id_demo_decode: pgs_hash_id_demo_decode_more: path: /hash-id/demo/decode_more/{id}/{other} controller: Pgs\HashIdBundle\Controller\DemoController::decodeMore + +pgs_hash_id_demo_encode_localized: + path: + en: /hash-id/demo/encode-en/{id} + pl: /hash-id/demo/encode-pl/{id} + controller: Pgs\HashIdBundle\Controller\DemoController::encodeLocalized \ No newline at end of file diff --git a/tests/Decorator/RouterDecoratorTest.php b/tests/Decorator/RouterDecoratorTest.php index 514a361..429fd5b 100644 --- a/tests/Decorator/RouterDecoratorTest.php +++ b/tests/Decorator/RouterDecoratorTest.php @@ -29,15 +29,29 @@ public function testGenerateUrl(): void $id = 10; $other = 20; $alphabet = self::$container->getParameter('pgs_hash_id.converter.hashids.alphabet'); + $hashLength = self::$container->getParameter('pgs_hash_id.converter.hashids.min_hash_length'); + $routeArgs = ['pgs_hash_id_demo_decode', ['id' => $id, 'other' => $other]]; $generatedPath = $this->router->generate(...$routeArgs); $this->assertNotSame(sprintf('/hash-id/demo/decode/%d/%d', $id, $other), $generatedPath); - $pattern = sprintf('/\/hash-id\/demo\/decode\/[%s]+\/\d+/', $alphabet); + $pattern = sprintf('/\/hash-id\/demo\/decode\/[%s]{%d}\/\d+/', $alphabet, $hashLength); + $this->assertRegExp($pattern, $generatedPath); + + $routeArgs = ['pgs_hash_id_demo_encode_localized', ['id' => $id, '_locale' => 'pl']]; + $generatedPath = $this->router->generate(...$routeArgs); + $this->assertNotSame(sprintf('/hash-id/demo/encode-pl/%d', $id), $generatedPath); + $pattern = sprintf('/\/hash-id\/demo\/encode-pl\/[%s]{%d}/', $alphabet, $hashLength); $this->assertRegExp($pattern, $generatedPath); $routeArgs = ['pgs_hash_id_demo_decode_more', ['id' => $id, 'other' => $other]]; $generatedPath = $this->router->generate(...$routeArgs); - $pattern = sprintf('/\/hash-id\/demo\/decode_more\/[%s]+\/[%s]+/', $alphabet, $alphabet); + $pattern = sprintf( + '/\/hash-id\/demo\/decode_more\/[%s]{%d}\/[%s]{%d}/', + $alphabet, + $hashLength, + $alphabet, + $hashLength + ); $this->assertRegExp($pattern, $generatedPath); } } From 893796e0870e2565840cf763bed87e6533da6167 Mon Sep 17 00:00:00 2001 From: Karol Jonski Date: Mon, 28 Sep 2020 07:35:06 +0200 Subject: [PATCH 8/9] Resolves #18 Update symfony/http-kernel --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 296b15d..151bece 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "phpstan/phpstan": "^0.12", "sebastian/phpcpd": "^4.0", "squizlabs/php_codesniffer": "^3.2", - "symfony/http-kernel": "^4.4|^5.0", + "symfony/http-kernel": "^4.4.13|^5.1.5", "sensio/framework-extra-bundle": "^5.1", "friendsofphp/php-cs-fixer": "^2.10", "phpunit/phpunit": "^7.0", From 5f75bee95ce18c4dc9e98bbba22cae6a8ec49c8a Mon Sep 17 00:00:00 2001 From: xtochko <111567447+xtochko@users.noreply.github.com> Date: Fri, 19 Aug 2022 13:07:06 +0300 Subject: [PATCH 9/9] Update restrictions to use PHP8 resolve#issue-22 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 151bece..b3adc56 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/dependency-injection": "^4.1.12|^5.0", "symfony/config": "~4.4|~5.0", "doctrine/annotations": "^1.6",