Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#137)
by Jérémiah
06:26
created

AutoMappingPass   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 5
dl 0
loc 180
ccs 114
cts 114
cp 1
rs 9.3999
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
B process() 0 40 5
A addServicesDefinitions() 0 6 2
A addServiceDefinition() 0 11 2
D addDefinitionTags() 0 27 9
A addDefinitionTagsFromAliasesMethod() 0 12 4
A subclass() 0 12 3
C reflectionClassesFromDirectory() 0 46 8
1
<?php
2
3
/*
4
 * This file is part of the OverblogGraphQLBundle package.
5
 *
6
 * (c) Overblog <http://github.com/overblog/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Overblog\GraphQLBundle\DependencyInjection\Compiler;
13
14
use GraphQL\Type\Definition\Type;
15
use Overblog\GraphQLBundle\Definition\Resolver\AliasedInterface;
16
use Overblog\GraphQLBundle\Definition\Resolver\MutationInterface;
17
use Overblog\GraphQLBundle\Definition\Resolver\ResolverInterface;
18
use Symfony\Component\Config\Resource\DirectoryResource;
19
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
20
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Definition;
23
use Symfony\Component\DependencyInjection\Reference;
24
use Symfony\Component\Finder\Finder;
25
26
class AutoMappingPass implements CompilerPassInterface
27
{
28
    private static $serviceSubclassTagMapping = [
29
        MutationInterface::class => 'overblog_graphql.mutation',
30
        ResolverInterface::class => 'overblog_graphql.resolver',
31
        Type::class => 'overblog_graphql.type',
32
    ];
33
34 13
    public function process(ContainerBuilder $container)
35
    {
36 13
        $enabled = $container->getParameter('overblog_graphql.auto_mapping.enabled');
37
        // enabled auto mapping for all bundles and custom dirs ?
38 13
        if ($enabled) {
39 1
            $directories = $container->getParameter('overblog_graphql.auto_mapping.directories');
40 1
            $bundles = $container->getParameter('kernel.bundles');
41 1
            $directories = array_merge(
42 1
                array_map(
43 1
                    function ($class) {
44 1
                        $bundle = new \ReflectionClass($class);
45 1
                        $bundleDir = dirname($bundle->getFileName());
46
47 1
                        return $bundleDir.'/GraphQL';
48 1
                    },
49
                    $bundles
50 1
                ),
51
                $directories
52 1
            );
53
            // add app dir
54 1
            if ($container->hasParameter('kernel.root_dir')) {
55 1
                $directories[] = $container->getParameter('kernel.root_dir').'/GraphQL';
56 1
            }
57 1
        } else {
58
            // enabled auto mapping only for this bundle
59 12
            $directories = [__DIR__.'/../../GraphQL'];
60
        }
61 13
        $directoryList = [];
62
63 13
        foreach ($directories as $directory) {
64 13
            list($reflectionClasses, $directories) = $this->reflectionClassesFromDirectory($directory);
65 13
            $directoryList = array_merge($directoryList, $directories);
66 13
            $this->addServicesDefinitions($container, $reflectionClasses);
67 13
        }
68
69 13
        foreach ($directoryList as $directory => $v) {
70 13
            $directory = realpath($directory);
71 13
            $container->addResource(new DirectoryResource($directory, '/\.php$/'));
72 13
        }
73 13
    }
74
75
    /**
76
     * @param ContainerBuilder   $container
77
     * @param \ReflectionClass[] $reflectionClasses
78
     */
79 13
    private function addServicesDefinitions(ContainerBuilder $container, array $reflectionClasses)
80
    {
81 13
        foreach ($reflectionClasses as $reflectionClass) {
82 13
            $this->addServiceDefinition($container, $reflectionClass);
83 13
        }
84 13
    }
85
86 13
    private function addServiceDefinition(ContainerBuilder $container, \ReflectionClass $reflectionClass)
87
    {
88 13
        $className = $reflectionClass->getName();
0 ignored issues
show
Bug introduced by
Consider using $reflectionClass->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
89 13
        $definition = $container->setDefinition($className, new Definition($className));
90 13
        $definition->setPublic(false);
91 13
        $definition->setAutowired(true);
92 13
        if (is_subclass_of($definition->getClass(), ContainerAwareInterface::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Symfony\Component\Depen...erAwareInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
93 1
            $definition->addMethodCall('setContainer', [new Reference('service_container')]);
94 1
        }
95 13
        $this->addDefinitionTags($definition, $reflectionClass);
96 13
    }
97
98 13
    private function addDefinitionTags(Definition $definition, \ReflectionClass $reflectionClass)
99
    {
100 13
        $className = $definition->getClass();
101
102 13
        foreach (self::$serviceSubclassTagMapping as $subclass => $tagName) {
103 13
            if (!$reflectionClass->isSubclassOf($subclass)) {
104 13
                continue;
105
            }
106
107 13
            if (Type::class !== $subclass) {
108 13
                $publicReflectionMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
109 13
                $isAliased = $reflectionClass->implementsInterface(AliasedInterface::class);
110 13
                foreach ($publicReflectionMethods as $publicReflectionMethod) {
111 13
                    if ('__construct' === $publicReflectionMethod->name || $isAliased && 'getAliases' === $publicReflectionMethod->name) {
112 13
                        continue;
113
                    }
114 13
                    $definition->addTag($tagName, ['method' => $publicReflectionMethod->name]);
115 13
                }
116 13
                if ($isAliased) {
117 13
                    $this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, true);
118 13
                }
119 13
            } else {
120 1
                $definition->addTag($tagName);
121 1
                $this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, false);
122
            }
123 13
        }
124 13
    }
125
126 13
    private function addDefinitionTagsFromAliasesMethod(Definition $definition, $className, $tagName, $withMethod)
127
    {
128
        // from getAliases
129 13
        if (!is_callable([$className, 'getAliases'])) {
130 1
            return;
131
        }
132 13
        $aliases = call_user_func([$className, 'getAliases']);
133
134 13
        foreach ($aliases as $key => $alias) {
135 13
            $definition->addTag($tagName, $withMethod ? ['alias' => $alias, 'method' => $key] : ['alias' => $alias]);
136 13
        }
137 13
    }
138
139 13
    private function subclass($class)
140
    {
141 13
        $interfaces = array_keys(self::$serviceSubclassTagMapping);
142
143 13
        foreach ($interfaces as $interface) {
144 13
            if (is_a($class, $interface, true)) {
145 13
                return $interface;
146
            }
147 13
        }
148
149 13
        return false;
150
    }
151
152
    /**
153
     * Gets the classes reflection of class in the given directory.
154
     *
155
     * @param string $directory
156
     *
157
     * @return array
158
     */
159 13
    private function reflectionClassesFromDirectory($directory)
160
    {
161 13
        $classes = [];
162 13
        $directoryList = [];
163 13
        $includedFiles = [];
164 13
        $reflectionClasses = [];
165
166 13
        $finder = new Finder();
167
        try {
168 13
            $finder->in($directory)->files()->name('*.php');
169 13
        } catch (\InvalidArgumentException $e) {
170 1
            return [$reflectionClasses, $directoryList];
171
        }
172
173 13
        foreach ($finder as $file) {
174 13
            $directoryList[$file->getPath()] = true;
175 13
            $sourceFile = $file->getRealpath();
176 13
            if (!preg_match('(^phar:)i', $sourceFile)) {
177 13
                $sourceFile = realpath($sourceFile);
178 13
            }
179
180 13
            require_once $sourceFile;
181 13
            $includedFiles[$sourceFile] = true;
182 13
        }
183
184 13
        $declared = get_declared_classes();
185 13
        foreach ($declared as $className) {
186 13
            $subclass = $this->subclass($className);
187 13
            if (false === $subclass) {
188 13
                continue;
189
            }
190 13
            $reflectionClass = new \ReflectionClass($className);
191 13
            $reflectionClasses[$className] = $reflectionClass;
192 13
            $sourceFile = $reflectionClass->getFileName();
193
194 13
            if ($reflectionClass->isAbstract()) {
195 13
                continue;
196
            }
197
198 13
            if (isset($includedFiles[$sourceFile])) {
199 13
                $classes[$className] = true;
200 13
            }
201 13
        }
202
203 13
        return [array_intersect_key($reflectionClasses, $classes), $directoryList];
204
    }
205
}
206