Completed
Push — master ( 8dce14...ef59ee )
by Freek
13:50
created

IgnitionServiceProvider::getLogLevel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace Facade\Ignition;
4
5
use Throwable;
6
use Monolog\Logger;
7
use Illuminate\Support\Arr;
8
use Facade\FlareClient\Flare;
9
use Illuminate\Log\LogManager;
10
use Illuminate\Queue\QueueManager;
11
use Facade\FlareClient\Http\Client;
12
use Illuminate\Support\Facades\Log;
13
use Whoops\Handler\HandlerInterface;
14
use Illuminate\Support\Facades\Route;
15
use Illuminate\Foundation\Application;
16
use Facade\Ignition\ErrorPage\Renderer;
17
use Facade\Ignition\Middleware\AddLogs;
18
use Illuminate\Support\ServiceProvider;
19
use Facade\Ignition\Logger\FlareHandler;
20
use Facade\Ignition\Middleware\AddDumps;
21
use Illuminate\Log\Events\MessageLogged;
22
use Facade\Ignition\Commands\TestCommand;
23
use Facade\Ignition\Middleware\AddQueries;
24
use Facade\Ignition\LogRecorder\LogRecorder;
25
use Facade\Ignition\Middleware\AddSolutions;
26
use Facade\Ignition\Views\Engines\PhpEngine;
27
use Facade\Ignition\Exceptions\InvalidConfig;
28
use Facade\Ignition\DumpRecorder\DumpRecorder;
29
use Facade\Ignition\Middleware\SetNotifierName;
30
use Facade\Ignition\QueryRecorder\QueryRecorder;
31
use Facade\Ignition\Middleware\AddGitInformation;
32
use Facade\Ignition\Views\Engines\CompilerEngine;
33
use Facade\Ignition\Context\LaravelContextDetector;
34
use Facade\Ignition\ErrorPage\IgnitionWhoopsHandler;
35
use Facade\Ignition\Http\Middleware\IgnitionEnabled;
36
use Facade\Ignition\Http\Controllers\StyleController;
37
use Facade\Ignition\Http\Controllers\ScriptController;
38
use Facade\Ignition\Middleware\AddEnvironmentInformation;
39
use Illuminate\View\Engines\PhpEngine as LaravelPhpEngine;
40
use Facade\Ignition\Http\Controllers\HealthCheckController;
41
use Facade\Ignition\Http\Controllers\ShareReportController;
42
use Facade\Ignition\Http\Controllers\ExecuteSolutionController;
43
use Facade\Ignition\Http\Middleware\IgnitionConfigValueEnabled;
44
use Facade\Ignition\SolutionProviders\SolutionProviderRepository;
45
use Facade\Ignition\SolutionProviders\ViewNotFoundSolutionProvider;
46
use Facade\Ignition\SolutionProviders\BadMethodCallSolutionProvider;
47
use Facade\Ignition\SolutionProviders\DefaultDbNameSolutionProvider;
48
use Facade\Ignition\SolutionProviders\MergeConflictSolutionProvider;
49
use Facade\Ignition\SolutionProviders\MissingAppKeySolutionProvider;
50
use Facade\Ignition\SolutionProviders\MissingColumnSolutionProvider;
51
use Facade\Ignition\SolutionProviders\MissingImportSolutionProvider;
52
use Facade\Ignition\SolutionProviders\TableNotFoundSolutionProvider;
53
use Illuminate\View\Engines\CompilerEngine as LaravelCompilerEngine;
54
use Facade\Ignition\SolutionProviders\MissingPackageSolutionProvider;
55
use Facade\Ignition\SolutionProviders\UndefinedVariableSolutionProvider;
56
use Facade\Ignition\SolutionProviders\InvalidRouteActionSolutionProvider;
57
use Facade\Ignition\SolutionProviders\RunningLaravelDuskInProductionProvider;
58
use Facade\Ignition\SolutionProviders\IncorrectValetDbCredentialsSolutionProvider;
59
use Facade\IgnitionContracts\SolutionProviderRepository as SolutionProviderRepositoryContract;
60
61
class IgnitionServiceProvider extends ServiceProvider
62
{
63
    public function boot()
64
    {
65
        if ($this->app->runningInConsole()) {
66
            $this->publishes([
67
                __DIR__.'/../config/flare.php' => config_path('flare.php'),
68
            ], 'flare-config');
69
70
            $this->publishes([
71
                __DIR__.'/../config/ignition.php' => config_path('ignition.php'),
72
            ], 'ignition-config');
73
        }
74
75
        $this
76
            ->registerViewEngines()
77
            ->setupQueue($this->app->queue);
0 ignored issues
show
Bug introduced by
Accessing queue on the interface Illuminate\Contracts\Foundation\Application suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
78
    }
79
80
    public function register()
81
    {
82
        $this->mergeConfigFrom(__DIR__.'/../config/flare.php', 'flare');
83
        $this->mergeConfigFrom(__DIR__.'/../config/ignition.php', 'ignition');
84
85
        $this
86
            ->registerHousekeepingRoutes()
87
            ->registerSolutionProviderRepository()
88
            ->registerExceptionRenderer()
89
            ->registerWhoopsHandler()
90
            ->registerIgnitionConfig()
91
            ->registerFlare()
92
            ->registerLogHandler()
93
            ->registerLogRecorder()
94
            ->registerDumpCollector()
95
            ->registerCommands();
96
97
        if (config('flare.reporting.report_queries')) {
98
            $this->registerQueryRecorder();
99
        }
100
101
        if (config('flare.reporting.anonymize_ips')) {
102
            $this->app->get('flare.client')->anonymizeIp();
103
        }
104
105
        $this->registerBuiltInMiddleware();
106
    }
107
108
    protected function registerViewEngines()
109
    {
110
        if (! $this->hasCustomViewEnginesRegistered()) {
111
            return $this;
112
        }
113
114
        $this->app->make('view.engine.resolver')->register('php', function () {
115
            return new PhpEngine();
116
        });
117
118
        $this->app->make('view.engine.resolver')->register('blade', function () {
119
            return new CompilerEngine($this->app['blade.compiler']);
120
        });
121
122
        return $this;
123
    }
124
125
    protected function registerHousekeepingRoutes()
126
    {
127
        Route::group([
128
            'prefix' => config('ignition.housekeeping_endpoint_prefix', '_ignition'),
129
            'middleware' => [IgnitionEnabled::class],
130
        ], function () {
131
            Route::get('health-check', HealthCheckController::class);
132
133
            Route::post('execute-solution', ExecuteSolutionController::class)
134
                ->middleware(IgnitionConfigValueEnabled::class.':enableRunnableSolutions');
135
136
            Route::post('share-report', ShareReportController::class)
137
                ->middleware(IgnitionConfigValueEnabled::class.':enableShareButton');
138
139
            Route::get('scripts/{script}', ScriptController::class);
140
            Route::get('styles/{style}', StyleController::class);
141
        });
142
143
        return $this;
144
    }
145
146
    protected function registerSolutionProviderRepository()
147
    {
148
        $this->app->singleton(SolutionProviderRepositoryContract::class, function () {
149
            $defaultSolutions = $this->getDefaultSolutions();
150
151
            return new SolutionProviderRepository($defaultSolutions);
152
        });
153
154
        return $this;
155
    }
156
157
    protected function registerExceptionRenderer()
158
    {
159
        $this->app->bind(Renderer::class, function () {
160
            return new Renderer(__DIR__.'/../resources/views/');
161
        });
162
163
        return $this;
164
    }
165
166
    protected function registerWhoopsHandler()
167
    {
168
        $this->app->bind(HandlerInterface::class, function (Application $app) {
169
            return $app->make(IgnitionWhoopsHandler::class);
170
        });
171
172
        return $this;
173
    }
174
175
    protected function registerIgnitionConfig()
176
    {
177
        $this->app->singleton(IgnitionConfig::class, function () {
178
            $options = [];
179
180
            try {
181
                if ($configPath = $this->getConfigFileLocation()) {
182
                    $options = require $configPath;
183
                }
184
            } catch (Throwable $e) {
185
                // possible open_basedir restriction
186
            }
187
188
            return new IgnitionConfig($options);
189
        });
190
191
        return $this;
192
    }
193
194
    protected function registerFlare()
195
    {
196
        $this->app->singleton('flare.http', function () {
197
            return new Client(
198
                config('flare.key'),
199
                config('flare.secret'),
200
                config('flare.base_url', 'https://flareapp.io/api')
201
            );
202
        });
203
204
        $this->app->alias('flare.http', Client::class);
205
206
        $this->app->singleton('flare.client', function () {
207
            $client = new Flare($this->app->get('flare.http'), new LaravelContextDetector, $this->app);
208
            $client->applicationPath(base_path());
209
            $client->stage(config('app.env'));
210
211
            return $client;
212
        });
213
214
        $this->app->alias('flare.client', Flare::class);
215
216
        return $this;
217
    }
218
219
    protected function registerLogHandler()
220
    {
221
        $this->app->singleton('flare.logger', function ($app) {
222
            $handler = new FlareHandler($app->make('flare.client'));
223
224
            $logLevelString = config('logging.channels.flare.level', 'error');
225
226
            $logLevel = $this->getLogLevel($logLevelString);
227
228
            $handler->setMinimumReportLogLevel($logLevel);
229
230
            $logger = new Logger('Flare');
231
            $logger->pushHandler($handler);
232
233
            return $logger;
234
        });
235
236
        if ($this->app['log'] instanceof LogManager) {
237
            Log::extend('flare', function ($app) {
238
                return $app['flare.logger'];
239
            });
240
        } else {
241
            $this->bindLogListener();
242
        }
243
244
        return $this;
245
    }
246
247
    protected function getLogLevel(string $logLevelString): int
248
    {
249
        $logLevel = Logger::getLevels()[strtoupper($logLevelString)] ?? null;
250
251
        if (! $logLevel) {
252
            throw InvalidConfig::invalidLogLevel($logLevelString);
253
        }
254
255
        return $logLevel;
256
    }
257
258
    protected function registerLogRecorder()
259
    {
260
        $logCollector = $this->app->make(LogRecorder::class)->register();
261
262
        $this->app->singleton(LogRecorder::class);
263
264
        $this->app->instance(LogRecorder::class, $logCollector);
265
266
        return $this;
267
    }
268
269
    protected function registerDumpCollector()
270
    {
271
        $dumpCollector = $this->app->make(DumpRecorder::class)->register();
272
273
        $this->app->singleton(DumpRecorder::class);
274
275
        $this->app->instance(DumpRecorder::class, $dumpCollector);
276
277
        return $this;
278
    }
279
280
    protected function registerCommands()
281
    {
282
        $this->app->bind('command.flare:test', TestCommand::class);
283
284
        $this->commands([
285
            'command.flare:test',
286
        ]);
287
    }
288
289
    protected function registerQueryRecorder()
290
    {
291
        $queryCollector = $this->app->make(QueryRecorder::class)->register();
292
293
        $this->app->singleton(QueryRecorder::class);
294
295
        $this->app->instance(QueryRecorder::class, $queryCollector);
296
297
        return $this;
298
    }
299
300
    protected function registerBuiltInMiddleware()
301
    {
302
        $middleware = collect([
303
            SetNotifierName::class,
304
            AddEnvironmentInformation::class,
305
            AddLogs::class,
306
            AddDumps::class,
307
            AddQueries::class,
308
            AddSolutions::class,
309
        ])
310
        ->map(function (string $middlewareClass) {
311
            return $this->app->make($middlewareClass);
312
        });
313
314
        if (config('flare.reporting.collect_git_information')) {
315
            $middleware[] = (new AddGitInformation());
316
        }
317
318
        foreach ($middleware as $singleMiddleware) {
319
            $this->app->get('flare.client')->registerMiddleware($singleMiddleware);
320
        }
321
322
        return $this;
323
    }
324
325
    protected function getDefaultSolutions(): array
326
    {
327
        return [
328
            IncorrectValetDbCredentialsSolutionProvider::class,
329
            MissingAppKeySolutionProvider::class,
330
            DefaultDbNameSolutionProvider::class,
331
            BadMethodCallSolutionProvider::class,
332
            TableNotFoundSolutionProvider::class,
333
            MissingImportSolutionProvider::class,
334
            MissingPackageSolutionProvider::class,
335
            InvalidRouteActionSolutionProvider::class,
336
            ViewNotFoundSolutionProvider::class,
337
            UndefinedVariableSolutionProvider::class,
338
            MergeConflictSolutionProvider::class,
339
            RunningLaravelDuskInProductionProvider::class,
340
            MissingColumnSolutionProvider::class,
341
        ];
342
    }
343
344
    protected function hasCustomViewEnginesRegistered()
345
    {
346
        $resolver = $this->app->make('view.engine.resolver');
347
348
        if (! $resolver->resolve('php') instanceof LaravelPhpEngine) {
349
            return false;
350
        }
351
352
        if (! $resolver->resolve('blade') instanceof LaravelCompilerEngine) {
353
            return false;
354
        }
355
356
        return true;
357
    }
358
359
    protected function bindLogListener()
360
    {
361
        $this->app['log']->listen(function (MessageLogged $messageLogged) {
362
            if (config('flare.key')) {
363
                try {
364
                    $this->app['flare.logger']->log(
365
                        $messageLogged->level,
366
                        $messageLogged->message,
367
                        $messageLogged->context
368
                    );
369
                } catch (Exception $exception) {
0 ignored issues
show
Bug introduced by
The class Facade\Ignition\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
370
                    return;
371
                }
372
            }
373
        });
374
    }
375
376
    protected function getConfigFileLocation(): ?string
377
    {
378
        $configFullPath = base_path().DIRECTORY_SEPARATOR.'.ignition';
379
380
        if (file_exists($configFullPath)) {
381
            return $configFullPath;
382
        }
383
384
        $configFullPath = Arr::get($_SERVER, 'HOME', '').DIRECTORY_SEPARATOR.'.ignition';
385
386
        if (file_exists($configFullPath)) {
387
            return $configFullPath;
388
        }
389
390
        return null;
391
    }
392
393
    protected function setupQueue(QueueManager $queue)
394
    {
395
        $queue->looping(function () {
396
            $this->app->get('flare.client')->reset();
397
398
            if (config('flare.reporting.report_queries')) {
399
                $this->app->make(QueryRecorder::class)->reset();
400
            }
401
402
            $this->app->make(LogRecorder::class)->reset();
403
404
            $this->app->make(DumpRecorder::class)->reset();
405
        });
406
    }
407
}
408