Skip to content

Commit

Permalink
Merge pull request #258 from mcg-web/fix-aliases
Browse files Browse the repository at this point in the history
Move Aliased to dedicated compiler pass
  • Loading branch information
mcg-web authored Dec 12, 2017
2 parents e3acfac + 0263c7d commit 7a124ed
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 30 deletions.
67 changes: 67 additions & 0 deletions DependencyInjection/Compiler/AliasedPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Overblog\GraphQLBundle\DependencyInjection\Compiler;

use Overblog\GraphQLBundle\Definition\Resolver\AliasedInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

final class AliasedPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$definitions = $this->filterDefinitions($container->getDefinitions());
foreach ($definitions as $definition) {
$this->addDefinitionTagsFromAliases($definition);
}
}

/**
* @param Definition[] $definitions
*
* @return Definition[]
*/
private function filterDefinitions($definitions)
{
return array_filter($definitions, function (Definition $definition) {
foreach (AutoMappingPass::SERVICE_SUBCLASS_TAG_MAPPING as $tagName) {
if ($definition->hasTag($tagName)) {
return is_subclass_of($definition->getClass(), AliasedInterface::class);
}
}

return false;
});
}

/**
* @param Definition $definition
*/
private function addDefinitionTagsFromAliases(Definition $definition)
{
$aliases = call_user_func([$definition->getClass(), 'getAliases']);
$tagName = $this->guessTagName($definition);
$withMethod = TypeTaggedServiceMappingPass::TAG_NAME !== $tagName;

foreach ($aliases as $key => $alias) {
$definition->addTag($tagName, $withMethod ? ['alias' => $alias, 'method' => $key] : ['alias' => $alias]);
}
}

private function guessTagName(Definition $definition)
{
$tagName = null;
foreach (AutoMappingPass::SERVICE_SUBCLASS_TAG_MAPPING as $refClassName => $tag) {
if (is_subclass_of($definition->getClass(), $refClassName)) {
$tagName = $tag;
break;
}
}

return $tagName;
}
}
31 changes: 4 additions & 27 deletions DependencyInjection/Compiler/AutoMappingPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

class AutoMappingPass implements CompilerPassInterface
{
private static $serviceSubclassTagMapping = [
const SERVICE_SUBCLASS_TAG_MAPPING = [
MutationInterface::class => 'overblog_graphql.mutation',
ResolverInterface::class => 'overblog_graphql.resolver',
Type::class => 'overblog_graphql.type',
Type::class => TypeTaggedServiceMappingPass::TAG_NAME,
];

public function process(ContainerBuilder $container)
Expand Down Expand Up @@ -88,9 +88,7 @@ private function addServiceDefinition(ContainerBuilder $container, \ReflectionCl

private function addDefinitionTags(Definition $definition, \ReflectionClass $reflectionClass)
{
$className = $definition->getClass();

foreach (self::$serviceSubclassTagMapping as $subclass => $tagName) {
foreach (self::SERVICE_SUBCLASS_TAG_MAPPING as $subclass => $tagName) {
if (!$reflectionClass->isSubclassOf($subclass)) {
continue;
}
Expand All @@ -104,36 +102,15 @@ private function addDefinitionTags(Definition $definition, \ReflectionClass $ref
}
$definition->addTag($tagName, ['method' => $publicReflectionMethod->name]);
}
if ($isAliased) {
$this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, true);
}
} else {
$definition->addTag($tagName);
$this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, false);
}
}
}

/**
* @param string|null $className
* @param bool $withMethod
*/
private function addDefinitionTagsFromAliasesMethod(Definition $definition, $className, $tagName, $withMethod)
{
// from getAliases
if (!is_callable([$className, 'getAliases'])) {
return;
}
$aliases = call_user_func([$className, 'getAliases']);

foreach ($aliases as $key => $alias) {
$definition->addTag($tagName, $withMethod ? ['alias' => $alias, 'method' => $key] : ['alias' => $alias]);
}
}

private function subclass($class)
{
$interfaces = array_keys(self::$serviceSubclassTagMapping);
$interfaces = array_keys(self::SERVICE_SUBCLASS_TAG_MAPPING);

foreach ($interfaces as $interface) {
if (is_a($class, $interface, true)) {
Expand Down
2 changes: 1 addition & 1 deletion DependencyInjection/Compiler/ConfigTypesPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private function setTypeServiceDefinition(ContainerBuilder $container, $class, a
$definition->setPublic(false);
$definition->setArguments([new Reference('service_container')]);
foreach ($aliases as $alias) {
$definition->addTag('overblog_graphql.type', ['alias' => $alias, 'generated' => true]);
$definition->addTag(TypeTaggedServiceMappingPass::TAG_NAME, ['alias' => $alias, 'generated' => true]);
}
}
}
4 changes: 3 additions & 1 deletion OverblogGraphQLBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Overblog\GraphQLBundle;

use Overblog\GraphQLBundle\DependencyInjection\Compiler\AliasedPass;
use Overblog\GraphQLBundle\DependencyInjection\Compiler\AutoMappingPass;
use Overblog\GraphQLBundle\DependencyInjection\Compiler\AutowiringTypesPass;
use Overblog\GraphQLBundle\DependencyInjection\Compiler\ConfigTypesPass;
Expand All @@ -26,7 +27,8 @@ public function build(ContainerBuilder $container)

//ConfigTypesPass and AutoMappingPass must be before TypeTaggedServiceMappingPass
$container->addCompilerPass(new AutoMappingPass());
$container->addCompilerPass(new ConfigTypesPass());
$container->addCompilerPass(new ConfigTypesPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new AliasedPass());
$container->addCompilerPass(new AutowiringTypesPass());

$container->addCompilerPass(new TypeTaggedServiceMappingPass(), PassConfig::TYPE_BEFORE_REMOVING);
Expand Down
21 changes: 20 additions & 1 deletion Resources/doc/definitions/resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,32 @@ Resolvers can be define 2 different ways
- "%kernel.root_dir%/src/*Bundle/CustomDir"
- "%kernel.root_dir%/src/AppBundle/{foo,bar}"
```
To disable auto mapping:

If using Symfony 3.3+ disabling auto mapping can be a solution to leave place to native
DI `autoconfigure`:

```yaml
overblog_graphql:
definitions:
auto_mapping: false
```

Here an example of how this can be done with DI `autoconfigure`:

```yaml
App\Mutation\:
resource: '../src/Mutation'
tags: ['overblog_graphql.mutation']

App\Resolver\:
resource: '../src/Resolver'
tags: ['overblog_graphql.resolver']

App\Type\:
resource: '../src/Type'
tags: ['overblog_graphql.type']
```

**Note:**
* When using FQCN in yaml definition, backslash must be correctly quotes,
here an example `'@=resolver("App\\GraphQL\\Resolver\\Greetings", [args['name']])'`.
Expand Down

0 comments on commit 7a124ed

Please sign in to comment.