Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor query mapper #8

Open
wants to merge 27 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0dbc81e
add compiler pass for search query mappers
crevillo Jan 26, 2019
ffa7bf7
add dedicated file for search query mappers and load it
crevillo Jan 26, 2019
cb3f444
define interface for searchCriterion and first of them
crevillo Jan 26, 2019
83bf501
create rest of the current available search criterions
crevillo Jan 26, 2019
8f0ad91
rename method name
crevillo Jan 26, 2019
4639965
add method to check if inputField can be mapped to a criteria
crevillo Jan 26, 2019
4b19c66
extract sortByPart logic to dedicate method
crevillo Jan 26, 2019
2279ce2
update namespaces after conflict resolution
crevillo Jan 28, 2019
a0925a7
add dedicated file for search query mappers and load it
crevillo Jan 26, 2019
6d9b245
define interface for searchCriterion and first of them
crevillo Jan 26, 2019
75ec18d
create rest of the current available search criterions
crevillo Jan 26, 2019
594c2a0
rename method name
crevillo Jan 26, 2019
832969c
updated namespaces after conflict
crevillo Jan 28, 2019
8ed08be
some typehints
crevillo Jan 28, 2019
eea3c5c
rename file with the visitors
crevillo Jan 28, 2019
05aa445
add querybuilder and adapt all the visitors to the new interface
crevillo Jan 29, 2019
cd4cb88
use "class" constant instead of string
crevillo Feb 1, 2019
a0b555e
remove unneded var
crevillo Feb 1, 2019
4494d2a
add basic criterion visitor
crevillo Feb 4, 2019
e6fab24
spec for querybuilder and searchQueryMapper
crevillo Feb 24, 2019
7184393
deleted unneded folder
crevillo Feb 25, 2019
37dcd75
cs
crevillo Feb 25, 2019
acc7834
spec for querybuilder and searchQueryMapper
crevillo Feb 26, 2019
7b22af1
wip
crevillo Feb 27, 2019
d4a0b70
wip
crevillo Mar 2, 2019
4cf468b
Merge branch 'refactor-query-mapper' of github.com:crevillo/ezplatfor…
crevillo Mar 2, 2019
af2fbf6
refactor to have visitors for sort clauses
crevillo Mar 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/ContentTypeId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace BD\EzPlatformGraphQLBundle\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;

class ContentTypeId implements SearchCriterion
{
public function map($value): array
{
return [new Query\Criterion\ContentTypeId($value)];
}

}
10 changes: 10 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/Created.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class Created extends DateMetadata
{
const TARGET = Query\Criterion\DateMetadata::CREATED;
}
34 changes: 34 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/DateMetadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class DateMetadata implements SearchCriterion
crevillo marked this conversation as resolved.
Show resolved Hide resolved
{
public function map($value): array
{
$dateOperatorsMap = [
'on' => 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";
crevillo marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

$criteria[] = new Query\Criterion\DateMetadata(
static::TARGET,
$dateOperatorsMap[$operator],
strtotime($dateString)
);
}

return $criteria;
}

}
46 changes: 46 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/Field.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class Field implements SearchCriterion
{
public function map($value): array
{
$criteria = [];

if (isset($value['target'])) {
$criteria[] = $this->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);
}
}
10 changes: 10 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/Modified.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class Modified extends DateMetadata
{
const TARGET = Query\Criterion\DateMetadata::MODIFIED;
}
20 changes: 20 additions & 0 deletions GraphQL/InputMapper/Search/Criterion/Text.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace BD\EzPlatformGraphQLBundle\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query\CriterionInterface;
use eZ\Publish\API\Repository\Values\Content\Query;

class Text implements SearchCriterion
{
public function map($value): array
{
$criteria = [];
crevillo marked this conversation as resolved.
Show resolved Hide resolved

foreach ($value as $text) {
$criteria[] = new Query\Criterion\FullText($text);
}

return $criteria;
}
}
34 changes: 34 additions & 0 deletions src/DependencyInjection/Compiler/SearchQueryMappersPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace EzSystems\EzPlatformGraphQL\DependencyInjection\Compiler;

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 = SearchQueryMapper::class;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually wouldn't use a class constant for that. It doesn't deduplicate much, and does so at the cost of readability. I'd use SearchQueryMapper::class directly inside the method.


public function process(ContainerBuilder $container)
{
if (!$container->has(self::ID)) {
return;
}

$definition = $container->findDefinition(self::ID);
$taggedServices = $container->findTaggedServiceIds('ezplatform_graphql.query_input_visitor');

$queryInputVisitors = [];
foreach ($taggedServices as $id => $tags) {
foreach ($tags as $tag) {
if (isset($tag['inputKey'])) {
$queryInputVisitors[$tag['inputKey']] = new Reference($id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: the advantage of this is that a query input visitor can be overridden using the key. Useful.

}
}
}

$definition->setArgument('$queryInputVisitors', $queryInputVisitors);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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('query_input_visitors.yml');
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/EzSystemsEzPlatformGraphQLBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new Compiler\FieldValueBuildersPass());
$container->addCompilerPass(new Compiler\SchemaWorkersPass());
$container->addCompilerPass(new Compiler\SchemaDomainIteratorsPass());
$container->addCompilerPass(new Compiler\SearchQueryMappersPass());
}
}
10 changes: 10 additions & 0 deletions src/GraphQL/InputMapper/Search/Criterion/Created.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class Created extends DateMetadata
{
const TARGET = Query\Criterion\DateMetadata::CREATED;
}
32 changes: 32 additions & 0 deletions src/GraphQL/InputMapper/Search/Criterion/DateMetadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

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 QueryInputVisitor
crevillo marked this conversation as resolved.
Show resolved Hide resolved
{
public function visit(QueryBuilder $queryBuilder, $value): void
{
$dateOperatorsMap = [
'on' => Query\Criterion\Operator::EQ,
'before' => Query\Criterion\Operator::LTE,
'after' => Query\Criterion\Operator::GTE,
];

foreach ($value as $operator => $dateString) {
if (!isset($dateOperatorsMap[$operator])) {
echo "Not a valid operator\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed to an exception. You could add a new one to the package, in src/Exceptions. Maybe InvalidQueryOperatorException ?

continue;
}

$queryBuilder->addCriterion(new Query\Criterion\DateMetadata(
static::TARGET,
$dateOperatorsMap[$operator],
strtotime($dateString)
));
}
}
}
50 changes: 50 additions & 0 deletions src/GraphQL/InputMapper/Search/Criterion/Field.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

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 QueryInputVisitor
{
public function visit(QueryBuilder $queryBuilder, $value): void
{
$criteria = [];

if (isset($value['target'])) {
$criteria[] = $this->mapInputToFieldCriterion($value);
} else {
$criteria = array_merge(
$criteria,
array_map(
function($input) {
return $this->mapInputToFieldCriterion($input);
},
$value
)
);
}

foreach ($criteria as $criterion) {
$queryBuilder->addCriterion($criterion);
}
}

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);
}
}
10 changes: 10 additions & 0 deletions src/GraphQL/InputMapper/Search/Criterion/Modified.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion;

use eZ\Publish\API\Repository\Values\Content\Query;

class Modified extends DateMetadata
{
const TARGET = Query\Criterion\DateMetadata::MODIFIED;
}
21 changes: 21 additions & 0 deletions src/GraphQL/InputMapper/Search/Criterion/Standard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\Criterion;

use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder;
use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryInputVisitor;

class Standard implements QueryInputVisitor
crevillo marked this conversation as resolved.
Show resolved Hide resolved
{
private $criterionClass;

public function __construct($criterionClass)
{
$this->criterionClass = $criterionClass;
}

public function visit(QueryBuilder $queryBuilder, $value): void
{
$queryBuilder->addCriterion(new {$this->criterionClass}($value));
}
}
39 changes: 39 additions & 0 deletions src/GraphQL/InputMapper/Search/QueryBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search;

use eZ\Publish\API\Repository\Values\Content\Query;

class QueryBuilder
{
/**
* @var array
crevillo marked this conversation as resolved.
Show resolved Hide resolved
*/
private $criterions = [];
crevillo marked this conversation as resolved.
Show resolved Hide resolved

/** @var Query\SortClause */
protected $sortBy;

public function addCriterion(Query\Criterion $criterion): void
{
$this->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;
}
}
10 changes: 10 additions & 0 deletions src/GraphQL/InputMapper/Search/QueryInputVisitor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search;

use EzSystems\EzPlatformGraphQL\GraphQL\InputMapper\Search\QueryBuilder;

interface QueryInputVisitor
{
public function visit(QueryBuilder $queryBuilder, $value): void;
}
Loading