Passed
Push — 1.2 ( f5cef1...6fd641 )
by Quentin
14:28 queued 04:42
created

TwillServiceProvider::requireHelpers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 6
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 8
rs 10
1
<?php
2
3
namespace A17\Twill;
4
5
use A17\Twill\Commands\Build;
6
use A17\Twill\Commands\CreateSuperAdmin;
7
use A17\Twill\Commands\GenerateBlocks;
8
use A17\Twill\Commands\Install;
9
use A17\Twill\Commands\ModuleMake;
10
use A17\Twill\Commands\RefreshLQIP;
11
use A17\Twill\Commands\Update;
12
use A17\Twill\Http\ViewComposers\ActiveNavigation;
13
use A17\Twill\Http\ViewComposers\CurrentUser;
14
use A17\Twill\Http\ViewComposers\FilesUploaderConfig;
15
use A17\Twill\Http\ViewComposers\MediasUploaderConfig;
16
use A17\Twill\Models\Block;
17
use A17\Twill\Models\File;
18
use A17\Twill\Models\Media;
19
use A17\Twill\Models\User;
20
use A17\Twill\Services\FileLibrary\FileService;
21
use A17\Twill\Services\MediaLibrary\ImageService;
22
use Barryvdh\Debugbar\Facade as Debugbar;
23
use Barryvdh\Debugbar\ServiceProvider as DebugbarServiceProvider;
24
use Cartalyst\Tags\TagsServiceProvider;
25
use Dimsav\Translatable\TranslatableServiceProvider;
26
use Illuminate\Database\Eloquent\Relations\Relation;
27
use Illuminate\Filesystem\Filesystem;
28
use Illuminate\Foundation\AliasLoader;
29
use Illuminate\Support\Facades\View;
30
use Illuminate\Support\ServiceProvider;
31
use Lsrur\Inspector\Facade\Inspector;
32
use Lsrur\Inspector\InspectorServiceProvider;
33
use Spatie\Activitylog\ActivitylogServiceProvider;
34
35
class TwillServiceProvider extends ServiceProvider
36
{
37
38
    /**
39
     * The Twill version.
40
     *
41
     * @var string
42
     */
43
    const VERSION = '1.2.2';
44
45
    /**
46
     * Service providers to be registered.
47
     *
48
     * @var string[]
49
     */
50
    protected $providers = [
51
        RouteServiceProvider::class,
52
        AuthServiceProvider::class,
53
        ValidationServiceProvider::class,
54
        TranslatableServiceProvider::class,
55
        TagsServiceProvider::class,
56
        ActivitylogServiceProvider::class
57
    ];
58
59
    private $migrationsCounter = 0;
60
61
    /**
62
     * Bootstraps the package services.
63
     *
64
     * @return void
65
     */
66
    public function boot()
67
    {
68
        $this->requireHelpers();
69
70
        $this->publishConfigs();
71
        $this->publishMigrations();
72
        $this->publishAssets();
73
74
        $this->registerCommands();
75
76
        $this->registerAndPublishViews();
77
78
        $this->extendBlade();
79
        $this->addViewComposers();
80
    }
81
82
    /**
83
     * @return void
84
     */
85
    private function requireHelpers()
86
    {
87
        require_once __DIR__ . '/Helpers/routes_helpers.php';
88
        require_once __DIR__ . '/Helpers/i18n_helpers.php';
89
        require_once __DIR__ . '/Helpers/media_library_helpers.php';
90
        require_once __DIR__ . '/Helpers/frontend_helpers.php';
91
        require_once __DIR__ . '/Helpers/migrations_helpers.php';
92
        require_once __DIR__ . '/Helpers/helpers.php';
93
    }
94
95
    /**
96
     * Registers the package services.
97
     *
98
     * @return void
99
     */
100
    public function register()
101
    {
102
        $this->mergeConfigs();
103
104
        $this->registerProviders();
105
        $this->registerAliases();
106
107
        Relation::morphMap([
108
            'users' => User::class,
109
            'media' => Media::class,
110
            'files' => File::class,
111
            'blocks' => Block::class,
112
        ]);
113
114
        config(['twill.version' => $this->version()]);
115
    }
116
117
    /**
118
     * Registers the package service providers.
119
     *
120
     * @return void
121
     */
122
    private function registerProviders()
123
    {
124
        foreach ($this->providers as $provider) {
125
            $this->app->register($provider);
126
        }
127
128
        if ($this->app->environment('development', 'local', 'staging')) {
129
            if (config('twill.debug.use_inspector', false)) {
130
                $this->app->register(InspectorServiceProvider::class);
131
            } else {
132
                $this->app->register(DebugbarServiceProvider::class);
133
            }
134
        }
135
136
        if (config('twill.enabled.media-library')) {
137
            $this->app->singleton('imageService', function () {
138
                return $this->app->make(config('twill.media_library.image_service'));
139
            });
140
        }
141
142
        if (config('twill.enabled.file-library')) {
143
            $this->app->singleton('fileService', function () {
144
                return $this->app->make(config('twill.file_library.file_service'));
145
            });
146
        }
147
    }
148
149
    /**
150
     * Registers the package facade aliases.
151
     *
152
     * @return void
153
     */
154
    private function registerAliases()
155
    {
156
        $loader = AliasLoader::getInstance();
157
158
        if (config('twill.debug.use_inspector', false)) {
159
            $loader->alias('Inspector', Inspector::class);
160
        } else {
161
            $loader->alias('Debugbar', Debugbar::class);
162
        }
163
164
        if (config('twill.enabled.media-library')) {
165
            $loader->alias('ImageService', ImageService::class);
166
        }
167
168
        if (config('twill.enabled.file-library')) {
169
            $loader->alias('FileService', FileService::class);
170
        }
171
172
    }
173
174
    /**
175
     * Defines the package configuration files for publishing.
176
     *
177
     * @return void
178
     */
179
    private function publishConfigs()
180
    {
181
        if (config('twill.enabled.users-management')) {
182
            config(['auth.providers.twill_users' => [
183
                'driver' => 'eloquent',
184
                'model' => User::class,
185
            ]]);
186
187
            config(['auth.guards.twill_users' => [
188
                'driver' => 'session',
189
                'provider' => 'twill_users',
190
            ]]);
191
192
            config(['auth.passwords.twill_users' => [
193
                'provider' => 'twill_users',
194
                'table' => config('twill.password_resets_table', 'twill_password_resets'),
195
                'expire' => 60,
196
            ]]);
197
        }
198
199
        config(['activitylog.enabled' => config('twill.enabled.dashboard') ? true : config('twill.enabled.activitylog')]);
200
        config(['activitylog.subject_returns_soft_deleted_models' => true]);
201
202
        config(['analytics.service_account_credentials_json' => config('twill.dashboard.analytics.service_account_credentials_json', storage_path('app/analytics/service-account-credentials.json'))]);
203
204
        $this->publishes([__DIR__ . '/../config/twill-publish.php' => config_path('twill.php')], 'config');
205
        $this->publishes([__DIR__ . '/../config/twill-navigation.php' => config_path('twill-navigation.php')], 'config');
206
        $this->publishes([__DIR__ . '/../config/translatable.php' => config_path('translatable.php')], 'config');
207
    }
208
209
    /**
210
     * Merges the package configuration files into the given configuration namespaces.
211
     *
212
     * @return void
213
     */
214
    private function mergeConfigs()
215
    {
216
        $this->mergeConfigFrom(__DIR__ . '/../config/twill.php', 'twill');
217
        $this->mergeConfigFrom(__DIR__ . '/../config/frontend.php', 'twill.frontend');
218
        $this->mergeConfigFrom(__DIR__ . '/../config/debug.php', 'twill.debug');
219
        $this->mergeConfigFrom(__DIR__ . '/../config/seo.php', 'twill.seo');
220
        $this->mergeConfigFrom(__DIR__ . '/../config/blocks.php', 'twill.block_editor');
221
        $this->mergeConfigFrom(__DIR__ . '/../config/enabled.php', 'twill.enabled');
222
        $this->mergeConfigFrom(__DIR__ . '/../config/file-library.php', 'twill.file_library');
223
        $this->mergeConfigFrom(__DIR__ . '/../config/media-library.php', 'twill.media_library');
224
        $this->mergeConfigFrom(__DIR__ . '/../config/imgix.php', 'twill.imgix');
225
        $this->mergeConfigFrom(__DIR__ . '/../config/glide.php', 'twill.glide');
226
        $this->mergeConfigFrom(__DIR__ . '/../config/cloudfront.php', 'services');
227
        $this->mergeConfigFrom(__DIR__ . '/../config/dashboard.php', 'twill.dashboard');
228
        $this->mergeConfigFrom(__DIR__ . '/../config/disks.php', 'filesystems.disks');
229
    }
230
231
    /**
232
     * Defines the package migration files for publishing.
233
     *
234
     * @return void
235
     */
236
    private function publishMigrations()
237
    {
238
        $migrations = ['CreateTagsTables', 'CreateBlocksTable', 'CreateRelatedTable'];
239
240
        $optionalMigrations = [
241
            'CreateTwillUsersTables' => 'users-management',
242
            'CreateTwillActivityLogTable' => 'activitylog',
243
            'CreateFilesTables' => 'file-library',
244
            'CreateMediasTables' => 'media-library',
245
            'CreateFeaturesTable' => 'buckets',
246
            'CreateSettingsTable' => 'settings',
247
        ];
248
249
        // The updatesMigrations array must include new migrations that should
250
        // be applied after minor and patch updates of Twill in a Laravel codebase.
251
        // When releasing a major version of Twill, we can move those up into
252
        // the optionalMigrations array above and keep this array empty until
253
        // a new migration is needed in a non breaking change version.
254
        $updatesMigations = [
255
            'AddTwoFactorAuthColumnsToTwillUsers' => 'users-2fa',
256
            'ChangeLocaleColumnInTwillFileables' => 'file-library',
257
            'AddLocaleColumnToTwillMediables' => 'media-library',
258
        ];
259
260
        if ($this->app->runningInConsole()) {
261
            foreach ($migrations as $migration) {
262
                $this->publishMigration($migration);
263
            }
264
265
            foreach ($optionalMigrations as $migration => $feature) {
266
                if (config('twill.enabled.' . $feature)) {
267
                    $this->publishMigration($migration);
268
                }
269
            }
270
271
            foreach ($updatesMigations as $migration => $feature) {
272
                if (config('twill.enabled.' . $feature)) {
273
                    $this->publishMigration($migration, 'twill-updates-migrations');
274
                }
275
            }
276
        }
277
    }
278
279
    /**
280
     * @param string $migration
281
     * @return void
282
     */
283
    private function publishMigration($migration, $publishKey = null)
284
    {
285
        $files = new Filesystem;
286
        $this->migrationsCounter += 1;
287
288
        if (!class_exists($migration)) {
289
            // Verify that migration doesn't exist
290
            $migration_file = database_path('migrations/*_' . snake_case($migration) . '.php');
0 ignored issues
show
Deprecated Code introduced by
The function snake_case() has been deprecated: Str::snake() should be used directly instead. Will be removed in Laravel 6.0. ( Ignorable by Annotation )

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

290
            $migration_file = database_path('migrations/*_' . /** @scrutinizer ignore-deprecated */ snake_case($migration) . '.php');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
291
            if (empty($files->glob($migration_file))) {
292
                $timestamp = date('Y_m_d_', time()) . (30000 + $this->migrationsCounter);
293
                $migrationSourcePath = __DIR__ . '/../migrations/' . snake_case($migration) . '.php';
0 ignored issues
show
Deprecated Code introduced by
The function snake_case() has been deprecated: Str::snake() should be used directly instead. Will be removed in Laravel 6.0. ( Ignorable by Annotation )

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

293
                $migrationSourcePath = __DIR__ . '/../migrations/' . /** @scrutinizer ignore-deprecated */ snake_case($migration) . '.php';

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
294
                $migrationOutputPath = database_path('migrations/' . $timestamp . '_' . snake_case($migration) . '.php');
0 ignored issues
show
Deprecated Code introduced by
The function snake_case() has been deprecated: Str::snake() should be used directly instead. Will be removed in Laravel 6.0. ( Ignorable by Annotation )

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

294
                $migrationOutputPath = database_path('migrations/' . $timestamp . '_' . /** @scrutinizer ignore-deprecated */ snake_case($migration) . '.php');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
295
296
                $this->publishes([
297
                    $migrationSourcePath => $migrationOutputPath,
298
                ], 'migrations');
299
300
                if ($publishKey) {
301
                    $this->publishes([
302
                        $migrationSourcePath => $migrationOutputPath,
303
                    ], $publishKey);
304
                }
305
            }
306
        }
307
    }
308
309
    /**
310
     * @return void
311
     */
312
    private function publishAssets()
313
    {
314
        $this->publishes([
315
            __DIR__ . '/../dist' => public_path(),
316
        ], 'assets');
317
    }
318
319
    /**
320
     * @return void
321
     */
322
    private function registerAndPublishViews()
323
    {
324
        $viewPath = __DIR__ . '/../views';
325
326
        $this->loadViewsFrom($viewPath, 'twill');
327
        $this->publishes([$viewPath => resource_path('views/vendor/twill')], 'views');
328
    }
329
330
    /**
331
     * @return void
332
     */
333
    private function registerCommands()
334
    {
335
        $this->commands([
336
            Install::class,
337
            ModuleMake::class,
338
            CreateSuperAdmin::class,
339
            RefreshLQIP::class,
340
            GenerateBlocks::class,
341
            Build::class,
342
            Update::class,
343
        ]);
344
    }
345
346
    /**
347
     * @param string $view
348
     * @param string $expression
349
     * @return string
350
     */
351
    private function includeView($view, $expression)
352
    {
353
        list($name) = str_getcsv($expression, ',', '\'');
354
355
        $partialNamespace = view()->exists('admin.' . $view . $name) ? 'admin.' : 'twill::';
356
357
        $view = $partialNamespace . $view . $name;
358
359
        $expression = explode(',', $expression);
360
        array_shift($expression);
361
        $expression = "(" . implode(',', $expression) . ")";
362
        if ($expression === "()") {
363
            $expression = '([])';
364
        }
365
        return "<?php echo \$__env->make('{$view}', array_except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render(); ?>";
366
    }
367
368
    /**
369
     * Defines the package additional Blade Directives.
370
     *
371
     * @return void
372
     */
373
    private function extendBlade()
374
    {
375
        $blade = $this->app['view']->getEngineResolver()->resolve('blade')->getCompiler();
376
377
        $blade->directive('dd', function ($param) {
378
            return "<?php dd({$param}); ?>";
379
        });
380
381
        $blade->directive('dumpData', function ($data) {
382
            return sprintf("<?php (new Symfony\Component\VarDumper\VarDumper)->dump(%s); exit; ?>",
383
                null != $data ? $data : "get_defined_vars()");
384
        });
385
386
        $blade->directive('formField', function ($expression) use ($blade) {
0 ignored issues
show
Unused Code introduced by
The import $blade is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
387
            return $this->includeView('partials.form._', $expression);
388
        });
389
390
        $blade->directive('partialView', function ($expression) use ($blade) {
0 ignored issues
show
Unused Code introduced by
The import $blade is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
391
392
            $expressionAsArray = str_getcsv($expression, ',', '\'');
393
394
            list($moduleName, $viewName) = $expressionAsArray;
395
            $partialNamespace = 'twill::partials';
396
397
            $viewModule = "'admin.'.$moduleName.'.{$viewName}'";
398
            $viewApplication = "'admin.partials.{$viewName}'";
399
            $viewModuleTwill = "'twill::'.$moduleName.'.{$viewName}'";
400
            $view = $partialNamespace . "." . $viewName;
401
402
            if (!isset($moduleName) || is_null($moduleName)) {
403
                $viewModule = $viewApplication;
404
            }
405
406
            $expression = explode(',', $expression);
407
            $expression = array_slice($expression, 2);
408
            $expression = "(" . implode(',', $expression) . ")";
409
            if ($expression === "()") {
410
                $expression = '([])';
411
            }
412
413
            return "<?php
414
            if( view()->exists($viewModule)) {
415
                echo \$__env->make($viewModule, array_except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
416
            } elseif( view()->exists($viewApplication)) {
417
                echo \$__env->make($viewApplication, array_except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
418
            } elseif( view()->exists($viewModuleTwill)) {
419
                echo \$__env->make($viewModuleTwill, array_except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
420
            } elseif( view()->exists('$view')) {
421
                echo \$__env->make('$view', array_except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
422
            }
423
            ?>";
424
        });
425
426
        $blade->directive('pushonce', function ($expression) {
427
            list($pushName, $pushSub) = explode(':', trim(substr($expression, 1, -1)));
428
            $key = '__pushonce_' . $pushName . '_' . str_replace('-', '_', $pushSub);
429
            return "<?php if(! isset(\$__env->{$key})): \$__env->{$key} = 1; \$__env->startPush('{$pushName}'); ?>";
430
        });
431
432
        $blade->directive('endpushonce', function () {
433
            return '<?php $__env->stopPush(); endif; ?>';
434
        });
435
    }
436
437
    /**
438
     * Registers the package additional View Composers.
439
     *
440
     * @return void
441
     */
442
    private function addViewComposers()
443
    {
444
        if (config('twill.enabled.users-management')) {
445
            View::composer(['admin.*', 'twill::*'], CurrentUser::class);
446
        }
447
448
        if (config('twill.enabled.media-library')) {
449
            View::composer('twill::layouts.main', MediasUploaderConfig::class);
450
        }
451
452
        if (config('twill.enabled.file-library')) {
453
            View::composer('twill::layouts.main', FilesUploaderConfig::class);
454
        }
455
456
        View::composer('twill::partials.navigation.*', ActiveNavigation::class);
457
458
        View::composer(['admin.*', 'templates.*', 'twill::*'], function ($view) {
459
            $with = array_merge([
460
                'renderForBlocks' => false,
461
                'renderForModal' => false,
462
            ], $view->getData());
463
464
            return $view->with($with);
465
        });
466
    }
467
468
    /**
469
     * Registers and publishes the package additional translations.
470
     *
471
     * @return void
472
     */
473
    private function registerAndPublishTranslations()
474
    {
475
        $translationPath = __DIR__ . '/../lang';
476
477
        $this->loadTranslationsFrom($translationPath, 'twill');
478
        $this->publishes([$translationPath => resource_path('lang/vendor/twill')], 'translations');
479
    }
480
481
    /**
482
     * Get the version number of Twill.
483
     *
484
     * @return string
485
     */
486
    public function version()
487
    {
488
        return static::VERSION;
489
    }
490
}
491