src/Routing/ProductRouter.php line 65

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Routing;
  4. use App\Locale\LocaleResolver;
  5. use App\Provider\ProductProvider;
  6. use Denios\Data\Product\Product;
  7. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  8. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  9. /**
  10. * Router for products
  11. *
  12. * @author Michel Chowanski <michel.chowanski@bestit-online.de>
  13. * @package App\Routing
  14. */
  15. class ProductRouter extends AbstractCommerceRouter
  16. {
  17. /**
  18. * Field for variant sku
  19. *
  20. * @var string
  21. */
  22. public const VARIANT_FIELD = 'variant';
  23. private const CATEGORY_ONLY_SLUG = 'kat';
  24. private ProductProvider $productProvider;
  25. private LocaleResolver $localeResolver;
  26. /**
  27. * ProductRouter constructor.
  28. *
  29. * @param UrlGeneratorInterface $urlGenerator
  30. * @param LocaleResolver $localeResolver
  31. * @param ProductProvider $productProvider
  32. */
  33. public function __construct(
  34. UrlGeneratorInterface $urlGenerator,
  35. LocaleResolver $localeResolver,
  36. ProductProvider $productProvider
  37. ) {
  38. parent::__construct($urlGenerator);
  39. $this->productProvider = $productProvider;
  40. $this->localeResolver = $localeResolver;
  41. }
  42. /**
  43. * @param string $path
  44. * @return array
  45. */
  46. public function match(string $path): array
  47. {
  48. $localeInfo = $this->localeResolver->resolveFromPath($path);
  49. $attributes = [];
  50. $matches = [];
  51. preg_match('#(?<slug>/?[^/]+)(/(?<sku>[\w|-]{6,}))?#i', $localeInfo->getPath(), $matches);
  52. $slug = $matches['slug'] ?? $localeInfo->getPath();
  53. $sku = $matches['sku'] ?? null;
  54. $attributes['sku'] = $sku;
  55. $product = $this->productProvider->getProductBySlug($slug);
  56. if (!$product && $sku && $matches['slug'] !== self::CATEGORY_ONLY_SLUG) {
  57. $product = $this->productProvider->getProductBySku($sku);
  58. if ($product) {
  59. $attributes['redirect'] = true;
  60. }
  61. }
  62. if (!$product) {
  63. throw new ResourceNotFoundException('Path could not be matched.');
  64. }
  65. if ($localeInfo->getCurrentLocale() !== $localeInfo->getDefaultLocale()) {
  66. $attributes['prefix'] = $localeInfo->getPrefix();
  67. }
  68. return $this->route($localeInfo->getCurrentLocale(), $product, $attributes);
  69. }
  70. /**
  71. * Create route params
  72. *
  73. * @param string $locale
  74. * @param Product $product
  75. * @param array $attributes
  76. * @return array
  77. */
  78. protected function route(string $locale, Product $product, array $attributes = []): array
  79. {
  80. $variant = $product->master;
  81. if ($attributes['sku'] !== null) {
  82. $matchedVariants = array_filter($product->variants, static fn($variant) => $variant->sku === $attributes['sku']);
  83. if (count($matchedVariants) === 0) {
  84. throw new ResourceNotFoundException(sprintf('Variant with sku `%s` not found.', $attributes['sku']));
  85. }
  86. $variant = array_shift($matchedVariants);
  87. }
  88. if (array_key_exists('redirect', $attributes) && $attributes['redirect'] === true) {
  89. $controller = 'App\Action\RedirectAction::__invoke';
  90. $prefix = '';
  91. if (array_key_exists('prefix', $attributes)) {
  92. $prefix = '/' . $attributes['prefix'];
  93. }
  94. return [
  95. '_controller' => $controller,
  96. '_locale' => $locale,
  97. 'product' => $product,
  98. 'variant' => $variant,
  99. 'path' => $prefix . '/' . $product->slug . '/' . $attributes['sku'],
  100. 'permanent' => true,
  101. ];
  102. }
  103. if ($product->businessUnit === 'ES') {
  104. $controller = 'App\Action\Product\GetDetailESAction::__invoke';
  105. } else {
  106. $controller = 'App\Action\Product\GetDetailAction::__invoke';
  107. }
  108. return [
  109. '_controller' => $controller,
  110. '_locale' => $locale,
  111. 'product' => $product,
  112. 'variant' => $variant,
  113. ];
  114. }
  115. /**
  116. * Get redis storage prefix
  117. *
  118. * @return string
  119. */
  120. protected function getPrefix(): string
  121. {
  122. return 'product';
  123. }
  124. /**
  125. * Append SKU to path if given
  126. *
  127. * @param array $parameters
  128. * @return array
  129. */
  130. protected function buildPath(array &$parameters): array
  131. {
  132. $values = parent::buildPath($parameters);
  133. if (isset($parameters[self::VARIANT_FIELD])) {
  134. $values[] = $parameters[self::VARIANT_FIELD];
  135. unset($parameters[self::VARIANT_FIELD]);
  136. }
  137. return $values;
  138. }
  139. }