From 5109227b2588d3d0e3edbb5687249d4c01f0770a Mon Sep 17 00:00:00 2001 From: Alexey Skobkin Date: Mon, 21 Oct 2019 00:29:08 +0300 Subject: [PATCH] Using DQL 'ILIKE' implementation instead of 'LIKE' for search. --- config/packages/doctrine.yaml | 3 ++ src/Doctrine/ORM/AST/BaseFunction.php | 73 +++++++++++++++++++++++++++ src/Doctrine/ORM/AST/Ilike.php | 25 +++++++++ src/Search/TorrentSearcher.php | 2 +- 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/Doctrine/ORM/AST/BaseFunction.php create mode 100644 src/Doctrine/ORM/AST/Ilike.php diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index d250885..2f4a930 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -41,3 +41,6 @@ doctrine: dir: '%kernel.project_dir%/src/Magnetico/Entity' prefix: 'App\Magnetico' alias: Magnetico + dql: + string_functions: + ILIKE: 'App\Doctrine\ORM\AST\Ilike' diff --git a/src/Doctrine/ORM/AST/BaseFunction.php b/src/Doctrine/ORM/AST/BaseFunction.php new file mode 100644 index 0000000..722ee13 --- /dev/null +++ b/src/Doctrine/ORM/AST/BaseFunction.php @@ -0,0 +1,73 @@ + + * @see https://github.com/martin-georgiev/postgresql-for-doctrine + */ +abstract class BaseFunction extends FunctionNode +{ + /** @var string */ + protected $functionPrototype; + + /** @var string[] */ + protected $nodesMapping = []; + + /** @var Node[] */ + protected $nodes = []; + + abstract protected function customiseFunction(): void; + + protected function setFunctionPrototype(string $functionPrototype): void + { + $this->functionPrototype = $functionPrototype; + } + + protected function addNodeMapping(string $parserMethod): void + { + $this->nodesMapping[] = $parserMethod; + } + + public function parse(Parser $parser): void + { + $this->customiseFunction(); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->feedParserWithNodes($parser); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + /** + * Feeds given parser with previously set nodes. + */ + protected function feedParserWithNodes(Parser $parser): void + { + $nodesMappingCount = \count($this->nodesMapping); + $lastNode = $nodesMappingCount - 1; + for ($i = 0; $i < $nodesMappingCount; $i++) { + $parserMethod = $this->nodesMapping[$i]; + $this->nodes[$i] = $parser->{$parserMethod}(); + if ($i < $lastNode) { + $parser->match(Lexer::T_COMMA); + } + } + } + + public function getSql(SqlWalker $sqlWalker): string + { + $dispatched = []; + foreach ($this->nodes as $node) { + $dispatched[] = $node->dispatch($sqlWalker); + } + + return \vsprintf($this->functionPrototype, $dispatched); + } +} \ No newline at end of file diff --git a/src/Doctrine/ORM/AST/Ilike.php b/src/Doctrine/ORM/AST/Ilike.php new file mode 100644 index 0000000..b9c374c --- /dev/null +++ b/src/Doctrine/ORM/AST/Ilike.php @@ -0,0 +1,25 @@ + + * @see https://github.com/martin-georgiev/postgresql-for-doctrine + */ +class Ilike extends BaseFunction +{ + protected function customiseFunction(): void + { + $this->setFunctionPrototype('%s ilike %s'); + $this->addNodeMapping('StringPrimary'); + $this->addNodeMapping('StringPrimary'); + } +} diff --git a/src/Search/TorrentSearcher.php b/src/Search/TorrentSearcher.php index 09fe611..f506774 100644 --- a/src/Search/TorrentSearcher.php +++ b/src/Search/TorrentSearcher.php @@ -39,7 +39,7 @@ class TorrentSearcher $where = $qb->expr()->andX(); foreach ($this->splitQueryToParts($query) as $idx => $part) { - $where->add($qb->expr()->like('LOWER(t.name)', ':part_'.$idx)); + $where->add('ILIKE(t.name , :part_'.$idx.') = TRUE'); $qb->setParameter('part_'.$idx, '%'.strtolower($part).'%'); }