Skip to content

Commit

Permalink
Merge pull request #59 from TomHAnderson/feature/services
Browse files Browse the repository at this point in the history
Bifurcated driver and services
  • Loading branch information
TomHAnderson authored Dec 23, 2022
2 parents 9897329 + a430341 commit fa1a78e
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 108 deletions.
147 changes: 39 additions & 108 deletions src/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,142 +4,73 @@

namespace ApiSkeletons\Doctrine\GraphQL;

use ApiSkeletons\Doctrine\GraphQL\Criteria\CriteriaFactory;
use ApiSkeletons\Doctrine\GraphQL\Hydrator\HydratorFactory;
use ApiSkeletons\Doctrine\GraphQL\Input\InputFactory;
use ApiSkeletons\Doctrine\GraphQL\Metadata\Metadata;
use ApiSkeletons\Doctrine\GraphQL\Metadata\MetadataFactory;
use ApiSkeletons\Doctrine\GraphQL\Resolve\FieldResolver;
use ApiSkeletons\Doctrine\GraphQL\Resolve\ResolveCollectionFactory;
use ApiSkeletons\Doctrine\GraphQL\Resolve\ResolveEntityFactory;
use ApiSkeletons\Doctrine\GraphQL\Type\Connection;
use ApiSkeletons\Doctrine\GraphQL\Type\TypeManager;
use Closure;
use Doctrine\ORM\EntityManager;
use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\ObjectType;
use League\Event\EventDispatcher;
use Psr\Container\ContainerInterface;

class Driver extends AbstractContainer
{
/**
* @param string $entityManagerAlias required
* @param Config $config required
* @param Metadata|null $metadata optional so cached metadata can be loaded
* @param Metadata\Metadata|null $metadata optional so cached metadata can be loaded
*/
public function __construct(EntityManager $entityManager, ?Config $config = null, ?array $metadataConfig = null)
{
$this
// Plain classes
->set(EntityManager::class, $entityManager)
->set(
Config::class,
static function () use ($config) {
if (! $config) {
$config = new Config();
}

return $config;
}
)
->set(
EventDispatcher::class,
static fn () => new EventDispatcher()
)
->set(
TypeManager::class,
static fn () => new TypeManager()
)
->set(
Metadata::class,
static function (ContainerInterface $container) use ($metadataConfig) {
return (new MetadataFactory($container, $metadataConfig))->getMetadata();
}
)
->set(
FieldResolver::class,
static function (ContainerInterface $container) {
return new FieldResolver(
$container->get(Config::class),
$container->get(Metadata::class)
);
}
)
->set(
ResolveCollectionFactory::class,
static function (ContainerInterface $container) {
return new ResolveCollectionFactory(
$container->get(EntityManager::class),
$container->get(Config::class),
$container->get(FieldResolver::class),
$container->get(TypeManager::class)
);
}
)
->set(
ResolveEntityFactory::class,
static function (ContainerInterface $container) {
return new ResolveEntityFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(EventDispatcher::class)
);
}
)
->set(
CriteriaFactory::class,
static function (ContainerInterface $container) {
return new CriteriaFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(TypeManager::class)
);
}
)
->set(
HydratorFactory::class,
static function (ContainerInterface $container) {
return new HydratorFactory(
$container->get(EntityManager::class),
$container->get(Metadata::class)
);
}
)
->set(
InputFactory::class,
static function (ContainerInterface $container) {
return new InputFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(TypeManager::class),
$container->get(Metadata::class)
);
}
);
// Services for this container are initialized in the Services class
new Services($this, $entityManager, $config, $metadataConfig);
}

/**
* Return a connection wrapper for a type
*
* @param ObjectType $objectType
* @return ObjectType
* @throws \GraphQL\Error\Error
*/
public function connection(ObjectType $objectType): ObjectType
{
return $this->get(TypeManager::class)
->build(Connection::class, $objectType->name . '_Connection', $objectType);
return $this->get(Type\TypeManager::class)
->build(Type\Connection::class, $objectType->name . '_Connection', $objectType);
}

/**
* Return a GraphQL type for the entity class
*
* @param string $entityClass
* @return ObjectType
* @throws \GraphQL\Error\Error
*/
public function type(string $entityClass): ObjectType
{
return $this->get(Metadata::class)->get($entityClass)->getGraphQLType();
return $this->get(Metadata\Metadata::class)->get($entityClass)->getGraphQLType();
}

/**
* Filters for a connection
*
* @param string $entityClass
* @return object
* @throws \GraphQL\Error\Error
*/
public function filter(string $entityClass): object
{
return $this->get(CriteriaFactory::class)
->get($this->get(Metadata::class)->get($entityClass));
return $this->get(Criteria\CriteriaFactory::class)
->get($this->get(Metadata\Metadata::class)->get($entityClass));
}

/**
* Resolve a connection
*
* @param string $entityClass
* @return Closure
* @throws \GraphQL\Error\Error
*/
public function resolve(string $entityClass): Closure
{
return $this->get(ResolveEntityFactory::class)
->get($this->get(Metadata::class)->get($entityClass));
return $this->get(Resolve\ResolveEntityFactory::class)
->get($this->get(Metadata\Metadata::class)->get($entityClass));
}

/**
Expand All @@ -150,6 +81,6 @@ public function resolve(string $entityClass): Closure
*/
public function input(string $entityClass, array $requiredFields = [], array $optionalFields = []): InputObjectType
{
return $this->get(InputFactory::class)->get($entityClass, $requiredFields, $optionalFields);
return $this->get(Input\InputFactory::class)->get($entityClass, $requiredFields, $optionalFields);
}
}
118 changes: 118 additions & 0 deletions src/Services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

declare(strict_types=1);

namespace ApiSkeletons\Doctrine\GraphQL;

use Doctrine\ORM\EntityManager;
use League\Event\EventDispatcher;
use Psr\Container\ContainerInterface;

/**
* This class is used to remove complexity from the Driver class.
* It doesn't change what the Driver does. It just moves service bootstrapping
* out of the Driver.
*/
class Services extends AbstractContainer
{
/**
* @param Driver $driver required
* @param string $entityManagerAlias required
* @param Config $config required
* @param Metadata\Metadata|null $metadata optional so cached metadata can be loaded
*/
public function __construct(
Driver $driver,
EntityManager $entityManager,
?Config $config = null,
?array $metadataConfig = null
) {
$driver
// Plain classes
->set(EntityManager::class, $entityManager)
->set(
Config::class,
static function () use ($config) {
if (! $config) {
$config = new Config();
}

return $config;
}
)
->set(
EventDispatcher::class,
static fn () => new EventDispatcher()
)
->set(
Type\TypeManager::class,
static fn () => new Type\TypeManager()
)
->set(
Metadata\Metadata::class,
static function (ContainerInterface $container) use ($metadataConfig) {
return (new Metadata\MetadataFactory($container, $metadataConfig))->getMetadata();
}
)
->set(
Resolve\FieldResolver::class,
static function (ContainerInterface $container) {
return new Resolve\FieldResolver(
$container->get(Config::class),
$container->get(Metadata\Metadata::class)
);
}
)
->set(
Resolve\ResolveCollectionFactory::class,
static function (ContainerInterface $container) {
return new Resolve\ResolveCollectionFactory(
$container->get(EntityManager::class),
$container->get(Config::class),
$container->get(Resolve\FieldResolver::class),
$container->get(Type\TypeManager::class)
);
}
)
->set(
Resolve\ResolveEntityFactory::class,
static function (ContainerInterface $container) {
return new Resolve\ResolveEntityFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(EventDispatcher::class)
);
}
)
->set(
Criteria\CriteriaFactory::class,
static function (ContainerInterface $container) {
return new Criteria\CriteriaFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(Type\TypeManager::class)
);
}
)
->set(
Hydrator\HydratorFactory::class,
static function (ContainerInterface $container) {
return new Hydrator\HydratorFactory(
$container->get(EntityManager::class),
$container->get(Metadata\Metadata::class)
);
}
)
->set(
Input\InputFactory::class,
static function (ContainerInterface $container) {
return new Input\InputFactory(
$container->get(Config::class),
$container->get(EntityManager::class),
$container->get(Type\TypeManager::class),
$container->get(Metadata\Metadata::class)
);
}
);
}
}

0 comments on commit fa1a78e

Please sign in to comment.