Skip to content

Commit

Permalink
Merge pull request #8 from TomHAnderson/feature/class-normalization
Browse files Browse the repository at this point in the history
Feature/class normalization
  • Loading branch information
TomHAnderson authored Jun 22, 2018
2 parents 17d78b0 + 86d2bfc commit 59aca60
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 110 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ fieldName_between - Fiilter between `from` and `to` values. Good substitute
fieldName_contains - Strings only. Similar to a Like query as `like '%value%'`
fieldName_startswith - Strings only. A like query from the beginning of the value `like 'value%'`
fieldName_endswith - Strings only. A like query from the end of the value `like '%value'`
fieldName_memberof - Matches a value in an array field.
fieldName_isnull - Takes a boolean. If TRUE return results where the field is null.
If FALSE returns results where the field is not null.
NOTE: acts as "isEmpty" for collection filters. A value of false will
Expand Down Expand Up @@ -289,6 +290,7 @@ This module would like to support all datatypes representable in a GraphQL respo
supported:

```
array - Arrays are handled as arrays of strings because Doctrine does not type the values of the array.
tinyint
smallint
integer
Expand Down
39 changes: 39 additions & 0 deletions src/AbstractAbstractFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace ZF\Doctrine\GraphQL;

use Exception;
use GraphQL\Type\Definition\Type;

/**
* Enable caching of build() resources
Expand Down Expand Up @@ -46,5 +47,43 @@ protected function cache($requestedName, array $options = null, $instance)
'options' => $options,
'instance' => $instance,
];

return $instance;
}

protected function mapFieldType(string $fieldType)
{
switch ($fieldType) {
case 'tinyint':
case 'smallint':
case 'integer':
case 'int':
case 'bigint':
$graphQLType = Type::int();
break;
case 'boolean':
$graphQLType = Type::boolean();
break;
case 'decimal':
case 'float':
$graphQLType = Type::float();
break;
case 'string':
case 'text':
$graphQLType = Type::string();
break;
case 'datetime':
$graphQLType = Type::string();
break;
case 'array':
$graphQLType = Type::listOf(Type::string());
break;
default:
// Do not process unknown for now
$graphQLType = null;
break;
}

return $graphQLType;
}
}
35 changes: 4 additions & 31 deletions src/Criteria/FilterTypeAbstractFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,34 +80,9 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
continue;
}

switch ($fieldMetadata['type']) {
case 'tinyint':
case 'smallint':
case 'integer':
case 'int':
case 'bigint':
$graphQLType = Type::int();
break;
case 'boolean':
$graphQLType = Type::boolean();
break;
case 'decimal':
case 'float':
$graphQLType = Type::float();
break;
case 'string':
case 'text':
$graphQLType = Type::string();
break;
case 'datetime':
$graphQLType = Type::string();
break;
default:
// @codeCoverageIgnoreStart
// Do not process unknown. If you have an unknown type please report it.
$graphQLType = null;
break;
// @codeCoverageIgnoreEnd
$graphQLType = $this->mapFieldType($fieldMetadata['type']);
if ($fieldMetadata['type'] == 'array') {
$graphQLType = Type::string();
}

if ($graphQLType && $classMetadata->isIdentifier($fieldMetadata['fieldName'])) {
Expand Down Expand Up @@ -277,8 +252,6 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
},
]);

$this->cache($requestedName, $options, $instance);

return $instance;
return $this->cache($requestedName, $options, $instance);
}
}
44 changes: 12 additions & 32 deletions src/Filter/FilterTypeAbstractFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use GraphQL\Type\Definition\Type;
use ZF\Doctrine\QueryBuilder\Filter\Service\ORMFilterManager;
use ZF\Doctrine\QueryBuilder\OrderBy\Service\ORMOrderByManager;
use ZF\Doctrine\Criteria\Filter\Service\FilterManager as CriteriaFilterManager;
use ZF\Doctrine\GraphQL\Type\TypeManager;
use ZF\Doctrine\GraphQL\Filter\Type as FilterTypeNS;
use ZF\Doctrine\GraphQL\AbstractAbstractFactory;
Expand Down Expand Up @@ -62,6 +63,7 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o

$objectManager = $container->get($hydratorConfig['object_manager']);
$filterManager = $container->get(ORMFilterManager::class);
$criteriaFilterManager = $container->get(CriteriaFilterManager::class);
$orderByManager = $container->get(ORMOrderByManager::class);

// Create an instance of the entity in order to get fields from the hydrator.
Expand All @@ -81,35 +83,7 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
continue;
}

switch ($fieldMetadata['type']) {
case 'tinyint':
case 'smallint':
case 'integer':
case 'int':
case 'bigint':
$graphQLType = Type::int();
break;
case 'boolean':
$graphQLType = Type::boolean();
break;
case 'decimal':
case 'float':
$graphQLType = Type::float();
break;
case 'string':
case 'text':
$graphQLType = Type::string();
break;
case 'datetime':
$graphQLType = Type::string();
break;
default:
// @codeCoverageIgnoreStart
// Do not process unknown. If you have an unknown type please report it.
$graphQLType = null;
break;
// @codeCoverageIgnoreEnd
}
$graphQLType = $this->mapFieldType($fieldMetadata['type']);

if ($graphQLType && $classMetadata->isIdentifier($fieldMetadata['fieldName'])) {
$graphQLType = Type::id();
Expand Down Expand Up @@ -236,6 +210,14 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
'type' => Type::string(),
];
}

if ($criteriaFilterManager->has('memberof')) {
$fields[$fieldName . '_memberof'] = [
'name' => $fieldName . '_memberof',
'type' => Type::string(),
'description' => 'building...',
];
}
}
$fields[$fieldName . '_distinct'] = [
'name' => $fieldName . '_distinct',
Expand Down Expand Up @@ -263,8 +245,6 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
},
]);

$this->cache($requestedName, $options, $instance);

return $instance;
return $this->cache($requestedName, $options, $instance);
}
}
48 changes: 34 additions & 14 deletions src/Resolve/EntityResolveAbstractFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\SharedEventManagerInterface;
use Doctrine\Common\Collections\ArrayCollection;
use ZF\Doctrine\QueryBuilder\Filter\Service\ORMFilterManager;
use ZF\Doctrine\QueryBuilder\OrderBy\Service\ORMOrderByManager;
use ZF\Doctrine\Criteria\Filter\Service\FilterManager as CriteriaFilterManager;
use ZF\Doctrine\Criteria\Builder as CriteriaBuilder;
use ZF\Doctrine\GraphQL\AbstractAbstractFactory;

final class EntityResolveAbstractFactory extends AbstractAbstractFactory implements
Expand Down Expand Up @@ -83,6 +86,8 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$hydratorConfig = $config['zf-doctrine-graphql-hydrator'][$hydratorAlias][$options['hydrator_section']];
$filterManager = $container->get(ORMFilterManager::class);
$orderByManager = $container->get(ORMOrderByManager::class);
$criteriaFilterManager = $container->get(CriteriaFilterManager::class);
$criteriaBuilder = $container->get(CriteriaBuilder::class);
$objectManager = $container->get($hydratorConfig['object_manager']);

$instance = function (
Expand All @@ -95,7 +100,8 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$objectManager,
$requestedName,
$filterManager,
$orderByManager
$orderByManager,
$criteriaBuilder
) {

// Allow listener to resolve function
Expand Down Expand Up @@ -137,6 +143,7 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$filter = $args['filter'] ?? [];
$filterArray = [];
$orderByArray = [];
$criteriaArray = [];
$distinctField = null;
$skip = 0;
$limit = $options['limit'];
Expand Down Expand Up @@ -234,6 +241,13 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$distinctField = $field;
}
break;
case 'memberof':
$criteriaArray[] = [
'type' => 'memberof',
'field' => $field,
'value' => $value,
];
break;
default:
$filterArray[] = [
'type' => $filter,
Expand Down Expand Up @@ -272,34 +286,42 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$queryBuilder->setMaxResults($limit);
}

// Fetch from Query Builder
$results = $queryBuilder->getQuery()->getResult();

$matching = [];
// Build hydrated result collection
$resultCollection = new ArrayCollection();
foreach ($results as $key => $value) {
$matching[$key] = $hydrator->extract($value);
$resultCollection->add($hydrator->extract($value));
}

// Criteria post filter
if ($criteriaArray) {
$criteria = $criteriaBuilder->create($metadata, $criteriaArray, []);
$resultCollection = $resultCollection->matching($criteria);
}

// Distinct post filter
if ($distinctField) {
$distinctValueArray = [];
foreach ($matching as $key => $value) {
if (! in_array($value[$distinctField], $distinctValueArray)) {
$distinctValueArray[] = $value[$distinctField];
$distinctValueCollection = new ArrayCollection();
foreach ($resultCollection as $key => $value) {
if (! in_array($value[$distinctField], $distinctValueCollection)) {
$distinctValueCollection->add($value[$distinctField]);
} else {
unset($matching[$key]);
$resultCollection->remove($key);
}
}
}

// Allow listener to resolve post function
$matching = new ArrayObject($matching);
$results = $this->getEventManager()->trigger(
self::RESOLVE_POST,
$this,
[
'object' => $obj,
'arguments' => $args,
'context' => $context,
'matching' => $matching,
'resultCollection' => $resultCollection,
'hydrator' => $hydrator,
'objectManager' => $objectManager,
'queryBuilder' => $queryBuilder,
Expand All @@ -310,11 +332,9 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
return $results->last();
}

return $matching->getArrayCopy();
return $resultCollection->toArray();
};

$this->cache($requestedName, $options, $instance);

return $instance;
return $this->cache($requestedName, $options, $instance);
}
}
35 changes: 6 additions & 29 deletions src/Type/EntityTypeAbstractFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
$distinctField = $field;
}
break;
case 'memberof':
default:
$filterArray[] = [
'type' => $filter,
Expand Down Expand Up @@ -288,32 +289,10 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
}
}

switch ($fieldMetadata['type']) {
case 'tinyint':
case 'smallint':
case 'integer':
case 'int':
case 'bigint':
$graphQLType = Type::int();
break;
case 'boolean':
$graphQLType = Type::boolean();
break;
case 'decimal':
case 'float':
$graphQLType = Type::float();
break;
case 'string':
case 'text':
$graphQLType = Type::string();
break;
case 'datetime':
$graphQLType = $container->get(TypeManager::class)->get(DateTime::class);
break;
default:
// Do not process unknown for now
$graphQLType = null;
break;
$graphQLType = $this->mapFieldType($fieldMetadata['type']);
// Override for datetime
if ($fieldMetadata['type'] == 'datetime') {
$graphQLType = $container->get(TypeManager::class)->get(DateTime::class);
}

if ($graphQLType && $classMetadata->isIdentifier($fieldMetadata['fieldName'])) {
Expand Down Expand Up @@ -344,8 +323,6 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o
},
]);

$this->cache($requestedName, $options, $instance);

return $instance;
return $this->cache($requestedName, $options, $instance);
}
}
Loading

0 comments on commit 59aca60

Please sign in to comment.