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

Passed
Pull Request — master (#234)
by Jérémiah
07:13
created

AutoMappingPass   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 5
dl 0
loc 187
ccs 101
cts 101
cp 1
rs 9.2
c 0
b 0
f 0

8 Methods

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