From 367191877747e7a5bd333f0513f6a3130e8bffb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 16 Jan 2017 20:20:43 +0100 Subject: [PATCH] adding custom dql function get_json_field_by_key and jsonaggregate --- DependencyInjection/ChillMainExtension.php | 7 ++- Doctrine/DQL/GetJsonFieldByKey.php | 53 ++++++++++++++++++++++ Doctrine/DQL/JsonAggregate.php | 49 ++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 Doctrine/DQL/GetJsonFieldByKey.php create mode 100644 Doctrine/DQL/JsonAggregate.php diff --git a/DependencyInjection/ChillMainExtension.php b/DependencyInjection/ChillMainExtension.php index feafc9f04..0399cc512 100644 --- a/DependencyInjection/ChillMainExtension.php +++ b/DependencyInjection/ChillMainExtension.php @@ -26,6 +26,9 @@ use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface; use Chill\MainBundle\DependencyInjection\Configuration; +use Chill\MainBundle\Doctrine\DQL\GetJsonFieldByKey; +use Chill\MainBundle\Doctrine\DQL\Unaccent; +use Chill\MainBundle\Doctrine\DQL\JsonAggregate; /** * This class load config for chillMainExtension. @@ -128,7 +131,9 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface, 'orm' => array( 'dql' => array( 'string_functions' => array( - 'unaccent' => 'Chill\MainBundle\Doctrine\DQL\Unaccent' + 'unaccent' => Unaccent::class, + 'GET_JSON_FIELD_BY_KEY' => GetJsonFieldByKey::class, + 'AGGREGATE' => JsonAggregate::class ) ) ) diff --git a/Doctrine/DQL/GetJsonFieldByKey.php b/Doctrine/DQL/GetJsonFieldByKey.php new file mode 100644 index 000000000..addc6b9b7 --- /dev/null +++ b/Doctrine/DQL/GetJsonFieldByKey.php @@ -0,0 +1,53 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Doctrine\DQL; + +use Doctrine\ORM\Query\AST\Functions\FunctionNode; +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; + +/** + * + * + * @author Julien Fastré + */ +class GetJsonFieldByKey extends FunctionNode +{ + private $expr1; + private $expr2; + + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->expr1 = $parser->StringPrimary(); + $parser->match(Lexer::T_COMMA); + $this->expr2 = $parser->StringPrimary(); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(SqlWalker $sqlWalker) + { + return sprintf( + '(%s->%s)', + $this->expr1->dispatch($sqlWalker), + $this->expr2->dispatch($sqlWalker) + ); + } +} diff --git a/Doctrine/DQL/JsonAggregate.php b/Doctrine/DQL/JsonAggregate.php new file mode 100644 index 000000000..54ef45493 --- /dev/null +++ b/Doctrine/DQL/JsonAggregate.php @@ -0,0 +1,49 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +namespace Chill\MainBundle\Doctrine\DQL; + +use Doctrine\ORM\Query\AST\Functions\FunctionNode; +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; + +/** + * Return an aggregation of values in a json representation, as a string. + * + * Internally, this function use the postgresql `jsonb_agg` function. Using + * json allow to aggregate data from different types without have to cast them. + * + * @author Julien Fastré + */ +class JsonAggregate extends FunctionNode +{ + private $expr; + + public function getSql(SqlWalker $sqlWalker) + { + return sprintf('jsonb_agg(%s)', $this->expr->dispatch($sqlWalker)); + } + + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $this->expr = $parser->StringPrimary(); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +}