Completed
Push — master ( 874ff6...d2d6f7 )
by Chin
01:11 queued 11s
created

MultilingualRegistrar::generatePrefixForLocale()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 2
dl 0
loc 8
rs 10
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
        foreach (Arr::get($options, 'constraints', []) as $name => $expression) {
68
            $route->where($name, $expression);
69
        }
70
71
        if ($prefix = $this->generatePrefixForLocale($key, $locale)) {
72
            $route->setUri("{$prefix}/{$route->uri}");
73
        }
74
75
        data_set($route, 'action.as', (
76
            $this->generateNameForLocaleFromOptions(
77
                $locale,
78
                $key,
79
                array_merge(
80
                    ['as' => data_get($route, 'action.as')],
81
                    $options
82
                )
83
            )
84
        ));
85
86
        return $this->cleanUniqueRegistrationKey($route, $locale);
87
    }
88
89
    /**
90
     * Generate a route.
91
     *
92
     * @param  string  $key
93
     * @param  mixed  $handle
94
     * @param  string  $locale
95
     * @param  array  $options
96
     * @return \Illuminate\Routing\Route
97
     */
98
    protected function generateRoute(string $key, $handle, string $locale, array $options): Route
99
    {
100
        $route = $this->router->addRoute(
101
            $this->getRequestMethodFromOptions($options),
102
            $this->applyUniqueRegistrationKey(
103
                $this->generateUriFromKey($key, $locale),
104
                $locale
105
            ),
106
            $handle ?: '\Illuminate\Routing\ViewController'
107
        );
108
109
        if (is_null($handle)) {
110
            return $route
111
                ->defaults('view', Arr::get($options, 'view', $key))
112
                ->defaults('data', Arr::get($options, 'data', []));
113
        }
114
115
        return $route;
116
    }
117
118
    /**
119
     * Retrieve the request method from the options.
120
     *
121
     * @param  array  $options
122
     * @return array
123
     */
124
    protected function getRequestMethodFromOptions(array $options): array
125
    {
126
        $method = $options['method'] ?? 'get';
127
128
        if ($method == 'get') {
129
            return ['GET', 'HEAD'];
130
        }
131
132
        return [strtoupper($method)];
133
    }
134
135
    /**
136
     * Generate the name of the route based on the options.
137
     *
138
     * @param  string  $locale
139
     * @param  string  $key
140
     * @param  array  $options
141
     * @return string
142
     */
143
    protected function generateNameForLocaleFromOptions(string $locale, string $key, array $options): string
144
    {
145
        $name = Arr::get($options, "names.{$locale}", Arr::get($options, 'name', $key));
146
147
        if ($prefix = Arr::get($options, 'as')) {
148
            return config('laravel-multilingual-routes.name_prefix_before_locale')
149
                ? "{$prefix}{$locale}.{$name}"
150
                : "{$locale}.{$prefix}{$name}";
151
        }
152
153
        return "{$locale}.{$name}";
154
    }
155
156
    /**
157
     * Generate the prefix of the route based on the options.
158
     *
159
     * @param  string  $key
160
     * @param  string  $locale
161
     * @return string|null
162
     */
163
    protected function generatePrefixForLocale(string $key, string $locale): ?string
164
    {
165
        if ($key == '/' || $this->shouldNotPrefixLocale($locale)) {
166
            return null;
167
        }
168
169
        return $locale;
170
    }
171
172
    /**
173
     * Generate the route uri from the translation key and locale.
174
     *
175
     * @param  string  $key
176
     * @param  string  $locale
177
     * @return string
178
     */
179
    protected function generateUriFromKey(string $key, string $locale): string
180
    {
181
        if ($key == '/') {
182
            return $this->shouldNotPrefixHome($locale) ? '/' : "/{$locale}";
183
        }
184
185
        return Lang::has("routes.{$key}", $locale)
186
            ? trans("routes.{$key}", [], $locale)
187
            : $key;
188
    }
189
190
    /**
191
     * Apply the unique registration key to make sure the route is registered.
192
     *
193
     * @param  string  $uri
194
     * @param  string  $locale
195
     * @return string
196
     */
197
    protected function applyUniqueRegistrationKey(string $uri, string $locale): string
198
    {
199
        return "__{$locale}__".$uri;
200
    }
201
202
    /**
203
     * Clean the unique registration key from the route uri after it has been
204
     * registered in the router.
205
     *
206
     * @param  \Illuminate\Routing\Route  $route
207
     * @param  string  $locale
208
     * @return \Illuminate\Routing\Route
209
     */
210
    protected function cleanUniqueRegistrationKey(Route $route, string $locale): Route
211
    {
212
        return $route->setUri(str_replace("__{$locale}__", '', $route->uri));
213
    }
214
215
    /**
216
     * Verify if we should not prefix the locale.
217
     *
218
     * @param  string  $locale
219
     * @return bool
220
     */
221
    protected function shouldNotPrefixLocale(string $locale): bool
222
    {
223
        return $locale == config('laravel-multilingual-routes.default')
224
            && ! config('laravel-multilingual-routes.prefix_default');
225
    }
226
227
    /**
228
     * Verify if we should not prefix the home page.
229
     *
230
     * @param  string  $locale
231
     * @return bool
232
     */
233
    protected function shouldNotPrefixHome(string $locale): bool
234
    {
235
        return $this->shouldNotPrefixLocale($locale)
236
            || $this->shouldNotPrefixDefaultHome($locale);
237
    }
238
239
    /**
240
     * Verify if we should not prefix the home page.
241
     *
242
     * @param  string  $locale
243
     * @return bool
244
     */
245
    protected function shouldNotPrefixDefaultHome(string $locale): bool
246
    {
247
        return $locale == config('laravel-multilingual-routes.default')
248
            && ! config('laravel-multilingual-routes.prefix_default_home');
249
    }
250
}
251