Completed
Push — master ( fd5c1f...b5e768 )
by Chin
01:11
created

generateNameForLocaleFromOptions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 3
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
namespace ChinLeung\MultilingualRoutes;
4
5
use Illuminate\Routing\Route;
6
use Illuminate\Routing\RouteCollection;
7
use Illuminate\Routing\Router;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\Facades\Lang;
10
11
class MultilingualRegistrar
12
{
13
    /**
14
     * The router instance.
15
     *
16
     * @var \Illuminate\Routing\Router
17
     */
18
    protected $router;
19
20
    /**
21
     * Constructor of the class.
22
     *
23
     * @param  \Illuminate\Routing\Router  $router
24
     */
25
    public function __construct(Router $router)
26
    {
27
        $this->router = $router;
28
    }
29
30
    /**
31
     * Register the routes.
32
     *
33
     * @param  string  $key
34
     * @param  mixed  $handle
35
     * @param  array  $locales
36
     * @param  array  $options
37
     * @return \Illuminate\Routing\RouteCollection
38
     */
39
    public function register(string $key, $handle, array $locales, array $options): RouteCollection
40
    {
41
        foreach ($locales as $locale) {
42
            $route = $this->registerRoute($key, $handle, $locale, $options);
43
44
            if (isset($options['defaults']) && is_array($options['defaults'])) {
45
                foreach ($options['defaults'] as $paramKey => $paramValue) {
46
                    $route->defaults($paramKey, $paramValue);
47
                }
48
            }
49
        }
50
51
        return tap($this->router->getRoutes())->refreshNameLookups();
52
    }
53
54
    /**
55
     * Register a single route.
56
     *
57
     * @param  string  $key
58
     * @param  mixed  $handle
59
     * @param  string  $locale
60
     * @param  array  $options
61
     * @return \Illuminate\Routing\Route
62
     */
63
    protected function registerRoute(string $key, $handle, string $locale, array $options): Route
64
    {
65
        $route = $this->generateRoute($key, $handle, $locale, $options);
66
67
        $this->applyConstraints($route, $locale, $options);
68
69
        if ($prefix = $this->generatePrefixForLocale($key, $locale)) {
70
            $route->setUri("{$prefix}/{$route->uri}");
71
        }
72
73
        if ($middleware = Arr::get($options, 'middleware')) {
74
            $route->middleware($middleware);
75
        }
76
77
        data_set($route, 'action.as', (
78
            $this->generateNameForLocaleFromOptions(
79
                $locale,
80
                $key,
81
                array_merge(
82
                    ['as' => data_get($route, 'action.as')],
83
                    $options
84
                )
85
            )
86
        ));
87
88
        return $this->cleanUniqueRegistrationKey($route, $locale);
89
    }
90
91
    /**
92
     * Generate a route.
93
     *
94
     * @param  string  $key
95
     * @param  mixed  $handle
96
     * @param  string  $locale
97
     * @param  array  $options
98
     * @return \Illuminate\Routing\Route
99
     */
100
    protected function generateRoute(string $key, $handle, string $locale, array $options): Route
101
    {
102
        $route = $this->router->addRoute(
103
            $this->getRequestMethodFromOptions($options),
104
            $this->applyUniqueRegistrationKey(
105
                $this->generateUriFromKey($key, $locale),
106
                $locale
107
            ),
108
            $handle ?: '\Illuminate\Routing\ViewController'
109
        );
110
111
        if ($handle === null) {
112
            return $route
113
                ->defaults('view', Arr::get($options, 'view', $key))
114
                ->defaults('data', Arr::get($options, 'data', []));
115
        }
116
117
        return $route;
118
    }
119
120
    /**
121
     * Retrieve the request method from the options.
122
     *
123
     * @param  array  $options
124
     * @return array
125
     */
126
    protected function getRequestMethodFromOptions(array $options): array
127
    {
128
        $method = $options['method'] ?? 'get';
129
130
        if ($method == 'get') {
131
            return ['GET', 'HEAD'];
132
        }
133
134
        return [strtoupper($method)];
135
    }
136
137
    /**
138
     * Generate the name of the route based on the options.
139
     *
140
     * @param  string  $locale
141
     * @param  string  $key
142
     * @param  array  $options
143
     * @return string
144
     */
145
    protected function generateNameForLocaleFromOptions(string $locale, string $key, array $options): string
146
    {
147
        $name = Arr::get($options, "names.{$locale}", Arr::get($options, 'name', $key));
148
149
        if ($prefix = Arr::get($options, 'as')) {
150
            return config('laravel-multilingual-routes.name_prefix_before_locale')
151
                ? "{$prefix}{$locale}.{$name}"
152
                : "{$locale}.{$prefix}{$name}";
153
        }
154
155
        return "{$locale}.{$name}";
156
    }
157
158
    /**
159
     * Generate the prefix of the route based on the options.
160
     *
161
     * @param  string  $key
162
     * @param  string  $locale
163
     * @return string|null
164
     */
165
    protected function generatePrefixForLocale(string $key, string $locale): ?string
166
    {
167
        if ($key == '/' || $this->shouldNotPrefixLocale($locale)) {
168
            return null;
169
        }
170
171
        return $locale;
172
    }
173
174
    /**
175
     * Generate the route uri from the translation key and locale.
176
     *
177
     * @param  string  $key
178
     * @param  string  $locale
179
     * @return string
180
     */
181
    protected function generateUriFromKey(string $key, string $locale): string
182
    {
183
        if ($key == '/') {
184
            return $this->shouldNotPrefixHome($locale) ? '/' : "/{$locale}";
185
        }
186
187
        return Lang::has("routes.{$key}", $locale)
188
            ? trans("routes.{$key}", [], $locale)
189
            : $key;
190
    }
191
192
    /**
193
     * Apply the unique registration key to make sure the route is registered.
194
     *
195
     * @param  string  $uri
196
     * @param  string  $locale
197
     * @return string
198
     */
199
    protected function applyUniqueRegistrationKey(string $uri, string $locale): string
200
    {
201
        return "__{$locale}__".$uri;
202
    }
203
204
    /**
205
     * Clean the unique registration key from the route uri after it has been
206
     * registered in the router.
207
     *
208
     * @param  \Illuminate\Routing\Route  $route
209
     * @param  string  $locale
210
     * @return \Illuminate\Routing\Route
211
     */
212
    protected function cleanUniqueRegistrationKey(Route $route, string $locale): Route
213
    {
214
        return $route->setUri(str_replace("__{$locale}__", '', $route->uri));
215
    }
216
217
    /**
218
     * Verify if we should not prefix the locale.
219
     *
220
     * @param  string  $locale
221
     * @return bool
222
     */
223
    protected function shouldNotPrefixLocale(string $locale): bool
224
    {
225
        return $locale == config('laravel-multilingual-routes.default')
226
            && ! config('laravel-multilingual-routes.prefix_default');
227
    }
228
229
    /**
230
     * Verify if we should not prefix the home page.
231
     *
232
     * @param  string  $locale
233
     * @return bool
234
     */
235
    protected function shouldNotPrefixHome(string $locale): bool
236
    {
237
        return $this->shouldNotPrefixLocale($locale)
238
            || $this->shouldNotPrefixDefaultHome($locale);
239
    }
240
241
    /**
242
     * Verify if we should not prefix the home page.
243
     *
244
     * @param  string  $locale
245
     * @return bool
246
     */
247
    protected function shouldNotPrefixDefaultHome(string $locale): bool
248
    {
249
        return $locale == config('laravel-multilingual-routes.default')
250
            && ! config('laravel-multilingual-routes.prefix_default_home');
251
    }
252
253
    /**
254
     * Apply the constraints of a route.
255
     *
256
     * @param  \Illuminate\Routing\Route  $route
257
     * @param  string  $locale
258
     * @param  array  $options
259
     * @return void
260
     */
261
    protected function applyConstraints(Route $route, string $locale, $options): void
262
    {
263
        $constraints = array_merge(
264
            Arr::get($options, 'constraints', []),
265
            Arr::get($options, "constraints-{$locale}", [])
266
        );
267
268
        foreach ($constraints as $name => $expression) {
269
            $route->where($name, $expression);
270
        }
271
    }
272
}
273