DoctrineFieldDefinitionDecorator   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Test Coverage

Coverage 85.53%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 35
eloc 74
c 2
b 0
f 1
dl 0
loc 133
ccs 65
cts 76
cp 0.8553
rs 9.6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
C getGraphQLType() 0 38 17
F decorateFieldDefinition() 0 67 17
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Definition\Loader\Annotation\FieldDecorator;
12
13
use Doctrine\Common\Annotations\Reader;
14
use Doctrine\DBAL\Types\Type as DoctrineType;
15
use Doctrine\ORM\Mapping\Column;
16
use Doctrine\ORM\Mapping\Embedded;
17
use Doctrine\ORM\Mapping\Id;
18
use Doctrine\ORM\Mapping\ManyToMany;
19
use Doctrine\ORM\Mapping\ManyToOne;
20
use Doctrine\ORM\Mapping\OneToMany;
21
use Doctrine\ORM\Mapping\OneToOne;
22
use Ynlo\GraphQLBundle\Definition\FieldDefinition;
23
use Ynlo\GraphQLBundle\Definition\ObjectDefinitionInterface;
24
use Ynlo\GraphQLBundle\Type\Types;
25
use Ynlo\GraphQLBundle\Util\TypeUtil;
26
27
/**
28
 * Decorate a field definition using doctrine annotations
29
 */
30
class DoctrineFieldDefinitionDecorator implements FieldDefinitionDecoratorInterface
31
{
32
    /**
33
     * @var Reader
34
     */
35
    protected $reader;
36
37
    /**
38
     * DoctrineFieldDefinitionDecorator constructor.
39
     *
40
     * @param Reader $reader
41
     */
42 42
    public function __construct(Reader $reader)
43
    {
44 42
        $this->reader = $reader;
45 42
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 37
    public function decorateFieldDefinition($field, FieldDefinition $definition, ObjectDefinitionInterface $objectDefinition)
51
    {
52 37
        if (!$field instanceof \ReflectionProperty && !$field instanceof \ReflectionMethod) {
53
            throw new \InvalidArgumentException('Invalid argument, expected reflection of property or method');
54
        }
55
56 37
        if ($field instanceof \ReflectionMethod) {
57 32
            return;
58
        }
59
60 37
        $pagination = $definition->getMeta('pagination') ?: [];
61 37
        $targetNode = null;
62
63
        /** @var Column $column */
64 37
        if ($column = $this->reader->getPropertyAnnotation($field, Column::class)) {
65 36
            $type = $this->getGraphQLType($column->type);
66 36
            $definition->setType(TypeUtil::normalize($type));
67 36
            $definition->setList(TypeUtil::isTypeList($type));
68 36
            $definition->setNonNullList(TypeUtil::isTypeNonNullList($type));
69 36
            $definition->setNonNull(!$column->nullable);
70
        }
71
72
        /** @var Id $id */
73 37
        if ($field->getName() === 'id' && ($column = $this->reader->getPropertyAnnotation($field, Id::class))) {
0 ignored issues
show
Unused Code introduced by
The assignment to $column is dead and can be removed.
Loading history...
74
            $definition->setType(Types::ID);
75
            $definition->setNonNull(true);
76
        }
77
78
        /** @var OneToOne $oneToOne */
79 37
        if ($oneToOne = $this->reader->getPropertyAnnotation($field, OneToOne::class)) {
80 15
            $definition->setType($targetNode = $oneToOne->targetEntity);
81
        }
82
83
        /** @var OneToMany $oneToMany */
84 37
        if ($oneToMany = $this->reader->getPropertyAnnotation($field, OneToMany::class)) {
85 32
            $definition->setType($targetNode = $oneToMany->targetEntity);
86 32
            $definition->setList(true);
87 32
            if ($oneToMany->fetch === 'EXTRA_LAZY') {
88 28
                $pagination['target'] = $pagination['target'] ?? $targetNode;
89 28
                $pagination['parent_field'] = $pagination['parent_field'] ?? $oneToMany->mappedBy;
90 28
                $pagination['parent_relation'] = $pagination['parent_relation'] ?? 'ONE_TO_MANY';
91
            }
92
        }
93
94
        /** @var ManyToOne $manyToOne */
95 37
        if ($manyToOne = $this->reader->getPropertyAnnotation($field, ManyToOne::class)) {
96 28
            $definition->setType($targetNode = $manyToOne->targetEntity);
97
        }
98
99
        /** @var ManyToMany $manyToMany */
100 37
        if ($manyToMany = $this->reader->getPropertyAnnotation($field, ManyToMany::class)) {
101 32
            $definition->setType($targetNode = $manyToMany->targetEntity);
102 32
            $definition->setList(true);
103 32
            if ($manyToMany->fetch === 'EXTRA_LAZY') {
104
                $pagination['target'] = $pagination['target'] ?? $targetNode;
105
                $pagination['parent_field'] = $pagination['parent_field'] ?? $manyToMany->mappedBy ?? $manyToMany->inversedBy;
106
                $pagination['parent_relation'] = $pagination['parent_relation'] ?? 'MANY_TO_MANY';
107
            }
108
        }
109
110
        /** @var Embedded $embedded */
111 37
        if ($embedded = $this->reader->getPropertyAnnotation($field, Embedded::class)) {
112
            $definition->setType($embedded->class);
113
        }
114
115 37
        if ($definition->isList() && $pagination) {
116 28
            $definition->setMeta('pagination', $pagination);
117
        }
118 37
    }
119
120
    /**
121
     * @param string $type
122
     *
123
     * @return string
124
     */
125 36
    protected function getGraphQLType(?string $type):?string
126
    {
127
        switch ($type) {
128 36
            case DoctrineType::BOOLEAN:
129 32
                $type = Types::BOOLEAN;
130 32
                break;
131 36
            case DoctrineType::DECIMAL:
132 36
            case DoctrineType::FLOAT:
133 32
                $type = Types::FLOAT;
134 32
                break;
135 36
            case DoctrineType::INTEGER:
136 36
            case DoctrineType::BIGINT:
137 36
            case DoctrineType::SMALLINT:
138 32
                $type = Types::INT;
139 32
                break;
140 36
            case DoctrineType::STRING:
141 36
            case DoctrineType::TEXT:
142 36
            case DoctrineType::GUID:
143 36
                $type = Types::STRING;
144 36
                break;
145 36
            case DoctrineType::TARRAY:
146 36
            case DoctrineType::SIMPLE_ARRAY:
147 36
            case DoctrineType::JSON_ARRAY:
148 32
                $type = Types::nonNull(Types::listOf(Types::STRING));
149 32
                break;
150 36
            case DoctrineType::TIME:
151 36
            case DoctrineType::TIME_IMMUTABLE:
152
                $type = Types::TIME;
153
                break;
154 36
            case DoctrineType::DATE:
155
                $type = Types::DATE;
156
                break;
157 36
            case DoctrineType::DATETIME:
158 36
                $type = Types::DATETIME;
159 36
                break;
160
        }
161
162 36
        return $type;
163
    }
164
}
165