Completed
Push — master ( 92472c...fe56a0 )
by Vitaly
02:18
created

AnnotationResolver::resolve()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 9
Bugs 0 Features 6
Metric Value
c 9
b 0
f 6
dl 0
loc 25
ccs 0
cts 14
cp 0
rs 8.5806
cc 4
eloc 12
nc 8
nop 2
crap 20
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: root
5
 * Date: 29.07.2016
6
 * Time: 21:38.
7
 */
8
namespace samsonframework\container\resolver;
9
10
use Doctrine\Common\Annotations\AnnotationReader;
11
use samsonframework\container\annotation\ClassInterface;
12
use samsonframework\container\annotation\MetadataInterface;
13
use samsonframework\container\annotation\MethodAnnotation;
14
use samsonframework\container\annotation\MethodInterface;
15
use samsonframework\container\annotation\PropertyInterface;
16
use samsonframework\container\metadata\ClassMetadata;
17
use samsonframework\container\metadata\MethodMetadata;
18
use samsonframework\container\metadata\PropertyMetadata;
19
20
/**
21
 * Annotation resolver class.
22
 */
23
class AnnotationResolver extends Resolver
24
{
25
    /** Property typeHint hint pattern */
26
    const P_PROPERTY_TYPE_HINT = '/@var\s+(?<class>[^\s]+)/';
27
28
    /**
29
     * @var AnnotationReader
30
     */
31
    protected $reader;
32
33
    /**
34
     * AnnotationResolver constructor.
35
     *
36
     * @throws \InvalidArgumentException
37
     */
38 1
    public function __construct()
39
    {
40 1
        $this->reader = new AnnotationReader();
41 1
    }
42
43
    /**
44
     * {@inheritDoc}
45
     */
46
    public function resolve($classData, $identifier = null)
47
    {
48
        /** @var \ReflectionClass $classData */
49
50
        // Create and fill class metadata base fields
51
        $metadata = new ClassMetadata();
52
        $metadata->className = $classData->getName();
53
        $metadata->nameSpace = $classData->getNamespaceName();
54
        $metadata->internalId = $identifier ?: uniqid();
55
        $metadata->name = $metadata->internalId;
56
57
        $this->resolveClassAnnotations($classData, $metadata);
58
59
        /** @var \ReflectionProperty $method */
60
        foreach ($classData->getProperties() as $property) {
61
            $this->resolveClassPropertyAnnotations($property, $metadata);
62
        }
63
64
        /** @var \ReflectionMethod $method */
65
        foreach ($classData->getMethods() as $method) {
66
            $this->resolveMethodAnnotation($method, $metadata);
67
        }
68
69
        return $metadata;
70
    }
71
72
    /**
73
     * Resolve all class annotations.
74
     *
75
     * @param \ReflectionClass $classData
76
     * @param ClassMetadata    $metadata
77
     */
78
    protected function resolveClassAnnotations(\ReflectionClass $classData, ClassMetadata $metadata)
79
    {
80
        /** @var ClassInterface $annotation Read class annotations */
81
        foreach ($this->reader->getClassAnnotations($classData) as $annotation) {
82
            if ($annotation instanceof ClassInterface) {
83
                $annotation->toClassMetadata($metadata);
84
            }
85
        }
86
    }
87
88
    /**
89
     * Resolve all class property annotations.
90
     *
91
     * @param \ReflectionProperty $property
92
     * @param ClassMetadata       $classMetadata
93
     */
94
    protected function resolveClassPropertyAnnotations(\ReflectionProperty $property, ClassMetadata $classMetadata)
95
    {
96
        // Create method metadata instance
97
        $propertyMetadata = new PropertyMetadata($classMetadata);
98
        $propertyMetadata->name = $property->getName();
99
        $propertyMetadata->modifiers = $property->getModifiers();
100
101
        // Parse property typeHint hint if present
102
        if (preg_match('/@var\s+(?<class>[^\s]+)/', $property->getDocComment(), $matches)) {
103
            list(, $propertyMetadata->typeHint) = $matches;
104
        }
105
106
        /** @var PropertyInterface $annotation Read class annotations */
107
        foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
108
            if ($annotation instanceof PropertyInterface) {
109
                $annotation->toPropertyMetadata($propertyMetadata);
110
            }
111
        }
112
113
        $classMetadata->propertyMetadata[$propertyMetadata->name] = $propertyMetadata;
114
    }
115
116
    /**
117
     * Resolve all method annotations.
118
     *
119
     * @param \ReflectionMethod $method
120
     * @param ClassMetadata     $metadata
121
     */
122
    protected function resolveMethodAnnotation(\ReflectionMethod $method, ClassMetadata $metadata)
123
    {
124
        // Create method metadata instance
125
        $methodMetadata = new MethodMetadata();
126
        $methodMetadata->name = $method->getName();
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
127
        $methodMetadata->modifiers = $method->getModifiers();
128
        $methodMetadata->parameters = $method->getParameters();
129
130
        /** @var MethodInterface $annotation */
131
        foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
132
            if ($annotation instanceof MethodInterface) {
133
                $methodMetadata->options[] = $annotation->toMethodMetadata($methodMetadata);
134
            }
135
        }
136
137
        $metadata->methodsMetadata[$method->getName()] = $methodMetadata;
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
138
    }
139
}
140