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
04:38
created

AutoMappingPass::addServiceDefinition()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2.0054

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 8
cts 9
cp 0.8889
rs 9.4285
cc 2
eloc 8
nc 2
nop 2
crap 2.0054
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 10
    public function process(ContainerBuilder $container)
27
    {
28 10
        $enabled = $container->getParameter('overblog_graphql.auto_mapping.enabled');
29
        // enabled auto mapping for all bundles and custom dirs ?
30 10
        if ($enabled) {
31
            $directories = $container->getParameter('overblog_graphql.auto_mapping.directories');
32
            $bundles = $container->getParameter('kernel.bundles');
33
            $directories = array_merge(
34
                array_map(
35
                    function ($class) {
36
                        $bundleDir = $this->bundleDir($class);
37
38
                        return $bundleDir.'/GraphQL';
39
                    },
40
                    $bundles
41
                ),
42
                $directories
43
            );
44
            // add app dir
45
            if ($container->hasParameter('kernel.root_dir')) {
46
                $directories[] = $container->getParameter('kernel.root_dir').'/GraphQL';
47
            }
48
        } else {
49
            // enabled auto mapping only for this bundle
50 10
            $directories = [$this->bundleDir(OverblogGraphQLBundle::class).'/GraphQL'];
51
        }
52 10
        $directoryList = [];
53
54 10
        foreach ($directories as $directory) {
55 10
            list($reflectionClasses, $directories) = $this->reflectionClassesFromDirectory($directory);
56 10
            $directoryList = array_merge($directoryList, $directories);
57 10
            $this->addServicesDefinitions($container, $reflectionClasses);
58
        }
59
60 10
        foreach ($directoryList as $directory => $v) {
61 10
            $directory = realpath($directory);
62 10
            $container->addResource(new DirectoryResource($directory, '/\.php$/'));
63
        }
64 10
    }
65
66
    /**
67
     * @param ContainerBuilder   $container
68
     * @param \ReflectionClass[] $reflectionClasses
69
     */
70 10
    private function addServicesDefinitions(ContainerBuilder $container, array $reflectionClasses)
71
    {
72 10
        foreach ($reflectionClasses as $reflectionClass) {
73 10
            $this->addServiceDefinition($container, $reflectionClass);
74
        }
75 10
    }
76
77 10
    private function addServiceDefinition(ContainerBuilder $container, \ReflectionClass $reflectionClass)
78
    {
79 10
        $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 10
        $definition = $container->setDefinition($className, new Definition($className));
81 10
        $definition->setPublic(false);
82 10
        $definition->setAutowired(true);
83 10
        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
            $definition->addMethodCall('setContainer', [new Reference('service_container')]);
85
        }
86 10
        $this->addDefinitionTags($definition, $reflectionClass);
87 10
    }
88
89 10
    private function addDefinitionTags(Definition $definition, \ReflectionClass $reflectionClass)
90
    {
91 10
        $className = $definition->getClass();
92
93 10
        foreach (self::$serviceSubclassTagMapping as $subclass => $tagName) {
94 10
            if (!$reflectionClass->isSubclassOf($subclass)) {
95 10
                continue;
96
            }
97
98 10
            if (Type::class !== $subclass) {
99 10
                $publicReflectionMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
100 10
                $isAliased = $reflectionClass->implementsInterface(AliasedInterface::class);
101 10
                foreach ($publicReflectionMethods as $publicReflectionMethod) {
102 10
                    if ('__construct' === $publicReflectionMethod->name || $isAliased && 'getAliases' === $publicReflectionMethod->name) {
103 10
                        continue;
104
                    }
105 10
                    $definition->addTag($tagName, ['method' => $publicReflectionMethod->name]);
106
                }
107 10
                if ($isAliased) {
108 10
                    $this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, true);
109
                }
110
            } else {
111
                $definition->addTag($tagName);
112 10
                $this->addDefinitionTagsFromAliasesMethod($definition, $className, $tagName, false);
113
            }
114
        }
115 10
    }
116
117 10
    private function addDefinitionTagsFromAliasesMethod(Definition $definition, $className, $tagName, $withMethod)
118
    {
119
        // from getAliases
120 10
        if (!is_callable([$className, 'getAliases'])) {
121
            return;
122
        }
123 10
        $aliases = call_user_func([$className, 'getAliases']);
124
125 10
        foreach ($aliases as $key => $alias) {
126 10
            $definition->addTag($tagName, $withMethod ? ['alias' => $alias, 'method' => $key] : ['alias' => $alias]);
127
        }
128 10
    }
129
130 10
    private function subclass($class)
131
    {
132 10
        $interfaces = array_keys(self::$serviceSubclassTagMapping);
133
134 10
        foreach ($interfaces as $interface) {
135 10
            if (is_a($class, $interface, true)) {
136 10
                return $interface;
137
            }
138
        }
139
140 10
        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 10
    private function reflectionClassesFromDirectory($directory)
151
    {
152 10
        $classes = [];
153 10
        $directoryList = [];
154 10
        $includedFiles = [];
155 10
        $reflectionClasses = [];
156
157 10
        $finder = new Finder();
158
        try {
159 10
            $finder->in($directory)->files()->name('*.php');
160
        } catch (\InvalidArgumentException $e) {
161
            return [$reflectionClasses, $directoryList];
162
        }
163
164 10
        foreach ($finder as $file) {
165 10
            $directoryList[$file->getPath()] = true;
166 10
            $sourceFile = $file->getRealpath();
167 10
            if (!preg_match('(^phar:)i', $sourceFile)) {
168 10
                $sourceFile = realpath($sourceFile);
169
            }
170
171 10
            require_once $sourceFile;
172 10
            $includedFiles[$sourceFile] = true;
173
        }
174
175 10
        $declared = get_declared_classes();
176 10
        foreach ($declared as $className) {
177 10
            $subclass = $this->subclass($className);
178 10
            if (false === $subclass) {
179 10
                continue;
180
            }
181 10
            $reflectionClass = new \ReflectionClass($className);
182 10
            $reflectionClasses[$className] = $reflectionClass;
183 10
            $sourceFile = $reflectionClass->getFileName();
184
185 10
            if ($reflectionClass->isAbstract()) {
186 10
                continue;
187
            }
188
189 10
            if (isset($includedFiles[$sourceFile])) {
190 10
                $classes[$className] = true;
191
            }
192
        }
193
194 10
        return [array_intersect_key($reflectionClasses, $classes), $directoryList];
195
    }
196
197 10
    private function bundleDir($bundleClass)
198
    {
199 10
        $bundle = new \ReflectionClass($bundleClass);
200 10
        $bundleDir = dirname($bundle->getFileName());
201
202 10
        return $bundleDir;
203
    }
204
}
205