Completed
Pull Request — master (#525)
by
unknown
01:45
created

ServiceProvider::loadRoutes()   B

Complexity

Conditions 5
Paths 9

Size

Total Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 8.7797
c 0
b 0
f 0
cc 5
nc 9
nop 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A ServiceProvider::getPackageDir() 0 4 1
A ServiceProvider::bootTracker() 0 4 1
A ServiceProvider::registerGlobalViewComposers() 0 12 1
A ServiceProvider::registerUpdateGeoIpCommand() 0 8 1
1
<?php
2
3
namespace PragmaRX\Tracker\Vendor\Laravel;
4
5
use PragmaRX\Support\GeoIp\GeoIp;
6
use PragmaRX\Support\PhpSession;
7
use PragmaRX\Support\ServiceProvider as PragmaRXServiceProvider;
8
use PragmaRX\Tracker\Data\Repositories\Agent;
9
use PragmaRX\Tracker\Data\Repositories\Connection;
10
use PragmaRX\Tracker\Data\Repositories\Cookie;
11
use PragmaRX\Tracker\Data\Repositories\Device;
12
use PragmaRX\Tracker\Data\Repositories\Domain;
13
use PragmaRX\Tracker\Data\Repositories\Error;
14
use PragmaRX\Tracker\Data\Repositories\Event;
15
use PragmaRX\Tracker\Data\Repositories\EventLog;
16
use PragmaRX\Tracker\Data\Repositories\GeoIp as GeoIpRepository;
17
use PragmaRX\Tracker\Data\Repositories\Language;
18
use PragmaRX\Tracker\Data\Repositories\Log;
19
use PragmaRX\Tracker\Data\Repositories\Path;
20
use PragmaRX\Tracker\Data\Repositories\Query;
21
use PragmaRX\Tracker\Data\Repositories\QueryArgument;
22
use PragmaRX\Tracker\Data\Repositories\Referer;
23
use PragmaRX\Tracker\Data\Repositories\Route;
24
use PragmaRX\Tracker\Data\Repositories\RoutePath;
25
use PragmaRX\Tracker\Data\Repositories\RoutePathParameter;
26
use PragmaRX\Tracker\Data\Repositories\Session;
27
use PragmaRX\Tracker\Data\Repositories\SqlQuery;
28
use PragmaRX\Tracker\Data\Repositories\SqlQueryBinding;
29
use PragmaRX\Tracker\Data\Repositories\SqlQueryBindingParameter;
30
use PragmaRX\Tracker\Data\Repositories\SqlQueryLog;
31
use PragmaRX\Tracker\Data\Repositories\SystemClass;
32
use PragmaRX\Tracker\Data\RepositoryManager;
33
use PragmaRX\Tracker\Eventing\EventStorage;
34
use PragmaRX\Tracker\Repositories\Message as MessageRepository;
35
use PragmaRX\Tracker\Services\Authentication;
36
use PragmaRX\Tracker\Support\Cache;
37
use PragmaRX\Tracker\Support\CrawlerDetector;
38
use PragmaRX\Tracker\Support\Exceptions\Handler as TrackerExceptionHandler;
39
use PragmaRX\Tracker\Support\LanguageDetect;
40
use PragmaRX\Tracker\Support\MobileDetect;
41
use PragmaRX\Tracker\Support\UserAgentParser;
42
use PragmaRX\Tracker\Tracker;
43
use PragmaRX\Tracker\Vendor\Laravel\Artisan\Tables as TablesCommand;
44
use PragmaRX\Tracker\Vendor\Laravel\Artisan\UpdateGeoIp;
45
46
class ServiceProvider extends PragmaRXServiceProvider
47
{
48
    protected $packageVendor = 'pragmarx';
49
50
    protected $packageName = 'tracker';
51
52
    protected $packageNameCapitalized = 'Tracker';
53
54
    protected $repositoryManagerIsBooted = false;
55
56
    /**
57
     * Indicates if loading of the provider is deferred.
58
     *
59
     * @var bool
60
     */
61
    protected $defer = false;
62
63
    protected $userChecked = false;
64
65
    protected $tracker;
66
67
    /**
68
     * Bootstrap the application events.
69
     *
70
     * @return void
71
     */
72
    public function boot()
73
    {
74
        parent::boot();
75
76
        if (!$this->getConfig('enabled')) {
77
            return false;
78
        }
79
        $this->registerErrorHandler();
80
81
        if (!$this->getConfig('use_middleware')) {
82
            $this->bootTracker();
83
        }
84
85
        $this->loadTranslations();
86
    }
87
88
    /**
89
     * Check if the service provider is full booted.
90
     *
91
     * @return void
92
     */
93
    public function isFullyBooted()
94
    {
95
        return $this->repositoryManagerIsBooted;
96
    }
97
98
    /**
99
     * Register the service provider.
100
     *
101
     * @return void
102
     */
103
    public function register()
104
    {
105
        parent::register();
106
107
        if ($this->getConfig('enabled')) {
108
            $this->registerAuthentication();
109
110
            $this->registerCache();
111
112
            $this->registerRepositories();
113
114
            $this->registerTracker();
115
116
            $this->registerTablesCommand();
117
118
            $this->registerUpdateGeoIpCommand();
119
120
            $this->registerExecutionCallback();
121
122
            $this->registerUserCheckCallback();
123
124
            $this->registerSqlQueryLogWatcher();
125
126
            $this->registerGlobalEventLogger();
127
128
            $this->registerDatatables();
129
130
            $this->registerMessageRepository();
131
132
            $this->registerGlobalViewComposers();
133
        }
134
    }
135
136
    /**
137
     * Get the services provided by the provider.
138
     *
139
     * @return string[]
140
     */
141
    public function provides()
142
    {
143
        return ['tracker'];
144
    }
145
146
    /**
147
     * Takes all the components of Tracker and glues them
148
     * together to create Tracker.
149
     *
150
     * @return void
151
     */
152
    protected function registerTracker()
153
    {
154
        $this->app->singleton('tracker', function ($app) {
155
            $app['tracker.loaded'] = true;
156
157
            return new Tracker(
158
                $app['tracker.config'],
159
                $app['tracker.repositories'],
160
                $app['request'],
161
                $app['router'],
162
                $app['log'],
163
                $app,
0 ignored issues
show
Documentation introduced by
$app is of type array<string,boolean,{"t...ker.loaded":"boolean"}>, but the function expects a object<Illuminate\Foundation\Application>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
164
                $app['tracker.messages']
165
            );
166
        });
167
    }
168
169
    public function registerRepositories()
170
    {
171
        $this->app->singleton('tracker.repositories', function ($app) {
172
            try {
173
                $uaParser = new UserAgentParser($app->make('path.base'));
174
            } catch (\Exception $exception) {
175
                $uaParser = null;
176
            }
177
178
            $sessionModel = $this->instantiateModel('session_model');
179
180
            $logModel = $this->instantiateModel('log_model');
181
182
            $agentModel = $this->instantiateModel('agent_model');
183
184
            $deviceModel = $this->instantiateModel('device_model');
185
186
            $cookieModel = $this->instantiateModel('cookie_model');
187
188
            $pathModel = $this->instantiateModel('path_model');
189
190
            $queryModel = $this->instantiateModel('query_model');
191
192
            $queryArgumentModel = $this->instantiateModel('query_argument_model');
193
194
            $domainModel = $this->instantiateModel('domain_model');
195
196
            $refererModel = $this->instantiateModel('referer_model');
197
198
            $refererSearchTermModel = $this->instantiateModel('referer_search_term_model');
199
200
            $routeModel = $this->instantiateModel('route_model');
201
202
            $routePathModel = $this->instantiateModel('route_path_model');
203
204
            $routePathParameterModel = $this->instantiateModel('route_path_parameter_model');
205
206
            $errorModel = $this->instantiateModel('error_model');
207
208
            $geoipModel = $this->instantiateModel('geoip_model');
209
210
            $sqlQueryModel = $this->instantiateModel('sql_query_model');
211
212
            $sqlQueryBindingModel = $this->instantiateModel('sql_query_binding_model');
213
214
            $sqlQueryBindingParameterModel = $this->instantiateModel('sql_query_binding_parameter_model');
215
216
            $sqlQueryLogModel = $this->instantiateModel('sql_query_log_model');
217
218
            $connectionModel = $this->instantiateModel('connection_model');
219
220
            $eventModel = $this->instantiateModel('event_model');
221
222
            $eventLogModel = $this->instantiateModel('event_log_model');
223
224
            $systemClassModel = $this->instantiateModel('system_class_model');
225
226
            $languageModel = $this->instantiateModel('language_model');
227
228
            $logRepository = new Log($logModel);
229
230
            $connectionRepository = new Connection($connectionModel);
231
232
            $sqlQueryBindingRepository = new SqlQueryBinding($sqlQueryBindingModel);
233
234
            $sqlQueryBindingParameterRepository = new SqlQueryBindingParameter($sqlQueryBindingParameterModel);
235
236
            $sqlQueryLogRepository = new SqlQueryLog($sqlQueryLogModel);
237
238
            $sqlQueryRepository = new SqlQuery(
239
                $sqlQueryModel,
240
                $sqlQueryLogRepository,
241
                $sqlQueryBindingRepository,
242
                $sqlQueryBindingParameterRepository,
243
                $connectionRepository,
244
                $logRepository,
245
                $app['tracker.config']
246
            );
247
248
            $eventLogRepository = new EventLog($eventLogModel);
249
250
            $systemClassRepository = new SystemClass($systemClassModel);
251
252
            $eventRepository = new Event(
253
                $eventModel,
254
                $app['tracker.events'],
255
                $eventLogRepository,
256
                $systemClassRepository,
257
                $logRepository,
258
                $app['tracker.config']
259
            );
260
261
            $routeRepository = new Route(
262
                $routeModel,
263
                $app['tracker.config']
264
            );
265
266
            $crawlerDetect = new CrawlerDetector(
267
                $app['request']->headers->all(),
268
                $app['request']->server('HTTP_USER_AGENT')
269
            );
270
271
            $manager = new RepositoryManager(
272
                new GeoIp($this->getConfig('geoip_database_path')),
273
                new MobileDetect(),
274
                $uaParser,
275
                $app['tracker.authentication'],
276
                $app['session.store'],
277
                $app['tracker.config'],
278
                new Session(
279
                    $sessionModel,
280
                    $app['tracker.config'],
281
                    new PhpSession()
282
                ),
283
                $logRepository,
284
                new Path($pathModel),
285
                new Query($queryModel),
286
                new QueryArgument($queryArgumentModel),
287
                new Agent($agentModel),
288
                new Device($deviceModel),
289
                new Cookie(
290
                    $cookieModel,
291
                    $app['tracker.config'],
292
                    $app['request'],
293
                    $app['cookie']
294
                ),
295
                new Domain($domainModel),
296
                new Referer(
297
                    $refererModel,
298
                    $refererSearchTermModel,
299
                    $this->getAppUrl(),
300
                    $app->make('PragmaRX\Tracker\Support\RefererParser')
301
                ),
302
                $routeRepository,
303
                new RoutePath($routePathModel),
304
                new RoutePathParameter($routePathParameterModel),
305
                new Error($errorModel),
306
                new GeoIpRepository($geoipModel),
307
                $sqlQueryRepository,
308
                $sqlQueryBindingRepository,
309
                $sqlQueryBindingParameterRepository,
310
                $sqlQueryLogRepository,
311
                $connectionRepository,
312
                $eventRepository,
313
                $eventLogRepository,
314
                $systemClassRepository,
315
                $crawlerDetect,
316
                new Language($languageModel),
317
                new LanguageDetect()
318
            );
319
320
            $this->repositoryManagerIsBooted = true;
321
322
            return $manager;
323
        });
324
    }
325
326
    public function registerAuthentication()
327
    {
328
        $this->app->singleton('tracker.authentication', function ($app) {
329
            return new Authentication($app['tracker.config'], $app);
330
        });
331
    }
332
333
    public function registerCache()
334
    {
335
        $this->app->singleton('tracker.cache', function ($app) {
336
            return new Cache($app['tracker.config'], $app);
337
        });
338
    }
339
340
    protected function registerTablesCommand()
341
    {
342
        $this->app->singleton('tracker.tables.command', function ($app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
343
            return new TablesCommand();
344
        });
345
346
        $this->commands('tracker.tables.command');
347
    }
348
349
    protected function registerExecutionCallback()
350
    {
351
        $me = $this;
352
353
        $mathingEvents = [
354
            'router.matched',
355
            'Illuminate\Routing\Events\RouteMatched',
356
        ];
357
358
        $this->app['events']->listen($mathingEvents, function () use ($me) {
359
            $me->getTracker()->routerMatched($me->getConfig('log_routes'));
360
        });
361
    }
362
363
    protected function registerErrorHandler()
364
    {
365
        if ($this->getConfig('log_exceptions')) {
366
            $illuminateHandler = 'Illuminate\Contracts\Debug\ExceptionHandler';
367
368
            $handler = new TrackerExceptionHandler(
369
                $this->getTracker(),
370
                $this->app[$illuminateHandler]
371
            );
372
373
            // Replace original Illuminate Exception Handler by Tracker's
374
            $this->app[$illuminateHandler] = $handler;
375
        }
376
    }
377
378
    /**
379
     * @param string $modelName
380
     */
381
    protected function instantiateModel($modelName)
382
    {
383
        $model = $this->getConfig($modelName);
384
385
        if (!$model) {
386
            $message = "Tracker: Model not found for '$modelName'.";
387
388
            $this->app['log']->error($message);
389
390
            throw new \Exception($message);
391
        }
392
393
        $model = new $model();
394
395
        $model->setConfig($this->app['tracker.config']);
396
397
        if ($connection = $this->getConfig('connection')) {
398
            $model->setConnection($connection);
399
        }
400
401
        return $model;
402
    }
403
404
    protected function registerSqlQueryLogWatcher()
405
    {
406
        $me = $this;
407
408
        if (!class_exists('Illuminate\Database\Events\QueryExecuted')) {
409
            $this->app['events']->listen('illuminate.query', function (
410
                $query,
411
                $bindings,
412
                $time,
413
                $name
414
            ) use ($me) {
415
                $me->logSqlQuery($query, $bindings, $time, $name);
416
            });
417
        } else {
418
            $this->app['events']->listen('Illuminate\Database\Events\QueryExecuted', function ($query) use ($me) {
419
                $me->logSqlQuery($query);
420
            });
421
        }
422
    }
423
424
    /**
425
     * @param $query
426
     * @param $bindings
427
     * @param $time
428
     * @param $name
429
     * @param $me
430
     */
431
    public function logSqlQuery($query, $bindings = null, $time = null, $connectionName = null)
432
    {
433
        if ($this->getTracker()->isEnabled()) {
434
            if ($query instanceof \Illuminate\Database\Events\QueryExecuted) {
435
                $bindings = $query->bindings;
436
                $time = $query->time;
437
                $connectionName = $query->connectionName;
438
                $query = $query->sql;
439
            }
440
441
            $this->getTracker()->logSqlQuery($query, $bindings, $time, $connectionName);
442
        }
443
    }
444
445
    protected function registerGlobalEventLogger()
446
    {
447
        $me = $this;
448
449
        $this->app->singleton('tracker.events', function ($app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
450
            return new EventStorage();
451
        });
452
453
        $this->app['events']->listen('*', function ($object = null) use ($me) {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
454
            if ($me->app['tracker.events']->isOff() || !$me->isFullyBooted()) {
455
                return;
456
            }
457
458
            // To avoid infinite recursion, event tracking while logging events
459
            // must be turned off
460
            $me->app['tracker.events']->turnOff();
461
462
            // Log events even before application is ready
463
            // $me->app['tracker.events']->logEvent(
464
            //    $me->app['events']->firing(),
465
            //    $object
466
            // );
467
            // TODO: we have to investigate a way of doing this
468
469
            // Can only send events to database after application is ready
470
            if (isset($me->app['tracker.loaded'])) {
471
                $me->getTracker()->logEvents();
472
            }
473
474
            // Turn the event tracking to on again
475
            $me->app['tracker.events']->turnOn();
476
        });
477
    }
478
479
   
480
    protected function registerDatatables()
481
    {
482
        $this->registerServiceProvider('Bllim\Datatables\DatatablesServiceProvider');
483
484
        $this->registerServiceAlias('Datatable', 'Bllim\Datatables\Facade\Datatables');
485
    }
486
487
    /**
488
     * Get the current package directory.
489
     *
490
     * @return string
491
     */
492
    public function getPackageDir()
493
    {
494
        return __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..';
495
    }
496
497
    /**
498
     * Boot & Track.
499
     */
500
    protected function bootTracker()
501
    {
502
        $this->getTracker()->boot();
503
    }
504
505
    /**
506
     * Register global view composers.
507
     */
508
    protected function registerGlobalViewComposers()
509
    {
510
        $me = $this;
511
512
        $this->app->make('view')->composer('pragmarx/tracker::*', function ($view) use ($me) {
513
            $view->with('stats_layout', $me->getConfig('stats_layout'));
514
515
            $template_path = url('/').$me->getConfig('stats_template_path');
516
517
            $view->with('stats_template_path', $template_path);
518
        });
519
    }
520
521
    protected function registerUpdateGeoIpCommand()
522
    {
523
        $this->app->singleton('tracker.updategeoip.command', function ($app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
524
            return new UpdateGeoIp();
525
        });
526
527
        $this->commands('tracker.updategeoip.command');
528
    }
529
530
    protected function registerUserCheckCallback()
531
    {
532
        $me = $this;
533
534
        $this->app['events']->listen('router.before', function ($object = null) use ($me) {
0 ignored issues
show
Unused Code introduced by
The parameter $object is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
535
536
            // get auth bindings to check
537
            $bindings = $me->getConfig('authentication_ioc_binding');
538
539
            // check if all bindings are resolved
540
            $checked_bindings = array_map(function ($abstract) use ($me) {
541
                return $me->app->resolved($abstract);
542
            }, $bindings);
543
544
            $all_bindings_resolved =
545
                (!in_array(false, $checked_bindings, true)) ?: false;
546
547
            if ($me->tracker &&
548
                !$me->userChecked &&
549
                $me->getConfig('log_users') &&
550
                $all_bindings_resolved
551
            ) {
552
                $me->userChecked = $me->getTracker()->checkCurrentUser();
553
            }
554
        });
555
    }
556
557
    /**
558
     * @return Tracker
559
     */
560
    public function getTracker()
561
    {
562
        if (!$this->tracker) {
563
            $this->tracker = $this->app['tracker'];
564
        }
565
566
        return $this->tracker;
567
    }
568
569
    public function getRootDirectory()
570
    {
571
        return __DIR__.'/../..';
572
    }
573
574
    protected function getAppUrl()
575
    {
576
        return $this->app['request']->url();
577
    }
578
579
    public function loadTranslations()
580
    {
581
        $this->loadTranslationsFrom(__DIR__.'/../../lang', 'tracker');
582
    }
583
584
    /**
585
     * Register the message repository.
586
     */
587
    protected function registerMessageRepository()
588
    {
589
        $this->app->singleton('tracker.messages', function () {
590
            return new MessageRepository();
591
        });
592
    }
593
}
594