src/Storefront/Framework/Captcha/CaptchaRouteListener.php line 43

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Framework\Captcha;
  3. use Shopware\Core\Framework\Log\Package;
  4. use Shopware\Core\Framework\Routing\KernelListenerPriorities;
  5. use Shopware\Core\PlatformRequest;
  6. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  7. use Shopware\Core\System\SystemConfig\SystemConfigService;
  8. use Shopware\Storefront\Controller\ErrorController;
  9. use Shopware\Storefront\Framework\Captcha\Exception\CaptchaInvalidException;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  12. use Symfony\Component\HttpKernel\KernelEvents;
  13. /**
  14.  * @internal
  15.  */
  16. #[Package('storefront')]
  17. class CaptchaRouteListener implements EventSubscriberInterface
  18. {
  19.     /**
  20.      * @internal
  21.      *
  22.      * @param iterable<AbstractCaptcha> $captchas
  23.      */
  24.     public function __construct(private readonly iterable $captchas, private readonly ErrorController $errorController, private readonly SystemConfigService $systemConfigService)
  25.     {
  26.     }
  27.     /**
  28.      * {@inheritdoc}
  29.      */
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return [
  33.             KernelEvents::CONTROLLER => [
  34.                 ['validateCaptcha'KernelListenerPriorities::KERNEL_CONTROLLER_EVENT_SCOPE_VALIDATE],
  35.             ],
  36.         ];
  37.     }
  38.     public function validateCaptcha(ControllerEvent $event): void
  39.     {
  40.         /** @var bool $captchaAnnotation */
  41.         $captchaAnnotation $event->getRequest()->attributes->get(PlatformRequest::ATTRIBUTE_CAPTCHAfalse);
  42.         if ($captchaAnnotation === false) {
  43.             return;
  44.         }
  45.         /** @var SalesChannelContext|null $context */
  46.         $context $event->getRequest()->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
  47.         $salesChannelId $context $context->getSalesChannelId() : null;
  48.         $activeCaptchas = (array) ($this->systemConfigService->get('core.basicInformation.activeCaptchasV2'$salesChannelId) ?? []);
  49.         foreach ($this->captchas as $captcha) {
  50.             $captchaConfig $activeCaptchas[$captcha->getName()] ?? [];
  51.             $request $event->getRequest();
  52.             if (
  53.                 $captcha->supports($request$captchaConfig) && !$captcha->isValid($request$captchaConfig)
  54.             ) {
  55.                 if ($captcha->shouldBreak()) {
  56.                     throw new CaptchaInvalidException($captcha);
  57.                 }
  58.                 $violations $captcha->getViolations();
  59.                 $event->setController(fn () => $this->errorController->onCaptchaFailure($violations$request));
  60.                 // Return on first invalid captcha
  61.                 return;
  62.             }
  63.         }
  64.     }
  65. }