1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Webino™ (http://webino.sk) |
4
|
|
|
* |
5
|
|
|
* @link https://github.com/webino for the canonical source repository |
6
|
|
|
* @copyright Copyright (c) 2015-2017 Webino, s.r.o. (http://webino.sk) |
7
|
|
|
* @author Peter Bačinský <[email protected]> |
8
|
|
|
* @license BSD-3-Clause |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace WebinoAppLib; |
12
|
|
|
|
13
|
|
|
use WebinoAppLib\Application\AbstractBaseApplication; |
14
|
|
|
use WebinoAppLib\Application\Config; |
15
|
|
|
use WebinoAppLib\Application\CoreConfig; |
16
|
|
|
use WebinoAppLib\Exception\DomainException; |
17
|
|
|
use WebinoAppLib\Exception\InvalidArgumentException; |
18
|
|
|
use WebinoAppLib\Service\DebuggerInterface; |
19
|
|
|
use Zend\ServiceManager\ServiceManager; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Class Factory |
23
|
|
|
*/ |
24
|
|
|
final class Factory |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* Application debugger file path |
28
|
|
|
*/ |
29
|
|
|
const DEBUGGER_PATH = 'config/debugger.php'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Application configuration file path |
33
|
|
|
*/ |
34
|
|
|
const CONFIG_PATH = 'config/application.php'; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @param array|object $config |
38
|
|
|
* @param DebuggerInterface $debugger |
39
|
|
|
* @return Application\AbstractBaseApplication |
40
|
|
|
*/ |
41
|
|
|
public function create($config = null, DebuggerInterface $debugger = null) |
42
|
|
|
{ |
43
|
|
|
$_debugger = $this->createDebugger($debugger); |
44
|
|
|
$_config = $this->createConfig($config); |
|
|
|
|
45
|
|
|
|
46
|
|
|
$services = $this->createServices($_config); |
47
|
|
|
$services->setService(Application::DEBUGGER, $_debugger); |
48
|
|
|
|
49
|
|
|
$app = $services->get(Application::SERVICE); |
50
|
|
|
if (!($app instanceof AbstractBaseApplication)) { |
51
|
|
|
throw (new DomainException('Expected application type %s but got %s')) |
52
|
|
|
->format(AbstractBaseApplication::class, get_class($app)); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
return $app; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @param DebuggerInterface $debugger |
60
|
|
|
* @return mixed|DebuggerInterface|\WebinoAppLib\Service\NullDebugger |
61
|
|
|
*/ |
62
|
|
|
private function createDebugger(DebuggerInterface $debugger = null) |
63
|
|
|
{ |
64
|
|
|
if (null !== $debugger) { |
65
|
|
|
return $debugger; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
$filePath = $this::DEBUGGER_PATH; |
69
|
|
|
if (!@stream_resolve_include_path($filePath)) { |
70
|
|
|
return $debugger; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** @noinspection PhpIncludeInspection */ |
74
|
|
|
$created = require $filePath; |
75
|
|
|
if (null === $created) { |
76
|
|
|
return null; |
77
|
|
|
} |
78
|
|
|
if (!($created instanceof DebuggerInterface)) { |
79
|
|
|
throw (new DomainException('Expected type of included debugger is %s but got %s')) |
80
|
|
|
->format(DebuggerInterface::class, get_class($created)); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
return $created; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param array|Config $config |
88
|
|
|
* @return array |
89
|
|
|
*/ |
90
|
|
|
private function normalizeConfig($config) |
91
|
|
|
{ |
92
|
|
|
if (null === $config) { |
93
|
|
|
return []; |
94
|
|
|
} |
95
|
|
|
if (is_array($config)) { |
96
|
|
|
return $config; |
97
|
|
|
} |
98
|
|
|
if (method_exists($config, 'toArray')) { |
99
|
|
|
return $config->toArray(); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
throw (new InvalidArgumentException('Expected config as %s but got %s')) |
103
|
|
|
->format('array or object with toArray() method', $config); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @param array|Config|null $config |
108
|
|
|
* @return Config |
109
|
|
|
* @throws InvalidArgumentException |
110
|
|
|
*/ |
111
|
|
|
private function createConfig($config) |
112
|
|
|
{ |
113
|
|
|
if (null !== $config) { |
114
|
|
|
$normalized = $this->normalizeConfig($config); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$filePath = $this::CONFIG_PATH; |
118
|
|
|
if (@stream_resolve_include_path($filePath)) { |
119
|
|
|
/** @noinspection PhpIncludeInspection */ |
120
|
|
|
$normalized = $this->normalizeConfig(require $filePath); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
if (empty($normalized)) { |
124
|
|
|
$normalized = (new CoreConfig)->toArray(); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return new Config($normalized, true); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @param Config $config |
132
|
|
|
* @return ServiceManager |
133
|
|
|
*/ |
134
|
|
|
private function createServices(Config $config) |
135
|
|
|
{ |
136
|
|
|
/** @var Config $coreConfig */ |
137
|
|
|
$coreConfig = $config->get(CoreConfig::CORE); |
138
|
|
|
if (null === $coreConfig) { |
139
|
|
|
throw (new DomainException('Expected %s node in the application config')) |
140
|
|
|
->format(CoreConfig::CORE); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$servicesConfig = $coreConfig->get(CoreConfig::SERVICES); |
144
|
|
|
if (null === $servicesConfig) { |
145
|
|
|
throw (new DomainException('Expected %s node in the application %s config node')) |
146
|
|
|
->format(CoreConfig::SERVICES, CoreConfig::CORE); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
$services = new ServiceManager; |
150
|
|
|
$this->configureServices($services, $coreConfig); |
151
|
|
|
|
152
|
|
|
$services->setService(Application::CORE_CONFIG, $coreConfig); |
153
|
|
|
$services->setService(Application::CONFIG, $config); |
154
|
|
|
|
155
|
|
|
return $services; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Configure service manager invokables and factories only |
160
|
|
|
* |
161
|
|
|
* @param ServiceManager $services |
162
|
|
|
* @param Config $coreConfig |
163
|
|
|
*/ |
164
|
|
|
private function configureServices(ServiceManager $services, Config $coreConfig) |
165
|
|
|
{ |
166
|
|
|
$config = $coreConfig[CoreConfig::SERVICES]; |
167
|
|
|
|
168
|
|
View Code Duplication |
if (!empty($config[CoreConfig::INVOKABLES])) { |
|
|
|
|
169
|
|
|
foreach ($config[CoreConfig::INVOKABLES] as $name => $service) { |
170
|
|
|
$services->setInvokableClass($name, $service); |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
174
|
|
View Code Duplication |
if (!empty($config[CoreConfig::FACTORIES])) { |
|
|
|
|
175
|
|
|
foreach ($config[CoreConfig::FACTORIES] as $name => $service) { |
176
|
|
|
$services->setFactory($name, $service); |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
if (!empty($config[CoreConfig::INITIALIZERS])) { |
181
|
|
|
foreach ($config[CoreConfig::INITIALIZERS] as $initializer) { |
182
|
|
|
$services->addInitializer($initializer); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.