custom/plugins/ScopPlatformRedirecter/src/Subscriber/RequestSubscriber.php line 70

Open in your IDE?
  1. <?php
  2. /**
  3.  * Implemented by scope01 GmbH team https://scope01.com
  4.  *
  5.  * @copyright scope01 GmbH https://scope01.com
  6.  * @license MIT License
  7.  * @link https://scope01.com
  8.  */
  9. declare(strict_types=1);
  10. /**
  11.  * Implemented by scope01 GmbH team https://scope01.com
  12.  *
  13.  * @copyright scope01 GmbH https://scope01.com
  14.  * @license MIT
  15.  * @link https://scope01.com
  16.  */
  17. namespace Scop\PlatformRedirecter\Subscriber;
  18. use Shopware\Core\Framework\Context;
  19. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  23. use Shopware\Core\Framework\Event\BeforeSendRedirectResponseEvent;
  24. use Shopware\Core\Framework\Event\BeforeSendResponseEvent;
  25. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  26. use Symfony\Component\HttpFoundation\RedirectResponse;
  27. class RequestSubscriber implements EventSubscriberInterface
  28. {
  29.     /**
  30.      * @var EntityRepositoryInterface
  31.      */
  32.     private $repository;
  33.     /**
  34.      * @var EntityRepositoryInterface
  35.      */
  36.     private $seoUrlRepository;
  37.     /**
  38.      * @param EntityRepositoryInterface $redirectRepository
  39.      */
  40.     public function __construct(EntityRepositoryInterface $redirectRepositoryEntityRepositoryInterface $seoUrlRepository)
  41.     {
  42.         /** @var EntityRepositoryInterface $repository */
  43.         $this->repository $redirectRepository;
  44.         $this->seoUrlRepository $seoUrlRepository;
  45.     }
  46.     /**
  47.      *
  48.      * @return array
  49.      */
  50.     public static function getSubscribedEvents(): array
  51.     {
  52.         return [
  53.             BeforeSendResponseEvent::class => 'redirectBeforeSendResponse',
  54.             BeforeSendRedirectResponseEvent::class => 'redirectBeforeSendResponse'
  55.         ];
  56.     }
  57.     /**
  58.      * Redirect to the new url if found in redirects
  59.      * Otherwise do nothing
  60.      * Modules like admin, api or widgets are excluded from redirects
  61.      *
  62.      * @param BeforeSendResponseEvent $event
  63.      */
  64.     public function redirectBeforeSendResponse(BeforeSendResponseEvent $event): void
  65.     {
  66.         $requestUri = (string)$event->getRequest()->get("sw-original-request-uri");
  67.         // "sw-original-request-uri" is not present in shopware versions below 6.4.0.0.
  68.         // In this case, an older method must be used for redirecting, which doesn't redirects correctly in some edge cases.
  69.         if ($requestUri === "") {
  70.             $this->oldRedirectBeforeSendResponse($event);
  71.             return;
  72.         }
  73.         $storefrontUri $event->getRequest()->get('sw-sales-channel-absolute-base-url');
  74.         $requestBase $event->getRequest()->getPathInfo();
  75.         $requestBaseUrl $event->getRequest()->getBaseUrl();
  76.         // Block overriding /admin and /api and widgets, so you can't lock out of the administration.
  77.         if (\strpos($requestBase"/admin") === 0) {
  78.             return;
  79.         }
  80.         if (\strpos($requestBase"/api") === 0) {
  81.             return;
  82.         }
  83.         if (\strpos($requestBase"/widgets") === 0) {
  84.             return;
  85.         }
  86.         if (\strpos($requestBase"/store-api") === 0) {
  87.             return;
  88.         }
  89.         if (\strpos($requestBase"/_profiler") === 0) {
  90.             return;
  91.         }
  92.         $context Context::createDefaultContext();
  93.         $search = [
  94.             $requestBaseUrl '/' $requestUri// relative url with shopware 6 in sub folder: /public/Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53
  95.             $requestBaseUrl $requestUri// relative url with shopware 6 in sub folder url is not shopware seo url: /public/test
  96.             $storefrontUri $requestUri// absolute url with shopware 6 in sub folder, full url with host: http://shopware-platform.local/public/test1
  97.             $storefrontUri '/' $requestUri// absolute url with shopware 6 in sub folder, full url with host and slash at the end: http://shopware-platform.local/public/Freizeit-Elektro/Telefone/
  98.             $requestUri// relative url domain configured in public folder: /Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53 or /test4
  99.             '/' $requestUri// absolute url domain configured in public folder: http://shopware-platform.local/Shoes-Baby/
  100.             \substr($requestUri1), // e.g. "test"
  101.         ];
  102.         // search for the redirect in the database
  103.         $redirects $this->repository->search((new Criteria())->addFilter(new EqualsAnyFilter('sourceURL'$search))->addFilter(new EqualsFilter('enabled'true))
  104.             ->setLimit(1), $context);
  105.         if ($redirects->count() === 0) {
  106.             // Checks if the requested URL contains Query parameters, and if so, checks if a redirect can be found with the ignoreQueryParams option
  107.             if(str_contains($requestUri'?')) {
  108.                 $searchWithoutQuery = [];
  109.                 foreach ($search as $string)
  110.                     $searchWithoutQuery[] = explode('?'$string)[0];
  111.                 $redirects $this->repository->search((new Criteria())->addFilter(new EqualsAnyFilter('sourceURL'$searchWithoutQuery))->addFilter(new EqualsFilter('enabled'true))->addFilter(new EqualsFilter('ignoreQueryParams'true))
  112.                     ->setLimit(1), $context);
  113.                 // No Redirect found for this URL, do nothing
  114.                 if ($redirects->count() === 0) {
  115.                     return;
  116.                 }
  117.             } else {
  118.                 // No Redirect found for this URL, do nothing
  119.                 return;
  120.             }
  121.         }
  122.         $redirect $redirects->first();
  123.         $targetURL $redirect->getTargetURL();
  124.         $code $redirect->getHttpCode();
  125.         // Prevent endless redirecting when target url and source url have only different capitalisation
  126.         if (in_array($targetURL$searchtrue)) {
  127.             return;
  128.         }
  129.         /*
  130.          *  checks if $targetURL is a full url or path and redirects accordingly
  131.          */
  132.         if (!(\strpos($targetURL"http:") === || \strpos($targetURL"https:") === 0)) {
  133.             if (\strpos($targetURL"www.") === 0) {
  134.                 $targetURL "http://" $targetURL;
  135.             } else {
  136.                 if (\strpos($targetURL"/") !== 0) {
  137.                     $targetURL "/" $targetURL;
  138.                 }
  139.             }
  140.         }
  141.         $event->setResponse(new RedirectResponse($targetURL$code));
  142.     }
  143.     /**
  144.      * Method for shopware versions below 6.4.0.0
  145.      *
  146.      * Redirect to the new url if found in redirects
  147.      * Otherwise do nothing
  148.      * Modules like admin, api or widgets are excluded from redirects
  149.      *
  150.      * @param BeforeSendResponseEvent $event
  151.      */
  152.     private function oldRedirectBeforeSendResponse(BeforeSendResponseEvent $event): void
  153.     {
  154.         $requestUri = (string)$event->getRequest()->get('resolved-uri');
  155.         $storefrontUri $event->getRequest()->get('sw-storefront-url');
  156.         $requestBase $event->getRequest()->getPathInfo();
  157.         $requestBaseUrl $event->getRequest()->getBaseUrl();
  158.         $queryString = (string)$event->getRequest()->getQueryString();
  159.         $search = [];
  160.         // Block overriding /admin and /api and widgets, so you can't lock out of the administration.
  161.         if (\strpos($requestBase"/admin") === 0) {
  162.             return;
  163.         }
  164.         if (\strpos($requestBase"/api") === 0) {
  165.             return;
  166.         }
  167.         if (\strpos($requestBase"/widgets") === 0) {
  168.             return;
  169.         }
  170.         if (\strpos($requestBase"/store-api") === 0) {
  171.             return;
  172.         }
  173.         if (\strpos($requestBase"/_profiler") === 0) {
  174.             return;
  175.         }
  176.         if ($queryString !== '') {
  177.             $queryString urldecode($queryString);
  178.             $requestUri .= '?' $queryString;
  179.         }
  180.         // try to load the seo route
  181.         $context Context::createDefaultContext();
  182.         $redirects $this->seoUrlRepository->search((new Criteria())
  183.             ->addFilter(new EqualsAnyFilter('pathInfo', [$requestUri])), $context);
  184.         // if found overwrite search term with the seo route
  185.         if ($redirects->count() !== 0) {
  186.             foreach ($redirects as $redirect) {
  187.                 $requestBase $redirect->getSeoPathInfo();
  188.                 // Search for Redirect
  189.                 $search[] = [
  190.                     $requestBaseUrl '/' $requestBase// relative url with shopware 6 in sub folder: /public/Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53
  191.                     $requestBaseUrl $requestBase// relative url with shopware 6 in sub folder url is not shopware seo url: /public/test
  192.                     $storefrontUri $requestBase// absolute url with shopware 6 in sub folder, full url with host: http://shopware-platform.local/public/test1
  193.                     $storefrontUri '/' $requestBase// absolute url with shopware 6 in sub folder, full url with host and slash at the end: http://shopware-platform.local/public/Freizeit-Elektro/Telefone/
  194.                     $requestBase// relative url domain configured in public folder: /Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53 or /test4
  195.                     '/' $requestBase// absolute url domain configured in public folder: http://shopware-platform.local/Shoes-Baby/
  196.                     \substr($requestBase1), // e.g. "test"
  197.                 ];
  198.             }
  199.         }
  200.         if (!empty($search)) {
  201.             $search array_merge(...$search);
  202.         } else {
  203.             $search = [
  204.                 $requestBaseUrl '/' $requestUri// relative url with shopware 6 in sub folder: /public/Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53
  205.                 $requestBaseUrl $requestUri// relative url with shopware 6 in sub folder url is not shopware seo url: /public/test
  206.                 $storefrontUri $requestUri// absolute url with shopware 6 in sub folder, full url with host: http://shopware-platform.local/public/test1
  207.                 $storefrontUri '/' $requestUri// absolute url with shopware 6 in sub folder, full url with host and slash at the end: http://shopware-platform.local/public/Freizeit-Elektro/Telefone/
  208.                 $requestUri// relative url domain configured in public folder: /Ergonomic-Concrete-Cough-Machine/48314803f1244f609a2ce907bfb48f53 or /test4
  209.                 '/' $requestUri// absolute url domain configured in public folder: http://shopware-platform.local/Shoes-Baby/
  210.                 \substr($requestUri1), // e.g. "test"
  211.             ];
  212.         }
  213.         // search for the redirect in the database
  214.         $redirects $this->repository->search((new Criteria())->addFilter(new EqualsAnyFilter('sourceURL'$search))->addFilter(new EqualsFilter('enabled'true))
  215.             ->setLimit(1), $context);
  216.         if ($redirects->count() === 0) {
  217.             // Checks if the requested URL contains Query parameters, and if so, checks if a redirect can be found with the ignoreQueryParams option
  218.             if(str_contains($requestUri'?')) {
  219.                 $searchWithoutQuery = [];
  220.                 foreach ($search as $string)
  221.                     $searchWithoutQuery[] = explode('?'$string)[0];
  222.                 $redirects $this->repository->search((new Criteria())->addFilter(new EqualsAnyFilter('sourceURL'$searchWithoutQuery))->addFilter(new EqualsFilter('enabled'true))->addFilter(new EqualsFilter('ignoreQueryParams'true))
  223.                     ->setLimit(1), $context);
  224.                 // No Redirect found for this URL, do nothing
  225.                 if ($redirects->count() === 0) {
  226.                     return;
  227.                 }
  228.             } else {
  229.                 // No Redirect found for this URL, do nothing
  230.                 return;
  231.             }
  232.         }
  233.         $redirect $redirects->first();
  234.         $targetURL $redirect->getTargetURL();
  235.         $code $redirect->getHttpCode();
  236.         // Prevent endless redirecting when target url belongs to the same seo url like the source url or when target url and source url have only different capitalisation
  237.         if (in_array($targetURL$searchtrue)) {
  238.             return;
  239.         }
  240.         /*
  241.          *  checks if $targetURL is a full url or path and redirects accordingly
  242.          */
  243.         if (!(\strpos($targetURL"http:") === || \strpos($targetURL"https:") === 0)) {
  244.             if (\strpos($targetURL"www.") === 0) {
  245.                 $targetURL "http://" $targetURL;
  246.             } else {
  247.                 if (\strpos($targetURL"/") !== 0) {
  248.                     $targetURL "/" $targetURL;
  249.                 }
  250.             }
  251.         }
  252.         $event->setResponse(new RedirectResponse($targetURL$code));
  253.     }
  254. }