Passed
Push — fix/singleton-navigation ( 6c7e89...5a669f )
by Quentin
06:53 queued 30s
created

RouteServiceProvider::shouldPrefixRouteName()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 3
nc 4
nop 2
dl 0
loc 5
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace A17\Twill;
4
5
use A17\Twill\Services\Capsules\Manager;
6
use A17\Twill\Http\Controllers\Front\GlideController;
7
use A17\Twill\Http\Middleware\Impersonate;
8
use A17\Twill\Http\Middleware\Localization;
9
use A17\Twill\Http\Middleware\RedirectIfAuthenticated;
10
use A17\Twill\Http\Middleware\SupportSubdomainRouting;
11
use A17\Twill\Http\Middleware\ValidateBackHistory;
12
use A17\Twill\Services\Routing\HasRoutes;
13
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
14
use Illuminate\Routing\Router;
15
use Illuminate\Support\Arr;
16
use Illuminate\Support\Facades\Route;
17
use Illuminate\Support\Str;
18
19
class RouteServiceProvider extends ServiceProvider
20
{
21
    use HasRoutes;
22
23
    protected $namespace = 'A17\Twill\Http\Controllers';
24
25
    /**
26
     * Bootstraps the package services.
27
     *
28
     * @return void
29
     */
30
    public function boot()
31
    {
32
        $this->registerRouteMiddlewares($this->app->get('router'));
33
        $this->registerMacros();
34
        parent::boot();
35
    }
36
37
    /**
38
     * @param Router $router
39
     * @return void
40
     */
41
    public function map(Router $router)
42
    {
43
        $this->registerRoutePatterns();
44
45
        $this->registerCapsulesRoutes($router);
46
47
        $this->mapInternalRoutes(
48
            $router,
49
            $this->getRouteGroupOptions(),
50
            $this->getRouteMiddleware(),
51
            $this->supportSubdomainRouting()
52
        );
53
54
        $this->mapHostRoutes(
55
            $router,
56
            $this->getRouteGroupOptions(),
57
            $this->getRouteMiddleware(),
58
            $this->supportSubdomainRouting()
59
        );
60
    }
61
62
    private function mapHostRoutes(
63
        $router,
64
        $groupOptions,
65
        $middlewares,
66
        $supportSubdomainRouting,
67
        $namespace = null
0 ignored issues
show
Unused Code introduced by
The parameter $namespace is not used and could be removed. ( Ignorable by Annotation )

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

67
        /** @scrutinizer ignore-unused */ $namespace = null

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
68
    ) {
69
        $this->registerRoutes(
70
            $router,
71
            $groupOptions,
72
            $middlewares,
73
            $supportSubdomainRouting,
74
            config('twill.namespace', 'App') . '\Http\Controllers\Admin',
75
            base_path('routes/admin.php')
76
        );
77
    }
78
79
    private function mapInternalRoutes(
80
        $router,
81
        $groupOptions,
82
        $middlewares,
83
        $supportSubdomainRouting
84
    ) {
85
        $internalRoutes = function ($router) use (
86
            $middlewares,
87
            $supportSubdomainRouting
88
        ) {
89
            $router->group(['middleware' => $middlewares], function ($router) {
90
                require __DIR__ . '/../routes/admin.php';
91
            });
92
93
            $router->group(
94
                [
95
                    'middleware' => $supportSubdomainRouting
96
                    ? ['supportSubdomainRouting']
97
                    : [],
98
                ],
99
                function ($router) {
100
                    require __DIR__ . '/../routes/auth.php';
101
                }
102
            );
103
104
            $router->group(
105
                [
106
                    'middleware' => $this->app->environment('production')
107
                    ? ['twill_auth:twill_users']
108
                    : [],
109
                ],
110
                function ($router) {
111
                    require __DIR__ . '/../routes/templates.php';
112
                }
113
            );
114
        };
115
116
        $router->group(
117
            $groupOptions + [
118
                'namespace' => $this->namespace . '\Admin',
119
            ],
120
            function ($router) use ($internalRoutes, $supportSubdomainRouting) {
121
                $router->group(
122
                    [
123
                        'domain' => config('twill.admin_app_url'),
124
                    ],
125
                    $internalRoutes
126
                );
127
128
                if ($supportSubdomainRouting) {
129
                    $router->group(
130
                        [
131
                            'domain' =>
132
                            config('twill.admin_app_subdomain', 'admin') .
133
                            '.{subdomain}.' .
134
                            config('app.url'),
135
                        ],
136
                        $internalRoutes
137
                    );
138
                }
139
            }
140
        );
141
142
        if (config('twill.templates_on_frontend_domain')) {
143
            $router->group(
144
                [
145
                    'namespace' => $this->namespace . '\Admin',
146
                    'domain' => config('app.url'),
147
                    'middleware' => [
148
                        config('twill.admin_middleware_group', 'web'),
149
                    ],
150
                ],
151
                function ($router) {
152
                    $router->group(
153
                        [
154
                            'middleware' => $this->app->environment(
155
                                'production'
156
                            )
157
                            ? ['twill_auth:twill_users']
158
                            : [],
159
                        ],
160
                        function ($router) {
161
                            require __DIR__ . '/../routes/templates.php';
162
                        }
163
                    );
164
                }
165
            );
166
        }
167
168
        if (
169
            config('twill.media_library.image_service') ===
170
            'A17\Twill\Services\MediaLibrary\Glide'
171
        ) {
172
            $router
173
                ->get(
174
                    '/' . config('twill.glide.base_path') . '/{path}',
175
                    GlideController::class
176
                )
177
                ->where('path', '.*');
178
        }
179
    }
180
181
    /**
182
     * Register Route middleware.
183
     *
184
     * @param Router $router
185
     * @return void
186
     */
187
    private function registerRouteMiddlewares(Router $router)
0 ignored issues
show
Unused Code introduced by
The parameter $router is not used and could be removed. ( Ignorable by Annotation )

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

187
    private function registerRouteMiddlewares(/** @scrutinizer ignore-unused */ Router $router)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
188
    {
189
        Route::aliasMiddleware(
190
            'supportSubdomainRouting',
191
            SupportSubdomainRouting::class
192
        );
193
        Route::aliasMiddleware('impersonate', Impersonate::class);
194
        Route::aliasMiddleware(
195
            'twill_auth',
196
            \Illuminate\Auth\Middleware\Authenticate::class
197
        );
198
        Route::aliasMiddleware('twill_guest', RedirectIfAuthenticated::class);
199
        Route::aliasMiddleware(
200
            'validateBackHistory',
201
            ValidateBackHistory::class
202
        );
203
        Route::aliasMiddleware('localization', Localization::class);
204
    }
205
206
    /**
207
     * Registers Route macros.
208
     *
209
     * @return void
210
     */
211
    protected function registerMacros()
212
    {
213
        Route::macro('moduleShowWithPreview', function (
214
            $moduleName,
215
            $routePrefix = null,
216
            $controllerName = null
217
        ) {
218
            if ($routePrefix === null) {
219
                $routePrefix = $moduleName;
220
            }
221
222
            if ($controllerName === null) {
223
                $controllerName = ucfirst(Str::plural($moduleName));
224
            }
225
226
            $routePrefix = empty($routePrefix)
227
            ? '/'
228
            : (Str::startsWith($routePrefix, '/')
229
                ? $routePrefix
230
                : '/' . $routePrefix);
231
            $routePrefix = Str::endsWith($routePrefix, '/')
232
            ? $routePrefix
233
            : $routePrefix . '/';
234
235
            Route::name($moduleName . '.show')->get(
236
                $routePrefix . '{slug}',
237
                $controllerName . 'Controller@show'
238
            );
239
            Route::name($moduleName . '.preview')
240
                ->get(
241
                    '/admin-preview' . $routePrefix . '{slug}',
242
                    $controllerName . 'Controller@show'
243
                )
244
                ->middleware(['web', 'twill_auth:twill_users', 'can:list']);
245
        });
246
247
        Route::macro('module', function (
248
            $slug,
249
            $options = [],
250
            $resource_options = [],
251
            $resource = true
252
        ) {
253
            $slugs = explode('.', $slug);
254
            $prefixSlug = str_replace('.', '/', $slug);
255
            $_slug = Arr::last($slugs);
0 ignored issues
show
Unused Code introduced by
The assignment to $_slug is dead and can be removed.
Loading history...
256
            $className = implode(
257
                '',
258
                array_map(function ($s) {
259
                    return ucfirst(Str::singular($s));
260
                }, $slugs)
261
            );
262
263
            $customRoutes = $defaults = [
264
                'reorder',
265
                'publish',
266
                'bulkPublish',
267
                'browser',
268
                'feature',
269
                'bulkFeature',
270
                'tags',
271
                'preview',
272
                'restore',
273
                'bulkRestore',
274
                'forceDelete',
275
                'bulkForceDelete',
276
                'bulkDelete',
277
                'restoreRevision',
278
                'duplicate',
279
            ];
280
281
            if (isset($options['only'])) {
282
                $customRoutes = array_intersect(
283
                    $defaults,
284
                    (array) $options['only']
285
                );
286
            } elseif (isset($options['except'])) {
287
                $customRoutes = array_diff(
288
                    $defaults,
289
                    (array) $options['except']
290
                );
291
            }
292
293
            $lastRouteGroupName = RouteServiceProvider::getLastRouteGroupName();
294
295
            $groupPrefix = RouteServiceProvider::getGroupPrefix();
296
297
            // Check if name will be a duplicate, and prevent if needed/allowed
298
            if (RouteServiceProvider::shouldPrefixRouteName($groupPrefix, $lastRouteGroupName)) {
299
                $customRoutePrefix = "{$groupPrefix}.{$slug}";
300
                $resourceCustomGroupPrefix = "{$groupPrefix}.";
301
            } else {
302
                $customRoutePrefix = $slug;
303
304
                // Prevent Laravel from generating route names with duplication
305
                $resourceCustomGroupPrefix = '';
306
            }
307
308
            foreach ($customRoutes as $route) {
309
                $routeSlug = "{$prefixSlug}/{$route}";
310
                $mapping = [
311
                    'as' => $customRoutePrefix . ".{$route}",
312
                    'uses' => "{$className}Controller@{$route}",
313
                ];
314
315
                if (in_array($route, ['browser', 'tags'])) {
316
                    Route::get($routeSlug, $mapping);
317
                }
318
319
                if (in_array($route, ['restoreRevision'])) {
320
                    Route::get($routeSlug . '/{id}', $mapping);
321
                }
322
323
                if (
324
                    in_array($route, [
325
                        'publish',
326
                        'feature',
327
                        'restore',
328
                        'forceDelete',
329
                    ])
330
                ) {
331
                    Route::put($routeSlug, $mapping);
332
                }
333
334
                if (in_array($route, ['duplicate'])) {
335
                    Route::put($routeSlug . '/{id}', $mapping);
336
                }
337
338
                if (in_array($route, ['preview'])) {
339
                    Route::put($routeSlug . '/{id}', $mapping);
340
                }
341
342
                if (
343
                    in_array($route, [
344
                        'reorder',
345
                        'bulkPublish',
346
                        'bulkFeature',
347
                        'bulkDelete',
348
                        'bulkRestore',
349
                        'bulkForceDelete',
350
                    ])
351
                ) {
352
                    Route::post($routeSlug, $mapping);
353
                }
354
            }
355
356
            if ($resource) {
357
                Route::group(
358
                    ['as' => $resourceCustomGroupPrefix],
359
                    function () use ($slug, $className, $resource_options) {
360
                        Route::resource(
361
                            $slug,
362
                            "{$className}Controller",
363
                            $resource_options
364
                        );
365
                    }
366
                );
367
            }
368
        });
369
370
        Route::macro('singleton', function (
371
            $slug,
372
            $options = [],
373
            $resource_options = [],
374
            $resource = true
375
        ) {
376
            $pluralSlug = Str::plural($slug);
377
            $modelName = Str::studly($slug);
378
379
            Route::module($pluralSlug, $options, $resource_options, $resource);
380
381
            $lastRouteGroupName = RouteServiceProvider::getLastRouteGroupName();
382
383
            $groupPrefix = RouteServiceProvider::getGroupPrefix();
384
385
            // Check if name will be a duplicate, and prevent if needed/allowed
386
            if (RouteServiceProvider::shouldPrefixRouteName($groupPrefix, $lastRouteGroupName)) {
387
                $singletonRouteName = "{$groupPrefix}.{$slug}";
388
            } else {
389
                $singletonRouteName = $slug;
390
            }
391
392
            Route::get($slug, $modelName . 'Controller@editSingleton')->name($singletonRouteName);
393
        });
394
    }
395
396
    public static function shouldPrefixRouteName($groupPrefix, $lastRouteGroupName)
397
    {
398
        return !empty($groupPrefix) && (blank($lastRouteGroupName) ||
399
            config('twill.allow_duplicates_on_route_names', true) ||
400
            (!Str::endsWith($lastRouteGroupName, ".{$groupPrefix}.")));
401
    }
402
403
    public static function getLastRouteGroupName()
404
    {
405
        // Get the current route groups
406
        $routeGroups = Route::getGroupStack() ?? [];
407
408
        // Get the name prefix of the last group
409
        return end($routeGroups)['as'] ?? '';
410
    }
411
412
    public static function getGroupPrefix()
413
    {
414
        $groupPrefix = trim(
415
            str_replace('/', '.', Route::getLastGroupPrefix()),
416
            '.'
417
        );
418
419
        if (!empty(config('twill.admin_app_path'))) {
420
            $groupPrefix = ltrim(
421
                str_replace(
422
                    config('twill.admin_app_path'),
423
                    '',
424
                    $groupPrefix
425
                ),
426
                '.'
427
            );
428
        }
429
430
        return $groupPrefix;
431
    }
432
}
433