Completed
Push — master ( 00ced4...d3edd8 )
by
unknown
07:54
created

ReflectionParameterAnalyzer::analyze()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 23
ccs 11
cts 11
cp 1
rs 8.7972
c 1
b 0
f 0
cc 4
eloc 13
nc 3
nop 3
crap 4
1
<?php declare(strict_types = 1);
2
/**
3
 * Created by Ruslan Molodyko.
4
 * Date: 10.09.2016
5
 * Time: 15:33
6
 */
7
namespace samsonframework\container\definition\analyzer\reflection;
8
9
use samsonframework\container\definition\analyzer\DefinitionAnalyzer;
10
use samsonframework\container\definition\analyzer\ParameterAnalyzerInterface;
11
use samsonframework\container\definition\builder\exception\ReferenceNotImplementsException;
12
use samsonframework\container\definition\ClassDefinition;
13
use samsonframework\container\definition\exception\MethodDefinitionNotFoundException;
14
use samsonframework\container\definition\exception\ParameterDefinitionAlreadyExistsException;
15
use samsonframework\container\definition\exception\ParameterDefinitionNotFoundException;
16
use samsonframework\container\definition\ParameterDefinition;
17
use samsonframework\container\definition\reference\ClassReference;
18
use samsonframework\container\definition\reference\CollectionReference;
19
use samsonframework\container\definition\reference\ConstantReference;
20
use samsonframework\container\definition\reference\UndefinedReference;
21
22
/**
23
 * Class ReflectionParameterAnalyzer
24
 *
25
 * @author Ruslan Molodyko <[email protected]>
26
 */
27
class ReflectionParameterAnalyzer implements ParameterAnalyzerInterface
28
{
29
    /**
30
     * {@inheritdoc}
31
     * @throws ParameterDefinitionAlreadyExistsException
32
     * @throws ReferenceNotImplementsException
33
     * @throws MethodDefinitionNotFoundException
34
     * @throws ParameterDefinitionNotFoundException
35
     * @throws \InvalidArgumentException
36
     */
37 4
    public function analyze(
38
        DefinitionAnalyzer $analyzer,
39
        ClassDefinition $classDefinition,
40
        \ReflectionParameter $reflectionParameter
41
    ) {
42 4
        $methodName = $reflectionParameter->getDeclaringFunction()->getName();
0 ignored issues
show
Bug introduced by
Consider using $reflectionParameter->ge...claringFunction()->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
43 4
        $parameterName = $reflectionParameter->getName();
0 ignored issues
show
Bug introduced by
Consider using $reflectionParameter->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
44
        // Define parameter only if method definition is available
45 4
        if ($classDefinition->hasMethod($methodName)) {
46 4
            $methodDefinition = $classDefinition->getMethod($methodName);
47
48
            // Define parameter definition if not exists
49 4
            $parameterDefinition = $methodDefinition->setupParameter($parameterName);
50 4
            $this->setReflectionMetadata($parameterDefinition, $reflectionParameter);
51
52 4
            $dependency = $parameterDefinition->getDependency();
53
            // If dependency was not set
54
            // UndefinedReference is the default value of dependency which was not use before
55 4
            if (!$dependency || ($dependency instanceof UndefinedReference)) {
56 1
                $this->setDependencyByReflection($parameterDefinition, $reflectionParameter);
57
            }
58
        }
59 4
    }
60
61
    /**
62
     * Set initial reflection metadata into the parameter definition
63
     *
64
     * @param ParameterDefinition $parameterDefinition
65
     * @param \ReflectionParameter $reflectionParameter
66
     */
67 4
    public function setReflectionMetadata(
68
        ParameterDefinition $parameterDefinition,
69
        \ReflectionParameter $reflectionParameter
70
    ) {
71
        // Set parameter metadata
72 4
        if ($reflectionParameter->isDefaultValueAvailable()) {
73 1
            $parameterDefinition->setValue($reflectionParameter->getDefaultValue());
74
        }
75 4
        if ($reflectionParameter->getType()) {
76 4
            $parameterDefinition->setTypeHint($reflectionParameter->getType());
77
        }
78 4
        $parameterDefinition->setIsOptional($reflectionParameter->isOptional());
79 4
    }
80
81
    /**
82
     * Set dependency value by reflection
83
     *
84
     * @param ParameterDefinition $parameterDefinition
85
     * @param \ReflectionParameter $reflectionParameter
86
     * @throws \InvalidArgumentException
87
     * @throws ReferenceNotImplementsException
88
     */
89 1
    public function setDependencyByReflection(
90
        ParameterDefinition $parameterDefinition,
91
        \ReflectionParameter $reflectionParameter
92
    ) {
93
        // If default value available
94 1
        if ($reflectionParameter->isDefaultValueAvailable()) {
95
            // There is a constant
96 1
            if ($reflectionParameter->isDefaultValueConstant()) {
97
                $parameterDefinition->setDependency(
98
                    new ConstantReference($reflectionParameter->getDefaultValueConstantName())
99
                );
100
            } else { // There is some php types
101 1
                $parameterDefinition->setDependency(
102 1
                    CollectionReference::convertValueToReference($reflectionParameter->getDefaultValue())
103
                );
104
            }
105
            // There is class dependency
106 1
        } elseif ($this->checkIfTypeHingIsClass($parameterDefinition)) {
107 1
            $class = (string)$parameterDefinition->getTypeHint();
108 1
            $parameterDefinition->setDependency(new ClassReference($class));
109
        }
110 1
    }
111
112
    /**
113
     * Check if type hint can be as class reference dependency
114
     *
115
     * @param ParameterDefinition $parameterDefinition
116
     * @return bool
117
     */
118 1
    protected function checkIfTypeHingIsClass(ParameterDefinition $parameterDefinition)
119
    {
120 1
        return is_object($parameterDefinition->getTypeHint()) &&
121 1
            (string)$parameterDefinition->getTypeHint() !== '' &&
122 1
            !$parameterDefinition->getTypeHint()->isBuiltin();
123
    }
124
}
125