From fac365d14ce148c643241d4852d7264444926c76 Mon Sep 17 00:00:00 2001 From: Dmitry Tsemma Date: Thu, 28 Nov 2024 17:34:08 +0200 Subject: [PATCH] FRW-7936 Allow to provide store name as part of URL path. (#11121) FRW-7936 Allow to provide store name as part of URL path. --- composer.json | 3 ++ src/Spryker/Shared/Router/RouterConstants.php | 10 ++++ .../Router/Transfer/router.transfer.xml | 4 ++ .../Client/RouterToStoreClientBridge.php | 34 +++++++++++++ .../Client/RouterToStoreClientInterface.php | 18 +++++++ .../StorePrefixRouterEnhancerPlugin.php | 18 ++++--- src/Spryker/Yves/Router/RouterConfig.php | 13 +++++ .../Yves/Router/RouterDependencyProvider.php | 21 ++++++++ src/Spryker/Yves/Router/RouterFactory.php | 9 ++++ ...nguageAndStorePrefixRouterEnhancerTest.php | 35 +++++++++++++ ...oreAndLanguagePrefixRouterEnhancerTest.php | 17 +++++++ ...luginWithStorePrefixRouterEnhancerTest.php | 33 +++++++++++++ .../Yves/Router/_support/RouterYvesTester.php | 49 +++++++++++++++++++ tests/SprykerTest/Yves/Router/codeception.yml | 2 + 14 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientBridge.php create mode 100644 src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientInterface.php diff --git a/composer.json b/composer.json index 3c4d32c..b851bdf 100644 --- a/composer.json +++ b/composer.json @@ -12,12 +12,15 @@ "spryker/laminas": "^1.0.0", "spryker/log": "^3.0.0", "spryker/router-extension": "^1.0.0", + "spryker/store": "^1.19.0", "spryker/symfony": "^3.5.0" }, "require-dev": { "spryker/application": "*", "spryker/code-sniffer": "*", + "spryker/config": "*", "spryker/event-dispatcher": "*", + "spryker/storage": "*", "spryker/testify": "*", "spryker/util-text": "*" }, diff --git a/src/Spryker/Shared/Router/RouterConstants.php b/src/Spryker/Shared/Router/RouterConstants.php index 9af91b3..38e87df 100644 --- a/src/Spryker/Shared/Router/RouterConstants.php +++ b/src/Spryker/Shared/Router/RouterConstants.php @@ -144,4 +144,14 @@ interface RouterConstants * @var string */ public const PROJECT_NAMESPACES = 'PROJECT_NAMESPACES'; + + /** + * Specification: + * - Returns true if the store routing is enabled. + * + * @api + * + * @var string + */ + public const IS_STORE_ROUTING_ENABLED = 'ROUTER:IS_STORE_ROUTING_ENABLED'; } diff --git a/src/Spryker/Shared/Router/Transfer/router.transfer.xml b/src/Spryker/Shared/Router/Transfer/router.transfer.xml index fc6c34f..5d81181 100644 --- a/src/Spryker/Shared/Router/Transfer/router.transfer.xml +++ b/src/Spryker/Shared/Router/Transfer/router.transfer.xml @@ -10,4 +10,8 @@ + + + + diff --git a/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientBridge.php b/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientBridge.php new file mode 100644 index 0000000..9d745aa --- /dev/null +++ b/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientBridge.php @@ -0,0 +1,34 @@ +storeClient = $storeClient; + } + + /** + * @return \Generated\Shared\Transfer\StoreTransfer + */ + public function getCurrentStore(): StoreTransfer + { + return $this->storeClient->getCurrentStore(); + } +} diff --git a/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientInterface.php b/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientInterface.php new file mode 100644 index 0000000..2eabe34 --- /dev/null +++ b/src/Spryker/Yves/Router/Dependency/Client/RouterToStoreClientInterface.php @@ -0,0 +1,18 @@ +currentStore !== null) { - $parameters['store'] = $this->currentStore; + $parameters[static::PARAMETER_STORE] = $this->currentStore; } return $parameters; @@ -83,11 +89,11 @@ public function afterGenerate(string $url, RequestContext $requestContext, int $ */ protected function findStore(RequestContext $requestContext): ?string { - if ($requestContext->hasParameter('store')) { - return $requestContext->getParameter('store'); - } - - return null; + return $requestContext->hasParameter(static::PARAMETER_STORE) && $requestContext->getParameter(static::PARAMETER_STORE) !== null + ? $requestContext->getParameter(static::PARAMETER_STORE) + : ($this->getConfig()->isStoreRoutingEnabled() + ? $this->getFactory()->getStoreClient()->getCurrentStore()->getNameOrFail() + : null); } /** diff --git a/src/Spryker/Yves/Router/RouterConfig.php b/src/Spryker/Yves/Router/RouterConfig.php index f32355a..0a00974 100644 --- a/src/Spryker/Yves/Router/RouterConfig.php +++ b/src/Spryker/Yves/Router/RouterConfig.php @@ -136,4 +136,17 @@ public function getAllowedStores(): array 'US', ]; } + + /** + * Specification: + * - Returns true if the store routing is enabled. + * + * @api + * + * @return bool + */ + public function isStoreRoutingEnabled(): bool + { + return $this->get(RouterConstants::IS_STORE_ROUTING_ENABLED, false); + } } diff --git a/src/Spryker/Yves/Router/RouterDependencyProvider.php b/src/Spryker/Yves/Router/RouterDependencyProvider.php index 2298900..9788aa0 100644 --- a/src/Spryker/Yves/Router/RouterDependencyProvider.php +++ b/src/Spryker/Yves/Router/RouterDependencyProvider.php @@ -9,6 +9,7 @@ use Spryker\Yves\Kernel\AbstractBundleDependencyProvider; use Spryker\Yves\Kernel\Container; +use Spryker\Yves\Router\Dependency\Client\RouterToStoreClientBridge; /** * @method \Spryker\Yves\Router\RouterConfig getConfig() @@ -35,6 +36,11 @@ class RouterDependencyProvider extends AbstractBundleDependencyProvider */ public const ROUTER_ENHANCER_PLUGINS = 'ROUTER_ENHANCER_PLUGINS'; + /** + * @var string + */ + public const CLIENT_STORE = 'CLIENT_STORE'; + /** * @param \Spryker\Yves\Kernel\Container $container * @@ -46,6 +52,7 @@ public function provideDependencies(Container $container) $container = $this->addRouterEnhancerPlugins($container); $container = $this->addRouteProvider($container); $container = $this->addPostAddRouteManipulator($container); + $container = $this->addStoreClient($container); return $container; } @@ -137,4 +144,18 @@ protected function getPostAddRouteManipulator(): array { return []; } + + /** + * @param \Spryker\Yves\Kernel\Container $container + * + * @return \Spryker\Yves\Kernel\Container + */ + protected function addStoreClient(Container $container): Container + { + $container->set(static::CLIENT_STORE, function (Container $container) { + return new RouterToStoreClientBridge($container->getLocator()->store()->client()); + }); + + return $container; + } } diff --git a/src/Spryker/Yves/Router/RouterFactory.php b/src/Spryker/Yves/Router/RouterFactory.php index af7230c..42a618a 100644 --- a/src/Spryker/Yves/Router/RouterFactory.php +++ b/src/Spryker/Yves/Router/RouterFactory.php @@ -10,6 +10,7 @@ use Spryker\Shared\Router\Cache\CacheInterface; use Spryker\Yves\Kernel\AbstractFactory; use Spryker\Yves\Router\Cache\Cache; +use Spryker\Yves\Router\Dependency\Client\RouterToStoreClientInterface; use Spryker\Yves\Router\Loader\ClosureLoader; use Spryker\Yves\Router\Loader\LoaderInterface; use Spryker\Yves\Router\Resolver\RequestRequestValueResolver; @@ -219,4 +220,12 @@ public function createCache(): CacheInterface { return new Cache($this->createRouter(), $this->getConfig()); } + + /** + * @return \Spryker\Yves\Router\Dependency\Client\RouterToStoreClientInterface + */ + public function getStoreClient(): RouterToStoreClientInterface + { + return $this->getProvidedDependency(RouterDependencyProvider::CLIENT_STORE); + } } diff --git a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithLanguageAndStorePrefixRouterEnhancerTest.php b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithLanguageAndStorePrefixRouterEnhancerTest.php index b12d32a..a927025 100644 --- a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithLanguageAndStorePrefixRouterEnhancerTest.php +++ b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithLanguageAndStorePrefixRouterEnhancerTest.php @@ -41,6 +41,7 @@ public function setUp(): void { parent::setUp(); + $this->tester->setupStorageRedisConfig(); $this->tester->mockEnvironmentConfig(RouterConstants::YVES_IS_CACHE_ENABLED, false); $this->tester->mockFactoryMethod('getRouteProviderPlugins', [ @@ -123,6 +124,7 @@ public function testGenerateReturnsUrlWithLanguageAndStoreWhenLanguageAndStoreAr */ public function testGenerateReturnsUrlWithoutLanguageAndStoreWhenLanguageAndStoreAreNotInContext(string $url, string $routeName): void { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, false); $routerPlugin = new YvesRouterPlugin(); $routerPlugin->setFactory($this->tester->getFactory()); @@ -133,6 +135,28 @@ public function testGenerateReturnsUrlWithoutLanguageAndStoreWhenLanguageAndStor $this->assertSame($url, $generatedUrl); } + /** + * @dataProvider generatorWithoutLanguageAndStoreDataProviderWithStoreRoutingEnabled + * + * @param string $url + * @param string $routeName + * + * @return void + */ + public function testGenerateReturnsUrlWithoutLanguageAndStoreWhenLanguageAndStoreAreNotInContextWithStoreRoutingEnabled( + string $url, + string $routeName + ): void { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, true); + $routerPlugin = new YvesRouterPlugin(); + $routerPlugin->setFactory($this->tester->getFactory()); + $router = $routerPlugin->getRouter(); + + $generatedUrl = $router->generate($routeName); + + $this->assertSame($url, $generatedUrl); + } + /** * @return array> */ @@ -169,4 +193,15 @@ public function generatorWithoutLanguageAndStoreDataProvider(): array ['/foo', 'foo'], ]; } + + /** + * @return array> + */ + public function generatorWithoutLanguageAndStoreDataProviderWithStoreRoutingEnabled(): array + { + return [ + ['/DE', 'home'], + ['/DE/foo', 'foo'], + ]; + } } diff --git a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStoreAndLanguagePrefixRouterEnhancerTest.php b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStoreAndLanguagePrefixRouterEnhancerTest.php index fe2afa9..9db1846 100644 --- a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStoreAndLanguagePrefixRouterEnhancerTest.php +++ b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStoreAndLanguagePrefixRouterEnhancerTest.php @@ -100,6 +100,7 @@ public function testGenerateReturnsUrlWithStoreAndLanguageWhenStoreAndLanguageAr */ public function testGenerateReturnsUrlWithoutStoreAndLanguageWhenStoreAndLanguageAreNotInContextParameter(): void { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, false); $routerPlugin = new YvesRouterPlugin(); $routerPlugin->setFactory($this->tester->getFactory()); @@ -109,4 +110,20 @@ public function testGenerateReturnsUrlWithoutStoreAndLanguageWhenStoreAndLanguag $this->assertSame('/foo', $url); } + + /** + * @return void + */ + public function testGenerateReturnsUrlWithoutStoreAndLanguageWhenStoreAndLanguageAreNotInContextParameterWithStoreRoutingEnabled(): void + { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, true); + $routerPlugin = new YvesRouterPlugin(); + $routerPlugin->setFactory($this->tester->getFactory()); + + $router = $routerPlugin->getRouter(); + + $url = $router->generate('foo'); + + $this->assertSame('/DE/foo', $url); + } } diff --git a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStorePrefixRouterEnhancerTest.php b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStorePrefixRouterEnhancerTest.php index 6999f94..1ed868a 100644 --- a/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStorePrefixRouterEnhancerTest.php +++ b/tests/SprykerTest/Yves/Router/Plugin/YvesRouterPluginWithStorePrefixRouterEnhancerTest.php @@ -111,6 +111,28 @@ public function testGenerateReturnsUrlWithStoreWhenStoreIsInContext(string $url, */ public function testGenerateReturnsUrlWithoutStoreWhenStoreIsNotInContext(string $url, string $routeName): void { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, false); + $routerPlugin = new YvesRouterPlugin(); + $routerPlugin->setFactory($this->tester->getFactory()); + + $router = $routerPlugin->getRouter(); + + $generatedUrl = $router->generate($routeName); + + $this->assertSame($url, $generatedUrl); + } + + /** + * @dataProvider generatorWithoutLanguageAndStoreDataProviderWithStoreRoutingEnabled + * + * @param string $url + * @param string $routeName + * + * @return void + */ + public function testGenerateReturnsUrlWithoutStoreWhenStoreIsNotInContextWithStoreRoutingEnabled(string $url, string $routeName): void + { + $this->tester->mockEnvironmentConfig(RouterConstants::IS_STORE_ROUTING_ENABLED, true); $routerPlugin = new YvesRouterPlugin(); $routerPlugin->setFactory($this->tester->getFactory()); @@ -157,4 +179,15 @@ public function generatorWithoutLanguageAndStoreDataProvider(): array ['/foo', 'foo'], ]; } + + /** + * @return array> + */ + public function generatorWithoutLanguageAndStoreDataProviderWithStoreRoutingEnabled(): array + { + return [ + ['/DE', 'home'], + ['/DE/foo', 'foo'], + ]; + } } diff --git a/tests/SprykerTest/Yves/Router/_support/RouterYvesTester.php b/tests/SprykerTest/Yves/Router/_support/RouterYvesTester.php index c6a7ab3..0ca801d 100644 --- a/tests/SprykerTest/Yves/Router/_support/RouterYvesTester.php +++ b/tests/SprykerTest/Yves/Router/_support/RouterYvesTester.php @@ -8,6 +8,8 @@ namespace SprykerTest\Yves\Router; use Codeception\Actor; +use Spryker\Shared\Config\Config; +use Spryker\Shared\Storage\StorageConstants; /** * @method void wantToTest($text) @@ -26,4 +28,51 @@ class RouterYvesTester extends Actor { use _generated\RouterYvesTesterActions; + + /** + * @uses \Spryker\Shared\StorageRedis\StorageRedisConstants::STORAGE_REDIS_SCHEME + * + * @var string + */ + protected const REDIS_SCHEME = 'STORAGE_REDIS:STORAGE_REDIS_SCHEME'; + + /** + * @uses \Spryker\Shared\StorageRedis\StorageRedisConstants::STORAGE_REDIS_HOST + * + * @var string + */ + protected const REDIS_HOST = 'STORAGE_REDIS:STORAGE_REDIS_HOST'; + + /** + * @uses \Spryker\Shared\StorageRedis\StorageRedisConstants::STORAGE_REDIS_PORT + * + * @var string + */ + protected const REDIS_PORT = 'STORAGE_REDIS:STORAGE_REDIS_PORT'; + + /** + * @uses \Spryker\Shared\StorageRedis\StorageRedisConstants::STORAGE_REDIS_DATABASE + * + * @var string + */ + protected const REDIS_DATABASE = 'STORAGE_REDIS:STORAGE_REDIS_DATABASE'; + + /** + * @uses \Spryker\Shared\StorageRedis\StorageRedisConstants::STORAGE_REDIS_PASSWORD + * + * @var string + */ + protected const REDIS_PASSWORD = 'STORAGE_REDIS:STORAGE_REDIS_PASSWORD'; + + /** + * @return void + */ + public function setupStorageRedisConfig(): void + { + $this->setConfig(StorageConstants::STORAGE_REDIS_PROTOCOL, Config::get(static::REDIS_SCHEME, false)); + $this->setConfig(StorageConstants::STORAGE_REDIS_PORT, Config::get(static::REDIS_PORT)); + $this->setConfig(StorageConstants::STORAGE_REDIS_HOST, Config::get(static::REDIS_HOST)); + $this->setConfig(StorageConstants::STORAGE_REDIS_DATABASE, Config::get(static::REDIS_DATABASE)); + $this->setConfig(StorageConstants::STORAGE_REDIS_PASSWORD, Config::get(static::REDIS_PASSWORD)); + } } diff --git a/tests/SprykerTest/Yves/Router/codeception.yml b/tests/SprykerTest/Yves/Router/codeception.yml index 451b3ff..1e9e14e 100644 --- a/tests/SprykerTest/Yves/Router/codeception.yml +++ b/tests/SprykerTest/Yves/Router/codeception.yml @@ -24,3 +24,5 @@ suites: - \SprykerTest\Shared\Testify\Helper\DependencyHelper - \SprykerTest\Yves\Testify\Helper\DependencyProviderHelper - \SprykerTest\Yves\Testify\Helper\FactoryHelper + - \SprykerTest\Service\Container\Helper\ContainerHelper + - \SprykerTest\Shared\Store\Helper\StoreDependencyHelper