From 0dbc81e8441adbfaa38ffcfc14ef46b8a9c5975e Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 13:37:43 +0100 Subject: [PATCH 01/26] add compiler pass for search query mappers --- .../Compiler/SearchQueryMappersPass.php | 34 +++++++++++++++++++ src/EzSystemsEzPlatformGraphQLBundle.php | 3 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/DependencyInjection/Compiler/SearchQueryMappersPass.php diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php new file mode 100644 index 00000000..f1a85d25 --- /dev/null +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -0,0 +1,34 @@ +has(self::ID)) { + return; + } + + $definition = $container->findDefinition(SearchQueryMapper::class); + $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.search_query_mapper'); + + $criteriaMappers = []; + foreach ($taggedServices as $id => $tags) { + foreach ($tags as $tag) { + if (isset($tag['criteria'])) { + $criteriaMappers[$tag['criteria']] = new Reference($id); + } + } + } + + $definition->setArgument('$criteriaMappers', $criteriaMappers); + } +} diff --git a/src/EzSystemsEzPlatformGraphQLBundle.php b/src/EzSystemsEzPlatformGraphQLBundle.php index 2054ce9a..2b9d8c4c 100644 --- a/src/EzSystemsEzPlatformGraphQLBundle.php +++ b/src/EzSystemsEzPlatformGraphQLBundle.php @@ -15,6 +15,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new Compiler\FieldValueTypesPass()); $container->addCompilerPass(new Compiler\FieldValueBuildersPass()); $container->addCompilerPass(new Compiler\SchemaWorkersPass()); - $container->addCompilerPass(new Compiler\SchemaDomainIteratorsPass()); + $container->addCompilerPass(new Compiler\SchemaBuildersPass()); + $container->addCompilerPass(new Compiler\SearchQueryMappersPass()); } } From ffa7bf7003288b934b6164c333d952624fa8620d Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 13:38:11 +0100 Subject: [PATCH 02/26] add dedicated file for search query mappers and load it --- .../EzSystemsEzPlatformGraphQLExtension.php | 1 + src/Resources/config/search_query_mappers.yml | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 src/Resources/config/search_query_mappers.yml diff --git a/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php b/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php index 0e8d3097..a62e7ace 100644 --- a/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php +++ b/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php @@ -31,6 +31,7 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('schema.yml'); $loader->load('resolvers.yml'); $loader->load('services.yml'); + $loader->load('search_query_mappers.yml'); } /** diff --git a/src/Resources/config/search_query_mappers.yml b/src/Resources/config/search_query_mappers.yml new file mode 100644 index 00000000..7fe34654 --- /dev/null +++ b/src/Resources/config/search_query_mappers.yml @@ -0,0 +1,4 @@ +services: + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeIdentifier'} From cb3f4442aa1eebc698bc05eea73a07b9298546dc Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 13:38:38 +0100 Subject: [PATCH 03/26] define interface for searchCriterion and first of them --- .../Criterion/ContentTypeIdentifier.php | 19 +++++++++++++++++++ .../Search/Criterion/SearchCriterion.php | 10 ++++++++++ src/GraphQL/InputMapper/SearchQueryMapper.php | 18 ++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php new file mode 100644 index 00000000..2aede815 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -0,0 +1,19 @@ +criteriaMappers = $criteriaMappers; + } + /** * @return \eZ\Publish\API\Repository\Values\Content\Query */ @@ -21,6 +28,11 @@ public function mapInputToQuery(array $inputArray) $query = new Query(); $criteria = []; + foreach ($inputArray as $key => $value) { + $criteria[] = $this->criteriaMappers[$key]->resolve($value); + } + + /** if (isset($inputArray['ContentTypeIdentifier'])) { $criteria[] = new Query\Criterion\ContentTypeIdentifier($inputArray['ContentTypeIdentifier']); } @@ -52,11 +64,13 @@ function($input) { $criteria = array_merge($criteria, $this->mapDateMetadata($inputArray, 'Modified')); $criteria = array_merge($criteria, $this->mapDateMetadata($inputArray, 'Created')); + */ + /* if (isset($inputArray['sortBy'])) { $query->sortClauses = array_map( function ($sortClauseClass) { - /** @var Query\SortClause $lastSortClause */ + static $lastSortClause; if ($sortClauseClass === Query::SORT_DESC) { @@ -83,7 +97,7 @@ function ($sortClauseClass) { // remove null entries left out because of sort direction $query->sortClauses = array_filter($query->sortClauses); } - + */ if (count($criteria) === 0) { return $query; } From 83bf501a2b325392928c501f6cb0d3b7720d63db Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 15:20:35 +0100 Subject: [PATCH 04/26] create rest of the current available search criterions --- .../Search/Criterion/ContentTypeId.php | 16 +++++ .../Criterion/ContentTypeIdentifier.php | 9 +-- .../InputMapper/Search/Criterion/Created.php | 10 +++ .../Search/Criterion/DateMetadata.php | 34 ++++++++++ .../InputMapper/Search/Criterion/Field.php | 46 ++++++++++++++ .../InputMapper/Search/Criterion/Modified.php | 10 +++ .../Search/Criterion/SearchCriterion.php | 2 +- .../InputMapper/Search/Criterion/Text.php | 20 ++++++ src/GraphQL/InputMapper/SearchQueryMapper.php | 63 +------------------ src/Resources/config/search_query_mappers.yml | 20 ++++++ 10 files changed, 163 insertions(+), 67 deletions(-) create mode 100644 src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/Created.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/Field.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/Modified.php create mode 100644 src/GraphQL/InputMapper/Search/Criterion/Text.php diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php new file mode 100644 index 00000000..1b144dd8 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -0,0 +1,16 @@ + Query\Criterion\Operator::EQ, + 'before' => Query\Criterion\Operator::LTE, + 'after' => Query\Criterion\Operator::GTE, + ]; + + $criteria = []; + foreach ($value as $operator => $dateString) { + if (!isset($dateOperatorsMap[$operator])) { + echo "Not a valid operator\n"; + continue; + } + + $criteria[] = new Query\Criterion\DateMetadata( + static::TARGET, + $dateOperatorsMap[$operator], + strtotime($dateString) + ); + } + + return $criteria; + } + +} diff --git a/src/GraphQL/InputMapper/Search/Criterion/Field.php b/src/GraphQL/InputMapper/Search/Criterion/Field.php new file mode 100644 index 00000000..b2f5a302 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/Criterion/Field.php @@ -0,0 +1,46 @@ +mapInputToFieldCriterion($value); + } else { + $criteria = array_merge( + $criteria, + array_map( + function($input) { + return $this->mapInputToFieldCriterion($input); + }, + $value + ) + ); + } + + return $criteria; + } + + private function mapInputToFieldCriterion($input) + { + $operators = ['in', 'eq', 'like', 'contains', 'between', 'lt', 'lte', 'gt', 'gte']; + foreach ($operators as $opString) { + if (isset($input[$opString])) { + $value = $input[$opString]; + $operator = constant('eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator::' . strtoupper($opString)); + } + } + + if (!isset($operator)) { + throw new InvalidArgumentException("Unspecified operator"); + } + + return new Query\Criterion\Field($input['target'], $operator, $value); + } +} diff --git a/src/GraphQL/InputMapper/Search/Criterion/Modified.php b/src/GraphQL/InputMapper/Search/Criterion/Modified.php new file mode 100644 index 00000000..35947fc2 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/Criterion/Modified.php @@ -0,0 +1,10 @@ + $value) { - $criteria[] = $this->criteriaMappers[$key]->resolve($value); - } - - /** - if (isset($inputArray['ContentTypeIdentifier'])) { - $criteria[] = new Query\Criterion\ContentTypeIdentifier($inputArray['ContentTypeIdentifier']); + $criteria = array_merge($criteria, $this->criteriaMappers[$key]->resolve($value)); } if (isset($inputArray['Text'])) { @@ -109,61 +104,5 @@ function ($sortClauseClass) { return $query; } - /** - * @param array $queryArg - * @param $dateMetadata - * @return \eZ\Publish\API\Repository\Values\Content\Query\Criterion\DateMetadata[] - */ - private function mapDateMetadata(array $queryArg = [], $dateMetadata) - { - if (!isset($queryArg[$dateMetadata]) || !is_array($queryArg[$dateMetadata])) { - return []; - } - - $targetMap = [ - 'Created' => Query\Criterion\DateMetadata::CREATED, - 'Modified' => Query\Criterion\DateMetadata::MODIFIED, - ]; - - if (!isset($targetMap[$dateMetadata])) { - return []; - } - - $dateOperatorsMap = [ - 'on' => Query\Criterion\Operator::EQ, - 'before' => Query\Criterion\Operator::LTE, - 'after' => Query\Criterion\Operator::GTE, - ]; - - $criteria = []; - foreach ($queryArg[$dateMetadata] as $operator => $dateString) { - if (!isset($dateOperatorsMap[$operator])) { - continue; - } - - $criteria[] = new Query\Criterion\DateMetadata( - $targetMap[$dateMetadata], - $dateOperatorsMap[$operator], - strtotime($dateString) - ); - } - - return $criteria; - } - - private function mapInputToFieldCriterion($input) - { - $operators = ['in', 'eq', 'like', 'contains', 'between', 'lt', 'lte', 'gt', 'gte']; - foreach ($operators as $opString) { - if (isset($input[$opString])) { - $value = $input[$opString]; - $operator = constant('eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator::' . strtoupper($opString)); - } - } - - if (!isset($operator)) { - throw new InvalidArgumentException("Unspecified operator"); - } - return new Query\Criterion\Field($input['target'], $operator, $value); } } diff --git a/src/Resources/config/search_query_mappers.yml b/src/Resources/config/search_query_mappers.yml index 7fe34654..86451803 100644 --- a/src/Resources/config/search_query_mappers.yml +++ b/src/Resources/config/search_query_mappers.yml @@ -2,3 +2,23 @@ services: BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: tags: - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeIdentifier'} + + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeId: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeId'} + + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Text: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Text'} + + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Created: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Created'} + + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Modified: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Modified'} + + BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Field: + tags: + - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Field'} From 8f0ad912b346ef3f165fb9d673f33e7a2b589fe5 Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 19:45:08 +0100 Subject: [PATCH 05/26] rename method name --- src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php | 2 +- .../InputMapper/Search/Criterion/ContentTypeIdentifier.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Field.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Text.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php index 1b144dd8..ab166fca 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -8,7 +8,7 @@ class ContentTypeId implements SearchCriterion { - public function resolve($value): array + public function map($value): array { return [new Query\Criterion\ContentTypeId($value)]; } diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php index 592f5e8b..3ee033ff 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -9,7 +9,7 @@ //@todo remove it, not needed anymore class ContentTypeIdentifier implements SearchCriterion { - public function resolve($value): array + public function map($value): array { if (!is_string($value)) { throw new InvalidArgumentException($value, 'value needs to be an string'); diff --git a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php index cb0d98be..86c7efe5 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php +++ b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php @@ -6,7 +6,7 @@ class DateMetadata implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $dateOperatorsMap = [ 'on' => Query\Criterion\Operator::EQ, diff --git a/src/GraphQL/InputMapper/Search/Criterion/Field.php b/src/GraphQL/InputMapper/Search/Criterion/Field.php index b2f5a302..fbbfeb8e 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Field.php +++ b/src/GraphQL/InputMapper/Search/Criterion/Field.php @@ -6,7 +6,7 @@ class Field implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $criteria = []; diff --git a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php b/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php index bc6d3551..7150135b 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php +++ b/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php @@ -6,5 +6,5 @@ interface SearchCriterion { - public function resolve($value) : array; + public function map($value) : array; } diff --git a/src/GraphQL/InputMapper/Search/Criterion/Text.php b/src/GraphQL/InputMapper/Search/Criterion/Text.php index 26c95ae9..72fa5455 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Text.php +++ b/src/GraphQL/InputMapper/Search/Criterion/Text.php @@ -7,7 +7,7 @@ class Text implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $criteria = []; From 46399650f9463f5fdee112f7323c2b9a0e842b06 Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 19:50:22 +0100 Subject: [PATCH 06/26] add method to check if inputField can be mapped to a criteria --- src/GraphQL/InputMapper/SearchQueryMapper.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index 8d02f38e..45f50026 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -28,8 +28,10 @@ public function mapInputToQuery(array $inputArray) $query = new Query(); $criteria = []; - foreach ($inputArray as $key => $value) { - $criteria = array_merge($criteria, $this->criteriaMappers[$key]->resolve($value)); + foreach ($inputArray as $inputField => $inputValue) { + if ($this->existsCriteriaMapperForField($inputField)) { + $criteria = array_merge($criteria, $this->criteriaMappers[$inputValue]->map($value)); + } } if (isset($inputArray['Text'])) { @@ -104,5 +106,13 @@ function ($sortClauseClass) { return $query; } + /** + * @param string $inputField + * @return bool + */ + private function existsCriteriaMapperForField(string $inputField) : bool + { + return isset($this->criteriaMappers[$inputField]); + } } From 4b19c6637acf2b3341e3aae3b8a3e1a967c0e0c2 Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 20:16:58 +0100 Subject: [PATCH 07/26] extract sortByPart logic to dedicate method --- src/GraphQL/InputMapper/SearchQueryMapper.php | 99 ++++++++----------- 1 file changed, 39 insertions(+), 60 deletions(-) diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index 45f50026..90612c6a 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -29,72 +29,18 @@ public function mapInputToQuery(array $inputArray) $criteria = []; foreach ($inputArray as $inputField => $inputValue) { - if ($this->existsCriteriaMapperForField($inputField)) { - $criteria = array_merge($criteria, $this->criteriaMappers[$inputValue]->map($value)); + if ($criteriaMapper = $this->existsCriteriaMapperForField($inputField)) { + $criteria = array_merge($criteria, $this->criteriaMappers[$inputField]->map($inputValue)); } - } - if (isset($inputArray['Text'])) { - $criteria[] = new Query\Criterion\FullText($inputArray['Text']); - } + if ($inputField == 'sortBy') { + $query->sortClauses = $this->mapSortByPart($inputValue); - if (isset($inputArray['Field'])) - { - if (isset($inputArray['Field']['target'])) { - $criteria[] = $this->mapInputToFieldCriterion($inputArray['Field']); - } else { - $criteria = array_merge( - $criteria, - array_map( - function($input) { - return $this->mapInputToFieldCriterion($input); - }, - $inputArray['Field'] - ) - ); + // remove null entries left out because of sort direction + $query->sortClauses = array_filter($query->sortClauses); } } - if (isset($inputArray['ParentLocationId'])) { - $criteria[] = new Query\Criterion\ParentLocationId($inputArray['ParentLocationId']); - } - - $criteria = array_merge($criteria, $this->mapDateMetadata($inputArray, 'Modified')); - $criteria = array_merge($criteria, $this->mapDateMetadata($inputArray, 'Created')); - */ - - /* - if (isset($inputArray['sortBy'])) { - $query->sortClauses = array_map( - function ($sortClauseClass) { - - static $lastSortClause; - - if ($sortClauseClass === Query::SORT_DESC) { - if (!$lastSortClause instanceof Query\SortClause) { - return null; - } - - $lastSortClause->direction = $sortClauseClass; - return null; - } - - if (!class_exists($sortClauseClass)) { - return null; - } - - if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { - return null; - } - - return $lastSortClause = new $sortClauseClass; - }, - $inputArray['sortBy'] - ); - // remove null entries left out because of sort direction - $query->sortClauses = array_filter($query->sortClauses); - } - */ if (count($criteria) === 0) { return $query; } @@ -115,4 +61,37 @@ private function existsCriteriaMapperForField(string $inputField) : bool return isset($this->criteriaMappers[$inputField]); } + /** + * @param $inputValue + * @return array + */ + private function mapSortByPart($inputValue) { + return array_map( + function ($sortClauseClass) { + + static $lastSortClause; + + if ($sortClauseClass === Query::SORT_DESC) { + if (!$lastSortClause instanceof Query\SortClause) { + return null; + } + + $lastSortClause->direction = $sortClauseClass; + return null; + } + + if (!class_exists($sortClauseClass)) { + return null; + } + + if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { + return null; + } + + return $lastSortClause = new $sortClauseClass; + }, + $inputValue + ); + } + } From 2279ce23e60c5f163be66295c2f548929aae6572 Mon Sep 17 00:00:00 2001 From: crevillo Date: Mon, 28 Jan 2019 19:03:37 +0100 Subject: [PATCH 08/26] update namespaces after conflict resolution --- src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php | 2 +- .../InputMapper/Search/Criterion/ContentTypeIdentifier.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Created.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Field.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Modified.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/Text.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php index ab166fca..2c18c340 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -1,6 +1,6 @@ Date: Sat, 26 Jan 2019 13:38:11 +0100 Subject: [PATCH 09/26] add dedicated file for search query mappers and load it --- src/Resources/config/search_query_mappers.yml | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/Resources/config/search_query_mappers.yml b/src/Resources/config/search_query_mappers.yml index 86451803..7fe34654 100644 --- a/src/Resources/config/search_query_mappers.yml +++ b/src/Resources/config/search_query_mappers.yml @@ -2,23 +2,3 @@ services: BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: tags: - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeIdentifier'} - - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeId: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeId'} - - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Text: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Text'} - - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Created: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Created'} - - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Modified: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Modified'} - - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Field: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Field'} From 6d9b245f308bdce999df883aba9f16b66a413e26 Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 26 Jan 2019 13:38:38 +0100 Subject: [PATCH 10/26] define interface for searchCriterion and first of them --- GraphQL/InputMapper/SearchQueryMapper.php | 0 .../Search/Criterion/ContentTypeIdentifier.php | 11 +++++------ .../InputMapper/Search/Criterion/SearchCriterion.php | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 GraphQL/InputMapper/SearchQueryMapper.php diff --git a/GraphQL/InputMapper/SearchQueryMapper.php b/GraphQL/InputMapper/SearchQueryMapper.php new file mode 100644 index 00000000..e69de29b diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php index f94030f8..2aede815 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -1,20 +1,19 @@ Date: Sat, 26 Jan 2019 15:20:35 +0100 Subject: [PATCH 11/26] create rest of the current available search criterions --- .../Search/Criterion/ContentTypeId.php | 16 +++++++ .../InputMapper/Search/Criterion/Created.php | 10 ++++ .../Search/Criterion/DateMetadata.php | 34 ++++++++++++++ .../InputMapper/Search/Criterion/Field.php | 46 +++++++++++++++++++ .../InputMapper/Search/Criterion/Modified.php | 10 ++++ GraphQL/InputMapper/Search/Criterion/Text.php | 20 ++++++++ .../Criterion/ContentTypeIdentifier.php | 9 ++-- .../Search/Criterion/SearchCriterion.php | 2 +- src/Resources/config/search_query_mappers.yml | 20 ++++++++ 9 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 GraphQL/InputMapper/Search/Criterion/ContentTypeId.php create mode 100644 GraphQL/InputMapper/Search/Criterion/Created.php create mode 100644 GraphQL/InputMapper/Search/Criterion/DateMetadata.php create mode 100644 GraphQL/InputMapper/Search/Criterion/Field.php create mode 100644 GraphQL/InputMapper/Search/Criterion/Modified.php create mode 100644 GraphQL/InputMapper/Search/Criterion/Text.php diff --git a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php new file mode 100644 index 00000000..1b144dd8 --- /dev/null +++ b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -0,0 +1,16 @@ + Query\Criterion\Operator::EQ, + 'before' => Query\Criterion\Operator::LTE, + 'after' => Query\Criterion\Operator::GTE, + ]; + + $criteria = []; + foreach ($value as $operator => $dateString) { + if (!isset($dateOperatorsMap[$operator])) { + echo "Not a valid operator\n"; + continue; + } + + $criteria[] = new Query\Criterion\DateMetadata( + static::TARGET, + $dateOperatorsMap[$operator], + strtotime($dateString) + ); + } + + return $criteria; + } + +} diff --git a/GraphQL/InputMapper/Search/Criterion/Field.php b/GraphQL/InputMapper/Search/Criterion/Field.php new file mode 100644 index 00000000..b2f5a302 --- /dev/null +++ b/GraphQL/InputMapper/Search/Criterion/Field.php @@ -0,0 +1,46 @@ +mapInputToFieldCriterion($value); + } else { + $criteria = array_merge( + $criteria, + array_map( + function($input) { + return $this->mapInputToFieldCriterion($input); + }, + $value + ) + ); + } + + return $criteria; + } + + private function mapInputToFieldCriterion($input) + { + $operators = ['in', 'eq', 'like', 'contains', 'between', 'lt', 'lte', 'gt', 'gte']; + foreach ($operators as $opString) { + if (isset($input[$opString])) { + $value = $input[$opString]; + $operator = constant('eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator::' . strtoupper($opString)); + } + } + + if (!isset($operator)) { + throw new InvalidArgumentException("Unspecified operator"); + } + + return new Query\Criterion\Field($input['target'], $operator, $value); + } +} diff --git a/GraphQL/InputMapper/Search/Criterion/Modified.php b/GraphQL/InputMapper/Search/Criterion/Modified.php new file mode 100644 index 00000000..35947fc2 --- /dev/null +++ b/GraphQL/InputMapper/Search/Criterion/Modified.php @@ -0,0 +1,10 @@ + Date: Sat, 26 Jan 2019 19:45:08 +0100 Subject: [PATCH 12/26] rename method name --- GraphQL/InputMapper/Search/Criterion/ContentTypeId.php | 2 +- GraphQL/InputMapper/Search/Criterion/DateMetadata.php | 2 +- GraphQL/InputMapper/Search/Criterion/Field.php | 2 +- GraphQL/InputMapper/Search/Criterion/Text.php | 2 +- .../InputMapper/Search/Criterion/ContentTypeIdentifier.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php index 1b144dd8..ab166fca 100644 --- a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -8,7 +8,7 @@ class ContentTypeId implements SearchCriterion { - public function resolve($value): array + public function map($value): array { return [new Query\Criterion\ContentTypeId($value)]; } diff --git a/GraphQL/InputMapper/Search/Criterion/DateMetadata.php b/GraphQL/InputMapper/Search/Criterion/DateMetadata.php index cb0d98be..86c7efe5 100644 --- a/GraphQL/InputMapper/Search/Criterion/DateMetadata.php +++ b/GraphQL/InputMapper/Search/Criterion/DateMetadata.php @@ -6,7 +6,7 @@ class DateMetadata implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $dateOperatorsMap = [ 'on' => Query\Criterion\Operator::EQ, diff --git a/GraphQL/InputMapper/Search/Criterion/Field.php b/GraphQL/InputMapper/Search/Criterion/Field.php index b2f5a302..fbbfeb8e 100644 --- a/GraphQL/InputMapper/Search/Criterion/Field.php +++ b/GraphQL/InputMapper/Search/Criterion/Field.php @@ -6,7 +6,7 @@ class Field implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $criteria = []; diff --git a/GraphQL/InputMapper/Search/Criterion/Text.php b/GraphQL/InputMapper/Search/Criterion/Text.php index 26c95ae9..72fa5455 100644 --- a/GraphQL/InputMapper/Search/Criterion/Text.php +++ b/GraphQL/InputMapper/Search/Criterion/Text.php @@ -7,7 +7,7 @@ class Text implements SearchCriterion { - public function resolve($value): array + public function map($value): array { $criteria = []; diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php index 592f5e8b..3ee033ff 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -9,7 +9,7 @@ //@todo remove it, not needed anymore class ContentTypeIdentifier implements SearchCriterion { - public function resolve($value): array + public function map($value): array { if (!is_string($value)) { throw new InvalidArgumentException($value, 'value needs to be an string'); diff --git a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php b/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php index bc6d3551..7150135b 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php +++ b/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php @@ -6,5 +6,5 @@ interface SearchCriterion { - public function resolve($value) : array; + public function map($value) : array; } From 832969c0f98afcd910d7833fe8ed30e69715cc3b Mon Sep 17 00:00:00 2001 From: crevillo Date: Mon, 28 Jan 2019 19:28:57 +0100 Subject: [PATCH 13/26] updated namespaces after conflict --- src/DependencyInjection/Compiler/SearchQueryMappersPass.php | 2 +- src/EzSystemsEzPlatformGraphQLBundle.php | 2 +- .../InputMapper/Search/Criterion/ContentTypeIdentifier.php | 2 +- src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index f1a85d25..a654aaa1 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -1,6 +1,6 @@ addCompilerPass(new Compiler\FieldValueTypesPass()); $container->addCompilerPass(new Compiler\FieldValueBuildersPass()); $container->addCompilerPass(new Compiler\SchemaWorkersPass()); - $container->addCompilerPass(new Compiler\SchemaBuildersPass()); + $container->addCompilerPass(new Compiler\SchemaDomainIteratorsPass()); $container->addCompilerPass(new Compiler\SearchQueryMappersPass()); } } diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php index 3ee033ff..f94030f8 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -1,6 +1,6 @@ Date: Mon, 28 Jan 2019 19:33:48 +0100 Subject: [PATCH 14/26] some typehints --- GraphQL/InputMapper/SearchQueryMapper.php | 0 .../Compiler/SearchQueryMappersPass.php | 4 ++-- src/GraphQL/InputMapper/SearchQueryMapper.php | 5 +++-- src/Resources/config/search_query_mappers.yml | 12 ++++++------ 4 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 GraphQL/InputMapper/SearchQueryMapper.php diff --git a/GraphQL/InputMapper/SearchQueryMapper.php b/GraphQL/InputMapper/SearchQueryMapper.php deleted file mode 100644 index e69de29b..00000000 diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index a654aaa1..72d4911b 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -23,8 +23,8 @@ public function process(ContainerBuilder $container) $criteriaMappers = []; foreach ($taggedServices as $id => $tags) { foreach ($tags as $tag) { - if (isset($tag['criteria'])) { - $criteriaMappers[$tag['criteria']] = new Reference($id); + if (isset($tag['inputKey'])) { + $criteriaMappers[$tag['inputKey']] = new Reference($id); } } } diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index 90612c6a..6cfea78c 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -23,7 +23,7 @@ public function __construct($criteriaMappers) /** * @return \eZ\Publish\API\Repository\Values\Content\Query */ - public function mapInputToQuery(array $inputArray) + public function mapInputToQuery(array $inputArray) : Query { $query = new Query(); $criteria = []; @@ -65,7 +65,8 @@ private function existsCriteriaMapperForField(string $inputField) : bool * @param $inputValue * @return array */ - private function mapSortByPart($inputValue) { + private function mapSortByPart($inputValue) : array + { return array_map( function ($sortClauseClass) { diff --git a/src/Resources/config/search_query_mappers.yml b/src/Resources/config/search_query_mappers.yml index 86451803..18275f6b 100644 --- a/src/Resources/config/search_query_mappers.yml +++ b/src/Resources/config/search_query_mappers.yml @@ -1,24 +1,24 @@ services: BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeIdentifier'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'ContentTypeIdentifier'} BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeId: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'ContentTypeId'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'ContentTypeId'} BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Text: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Text'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Text'} BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Created: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Created'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Created'} BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Modified: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Modified'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Modified'} BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Field: tags: - - {name: 'ezplatform_graphql.search_query_mapper', criteria: 'Field'} + - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Field'} From eea3c5c87a0fe9b4e7f63ce559eccdfd20025902 Mon Sep 17 00:00:00 2001 From: crevillo Date: Mon, 28 Jan 2019 19:37:27 +0100 Subject: [PATCH 15/26] rename file with the visitors --- src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php | 2 +- .../{search_query_mappers.yml => query_input_visitors.yml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Resources/config/{search_query_mappers.yml => query_input_visitors.yml} (100%) diff --git a/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php b/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php index a62e7ace..288b9edf 100644 --- a/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php +++ b/src/DependencyInjection/EzSystemsEzPlatformGraphQLExtension.php @@ -31,7 +31,7 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('schema.yml'); $loader->load('resolvers.yml'); $loader->load('services.yml'); - $loader->load('search_query_mappers.yml'); + $loader->load('query_input_visitors.yml'); } /** diff --git a/src/Resources/config/search_query_mappers.yml b/src/Resources/config/query_input_visitors.yml similarity index 100% rename from src/Resources/config/search_query_mappers.yml rename to src/Resources/config/query_input_visitors.yml From 05aa44550975e37b1b82fc998ea5a2d469c7e6ea Mon Sep 17 00:00:00 2001 From: crevillo Date: Tue, 29 Jan 2019 10:19:21 +0100 Subject: [PATCH 16/26] add querybuilder and adapt all the visitors to the new interface --- .../Compiler/SearchQueryMappersPass.php | 12 +-- .../Search/Criterion/ContentTypeId.php | 11 ++- .../Criterion/ContentTypeIdentifier.php | 16 ++-- .../Search/Criterion/DateMetadata.php | 13 ++-- .../InputMapper/Search/Criterion/Field.php | 10 ++- .../Search/Criterion/ParentLocationId.php | 15 ++++ .../Search/Criterion/SearchCriterion.php | 10 --- .../InputMapper/Search/Criterion/Text.php | 14 ++-- .../InputMapper/Search/QueryBuilder.php | 39 ++++++++++ .../InputMapper/Search/QueryInputVisitor.php | 10 +++ src/GraphQL/InputMapper/Search/SortBy.php | 38 +++++++++ src/GraphQL/InputMapper/SearchQueryMapper.php | 78 +++---------------- src/Resources/config/query_input_visitors.yml | 38 +++++---- src/Resources/config/services.yml | 6 +- 14 files changed, 175 insertions(+), 135 deletions(-) create mode 100644 src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php delete mode 100644 src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php create mode 100644 src/GraphQL/InputMapper/Search/QueryBuilder.php create mode 100644 src/GraphQL/InputMapper/Search/QueryInputVisitor.php create mode 100644 src/GraphQL/InputMapper/Search/SortBy.php diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index 72d4911b..fcd50646 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -2,14 +2,14 @@ namespace EzSystems\EzPlatformGraphQL\DependencyInjection\Compiler; -use BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\SearchQueryMapper; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; class SearchQueryMappersPass implements CompilerPassInterface { - const ID = 'BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\SearchQueryMapper'; + const ID = 'EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper'; public function process(ContainerBuilder $container) { @@ -18,17 +18,17 @@ public function process(ContainerBuilder $container) } $definition = $container->findDefinition(SearchQueryMapper::class); - $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.search_query_mapper'); + $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor'); - $criteriaMappers = []; + $queryInputVisitors = []; foreach ($taggedServices as $id => $tags) { foreach ($tags as $tag) { if (isset($tag['inputKey'])) { - $criteriaMappers[$tag['inputKey']] = new Reference($id); + $queryInputVisitors[$tag['inputKey']] = new Reference($id); } } } - $definition->setArgument('$criteriaMappers', $criteriaMappers); + $definition->setArgument('$queryInputVisitors', $queryInputVisitors); } } diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php index 2c18c340..05f4d327 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php @@ -2,15 +2,14 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; -use eZ\Publish\API\Repository\Values\Content\Query\CriterionInterface; use eZ\Publish\API\Repository\Values\Content\Query; -use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class ContentTypeId implements SearchCriterion +class ContentTypeId implements QueryInputVisitor { - public function map($value): array + public function visit(QueryBuilder $queryBuilder, $value): void { - return [new Query\Criterion\ContentTypeId($value)]; + $queryBuilder->addCriterion(new Query\Criterion\ContentTypeId($value)); } - } diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php index f94030f8..462465e0 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php @@ -2,19 +2,15 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; -use eZ\Publish\API\Repository\Values\Content; -use eZ\Publish\API\Repository\Values\Content\Query\CriterionInterface; -use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException; +use eZ\Publish\API\Repository\Values\Content\Query; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; //@todo remove it, not needed anymore -class ContentTypeIdentifier implements SearchCriterion +class ContentTypeIdentifier implements QueryInputVisitor { - public function map($value): array + public function visit(QueryBuilder $queryBuilder, $value): void { - if (!is_string($value)) { - throw new InvalidArgumentException($value, 'value needs to be an string'); - } - - return [new Content\Query\Criterion\ContentTypeIdentifier($value)]; + $queryBuilder->addCriterion(new Query\Criterion\ContentTypeIdentifier($value)); } } diff --git a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php index a3036167..bcaf1ee5 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php +++ b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php @@ -3,10 +3,12 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; use eZ\Publish\API\Repository\Values\Content\Query; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class DateMetadata implements SearchCriterion +class DateMetadata implements QueryInputVisitor { - public function map($value): array + public function visit(QueryBuilder $queryBuilder, $value): void { $dateOperatorsMap = [ 'on' => Query\Criterion\Operator::EQ, @@ -21,14 +23,11 @@ public function map($value): array continue; } - $criteria[] = new Query\Criterion\DateMetadata( + $queryBuilder->addCriterion(new Query\Criterion\DateMetadata( static::TARGET, $dateOperatorsMap[$operator], strtotime($dateString) - ); + )); } - - return $criteria; } - } diff --git a/src/GraphQL/InputMapper/Search/Criterion/Field.php b/src/GraphQL/InputMapper/Search/Criterion/Field.php index 978db76b..e84a6172 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Field.php +++ b/src/GraphQL/InputMapper/Search/Criterion/Field.php @@ -3,10 +3,12 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; use eZ\Publish\API\Repository\Values\Content\Query; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class Field implements SearchCriterion +class Field implements QueryInputVisitor { - public function map($value): array + public function visit(QueryBuilder $queryBuilder, $value): void { $criteria = []; @@ -24,7 +26,9 @@ function($input) { ); } - return $criteria; + foreach ($criteria as $criterion) { + $queryBuilder->addCriterion($criterion); + } } private function mapInputToFieldCriterion($input) diff --git a/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php b/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php new file mode 100644 index 00000000..995abe19 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php @@ -0,0 +1,15 @@ +addCriterion(new Query\Criterion\ParentLocationId($value)); + } +} diff --git a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php b/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php deleted file mode 100644 index ec1043d3..00000000 --- a/src/GraphQL/InputMapper/Search/Criterion/SearchCriterion.php +++ /dev/null @@ -1,10 +0,0 @@ -addCriterion(new Query\Criterion\FullText($value)); } } diff --git a/src/GraphQL/InputMapper/Search/QueryBuilder.php b/src/GraphQL/InputMapper/Search/QueryBuilder.php new file mode 100644 index 00000000..4ce91829 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/QueryBuilder.php @@ -0,0 +1,39 @@ +criterions[] = $criterion; + } + + public function buildQuery(): Query + { + + $query = new Query(); + + if (count($this->criterions) === 0) { + return $query; + } + + $query->filter = count($this->criterions) === 1 ? $this->criterions[0] : new Query\Criterion\LogicalAnd($this->criterions); + + if ($this->sortBy) { + $query->sortClauses = $this->sortBy; + } + + return $query; + } +} diff --git a/src/GraphQL/InputMapper/Search/QueryInputVisitor.php b/src/GraphQL/InputMapper/Search/QueryInputVisitor.php new file mode 100644 index 00000000..01ec27a0 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/QueryInputVisitor.php @@ -0,0 +1,10 @@ +sortBy = array_map( + function ($sortClauseClass) { + + static $lastSortClause; + + if ($sortClauseClass === Query::SORT_DESC) { + if (!$lastSortClause instanceof Query\SortClause) { + return null; + } + + $lastSortClause->direction = $sortClauseClass; + return null; + } + + if (!class_exists($sortClauseClass)) { + return null; + } + + if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { + return null; + } + + return $lastSortClause = new $sortClauseClass; + }, + $value + ); + } +} diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index 6cfea78c..bf69216f 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -9,15 +9,19 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper; use eZ\Publish\API\Repository\Values\Content\Query; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; use InvalidArgumentException; class SearchQueryMapper { - private $criteriaMappers; + private $queryInputVisitors; - public function __construct($criteriaMappers) + private $queryBuilder; + + public function __construct(array $queryInputVisitors, QueryBuilder $queryBuilder) { - $this->criteriaMappers = $criteriaMappers; + $this->queryInputVisitors = $queryInputVisitors; + $this->queryBuilder = $queryBuilder; } /** @@ -25,74 +29,12 @@ public function __construct($criteriaMappers) */ public function mapInputToQuery(array $inputArray) : Query { - $query = new Query(); - $criteria = []; - foreach ($inputArray as $inputField => $inputValue) { - if ($criteriaMapper = $this->existsCriteriaMapperForField($inputField)) { - $criteria = array_merge($criteria, $this->criteriaMappers[$inputField]->map($inputValue)); + if (isset($this->queryInputVisitors[$inputField])) { + $this->queryInputVisitors[$inputField]->visit($this->queryBuilder, $inputValue); } - - if ($inputField == 'sortBy') { - $query->sortClauses = $this->mapSortByPart($inputValue); - - // remove null entries left out because of sort direction - $query->sortClauses = array_filter($query->sortClauses); - } - } - - if (count($criteria) === 0) { - return $query; } - if (count($criteria)) { - $query->filter = count($criteria) > 1 ? new Query\Criterion\LogicalAnd($criteria) : $criteria[0]; - } - - return $query; - } - - /** - * @param string $inputField - * @return bool - */ - private function existsCriteriaMapperForField(string $inputField) : bool - { - return isset($this->criteriaMappers[$inputField]); - } - - /** - * @param $inputValue - * @return array - */ - private function mapSortByPart($inputValue) : array - { - return array_map( - function ($sortClauseClass) { - - static $lastSortClause; - - if ($sortClauseClass === Query::SORT_DESC) { - if (!$lastSortClause instanceof Query\SortClause) { - return null; - } - - $lastSortClause->direction = $sortClauseClass; - return null; - } - - if (!class_exists($sortClauseClass)) { - return null; - } - - if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { - return null; - } - - return $lastSortClause = new $sortClauseClass; - }, - $inputValue - ); + return $this->queryBuilder->buildQuery(); } - } diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index 18275f6b..7da1a774 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -1,24 +1,32 @@ services: - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'ContentTypeIdentifier'} + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeIdentifier'} - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\ContentTypeId: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeId: tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'ContentTypeId'} + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeId'} - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Text: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Text'} + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Text: + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Text'} - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Created: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Created'} + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Created: + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Created'} - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Modified: - tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Modified'} + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Modified: + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Modified'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Field: + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Field'} - BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion\Field: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ParentLocationId: tags: - - {name: 'ezplatform_graphql.search_query_mapper', inputKey: 'Field'} + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ParentLocationId'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortBy: + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'SortBy'} diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml index 297d9b54..d796a93a 100644 --- a/src/Resources/config/services.yml +++ b/src/Resources/config/services.yml @@ -19,4 +19,8 @@ services: - { name: "overblog_graphql.mutation", alias: "CreateSection", method: "createSection" } - { name: "overblog_graphql.mutation", alias: "DeleteSection", method: "deleteSection" } - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper: ~ + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder: ~ + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper: + arguments: + $queryBuilder: '@EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder' From cd4cb884975b66597981ffc2454f526c7feb643b Mon Sep 17 00:00:00 2001 From: crevillo Date: Fri, 1 Feb 2019 19:44:59 +0100 Subject: [PATCH 17/26] use "class" constant instead of string --- src/DependencyInjection/Compiler/SearchQueryMappersPass.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index fcd50646..e4b651c4 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -9,7 +9,7 @@ class SearchQueryMappersPass implements CompilerPassInterface { - const ID = 'EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper'; + const ID = SearchQueryMapper::class; public function process(ContainerBuilder $container) { @@ -17,7 +17,7 @@ public function process(ContainerBuilder $container) return; } - $definition = $container->findDefinition(SearchQueryMapper::class); + $definition = $container->findDefinition(self::ID); $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor'); $queryInputVisitors = []; From a0b555eb72d49b05a0b384b1bcb1c29d0008d0f5 Mon Sep 17 00:00:00 2001 From: crevillo Date: Fri, 1 Feb 2019 19:47:45 +0100 Subject: [PATCH 18/26] remove unneded var --- src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php index bcaf1ee5..ad747d60 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php +++ b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php @@ -16,7 +16,6 @@ public function visit(QueryBuilder $queryBuilder, $value): void 'after' => Query\Criterion\Operator::GTE, ]; - $criteria = []; foreach ($value as $operator => $dateString) { if (!isset($dateOperatorsMap[$operator])) { echo "Not a valid operator\n"; From 4494d2a2a92a93621e28fb2ab53ed799b15ed12a Mon Sep 17 00:00:00 2001 From: crevillo Date: Mon, 4 Feb 2019 21:06:52 +0100 Subject: [PATCH 19/26] add basic criterion visitor fix ident in yaml --- .../Criterion/ContentTypeIdentifier.php | 16 -------------- .../Search/Criterion/ParentLocationId.php | 15 ------------- .../{ContentTypeId.php => Standard.php} | 12 +++++++--- .../InputMapper/Search/Criterion/Text.php | 16 -------------- src/Resources/config/query_input_visitors.yml | 22 ++++++++++++------- 5 files changed, 23 insertions(+), 58 deletions(-) delete mode 100644 src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php delete mode 100644 src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php rename src/GraphQL/InputMapper/Search/Criterion/{ContentTypeId.php => Standard.php} (55%) delete mode 100644 src/GraphQL/InputMapper/Search/Criterion/Text.php diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php b/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php deleted file mode 100644 index 462465e0..00000000 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeIdentifier.php +++ /dev/null @@ -1,16 +0,0 @@ -addCriterion(new Query\Criterion\ContentTypeIdentifier($value)); - } -} diff --git a/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php b/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php deleted file mode 100644 index 995abe19..00000000 --- a/src/GraphQL/InputMapper/Search/Criterion/ParentLocationId.php +++ /dev/null @@ -1,15 +0,0 @@ -addCriterion(new Query\Criterion\ParentLocationId($value)); - } -} diff --git a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/src/GraphQL/InputMapper/Search/Criterion/Standard.php similarity index 55% rename from src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php rename to src/GraphQL/InputMapper/Search/Criterion/Standard.php index 05f4d327..79d4fa29 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ b/src/GraphQL/InputMapper/Search/Criterion/Standard.php @@ -2,14 +2,20 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; -use eZ\Publish\API\Repository\Values\Content\Query; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class ContentTypeId implements QueryInputVisitor +class Standard implements QueryInputVisitor { + private $criterionClass; + + public function __construct($criterionClass) + { + $this->criterionClass = $criterionClass; + } + public function visit(QueryBuilder $queryBuilder, $value): void { - $queryBuilder->addCriterion(new Query\Criterion\ContentTypeId($value)); + $queryBuilder->addCriterion(new {$this->criterionClass}($value)); } } diff --git a/src/GraphQL/InputMapper/Search/Criterion/Text.php b/src/GraphQL/InputMapper/Search/Criterion/Text.php deleted file mode 100644 index c6c60203..00000000 --- a/src/GraphQL/InputMapper/Search/Criterion/Text.php +++ /dev/null @@ -1,16 +0,0 @@ -addCriterion(new Query\Criterion\FullText($value)); - } -} diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index 7da1a774..60cd3fb7 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -1,16 +1,26 @@ services: - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeIdentifier: - tags: - - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeIdentifier'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeId: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + arguments: + $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ContentTypeId' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeId'} EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Text: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + arguments: + $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\Fulltext' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Text'} + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ParentLocationId: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + arguments: + $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId' + tags: + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ParentLocationId'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Created: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Created'} @@ -23,10 +33,6 @@ services: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Field'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ParentLocationId: - tags: - - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ParentLocationId'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortBy: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'SortBy'} From e6fab245f92a98758ce3f8254b9eece7639d51c4 Mon Sep 17 00:00:00 2001 From: crevillo Date: Sun, 24 Feb 2019 12:10:36 +0100 Subject: [PATCH 20/26] spec for querybuilder and searchQueryMapper --- .../InputMapper/Search/QueryBuilderSpec.php | 52 ++++ .../InputMapper/SearchQueryMapperSpec.php | 259 ++---------------- .../InputMapper/Search/QueryBuilder.php | 12 +- .../InputMapper/Search/QueryInputVisitor.php | 2 - src/GraphQL/InputMapper/Search/SortBy.php | 6 +- 5 files changed, 93 insertions(+), 238 deletions(-) create mode 100644 spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php diff --git a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php new file mode 100644 index 00000000..f0f8ad0b --- /dev/null +++ b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php @@ -0,0 +1,52 @@ +shouldHaveType(QueryBuilder::class); + } + + function it_builds_a_query_when_no_citerion_is_defined() + { + $query = $this->buildQuery(); + $query->shouldBeAnInstanceOf(Query::class); + } + + function it_builds_a_query_when_only_one_criterion_is_criterion($criterion) + { + $criterion->beADoubleOf(Criterion::class); + $this->addCriterion($criterion); + $query = $this->buildQuery(); + $query->filter->shouldBe($criterion); + } + + function it_builds_a_query_when_more_than_criterion_is_passed($criterion1, $criterion2) + { + $criterion1->beADoubleOf(Criterion::class); + $criterion2->beADoubleOf(Criterion::class); + + $this->addCriterion($criterion1); + $this->addCriterion($criterion2); + + $query = $this->buildQuery(); + + $query->filter->shouldBeAnInstanceOf(Criterion\LogicalAnd::class); + } + + function it_builds_a_query_with_sort_criterias($sortBy) + { + $sortBy->beADoubleOf(Query\SortClause::class); + $this->setSortBy($sortBy); + + $query = $this->buildQuery(); + $query->sortClauses->shouldBeArray(); + } +} \ No newline at end of file diff --git a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php index 5c613961..325798e0 100644 --- a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php +++ b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php @@ -2,253 +2,52 @@ namespace spec\EzSystems\EzPlatformGraphQL\GraphQL\InputMapper; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\SearchQueryMapper; -use DateTime; -use eZ\Publish\API\Repository\Values\Content\Query; -use eZ\Publish\Core\REST\Server\Input\Parser\Criterion\Operator; use PhpSpec\ObjectBehavior; +use Prophecy\Argument; class SearchQueryMapperSpec extends ObjectBehavior { - function it_is_initializable() - { - $this->shouldHaveType(SearchQueryMapper::class); - } - - public function it_maps_ContentTypeIdentifier_to_a_ContentTypeIdentifier_criterion() - { - $this->mapInputToQuery(['ContentTypeIdentifier' => ['article']])->shouldFilterByContentType(['article']); - } - - public function it_maps_Text_to_a_FullText_criterion() - { - $this - ->mapInputToQuery(['Text' => 'graphql']) - ->shouldFilterByFullText('graphql'); - } - - public function it_maps_Modified_before_to_a_created_lte_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Modified' => ['before' => '1977/05/04']]) - ->shouldFilterByDateModified(Query\Criterion\Operator::LTE, '1977/05/04'); - } - - public function it_maps_Modified_on_to_a_created_eq_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Modified' => ['on' => '1977/05/04']]) - ->shouldFilterByDateModified(Query\Criterion\Operator::EQ, '1977/05/04'); - } - - public function it_maps_Modified_after_to_a_created_gte_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Modified' => ['after' => '1977/05/04']]) - ->shouldFilterByDateModified(Query\Criterion\Operator::GTE, '1977/05/04'); - } - - public function it_maps_Created_before_to_a_created_lte_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Created' => ['before' => '1977/05/04']]) - ->shouldFilterByDateCreated(Query\Criterion\Operator::LTE, '1977/05/04'); - } - - public function it_maps_Created_on_to_a_created_eq_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Created' => ['on' => '1977/05/04']]) - ->shouldFilterByDateCreated(Query\Criterion\Operator::EQ, '1977/05/04'); - } - - public function it_maps_Created_after_to_a_created_gte_DateMetaData_criterion() - { - $this - ->mapInputToQuery(['Created' => ['after' => '1977/05/04']]) - ->shouldFilterByDateCreated(Query\Criterion\Operator::GTE, '1977/05/04'); - } - - function it_maps_Field_to_a_Field_criterion() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'eq' => 'bar']]) - ->shouldFilterByField('target_field'); - } - - function it_maps_Field_target_to_the_Field_criterion_target() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'eq' => 'bar']]) - ->shouldFilterByField('target_field', Query\Criterion\Operator::EQ, 'bar'); - } - - function it_maps_Field_with_value_at_operator_key_to_the_Field_criterion_value() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'eq' => 'bar']]) - ->shouldFilterByField('target_field', null, 'bar'); - } - - function it_maps_Field_operator_eq_to_Field_criterion_operator_EQ() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'eq' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::EQ); - } - - function it_maps_Field_operator_in_to_Field_criterion_operator_IN() + function let(QueryInputVisitor $visitor1, QueryInputVisitor $visitor2, QueryBuilder $queryBuilder) { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'eq' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::EQ); + $this->beConstructedWith(['visitor_1' => $visitor1, 'visitor_2' => $visitor2, 'visitor_3' => $visitor2], $queryBuilder); } - function it_maps_Field_operator_lt_to_Field_criterion_operator_LT() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'lt' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::LT); - } - - function it_maps_Field_operator_lte_to_Field_criterion_operator_LTE() + function it_is_initializable() { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'lte' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::LTE); + $this->shouldHaveType(SearchQueryMapper::class); } - function it_maps_Field_operator_gte_to_Field_criterion_operator_GTE() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'gte' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::GTE); - } + function it_uses_one_visitor_and_not_the_other( + QueryInputVisitor $visitor1, + QueryInputVisitor $visitor2, + QueryBuilder $queryBuilder + ) { + $queryBuilder->buildQuery()->shouldBeCalledOnce(); - function it_maps_Field_operator_gt_to_Field_criterion_operator_GT() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'gt' => 'bar']]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::GT); - } + $visitor1->visit($queryBuilder, 'a_value')->shouldBeCalled(); + $visitor2->visit()->shouldNotBeCalled(); - function it_maps_Field_operator_between_to_Field_criterion_operator_BETWEEN() - { - $this - ->mapInputToQuery(['Field' => ['target' => 'target_field', 'between' => [10, 20]]]) - ->shouldFilterByFieldWithOperator(Query\Criterion\Operator::BETWEEN); + $this->mapInputToQuery(['visitor_1' => 'a_value']); } - public function getMatchers(): array - { - return [ - 'filterByContentType' => function(Query $query, array $contentTypes) { - $criterion = $this->findCriterionInQueryFilter( - $query, - Query\Criterion\ContentTypeIdentifier::class - ); - - if ($criterion === null) { - return false; - } - - return $criterion->value === $contentTypes; - }, - 'filterByFullText' => function(Query $query, $text) { - $criterion = $this->findCriterionInQueryFilter( - $query, - Query\Criterion\FullText::class - ); + function it_visits_same_visitor_more_than_once( + QueryInputVisitor $visitor1, + QueryInputVisitor $visitor2, + QueryBuilder $queryBuilder + ) { + $queryBuilder->buildQuery()->shouldBeCalledOnce(); - if ($criterion === null) { - return false; - } + $visitor1->visit($queryBuilder, 'a_value')->shouldBeCalledOnce(); + $visitor2->visit($queryBuilder, Argument::type('string'))->shouldBeCalledTimes(2); - return $criterion->value === $text; - }, - 'filterByDateModified' => function(Query $query, $operator, $date) { - $criterion = $this->findCriterionInQueryFilter($query, Query\Criterion\DateMetadata::class); - - if ($criterion === null) { - return false; - } - - if ($criterion->target !== Query\Criterion\DateMetadata::MODIFIED) { - return false; - } - - return $criterion->operator == $operator - && $criterion->value[0] == strtotime($date); - }, - 'filterByDateCreated' => function(Query $query, $operator, $date) { - $criterion = $this->findCriterionInQueryFilter($query, Query\Criterion\DateMetadata::class); - - if ($criterion === null) { - return false; - } - - if ($criterion->target !== Query\Criterion\DateMetadata::CREATED) { - return false; - } - - return $criterion->operator == $operator - && $criterion->value[0] == strtotime($date); - }, - 'filterByField' => function(Query $query, $field, $operator = null, $value = null) { - $criterion = $this->findCriterionInQueryFilter($query, Query\Criterion\Field::class); - - if ($criterion === null) { - return false; - } - - if ($criterion->target !== $field) { - return false; - } - - if ($operator !== null && $criterion->operator != $operator) { - return false; - } - return ($value === null || $criterion->value == $value); - }, - 'filterByFieldWithOperator' => function(Query $query, $operator) { - $criterion = $this->findCriterionInQueryFilter($query, Query\Criterion\Field::class); - if ($criterion === null) { - return false; - } - - return $criterion->operator == $operator; - } - ]; - } - - private function findCriterionInQueryFilter(Query $query, $searchedCriterionClass) - { - if ($query->filter instanceof Query\Criterion\LogicalOperator) { - return $this->findCriterionInCriterion($query->filter, $searchedCriterionClass); - } else { - if ($query->filter instanceof $searchedCriterionClass) { - return $query->filter; - } - } - - return null; + $this->mapInputToQuery([ + 'visitor_1' => 'a_value', + 'visitor_2' => 'value2', + 'visitor_3' => 'value3' + ]); } - private function findCriterionInCriterion(Query\Criterion\LogicalOperator $logicalCriterion, $searchedCriterionClass) - { - foreach ($logicalCriterion->criteria as $criterion) { - if ($criterion instanceof Query\Criterion\LogicalOperator) { - $criterion = $this->findCriterionInCriterion($criterion, $searchedCriterionClass); - if ($criterion !== null) { - return $criterion; - } - } - - if ($criterion instanceof $searchedCriterionClass) { - return $criterion; - } - } - - return null; - } } diff --git a/src/GraphQL/InputMapper/Search/QueryBuilder.php b/src/GraphQL/InputMapper/Search/QueryBuilder.php index 4ce91829..07ea6c4c 100644 --- a/src/GraphQL/InputMapper/Search/QueryBuilder.php +++ b/src/GraphQL/InputMapper/Search/QueryBuilder.php @@ -11,7 +11,9 @@ class QueryBuilder */ private $criterions = []; - /** @var Query\SortClause */ + /** + * @var Query\SortClause + */ protected $sortBy; public function addCriterion(Query\Criterion $criterion): void @@ -19,9 +21,13 @@ public function addCriterion(Query\Criterion $criterion): void $this->criterions[] = $criterion; } - public function buildQuery(): Query + public function setSortBy(Query\SortClause $sortClause): void { + $this->sortBy = $sortClause; + } + public function buildQuery(): Query + { $query = new Query(); if (count($this->criterions) === 0) { @@ -30,7 +36,9 @@ public function buildQuery(): Query $query->filter = count($this->criterions) === 1 ? $this->criterions[0] : new Query\Criterion\LogicalAnd($this->criterions); + print 'bh'; if ($this->sortBy) { + print 'ah'; $query->sortClauses = $this->sortBy; } diff --git a/src/GraphQL/InputMapper/Search/QueryInputVisitor.php b/src/GraphQL/InputMapper/Search/QueryInputVisitor.php index 01ec27a0..373762cc 100644 --- a/src/GraphQL/InputMapper/Search/QueryInputVisitor.php +++ b/src/GraphQL/InputMapper/Search/QueryInputVisitor.php @@ -2,8 +2,6 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search; -use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; - interface QueryInputVisitor { public function visit(QueryBuilder $queryBuilder, $value): void; diff --git a/src/GraphQL/InputMapper/Search/SortBy.php b/src/GraphQL/InputMapper/Search/SortBy.php index a3bd0705..7a8082da 100644 --- a/src/GraphQL/InputMapper/Search/SortBy.php +++ b/src/GraphQL/InputMapper/Search/SortBy.php @@ -2,13 +2,11 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search; -use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; - class SortBy implements QueryInputVisitor { public function visit(QueryBuilder $queryBuilder, $value): void { - $queryBuilder->sortBy = array_map( + $queryBuilder->setSortBy(array_map( function ($sortClauseClass) { static $lastSortClause; @@ -33,6 +31,6 @@ function ($sortClauseClass) { return $lastSortClause = new $sortClauseClass; }, $value - ); + )); } } From 718439321bdc4f1d1f253b0c045719c8b0eb9801 Mon Sep 17 00:00:00 2001 From: crevillo Date: Mon, 25 Feb 2019 12:35:34 +0100 Subject: [PATCH 21/26] deleted unneded folder --- .../Search/Criterion/ContentTypeId.php | 16 ------- .../InputMapper/Search/Criterion/Created.php | 10 ---- .../Search/Criterion/DateMetadata.php | 34 -------------- .../InputMapper/Search/Criterion/Field.php | 46 ------------------- .../InputMapper/Search/Criterion/Modified.php | 10 ---- GraphQL/InputMapper/Search/Criterion/Text.php | 20 -------- 6 files changed, 136 deletions(-) delete mode 100644 GraphQL/InputMapper/Search/Criterion/ContentTypeId.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Created.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/DateMetadata.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Field.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Modified.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Text.php diff --git a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php deleted file mode 100644 index ab166fca..00000000 --- a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ /dev/null @@ -1,16 +0,0 @@ - Query\Criterion\Operator::EQ, - 'before' => Query\Criterion\Operator::LTE, - 'after' => Query\Criterion\Operator::GTE, - ]; - - $criteria = []; - foreach ($value as $operator => $dateString) { - if (!isset($dateOperatorsMap[$operator])) { - echo "Not a valid operator\n"; - continue; - } - - $criteria[] = new Query\Criterion\DateMetadata( - static::TARGET, - $dateOperatorsMap[$operator], - strtotime($dateString) - ); - } - - return $criteria; - } - -} diff --git a/GraphQL/InputMapper/Search/Criterion/Field.php b/GraphQL/InputMapper/Search/Criterion/Field.php deleted file mode 100644 index fbbfeb8e..00000000 --- a/GraphQL/InputMapper/Search/Criterion/Field.php +++ /dev/null @@ -1,46 +0,0 @@ -mapInputToFieldCriterion($value); - } else { - $criteria = array_merge( - $criteria, - array_map( - function($input) { - return $this->mapInputToFieldCriterion($input); - }, - $value - ) - ); - } - - return $criteria; - } - - private function mapInputToFieldCriterion($input) - { - $operators = ['in', 'eq', 'like', 'contains', 'between', 'lt', 'lte', 'gt', 'gte']; - foreach ($operators as $opString) { - if (isset($input[$opString])) { - $value = $input[$opString]; - $operator = constant('eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator::' . strtoupper($opString)); - } - } - - if (!isset($operator)) { - throw new InvalidArgumentException("Unspecified operator"); - } - - return new Query\Criterion\Field($input['target'], $operator, $value); - } -} diff --git a/GraphQL/InputMapper/Search/Criterion/Modified.php b/GraphQL/InputMapper/Search/Criterion/Modified.php deleted file mode 100644 index 35947fc2..00000000 --- a/GraphQL/InputMapper/Search/Criterion/Modified.php +++ /dev/null @@ -1,10 +0,0 @@ - Date: Mon, 25 Feb 2019 12:37:37 +0100 Subject: [PATCH 22/26] cs --- .../GraphQL/InputMapper/Search/QueryBuilderSpec.php | 2 +- .../GraphQL/InputMapper/SearchQueryMapperSpec.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php index f0f8ad0b..093e9f0f 100644 --- a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php +++ b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php @@ -49,4 +49,4 @@ function it_builds_a_query_with_sort_criterias($sortBy) $query = $this->buildQuery(); $query->sortClauses->shouldBeArray(); } -} \ No newline at end of file +} diff --git a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php index 325798e0..be4196ef 100644 --- a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php +++ b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/SearchQueryMapperSpec.php @@ -49,5 +49,4 @@ function it_visits_same_visitor_more_than_once( 'visitor_3' => 'value3' ]); } - } From acc7834d0598ca4d1ea957a66c9d126c8d3b56f3 Mon Sep 17 00:00:00 2001 From: crevillo Date: Tue, 26 Feb 2019 19:43:23 +0100 Subject: [PATCH 23/26] spec for querybuilder and searchQueryMapper --- .../Compiler/SearchQueryMappersPass.php | 4 +--- src/Exceptions/InvalidOperatorException.php | 8 ++++++++ .../InputMapper/Search/Criterion/Created.php | 6 ++++++ .../Criterion/{Standard.php => CriterionClass.php} | 7 +++++-- .../InputMapper/Search/Criterion/DateMetadata.php | 6 +++--- .../InputMapper/Search/Criterion/Modified.php | 6 ++++++ src/GraphQL/InputMapper/Search/QueryBuilder.php | 13 ++++++------- .../Search/{SortBy.php => SortClauseVisitor.php} | 2 +- src/Resources/config/query_input_visitors.yml | 8 ++++---- 9 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 src/Exceptions/InvalidOperatorException.php rename src/GraphQL/InputMapper/Search/Criterion/{Standard.php => CriterionClass.php} (77%) rename src/GraphQL/InputMapper/Search/{SortBy.php => SortClauseVisitor.php} (94%) diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index e4b651c4..bcfbc697 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -9,15 +9,13 @@ class SearchQueryMappersPass implements CompilerPassInterface { - const ID = SearchQueryMapper::class; - public function process(ContainerBuilder $container) { if (!$container->has(self::ID)) { return; } - $definition = $container->findDefinition(self::ID); + $definition = $container->findDefinition(SearchQueryMapper::class); $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor'); $queryInputVisitors = []; diff --git a/src/Exceptions/InvalidOperatorException.php b/src/Exceptions/InvalidOperatorException.php new file mode 100644 index 00000000..cda32fb6 --- /dev/null +++ b/src/Exceptions/InvalidOperatorException.php @@ -0,0 +1,8 @@ +visitCriterion($queryBuilder, $value, self::TARGET); + } } diff --git a/src/GraphQL/InputMapper/Search/Criterion/Standard.php b/src/GraphQL/InputMapper/Search/Criterion/CriterionClass.php similarity index 77% rename from src/GraphQL/InputMapper/Search/Criterion/Standard.php rename to src/GraphQL/InputMapper/Search/Criterion/CriterionClass.php index 79d4fa29..7c5d3a9c 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Standard.php +++ b/src/GraphQL/InputMapper/Search/Criterion/CriterionClass.php @@ -5,11 +5,14 @@ use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class Standard implements QueryInputVisitor +class CriterionClass implements QueryInputVisitor { + /** + * @var string + */ private $criterionClass; - public function __construct($criterionClass) + public function __construct(string $criterionClass) { $this->criterionClass = $criterionClass; } diff --git a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php index ad747d60..1860b0a1 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php +++ b/src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php @@ -6,9 +6,9 @@ use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; -class DateMetadata implements QueryInputVisitor +abstract class DateMetadata implements QueryInputVisitor { - public function visit(QueryBuilder $queryBuilder, $value): void + protected function visitCriterion(QueryBuilder $queryBuilder, $value, string $criterion): void { $dateOperatorsMap = [ 'on' => Query\Criterion\Operator::EQ, @@ -23,7 +23,7 @@ public function visit(QueryBuilder $queryBuilder, $value): void } $queryBuilder->addCriterion(new Query\Criterion\DateMetadata( - static::TARGET, + $criterion, $dateOperatorsMap[$operator], strtotime($dateString) )); diff --git a/src/GraphQL/InputMapper/Search/Criterion/Modified.php b/src/GraphQL/InputMapper/Search/Criterion/Modified.php index 89332150..274fda92 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Modified.php +++ b/src/GraphQL/InputMapper/Search/Criterion/Modified.php @@ -3,8 +3,14 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion; use eZ\Publish\API\Repository\Values\Content\Query; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; class Modified extends DateMetadata { const TARGET = Query\Criterion\DateMetadata::MODIFIED; + + public function visit(QueryBuilder $queryBuilder, $value): void + { + $this->visitCriterion($queryBuilder, $value, self::TARGET); + } } diff --git a/src/GraphQL/InputMapper/Search/QueryBuilder.php b/src/GraphQL/InputMapper/Search/QueryBuilder.php index 07ea6c4c..50877d97 100644 --- a/src/GraphQL/InputMapper/Search/QueryBuilder.php +++ b/src/GraphQL/InputMapper/Search/QueryBuilder.php @@ -3,13 +3,14 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search; use eZ\Publish\API\Repository\Values\Content\Query; +use eZ\Publish\Core\REST\Server\Input\Parser\Criterion; class QueryBuilder { /** - * @var array + * @var Criterion[] */ - private $criterions = []; + private $criteria = []; /** * @var Query\SortClause @@ -18,7 +19,7 @@ class QueryBuilder public function addCriterion(Query\Criterion $criterion): void { - $this->criterions[] = $criterion; + $this->criteria[] = $criterion; } public function setSortBy(Query\SortClause $sortClause): void @@ -30,15 +31,13 @@ public function buildQuery(): Query { $query = new Query(); - if (count($this->criterions) === 0) { + if (count($this->criteria) === 0) { return $query; } - $query->filter = count($this->criterions) === 1 ? $this->criterions[0] : new Query\Criterion\LogicalAnd($this->criterions); + $query->filter = count($this->criteria) === 1 ? $this->criteria[0] : new Query\Criterion\LogicalAnd($this->criteria); - print 'bh'; if ($this->sortBy) { - print 'ah'; $query->sortClauses = $this->sortBy; } diff --git a/src/GraphQL/InputMapper/Search/SortBy.php b/src/GraphQL/InputMapper/Search/SortClauseVisitor.php similarity index 94% rename from src/GraphQL/InputMapper/Search/SortBy.php rename to src/GraphQL/InputMapper/Search/SortClauseVisitor.php index 7a8082da..9f50d671 100644 --- a/src/GraphQL/InputMapper/Search/SortBy.php +++ b/src/GraphQL/InputMapper/Search/SortClauseVisitor.php @@ -2,7 +2,7 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search; -class SortBy implements QueryInputVisitor +class SortClauseVisitor implements QueryInputVisitor { public function visit(QueryBuilder $queryBuilder, $value): void { diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index 60cd3fb7..a60972be 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -1,20 +1,20 @@ services: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeId: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ContentTypeId' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeId'} EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Text: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\Fulltext' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Text'} EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ParentLocationId: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Standard + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId' tags: @@ -33,6 +33,6 @@ services: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Field'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortBy: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauseVisitor: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'SortBy'} From 7b22af18c265079a8b5f6b687d6bc97ae4e34300 Mon Sep 17 00:00:00 2001 From: crevillo Date: Wed, 27 Feb 2019 07:03:18 +0100 Subject: [PATCH 24/26] wip --- .../InputMapper/Search/QueryBuilderSpec.php | 8 ++-- .../Compiler/SearchQueryMappersPass.php | 4 +- .../{Criterion => Criteria}/Created.php | 2 +- .../CriterionClass.php | 2 +- .../{Criterion => Criteria}/DateMetadata.php | 2 +- .../Search/{Criterion => Criteria}/Field.php | 2 +- .../{Criterion => Criteria}/Modified.php | 2 +- .../InputMapper/Search/QueryBuilder.php | 21 ++++------ .../Search/SortClauses/SortClauseClass.php | 41 +++++++++++++++++++ src/GraphQL/InputMapper/SearchQueryMapper.php | 32 ++++++++++++--- src/Resources/config/query_input_visitors.yml | 18 ++++---- 11 files changed, 96 insertions(+), 38 deletions(-) rename src/GraphQL/InputMapper/Search/{Criterion => Criteria}/Created.php (97%) rename src/GraphQL/InputMapper/Search/{Criterion => Criteria}/CriterionClass.php (98%) rename src/GraphQL/InputMapper/Search/{Criterion => Criteria}/DateMetadata.php (98%) rename src/GraphQL/InputMapper/Search/{Criterion => Criteria}/Field.php (99%) rename src/GraphQL/InputMapper/Search/{Criterion => Criteria}/Modified.php (97%) create mode 100644 src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php diff --git a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php index f0f8ad0b..3998be22 100644 --- a/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php +++ b/spec/EzSystems/EzPlatformGraphQL/GraphQL/InputMapper/Search/QueryBuilderSpec.php @@ -41,12 +41,12 @@ function it_builds_a_query_when_more_than_criterion_is_passed($criterion1, $crit $query->filter->shouldBeAnInstanceOf(Criterion\LogicalAnd::class); } - function it_builds_a_query_with_sort_criterias($sortBy) + function it_builds_a_query_with_sort_criterias($sortClause) { - $sortBy->beADoubleOf(Query\SortClause::class); - $this->setSortBy($sortBy); + $sortClause->beADoubleOf(Query\SortClause::class); + $this->addSortClause($sortClause); $query = $this->buildQuery(); $query->sortClauses->shouldBeArray(); } -} \ No newline at end of file +} diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index bcfbc697..bfe68969 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -16,10 +16,10 @@ public function process(ContainerBuilder $container) } $definition = $container->findDefinition(SearchQueryMapper::class); - $taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor'); + $criteriaTaggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_criterion_visitor'); $queryInputVisitors = []; - foreach ($taggedServices as $id => $tags) { + foreach ($criteriaTaggedServices as $id => $tags) { foreach ($tags as $tag) { if (isset($tag['inputKey'])) { $queryInputVisitors[$tag['inputKey']] = new Reference($id); diff --git a/src/GraphQL/InputMapper/Search/Criterion/Created.php b/src/GraphQL/InputMapper/Search/Criteria/Created.php similarity index 97% rename from src/GraphQL/InputMapper/Search/Criterion/Created.php rename to src/GraphQL/InputMapper/Search/Criteria/Created.php index 94484d17..869259e8 100644 --- a/src/GraphQL/InputMapper/Search/Criterion/Created.php +++ b/src/GraphQL/InputMapper/Search/Criteria/Created.php @@ -1,6 +1,6 @@ criteria[] = $criterion; } - public function setSortBy(Query\SortClause $sortClause): void + public function addSortClause(Query\SortClause $sortClause): void { - $this->sortBy = $sortClause; + $this->sortClauses[] = $sortClause; } public function buildQuery(): Query { $query = new Query(); - if (count($this->criteria) === 0) { - return $query; + if (count($this->criteria) > 0) { + $query->filter = count($this->criteria) === 1 ? $this->criteria[0] : new Query\Criterion\LogicalAnd($this->criteria); } - $query->filter = count($this->criteria) === 1 ? $this->criteria[0] : new Query\Criterion\LogicalAnd($this->criteria); - - if ($this->sortBy) { - $query->sortClauses = $this->sortBy; + if (count($this->sortClauses) > 0) { + $query->sortClauses = $this->sortClauses; } return $query; diff --git a/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php b/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php new file mode 100644 index 00000000..d02ff3b8 --- /dev/null +++ b/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php @@ -0,0 +1,41 @@ +addSortClause(array_map( + function ($sortClauseClass) { + + static $lastSortClause; + + if ($sortClauseClass === Query::SORT_DESC) { + if (!$lastSortClause instanceof Query\SortClause) { + return null; + } + + $lastSortClause->direction = $sortClauseClass; + return null; + } + + if (!class_exists($sortClauseClass)) { + return null; + } + + if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { + return null; + } + + return $lastSortClause = new $sortClauseClass; + }, + $value + )); + } + +} diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index bf69216f..74026c91 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -10,17 +10,33 @@ use eZ\Publish\API\Repository\Values\Content\Query; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; use InvalidArgumentException; class SearchQueryMapper { - private $queryInputVisitors; + /** + * @var QueryInputVisitor[] + */ + private $queryInputCriteriaVisitors; + + /** + * @var QueryInputVisitor[] + */ + private $queryInputSortClauseVisitors; + /** + * @var QueryBuilder + */ private $queryBuilder; - public function __construct(array $queryInputVisitors, QueryBuilder $queryBuilder) - { - $this->queryInputVisitors = $queryInputVisitors; + public function __construct( + array $queryInputCriteriaVisitors, + array $queryInputSortClauseVisitors, + QueryBuilder $queryBuilder + ) { + $this->queryInputCriteriaVisitors = $queryInputCriteriaVisitors; + $this->queryInputSortClauseVisitors = $queryInputSortClauseVisitors; $this->queryBuilder = $queryBuilder; } @@ -30,8 +46,12 @@ public function __construct(array $queryInputVisitors, QueryBuilder $queryBuilde public function mapInputToQuery(array $inputArray) : Query { foreach ($inputArray as $inputField => $inputValue) { - if (isset($this->queryInputVisitors[$inputField])) { - $this->queryInputVisitors[$inputField]->visit($this->queryBuilder, $inputValue); + if (isset($this->queryInputCriteriaVisitors[$inputField])) { + $this->queryInputCriteriaVisitors[$inputField]->visit($this->queryBuilder, $inputValue); + } + + if (isset($this->queryInputSortClauseVisitors[$inputField])) { + $this->queryInputSortClauseVisitors[$inputField]->visit($this->queryBuilder, $inputValue); } } diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index a60972be..78e5cdce 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -1,35 +1,35 @@ services: - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ContentTypeId: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\ContentTypeId: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ContentTypeId' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ContentTypeId'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Text: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\Text: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\Fulltext' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Text'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\ParentLocationId: - class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\CriterionClass + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\ParentLocationId: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\CriterionClass arguments: $criterionClass: 'eZ\Publish\API\Repository\Values\Content\Query\Criterion\ParentLocationId' tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ParentLocationId'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Created: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\Created: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Created'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Modified: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\Modified: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Modified'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion\Field: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\Field: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Field'} From d4a0b703d2a81492c5a021be338c87363e9d920b Mon Sep 17 00:00:00 2001 From: crevillo Date: Sat, 2 Mar 2019 12:02:16 +0100 Subject: [PATCH 25/26] wip --- .../Search/Criterion/ContentTypeId.php | 16 ------- .../InputMapper/Search/Criterion/Created.php | 10 ---- .../Search/Criterion/DateMetadata.php | 34 -------------- .../InputMapper/Search/Criterion/Field.php | 46 ------------------- .../InputMapper/Search/Criterion/Modified.php | 10 ---- GraphQL/InputMapper/Search/Criterion/Text.php | 20 -------- src/GraphQL/InputMapper/Search/SortBy.php | 21 +++++++++ .../InputMapper/Search/SortClauseVisitor.php | 32 +------------ src/GraphQL/InputMapper/SearchQueryMapper.php | 30 +++--------- src/Resources/config/query_input_visitors.yml | 2 +- 10 files changed, 31 insertions(+), 190 deletions(-) delete mode 100644 GraphQL/InputMapper/Search/Criterion/ContentTypeId.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Created.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/DateMetadata.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Field.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Modified.php delete mode 100644 GraphQL/InputMapper/Search/Criterion/Text.php create mode 100644 src/GraphQL/InputMapper/Search/SortBy.php diff --git a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php b/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php deleted file mode 100644 index ab166fca..00000000 --- a/GraphQL/InputMapper/Search/Criterion/ContentTypeId.php +++ /dev/null @@ -1,16 +0,0 @@ - Query\Criterion\Operator::EQ, - 'before' => Query\Criterion\Operator::LTE, - 'after' => Query\Criterion\Operator::GTE, - ]; - - $criteria = []; - foreach ($value as $operator => $dateString) { - if (!isset($dateOperatorsMap[$operator])) { - echo "Not a valid operator\n"; - continue; - } - - $criteria[] = new Query\Criterion\DateMetadata( - static::TARGET, - $dateOperatorsMap[$operator], - strtotime($dateString) - ); - } - - return $criteria; - } - -} diff --git a/GraphQL/InputMapper/Search/Criterion/Field.php b/GraphQL/InputMapper/Search/Criterion/Field.php deleted file mode 100644 index fbbfeb8e..00000000 --- a/GraphQL/InputMapper/Search/Criterion/Field.php +++ /dev/null @@ -1,46 +0,0 @@ -mapInputToFieldCriterion($value); - } else { - $criteria = array_merge( - $criteria, - array_map( - function($input) { - return $this->mapInputToFieldCriterion($input); - }, - $value - ) - ); - } - - return $criteria; - } - - private function mapInputToFieldCriterion($input) - { - $operators = ['in', 'eq', 'like', 'contains', 'between', 'lt', 'lte', 'gt', 'gte']; - foreach ($operators as $opString) { - if (isset($input[$opString])) { - $value = $input[$opString]; - $operator = constant('eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator::' . strtoupper($opString)); - } - } - - if (!isset($operator)) { - throw new InvalidArgumentException("Unspecified operator"); - } - - return new Query\Criterion\Field($input['target'], $operator, $value); - } -} diff --git a/GraphQL/InputMapper/Search/Criterion/Modified.php b/GraphQL/InputMapper/Search/Criterion/Modified.php deleted file mode 100644 index 35947fc2..00000000 --- a/GraphQL/InputMapper/Search/Criterion/Modified.php +++ /dev/null @@ -1,10 +0,0 @@ -sortClauseVisitors = $sortClauseVisitors; + } + + public function visit(QueryBuilder $queryBuilder, $value): void + { + // TODO: Implement visit() method. + } +} diff --git a/src/GraphQL/InputMapper/Search/SortClauseVisitor.php b/src/GraphQL/InputMapper/Search/SortClauseVisitor.php index 9f50d671..b2f530d4 100644 --- a/src/GraphQL/InputMapper/Search/SortClauseVisitor.php +++ b/src/GraphQL/InputMapper/Search/SortClauseVisitor.php @@ -2,35 +2,7 @@ namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search; -class SortClauseVisitor implements QueryInputVisitor +interface SortClauseVisitor { - public function visit(QueryBuilder $queryBuilder, $value): void - { - $queryBuilder->setSortBy(array_map( - function ($sortClauseClass) { - - static $lastSortClause; - - if ($sortClauseClass === Query::SORT_DESC) { - if (!$lastSortClause instanceof Query\SortClause) { - return null; - } - - $lastSortClause->direction = $sortClauseClass; - return null; - } - - if (!class_exists($sortClauseClass)) { - return null; - } - - if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { - return null; - } - - return $lastSortClause = new $sortClauseClass; - }, - $value - )); - } + public function visit(QueryBuilder $queryBuilder, $value): void; } diff --git a/src/GraphQL/InputMapper/SearchQueryMapper.php b/src/GraphQL/InputMapper/SearchQueryMapper.php index 74026c91..e0f5cc6b 100644 --- a/src/GraphQL/InputMapper/SearchQueryMapper.php +++ b/src/GraphQL/InputMapper/SearchQueryMapper.php @@ -1,10 +1,4 @@ queryInputCriteriaVisitors = $queryInputCriteriaVisitors; - $this->queryInputSortClauseVisitors = $queryInputSortClauseVisitors; + $this->queryInputVisitors = $queryInputVisitors; $this->queryBuilder = $queryBuilder; } /** - * @return \eZ\Publish\API\Repository\Values\Content\Query + * @param array $inputArray + * @return Query */ public function mapInputToQuery(array $inputArray) : Query { foreach ($inputArray as $inputField => $inputValue) { - if (isset($this->queryInputCriteriaVisitors[$inputField])) { - $this->queryInputCriteriaVisitors[$inputField]->visit($this->queryBuilder, $inputValue); - } - - if (isset($this->queryInputSortClauseVisitors[$inputField])) { - $this->queryInputSortClauseVisitors[$inputField]->visit($this->queryBuilder, $inputValue); + if (isset($this->queryInputVisitors[$inputField])) { + $this->queryInputVisitors[$inputField]->visit($this->queryBuilder, $inputValue); } } diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index 78e5cdce..00c724a4 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -33,6 +33,6 @@ services: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Field'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauseVisitor: + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortBy: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'SortBy'} From af2fbf66853ea74f0145f6d69f8688296f41f09c Mon Sep 17 00:00:00 2001 From: crevillo Date: Sun, 3 Mar 2019 14:15:01 +0100 Subject: [PATCH 26/26] refactor to have visitors for sort clauses --- ...mainContentCollectionToDomainGroupSpec.php | 2 +- .../Compiler/SearchQueryMappersPass.php | 4 +- .../Compiler/SearchSortClauseMappersPass.php | 33 ++++++++++++++ src/EzSystemsEzPlatformGraphQLBundle.php | 1 + .../Search/Criteria/CriterionClass.php | 2 +- src/GraphQL/InputMapper/Search/SortBy.php | 8 +++- .../Search/SortClauses/SortClauseClass.php | 43 +++++++----------- src/Resources/config/graphql/Search.types.yml | 31 ++++++------- src/Resources/config/query_input_visitors.yml | 45 ++++++++++++++++++- ...ddDomainContentCollectionToDomainGroup.php | 4 +- 10 files changed, 119 insertions(+), 54 deletions(-) create mode 100644 src/DependencyInjection/Compiler/SearchSortClauseMappersPass.php diff --git a/spec/EzSystems/EzPlatformGraphQL/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroupSpec.php b/spec/EzSystems/EzPlatformGraphQL/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroupSpec.php index 0edc0f2d..703edbab 100644 --- a/spec/EzSystems/EzPlatformGraphQL/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroupSpec.php +++ b/spec/EzSystems/EzPlatformGraphQL/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroupSpec.php @@ -89,7 +89,7 @@ function it_adds_a_collection_field_for_the_ContentType_to_the_ContentTypeGroup( self::COLLECTION_FIELD, Argument::allOf( FieldArgArgument::withName('sortBy'), - FieldArgArgument::withType('[SortByOptions]') + FieldArgArgument::withType('SortByOptions∫') ) ) ->shouldBeCalled(); diff --git a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php index bfe68969..5911f1ea 100644 --- a/src/DependencyInjection/Compiler/SearchQueryMappersPass.php +++ b/src/DependencyInjection/Compiler/SearchQueryMappersPass.php @@ -11,12 +11,12 @@ class SearchQueryMappersPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { - if (!$container->has(self::ID)) { + if (!$container->has(SearchQueryMapper::class)) { return; } $definition = $container->findDefinition(SearchQueryMapper::class); - $criteriaTaggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_criterion_visitor'); + $criteriaTaggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor'); $queryInputVisitors = []; foreach ($criteriaTaggedServices as $id => $tags) { diff --git a/src/DependencyInjection/Compiler/SearchSortClauseMappersPass.php b/src/DependencyInjection/Compiler/SearchSortClauseMappersPass.php new file mode 100644 index 00000000..85bb9ac9 --- /dev/null +++ b/src/DependencyInjection/Compiler/SearchSortClauseMappersPass.php @@ -0,0 +1,33 @@ +has(SortBy::class)) { + return; + } + + $definition = $container->findDefinition(SortBy::class); + $sortClauseTaggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_sortclause_visitor'); + + $sortClauseVisitors = []; + foreach ($sortClauseTaggedServices as $id => $tags) { + foreach ($tags as $tag) { + if (isset($tag['inputKey'])) { + $sortClauseVisitors[$tag['inputKey']] = new Reference($id); + } + } + } + + $definition->setArgument('$sortClauseVisitors', $sortClauseVisitors); + } + +} diff --git a/src/EzSystemsEzPlatformGraphQLBundle.php b/src/EzSystemsEzPlatformGraphQLBundle.php index dac19fa0..481673c9 100644 --- a/src/EzSystemsEzPlatformGraphQLBundle.php +++ b/src/EzSystemsEzPlatformGraphQLBundle.php @@ -17,5 +17,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new Compiler\SchemaWorkersPass()); $container->addCompilerPass(new Compiler\SchemaDomainIteratorsPass()); $container->addCompilerPass(new Compiler\SearchQueryMappersPass()); + $container->addCompilerPass(new Compiler\SearchSortClauseMappersPass()); } } diff --git a/src/GraphQL/InputMapper/Search/Criteria/CriterionClass.php b/src/GraphQL/InputMapper/Search/Criteria/CriterionClass.php index 28c4f05b..85b4d0f0 100644 --- a/src/GraphQL/InputMapper/Search/Criteria/CriterionClass.php +++ b/src/GraphQL/InputMapper/Search/Criteria/CriterionClass.php @@ -19,6 +19,6 @@ public function __construct(string $criterionClass) public function visit(QueryBuilder $queryBuilder, $value): void { - $queryBuilder->addCriterion(new {$this->criterionClass}($value)); + $queryBuilder->addCriterion(new $this->criterionClass($value)); } } diff --git a/src/GraphQL/InputMapper/Search/SortBy.php b/src/GraphQL/InputMapper/Search/SortBy.php index 81c2aa18..678b1e50 100644 --- a/src/GraphQL/InputMapper/Search/SortBy.php +++ b/src/GraphQL/InputMapper/Search/SortBy.php @@ -9,13 +9,17 @@ class SortBy implements QueryInputVisitor */ private $sortClauseVisitors; - public function __construct(array $sortClauseVisitors) + public function __construct(array $sortClauseVisitors = []) { $this->sortClauseVisitors = $sortClauseVisitors; } public function visit(QueryBuilder $queryBuilder, $value): void { - // TODO: Implement visit() method. + foreach ($value as $inputKey => $inputValue) { + if (isset($this->sortClauseVisitors[$inputKey])) { + $this->sortClauseVisitors[$inputKey]->visit($queryBuilder, $inputValue); + } + } } } diff --git a/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php b/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php index d02ff3b8..05f47e10 100644 --- a/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php +++ b/src/GraphQL/InputMapper/Search/SortClauses/SortClauseClass.php @@ -5,37 +5,26 @@ use eZ\Publish\API\Repository\Values\Content\Query; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder; use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor; +use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauseVisitor; -class SortClauseClass implements QueryInputVisitor +class SortClauseClass implements SortClauseVisitor { - public function visit(QueryBuilder $queryBuilder, $value): void - { - $queryBuilder->addSortClause(array_map( - function ($sortClauseClass) { - - static $lastSortClause; - - if ($sortClauseClass === Query::SORT_DESC) { - if (!$lastSortClause instanceof Query\SortClause) { - return null; - } - - $lastSortClause->direction = $sortClauseClass; - return null; - } + /** + * @var string + */ + private $sortClauseClass; - if (!class_exists($sortClauseClass)) { - return null; - } + public function __construct(string $sortClauseClass) + { + $this->sortClauseClass = $sortClauseClass; + } - if (!in_array(Query\SortClause::class, class_parents($sortClauseClass))) { - return null; - } + public function visit(QueryBuilder $queryBuilder, $value): void + { + if (empty($value)) { + $value = Query::SORT_ASC; + } - return $lastSortClause = new $sortClauseClass; - }, - $value - )); + $queryBuilder->addSortClause(new $this->sortClauseClass($value)); } - } diff --git a/src/Resources/config/graphql/Search.types.yml b/src/Resources/config/graphql/Search.types.yml index 0ce5ddb1..f72a2ff3 100644 --- a/src/Resources/config/graphql/Search.types.yml +++ b/src/Resources/config/graphql/Search.types.yml @@ -84,27 +84,24 @@ DateCriterionOperator: after: {} SortByOptions: - type: enum + type: "input-object" config: - values: - _contentId: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\ContentId' + fields: + ContentId: + type: "String" description: "Sort by content id" - _name: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\ContentName' + Name: + type: "String" description: "Sort by content name" - _dateModified: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\DateModified' + DateModified: + type: "String" description: "Sort by last modification date" - _datePublished: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\DatePublished' + DatePublished: + type: "String" description: "Sort by initial publication date" - _sectionIdentifier: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\SectionIdentifier' + SectionIdentifier: + type: "String" description: "Sort by content section identifier" - _sectionName: - value: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\SectionName' + SectionName: + type: "String" description: "Sort by section name" - _desc: - value: 'descending' - description: "Reverse the previous sorting option" diff --git a/src/Resources/config/query_input_visitors.yml b/src/Resources/config/query_input_visitors.yml index 00c724a4..b52542f2 100644 --- a/src/Resources/config/query_input_visitors.yml +++ b/src/Resources/config/query_input_visitors.yml @@ -20,7 +20,6 @@ services: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'ParentLocationId'} - EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criteria\Created: tags: - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'Created'} @@ -35,4 +34,46 @@ services: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortBy: tags: - - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'SortBy'} + - {name: 'ezplatform_graphql.query_input_visitor', inputKey: 'sortBy'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\ContentName: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\ContentName' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'Name'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\ContentId: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\ContentId' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'ContentId'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\DateModified: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\DateModified' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'DateModified'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\DatePublished: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\DatePublished' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'DatePublished'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SectionIdentifier: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\SectionIdentifier' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'SectionIdentifier'} + + EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SectionName: + class: EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\SortClauses\SortClauseClass + arguments: + $sortClauseClass: '\eZ\Publish\API\Repository\Values\Content\Query\SortClause\SectionName' + tags: + - {name: 'ezplatform_graphql.query_sortclause_visitor', inputKey: 'SectionName'} diff --git a/src/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroup.php b/src/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroup.php index bd32f6fb..f4db2047 100644 --- a/src/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroup.php +++ b/src/Schema/Domain/Content/Worker/ContentType/AddDomainContentCollectionToDomainGroup.php @@ -33,7 +33,7 @@ public function work(Builder $schema, array $args) )); $schema->addArgToField($this->groupName($args), $this->typeCollectionField($args), new Input\Arg( - 'sortBy', '[SortByOptions]', + 'sortBy', 'SortByOptions', ['description' => "A sort clause, or array of clauses. Add _desc after a clause to reverse it"] )); } @@ -62,4 +62,4 @@ protected function typeName($args): string { return $this->getNameHelper()->domainContentName($args['ContentType']); } -} \ No newline at end of file +}