Skip to content

Commit

Permalink
Merge pull request API-Skeletons#71 from TomHAnderson/feature/driver-…
Browse files Browse the repository at this point in the history
…type-manager

Feature/driver type manager
  • Loading branch information
TomHAnderson authored Mar 20, 2024
2 parents 3435c85 + 75b40bf commit b6d9f95
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 24 deletions.
60 changes: 46 additions & 14 deletions src/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace ApiSkeletons\Doctrine\ORM\GraphQL;

use ApiSkeletons\Doctrine\ORM\GraphQL\Type\TypeManager;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\Entity;
use Closure;
use GraphQL\Error\Error;
use GraphQL\Type\Definition\InputObjectType;
Expand All @@ -15,39 +15,55 @@ class Driver extends AbstractContainer
use Services;

/**
* Return a connection wrapper for a type
* Return a connection wrapper for a type. This is a special type that
* wraps the entity type
*
* @throws Error
*/
public function connection(ObjectType $objectType): ObjectType
{
/**
* Connections rely on the entity ObjectType so the build() method is used
*/
return $this->get(Type\TypeManager::class)
->build(Type\Connection::class, $objectType->name . '_Connection', $objectType);
}

/**
* Return a GraphQL type for the entity class
* A shortcut into the TypeManager that also handles Entity objects
*
* @throws Error
*/
public function type(string $entityClass): ObjectType
public function type(string $typeName): mixed
{
return $this->get(Type\TypeManager::class)->build(Type\Entity::class, $entityClass)();
$typeManager = $this->get(Type\TypeManager::class);

try {
// If a type is not registered, try to resolve it as an Entity
if (! $typeManager->has($typeName)) {
return $this->entityType($typeName)();
}

$type = $typeManager->get($typeName);

// Resolve an Entity type to its GraphQL representation
if ($type instanceof Entity) {
return $type();
}
} catch (Error) {
throw new Error('Type "' . $typeName . '" is not registered');
}

return $type;
}

/**
* Filters for a connection
* Return an InputObject type of filters for a connection
* Requires the internal representation of the entity
*
* @throws Error
*/
public function filter(string $entityClass): object
{
return $this->get(Filter\FilterFactory::class)->get(
$this->get(Type\TypeManager::class)
->build(Type\Entity::class, $entityClass),
$this->entityType($entityClass),
);
}

Expand All @@ -58,7 +74,7 @@ public function filter(string $entityClass): object
*/
public function pagination(): object
{
return $this->get(TypeManager::class)->get('pagination');
return $this->type('pagination');
}

/**
Expand All @@ -69,8 +85,7 @@ public function pagination(): object
public function resolve(string $entityClass, string|null $eventName = null): Closure
{
return $this->get(Resolve\ResolveEntityFactory::class)->get(
$this->get(Type\TypeManager::class)
->build(Type\Entity::class, $entityClass),
$this->entityType($entityClass),
$eventName,
);
}
Expand All @@ -85,4 +100,21 @@ public function input(string $entityClass, array $requiredFields = [], array $op
{
return $this->get(Input\InputFactory::class)->get($entityClass, $requiredFields, $optionalFields);
}

/**
* Internally an Entity object is used for Doctrine entities.
* The Entity object has an __invoke method which returns the
* GraphQL ObjectType. This method exists to fetch that Entity
* object. It is resolved by $this->type()
*
* Access to this method is not recommended. It is used internally
* but requires public scope.
*
* @throws Error
*/
public function entityType(string $entityClass): Entity
{
return $this->get(Type\TypeManager::class)
->build(Type\Entity::class, $entityClass);
}
}
4 changes: 2 additions & 2 deletions src/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ static function () use ($config) {
)
->set(
EventDispatcher::class,
static fn () => new EventDispatcher()
static fn () => new EventDispatcher(),
)
->set(
Type\TypeManager::class,
static fn (AbstractContainer $container) => new Type\TypeManager($container)
static fn (AbstractContainer $container) => new Type\TypeManager($container),
)
->set(
'metadata',
Expand Down
22 changes: 22 additions & 0 deletions test/Feature/DriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
use ArrayObject;
use GraphQL\Error\Error;
use GraphQL\GraphQL;
use GraphQL\Type\Definition\BooleanType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;
use Psr\Container\ContainerInterface;

Expand Down Expand Up @@ -165,4 +167,24 @@ public function testUseHydratorCache(): void

$this->assertEquals('Grateful Dead', $output['data']['artist']['edges'][0]['node']['name']);
}

public function testTypeMethodForCustomScalarValues(): void
{
$driver = new Driver($this->getEntityManager());

$driver->get(TypeManager::class)
->set('custom', static fn () => Type::boolean());

$this->assertInstanceOf(BooleanType::class, $driver->type('custom'));
}

public function testTypeMethodInvalidType(): void
{
$this->expectException(Error::class);
$this->expectExceptionMessage('Type "custom" is not registered');

$driver = new Driver($this->getEntityManager());

$this->assertInstanceOf(BooleanType::class, $driver->type('custom'));
}
}
3 changes: 1 addition & 2 deletions test/Feature/Metadata/TypeNameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use ApiSkeletons\Doctrine\ORM\GraphQL\Config;
use ApiSkeletons\Doctrine\ORM\GraphQL\Driver;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\TypeManager;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\AbstractTest;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\Entity\Artist;
use GraphQL\GraphQL;
Expand Down Expand Up @@ -38,7 +37,7 @@ public function testGroupSuffix(): void
]),
]);

$artistClass = $driver->get(TypeManager::class)->get(Artist::class);
$artistClass = $driver->entityType(Artist::class);

$this->assertEquals('Artist_unittest', $artistClass->getTypeName());
}
Expand Down
3 changes: 1 addition & 2 deletions test/Feature/Type/BlobTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use ApiSkeletons\Doctrine\ORM\GraphQL\Config;
use ApiSkeletons\Doctrine\ORM\GraphQL\Driver;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\Blob;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\TypeManager;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\AbstractTest;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\Entity\TypeTest;
use Doctrine\ORM\EntityManager;
Expand Down Expand Up @@ -127,7 +126,7 @@ public function testMutation(): void
'typetest' => [
'type' => $driver->type(TypeTest::class),
'args' => [
'blob' => $driver->get(TypeManager::class)->get('blob'),
'blob' => $driver->type('blob'),
],
'resolve' => function ($root, array $args, $context, ResolveInfo $info) use ($driver) {
$control = file_get_contents(__DIR__ . '/../../../banner.png');
Expand Down
2 changes: 1 addition & 1 deletion test/Feature/Type/PaginationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace ApiSkeletonsTest\Doctrine\ORM\GraphQL\Feature\Resolve;
namespace ApiSkeletonsTest\Doctrine\ORM\GraphQL\Feature\Type;

use ApiSkeletons\Doctrine\ORM\GraphQL\Driver;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\AbstractTest;
Expand Down
2 changes: 1 addition & 1 deletion test/Feature/Type/TypeManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace ApiSkeletonsTest\Doctrine\ORM\GraphQL\Feature\Resolve;
namespace ApiSkeletonsTest\Doctrine\ORM\GraphQL\Feature\Type;

use ApiSkeletons\Doctrine\ORM\GraphQL\Driver;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\Connection;
Expand Down
3 changes: 1 addition & 2 deletions test/Feature/Type/UuidTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use ApiSkeletons\Doctrine\ORM\GraphQL\Config;
use ApiSkeletons\Doctrine\ORM\GraphQL\Driver;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\TypeManager;
use ApiSkeletons\Doctrine\ORM\GraphQL\Type\Uuid;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\AbstractTest;
use ApiSkeletonsTest\Doctrine\ORM\GraphQL\Entity\TypeTest;
Expand Down Expand Up @@ -109,7 +108,7 @@ public function testMutation(): void
'typetest' => [
'type' => $driver->type(TypeTest::class),
'args' => [
'uuid' => $driver->get(TypeManager::class)->get('uuid'),
'uuid' => $driver->type('uuid'),
],
'resolve' => function ($root, array $args, $context, ResolveInfo $info) use ($driver) {
// This tests the Uuid type for changing a string into a UuidInterface
Expand Down

0 comments on commit b6d9f95

Please sign in to comment.