Completed
Push — master ( ac0b2b...25e509 )
by Nate
02:57
created

createPropertyAnnotations()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 36
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 36
ccs 18
cts 18
cp 1
rs 8.439
c 0
b 0
f 0
cc 6
eloc 18
nc 7
nop 2
crap 6
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
namespace Tebru\Gson\Internal\Data;
8
9
use Doctrine\Common\Annotations\Reader;
10
use Doctrine\Common\Cache\Cache;
11
use ReflectionClass;
12
use ReflectionMethod;
13
use ReflectionProperty;
14
15
/**
16
 * Class AnnotationCollectionFactory
17
 *
18
 * @author Nate Brunette <[email protected]>
19
 */
20
final class AnnotationCollectionFactory
21
{
22
    /**
23
     * Doctrine annotation reader
24
     *
25
     * @var Reader
26
     */
27
    private $reader;
28
29
    /**
30
     * Cache for collection of annotations
31
     *
32
     * @var Cache
33
     */
34
    private $cache;
35
36
    /**
37
     * Constructor
38
     *
39
     * @param Reader $reader
40
     * @param Cache $cache
41
     */
42 8
    public function __construct(Reader $reader, Cache $cache)
43
    {
44 8
        $this->reader = $reader;
45 8
        $this->cache = $cache;
46 8
    }
47
48
    /**
49
     * Create a set of property annotations
50
     *
51
     * @param string $className
52
     * @param string $propertyName
53
     * @return AnnotationSet
54
     * @throws \InvalidArgumentException If the type does not exist
55
     */
56 4
    public function createPropertyAnnotations(string $className, string $propertyName): AnnotationSet
57
    {
58 4
        $key = $className.':'.$propertyName;
59 4
        if ($this->cache->contains($key)) {
60 1
            return $this->cache->fetch($key);
61
        }
62
63 3
        $reflectionProperty = new ReflectionProperty($className, $propertyName);
64
65 3
        $annotations = new AnnotationSet();
66
67
        // start with with all property annotations
68 3
        foreach ($this->reader->getPropertyAnnotations($reflectionProperty) as $defaultAnnotation) {
69 3
            $annotations->addAnnotation($defaultAnnotation, AnnotationSet::TYPE_PROPERTY);
70
        }
71
72 3
        $reflectionClass = $reflectionProperty->getDeclaringClass();
73 3
        $parentClass = $reflectionClass->getParentClass();
74
75 3
        while (false !== $parentClass) {
76
            // add parent property annotations if they exist
77 1
            if ($parentClass->hasProperty($reflectionProperty->getName())) {
78 1
                $parentProperty = $parentClass->getProperty($reflectionProperty->getName());
79 1
                foreach ($this->reader->getPropertyAnnotations($parentProperty) as $parentPropertyAnnotation) {
80 1
                    $annotations->addAnnotation($parentPropertyAnnotation, AnnotationSet::TYPE_PROPERTY);
81
                }
82
            }
83
84
            // reset $parentClass
85 1
            $parentClass = $parentClass->getParentClass();
86
        }
87
88 3
        $this->cache->save($key, $annotations);
89
90 3
        return $annotations;
91
    }
92
93
    /**
94
     * Create a set of class annotations
95
     *
96
     * @param string $className
97
     * @return AnnotationSet
98
     * @throws \InvalidArgumentException If the type does not exist
99
     */
100 2
    public function createClassAnnotations(string $className): AnnotationSet
101
    {
102 2
        if ($this->cache->contains($className)) {
103 1
            return $this->cache->fetch($className);
104
        }
105
106 1
        $reflectionClass = new ReflectionClass($className);
107
108 1
        $annotations = new AnnotationSet();
109 1
        foreach ($this->reader->getClassAnnotations($reflectionClass) as $annotation) {
110 1
            $annotations->addAnnotation($annotation, AnnotationSet::TYPE_CLASS);
111
        }
112 1
        $parentClass = $reflectionClass->getParentClass();
113
114 1
        while (false !== $parentClass) {
115 1
            foreach ($this->reader->getClassAnnotations($parentClass) as $parentAnnotation) {
116 1
                $annotations->addAnnotation($parentAnnotation, AnnotationSet::TYPE_CLASS);
117
            }
118 1
            $parentClass = $parentClass->getParentClass();
119
        }
120
121 1
        $this->cache->save($className, $annotations);
122
123 1
        return $annotations;
124
    }
125
126
    /**
127
     * Create a set of method annotations
128
     *
129
     * @param string $className
130
     * @param string $methodName
131
     * @return AnnotationSet
132
     * @throws \InvalidArgumentException If the type does not exist
133
     */
134 2
    public function createMethodAnnotations(string $className, string $methodName): AnnotationSet
135
    {
136 2
        $key = $className.':'.$methodName;
137 2
        if ($this->cache->contains($key)) {
138 1
            return $this->cache->fetch($key);
139
        }
140
141 1
        $annotations = new AnnotationSet();
142
143 1
        $reflectionMethod = new ReflectionMethod($className, $methodName);
144 1
        foreach ($this->reader->getMethodAnnotations($reflectionMethod) as $annotation) {
145 1
            $annotations->addAnnotation($annotation, AnnotationSet::TYPE_METHOD);
146
        }
147
148 1
        $this->cache->save($key, $annotations);
149
150 1
        return $annotations;
151
    }
152
}
153