Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Issues (969)

Branch: fix-hooks-at-setup-level

src/BackpackServiceProvider.php (1 issue)

1
<?php
2
3
namespace Backpack\CRUD;
4
5
use Backpack\Basset\Facades\Basset;
6
use Backpack\CRUD\app\Http\Middleware\EnsureEmailVerification;
7
use Backpack\CRUD\app\Http\Middleware\ThrottlePasswordRecovery;
8
use Backpack\CRUD\app\Library\Database\DatabaseSchema;
9
use Backpack\CRUD\app\Library\Uploaders\Support\UploadersRepository;
10
use Illuminate\Contracts\Debug\ExceptionHandler;
11
use Illuminate\Routing\Router;
12
use Illuminate\Support\Collection;
13
use Illuminate\Support\Facades\Blade;
14
use Illuminate\Support\Facades\File;
15
use Illuminate\Support\ServiceProvider;
16
use Illuminate\Support\Str;
17
use Illuminate\View\Compilers\BladeCompiler;
18
19
class BackpackServiceProvider extends ServiceProvider
20
{
21
    use Stats;
22
23
    protected $commands = [
24
        app\Console\Commands\Install::class,
25
        app\Console\Commands\AddMenuContent::class,
26
        app\Console\Commands\AddCustomRouteContent::class,
27
        app\Console\Commands\Version::class,
28
        app\Console\Commands\CreateUser::class,
29
        app\Console\Commands\PublishBackpackMiddleware::class,
30
        app\Console\Commands\PublishView::class,
31
        app\Console\Commands\Addons\RequireDevTools::class,
32
        app\Console\Commands\Addons\RequireEditableColumns::class,
33
        app\Console\Commands\Addons\RequirePro::class,
34
        app\Console\Commands\Themes\RequireThemeTabler::class,
35
        app\Console\Commands\Themes\RequireThemeCoreuiv2::class,
36
        app\Console\Commands\Themes\RequireThemeCoreuiv4::class,
37
        app\Console\Commands\Fix::class,
38
        app\Console\Commands\PublishHeaderMetas::class,
39
    ];
40
41
    // Indicates if loading of the provider is deferred.
42
    protected $defer = false;
43
44
    // Where the route file lives, both inside the package and in the app (if overwritten).
45
    public $routeFilePath = '/routes/backpack/base.php';
46
47
    // Where custom routes can be written, and will be registered by Backpack.
48
    public $customRoutesFilePath = '/routes/backpack/custom.php';
49
50
    /**
51
     * Perform post-registration booting of services.
52
     *
53
     * @return void
54
     */
55
    public function boot(Router $router)
56
    {
57
        $this->loadTranslationsFrom(realpath(__DIR__.'/resources/lang'), 'backpack');
58
        $this->loadConfigs();
59
        $this->registerMiddlewareGroup($this->app->router);
60
        $this->setupRoutes($this->app->router);
61
        $this->setupCustomRoutes($this->app->router);
62
        $this->publishFiles();
63
        $this->sendUsageStats();
64
65
        Basset::addViewPath(realpath(__DIR__.'/resources/views'));
66
    }
67
68
    /**
69
     * Register any package services.
70
     *
71
     * @return void
72
     */
73
    public function register()
74
    {
75
        // load the macros
76
        include_once __DIR__.'/macros.php';
77
78
        $this->loadViewsWithFallbacks('crud');
79
        $this->loadViewsWithFallbacks('ui', 'backpack.ui');
80
        $this->loadViewNamespace('widgets', 'backpack.ui::widgets');
81
        ViewNamespaces::addFor('widgets', 'crud::widgets');
82
83
        $this->loadViewComponents();
84
        $this->registerDynamicBladeComponents();
85
86
        $this->registerBackpackErrorViews();
87
88
        $this->app->bind('crud', function ($app) {
89
            return CrudManager::identifyCrudPanel();
90
        });
91
92
        $this->app->scoped('CrudManager', function ($app) {
93
            return new CrudPanelManager();
94
        });
95
96
        $this->app->scoped('DatabaseSchema', function ($app) {
97
            return new DatabaseSchema();
98
        });
99
100
        $this->app->scoped('BackpackLifecycleHooks', function ($app) {
101
            return new app\Library\CrudPanel\Hooks\LifecycleHooks();
102
        });
103
104
        $this->app->singleton('BackpackViewNamespaces', function ($app) {
105
            return new ViewNamespaces();
106
        });
107
108
        // Bind the widgets collection object to Laravel's service container
109
        $this->app->singleton('widgets', function ($app) {
110
            return new Collection();
111
        });
112
113
        $this->app->scoped('UploadersRepository', function ($app) {
114
            return new UploadersRepository();
115
        });
116
117
        // register the helper functions
118
        $this->loadHelpers();
119
120
        // register the artisan commands
121
        $this->commands($this->commands);
122
    }
123
124
    public function registerMiddlewareGroup(Router $router)
125
    {
126
        $middleware_key = config('backpack.base.middleware_key');
127
        $middleware_class = config('backpack.base.middleware_class');
128
129
        if (! is_array($middleware_class)) {
130
            $router->pushMiddlewareToGroup($middleware_key, $middleware_class);
131
132
            return;
133
        }
134
135
        foreach ($middleware_class as $middleware_class) {
136
            $router->pushMiddlewareToGroup($middleware_key, $middleware_class);
137
        }
138
139
        // register internal backpack middleware for throttling the password recovery functionality
140
        // but only if functionality is enabled by developer in config
141
        if (config('backpack.base.setup_password_recovery_routes')) {
142
            $router->aliasMiddleware('backpack.throttle.password.recovery', ThrottlePasswordRecovery::class);
143
        }
144
145
        // register the email verification middleware, if the developer enabled it in the config.
146
        if (config('backpack.base.setup_email_verification_routes', false) && config('backpack.base.setup_email_verification_middleware', true)) {
147
            $router->pushMiddlewareToGroup($middleware_key, EnsureEmailVerification::class);
148
        }
149
    }
150
151
    public function publishFiles()
152
    {
153
        $backpack_views = [__DIR__.'/resources/views' => resource_path('views/vendor/backpack')];
154
        $backpack_lang_files = [__DIR__.'/resources/lang' => app()->langPath().'/vendor/backpack'];
0 ignored issues
show
The method langPath() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

154
        $backpack_lang_files = [__DIR__.'/resources/lang' => app()->/** @scrutinizer ignore-call */ langPath().'/vendor/backpack'];
Loading history...
155
        $backpack_config_files = [__DIR__.'/config' => config_path()];
156
157
        // sidebar content views, which are the only views most people need to overwrite
158
        $backpack_menu_contents_view = [
159
            __DIR__.'/resources/views/ui/inc/menu_items.blade.php' => resource_path('views/vendor/backpack/ui/inc/menu_items.blade.php'),
160
        ];
161
        $backpack_custom_routes_file = [__DIR__.$this->customRoutesFilePath => base_path($this->customRoutesFilePath)];
162
163
        // calculate the path from current directory to get the vendor path
164
        $vendorPath = dirname(__DIR__, 3);
165
        $gravatar_assets = [$vendorPath.'/creativeorange/gravatar/config' => config_path()];
166
167
        // establish the minimum amount of files that need to be published, for Backpack to work; there are the files that will be published by the install command
168
        $minimum = array_merge(
169
            // $backpack_views,
170
            // $backpack_lang_files,
171
            $backpack_config_files,
172
            $backpack_menu_contents_view,
173
            $backpack_custom_routes_file,
174
            $gravatar_assets
175
        );
176
177
        // register all possible publish commands and assign tags to each
178
        $this->publishes($backpack_config_files, 'config');
179
        $this->publishes($backpack_lang_files, 'lang');
180
        $this->publishes($backpack_views, 'views');
181
        $this->publishes($backpack_menu_contents_view, 'menu_contents');
182
        $this->publishes($backpack_custom_routes_file, 'custom_routes');
183
        $this->publishes($gravatar_assets, 'gravatar');
184
        $this->publishes($minimum, 'minimum');
185
    }
186
187
    /**
188
     * Define the routes for the application.
189
     *
190
     * @param  Router  $router
191
     * @return void
192
     */
193
    public function setupRoutes(Router $router)
194
    {
195
        // by default, use the routes file provided in vendor
196
        $routeFilePathInUse = __DIR__.$this->routeFilePath;
197
198
        // but if there's a file with the same name in routes/backpack, use that one
199
        if (file_exists(base_path().$this->routeFilePath)) {
200
            $routeFilePathInUse = base_path().$this->routeFilePath;
201
        }
202
203
        $this->loadRoutesFrom($routeFilePathInUse);
204
    }
205
206
    /**
207
     * Load custom routes file.
208
     *
209
     * @param  Router  $router
210
     * @return void
211
     */
212
    public function setupCustomRoutes(Router $router)
213
    {
214
        // if the custom routes file is published, register its routes
215
        if (file_exists(base_path().$this->customRoutesFilePath)) {
216
            $this->loadRoutesFrom(base_path().$this->customRoutesFilePath);
217
        }
218
    }
219
220
    public function loadViewNamespace($domain, $namespace)
221
    {
222
        ViewNamespaces::addFor($domain, $namespace);
223
    }
224
225
    public function loadViewsWithFallbacks($dir, $namespace = null)
226
    {
227
        $customFolder = resource_path('views/vendor/backpack/'.$dir);
228
        $vendorFolder = realpath(__DIR__.'/resources/views/'.$dir);
229
        $namespace = $namespace ?? $dir;
230
231
        // first the published/overwritten views (in case they have any changes)
232
        if (file_exists($customFolder)) {
233
            $this->loadViewsFrom($customFolder, $namespace);
234
        }
235
        // then the stock views that come with the package, in case a published view might be missing
236
        $this->loadViewsFrom($vendorFolder, $namespace);
237
    }
238
239
    protected function mergeConfigsFromDirectory($dir)
240
    {
241
        $configs = scandir(__DIR__."/config/backpack/$dir/");
242
        $configs = array_diff($configs, ['.', '..']);
243
244
        if (! count($configs)) {
245
            return;
246
        }
247
248
        foreach ($configs as $configFile) {
249
            $this->mergeConfigFrom(
250
                __DIR__."/config/backpack/$dir/$configFile",
251
                "backpack.$dir.".substr($configFile, 0, strrpos($configFile, '.'))
252
            );
253
        }
254
    }
255
256
    public function loadConfigs()
257
    {
258
        // use the vendor configuration file as fallback
259
        $this->mergeConfigFrom(__DIR__.'/config/backpack/crud.php', 'backpack.crud');
260
        $this->mergeConfigFrom(__DIR__.'/config/backpack/base.php', 'backpack.base');
261
        $this->mergeConfigFrom(__DIR__.'/config/backpack/ui.php', 'backpack.ui');
262
        $this->mergeConfigsFromDirectory('operations');
263
264
        // add the root disk to filesystem configuration
265
        app()->config['filesystems.disks.'.config('backpack.base.root_disk_name')] = [
266
            'driver' => 'local',
267
            'root' => base_path(),
268
        ];
269
270
        /*
271
         * Backpack login differs from the standard Laravel login.
272
         * As such, Backpack uses its own authentication provider, password broker and guard.
273
         *
274
         * THe process below adds those configuration values on top of whatever is in config/auth.php.
275
         * Developers can overwrite the backpack provider, password broker or guard by adding a
276
         * provider/broker/guard with the "backpack" name inside their config/auth.php file.
277
         * Or they can use another provider/broker/guard entirely, by changing the corresponding
278
         * value inside config/backpack/base.php
279
         */
280
281
        // add the backpack_users authentication provider to the configuration
282
        app()->config['auth.providers'] = app()->config['auth.providers'] +
283
            [
284
                'backpack' => [
285
                    'driver' => 'eloquent',
286
                    'model' => config('backpack.base.user_model_fqn'),
287
                ],
288
            ];
289
290
        // add the backpack_users password broker to the configuration
291
        $laravelAuthPasswordBrokers = app()->config['auth.passwords'];
292
        $laravelFirstPasswordBroker = is_array($laravelAuthPasswordBrokers) && current($laravelAuthPasswordBrokers) ?
293
                                        current($laravelAuthPasswordBrokers)['table'] :
294
                                        '';
295
296
        $backpackPasswordBrokerTable = config('backpack.base.password_resets_table') ??
297
                                        config('auth.passwords.users.table') ??
298
                                        $laravelFirstPasswordBroker;
299
300
        app()->config['auth.passwords'] = $laravelAuthPasswordBrokers +
301
        [
302
            'backpack' => [
303
                'provider' => 'backpack',
304
                'table' => $backpackPasswordBrokerTable,
305
                'expire' => config('backpack.base.password_recovery_token_expiration', 60),
306
                'throttle' => config('backpack.base.password_recovery_throttle_notifications'),
307
            ],
308
        ];
309
310
        // add the backpack_users guard to the configuration
311
        app()->config['auth.guards'] = app()->config['auth.guards'] +
312
            [
313
                'backpack' => [
314
                    'driver' => 'session',
315
                    'provider' => 'backpack',
316
                ],
317
            ];
318
    }
319
320
    public function loadViewComponents()
321
    {
322
        $this->app->afterResolving(BladeCompiler::class, function () {
323
            Blade::componentNamespace('Backpack\\CRUD\\app\\View\\Components', 'backpack');
324
        });
325
    }
326
327
    /**
328
     * Register dynamic Blade components from the Components directory.
329
     *
330
     * Any Blade component classes that are in that directory will be registered
331
     * as dynamic components with the 'bp-{component-name}' prefix.
332
     */
333
    private function registerDynamicBladeComponents()
334
    {
335
        $path = __DIR__.'/app/View/Components';
336
        $namespace = 'Backpack\\CRUD\\app\\View\\Components';
337
338
        if (! is_dir($path)) {
339
            return;
340
        }
341
342
        foreach (File::allFiles($path) as $file) {
343
            $relativePath = str_replace(
344
                ['/', '.php'],
345
                ['\\', ''],
346
                Str::after($file->getRealPath(), realpath($path).DIRECTORY_SEPARATOR)
347
            );
348
349
            $class = $namespace.'\\'.$relativePath;
350
351
            // Check if the class exists and is a subclass of Illuminate\View\Component
352
            // This ensures that only valid Blade components are registered.
353
            if (class_exists($class) && is_subclass_of($class, \Illuminate\View\Component::class)) {
354
                Blade::component('bp-'.Str::kebab(class_basename($class)), $class);
355
            }
356
        }
357
    }
358
359
    /**
360
     * Load the Backpack helper methods, for convenience.
361
     */
362
    public function loadHelpers()
363
    {
364
        require_once __DIR__.'/helpers.php';
365
    }
366
367
    /**
368
     * Get the services provided by the provider.
369
     *
370
     * @return array
371
     */
372
    public function provides()
373
    {
374
        return ['widgets', 'BackpackViewNamespaces', 'DatabaseSchema', 'UploadersRepository', 'CrudManager'];
375
    }
376
377
    private function registerBackpackErrorViews()
378
    {
379
        // register the backpack error when the exception handler is resolved from the container
380
        $this->callAfterResolving(ExceptionHandler::class, function ($handler) {
381
            if (! Str::startsWith(request()->path(), config('backpack.base.route_prefix'))) {
382
                return;
383
            }
384
385
            // parse the namespaces set in config
386
            [$themeNamespace, $themeFallbackNamespace] = (function () {
387
                $themeNamespace = config('backpack.ui.view_namespace');
388
                $themeFallbackNamespace = config('backpack.ui.view_namespace_fallback');
389
390
                return [
391
                    Str::endsWith($themeNamespace, '::') ? substr($themeNamespace, 0, -2) : substr($themeNamespace, 0, -1),
392
                    Str::endsWith($themeFallbackNamespace, '::') ? substr($themeFallbackNamespace, 0, -2) : substr($themeFallbackNamespace, 0, -1),
393
                ];
394
            })();
395
396
            $viewFinderHints = app('view')->getFinder()->getHints();
397
398
            // here we are going to generate the paths array containing:
399
            // - theme paths
400
            // - fallback theme paths
401
            // - ui path
402
            $themeErrorPaths = $viewFinderHints[$themeNamespace] ?? [];
403
            $themeErrorPaths = $themeNamespace === $themeFallbackNamespace ? $themeErrorPaths :
404
                array_merge($viewFinderHints[$themeFallbackNamespace] ?? [], $themeErrorPaths);
405
            $uiErrorPaths = [base_path('vendor/backpack/crud/src/resources/views/ui')];
406
            $themeErrorPaths = array_merge($themeErrorPaths, $uiErrorPaths);
407
408
            // merge the paths array with the view.paths defined in the application
409
            app('config')->set('view.paths', array_merge($themeErrorPaths, config('view.paths', [])));
410
        });
411
    }
412
}
413