vendor/contao/core-bundle/src/EventListener/SearchIndexListener.php line 55

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\CoreBundle\EventListener;
  11. use Contao\CoreBundle\Crawl\Escargot\Factory;
  12. use Contao\CoreBundle\Search\Document;
  13. use Contao\CoreBundle\Search\Indexer\IndexerException;
  14. use Contao\CoreBundle\Search\Indexer\IndexerInterface;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpKernel\Event\TerminateEvent;
  17. /**
  18.  * @internal
  19.  */
  20. class SearchIndexListener
  21. {
  22.     public const FEATURE_INDEX 0b01;
  23.     public const FEATURE_DELETE 0b10;
  24.     /**
  25.      * @var IndexerInterface
  26.      */
  27.     private $indexer;
  28.     /**
  29.      * @var string
  30.      */
  31.     private $fragmentPath;
  32.     /**
  33.      * @var int
  34.      */
  35.     private $enabledFeatures;
  36.     public function __construct(IndexerInterface $indexerstring $fragmentPath '_fragment'int $enabledFeatures self::FEATURE_INDEX self::FEATURE_DELETE)
  37.     {
  38.         $this->indexer $indexer;
  39.         $this->fragmentPath $fragmentPath;
  40.         $this->enabledFeatures $enabledFeatures;
  41.     }
  42.     /**
  43.      * Checks if the request can be indexed and forwards it accordingly.
  44.      */
  45.     public function __invoke(TerminateEvent $event): void
  46.     {
  47.         $request $event->getRequest();
  48.         // Only handle GET requests (see #1194)
  49.         if (!$request->isMethod(Request::METHOD_GET)) {
  50.             return;
  51.         }
  52.         // Do not index if called by crawler
  53.         if (Factory::USER_AGENT === $request->headers->get('User-Agent')) {
  54.             return;
  55.         }
  56.         // Do not handle fragments
  57.         if (preg_match('~(?:^|/)'.preg_quote($this->fragmentPath'~').'/~'$request->getPathInfo())) {
  58.             return;
  59.         }
  60.         $response $event->getResponse();
  61.         // Do not index if the X-Robots-Tag header contains "noindex"
  62.         if (false !== strpos($response->headers->get('X-Robots-Tag'''), 'noindex')) {
  63.             return;
  64.         }
  65.         $document Document::createFromRequestResponse($request$response);
  66.         try {
  67.             $robots $document->getContentCrawler()->filterXPath('//head/meta[@name="robots"]')->first()->attr('content');
  68.             // Do not index if the meta robots tag contains "noindex"
  69.             if (false !== strpos($robots'noindex')) {
  70.                 return;
  71.             }
  72.         } catch (\Exception $e) {
  73.             // No meta robots tag found
  74.         }
  75.         $lds $document->extractJsonLdScripts();
  76.         // If there are no json ld scripts at all, this should not be handled by our indexer
  77.         if (=== \count($lds)) {
  78.             return;
  79.         }
  80.         try {
  81.             $success $event->getResponse()->isSuccessful();
  82.             if ($success && $this->enabledFeatures self::FEATURE_INDEX) {
  83.                 $this->indexer->index($document);
  84.             }
  85.             if (!$success && $this->enabledFeatures self::FEATURE_DELETE) {
  86.                 $this->indexer->delete($document);
  87.             }
  88.         } catch (IndexerException $e) {
  89.             // ignore
  90.         }
  91.     }
  92. }