diff --git a/composer.json b/composer.json
index d893ae2..c38e29b 100644
--- a/composer.json
+++ b/composer.json
@@ -5,14 +5,19 @@
"license": "proprietary",
"require": {
"php": ">=8.2",
- "spryker-shop/storage-router-extension": "^1.0.0",
+ "spryker-shop/storage-router-extension": "^1.1.0",
"spryker/kernel": "^3.30.0",
"spryker/router-extension": "^1.0.0",
+ "spryker/store": "^1.19.0",
"spryker/symfony": "^3.2.2",
"spryker/url-storage": "^1.4.1"
},
"require-dev": {
- "spryker/code-sniffer": "*"
+ "spryker/code-sniffer": "*",
+ "spryker/util-text": "*"
+ },
+ "suggest": {
+ "spryker/util-text": "If you want to use the RouterEnhancer plugins."
},
"autoload": {
"psr-4": {
diff --git a/src/SprykerShop/Shared/StorageRouter/StorageRouterConstants.php b/src/SprykerShop/Shared/StorageRouter/StorageRouterConstants.php
new file mode 100644
index 0000000..e82a12e
--- /dev/null
+++ b/src/SprykerShop/Shared/StorageRouter/StorageRouterConstants.php
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/src/SprykerShop/Yves/StorageRouter/Dependency/Client/StorageRouterToStoreClientInterface.php b/src/SprykerShop/Yves/StorageRouter/Dependency/Client/StorageRouterToStoreClientInterface.php
new file mode 100644
index 0000000..a4d9389
--- /dev/null
+++ b/src/SprykerShop/Yves/StorageRouter/Dependency/Client/StorageRouterToStoreClientInterface.php
@@ -0,0 +1,18 @@
+storeClient = $storeClient;
+ }
+
+ /**
+ * @return \Generated\Shared\Transfer\StoreTransfer
+ */
+ public function getCurrentStore(): StoreTransfer
+ {
+ return $this->storeClient->getCurrentStore();
+ }
+}
diff --git a/src/SprykerShop/Yves/StorageRouter/Plugin/RouterEnhancer/StorePrefixStorageRouterEnhancerPlugin.php b/src/SprykerShop/Yves/StorageRouter/Plugin/RouterEnhancer/StorePrefixStorageRouterEnhancerPlugin.php
new file mode 100644
index 0000000..1cf570f
--- /dev/null
+++ b/src/SprykerShop/Yves/StorageRouter/Plugin/RouterEnhancer/StorePrefixStorageRouterEnhancerPlugin.php
@@ -0,0 +1,128 @@
+getConfig()->getAllowedStores(), true)) {
+ $this->currentStore = array_shift($pathinfoFragments);
+
+ return '/' . implode('/', $pathinfoFragments);
+ }
+
+ return $pathinfo;
+ }
+
+ /**
+ * @param array $parameters
+ * @param \Symfony\Component\Routing\RequestContext $requestContext
+ *
+ * @return array
+ */
+ public function afterMatch(array $parameters, RequestContext $requestContext): array
+ {
+ if ($this->currentStore !== null) {
+ $parameters[static::PARAMETER_STORE] = $this->currentStore;
+ }
+
+ return $parameters;
+ }
+
+ /**
+ * @param string $url
+ * @param \Symfony\Component\Routing\RequestContext $requestContext
+ * @param int $referenceType
+ *
+ * @return string
+ */
+ public function afterGenerate(string $url, RequestContext $requestContext, int $referenceType): string
+ {
+ $store = $this->findStore($requestContext);
+
+ if ($store !== null) {
+ return $this->buildUrlWithStore($url, $store, $referenceType);
+ }
+
+ return $url;
+ }
+
+ /**
+ * @param \Symfony\Component\Routing\RequestContext $requestContext
+ *
+ * @return string|null
+ */
+ protected function findStore(RequestContext $requestContext): ?string
+ {
+ 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);
+ }
+
+ /**
+ * @param string $url
+ * @param string $store
+ * @param int $referenceType
+ *
+ * @return string
+ */
+ protected function buildUrlWithStore(string $url, string $store, int $referenceType): string
+ {
+ if ($url === '/') {
+ $url = '';
+ }
+
+ if ($referenceType === DynamicRouter::ABSOLUTE_PATH) {
+ return sprintf('/%s%s', $store, $url);
+ }
+
+ if ($referenceType === DynamicRouter::ABSOLUTE_URL) {
+ $parsedUrl = Url::parse($url);
+ $pathWithStore = sprintf('/%s%s', $store, $parsedUrl->getPath());
+ $parsedUrl->setPath($pathWithStore);
+
+ return (string)$parsedUrl;
+ }
+
+ return $url;
+ }
+}
diff --git a/src/SprykerShop/Yves/StorageRouter/RequestMatcher/StorageRequestMatcher.php b/src/SprykerShop/Yves/StorageRouter/RequestMatcher/StorageRequestMatcher.php
index 722153a..8a8bf47 100644
--- a/src/SprykerShop/Yves/StorageRouter/RequestMatcher/StorageRequestMatcher.php
+++ b/src/SprykerShop/Yves/StorageRouter/RequestMatcher/StorageRequestMatcher.php
@@ -11,20 +11,35 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
+use Symfony\Component\Routing\RequestContext;
class StorageRequestMatcher implements RequestMatcherInterface
{
+ /**
+ * @var string
+ */
+ protected const ATTRIBUTE_PATH_INFO = 'pathinfo';
+
/**
* @var \SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToUrlStorageClientInterface
*/
protected $urlStorageClient;
+ /**
+ * @var array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface>
+ */
+ protected array $storageRouterEnhancerPlugins;
+
/**
* @param \SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToUrlStorageClientInterface $urlStorageClient
+ * @param array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface> $storageRouterEnhancerPlugins
*/
- public function __construct(StorageRouterToUrlStorageClientInterface $urlStorageClient)
- {
+ public function __construct(
+ StorageRouterToUrlStorageClientInterface $urlStorageClient,
+ array $storageRouterEnhancerPlugins
+ ) {
$this->urlStorageClient = $urlStorageClient;
+ $this->storageRouterEnhancerPlugins = $storageRouterEnhancerPlugins;
}
/**
@@ -36,12 +51,23 @@ public function __construct(StorageRouterToUrlStorageClientInterface $urlStorage
*/
public function matchRequest(Request $request): array
{
+ $requestContext = new RequestContext();
$pathinfo = $request->getPathInfo();
+
+ foreach ($this->storageRouterEnhancerPlugins as $storageRouterEnhancerPlugin) {
+ $pathinfo = $storageRouterEnhancerPlugin->beforeMatch($pathinfo, $requestContext);
+ }
+
if ($pathinfo !== '/') {
$localeName = $request->attributes->get('_locale');
$urlDetails = $this->urlStorageClient->matchUrl($pathinfo, $localeName);
if ($urlDetails) {
+ foreach ($this->storageRouterEnhancerPlugins as $storageRouterEnhancerPlugin) {
+ $urlDetails = $storageRouterEnhancerPlugin->afterMatch($urlDetails, $requestContext);
+ }
+ $urlDetails[static::ATTRIBUTE_PATH_INFO] = $pathinfo;
+
return $urlDetails;
}
}
diff --git a/src/SprykerShop/Yves/StorageRouter/RouteEnhancer/ControllerRouteEnhancer.php b/src/SprykerShop/Yves/StorageRouter/RouteEnhancer/ControllerRouteEnhancer.php
index d32f7c7..0a25507 100644
--- a/src/SprykerShop/Yves/StorageRouter/RouteEnhancer/ControllerRouteEnhancer.php
+++ b/src/SprykerShop/Yves/StorageRouter/RouteEnhancer/ControllerRouteEnhancer.php
@@ -16,6 +16,16 @@
class ControllerRouteEnhancer implements RouteEnhancerInterface
{
+ /**
+ * @var string
+ */
+ protected const ATTRIBUTE_PATH_INFO = 'pathinfo';
+
+ /**
+ * @var string
+ */
+ protected const ATTRIBUTE_DATA = 'data';
+
/**
* @var array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\ResourceCreatorPluginInterface>
*/
@@ -39,7 +49,10 @@ public function enhance(array $defaults, Request $request): array
{
foreach ($this->resourceCreatorPlugins as $resourceCreator) {
if ($defaults['type'] === $resourceCreator->getType()) {
- return $this->createResource($resourceCreator, $defaults['data']);
+ $resource = $this->createResource($resourceCreator, $defaults[static::ATTRIBUTE_DATA]);
+ $resource[static::ATTRIBUTE_PATH_INFO] = $defaults[static::ATTRIBUTE_PATH_INFO];
+
+ return $resource;
}
}
diff --git a/src/SprykerShop/Yves/StorageRouter/StorageRouterConfig.php b/src/SprykerShop/Yves/StorageRouter/StorageRouterConfig.php
index 2c40aba..80586ad 100644
--- a/src/SprykerShop/Yves/StorageRouter/StorageRouterConfig.php
+++ b/src/SprykerShop/Yves/StorageRouter/StorageRouterConfig.php
@@ -8,7 +8,38 @@
namespace SprykerShop\Yves\StorageRouter;
use Spryker\Yves\Kernel\AbstractBundleConfig;
+use SprykerShop\Shared\StorageRouter\StorageRouterConstants;
class StorageRouterConfig extends AbstractBundleConfig
{
+ /**
+ * Specification:
+ * - Returns a list of supported stores for Route manipulation.
+ * - Will be used to strip of store information from a route before a route is matched.
+ *
+ * @api
+ *
+ * @example Incoming URL `/DE/home` will be manipulated to `/home` because the router only knows URL's without any optional pre/suffix.
+ *
+ * @see \Spryker\Yves\Router\Plugin\RouterEnhancer\StorePrefixRouterEnhancerPlugin
+ *
+ * @return array
+ */
+ public function getAllowedStores(): array
+ {
+ return [];
+ }
+
+ /**
+ * Specification:
+ * - Returns true if the store routing is enabled.
+ *
+ * @api
+ *
+ * @return bool
+ */
+ public function isStoreRoutingEnabled(): bool
+ {
+ return $this->get(StorageRouterConstants::IS_STORE_ROUTING_ENABLED, false);
+ }
}
diff --git a/src/SprykerShop/Yves/StorageRouter/StorageRouterDependencyProvider.php b/src/SprykerShop/Yves/StorageRouter/StorageRouterDependencyProvider.php
index d5ecffe..b1ca0c7 100644
--- a/src/SprykerShop/Yves/StorageRouter/StorageRouterDependencyProvider.php
+++ b/src/SprykerShop/Yves/StorageRouter/StorageRouterDependencyProvider.php
@@ -10,6 +10,7 @@
use Spryker\Yves\Kernel\AbstractBundleDependencyProvider;
use Spryker\Yves\Kernel\Container;
use SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToUrlStorageClientBridge;
+use SprykerShop\Yves\StorageRouter\Dependency\Client\StorageStorageRouterToStoreClientBridge;
/**
* @method \SprykerShop\Yves\StorageRouter\StorageRouterConfig getConfig()
@@ -26,6 +27,16 @@ class StorageRouterDependencyProvider extends AbstractBundleDependencyProvider
*/
public const PLUGIN_RESOURCE_CREATORS = 'PLUGIN_RESOURCE_CREATORS';
+ /**
+ * @var string
+ */
+ public const PLUGINS_ROUTER_ENHANCER = 'PLUGINS_ROUTER_ENHANCER';
+
+ /**
+ * @var string
+ */
+ public const CLIENT_STORE = 'CLIENT_STORE';
+
/**
* @param \Spryker\Yves\Kernel\Container $container
*
@@ -35,6 +46,8 @@ public function provideDependencies(Container $container)
{
$container = $this->addUrlStorageClient($container);
$container = $this->addResourceCreatorPlugins($container);
+ $container = $this->addStorageRouterEnhancerPlugins($container);
+ $container = $this->addStoreClient($container);
return $container;
}
@@ -67,6 +80,20 @@ protected function addResourceCreatorPlugins(Container $container): Container
return $container;
}
+ /**
+ * @param \Spryker\Yves\Kernel\Container $container
+ *
+ * @return \Spryker\Yves\Kernel\Container
+ */
+ protected function addStorageRouterEnhancerPlugins(Container $container): Container
+ {
+ $container->set(static::PLUGINS_ROUTER_ENHANCER, function () {
+ return $this->getStorageRouterEnhancerPlugins();
+ });
+
+ return $container;
+ }
+
/**
* @return array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\ResourceCreatorPluginInterface>
*/
@@ -74,4 +101,26 @@ protected function getResourceCreatorPlugins()
{
return [];
}
+
+ /**
+ * @return array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface>
+ */
+ protected function getStorageRouterEnhancerPlugins(): 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 StorageStorageRouterToStoreClientBridge($container->getLocator()->store()->client());
+ });
+
+ return $container;
+ }
}
diff --git a/src/SprykerShop/Yves/StorageRouter/StorageRouterFactory.php b/src/SprykerShop/Yves/StorageRouter/StorageRouterFactory.php
index 5d00cbe..8a2cced 100644
--- a/src/SprykerShop/Yves/StorageRouter/StorageRouterFactory.php
+++ b/src/SprykerShop/Yves/StorageRouter/StorageRouterFactory.php
@@ -8,6 +8,7 @@
namespace SprykerShop\Yves\StorageRouter;
use Spryker\Yves\Kernel\AbstractFactory;
+use SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToStoreClientInterface;
use SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToUrlStorageClientInterface;
use SprykerShop\Yves\StorageRouter\ParameterMerger\ParameterMerger;
use SprykerShop\Yves\StorageRouter\ParameterMerger\ParameterMergerInterface;
@@ -53,6 +54,7 @@ public function createRequestMatcher(): RequestMatcherInterface
{
return new StorageRequestMatcher(
$this->getUrlStorageClient(),
+ $this->getStorageRouterEnhancerPlugins(),
);
}
@@ -64,6 +66,7 @@ public function createUrlGenerator(): UrlGeneratorInterface
return new StorageUrlGenerator(
$this->getUrlStorageClient(),
$this->createParameterMerger(),
+ $this->getStorageRouterEnhancerPlugins(),
);
}
@@ -90,4 +93,20 @@ public function createParameterMerger(): ParameterMergerInterface
{
return new ParameterMerger();
}
+
+ /**
+ * @return array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface>
+ */
+ public function getStorageRouterEnhancerPlugins(): array
+ {
+ return $this->getProvidedDependency(StorageRouterDependencyProvider::PLUGINS_ROUTER_ENHANCER);
+ }
+
+ /**
+ * @return \SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToStoreClientInterface
+ */
+ public function getStoreClient(): StorageRouterToStoreClientInterface
+ {
+ return $this->getProvidedDependency(StorageRouterDependencyProvider::CLIENT_STORE);
+ }
}
diff --git a/src/SprykerShop/Yves/StorageRouter/UrlGenerator/StorageUrlGenerator.php b/src/SprykerShop/Yves/StorageRouter/UrlGenerator/StorageUrlGenerator.php
index fed2c4f..878db12 100644
--- a/src/SprykerShop/Yves/StorageRouter/UrlGenerator/StorageUrlGenerator.php
+++ b/src/SprykerShop/Yves/StorageRouter/UrlGenerator/StorageUrlGenerator.php
@@ -31,14 +31,24 @@ class StorageUrlGenerator implements UrlGeneratorInterface
*/
protected $parameterMerger;
+ /**
+ * @var array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface>
+ */
+ protected array $storageRouterEnhancerPlugins;
+
/**
* @param \SprykerShop\Yves\StorageRouter\Dependency\Client\StorageRouterToUrlStorageClientInterface $urlStorageClient
* @param \SprykerShop\Yves\StorageRouter\ParameterMerger\ParameterMergerInterface $parameterMerger
+ * @param array<\SprykerShop\Yves\StorageRouterExtension\Dependency\Plugin\StorageRouterEnhancerPluginInterface> $storageRouterEnhancerPlugins
*/
- public function __construct(StorageRouterToUrlStorageClientInterface $urlStorageClient, ParameterMergerInterface $parameterMerger)
- {
+ public function __construct(
+ StorageRouterToUrlStorageClientInterface $urlStorageClient,
+ ParameterMergerInterface $parameterMerger,
+ array $storageRouterEnhancerPlugins
+ ) {
$this->urlStorageClient = $urlStorageClient;
$this->parameterMerger = $parameterMerger;
+ $this->storageRouterEnhancerPlugins = $storageRouterEnhancerPlugins;
}
/**
@@ -71,10 +81,17 @@ public function getContext(): RequestContext
public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
{
$localeName = $this->getContext()->getParameter('_locale');
+ foreach ($this->storageRouterEnhancerPlugins as $storageRouterEnhancerPlugin) {
+ $name = $storageRouterEnhancerPlugin->beforeMatch($name, $this->getContext());
+ }
if (!$this->urlStorageClient->matchUrl($name, $localeName)) {
throw new RouteNotFoundException();
}
+ foreach ($this->storageRouterEnhancerPlugins as $storageRouterEnhancerPlugin) {
+ $storageRouterEnhancerPlugin->afterMatch([], $this->getContext());
+ }
+
parse_str($this->getContext()->getQueryString(), $requestParameter);
$queryString = http_build_query($this->parameterMerger->mergeParameters($requestParameter, $parameters));
@@ -83,7 +100,13 @@ public function generate(string $name, array $parameters = [], int $referenceTyp
$name .= '?' . $queryString;
}
- return $this->getUrlOrPathForType($name, $referenceType);
+ $url = $this->getUrlOrPathForType($name, $referenceType);
+
+ foreach (array_reverse($this->storageRouterEnhancerPlugins) as $storageRouterEnhancerPlugin) {
+ $url = $storageRouterEnhancerPlugin->afterGenerate($url, $this->getContext(), $referenceType);
+ }
+
+ return $url;
}
/**