Skip to content

Refactoring to use SchemaFactory #26

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

Merged
merged 2 commits into from
Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 24 additions & 64 deletions DependencyInjection/GraphqliteCompilerPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use TheCodingMachine\GraphQLite\Annotations\Parameter;
use TheCodingMachine\GraphQLite\Annotations\Query;
use TheCodingMachine\Graphqlite\Bundle\QueryProviders\ControllerQueryProvider;
use TheCodingMachine\GraphQLite\FieldsBuilder;
use TheCodingMachine\GraphQLite\FieldsBuilderFactory;
use TheCodingMachine\GraphQLite\GraphQLException;
Expand All @@ -52,6 +51,7 @@
use TheCodingMachine\GraphQLite\Mappers\Root\CompositeRootTypeMapper;
use TheCodingMachine\GraphQLite\Mappers\StaticTypeMapper;
use TheCodingMachine\GraphQLite\NamingStrategy;
use TheCodingMachine\GraphQLite\SchemaFactory;
use TheCodingMachine\GraphQLite\TypeGenerator;
use TheCodingMachine\GraphQLite\Types\MutableObjectType;
use TheCodingMachine\GraphQLite\Types\ResolvableInputObjectType;
Expand Down Expand Up @@ -86,10 +86,7 @@ public function process(ContainerBuilder $container)
$globTtl = 2;
}

/**
* @var array<string, array<int, string>>
*/
$classToServicesMap = [];
$schemaFactory = $container->getDefinition(SchemaFactory::class);

foreach ($container->getDefinitions() as $id => $definition) {
if ($definition->isAbstract() || $definition->getClass() === null) {
Expand Down Expand Up @@ -125,63 +122,19 @@ public function process(ContainerBuilder $container)
}

foreach ($controllersNamespaces as $controllersNamespace) {
$schemaFactory->addMethodCall('addControllerNamespace', [ $controllersNamespace ]);
foreach ($this->getClassList($controllersNamespace) as $className => $refClass) {
$this->makePublicInjectedServices($refClass, $reader, $container);
}
}

foreach ($typesNamespaces as $typeNamespace) {
$schemaFactory->addMethodCall('addTypeNamespace', [ $typeNamespace ]);
foreach ($this->getClassList($typeNamespace) as $className => $refClass) {
$this->makePublicInjectedServices($refClass, $reader, $container);
}
}

foreach ($container->findTaggedServiceIds('graphql.annotated.controller') as $id => $tag) {
$definition = $container->findDefinition($id);
$class = $definition->getClass();
if ($class === null) {
throw new \RuntimeException(sprintf('Service %s has no class defined.', $id));
}

$reflectionClass = new ReflectionClass($class);
$isController = false;
$method = null;
foreach ($reflectionClass->getMethods() as $method) {
$query = $reader->getRequestAnnotation($method, Query::class);
if ($query !== null) {
$isController = true;
break;
}
$mutation = $reader->getRequestAnnotation($method, Mutation::class);
if ($mutation !== null) {
$isController = true;
break;
}
}

if ($isController) {
// Let's create a QueryProvider from this controller
$controllerIdentifier = $class.'__QueryProvider';
$queryProvider = new Definition(ControllerQueryProvider::class);
$queryProvider->setPrivate(true);
$queryProvider->setFactory([self::class, 'createQueryProvider']);
$queryProvider->addArgument(new Reference($id));
$queryProvider->addArgument(new Reference(FieldsBuilder::class));
$queryProvider->addTag('graphql.queryprovider');
$container->setDefinition($controllerIdentifier, $queryProvider);
}
}

foreach ($typesNamespaces as $typesNamespace) {
$definition = new Definition(GlobTypeMapper::class);
$definition->addArgument($typesNamespace);
$definition->setArgument('$globTtl', $globTtl);
$definition->setAutowired(true);
$definition->addTag('graphql.type_mapper');
$container->setDefinition('globTypeMapper_'.str_replace('\\', '__', $typesNamespace), $definition);
}


// Register custom output types
$taggedServices = $container->findTaggedServiceIds('graphql.output_type');

Expand Down Expand Up @@ -210,12 +163,27 @@ public function process(ContainerBuilder $container)
$definition->addMethodCall('setNotMappedTypes', [$customNotMappedTypes]);
}

// Register type mappers
$typeMapperServices = $container->findTaggedServiceIds('graphql.type_mapper');
$compositeTypeMapper = $container->getDefinition(CompositeTypeMapper::class);
foreach ($typeMapperServices as $id => $tags) {
// Register graphql.queryprovider
$this->mapAdderToTag('graphql.queryprovider', 'addQueryProvider', $container, $schemaFactory);
$this->mapAdderToTag('graphql.root_type_mapper', 'addRootTypeMapper', $container, $schemaFactory);
$this->mapAdderToTag('graphql.parameter_mapper', 'addParameterMapper', $container, $schemaFactory);
$this->mapAdderToTag('graphql.field_middleware', 'addFieldMiddleware', $container, $schemaFactory);
$this->mapAdderToTag('graphql.type_mapper', 'addTypeMapper', $container, $schemaFactory);
}

/**
* Register a method call on SchemaFactory for each tagged service, passing the service in parameter.
*
* @param string $tag
* @param string $methodName
*/
private function mapAdderToTag(string $tag, string $methodName, ContainerBuilder $container, Definition $schemaFactory): void
{
$taggedServices = $container->findTaggedServiceIds($tag);

foreach ($taggedServices as $id => $tags) {
// add the transport service to the TransportChain service
$compositeTypeMapper->addMethodCall('addTypeMapper', [new Reference($id)]);
$schemaFactory->addMethodCall($methodName, [new Reference($id)]);
}
}

Expand Down Expand Up @@ -296,14 +264,6 @@ private static function getParametersByName(ReflectionMethod $method): array
return $parameters;
}

/**
* @param object $controller
*/
public static function createQueryProvider($controller, FieldsBuilder $fieldsBuilder): ControllerQueryProvider
{
return new ControllerQueryProvider($controller, $fieldsBuilder);
}

/**
* Returns a cached Doctrine annotation reader.
* Note: we cannot get the annotation reader service in the container as we are in a compiler pass.
Expand Down
47 changes: 0 additions & 47 deletions QueryProviders/ControllerQueryProvider.php

This file was deleted.

95 changes: 13 additions & 82 deletions Resources/config/container/graphqlite.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,66 +12,29 @@
<services>
<defaults autowire="true" autoconfigure="true" public="false" />

<service id="TheCodingMachine\GraphQLite\Schema" public="true">
</service>

<service id="GraphQL\Type\Schema" alias="TheCodingMachine\GraphQLite\Schema" />

<service id="TheCodingMachine\GraphQLite\AggregateQueryProvider">
<argument type="tagged" tag="graphql.queryprovider" />
</service>

<service id="TheCodingMachine\GraphQLite\QueryProviderInterface" alias="TheCodingMachine\GraphQLite\AggregateQueryProvider" />

<service id="TheCodingMachine\GraphQLite\Mappers\Root\CompositeRootTypeMapper">
<argument type="tagged" tag="graphql.root_type_mapper" />
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\Root\RootTypeMapperInterface" alias="TheCodingMachine\GraphQLite\Mappers\Root\CompositeRootTypeMapper" />

<service id="TheCodingMachine\GraphQLite\Mappers\Parameters\ResolveInfoParameterMapper">
<tag name="graphql.parameter_mapper" />
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\Parameters\ContainerParameterMapper">
<argument type="service" id="service_container" />
<tag name="graphql.parameter_mapper" />
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\Parameters\CompositeParameterMapper">
<argument type="tagged" tag="graphql.parameter_mapper" />
</service>

<service id="TheCodingMachine\GraphQLite\Middlewares\FieldMiddlewareInterface" alias="TheCodingMachine\GraphQLite\Middlewares\FieldMiddlewarePipe" />

<service id="TheCodingMachine\GraphQLite\Middlewares\FieldMiddlewarePipe">
<argument type="tagged" tag="graphql.field_middleware" />
</service>

<service id="TheCodingMachine\GraphQLite\Middlewares\AuthorizationFieldMiddleware">
<tag name="graphql.field_middleware" />
<service id="TheCodingMachine\GraphQLite\SchemaFactory">
<argument index="1" type="service" id="service_container" />
<call method="setAuthenticationService">
<argument type="service" id="TheCodingMachine\GraphQLite\Security\AuthenticationServiceInterface" />
</call>
<call method="setAuthorizationService">
<argument type="service" id="TheCodingMachine\GraphQLite\Security\AuthorizationServiceInterface" />
</call>
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\Parameters\ParameterMapperInterface" alias="TheCodingMachine\GraphQLite\Mappers\Parameters\CompositeParameterMapper" />

<service id="TheCodingMachine\GraphQLite\Mappers\Root\MyCLabsEnumTypeMapper">
<tag name="graphql.root_type_mapper" />
<service id="TheCodingMachine\GraphQLite\Schema" public="true">
<factory service="TheCodingMachine\GraphQLite\SchemaFactory"
method="createSchema"
/>
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\Root\BaseTypeMapper">
<tag name="graphql.root_type_mapper" />
</service>
<service id="GraphQL\Type\Schema" alias="TheCodingMachine\GraphQLite\Schema" />

<service id="TheCodingMachine\GraphQLite\FieldsBuilder" public="true" />

<service id="TheCodingMachine\GraphQLite\AnnotationReader" >
<argument key="$mode">%graphqlite.annotations.error_mode%</argument>
</service>

<service id="TheCodingMachine\GraphQLite\Hydrators\FactoryHydrator" />

<service id="TheCodingMachine\GraphQLite\Hydrators\HydratorInterface" alias="TheCodingMachine\GraphQLite\Hydrators\FactoryHydrator" />

<service id="TheCodingMachine\Graphqlite\Bundle\Security\AuthenticationService">
<argument type="service" id="security.token_storage" on-invalid="null" />
</service>
Expand All @@ -84,22 +47,6 @@

<service id="TheCodingMachine\GraphQLite\Security\AuthorizationServiceInterface" alias="TheCodingMachine\Graphqlite\Bundle\Security\AuthorizationService" />

<service id="TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapper" public="true" />

<service id="TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapperInterface" alias="TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapper" public="true" />

<service id="TheCodingMachine\GraphQLite\Mappers\CompositeTypeMapper">
<argument type="tagged" tag="graphql.type_mapper" />
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\TypeMapperInterface" alias="TheCodingMachine\GraphQLite\Mappers\CompositeTypeMapper" />

<service id="TheCodingMachine\GraphQLite\TypeGenerator" public="true" />

<service id="TheCodingMachine\GraphQLite\InputTypeGenerator" public="true" />

<service id="TheCodingMachine\GraphQLite\InputTypeUtils" />

<service id="GraphQL\Server\StandardServer">
<argument type="service" id="GraphQL\Server\ServerConfig" />
</service>
Expand All @@ -114,22 +61,6 @@
<tag name="graphql.type_mapper"/>
</service>

<service id="TheCodingMachine\GraphQLite\Mappers\PorpaginasTypeMapper">
<tag name="graphql.type_mapper"/>
</service>

<service id="TheCodingMachine\GraphQLite\Reflection\CachedDocBlockFactory" />

<service id="TheCodingMachine\GraphQLite\NamingStrategy" />

<service id="TheCodingMachine\GraphQLite\NamingStrategyInterface" alias="TheCodingMachine\GraphQLite\NamingStrategy" />

<service id="TheCodingMachine\GraphQLite\Types\TypeResolver" />

<service id="TheCodingMachine\GraphQLite\TypeRegistry" />

<service id="TheCodingMachine\GraphQLite\Types\ArgumentResolver" />

<service id="TheCodingMachine\Graphqlite\Bundle\Controller\GraphqliteController" public="true" />
</services>

Expand Down
1 change: 0 additions & 1 deletion Security/AuthenticationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace TheCodingMachine\Graphqlite\Bundle\Security;


use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use TheCodingMachine\GraphQLite\Security\AuthenticationServiceInterface;

Expand Down
15 changes: 13 additions & 2 deletions Security/AuthorizationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace TheCodingMachine\Graphqlite\Bundle\Security;


use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use TheCodingMachine\GraphQLite\Security\AuthorizationServiceInterface;

Expand All @@ -13,10 +14,15 @@ class AuthorizationService implements AuthorizationServiceInterface
* @var AuthorizationCheckerInterface|null
*/
private $authorizationChecker;
/**
* @var TokenStorageInterface|null
*/
private $tokenStorage;

public function __construct(?AuthorizationCheckerInterface $authorizationChecker)
public function __construct(?AuthorizationCheckerInterface $authorizationChecker, ?TokenStorageInterface $tokenStorage)
{
$this->authorizationChecker = $authorizationChecker;
$this->tokenStorage = $tokenStorage;
}

/**
Expand All @@ -27,10 +33,15 @@ public function __construct(?AuthorizationCheckerInterface $authorizationChecker
*/
public function isAllowed(string $right): bool
{
if ($this->authorizationChecker === null) {
if ($this->authorizationChecker === null || $this->tokenStorage === null) {
throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
}

$token = $this->tokenStorage->getToken();
if (null === $token) {
return false;
}

return $this->authorizationChecker->isGranted($right);
}
}
Loading