1
|
|
|
<?php namespace Understand\UnderstandLaravel5; |
2
|
|
|
|
3
|
|
|
use Illuminate\Support\ServiceProvider; |
4
|
|
|
use Illuminate\Foundation\AliasLoader; |
5
|
|
|
use Illuminate\Support\Str; |
6
|
|
|
use Illuminate\Foundation\Application; |
7
|
|
|
use Illuminate\Database\Eloquent\Model as EloquentModel; |
8
|
|
|
|
9
|
|
|
class UnderstandLaravel5ServiceProvider extends ServiceProvider |
10
|
|
|
{ |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Indicates if loading of the provider is deferred. |
14
|
|
|
* |
15
|
|
|
* @var bool |
16
|
|
|
*/ |
17
|
|
|
protected $defer = false; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Bootstrap the application events. |
21
|
|
|
* |
22
|
|
|
* @return void |
23
|
|
|
*/ |
24
|
|
|
public function boot() |
25
|
|
|
{ |
26
|
|
|
$configPath = __DIR__ . '/../../config/understand-laravel.php'; |
27
|
|
|
$this->publishes([$configPath => config_path('understand-laravel.php')], 'config'); |
28
|
|
|
|
29
|
|
|
if ($this->app['config']->get('understand-laravel.log_types.eloquent_log.enabled')) |
30
|
|
|
{ |
31
|
|
|
$this->listenEloquentEvents(); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
if ($this->app['config']->get('understand-laravel.log_types.laravel_log.enabled')) |
35
|
|
|
{ |
36
|
|
|
$this->listenLaravelEvents(); |
37
|
|
|
} |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Register the service provider. |
42
|
|
|
* |
43
|
|
|
* @return void |
44
|
|
|
*/ |
45
|
|
|
public function register() |
46
|
|
|
{ |
47
|
|
|
$this->registerConfig(); |
48
|
|
|
$this->registerFieldProvider(); |
49
|
|
|
$this->registerTokenProvider(); |
50
|
|
|
$this->registerLogger(); |
51
|
|
|
$this->registerModelEventListenerProvider(); |
52
|
|
|
$this->registerExceptionEncoder(); |
53
|
|
|
$this->registerExceptionLogger(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Register config |
58
|
|
|
* |
59
|
|
|
* @return void |
60
|
|
|
*/ |
61
|
|
|
protected function registerConfig() |
62
|
|
|
{ |
63
|
|
|
$configPath = __DIR__ . '/../../config/understand-laravel.php'; |
64
|
|
|
$this->mergeConfigFrom($configPath, 'understand-laravel'); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Register field provider |
69
|
|
|
* |
70
|
|
|
* @return void |
71
|
|
|
*/ |
72
|
|
|
protected function registerFieldProvider() |
73
|
|
|
{ |
74
|
|
|
$this->app->bind('understand.field-provider', function($app) |
75
|
|
|
{ |
76
|
|
|
$fieldProvider = new FieldProvider(); |
77
|
|
|
|
78
|
|
|
if ($app['config']['session.driver']) |
79
|
|
|
{ |
80
|
|
|
$fieldProvider->setSessionStore($app['session.store']); |
81
|
|
|
} |
82
|
|
|
$fieldProvider->setRouter($app['router']); |
83
|
|
|
$fieldProvider->setRequest($app['request']); |
84
|
|
|
$fieldProvider->setEnvironment($app->environment()); |
85
|
|
|
$fieldProvider->setTokenProvider($app['understand.token-provider']); |
86
|
|
|
|
87
|
|
|
return $fieldProvider; |
88
|
|
|
}); |
89
|
|
|
|
90
|
|
|
$this->app->booting(function() |
91
|
|
|
{ |
92
|
|
|
$loader = AliasLoader::getInstance(); |
93
|
|
|
$loader->alias('UnderstandFieldProvider', 'Understand\UnderstandLaravel5\Facades\UnderstandFieldProvider'); |
94
|
|
|
}); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Register token generator class |
99
|
|
|
* |
100
|
|
|
* @return void |
101
|
|
|
*/ |
102
|
|
|
protected function registerTokenProvider() |
103
|
|
|
{ |
104
|
|
|
$this->app->singleton('understand.token-provider', function() |
105
|
|
|
{ |
106
|
|
|
return new TokenProvider(); |
107
|
|
|
}); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Register exception encoder |
112
|
|
|
* |
113
|
|
|
* @return void |
114
|
|
|
*/ |
115
|
|
|
protected function registerExceptionEncoder() |
116
|
|
|
{ |
117
|
|
|
$this->app->bind('understand.exception-encoder', function() |
118
|
|
|
{ |
119
|
|
|
return new ExceptionEncoder; |
120
|
|
|
}); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Register exception logger |
125
|
|
|
* |
126
|
|
|
* @return void |
127
|
|
|
*/ |
128
|
|
|
protected function registerExceptionLogger() |
129
|
|
|
{ |
130
|
|
|
$this->app->bind('understand.exceptionLogger', function($app) |
131
|
|
|
{ |
132
|
|
|
$logger = $app['understand.logger']; |
133
|
|
|
$encoder = $app['understand.exception-encoder']; |
134
|
|
|
|
135
|
|
|
return new ExceptionLogger($logger, $encoder, $app['config']); |
136
|
|
|
}); |
137
|
|
|
|
138
|
|
|
$this->app->booting(function() |
139
|
|
|
{ |
140
|
|
|
$loader = AliasLoader::getInstance(); |
141
|
|
|
$loader->alias('UnderstandExceptionLogger', 'Understand\UnderstandLaravel5\Facades\UnderstandExceptionLogger'); |
142
|
|
|
}); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Register understand logger |
147
|
|
|
* |
148
|
|
|
* @return void |
149
|
|
|
*/ |
150
|
|
|
protected function registerLogger() |
151
|
|
|
{ |
152
|
|
|
$this->app->singleton('understand.logger', function($app) |
153
|
|
|
{ |
154
|
|
|
$fieldProvider = $app['understand.field-provider']; |
155
|
|
|
$handler = $this->resolveHandler($app); |
156
|
|
|
$silent = $app['config']->get('understand-laravel.silent'); |
157
|
|
|
|
158
|
|
|
return new Logger($fieldProvider, $handler, $silent); |
159
|
|
|
}); |
160
|
|
|
|
161
|
|
|
$this->app->booting(function() |
162
|
|
|
{ |
163
|
|
|
$loader = AliasLoader::getInstance(); |
164
|
|
|
$loader->alias('UnderstandLogger', 'Understand\UnderstandLaravel5\Facades\UnderstandLogger'); |
165
|
|
|
}); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* Return default handler |
170
|
|
|
* |
171
|
|
|
* @param type $app |
172
|
|
|
* @return mixed |
173
|
|
|
* @throws \ErrorException |
174
|
|
|
*/ |
175
|
|
|
protected function resolveHandler($app) |
176
|
|
|
{ |
177
|
|
|
$inputToken = $app['config']->get('understand-laravel.token'); |
178
|
|
|
|
179
|
|
|
$apiUrl = $app['config']->get('understand-laravel.url', 'https://api.understand.io'); |
180
|
|
|
$silent = $app['config']->get('understand-laravel.silent'); |
181
|
|
|
$handlerType = $app['config']->get('understand-laravel.handler'); |
182
|
|
|
$sslBundlePath = $app['config']->get('understand-laravel.ssl_ca_bundle'); |
183
|
|
|
|
184
|
|
|
if ($handlerType == 'async') |
185
|
|
|
{ |
186
|
|
|
return new Handlers\AsyncHandler($inputToken, $apiUrl, $silent, $sslBundlePath); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
if ($handlerType == 'sync') |
190
|
|
|
{ |
191
|
|
|
return new Handlers\SyncHandler($inputToken, $apiUrl, $silent, $sslBundlePath); |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
if ($handlerType == 'queue') |
195
|
|
|
{ |
196
|
|
|
return new Handlers\LaravelQueueHandler($inputToken, $apiUrl, $silent, $sslBundlePath); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
throw new \ErrorException('understand-laravel handler misconfiguration:' . $handlerType); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Register model event listener provider |
204
|
|
|
* |
205
|
|
|
* @return void |
206
|
|
|
*/ |
207
|
|
|
protected function registerModelEventListenerProvider() |
208
|
|
|
{ |
209
|
|
|
$this->app->bind('understand.model-event-listener-provider', function($app) |
210
|
|
|
{ |
211
|
|
|
$logger = $app['understand.logger']; |
212
|
|
|
$additional = $app['config']->get('understand-laravel.additional.model_log', []); |
213
|
|
|
|
214
|
|
|
return new ModelEventListener($logger, $additional); |
215
|
|
|
}); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Detect Laravel version |
220
|
|
|
* |
221
|
|
|
* @param array $versions |
222
|
|
|
* @return type |
223
|
|
|
*/ |
224
|
|
|
protected function detectLaravelVersion(array $versions) |
225
|
|
|
{ |
226
|
|
|
return Str::startsWith(Application::VERSION, $versions); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Listen Laravel logs |
231
|
|
|
* |
232
|
|
|
* @return void |
233
|
|
|
*/ |
234
|
|
|
protected function listenLaravelEvents() |
235
|
|
|
{ |
236
|
|
|
// only Laravel versions below L5.4 supports `illuminate.log` |
237
|
|
|
if ($this->detectLaravelVersion(['5.0', '5.1', '5.2', '5.3'])) |
238
|
|
|
{ |
239
|
|
|
$this->app['events']->listen('illuminate.log', function($level, $message, $context) |
240
|
|
|
{ |
241
|
|
|
$this->handleEvent($level, $message, $context); |
242
|
|
|
}); |
243
|
|
|
} |
244
|
|
|
else |
245
|
|
|
{ |
246
|
|
|
// starting from L5.4 MessageLogged event class was introduced |
247
|
|
|
// https://github.com/laravel/framework/commit/57c82d095c356a0fe0f9381536afec768cdcc072 |
248
|
|
|
$this->app['events']->listen('Illuminate\Log\Events\MessageLogged', function($log) |
249
|
|
|
{ |
250
|
|
|
|
251
|
|
|
$this->handleEvent($log->level, $log->message, $log->context); |
252
|
|
|
}); |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Handle a new log event |
258
|
|
|
* |
259
|
|
|
* @param string $level |
260
|
|
|
* @param mixed $message |
261
|
|
|
* @param array $context |
262
|
|
|
* @return void |
263
|
|
|
*/ |
264
|
|
|
protected function handleEvent($level, $message, $context) |
265
|
|
|
{ |
266
|
|
|
$log = []; |
267
|
|
|
|
268
|
|
|
if ($message instanceof Exceptions\HandlerException) |
269
|
|
|
{ |
270
|
|
|
return; |
271
|
|
|
} |
272
|
|
|
else if ($message instanceof \Exception) |
273
|
|
|
{ |
274
|
|
|
$log = $this->app['understand.exception-encoder']->exceptionToArray($message); |
275
|
|
|
$log['tags'] = ['exception_log']; |
276
|
|
|
} |
277
|
|
|
// // integer, float, string or boolean as message |
278
|
|
|
else if (is_scalar($message)) |
279
|
|
|
{ |
280
|
|
|
$log['message'] = $message; |
281
|
|
|
$log['tags'] = ['laravel_log']; |
282
|
|
|
} |
283
|
|
|
else |
284
|
|
|
{ |
285
|
|
|
$log = (array)$message; |
286
|
|
|
$log['tags'] = ['laravel_log']; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
if ($context) |
|
|
|
|
290
|
|
|
{ |
291
|
|
|
$log['context'] = $context; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
$log['level'] = $level; |
295
|
|
|
|
296
|
|
|
$additional = $this->app['config']->get('understand-laravel.log_types.laravel_log.meta', []); |
297
|
|
|
$this->app['understand.logger']->log($log, $additional); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Listen eloquent model events and log them |
302
|
|
|
* |
303
|
|
|
* @return void |
304
|
|
|
*/ |
305
|
|
|
protected function listenEloquentEvents() |
306
|
|
|
{ |
307
|
|
|
$modelLogger = $this->app['understand.model-event-listener-provider']; |
308
|
|
|
|
309
|
|
|
$events = [ |
310
|
|
|
'eloquent.created*' => 'created', |
311
|
|
|
'eloquent.updated*' => 'updated', |
312
|
|
|
'eloquent.deleted*' => 'deleted', |
313
|
|
|
'eloquent.restored*' => 'restored', |
314
|
|
|
]; |
315
|
|
|
|
316
|
|
|
foreach ($events as $listenerName => $eventName) |
317
|
|
|
{ |
318
|
|
|
if ($this->detectLaravelVersion(['5.0', '5.1', '5.2', '5.3'])) |
319
|
|
|
{ |
320
|
|
|
$this->app['events']->listen($listenerName, function($model) use($modelLogger, $eventName) |
321
|
|
|
{ |
322
|
|
|
$modelLevelEventName = 'eloquent.' . $eventName . ': ' . get_class($model); |
323
|
|
|
|
324
|
|
|
$modelLogger->logModelEvent($eventName, $model, $modelLevelEventName); |
325
|
|
|
}); |
326
|
|
|
} |
327
|
|
|
else |
328
|
|
|
{ |
329
|
|
|
$this->app['events']->listen($listenerName, function($modelLevelEventName, $eventPayload) use($modelLogger, $eventName) |
330
|
|
|
{ |
331
|
|
|
if (isset($eventPayload[0]) && $eventPayload[0] instanceof EloquentModel) |
332
|
|
|
{ |
333
|
|
|
$modelLogger->logModelEvent($eventName, $eventPayload[0], $modelLevelEventName); |
334
|
|
|
} |
335
|
|
|
}); |
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
/** |
341
|
|
|
* Get the services provided by the provider. |
342
|
|
|
* |
343
|
|
|
* @return array |
344
|
|
|
*/ |
345
|
|
|
public function provides() |
346
|
|
|
{ |
347
|
|
|
return [ |
348
|
|
|
'understand.field-provider', |
349
|
|
|
'understand.logger', |
350
|
|
|
'understand.model-event-listener-provider', |
351
|
|
|
'understand.exception-encoder', |
352
|
|
|
'understand.exceptionLogger' |
353
|
|
|
]; |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.