Passed
Push — master ( a2cf38...39e4c0 )
by Michael
18:56
created

AnnotationDefinitionProvider::getDefinition()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
ccs 10
cts 10
cp 1
rs 9.3142
cc 3
eloc 11
nc 3
nop 1
crap 3
1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Component\JsonApi\Mapper\Definition;
5
6
use Doctrine\Common\Annotations\Reader;
7
use Mikemirten\Component\JsonApi\Mapper\Definition\Annotation\Relationship as RelationshipAnnotation;
8
9
/**
10
 * Annotation Definition Provider based on the Doctrine-Annotation library
11
 *
12
 * @package Mikemirten\Component\JsonApi\Mapper\Definition
13
 */
14
class AnnotationDefinitionProvider implements DefinitionProviderInterface
15
{
16
    /**
17
     * Doctrine annotation reader
18
     *
19
     * @var Reader
20
     */
21
    protected $reader;
22
23
    /**
24
     * AnnotationDefinitionProvider constructor.
25
     *
26
     * @param Reader $reader
27
     */
28 2
    public function __construct(Reader $reader)
29
    {
30 2
        $this->reader = $reader;
31 2
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 2
    public function getDefinition(string $class): Definition
37
    {
38 2
        $definition = new Definition();
39 2
        $reflection = new \ReflectionClass($class);
40
41 2
        foreach ($reflection->getProperties() as $property)
42
        {
43 2
            $relationshipAnnotation = $this->reader->getPropertyAnnotation(
44
                $property,
45 2
                RelationshipAnnotation::class
46
            );
47
48 2
            if ($relationshipAnnotation !== null) {
49 2
                $relationship = $this->createRelationship($relationshipAnnotation, $property);
50
51 2
                $definition->addRelationship($relationship);
52
            }
53
        }
54
55 2
        return $definition;
56
    }
57
58
    /**
59
     * Process relationship
60
     *
61
     * @param  RelationshipAnnotation $annotation
62
     * @param  \ReflectionProperty    $property
63
     * @return Relationship
64
     */
65 2
    protected function createRelationship(RelationshipAnnotation $annotation, \ReflectionProperty $property): Relationship
66
    {
67 2
        $name = ($annotation->name === null)
68 1
            ? $property->getName()
69 2
            : $annotation->name;
70
71 2
        $type = $this->resoleType($annotation);
72
73 2
        $relationship = new Relationship($name, $type);
74 2
        $relationship->setPropertyName($property->getName());
75
76 2
        if ($annotation->resourceType !== null) {
77 2
            $relationship->setResourceType($annotation->resourceType);
78
        }
79
80 2
        $this->handleGetter($annotation, $relationship);
81 2
        $this->handleIdentifier($annotation, $relationship);
82
83 2
        return $relationship;
84
    }
85
86
    /**
87
     * Handler getter of related object
88
     *
89
     * @param RelationshipAnnotation $annotation
90
     * @param Relationship           $relationship
91
     */
92 2
    protected function handleGetter(RelationshipAnnotation $annotation, Relationship $relationship)
93
    {
94 2
        if ($annotation->getter === null) {
95 1
            $name   = $relationship->getPropertyName();
96 1
            $getter = 'get' . ucfirst($name);
97
98 1
            $relationship->setGetter($getter);
99 1
            return;
100
        }
101
102 1
        $relationship->setGetter($annotation->getter);
103 1
    }
104
105
    /**
106
     * Handle identifier
107
     *
108
     * @param RelationshipAnnotation $annotation
109
     * @param Relationship           $relationship
110
     */
111 2
    protected function handleIdentifier(RelationshipAnnotation $annotation, Relationship $relationship)
112
    {
113 2
        if ($annotation->idGetter !== null) {
114
            $relationship->setIdentifierGetter($annotation->idGetter);
115
            return;
116
        }
117
118 2
        if ($annotation->idProperty !== null) {
119 2
            $getter = 'get' . ucfirst($annotation->idProperty);
120
121 2
            $relationship->setIdentifierGetter($getter);
122 2
            return;
123
        }
124
    }
125
126
    /**
127
     * Resolve type of relationship
128
     *
129
     * @param  RelationshipAnnotation $annotation
130
     * @return int
131
     */
132 2
    protected function resoleType(RelationshipAnnotation $annotation): int
133
    {
134 2
        if ($annotation->type === RelationshipAnnotation::TYPE_ONE) {
135
            return Relationship::TYPE_X_TO_ONE;
136
        }
137
138 2
        if ($annotation->type === RelationshipAnnotation::TYPE_MANY) {
139 2
            return Relationship::TYPE_X_TO_MANY;
140
        }
141
142
        throw new \LogicException(sprintf('Invalid type of relation "%s" defined.', $annotation->type));
143
    }
144
}