Skip to content

Commit 9f81292

Browse files
authored
Merge pull request #27 from moufmouf/static_factory
Adding support for static factories
2 parents f48aee9 + b81edd2 commit 9f81292

File tree

7 files changed

+117
-6
lines changed

7 files changed

+117
-6
lines changed

src/InputTypeGenerator.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use GraphQL\Type\Definition\ObjectType;
99
use phpDocumentor\Reflection\Fqsen;
1010
use phpDocumentor\Reflection\Types\Object_;
11+
use Psr\Container\ContainerInterface;
1112
use ReflectionClass;
1213
use ReflectionMethod;
1314
use ReflectionType;
@@ -48,20 +49,26 @@ public function __construct(InputTypeUtils $inputTypeUtils,
4849
}
4950

5051
/**
51-
* @param object $factory
52+
* @param string $factory
5253
* @param string $methodName
5354
* @param RecursiveTypeMapperInterface $recursiveTypeMapper
5455
* @return InputObjectType
5556
*/
56-
public function mapFactoryMethod($factory, string $methodName, RecursiveTypeMapperInterface $recursiveTypeMapper): InputObjectType
57+
public function mapFactoryMethod(string $factory, string $methodName, RecursiveTypeMapperInterface $recursiveTypeMapper, ContainerInterface $container): InputObjectType
5758
{
5859
$method = new ReflectionMethod($factory, $methodName);
5960

61+
if ($method->isStatic()) {
62+
$object = $factory;
63+
} else {
64+
$object = $container->get($factory);
65+
}
66+
6067
[$inputName, $className] = $this->inputTypeUtils->getInputTypeNameAndClassName($method);
6168

6269
if (!isset($this->cache[$inputName])) {
6370
// TODO: add comment argument.
64-
$this->cache[$inputName] = new ResolvableInputObjectType($inputName, $this->fieldsBuilderFactory, $recursiveTypeMapper, $factory, $methodName, $this->hydrator, null);
71+
$this->cache[$inputName] = new ResolvableInputObjectType($inputName, $this->fieldsBuilderFactory, $recursiveTypeMapper, $object, $methodName, $this->hydrator, null);
6572
}
6673

6774
return $this->cache[$inputName];

src/InputTypeUtils.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
namespace TheCodingMachine\GraphQLite;
55

66
use phpDocumentor\Reflection\Fqsen;
7+
use phpDocumentor\Reflection\Type;
78
use phpDocumentor\Reflection\Types\Object_;
9+
use phpDocumentor\Reflection\Types\Self_;
10+
use ReflectionClass;
811
use ReflectionMethod;
912

1013
class InputTypeUtils
@@ -57,10 +60,25 @@ private function validateReturnType(ReflectionMethod $refMethod): Fqsen
5760
$typeResolver = new \phpDocumentor\Reflection\TypeResolver();
5861

5962
$phpdocType = $typeResolver->resolve($type);
63+
$phpdocType = $this->resolveSelf($phpdocType, $refMethod->getDeclaringClass());
6064
if (!$phpdocType instanceof Object_) {
6165
throw MissingTypeHintException::invalidReturnType($refMethod);
6266
}
6367

6468
return $phpdocType->getFqsen();
6569
}
70+
71+
/**
72+
* Resolves "self" types into the class type.
73+
*
74+
* @param Type $type
75+
* @return Type
76+
*/
77+
private function resolveSelf(Type $type, ReflectionClass $reflectionClass): Type
78+
{
79+
if ($type instanceof Self_) {
80+
return new Object_(new Fqsen('\\'.$reflectionClass->getName()));
81+
}
82+
return $type;
83+
}
6684
}

src/Mappers/GlobTypeMapper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ public function mapClassToInputType(string $className, RecursiveTypeMapperInterf
653653
$factory = $map[$className];
654654
}
655655

656-
return $this->inputTypeGenerator->mapFactoryMethod($this->container->get($factory[0]), $factory[1], $recursiveTypeMapper);
656+
return $this->inputTypeGenerator->mapFactoryMethod($factory[0], $factory[1], $recursiveTypeMapper, $this->container);
657657
}
658658

659659
/**
@@ -687,7 +687,7 @@ public function mapNameToType(string $typeName, RecursiveTypeMapperInterface $re
687687
return $this->typeGenerator->mapAnnotatedObject($typeClassName, $recursiveTypeMapper);
688688
}
689689
if (isset($factory)) {
690-
return $this->inputTypeGenerator->mapFactoryMethod($this->container->get($factory[0]), $factory[1], $recursiveTypeMapper);
690+
return $this->inputTypeGenerator->mapFactoryMethod($factory[0], $factory[1], $recursiveTypeMapper, $this->container);
691691
}
692692

693693
throw CannotMapTypeException::createForName($typeName);

src/Types/ResolvableInputObjectType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ResolvableInputObjectType extends InputObjectType implements ResolvableInp
3737
* @param string $name
3838
* @param FieldsBuilderFactory $controllerQueryProviderFactory
3939
* @param RecursiveTypeMapperInterface $recursiveTypeMapper
40-
* @param object $factory
40+
* @param object|string $factory
4141
* @param string $methodName
4242
* @param HydratorInterface $hydrator
4343
* @param null|string $comment
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\GraphQLite\Fixtures\Integration\Controllers;
5+
6+
7+
use TheCodingMachine\GraphQLite\Annotations\Query;
8+
use TheCodingMachine\GraphQLite\Fixtures\Integration\Models\Filter;
9+
use function var_export;
10+
11+
class FilterController
12+
{
13+
/**
14+
* @Query()
15+
* @return string[]
16+
*/
17+
public function echoFilters(Filter $filter): array
18+
{
19+
return $filter->getValues();
20+
}
21+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\GraphQLite\Fixtures\Integration\Models;
5+
6+
7+
use TheCodingMachine\GraphQLite\Annotations\Factory;
8+
9+
class Filter
10+
{
11+
/**
12+
* @var string[]|int[]
13+
*/
14+
private $values;
15+
16+
/**
17+
* Filter constructor.
18+
* @param string[]|int[] $values
19+
*/
20+
public function __construct(array $values)
21+
{
22+
$this->values = $values;
23+
}
24+
25+
/**
26+
* @return string[]|int[]
27+
*/
28+
public function getValues(): array
29+
{
30+
return $this->values;
31+
}
32+
33+
/**
34+
* @Factory()
35+
* @param string[] $values
36+
*/
37+
public static function create(array $values): self
38+
{
39+
return new self($values);
40+
}
41+
}

tests/Integration/EndToEndTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,4 +462,28 @@ public function testEndToEnd2Iterators()
462462
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
463463

464464
}
465+
466+
public function testEndToEndStaticFactories()
467+
{
468+
/**
469+
* @var Schema $schema
470+
*/
471+
$schema = $this->mainContainer->get(Schema::class);
472+
473+
$queryString = '
474+
query {
475+
echoFilters(filter: {values: ["foo", "bar"]})
476+
}
477+
';
478+
479+
$result = GraphQL::executeQuery(
480+
$schema,
481+
$queryString
482+
);
483+
484+
$this->assertSame([
485+
'echoFilters' => [ "foo", "bar" ]
486+
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
487+
}
488+
465489
}

0 commit comments

Comments
 (0)