Resolver::getReflection()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of slick/di
5
 *
6
 * For the full copyright and license information, please view the LICENSE.md
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Di\Definition\Object;
11
12
use Slick\Di\ContainerAwareMethods;
13
14
/**
15
 * Object definition Resolver
16
 *
17
 * @package Slick\Di\Definition\Object
18
 * @author  Filipe Silva <[email protected]>
19
 */
20
class Resolver implements ResolverInterface
21
{
22
23
    /**
24
     * @var DefinitionData
25
     */
26
    protected $data;
27
28
    /**
29
     * @var object
30
     */
31
    protected $object;
32
33
    /**
34
     * @var \ReflectionClass
35
     */
36
    protected $reflection;
37
38
    /**
39
     * Used to implement the ContainerAwareInterface
40
     */
41
    use ContainerAwareMethods;
42
43
    /**
44
     * Resolves the provided data into and object
45
     *
46
     * @param DefinitionData $data
47
     *
48
     * @return object
49
     *
50
     * @throws \Psr\Container\Exception\ContainerException
51
     * @throws \Psr\Container\Exception\NotFoundException
52
     */
53
    public function resolve(DefinitionData $data)
54
    {
55
        $this->data = $data;
56
57
        $this->object = $this->createObject();
58
59
        foreach ($data->calls() as $call) {
60
            $this->apply($call);
61
        }
62
63
        return $this->object;
64
    }
65
66
    /**
67
     * Creates the object
68
     *
69
     * @return object
70
     *
71
     * @throws \Psr\Container\Exception\ContainerException
72
     * @throws \Psr\Container\Exception\NotFoundException
73
     */
74
    public function createObject()
75
    {
76
        $reflection = new \ReflectionClass($this->data->className());
77
        return $reflection->hasMethod('__construct')
78
            ? $reflection->newInstanceArgs(
79
                $this->filterArguments($this->data->arguments())
80
            )
81
            : $reflection->newInstance();
82
    }
83
84
    /**
85
     * Invoke a method with optional arguments on current object
86
     *
87
     * @param array $call
88
     *
89
     * @return Resolver
90
     *
91
     * @throws \Psr\Container\Exception\ContainerException
92
     * @throws \Psr\Container\Exception\NotFoundException
93
     */
94
    protected function apply($call)
95
    {
96
        if ($call['type'] !== DefinitionData::METHOD) {
97
            return $this->setProperty($call);
98
        }
99
100
        $this->getReflection()
101
            ->getMethod($call['name'])
102
            ->invokeArgs(
103
                $this->object,
104
                $this->filterArguments($call['arguments'])
105
            )
106
        ;
107
        return $this;
108
    }
109
110
    /**
111
     * Assign the call value to a property
112
     *
113
     * @param array $data
114
     *
115
     * @return Resolver
116
     *
117
     * @throws \Psr\Container\Exception\ContainerException
118
     * @throws \Psr\Container\Exception\NotFoundException
119
     */
120
    protected function setProperty($data)
121
    {
122
        $this->getReflection()
123
            ->getProperty($data['name'])
124
            ->setValue(
125
                $this->object,
126
                $this->filterValue($data['arguments'])
127
            )
128
        ;
129
        return $this;
130
    }
131
132
    /**
133
     * Filters all the arguments for aliases
134
     *
135
     * If an argument is prefixed with an '@' its value will be retrieved
136
     * from the container.
137
     *
138
     * @param array $data
139
     *
140
     * @return array
141
     *
142
     * @throws \Psr\Container\Exception\ContainerException
143
     * @throws \Psr\Container\Exception\NotFoundException
144
     */
145
    protected function filterArguments(array $data)
146
    {
147
        $values = [];
148
        foreach ($data as $argument) {
149
            array_push($values, $this->filterValue($argument));
150
        }
151
        return $values;
152
    }
153
154
    /**
155
     * Filters the value for aliases cases
156
     *
157
     * If the value is a string with an '@' prefix the it should try to get
158
     * value from the container
159
     *
160
     * @param string $value
161
     *
162
     * @return mixed
163
     *
164
     * @throws \Psr\Container\Exception\ContainerException
165
     * @throws \Psr\Container\Exception\NotFoundException
166
     */
167
    protected function filterValue($value)
168
    {
169
        if (is_string($value) && strpos($value, '@') !== false) {
170
            $key = substr($value, 1);
171
            return $this->getContainer()->get($key);
172
        }
173
        return $value;
174
    }
175
176
    /**
177
     * Get object reflection class
178
     *
179
     * @return \ReflectionClass
180
     */
181
    protected function getReflection()
182
    {
183
        if (!$this->reflection) {
184
            $this->reflection = new \ReflectionClass($this->object);
185
        }
186
        return $this->reflection;
187
    }
188
}
189