vendor/shopware/elasticsearch/Framework/ElasticsearchHelper.php line 236

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Elasticsearch\Framework;
  3. use Elasticsearch\Client;
  4. use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
  5. use ONGR\ElasticsearchDSL\Query\FullText\MatchQuery;
  6. use ONGR\ElasticsearchDSL\Search;
  7. use Psr\Log\LoggerInterface;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  13. use Shopware\Core\Framework\Feature;
  14. use Shopware\Elasticsearch\Exception\ServerNotAvailableException;
  15. use Shopware\Elasticsearch\Exception\UnsupportedElasticsearchDefinitionException;
  16. use Shopware\Elasticsearch\Framework\DataAbstractionLayer\CriteriaParser;
  17. class ElasticsearchHelper
  18. {
  19.     // max for default configuration
  20.     public const MAX_SIZE_VALUE 10000;
  21.     private Client $client;
  22.     private ElasticsearchRegistry $registry;
  23.     private CriteriaParser $parser;
  24.     private bool $searchEnabled;
  25.     private bool $indexingEnabled;
  26.     private string $environment;
  27.     private LoggerInterface $logger;
  28.     private string $prefix;
  29.     private bool $throwException;
  30.     /**
  31.      * @internal
  32.      */
  33.     public function __construct(
  34.         string $environment,
  35.         bool $searchEnabled,
  36.         bool $indexingEnabled,
  37.         string $prefix,
  38.         bool $throwException,
  39.         Client $client,
  40.         ElasticsearchRegistry $registry,
  41.         CriteriaParser $parser,
  42.         LoggerInterface $logger
  43.     ) {
  44.         $this->client $client;
  45.         $this->registry $registry;
  46.         $this->parser $parser;
  47.         $this->searchEnabled $searchEnabled;
  48.         $this->indexingEnabled $indexingEnabled;
  49.         $this->environment $environment;
  50.         $this->logger $logger;
  51.         $this->prefix $prefix;
  52.         $this->throwException $throwException;
  53.     }
  54.     /**
  55.      * @deprecated tag:v6.5.0 - use logAndThrowException instead
  56.      */
  57.     public function logOrThrowException(\Throwable $exception): bool
  58.     {
  59.         Feature::triggerDeprecationOrThrow(
  60.             'v6.5.0.0',
  61.             Feature::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0''logAndThrowException()')
  62.         );
  63.         return $this->logAndThrowException($exception);
  64.     }
  65.     public function logAndThrowException(\Throwable $exception): bool
  66.     {
  67.         $this->logger->critical($exception->getMessage());
  68.         if ($this->environment === 'test') {
  69.             throw $exception;
  70.         }
  71.         if ($this->throwException) {
  72.             throw $exception;
  73.         }
  74.         return false;
  75.     }
  76.     /**
  77.      * Created the index alias
  78.      */
  79.     public function getIndexName(EntityDefinition $definitionstring $languageId): string
  80.     {
  81.         return $this->prefix '_' $definition->getEntityName() . '_' $languageId;
  82.     }
  83.     public function allowIndexing(): bool
  84.     {
  85.         if (!$this->indexingEnabled) {
  86.             return false;
  87.         }
  88.         if (!$this->client->ping()) {
  89.             return $this->logAndThrowException(new ServerNotAvailableException());
  90.         }
  91.         return true;
  92.     }
  93.     /**
  94.      * Validates if it is allowed do execute the search request over elasticsearch
  95.      */
  96.     public function allowSearch(EntityDefinition $definitionContext $context): bool
  97.     {
  98.         if (!$this->searchEnabled) {
  99.             return false;
  100.         }
  101.         if (!$this->isSupported($definition)) {
  102.             return false;
  103.         }
  104.         if (!$context->hasState(Context::STATE_ELASTICSEARCH_AWARE)) {
  105.             return false;
  106.         }
  107.         return true;
  108.     }
  109.     public function handleIds(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  110.     {
  111.         $ids $criteria->getIds();
  112.         if (empty($ids)) {
  113.             return;
  114.         }
  115.         $query $this->parser->parseFilter(
  116.             new EqualsAnyFilter('id'array_values($ids)),
  117.             $definition,
  118.             $definition->getEntityName(),
  119.             $context
  120.         );
  121.         $search->addQuery($queryBoolQuery::FILTER);
  122.     }
  123.     public function addFilters(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  124.     {
  125.         $filters $criteria->getFilters();
  126.         if (empty($filters)) {
  127.             return;
  128.         }
  129.         $query $this->parser->parseFilter(
  130.             new MultiFilter(MultiFilter::CONNECTION_AND$filters),
  131.             $definition,
  132.             $definition->getEntityName(),
  133.             $context
  134.         );
  135.         $search->addQuery($queryBoolQuery::FILTER);
  136.     }
  137.     public function addPostFilters(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  138.     {
  139.         $postFilters $criteria->getPostFilters();
  140.         if (empty($postFilters)) {
  141.             return;
  142.         }
  143.         $query $this->parser->parseFilter(
  144.             new MultiFilter(MultiFilter::CONNECTION_AND$postFilters),
  145.             $definition,
  146.             $definition->getEntityName(),
  147.             $context
  148.         );
  149.         $search->addPostFilter($queryBoolQuery::FILTER);
  150.     }
  151.     public function addTerm(Criteria $criteriaSearch $searchContext $contextEntityDefinition $definition): void
  152.     {
  153.         if (!$criteria->getTerm()) {
  154.             return;
  155.         }
  156.         $esDefinition $this->registry->get($definition->getEntityName());
  157.         if (!$esDefinition) {
  158.             throw new UnsupportedElasticsearchDefinitionException($definition->getEntityName());
  159.         }
  160.         $query $esDefinition->buildTermQuery($context$criteria);
  161.         $search->addQuery($query);
  162.     }
  163.     public function addQueries(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  164.     {
  165.         $queries $criteria->getQueries();
  166.         if (empty($queries)) {
  167.             return;
  168.         }
  169.         $bool = new BoolQuery();
  170.         foreach ($queries as $query) {
  171.             $parsed $this->parser->parseFilter($query->getQuery(), $definition$definition->getEntityName(), $context);
  172.             if ($parsed instanceof MatchQuery) {
  173.                 $score = (string) $query->getScore();
  174.                 $parsed->addParameter('boost'$score);
  175.                 $parsed->addParameter('fuzziness''2');
  176.             }
  177.             $bool->add($parsedBoolQuery::SHOULD);
  178.         }
  179.         $bool->addParameter('minimum_should_match''1');
  180.         $search->addQuery($bool);
  181.     }
  182.     public function addSortings(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  183.     {
  184.         foreach ($criteria->getSorting() as $sorting) {
  185.             $search->addSort(
  186.                 $this->parser->parseSorting($sorting$definition$context)
  187.             );
  188.         }
  189.     }
  190.     public function addAggregations(EntityDefinition $definitionCriteria $criteriaSearch $searchContext $context): void
  191.     {
  192.         $aggregations $criteria->getAggregations();
  193.         if (empty($aggregations)) {
  194.             return;
  195.         }
  196.         foreach ($aggregations as $aggregation) {
  197.             $agg $this->parser->parseAggregation($aggregation$definition$context);
  198.             if (!$agg) {
  199.                 continue;
  200.             }
  201.             $search->addAggregation($agg);
  202.         }
  203.     }
  204.     /**
  205.      * Only used for unit tests because the container parameter bag is frozen and can not be changed at runtime.
  206.      * Therefore this function can be used to test different behaviours
  207.      *
  208.      * @internal
  209.      */
  210.     public function setEnabled(bool $enabled): self
  211.     {
  212.         $this->searchEnabled $enabled;
  213.         $this->indexingEnabled $enabled;
  214.         return $this;
  215.     }
  216.     public function isSupported(EntityDefinition $definition): bool
  217.     {
  218.         $entityName $definition->getEntityName();
  219.         return $this->registry->has($entityName);
  220.     }
  221. }