vendor/dvdw/events/src/Content/Product/ProductUrlValidator.php line 36

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Dvdw\Events\Content\Product;
  3. use Dvdw\Events\Content\Product\Exception\ProductUrlAlreadyExistsException;
  4. use Dvdw\Events\Content\Product\Exception\ProductUrlInvalidException;
  5. use Shopware\Core\Content\Product\Aggregate\ProductTranslation\ProductTranslationDefinition;
  6. use Shopware\Core\Defaults;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\PrefixFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  15. use Shopware\Core\Framework\Uuid\Uuid;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. class ProductUrlValidator implements EventSubscriberInterface
  18. {
  19.     private EntityRepository $repo;
  20.     public function __construct(
  21.         EntityRepository $repo
  22.     )
  23.     {
  24.         $this->repo $repo;
  25.     }
  26.     public static function getSubscribedEvents(): iterable
  27.     {
  28.         return [PreWriteValidationEvent::class => 'validate'];
  29.     }
  30.     public function validate(PreWriteValidationEvent $event): void
  31.     {
  32.         $context $event->getContext();
  33.         if ($context->getVersionId() !== Defaults::LIVE_VERSION) {
  34.             return;
  35.         }
  36.         foreach ($event->getCommands() as $command) {
  37.             $payload $command->getPayload();
  38.             if (!$command->getDefinition() instanceof ProductTranslationDefinition
  39.                 || ($url $this->getUrlFromPayload($payload)) === null)
  40.             {
  41.                 continue;
  42.             }
  43.             $this->validateUrl($url$contextUuid::fromBytesToHexList($command->getPrimaryKey()));
  44.         }
  45.     }
  46.     private function getUrlFromPayload(array $payload): ?string
  47.     {
  48.         if (isset($payload[ProductCustomFields::WEBSITE_FIELD_NAME])) {
  49.             return $payload[ProductCustomFields::WEBSITE_FIELD_NAME];
  50.         }
  51.         if (!isset($payload['custom_fields'])) {
  52.             return null;
  53.         }
  54.         $customFields json_decode($payload['custom_fields'], true);
  55.         return $customFields[ProductCustomFields::WEBSITE_FIELD_NAME] ?? null;
  56.     }
  57.     private function validateUrl(string $urlContext $context, array $primaryKey): void
  58.     {
  59.         $parsedUrl parse_url($url);
  60.         if (!isset($parsedUrl['host']) || !isset($parsedUrl['scheme']) || $parsedUrl['scheme'] !== 'https') {
  61.             throw new ProductUrlInvalidException($url$primaryKey);
  62.         }
  63.         $criteria = new Criteria();
  64.         $criteria->setLimit(1);
  65.         $criteria->addFilter(new PrefixFilter(
  66.             'customFields.' ProductCustomFields::WEBSITE_FIELD_NAME,
  67.             'https://' $parsedUrl['host']
  68.         ));
  69.         $languageId $primaryKey['language_id'] ?? null;
  70.         if ($languageId !== null) {
  71.             $criteria->addFilter(new EqualsFilter('languageId'$languageId));
  72.         }
  73.         $productId $primaryKey['product_id'] ?? null;
  74.         if ($productId !== null) {
  75.             $criteria->addFilter(new NotFilter(
  76.                 MultiFilter::CONNECTION_AND,
  77.                 [new EqualsFilter('productId'$productId)]
  78.             ));
  79.         }
  80.         if (empty($this->repo->search($criteria$context)->getElements())) {
  81.             return;
  82.         }
  83.         throw new ProductUrlAlreadyExistsException($url$primaryKey);
  84.     }
  85. }