src/Core/Content/Seo/SeoResolver.php line 51

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Seo;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Dbal\QueryBuilder;
  5. use Shopware\Core\Framework\Log\Package;
  6. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  7. use Shopware\Core\Framework\Uuid\Uuid;
  8. /**
  9.  * @phpstan-import-type ResolvedSeoUrl from AbstractSeoResolver
  10.  */
  11. #[Package('sales-channel')]
  12. class SeoResolver extends AbstractSeoResolver
  13. {
  14.     /**
  15.      * @internal
  16.      */
  17.     public function __construct(private readonly Connection $connection)
  18.     {
  19.     }
  20.     public function getDecorated(): AbstractSeoResolver
  21.     {
  22.         throw new DecorationPatternException(self::class);
  23.     }
  24.     /**
  25.      * @return ResolvedSeoUrl
  26.      */
  27.     public function resolve(string $languageIdstring $salesChannelIdstring $pathInfo): array
  28.     {
  29.         $seoPathInfo ltrim($pathInfo'/');
  30.         $query = (new QueryBuilder($this->connection))
  31.             ->select('id''path_info pathInfo''is_canonical isCanonical')
  32.             ->from('seo_url')
  33.             ->where('language_id = :language_id')
  34.             ->andWhere('(sales_channel_id = :sales_channel_id OR sales_channel_id IS NULL)')
  35.             ->andWhere('seo_path_info = :seoPath')
  36.             ->orderBy('seo_path_info')
  37.             ->addOrderBy('sales_channel_id IS NULL'// sales_channel_specific comes first
  38.             ->setMaxResults(1)
  39.             ->setParameter('language_id'Uuid::fromHexToBytes($languageId))
  40.             ->setParameter('sales_channel_id'Uuid::fromHexToBytes($salesChannelId))
  41.             ->setParameter('seoPath'$seoPathInfo);
  42.         $query->setTitle('seo-url::resolve');
  43.         $seoPath $query->executeQuery()->fetchAssociative();
  44.         $seoPath $seoPath !== false
  45.             $seoPath
  46.             : ['pathInfo' => $seoPathInfo'isCanonical' => false];
  47.         if (!$seoPath['isCanonical']) {
  48.             $query $this->connection->createQueryBuilder()
  49.                 ->select('path_info pathInfo''seo_path_info seoPathInfo')
  50.                 ->from('seo_url')
  51.                 ->where('language_id = :language_id')
  52.                 ->andWhere('sales_channel_id = :sales_channel_id')
  53.                 ->andWhere('id != :id')
  54.                 ->andWhere('path_info = :pathInfo')
  55.                 ->andWhere('is_canonical = 1')
  56.                 ->setMaxResults(1)
  57.                 ->setParameter('language_id'Uuid::fromHexToBytes($languageId))
  58.                 ->setParameter('sales_channel_id'Uuid::fromHexToBytes($salesChannelId))
  59.                 ->setParameter('id'$seoPath['id'] ?? '')
  60.                 ->setParameter('pathInfo''/' ltrim((string) $seoPath['pathInfo'], '/'));
  61.             $canonical $query->executeQuery()->fetchAssociative();
  62.             if ($canonical) {
  63.                 $seoPath['canonicalPathInfo'] = '/' ltrim((string) $canonical['seoPathInfo'], '/');
  64.             }
  65.         }
  66.         $seoPath['pathInfo'] = '/' ltrim((string) $seoPath['pathInfo'], '/');
  67.         return $seoPath;
  68.     }
  69. }