1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @author : Jagepard <[email protected]"> |
5
|
|
|
* @license https://mit-license.org/ MIT |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Rudra\Container; |
9
|
|
|
|
10
|
|
|
use Rudra\Container\Interfaces\ContainerInterface; |
11
|
|
|
|
12
|
|
|
class Objects extends Container |
13
|
|
|
{ |
14
|
|
|
private ContainerInterface $binding; |
15
|
|
|
|
16
|
|
|
public function __construct(ContainerInterface $binding) |
17
|
|
|
{ |
18
|
|
|
$this->binding = $binding; |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
public function set(array $data): void |
22
|
|
|
{ |
23
|
|
|
list($key, $object) = $data; |
24
|
|
|
|
25
|
|
|
if (is_array($object) && array_key_exists(1, $object)) { |
26
|
|
|
("raw" === $object[1]) ? $this->mergeData($key, $object[0]) : $this->iOc($key, $object[0], $object[1]); |
27
|
|
|
return; |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
$this->iOc($key, $object); |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
private function mergeData(string $key, $object) |
34
|
|
|
{ |
35
|
|
|
$this->data = array_merge([$key => $object], $this->data); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
private function iOc(string $key, $object, $params = null): void |
39
|
|
|
{ |
40
|
|
|
$reflection = new \ReflectionClass($object); |
41
|
|
|
$constructor = $reflection->getConstructor(); |
42
|
|
|
|
43
|
|
|
if ($constructor && $constructor->getNumberOfParameters()) { |
44
|
|
|
$paramsIoC = $this->getParamsIoC($constructor, $params); |
45
|
|
|
$this->mergeData($key, $reflection->newInstanceArgs($paramsIoC)); |
46
|
|
|
return; |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
$this->mergeData($key, new $object()); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
private function getParamsIoC(\ReflectionMethod $constructor, $params): array |
53
|
|
|
{ |
54
|
|
|
$i = 0; |
55
|
|
|
$paramsIoC = []; |
56
|
|
|
|
57
|
|
|
foreach ($constructor->getParameters() as $value) { |
58
|
|
|
/* |
59
|
|
|
| If in the constructor expects the implementation of interface, |
60
|
|
|
| so that the container automatically created the necessary object and substituted as an argument, |
61
|
|
|
| we need to bind the interface with the implementation. |
62
|
|
|
*/ |
63
|
|
|
if (isset($value->getClass()->name) && $this->binding->has($value->getClass()->name)) { |
64
|
|
|
$className = $this->binding->get($value->getClass()->name); |
65
|
|
|
$paramsIoC[] = (is_object($className)) ? $className : new $className; |
66
|
|
|
continue; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/* |
70
|
|
|
| If the class constructor contains arguments with default values, |
71
|
|
|
| then if no arguments are passed, |
72
|
|
|
| values will be added by default by container |
73
|
|
|
*/ |
74
|
|
|
if ($value->isDefaultValueAvailable() && !isset($params[$i])) { |
75
|
|
|
$paramsIoC[] = $value->getDefaultValue(); |
76
|
|
|
continue; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
$paramsIoC[] = $params[$i++]; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
return $paramsIoC; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
/* |
86
|
|
|
| Creates an object without adding to the container |
87
|
|
|
*/ |
88
|
|
|
public function new($object, $params = null) |
89
|
|
|
{ |
90
|
|
|
$reflection = new \ReflectionClass($object); |
91
|
|
|
$constructor = $reflection->getConstructor(); |
92
|
|
|
|
93
|
|
|
if ($constructor && $constructor->getNumberOfParameters()) { |
94
|
|
|
$paramsIoC = $this->getParamsIoC($constructor, $params); |
95
|
|
|
|
96
|
|
|
return $reflection->newInstanceArgs($paramsIoC); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
return new $object(); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|