Autowiring::getClassDefinition()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 3 Features 0
Metric Value
c 4
b 3
f 0
dl 0
loc 12
rs 9.4285
cc 3
eloc 7
nc 4
nop 1
1
<?php
2
/**
3
 * This file is part of the Stack package.
4
 *
5
 * (c) Andrzej Kostrzewa <[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 Stack\DI\Definition\Source;
12
13
/**
14
 * Reads DI class definitions using reflection.
15
 *
16
 * @author Andrzej Kostrzewa <[email protected]>
17
 */
18
class Autowiring extends AbstractDefinitionSource
19
{
20
    /**
21
     * {@inheritdoc}
22
     */
23
    public function get($name)
24
    {
25
        if ($this->has($name)) {
26
            return $this->definitions[$name];
27
        }
28
29
        if (!class_exists($name) && !interface_exists($name)) {
30
            return;
31
        }
32
33
        $autowiring = function ($name) {
34
            $class = new \ReflectionClass($name);
35
36
            $constructor = $class->getConstructor();
37
38
            if ($constructor && $constructor->isPublic()) {
39
                $parameters = $this->getParametersDefinition($constructor);
40
                if ($constructor->getNumberOfRequiredParameters() !== count($parameters)) {
41
                    return;
42
                }
43
44
                $object = $class->newInstanceArgs($parameters);
45
                $this->set($name, $object);
46
47
                return $object;
48
            }
49
50
            $object = $class->newInstanceWithoutConstructor();
51
            $this->set($name, $object);
52
53
            return $object;
54
        };
55
56
        return $autowiring($name);
57
    }
58
59
    /**
60
     * Get constructor parameters definitions.
61
     *
62
     * @param \ReflectionFunctionAbstract $constructor
63
     *
64
     * @return array
65
     */
66
    public function getParametersDefinition(\ReflectionFunctionAbstract $constructor)
67
    {
68
        $parameters = [];
69
70
        foreach ($constructor->getParameters() as $index => $parameter) {
71
            if ($parameter->isOptional()) {
72
                continue;
73
            }
74
75
            $parameterClass = $parameter->getClass();
76
            if ($parameterClass) {
77
                $parameters[$index] = $this->getClassDefinition($parameterClass);
78
            }
79
        }
80
81
        return $parameters;
82
    }
83
84
    /**
85
     * Get Class definition for constructor parameter.
86
     *
87
     * @param \ReflectionClass $parameterClass
88
     *
89
     * @return mixed|null|object
90
     */
91
    private function getClassDefinition(\ReflectionClass $parameterClass)
92
    {
93
        $parameterClassName = $parameterClass->getName();
94
        $entryReference     = new \ReflectionClass($parameterClass->getName());
95
        $argumentParams     = false;
96
97
        if ($entryReference->getConstructor()) {
98
            $argumentParams = $entryReference->getConstructor()->getParameters();
99
        }
100
101
        return $argumentParams ? $this->get($parameterClassName) : new $parameterClassName();
102
    }
103
}
104