Passed
Pull Request — 2.x (#1042)
by Antonio Carlos
05:47
created

TwillServiceProvider::publishAssets()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace A17\Twill;
4
5
use Exception;
6
use A17\Twill\Commands\BlockMake;
7
use A17\Twill\Commands\Build;
8
use A17\Twill\Commands\CapsuleInstall;
9
use A17\Twill\Commands\CreateSuperAdmin;
10
use A17\Twill\Commands\Dev;
11
use A17\Twill\Commands\GenerateBlocks;
12
use A17\Twill\Commands\Install;
13
use A17\Twill\Commands\ListBlocks;
14
use A17\Twill\Commands\ListIcons;
15
use A17\Twill\Commands\MakeCapsule;
16
use A17\Twill\Commands\ModuleMake;
17
use A17\Twill\Commands\ModuleMakeDeprecated;
18
use A17\Twill\Commands\RefreshLQIP;
19
use A17\Twill\Commands\SyncLang;
20
use A17\Twill\Commands\Update;
21
use A17\Twill\Http\ViewComposers\ActiveNavigation;
22
use A17\Twill\Http\ViewComposers\CurrentUser;
23
use A17\Twill\Http\ViewComposers\FilesUploaderConfig;
24
use A17\Twill\Http\ViewComposers\Localization;
25
use A17\Twill\Http\ViewComposers\MediasUploaderConfig;
26
use A17\Twill\Models\Block;
27
use A17\Twill\Models\File;
28
use A17\Twill\Models\Media;
29
use A17\Twill\Models\User;
30
use A17\Twill\Services\Capsules\HasCapsules;
31
use A17\Twill\Services\FileLibrary\FileService;
32
use A17\Twill\Services\MediaLibrary\ImageService;
33
use Astrotomic\Translatable\TranslatableServiceProvider;
34
use Cartalyst\Tags\TagsServiceProvider;
35
use Illuminate\Database\Eloquent\Relations\Relation;
36
use Illuminate\Foundation\AliasLoader;
37
use Illuminate\Support\Facades\View;
38
use Illuminate\Support\ServiceProvider;
39
use Illuminate\Support\Str;
40
use Spatie\Activitylog\ActivitylogServiceProvider;
41
use PragmaRX\Google2FAQRCode\Google2FA as Google2FAQRCode;
42
43
class TwillServiceProvider extends ServiceProvider
44
{
45
    use HasCapsules;
0 ignored issues
show
Bug introduced by
The trait A17\Twill\Services\Capsules\HasCapsules requires the property $command which is not provided by A17\Twill\TwillServiceProvider.
Loading history...
46
47
    /**
48
     * The Twill version.
49
     *
50
     * @var string
51
     */
52
    const VERSION = '2.4.0';
53
54
    /**
55
     * Service providers to be registered.
56
     *
57
     * @var string[]
58
     */
59
    protected $providers = [
60
        RouteServiceProvider::class,
61
        AuthServiceProvider::class,
62
        ValidationServiceProvider::class,
63
        TranslatableServiceProvider::class,
64
        TagsServiceProvider::class,
65
        ActivitylogServiceProvider::class,
66
        CapsulesServiceProvider::class,
67
    ];
68
69 73
    private $migrationsCounter = 0;
0 ignored issues
show
introduced by
The private property $migrationsCounter is not used, and could be removed.
Loading history...
70
71 73
    /**
72
     * Bootstraps the package services.
73 73
     *
74 73
     * @return void
75 73
     */
76
    public function boot()
77 73
    {
78
        $this->requireHelpers();
79 73
80 73
        $this->publishConfigs();
81
        $this->publishMigrations();
82 73
        $this->publishAssets();
83 73
84 73
        $this->registerCommands();
85
86
        $this->registerAndPublishViews();
87
        $this->registerAndPublishTranslations();
88
89 73
        $this->extendBlade();
90
        $this->addViewComposers();
91 73
92 73
        $this->check2FA();
93 73
    }
94 73
95 73
    /**
96 73
     * @return void
97 73
     */
98
    private function requireHelpers()
99
    {
100
        require_once __DIR__ . '/Helpers/routes_helpers.php';
101
        require_once __DIR__ . '/Helpers/i18n_helpers.php';
102
        require_once __DIR__ . '/Helpers/media_library_helpers.php';
103
        require_once __DIR__ . '/Helpers/frontend_helpers.php';
104 73
        require_once __DIR__ . '/Helpers/migrations_helpers.php';
105
        require_once __DIR__ . '/Helpers/helpers.php';
106 73
    }
107
108 73
    /**
109 73
     * Registers the package services.
110
     *
111 73
     * @return void
112 73
     */
113
    public function register()
114
    {
115
        $this->mergeConfigs();
116
117
        $this->registerProviders();
118 73
        $this->registerAliases();
119 73
120
        Relation::morphMap([
121
            'users' => User::class,
122
            'media' => Media::class,
123
            'files' => File::class,
124
            'blocks' => Block::class,
125
        ]);
126 73
127
        config(['twill.version' => $this->version()]);
128 73
    }
129 73
130
    /**
131
     * Registers the package service providers.
132 73
     *
133 73
     * @return void
134 8
     */
135 73
    private function registerProviders()
136
    {
137
        foreach ($this->providers as $provider) {
138 73
            $this->app->register($provider);
139 73
        }
140 3
141 73
        if (config('twill.enabled.media-library')) {
142
            $this->app->singleton('imageService', function () {
143 73
                return $this->app->make(config('twill.media_library.image_service'));
144
            });
145
        }
146
147
        if (config('twill.enabled.file-library')) {
148
            $this->app->singleton('fileService', function () {
149
                return $this->app->make(config('twill.file_library.file_service'));
150 73
            });
151
        }
152 73
    }
153
154 73
    /**
155 73
     * Registers the package facade aliases.
156
     *
157
     * @return void
158 73
     */
159 73
    private function registerAliases()
160
    {
161
        $loader = AliasLoader::getInstance();
162 73
163
        if (config('twill.enabled.media-library')) {
164
            $loader->alias('ImageService', ImageService::class);
165
        }
166
167
        if (config('twill.enabled.file-library')) {
168
            $loader->alias('FileService', FileService::class);
169 73
        }
170
171 73
    }
172 73
173 73
    /**
174
     * Defines the package configuration files for publishing.
175
     *
176
     * @return void
177 73
     */
178 73
    private function publishConfigs()
179
    {
180
        if (config('twill.enabled.users-management')) {
181
            config(['auth.providers.twill_users' => [
182 73
                'driver' => 'eloquent',
183 73
                'model' => User::class,
184 73
            ]]);
185 73
186
            config(['auth.guards.twill_users' => [
187
                'driver' => 'session',
188
                'provider' => 'twill_users',
189 73
            ]]);
190 73
191
            config(['auth.passwords.twill_users' => [
192 73
                'provider' => 'twill_users',
193
                'table' => config('twill.password_resets_table', 'twill_password_resets'),
194 73
                'expire' => 60,
195 73
            ]]);
196 73
        }
197 73
198
        config(['activitylog.enabled' => config('twill.enabled.dashboard') ? true : config('twill.enabled.activitylog')]);
199
        config(['activitylog.subject_returns_soft_deleted_models' => true]);
200
201
        config(['analytics.service_account_credentials_json' => config('twill.dashboard.analytics.service_account_credentials_json', storage_path('app/analytics/service-account-credentials.json'))]);
202
203
        $this->publishes([__DIR__ . '/../config/twill-publish.php' => config_path('twill.php')], 'config');
204 73
        $this->publishes([__DIR__ . '/../config/twill-navigation.php' => config_path('twill-navigation.php')], 'config');
205
        $this->publishes([__DIR__ . '/../config/translatable.php' => config_path('translatable.php')], 'config');
206 73
    }
207 73
208 73
    /**
209 73
     * Merges the package configuration files into the given configuration namespaces.
210 73
     *
211 73
     * @return void
212 73
     */
213 73
    private function mergeConfigs()
214 73
    {
215 73
        $this->mergeConfigFrom(__DIR__ . '/../config/twill.php', 'twill');
216 73
        $this->mergeConfigFrom(__DIR__ . '/../config/frontend.php', 'twill.frontend');
217 73
        $this->mergeConfigFrom(__DIR__ . '/../config/debug.php', 'twill.debug');
218 73
        $this->mergeConfigFrom(__DIR__ . '/../config/seo.php', 'twill.seo');
219
        $this->mergeConfigFrom(__DIR__ . '/../config/blocks.php', 'twill.block_editor');
220 73
        $this->mergeConfigFrom(__DIR__ . '/../config/enabled.php', 'twill.enabled');
221 73
        $this->mergeConfigFrom(__DIR__ . '/../config/file-library.php', 'twill.file_library');
222 73
        $this->mergeConfigFrom(__DIR__ . '/../config/media-library.php', 'twill.media_library');
223
        $this->mergeConfigFrom(__DIR__ . '/../config/imgix.php', 'twill.imgix');
224
        $this->mergeConfigFrom(__DIR__ . '/../config/glide.php', 'twill.glide');
225 73
        $this->mergeConfigFrom(__DIR__ . '/../config/dashboard.php', 'twill.dashboard');
226 73
        $this->mergeConfigFrom(__DIR__ . '/../config/oauth.php', 'twill.oauth');
227 73
        $this->mergeConfigFrom(__DIR__ . '/../config/disks.php', 'filesystems.disks');
228
229
        if (config('twill.media_library.endpoint_type') === 'local'
230 73
            && config('twill.media_library.disk') === 'twill_media_library') {
231 73
            $this->setLocalDiskUrl('media');
232
        }
233 73
234
        if (config('twill.file_library.endpoint_type') === 'local'
235 73
            && config('twill.file_library.disk') === 'twill_file_library') {
236 73
            $this->setLocalDiskUrl('file');
237 73
        }
238 73
239 73
        $this->mergeConfigFrom(__DIR__ . '/../config/services.php', 'services');
240 73
    }
241
242 73
    private function setLocalDiskUrl($type)
243
    {
244 73
        config([
245
            'filesystems.disks.twill_' . $type . '_library.url' => request()->getScheme()
246 73
            . '://'
247 73
            . str_replace(['http://', 'https://'], '', config('app.url'))
248
            . '/storage/'
249
            . trim(config('twill.' . $type . '_library.local_path'), '/ '),
250 73
        ]);
251 73
    }
252 73
253
    private function publishMigrations()
254 73
    {
255 73
        if (config('twill.load_default_migrations', true)) {
256 73
            $this->loadMigrationsFrom(__DIR__ . '/../migrations/default');
257
        }
258 73
259
        $this->publishes([
260 73
            __DIR__ . '/../migrations/default' => database_path('migrations'),
261 69
        ], 'migrations');
262
263 69
        $this->publishOptionalMigration('users-2fa');
264 69
        $this->publishOptionalMigration('users-oauth');
265 69
    }
266
267 73
    private function publishOptionalMigration($feature)
268
    {
269
        if (config('twill.enabled.' . $feature, false)) {
270
            $this->loadMigrationsFrom(__DIR__ . '/../migrations/optional/' . $feature);
271
272 73
            $this->publishes([
273
                __DIR__ . '/../migrations/optional/' . $feature => database_path('migrations'),
274 73
            ], 'migrations');
275 73
        }
276 73
    }
277 73
278
    /**
279
     * @return void
280
     */
281
    private function publishAssets()
282 73
    {
283
        $this->publishes([
284 73
            __DIR__ . '/../dist' => public_path(),
285
        ], 'assets');
286 73
    }
287 73
288 73
    /**
289
     * @return void
290
     */
291
    private function registerAndPublishViews()
292
    {
293 73
        $viewPath = __DIR__ . '/../views';
294
295 73
        $this->loadViewsFrom($viewPath, 'twill');
296 73
        $this->publishes([$viewPath => resource_path('views/vendor/twill')], 'views');
297
    }
298
299
    /**
300
     * @return void
301
     */
302
    private function registerCommands()
303
    {
304
        $this->commands([
305
            Install::class,
306
            ModuleMake::class,
307
            MakeCapsule::class,
308
            ModuleMakeDeprecated::class,
309
            BlockMake::class,
310 73
            ListIcons::class,
311
            ListBlocks::class,
312
            CreateSuperAdmin::class,
313
            RefreshLQIP::class,
314
            GenerateBlocks::class,
315
            Build::class,
316
            Update::class,
317 5
            Dev::class,
318
            SyncLang::class,
319 5
            CapsuleInstall::class,
320
        ]);
321 5
    }
322
323 5
    /**
324
     * @param string $view
325 5
     * @param string $expression
326 5
     * @return string
327 5
     */
328 5
    private function includeView($view, $expression)
329 4
    {
330
        [$name] = str_getcsv($expression, ',', '\'');
331
332 5
        $partialNamespace = view()->exists('admin.' . $view . $name) ? 'admin.' : 'twill::';
333
334
        $view = $partialNamespace . $view . $name;
335
336
        $expression = explode(',', $expression);
337
        array_shift($expression);
338
        $expression = "(" . implode(',', $expression) . ")";
339
        if ($expression === "()") {
340 73
            $expression = '([])';
341
        }
342 73
343
        return "<?php echo \$__env->make('{$view}', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render(); ?>";
344 73
    }
345
346 73
    /**
347
     * Defines the package additional Blade Directives.
348 73
     *
349
     * @return void
350
     */
351 73
    private function extendBlade()
352
    {
353 73
        $blade = $this->app['view']->getEngineResolver()->resolve('blade')->getCompiler();
354 5
355 73
        $blade->directive('dd', function ($param) {
356
            return "<?php dd({$param}); ?>";
357 73
        });
358
359 3
        $blade->directive('dumpData', function ($data) {
360
            return sprintf("<?php (new Symfony\Component\VarDumper\VarDumper)->dump(%s); exit; ?>",
361 3
                null != $data ? $data : "get_defined_vars()");
362 3
        });
363
364 3
        $blade->directive('formField', function ($expression) {
365 3
            return $this->includeView('partials.form._', $expression);
366 3
        });
367 3
368
        $blade->directive('partialView', function ($expression) {
369 3
370
            $expressionAsArray = str_getcsv($expression, ',', '\'');
371
372
            [$moduleName, $viewName] = $expressionAsArray;
373 3
            $partialNamespace = 'twill::partials';
374 3
375 3
            $viewModule = "twillViewName($moduleName, '{$viewName}')";
376 3
            $viewApplication = "'admin.partials.{$viewName}'";
377 2
            $viewModuleTwill = "'twill::'.$moduleName.'.{$viewName}'";
378
            $view = $partialNamespace . "." . $viewName;
379
380 3
            if (!isset($moduleName) || is_null($moduleName)) {
381 3
                $viewModule = $viewApplication;
382 3
            }
383 3
384 3
            $expression = explode(',', $expression);
385 3
            $expression = array_slice($expression, 2);
386 3
            $expression = "(" . implode(',', $expression) . ")";
387 3
            if ($expression === "()") {
388 3
                $expression = '([])';
389
            }
390
391 73
            return "<?php
392
            if( view()->exists($viewModule)) {
393 73
                echo \$__env->make($viewModule, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
394 1
            } elseif( view()->exists($viewApplication)) {
395 1
                echo \$__env->make($viewApplication, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
396 1
            } elseif( view()->exists($viewModuleTwill)) {
397 73
                echo \$__env->make($viewModuleTwill, \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
398
            } elseif( view()->exists('$view')) {
399 73
                echo \$__env->make('$view', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->with{$expression}->render();
400 1
            }
401 73
            ?>";
402
        });
403 73
404 73
        $blade->directive('pushonce', function ($expression) {
405 73
            [$pushName, $pushSub] = explode(':', trim(substr($expression, 1, -1)));
406 73
            $key = '__pushonce_' . $pushName . '_' . str_replace('-', '_', $pushSub);
407 73
            return "<?php if(! isset(\$__env->{$key})): \$__env->{$key} = 1; \$__env->startPush('{$pushName}'); ?>";
408
        });
409 73
410 73
        $blade->directive('endpushonce', function () {
411 73
            return '<?php $__env->stopPush(); endif; ?>';
412 73
        });
413 73
414 73
        $blade->component('twill::partials.form.utils._fieldset', 'formFieldset');
415
        $blade->component('twill::partials.form.utils._columns', 'formColumns');
416
        $blade->component('twill::partials.form.utils._collapsed_fields', 'formCollapsedFields');
417 73
        $blade->component('twill::partials.form.utils._connected_fields', 'formConnectedFields');
418
        $blade->component('twill::partials.form.utils._inline_checkboxes', 'formInlineCheckboxes');
419
420
        if (method_exists($blade, 'aliasComponent')) {
421
            $blade->aliasComponent('twill::partials.form.utils._fieldset', 'formFieldset');
422
            $blade->aliasComponent('twill::partials.form.utils._columns', 'formColumns');
423
            $blade->aliasComponent('twill::partials.form.utils._collapsed_fields', 'formCollapsedFields');
424 73
            $blade->aliasComponent('twill::partials.form.utils._connected_fields', 'formConnectedFields');
425
            $blade->aliasComponent('twill::partials.form.utils._inline_checkboxes', 'formInlineCheckboxes');
426 73
        }
427 73
428
    }
429
430 73
    /**
431 73
     * Registers the package additional View Composers.
432
     *
433
     * @return void
434 73
     */
435 73
    private function addViewComposers()
436
    {
437
        if (config('twill.enabled.users-management')) {
438 73
            View::composer(['admin.*', 'twill::*'], CurrentUser::class);
439
        }
440 73
441 52
        if (config('twill.enabled.media-library')) {
442 52
            View::composer('twill::layouts.main', MediasUploaderConfig::class);
443
        }
444 52
445
        if (config('twill.enabled.file-library')) {
446 52
            View::composer('twill::layouts.main', FilesUploaderConfig::class);
447 73
        }
448
449 73
        View::composer('twill::partials.navigation.*', ActiveNavigation::class);
450 73
451
        View::composer(['admin.*', 'templates.*', 'twill::*'], function ($view) {
452
            $with = array_merge([
453
                'renderForBlocks' => false,
454
                'renderForModal' => false,
455
            ], $view->getData());
456
457 73
            return $view->with($with);
458
        });
459 73
460
        View::composer(['admin.*', 'twill::*'], Localization::class);
461 73
    }
462 73
463 73
    /**
464
     * Registers and publishes the package additional translations.
465
     *
466
     * @return void
467
     */
468
    private function registerAndPublishTranslations()
469
    {
470 73
        $translationPath = __DIR__ . '/../lang';
471
472 73
        $this->loadTranslationsFrom($translationPath, 'twill');
473
        $this->publishes([$translationPath => resource_path('lang/vendor/twill')], 'translations');
474
    }
475
476
    /**
477
     * Get the version number of Twill.
478
     *
479
     * @return string
480
     */
481
    public function version()
482
    {
483
        return static::VERSION;
484
    }
485
486
    /**
487
     * In case 2FA is enabled, we need to check if a QRCode compatible package is
488
     * installed.
489
     */
490
    public function check2FA()
491
    {
492
        if (!$this->app->runningInConsole() || !config('twill.enabled.users-2fa')) {
493
            return;
494
        }
495
496
        if (blank((new Google2FAQRCode())->getQrCodeService()))
497
        {
498
            throw new Exception(
499
                "Twill ERROR: As you have 2FA enabled, you also need to install a QRCode service package, please check https://github.com/antonioribeiro/google2fa-qrcode#built-in-qrcode-rendering-services"
500
            );
501
        }
502
    }
503
}
504