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