Completed
Push — master ( 18a7c0...5aa638 )
by Antonio Carlos
01:52
created

ServiceProvider::getPackageDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
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 $repositoryMangerIsBooted = 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
80
        $this->loadRoutes();
81
82
        $this->registerErrorHandler();
83
84
        if (!isLaravel5()) {
85
            $this->bootTracker();
86
        }
87
88
        $this->loadTranslations();
89
    }
90
91
    /**
92
     * Check if the service provider is full booted.
93
     *
94
     * @return void
95
     */
96
    public function isFullyBooted()
97
    {
98
        return $this->repositoryMangerIsBooted;
99
    }
100
101
    /**
102
     * Register the service provider.
103
     *
104
     * @return void
105
     */
106
    public function register()
107
    {
108
        parent::register();
109
110
        if ($this->getConfig('enabled')) {
111
            $this->registerAuthentication();
112
113
            $this->registerCache();
114
115
            $this->registerRepositories();
116
117
            $this->registerTracker();
118
119
            $this->registerTablesCommand();
120
121
            $this->registerUpdateGeoIpCommand();
122
123
            $this->registerExecutionCallback();
124
125
            $this->registerUserCheckCallback();
126
127
            $this->registerSqlQueryLogWatcher();
128
129
            $this->registerGlobalEventLogger();
130
131
            $this->registerDatatables();
132
133
            $this->registerMessageRepository();
134
135
            $this->registerGlobalViewComposers();
136
        }
137
    }
138
139
    /**
140
     * Get the services provided by the provider.
141
     *
142
     * @return string[]
143
     */
144
    public function provides()
145
    {
146
        return ['tracker'];
147
    }
148
149
    /**
150
     * Takes all the components of Tracker and glues them
151
     * together to create Tracker.
152
     *
153
     * @return void
154
     */
155
    protected function registerTracker()
156
    {
157
        $this->app->singleton('tracker', function ($app) {
158
            $app['tracker.loaded'] = true;
159
160
            return new Tracker(
161
                                    $app['tracker.config'],
162
                                    $app['tracker.repositories'],
163
                                    $app['request'],
164
                                    $app['router'],
165
                                    $app['log'],
166
                                    $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...
167
                                    $app['tracker.messages']
168
                                );
169
        });
170
    }
171
172
    public function registerRepositories()
173
    {
174
        $this->app->singleton('tracker.repositories', function ($app) {
175
            try {
176
                $uaParser = new UserAgentParser($app->make('path.base'));
177
            } catch (\Exception $exception) {
178
                $uaParser = null;
179
            }
180
181
            $sessionModel = $this->instantiateModel('session_model');
182
183
            $logModel = $this->instantiateModel('log_model');
184
185
            $agentModel = $this->instantiateModel('agent_model');
186
187
            $deviceModel = $this->instantiateModel('device_model');
188
189
            $cookieModel = $this->instantiateModel('cookie_model');
190
191
            $pathModel = $this->instantiateModel('path_model');
192
193
            $queryModel = $this->instantiateModel('query_model');
194
195
            $queryArgumentModel = $this->instantiateModel('query_argument_model');
196
197
            $domainModel = $this->instantiateModel('domain_model');
198
199
            $refererModel = $this->instantiateModel('referer_model');
200
201
            $refererSearchTermModel = $this->instantiateModel('referer_search_term_model');
202
203
            $routeModel = $this->instantiateModel('route_model');
204
205
            $routePathModel = $this->instantiateModel('route_path_model');
206
207
            $routePathParameterModel = $this->instantiateModel('route_path_parameter_model');
208
209
            $errorModel = $this->instantiateModel('error_model');
210
211
            $geoipModel = $this->instantiateModel('geoip_model');
212
213
            $sqlQueryModel = $this->instantiateModel('sql_query_model');
214
215
            $sqlQueryBindingModel = $this->instantiateModel('sql_query_binding_model');
216
217
            $sqlQueryBindingParameterModel = $this->instantiateModel('sql_query_binding_parameter_model');
218
219
            $sqlQueryLogModel = $this->instantiateModel('sql_query_log_model');
220
221
            $connectionModel = $this->instantiateModel('connection_model');
222
223
            $eventModel = $this->instantiateModel('event_model');
224
225
            $eventLogModel = $this->instantiateModel('event_log_model');
226
227
            $systemClassModel = $this->instantiateModel('system_class_model');
228
229
            $languageModel = $this->instantiateModel('language_model');
230
231
            $logRepository = new Log($logModel);
232
233
            $connectionRepository = new Connection($connectionModel);
234
235
            $sqlQueryBindingRepository = new SqlQueryBinding($sqlQueryBindingModel);
236
237
            $sqlQueryBindingParameterRepository = new SqlQueryBindingParameter($sqlQueryBindingParameterModel);
238
239
            $sqlQueryLogRepository = new SqlQueryLog($sqlQueryLogModel);
240
241
            $sqlQueryRepository = new SqlQuery(
242
                $sqlQueryModel,
243
                $sqlQueryLogRepository,
244
                $sqlQueryBindingRepository,
245
                $sqlQueryBindingParameterRepository,
246
                $connectionRepository,
247
                $logRepository,
248
                $app['tracker.config']
249
            );
250
251
            $eventLogRepository = new EventLog($eventLogModel);
252
253
            $systemClassRepository = new SystemClass($systemClassModel);
254
255
            $eventRepository = new Event(
256
                $eventModel,
257
                $app['tracker.events'],
258
                $eventLogRepository,
259
                $systemClassRepository,
260
                $logRepository,
261
                $app['tracker.config']
262
            );
263
264
            $routeRepository = new Route(
265
                $routeModel,
266
                $app['tracker.config']
267
            );
268
269
            $crawlerDetect = new CrawlerDetector(
270
                $app['request']->headers->all(),
271
                $app['request']->server('HTTP_USER_AGENT')
272
            );
273
274
            $manager = new RepositoryManager(
275
                new GeoIp($this->getConfig('geoip_database_path')),
276
277
                new MobileDetect(),
278
279
                $uaParser,
280
281
                $app['tracker.authentication'],
282
283
                $app['session.store'],
284
285
                $app['tracker.config'],
286
287
                new Session($sessionModel,
288
                            $app['tracker.config'],
289
                            new PhpSession()),
290
291
                $logRepository,
292
293
                new Path($pathModel),
294
295
                new Query($queryModel),
296
297
                new QueryArgument($queryArgumentModel),
298
299
                new Agent($agentModel),
300
301
                new Device($deviceModel),
302
303
                new Cookie($cookieModel,
304
                            $app['tracker.config'],
305
                            $app['request'],
306
                            $app['cookie']),
307
308
                new Domain($domainModel),
309
310
                new Referer(
311
                    $refererModel,
312
                    $refererSearchTermModel,
313
                    $this->getAppUrl(),
314
                    $app->make('PragmaRX\Tracker\Support\RefererParser')
315
                ),
316
317
                $routeRepository,
318
319
                new RoutePath($routePathModel),
320
321
                new RoutePathParameter($routePathParameterModel),
322
323
                new Error($errorModel),
324
325
                new GeoIpRepository($geoipModel),
326
327
                $sqlQueryRepository,
328
329
                $sqlQueryBindingRepository,
330
331
                $sqlQueryBindingParameterRepository,
332
333
                $sqlQueryLogRepository,
334
335
                $connectionRepository,
336
337
                $eventRepository,
338
339
                $eventLogRepository,
340
341
                $systemClassRepository,
342
343
                $crawlerDetect,
344
345
                new Language($languageModel),
346
347
                new LanguageDetect()
348
            );
349
350
            $this->repositoryMangerIsBooted = true;
351
352
            return $manager;
353
        });
354
    }
355
356
    public function registerAuthentication()
357
    {
358
        $this->app->singleton('tracker.authentication', function ($app) {
359
            return new Authentication($app['tracker.config'], $app);
360
        });
361
    }
362
363
    public function registerCache()
364
    {
365
        $this->app->singleton('tracker.cache', function ($app) {
366
            return new Cache($app['tracker.config'], $app);
367
        });
368
    }
369
370
    protected function registerTablesCommand()
371
    {
372
        $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...
373
            return new TablesCommand();
374
        });
375
376
        $this->commands('tracker.tables.command');
377
    }
378
379
    protected function registerExecutionCallback()
380
    {
381
        $me = $this;
382
383
        $mathingEvents = [
384
            'router.matched',
385
            'Illuminate\Routing\Events\RouteMatched',
386
        ];
387
388
        $this->app['events']->listen($mathingEvents, function () use ($me) {
389
            $me->getTracker()->routerMatched($me->getConfig('log_routes'));
390
        });
391
    }
392
393
    protected function registerErrorHandler()
394
    {
395
        if ($this->getConfig('log_exceptions')) {
396
            if (isLaravel5()) {
397
                $illuminateHandler = 'Illuminate\Contracts\Debug\ExceptionHandler';
398
399
                $handler = new TrackerExceptionHandler(
400
                    $this->getTracker(),
401
                    $this->app[$illuminateHandler]
402
                );
403
404
                // Replace original Illuminate Exception Handler by Tracker's
405
                $this->app[$illuminateHandler] = $handler;
406
            } else {
407
                $me = $this;
408
409
                $this->app->error(
0 ignored issues
show
Bug introduced by
The method error() does not seem to exist on object<Illuminate\Contra...Foundation\Application>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
410
                    function (\Exception $exception, $code) use ($me) {
411
                        $me->app['tracker']->handleException($exception, $code);
412
                    }
413
                );
414
            }
415
        }
416
    }
417
418
    /**
419
     * @param string $modelName
420
     */
421
    protected function instantiateModel($modelName)
422
    {
423
        $model = $this->getConfig($modelName);
424
425
        if (!$model) {
426
            $message = "Tracker: Model not found for '$modelName'.";
427
428
            $this->app['log']->error($message);
429
430
            throw new \Exception($message);
431
        }
432
433
        $model = new $model();
434
435
        $model->setConfig($this->app['tracker.config']);
436
437
        if ($connection = $this->getConfig('connection')) {
438
            $model->setConnection($connection);
439
        }
440
441
        return $model;
442
    }
443
444
    protected function registerSqlQueryLogWatcher()
445
    {
446
        $me = $this;
447
448
        if (!class_exists('Illuminate\Database\Events\QueryExecuted')) {
449
            $this->app['events']->listen('illuminate.query', function ($query,
450
                                                                        $bindings,
451
                                                                        $time,
452
                                                                        $name) use ($me) {
453
                $me->logSqlQuery($query, $bindings, $time, $name);
454
            });
455
        } else {
456
            $this->app['events']->listen('Illuminate\Database\Events\QueryExecuted', function ($query) use ($me) {
457
                $me->logSqlQuery($query);
458
            });
459
        }
460
    }
461
462
    /**
463
     * @param $query
464
     * @param $bindings
465
     * @param $time
466
     * @param $name
467
     * @param $me
468
     */
469
    public function logSqlQuery($query, $bindings = null, $time = null, $connectionName = null)
470
    {
471
        if ($this->getTracker()->isEnabled()) {
472
            if ($query instanceof \Illuminate\Database\Events\QueryExecuted) {
473
                $bindings = $query->bindings;
474
                $time = $query->time;
475
                $connectionName = $query->connectionName;
476
                $query = $query->sql;
477
            }
478
479
            $this->getTracker()->logSqlQuery($query, $bindings, $time, $connectionName);
480
        }
481
    }
482
483
    protected function registerGlobalEventLogger()
484
    {
485
        $me = $this;
486
487
        $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...
488
            return new EventStorage();
489
        });
490
491
        $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...
492
            if ($me->app['tracker.events']->isOff() || !$me->isFullyBooted()) {
493
                return;
494
            }
495
496
            // To avoid infinite recursion, event tracking while logging events
497
            // must be turned off
498
            $me->app['tracker.events']->turnOff();
499
500
            // Log events even before application is ready
501
            // $me->app['tracker.events']->logEvent(
502
            //    $me->app['events']->firing(),
503
            //    $object
504
            // );
505
            // TODO: we have to investigate a way of doing this
506
507
            // Can only send events to database after application is ready
508
            if (isset($me->app['tracker.loaded'])) {
509
                $me->getTracker()->logEvents();
510
            }
511
512
            // Turn the event tracking to on again
513
            $me->app['tracker.events']->turnOn();
514
        });
515
    }
516
517
    protected function loadRoutes()
518
    {
519
        if (!$this->getConfig('stats_panel_enabled')) {
520
            return false;
521
        }
522
523
        $prefix = $this->getConfig('stats_base_uri');
524
525
        $namespace = $this->getConfig('stats_controllers_namespace');
526
527
        $filters = [];
528
529
        if ($before = $this->getConfig('stats_routes_before_filter')) {
530
            $filters['before'] = $before;
531
        }
532
533
        if ($after = $this->getConfig('stats_routes_after_filter')) {
534
            $filters['after'] = $after;
535
        }
536
537
        if ($middleware = $this->getConfig('stats_routes_middleware')) {
538
            $filters['middleware'] = $middleware;
539
        }
540
541
        $router = $this->app->make('router');
542
543
        $router->group(['namespace' => $namespace], function () use ($prefix, $router, $filters) {
544
            $router->group($filters, function () use ($prefix, $router) {
545
                $router->group(['prefix' => $prefix], function ($router) {
546
                    $router->get('/', ['as' => 'tracker.stats.index', 'uses' => 'Stats@index']);
547
548
                    $router->get('log/{uuid}', ['as' => 'tracker.stats.log', 'uses' => 'Stats@log']);
549
550
                    $router->get('api/pageviews', ['as' => 'tracker.stats.api.pageviews', 'uses' => 'Stats@apiPageviews']);
551
552
                    $router->get('api/pageviewsbycountry', ['as' => 'tracker.stats.api.pageviewsbycountry', 'uses' => 'Stats@apiPageviewsByCountry']);
553
554
                    $router->get('api/log/{uuid}', ['as' => 'tracker.stats.api.log', 'uses' => 'Stats@apiLog']);
555
556
                    $router->get('api/errors', ['as' => 'tracker.stats.api.errors', 'uses' => 'Stats@apiErrors']);
557
558
                    $router->get('api/events', ['as' => 'tracker.stats.api.events', 'uses' => 'Stats@apiEvents']);
559
560
                    $router->get('api/users', ['as' => 'tracker.stats.api.users', 'uses' => 'Stats@apiUsers']);
561
562
                    $router->get('api/visits', ['as' => 'tracker.stats.api.visits', 'uses' => 'Stats@apiVisits']);
563
                });
564
            });
565
        });
566
    }
567
568
    protected function registerDatatables()
569
    {
570
        $this->registerServiceProvider('Bllim\Datatables\DatatablesServiceProvider');
571
572
        $this->registerServiceAlias('Datatable', 'Bllim\Datatables\Facade\Datatables');
573
    }
574
575
    /**
576
     * Get the current package directory.
577
     *
578
     * @return string
579
     */
580
    public function getPackageDir()
581
    {
582
        return __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..';
583
    }
584
585
    /**
586
     * Boot & Track.
587
     */
588
    protected function bootTracker()
589
    {
590
        $this->getTracker()->boot();
591
    }
592
593
    /**
594
     * Register global view composers.
595
     */
596
    protected function registerGlobalViewComposers()
597
    {
598
        $me = $this;
599
600
        $this->app->make('view')->composer('pragmarx/tracker::*', function ($view) use ($me) {
601
            $view->with('stats_layout', $me->getConfig('stats_layout'));
602
603
            $template_path = url('/').$me->getConfig('stats_template_path');
604
605
            $view->with('stats_template_path', $template_path);
606
        });
607
    }
608
609
    protected function registerUpdateGeoIpCommand()
610
    {
611
        $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...
612
            return new UpdateGeoIp();
613
        });
614
615
        $this->commands('tracker.updategeoip.command');
616
    }
617
618
    protected function registerUserCheckCallback()
619
    {
620
        $me = $this;
621
622
        $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...
623
624
            // get auth bindings to check
625
            $bindings = $me->getConfig('authentication_ioc_binding');
626
627
            // check if all bindings are resolved
628
            $checked_bindings = array_map(function ($abstract) use ($me) {
629
                return $me->app->resolved($abstract);
630
            }, $bindings);
631
632
            $all_bindings_resolved =
633
                (!in_array(false, $checked_bindings, true)) ?: false;
634
635
            if ($me->tracker &&
636
                !$me->userChecked &&
637
                $me->getConfig('log_users') &&
638
                $all_bindings_resolved
639
            ) {
640
                $me->userChecked = $me->getTracker()->checkCurrentUser();
641
            }
642
        });
643
    }
644
645
    /**
646
     * @return Tracker
647
     */
648
    public function getTracker()
649
    {
650
        if (!$this->tracker) {
651
            $this->tracker = $this->app['tracker'];
652
        }
653
654
        return $this->tracker;
655
    }
656
657
    public function getRootDirectory()
658
    {
659
        return __DIR__.'/../..';
660
    }
661
662
    protected function getAppUrl()
663
    {
664
        return $this->app['request']->url();
665
    }
666
667
    public function loadTranslations()
668
    {
669
        $this->loadTranslationsFrom(__DIR__.'/../../lang', 'tracker');
670
    }
671
672
    /**
673
     * Register the message repository.
674
     */
675
    protected function registerMessageRepository()
676
    {
677
        $this->app->singleton('tracker.messages', function () {
678
            return new MessageRepository();
679
        });
680
    }
681
}
682