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

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