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

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