This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 Blade; |
||
8 | use Exception; |
||
9 | use Throwable; |
||
10 | use Understand\UnderstandLaravel5\Facades\UnderstandJsProvider; |
||
11 | |||
12 | class UnderstandLaravel5ServiceProvider extends ServiceProvider |
||
13 | { |
||
14 | |||
15 | /** |
||
16 | * Indicates if loading of the provider is deferred. |
||
17 | * |
||
18 | * @var bool |
||
19 | */ |
||
20 | protected $defer = false; |
||
21 | |||
22 | /** |
||
23 | * Bootstrap the application events. |
||
24 | * |
||
25 | * @return void |
||
26 | */ |
||
27 | public function boot() |
||
28 | { |
||
29 | $configPath = __DIR__ . '/../../config/understand-laravel.php'; |
||
30 | $this->publishes([$configPath => config_path('understand-laravel.php')], 'config'); |
||
31 | $enabled = $this->app['config']->get('understand-laravel.enabled'); |
||
32 | |||
33 | if ($enabled) |
||
34 | { |
||
35 | $this->listenLaravelEvents(); |
||
36 | } |
||
37 | |||
38 | if ($enabled && $this->app['config']->get('understand-laravel.sql_enabled')) |
||
39 | { |
||
40 | $this->listenQueryEvents(); |
||
41 | } |
||
42 | |||
43 | $this->registerBladeDirectives(); |
||
44 | } |
||
45 | |||
46 | /** |
||
47 | * Register Blade directives. |
||
48 | * |
||
49 | * @return void |
||
50 | */ |
||
51 | protected function registerBladeDirectives() |
||
52 | { |
||
53 | // L5.0 does not support custom directives |
||
54 | if ($this->detectLaravelVersion(['5.0'])) |
||
55 | { |
||
56 | Blade::extend(function ($view, $compiler) |
||
57 | { |
||
58 | $configuration = UnderstandJsProvider::getJsConfig(); |
||
59 | |||
60 | $pattern = $compiler->createMatcher('understandJsConfig'); |
||
61 | |||
62 | return preg_replace($pattern, json_encode($configuration), $view); |
||
63 | }); |
||
64 | |||
65 | Blade::extend(function ($view, $compiler) |
||
66 | { |
||
67 | $configuration = UnderstandJsProvider::getJsConfig(); |
||
68 | |||
69 | $pattern = $compiler->createMatcher('understandJs'); |
||
70 | |||
71 | $out = "<script src=\"" . UnderstandJsProvider::getJsBundleUrl() . "\"></script>\r\n"; |
||
72 | $out .= "<script>\r\n"; |
||
73 | $out .= "Understand.init(" . json_encode($configuration) . ");\r\n"; |
||
74 | $out .= "Understand.catchErrors();\r\n"; |
||
75 | $out .= "</script>"; |
||
76 | |||
77 | return preg_replace($pattern, $out, $view); |
||
78 | }); |
||
79 | } |
||
80 | else |
||
81 | { |
||
82 | Blade::directive('understandJsConfig', function () |
||
83 | { |
||
84 | $configuration = UnderstandJsProvider::getJsConfig(); |
||
85 | |||
86 | return json_encode($configuration); |
||
87 | }); |
||
88 | |||
89 | Blade::directive('understandJs', function () |
||
90 | { |
||
91 | $configuration = UnderstandJsProvider::getJsConfig(); |
||
92 | |||
93 | $out = "<script src=\"" . UnderstandJsProvider::getJsBundleUrl() . "\"></script>\r\n"; |
||
94 | $out .= "<script>\r\n"; |
||
95 | $out .= "Understand.init(" . json_encode($configuration) . ");\r\n"; |
||
96 | $out .= "Understand.catchErrors();\r\n"; |
||
97 | $out .= "</script>"; |
||
98 | |||
99 | return $out; |
||
100 | }); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | /** |
||
105 | * Register the service provider. |
||
106 | * |
||
107 | * @return void |
||
108 | */ |
||
109 | public function register() |
||
110 | { |
||
111 | $this->registerConfig(); |
||
112 | $this->registerFieldProvider(); |
||
113 | $this->registerJsProvider(); |
||
114 | $this->registerDataCollector(); |
||
115 | $this->registerTokenProvider(); |
||
116 | $this->registerLogger(); |
||
117 | $this->registerExceptionEncoder(); |
||
118 | $this->registerEventLoggers(); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Register config |
||
123 | * |
||
124 | * @return void |
||
125 | */ |
||
126 | protected function registerConfig() |
||
127 | { |
||
128 | $configPath = __DIR__ . '/../../config/understand-laravel.php'; |
||
129 | $this->mergeConfigFrom($configPath, 'understand-laravel'); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Register field provider |
||
134 | * |
||
135 | * @return void |
||
136 | */ |
||
137 | protected function registerFieldProvider() |
||
138 | { |
||
139 | $this->app->bind('understand.fieldProvider', function($app) |
||
140 | { |
||
141 | $fieldProvider = new FieldProvider(); |
||
142 | |||
143 | if ($app['config']['session.driver']) |
||
144 | { |
||
145 | $fieldProvider->setSessionStore($app['session.store']); |
||
146 | } |
||
147 | |||
148 | $fieldProvider->setRouter($app['router']); |
||
149 | $fieldProvider->setRequest($app['request']); |
||
150 | $fieldProvider->setEnvironment($app->environment()); |
||
151 | $fieldProvider->setTokenProvider($app['understand.tokenProvider']); |
||
152 | $fieldProvider->setDataCollector($app['understand.dataCollector']); |
||
153 | $fieldProvider->setApp($app); |
||
154 | |||
155 | return $fieldProvider; |
||
156 | }); |
||
157 | |||
158 | $this->app->booting(function() |
||
159 | { |
||
160 | $loader = AliasLoader::getInstance(); |
||
161 | $loader->alias('UnderstandFieldProvider', 'Understand\UnderstandLaravel5\Facades\UnderstandFieldProvider'); |
||
162 | }); |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * Register JS provider |
||
167 | * |
||
168 | * @return void |
||
169 | */ |
||
170 | protected function registerJsProvider() |
||
171 | { |
||
172 | $this->app->bind('understand.jsProvider', function($app) |
||
173 | { |
||
174 | return new JsProvider($app); |
||
175 | }); |
||
176 | |||
177 | $this->app->booting(function() |
||
178 | { |
||
179 | $loader = AliasLoader::getInstance(); |
||
180 | $loader->alias('UnderstandJsProvider', 'Understand\UnderstandLaravel5\Facades\UnderstandJsProvider'); |
||
181 | }); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Register token generator class |
||
186 | * |
||
187 | * @return void |
||
188 | */ |
||
189 | protected function registerTokenProvider() |
||
190 | { |
||
191 | $this->app->singleton('understand.tokenProvider', function() |
||
192 | { |
||
193 | return new TokenProvider(); |
||
194 | }); |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Register data collector class |
||
199 | * |
||
200 | * @return void |
||
201 | */ |
||
202 | protected function registerDataCollector() |
||
203 | { |
||
204 | $this->app->singleton('understand.dataCollector', function() |
||
205 | { |
||
206 | return new DataCollector(); |
||
207 | }); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Register exception encoder |
||
212 | * |
||
213 | * @return void |
||
214 | */ |
||
215 | protected function registerExceptionEncoder() |
||
216 | { |
||
217 | $this->app->bind('understand.exceptionEncoder', function() |
||
218 | { |
||
219 | return new ExceptionEncoder; |
||
220 | }); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Register exception and event logger |
||
225 | * |
||
226 | * @return void |
||
227 | */ |
||
228 | protected function registerEventLoggers() |
||
229 | { |
||
230 | $this->app->bind('understand.eventLogger', function($app) |
||
231 | { |
||
232 | return new EventLogger($app['understand.logger'], $app['config']); |
||
233 | }); |
||
234 | |||
235 | $this->app->bind('understand.exceptionLogger', function($app) |
||
236 | { |
||
237 | return new ExceptionLogger($app['understand.logger'], $app['understand.exceptionEncoder'], $app['config']); |
||
238 | }); |
||
239 | |||
240 | $this->app->booting(function() |
||
241 | { |
||
242 | $loader = AliasLoader::getInstance(); |
||
243 | $loader->alias('UnderstandExceptionLogger', 'Understand\UnderstandLaravel5\Facades\UnderstandExceptionLogger'); |
||
244 | }); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Register understand logger |
||
249 | * |
||
250 | * @return void |
||
251 | */ |
||
252 | protected function registerLogger() |
||
253 | { |
||
254 | $this->app->singleton('understand.logger', function($app) |
||
255 | { |
||
256 | $fieldProvider = $app['understand.fieldProvider']; |
||
257 | $handler = $this->resolveHandler($app); |
||
258 | |||
259 | return new Logger($fieldProvider, $handler); |
||
260 | }); |
||
261 | |||
262 | $this->app->booting(function() |
||
263 | { |
||
264 | $loader = AliasLoader::getInstance(); |
||
265 | $loader->alias('UnderstandLogger', 'Understand\UnderstandLaravel5\Facades\UnderstandLogger'); |
||
266 | }); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Return default handler |
||
271 | * |
||
272 | * @param type $app |
||
273 | * @return mixed |
||
274 | * @throws \ErrorException |
||
275 | */ |
||
276 | protected function resolveHandler($app) |
||
277 | { |
||
278 | $inputToken = $app['config']->get('understand-laravel.token'); |
||
279 | |||
280 | $apiUrl = $app['config']->get('understand-laravel.url', 'https://api.understand.io'); |
||
281 | $handlerType = $app['config']->get('understand-laravel.handler'); |
||
282 | $sslBundlePath = $app['config']->get('understand-laravel.ssl_ca_bundle'); |
||
283 | |||
284 | if ($handlerType == 'async') |
||
285 | { |
||
286 | return new Handlers\AsyncHandler($inputToken, $apiUrl, $sslBundlePath); |
||
287 | } |
||
288 | |||
289 | if ($handlerType == 'sync') |
||
290 | { |
||
291 | return new Handlers\SyncHandler($inputToken, $apiUrl, $sslBundlePath); |
||
292 | } |
||
293 | |||
294 | throw new \ErrorException('understand-laravel handler misconfiguration:' . $handlerType); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Detect Laravel version |
||
299 | * |
||
300 | * @param array $versions |
||
301 | * @return type |
||
302 | */ |
||
303 | protected function detectLaravelVersion(array $versions) |
||
304 | { |
||
305 | return Str::startsWith(Application::VERSION, $versions); |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Listen Laravel logs and queue events |
||
310 | * |
||
311 | * @return void |
||
312 | */ |
||
313 | protected function listenLaravelEvents() |
||
314 | { |
||
315 | // only Laravel versions below L5.4 supports `illuminate.log` |
||
316 | if ($this->detectLaravelVersion(['5.0', '5.1', '5.2', '5.3'])) |
||
317 | { |
||
318 | $this->app['events']->listen('illuminate.log', function($level, $message, $context) |
||
319 | { |
||
320 | $this->handleEvent($level, $message, $context); |
||
321 | }); |
||
322 | } |
||
323 | else |
||
324 | { |
||
325 | // starting from L5.4 MessageLogged event class was introduced |
||
326 | // https://github.com/laravel/framework/commit/57c82d095c356a0fe0f9381536afec768cdcc072 |
||
327 | $this->app['events']->listen('Illuminate\Log\Events\MessageLogged', function($log) |
||
328 | { |
||
329 | |||
330 | $this->handleEvent($log->level, $log->message, $log->context); |
||
331 | }); |
||
332 | } |
||
333 | |||
334 | // starting from L5.2 JobProcessing event class was introduced |
||
335 | // https://github.com/illuminate/queue/commit/ce2b5518902b1bcb9ef650c41900fc8c6392eb0c |
||
336 | if ($this->app->runningInConsole()) |
||
337 | { |
||
338 | if ($this->detectLaravelVersion(['5.0', '5.1'])) |
||
339 | { |
||
340 | $this->app['events']->listen('illuminate.queue.after', function() |
||
341 | { |
||
342 | $this->app['understand.tokenProvider']->generate(); |
||
343 | $this->app['understand.dataCollector']->reset(); |
||
344 | }); |
||
345 | |||
346 | $this->app['events']->listen('illuminate.queue.failed', function() |
||
347 | { |
||
348 | $this->app['understand.tokenProvider']->generate(); |
||
349 | $this->app['understand.dataCollector']->reset(); |
||
350 | }); |
||
351 | } |
||
352 | else |
||
353 | { |
||
354 | $this->app['events']->listen('Illuminate\Queue\Events\JobProcessing', function() |
||
355 | { |
||
356 | $this->app['understand.tokenProvider']->generate(); |
||
357 | $this->app['understand.dataCollector']->reset(); |
||
358 | }); |
||
359 | } |
||
360 | } |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Listen Query events |
||
365 | * |
||
366 | * @return void |
||
367 | */ |
||
368 | protected function listenQueryEvents() |
||
369 | { |
||
370 | // only Laravel versions below L5.2 supports `illuminate.query` |
||
371 | if ($this->detectLaravelVersion(['5.0', '5.1'])) |
||
372 | { |
||
373 | // $this->events->fire('illuminate.query', [$query, $bindings, $time, $this->getName()]); |
||
374 | View Code Duplication | $this->app['events']->listen('illuminate.query', function($query, $bindings, $time) |
|
0 ignored issues
–
show
|
|||
375 | { |
||
376 | $this->app['understand.dataCollector']->setInArray('sql_queries', [ |
||
377 | 'query' => $query, |
||
378 | 'bindings' => $bindings, |
||
379 | 'time' => $time, |
||
380 | ]); |
||
381 | }); |
||
382 | } |
||
383 | else |
||
384 | { |
||
385 | // https://laravel.com/api/5.3/Illuminate/Database/Events/QueryExecuted.html |
||
386 | View Code Duplication | $this->app['events']->listen('Illuminate\Database\Events\QueryExecuted', function($event) |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
387 | { |
||
388 | $this->app['understand.dataCollector']->setInArray('sql_queries', [ |
||
389 | 'query' => $event->sql, |
||
390 | 'bindings' => $event->bindings, |
||
391 | 'time' => $event->time, |
||
392 | ]); |
||
393 | }); |
||
394 | } |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * Handle a new log event |
||
399 | * |
||
400 | * @param string $level |
||
401 | * @param mixed $message |
||
402 | * @param array $context |
||
403 | * @return void |
||
404 | */ |
||
405 | protected function handleEvent($level, $message, $context) |
||
406 | { |
||
407 | if ($this->shouldIgnoreEvent($level, $message, $context)) |
||
408 | { |
||
409 | return; |
||
410 | } |
||
411 | |||
412 | // `\Log::info`, `\Log::debug` and NOT `\Exception` or `\Throwable` |
||
413 | if (in_array($level, ['info', 'debug']) && ! ($message instanceof Exception || $message instanceof Throwable)) |
||
0 ignored issues
–
show
|
|||
414 | { |
||
415 | $this->app['understand.eventLogger']->logEvent($level, $message, $context); |
||
416 | } |
||
417 | // `\Log::notice`, `\Log::warning`, `\Log::error`, `\Log::critical`, `\Log::alert`, `\Log::emergency` and `\Exception`, `\Throwable` |
||
418 | // '5.5', '5.6', '5.7', '5.8' |
||
419 | else if ( ! $this->detectLaravelVersion(['5.0', '5.1', '5.2', '5.3', '5.4']) && isset($context['exception']) && ($context['exception'] instanceof Exception || $context['exception'] instanceof Throwable)) |
||
0 ignored issues
–
show
|
|||
420 | { |
||
421 | $exception = $context['exception']; |
||
422 | unset($context['exception']); |
||
423 | |||
424 | $this->app['understand.exceptionLogger']->logError($level, $exception, $context); |
||
425 | } |
||
426 | else |
||
427 | { |
||
428 | $this->app['understand.exceptionLogger']->logError($level, $message, $context); |
||
429 | } |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * @param $level |
||
434 | * @param $message |
||
435 | * @param $context |
||
436 | * @return bool |
||
437 | */ |
||
438 | protected function shouldIgnoreEvent($level, $message, $context) |
||
0 ignored issues
–
show
|
|||
439 | { |
||
440 | $ignoredEventTypes = (array)$this->app['config']->get('understand-laravel.ignored_logs'); |
||
441 | |||
442 | if ( ! $ignoredEventTypes) |
||
0 ignored issues
–
show
The expression
$ignoredEventTypes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
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 ![]() |
|||
443 | { |
||
444 | return false; |
||
445 | } |
||
446 | |||
447 | return in_array($level, $ignoredEventTypes, true); |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * Get the services provided by the provider. |
||
452 | * |
||
453 | * @return array |
||
454 | */ |
||
455 | public function provides() |
||
456 | { |
||
457 | return [ |
||
458 | 'understand.fieldProvider', |
||
459 | 'understand.logger', |
||
460 | 'understand.exceptionEncoder', |
||
461 | 'understand.exceptionLogger', |
||
462 | 'understand.eventLogger', |
||
463 | 'understand.tokenProvider', |
||
464 | 'understand.dataCollector', |
||
465 | ]; |
||
466 | } |
||
467 | } |
||
468 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.