Failed Conditions
Pull Request — master (#62)
by Adrien
06:30 queued 04:20
created

AbstractFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
c 1
b 0
f 0
dl 0
loc 2
ccs 0
cts 0
cp 0
rs 10
cc 1
nc 1
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Doctrine\Factory;
6
7
use Doctrine\Common\Annotations\Reader;
8
use Doctrine\ORM\EntityManager;
9
use Doctrine\Persistence\Mapping\Driver\AnnotationDriver;
10
use Doctrine\Persistence\Mapping\Driver\MappingDriverChain;
11
use GraphQL\Doctrine\Annotation\Exclude;
12
use GraphQL\Doctrine\Exception;
13
use GraphQL\Doctrine\Factory\MetadataReader\MappingDriverChainAdapter;
1 ignored issue
show
Bug introduced by
The type GraphQL\Doctrine\Factory...ppingDriverChainAdapter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use GraphQL\Doctrine\Types;
15
use GraphQL\Type\Definition\Type;
16
use ReflectionClass;
17
use ReflectionProperty;
18
19
/**
20
 * Abstract factory to be aware of types and entityManager.
21
 */
22
abstract class AbstractFactory
23
{
24
    public function __construct(protected Types $types, protected EntityManager $entityManager)
25
    {
26
    }
27
28
    /**
29
     * Get annotation reader.
30
     */
31 46
    final protected function getAnnotationReader(): Reader
32
    {
33 46
        $driver = $this->entityManager->getConfiguration()->getMetadataDriverImpl();
34 46
        if ($driver instanceof AnnotationDriver) {
35 42
            return $driver->getReader();
36
        }
37
38 4
        if ($driver instanceof MappingDriverChain) {
39 3
            return new MappingDriverChainAdapter($driver);
40
        }
41
42 1
        throw new Exception('graphql-doctrine requires Doctrine to be configured with a `' . AnnotationDriver::class . '`.');
43
    }
44
45
    /**
46
     * Returns whether the property is excluded.
47
     */
48 17
    final protected function isPropertyExcluded(ReflectionProperty $property): bool
49
    {
50 17
        $exclude = $this->getAnnotationReader()->getPropertyAnnotation($property, Exclude::class);
51
52 17
        return $exclude !== null;
53
    }
54
55
    /**
56
     * Get instance of GraphQL type from a PHP class name.
57
     *
58
     * Supported syntaxes are the following:
59
     *
60
     *  - `?MyType`
61
     *  - `null|MyType`
62
     *  - `MyType|null`
63
     *  - `MyType[]`
64
     *  - `?MyType[]`
65
     *  - `null|MyType[]`
66
     *  - `MyType[]|null`
67
     */
68 32
    final protected function getTypeFromPhpDeclaration(ReflectionClass $class, ?string $typeDeclaration, bool $isEntityId = false): ?Type
69
    {
70 32
        if (!$typeDeclaration) {
71 21
            return null;
72
        }
73
74 26
        $isNullable = 0;
75 26
        $name = preg_replace('~(^\?|^null\||\|null$)~', '', $typeDeclaration, -1, $isNullable);
76
77 26
        $isList = 0;
78 26
        $name = preg_replace('~^(.*)\[\]$~', '$1', $name, -1, $isList);
79 26
        $name = $this->adjustNamespace($class, $name);
80 26
        $type = $this->getTypeFromRegistry($name, $isEntityId);
81
82 26
        if ($isList) {
83 6
            $type = Type::listOf(Type::nonNull($type));
84
        }
85
86 26
        if (!$isNullable) {
87 15
            $type = Type::nonNull($type);
88
        }
89
90 26
        return $type;
91
    }
92
93
    /**
94
     * Prepend namespace of the method if the class actually exists.
95
     */
96 26
    private function adjustNamespace(ReflectionClass $class, string $type): string
97
    {
98 26
        if ($type === 'self') {
99 2
            $type = $class->getName();
100
        }
101
102 26
        $namespace = $class->getNamespaceName();
103 26
        if ($namespace) {
104 26
            $namespacedType = $namespace . '\\' . $type;
105
106 26
            if (class_exists($namespacedType)) {
107 2
                return $namespacedType;
108
            }
109
        }
110
111 26
        return $type;
112
    }
113
114
    /**
115
     * Returns a type from our registry.
116
     */
117 27
    final protected function getTypeFromRegistry(string $type, bool $isEntityId): Type
118
    {
119 27
        if ($this->types->isEntity($type) && $isEntityId) {
120
            // @phpstan-ignore-next-line
121 7
            return $this->types->getId($type);
122
        }
123
124 27
        if ($this->types->isEntity($type) && !$isEntityId) {
125
            // @phpstan-ignore-next-line
126 9
            return $this->types->getOutput($type);
127
        }
128
129 25
        return $this->types->get($type);
130
    }
131
}
132