1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Evgeny Shpilevsky <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace EnliteMonolog\Service; |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
use Closure; |
10
|
|
|
use Exception; |
11
|
|
|
use Interop\Container\ContainerInterface; |
12
|
|
|
use Monolog\Handler\HandlerInterface; |
13
|
|
|
use Monolog\Logger; |
14
|
|
|
use Monolog\Formatter\FormatterInterface; |
15
|
|
|
use RuntimeException; |
16
|
|
|
use Zend\ServiceManager\FactoryInterface; |
17
|
|
|
use Zend\ServiceManager\ServiceLocatorInterface; |
18
|
|
|
|
19
|
|
|
class MonologServiceFactory implements FactoryInterface |
|
|
|
|
20
|
|
|
{ |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
* @throws \Interop\Container\Exception\ContainerException |
25
|
|
|
* @throws \RuntimeException |
26
|
|
|
* @throws \Interop\Container\Exception\NotFoundException |
27
|
|
|
*/ |
28
|
|
|
public function createService(ServiceLocatorInterface $serviceLocator) |
29
|
2 |
|
{ |
30
|
|
|
/** @var MonologOptions $options */ |
31
|
|
|
$options = $serviceLocator->get('EnliteMonologOptions'); |
32
|
2 |
|
return $this->createLogger($serviceLocator, $options); |
33
|
2 |
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* {@inheritdoc} |
37
|
|
|
* @throws \Interop\Container\Exception\NotFoundException |
38
|
|
|
* @throws \RuntimeException |
39
|
|
|
*/ |
40
|
|
|
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) |
41
|
|
|
{ |
42
|
|
|
/** @var MonologOptions $options */ |
43
|
|
|
$options = $container->get('EnliteMonologOptions'); |
44
|
|
|
return $this->createLogger($container, $options); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @param ServiceLocatorInterface|ContainerInterface $container |
49
|
|
|
* @param MonologOptions $options |
50
|
|
|
* @return Logger |
51
|
|
|
* @throws \Interop\Container\Exception\NotFoundException |
52
|
|
|
* @throws \RuntimeException |
53
|
|
|
* @throws \Interop\Container\Exception\ContainerException |
54
|
|
|
*/ |
55
|
|
|
public function createLogger($container, MonologOptions $options) |
56
|
3 |
|
{ |
57
|
|
|
$logger = new Logger($options->getName()); |
58
|
3 |
|
|
59
|
|
|
$handlers = array_reverse($options->getHandlers()); |
60
|
3 |
|
foreach ($handlers as $handler) { |
61
|
3 |
|
$logger->pushHandler($this->createHandler($container, $options, $handler)); |
62
|
2 |
|
} |
63
|
|
|
|
64
|
|
|
foreach ($options->getProcessors() as $processor) { |
65
|
3 |
|
$logger->pushProcessor($this->createProcessor($container, $processor)); |
66
|
1 |
|
} |
67
|
|
|
|
68
|
|
|
return $logger; |
69
|
3 |
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @param ServiceLocatorInterface|ContainerInterface $container |
73
|
|
|
* @param MonologOptions $options |
74
|
|
|
* @param string|array $handler |
75
|
|
|
* @throws \RuntimeException |
76
|
|
|
* @return HandlerInterface |
77
|
|
|
* @throws \Interop\Container\Exception\NotFoundException |
78
|
|
|
* @throws \Interop\Container\Exception\ContainerException |
79
|
|
|
* |
80
|
|
|
*/ |
81
|
|
|
public function createHandler($container, MonologOptions $options, $handler) |
82
|
12 |
|
{ |
83
|
|
|
if (is_string($handler) && $container->has($handler)) { |
84
|
12 |
|
return $container->get($handler); |
85
|
2 |
|
} |
86
|
|
|
|
87
|
11 |
|
|
88
|
1 |
|
if (!isset($handler['name'])) { |
89
|
|
|
throw new RuntimeException('Cannot create logger handler'); |
90
|
|
|
} |
91
|
10 |
|
|
92
|
1 |
|
$handlerClassName = $handler['name']; |
93
|
|
|
|
94
|
|
|
if (!class_exists($handlerClassName)) { |
95
|
9 |
|
throw new RuntimeException('Cannot create logger handler (' . $handlerClassName . ')'); |
96
|
4 |
|
} |
97
|
1 |
|
|
98
|
|
|
$arguments = array_key_exists('args', $handler) ? $handler['args'] : array(); |
99
|
|
|
|
100
|
3 |
|
if (!is_array($arguments)) { |
101
|
|
|
throw new RuntimeException('Arguments of handler(' . $handlerClassName . ') must be array'); |
102
|
3 |
|
} |
103
|
|
|
|
104
|
|
|
if (isset($arguments['handler'])) { |
105
|
|
|
foreach ($options->getHandlers() as $key => $option) { |
106
|
|
|
if ($arguments['handler'] == $key) { |
107
|
|
|
$arguments['handler'] = $this->createHandler($container, $options, $option); |
108
|
|
|
break; |
109
|
|
|
} |
110
|
|
|
} |
111
|
3 |
|
} |
112
|
3 |
|
|
113
|
|
|
try { |
114
|
3 |
|
/** @var HandlerInterface $instance */ |
115
|
|
|
$instance = $this->createInstanceFromArguments($handlerClassName, $arguments); |
116
|
3 |
|
} catch (\InvalidArgumentException $exception) { |
117
|
|
|
throw new RuntimeException(sprintf( |
118
|
|
|
'Handler(%s) has an invalid argument configuration', |
119
|
|
|
$handlerClassName |
120
|
3 |
|
), 0, $exception); |
121
|
3 |
|
} |
122
|
1 |
|
|
123
|
2 |
|
if (isset($handler['formatter'])) { |
124
|
2 |
|
$formatter = $this->createFormatter($container, $handler['formatter']); |
125
|
2 |
|
$instance->setFormatter($formatter); |
126
|
|
|
} |
127
|
2 |
|
|
128
|
|
|
return $instance; |
129
|
3 |
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* @param ServiceLocatorInterface|ContainerInterface $container |
133
|
3 |
|
* @param string|array $formatter |
134
|
|
|
* @return FormatterInterface |
135
|
6 |
|
* @throws \Interop\Container\Exception\NotFoundException |
136
|
|
|
* @throws \Interop\Container\Exception\ContainerException |
137
|
|
|
* @throws RuntimeException |
138
|
6 |
|
*/ |
139
|
|
|
public function createFormatter($container, $formatter) |
140
|
|
|
{ |
141
|
8 |
|
if (is_string($formatter) && $container->has($formatter)) { |
142
|
1 |
|
return $container->get($formatter); |
143
|
1 |
|
} |
144
|
|
|
|
145
|
|
|
if (!isset($formatter['name'])) { |
146
|
8 |
|
throw new RuntimeException('Cannot create logger formatter'); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
$formatterClassName = $formatter['name']; |
150
|
|
|
|
151
|
|
|
if (!class_exists($formatter['name'])) { |
152
|
|
|
throw new RuntimeException('Cannot create logger formatter (' . $formatterClassName . ')'); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$arguments = array_key_exists('args', $formatter) ? $formatter['args'] : array(); |
156
|
|
|
|
157
|
|
|
if (!is_array($arguments)) { |
158
|
7 |
|
throw new RuntimeException('Arguments of formatter(' . $formatterClassName . ') must be array'); |
159
|
|
|
} |
160
|
7 |
|
|
161
|
1 |
|
try { |
162
|
|
|
/** @var FormatterInterface $instance */ |
163
|
6 |
|
$instance = $this->createInstanceFromArguments($formatterClassName, $arguments); |
164
|
1 |
|
} catch (\InvalidArgumentException $exception) { |
165
|
|
|
throw new RuntimeException(sprintf( |
166
|
|
|
'Formatter(%s) has an invalid argument configuration', |
167
|
5 |
|
$formatterClassName |
168
|
1 |
|
), 0, $exception); |
169
|
|
|
} |
170
|
|
|
|
171
|
4 |
|
return $instance; |
172
|
2 |
|
} |
173
|
1 |
|
|
174
|
|
|
/** |
175
|
|
|
* @param ServiceLocatorInterface|ContainerInterface $container |
176
|
1 |
|
* @param $processor |
177
|
|
|
* @return Closure |
178
|
1 |
|
* @throws \Interop\Container\Exception\NotFoundException |
179
|
|
|
* @throws \Interop\Container\Exception\ContainerException |
180
|
|
|
* @throws RuntimeException |
181
|
2 |
|
*/ |
182
|
|
|
public function createProcessor($container, $processor) |
183
|
2 |
|
{ |
184
|
|
|
if ($processor instanceof Closure) { |
185
|
|
|
return $processor; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
if (is_string($processor)) { |
189
|
|
|
try { |
190
|
|
|
$instance = $container->get($processor); |
191
|
|
|
} catch (Exception $ex) { |
192
|
|
|
$instance = null; |
193
|
|
|
} |
194
|
|
|
|
195
|
5 |
|
if ($instance && is_callable($instance)) { |
196
|
|
|
return $instance; |
197
|
5 |
|
} |
198
|
1 |
|
|
199
|
|
|
$processor = new $processor(); |
200
|
|
|
|
201
|
4 |
|
if (is_callable($processor)) { |
202
|
|
|
return $processor; |
203
|
4 |
|
} |
204
|
3 |
|
} |
205
|
3 |
|
|
206
|
|
|
throw new RuntimeException('Unknown processor type, must be a Closure or the FQCN of an invokable class'); |
207
|
|
|
} |
208
|
4 |
|
|
209
|
1 |
|
/** |
210
|
|
|
* Handles the constructor arguments and if they're named, just sort them to fit constructor ordering. |
211
|
|
|
* |
212
|
3 |
|
* @param string $className |
213
|
|
|
* @param array $arguments |
214
|
3 |
|
* |
215
|
2 |
|
* @return object |
216
|
|
|
* @throws \InvalidArgumentException If given arguments are not valid for provided className constructor. |
217
|
|
|
*/ |
218
|
|
|
private function createInstanceFromArguments($className, array $arguments) |
219
|
1 |
|
{ |
220
|
|
|
$reflection = new \ReflectionClass($className); |
221
|
|
|
$constructor = $reflection->getConstructor(); |
222
|
|
|
|
223
|
|
|
// There is no or at least a non-accessible constructor for provided class name, |
224
|
|
|
// therefore there is no need to handle arguments anyway |
225
|
|
|
if ($constructor === null) { |
226
|
|
|
return $reflection->newInstanceArgs($arguments); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
if (!$constructor->isPublic()) { |
230
|
|
|
throw new \InvalidArgumentException(sprintf( |
231
|
|
|
'%s::__construct is not accessible', |
232
|
|
|
$className |
233
|
|
|
)); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
$requiredArgsCount = $constructor->getNumberOfRequiredParameters(); |
237
|
|
|
$argumentCount = count($arguments); |
238
|
|
|
|
239
|
|
|
if ($requiredArgsCount > $argumentCount) { |
240
|
|
|
throw new \InvalidArgumentException(sprintf( |
241
|
|
|
'%s::__construct() requires at least %d arguments; %d given', |
242
|
|
|
$className, |
243
|
|
|
$requiredArgsCount, |
244
|
|
|
$argumentCount |
245
|
|
|
)); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
// Arguments supposed to be ordered |
249
|
|
|
if (isset($arguments[0])) { |
250
|
|
|
return $reflection->newInstanceArgs($arguments); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
$parameters = array(); |
254
|
|
|
|
255
|
|
|
foreach($constructor->getParameters() as $parameter) { |
256
|
|
|
$parameterName = $parameter->getName(); |
257
|
|
|
|
258
|
|
|
if (array_key_exists($parameterName, $arguments)) { |
259
|
|
|
$parameters[$parameter->getPosition()] = $arguments[$parameterName]; |
260
|
|
|
continue; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
if (!$parameter->isOptional()) { |
264
|
|
|
throw new \InvalidArgumentException(sprintf( |
265
|
|
|
'Missing at least one required parameters `%s`', |
266
|
|
|
$parameterName |
267
|
|
|
)); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
$parameters[$parameter->getPosition()] = $parameter->getDefaultValue(); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
return $reflection->newInstanceArgs($parameters); |
274
|
|
|
} |
275
|
|
|
} |
276
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.