vendor/shopware/core/Framework/DataAbstractionLayer/Search/Parser/SqlQueryParser.php line 285

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\DataAbstractionLayer\Search\Parser;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\Context;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
  6. use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Field\IdField;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Field\ListField;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\Filter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\PrefixFilter;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\SingleFieldFilter;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\SuffixFilter;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Query\ScoreQuery;
  21. use Shopware\Core\Framework\Log\Package;
  22. use Shopware\Core\Framework\Uuid\Uuid;
  23. /**
  24.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will be internal
  25.  */
  26. #[Package('core')]
  27. class SqlQueryParser
  28. {
  29.     /**
  30.      * @var EntityDefinitionQueryHelper
  31.      */
  32.     private $queryHelper;
  33.     /**
  34.      * @var Connection
  35.      */
  36.     private $connection;
  37.     /**
  38.      * @internal
  39.      */
  40.     public function __construct(EntityDefinitionQueryHelper $queryHelperConnection $connection)
  41.     {
  42.         $this->queryHelper $queryHelper;
  43.         $this->connection $connection;
  44.     }
  45.     public function parseRanking(
  46.         array $queries,
  47.         EntityDefinition $definition,
  48.         string $root,
  49.         Context $context
  50.     ): ParseResult {
  51.         $result = new ParseResult();
  52.         /** @var ScoreQuery $query */
  53.         foreach ($queries as $query) {
  54.             $parsed $this->parse($query->getQuery(), $definition$context$root);
  55.             foreach ($parsed->getWheres() as $where) {
  56.                 if ($query->getScoreField()) {
  57.                     $field $this->queryHelper->getFieldAccessor(
  58.                         $query->getScoreField(),
  59.                         $definition,
  60.                         $root,
  61.                         $context
  62.                     );
  63.                     $result->addWhere(
  64.                         sprintf('IF(%s , %s * %s, 0)'$where$this->connection->quote($query->getScore()), $field)
  65.                     );
  66.                     continue;
  67.                 }
  68.                 $result->addWhere(
  69.                     sprintf('IF(%s , %s, 0)'$where$this->connection->quote($query->getScore()))
  70.                 );
  71.             }
  72.             foreach ($parsed->getParameters() as $key => $parameter) {
  73.                 $result->addParameter($key$parameter$parsed->getType($key));
  74.             }
  75.         }
  76.         return $result;
  77.     }
  78.     public function parse(
  79.         Filter $query,
  80.         EntityDefinition $definition,
  81.         Context $context,
  82.         ?string $root null,
  83.         bool $negated false
  84.     ): ParseResult {
  85.         if ($root === null) {
  86.             $root $definition->getEntityName();
  87.         }
  88.         if ($query instanceof SingleFieldFilter && $query->getResolved()) {
  89.             $result = new ParseResult();
  90.             $result->addWhere((string) $query->getResolved());
  91.             return $result;
  92.         }
  93.         switch (true) {
  94.             case $query instanceof EqualsFilter:
  95.                 return $this->parseEqualsFilter($query$definition$root$context$negated);
  96.             case $query instanceof EqualsAnyFilter:
  97.                 return $this->parseEqualsAnyFilter($query$definition$root$context);
  98.             case $query instanceof ContainsFilter:
  99.                 return $this->parseContainsFilter($query$definition$root$context);
  100.             case $query instanceof PrefixFilter:
  101.                 return $this->parsePrefixFilter($query$definition$root$context);
  102.             case $query instanceof SuffixFilter:
  103.                 return $this->parseSuffixFilter($query$definition$root$context);
  104.             case $query instanceof RangeFilter:
  105.                 return $this->parseRangeFilter($query$definition$root$context);
  106.             case $query instanceof NotFilter:
  107.                 return $this->parseNotFilter($query$definition$root$context);
  108.             case $query instanceof MultiFilter:
  109.                 return $this->parseMultiFilter($query$definition$root$context$negated);
  110.             default:
  111.                 throw new \RuntimeException(sprintf('Unsupported query %s'\get_class($query)));
  112.         }
  113.     }
  114.     private function parseRangeFilter(
  115.         RangeFilter $query,
  116.         EntityDefinition $definition,
  117.         string $root,
  118.         Context $context
  119.     ): ParseResult {
  120.         $result = new ParseResult();
  121.         $key $this->getKey();
  122.         $field $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  123.         $where = [];
  124.         if ($query->hasParameter(RangeFilter::GT)) {
  125.             $where[] = $field ' > :' $key;
  126.             $result->addParameter($key$query->getParameter(RangeFilter::GT));
  127.         } elseif ($query->hasParameter(RangeFilter::GTE)) {
  128.             $where[] = $field ' >= :' $key;
  129.             $result->addParameter($key$query->getParameter(RangeFilter::GTE));
  130.         }
  131.         $key $this->getKey();
  132.         if ($query->hasParameter(RangeFilter::LT)) {
  133.             $where[] = $field ' < :' $key;
  134.             $result->addParameter($key$query->getParameter(RangeFilter::LT));
  135.         } elseif ($query->hasParameter(RangeFilter::LTE)) {
  136.             $where[] = $field ' <= :' $key;
  137.             $result->addParameter($key$query->getParameter(RangeFilter::LTE));
  138.         }
  139.         $where '(' implode(' AND '$where) . ')';
  140.         $result->addWhere($where);
  141.         return $result;
  142.     }
  143.     private function parseContainsFilter(ContainsFilter $queryEntityDefinition $definitionstring $rootContext $context): ParseResult
  144.     {
  145.         $key $this->getKey();
  146.         $field $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  147.         $result = new ParseResult();
  148.         $result->addWhere($field ' LIKE :' $key);
  149.         $escaped addcslashes($query->getValue(), '\\_%');
  150.         $result->addParameter($key'%' $escaped '%');
  151.         return $result;
  152.     }
  153.     private function parsePrefixFilter(PrefixFilter $queryEntityDefinition $definitionstring $rootContext $context): ParseResult
  154.     {
  155.         $key $this->getKey();
  156.         $field $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  157.         $result = new ParseResult();
  158.         $result->addWhere($field ' LIKE :' $key);
  159.         $escaped addcslashes($query->getValue(), '\\_%');
  160.         $result->addParameter($key$escaped '%');
  161.         return $result;
  162.     }
  163.     private function parseSuffixFilter(SuffixFilter $queryEntityDefinition $definitionstring $rootContext $context): ParseResult
  164.     {
  165.         $key $this->getKey();
  166.         $field $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  167.         $result = new ParseResult();
  168.         $result->addWhere($field ' LIKE :' $key);
  169.         $escaped addcslashes($query->getValue(), '\\_%');
  170.         $result->addParameter($key'%' $escaped);
  171.         return $result;
  172.     }
  173.     private function parseEqualsAnyFilter(EqualsAnyFilter $queryEntityDefinition $definitionstring $rootContext $context): ParseResult
  174.     {
  175.         $key $this->getKey();
  176.         $select $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  177.         $field $this->queryHelper->getField($query->getField(), $definition$root);
  178.         $result = new ParseResult();
  179.         if ($field instanceof ListField) {
  180.             if (\is_array($query->getValue())) {
  181.                 $where = [];
  182.                 foreach ($query->getValue() as $value) {
  183.                     $key $this->getKey();
  184.                     $where[] = sprintf('JSON_CONTAINS(%s, JSON_ARRAY(%s))'$select':' $key);
  185.                     $result->addParameter($key$value);
  186.                 }
  187.                 $result->addWhere('(' implode(' OR '$where) . ')');
  188.                 return $result;
  189.             }
  190.             $result->addWhere('JSON_CONTAINS(' $select ', JSON_ARRAY(:' $key '))');
  191.             $result->addParameter($key$query->getValue());
  192.             return $result;
  193.         }
  194.         $result->addWhere($select ' IN (:' $key ')');
  195.         $value array_values($query->getValue());
  196.         if ($field instanceof IdField || $field instanceof FkField) {
  197.             $value array_map(function (string $id) {
  198.                 return Uuid::fromHexToBytes($id);
  199.             }, $value);
  200.         }
  201.         $result->addParameter($key$valueConnection::PARAM_STR_ARRAY);
  202.         return $result;
  203.     }
  204.     private function parseEqualsFilter(EqualsFilter $queryEntityDefinition $definitionstring $rootContext $contextbool $negated): ParseResult
  205.     {
  206.         $key $this->getKey();
  207.         $select $this->queryHelper->getFieldAccessor($query->getField(), $definition$root$context);
  208.         $field $this->queryHelper->getField($query->getField(), $definition$root);
  209.         $result = new ParseResult();
  210.         if ($field instanceof ListField) {
  211.             $result->addWhere('JSON_CONTAINS(' $select ', JSON_ARRAY(:' $key '))');
  212.             $result->addParameter($key$query->getValue());
  213.             return $result;
  214.         }
  215.         if ($negated || $query->getValue() === null) {
  216.             $result->addWhere($select ' <=> :' $key);
  217.         } else {
  218.             $result->addWhere($select ' = :' $key);
  219.         }
  220.         $value $query->getValue();
  221.         if ($value === null) {
  222.             $result->addParameter($keynull);
  223.             return $result;
  224.         }
  225.         if ($field instanceof IdField || $field instanceof FkField) {
  226.             $value Uuid::fromHexToBytes($value);
  227.         }
  228.         $result->addParameter($key$value);
  229.         return $result;
  230.     }
  231.     private function parseMultiFilter(MultiFilter $queryEntityDefinition $definitionstring $rootContext $contextbool $negated): ParseResult
  232.     {
  233.         $result $this->iterateNested($query$definition$root$context$negated);
  234.         $wheres $result->getWheres();
  235.         $result->resetWheres();
  236.         $glue ' ' $query->getOperator() . ' ';
  237.         if (!empty($wheres)) {
  238.             $result->addWhere('(' implode($glue$wheres) . ')');
  239.         }
  240.         return $result;
  241.     }
  242.     private function parseNotFilter(NotFilter $queryEntityDefinition $definitionstring $rootContext $context): ParseResult
  243.     {
  244.         $result $this->iterateNested($query$definition$root$contexttrue);
  245.         $wheres $result->getWheres();
  246.         $result->resetWheres();
  247.         $glue ' ' $query->getOperator() . ' ';
  248.         if (!empty($wheres)) {
  249.             $result->addWhere('NOT (' implode($glue$wheres) . ')');
  250.         }
  251.         return $result;
  252.     }
  253.     private function iterateNested(MultiFilter $queryEntityDefinition $definitionstring $rootContext $contextbool $negated): ParseResult
  254.     {
  255.         $result = new ParseResult();
  256.         foreach ($query->getQueries() as $multiFilter) {
  257.             $result $result->merge(
  258.                 $this->parse($multiFilter$definition$context$root$negated)
  259.             );
  260.         }
  261.         return $result;
  262.     }
  263.     private function getKey(): string
  264.     {
  265.         return 'param_' Uuid::randomHex();
  266.     }
  267. }