Completed
Pull Request — master (#33)
by
unknown
01:07
created

MultilingualRegistrar::generateRoute()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 4
dl 0
loc 19
rs 9.6333
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->shouldNotPrefixLocale($locale) ||
183
            $this->shouldNotPrefixDefaultHome($locale) ? '/' : "/$locale";
184
        }
185
186
        return Lang::has("routes.{$key}")
187
            ? trans("routes.{$key}", [], $locale)
188
            : $key;
189
    }
190
191
    /**
192
     * Apply the unique registration key to make sure the route is registered.
193
     *
194
     * @param  string  $uri
195
     * @param  string  $locale
196
     * @return string
197
     */
198
    protected function applyUniqueRegistrationKey(string $uri, string $locale): string
199
    {
200
        return "__{$locale}__".$uri;
201
    }
202
203
    /**
204
     * Clean the unique registration key from the route uri after it has been
205
     * registered in the router.
206
     *
207
     * @param  \Illuminate\Routing\Route  $route
208
     * @param  string  $locale
209
     * @return \Illuminate\Routing\Route
210
     */
211
    protected function cleanUniqueRegistrationKey(Route $route, string $locale): Route
212
    {
213
        return $route->setUri(str_replace("__{$locale}__", '', $route->uri));
214
    }
215
216
    /**
217
     * Verify if we should not prefix the locale.
218
     *
219
     * @param  string  $locale
220
     * @return bool
221
     */
222
    protected function shouldNotPrefixLocale(string $locale): bool
223
    {
224
        return $locale == config('laravel-multilingual-routes.default')
225
            && ! config('laravel-multilingual-routes.prefix_default');
226
    }
227
228
    /**
229
     * Verify if we should not prefix the default Home Route.
230
     *
231
     * @param  string  $locale
232
     * @return bool
233
     */
234
    protected function shouldNotPrefixDefaultHome(string $locale): bool
235
    {
236
        return $locale == config('laravel-multilingual-routes.default')
237
            && ! config('laravel-multilingual-routes.prefix_default_home');
238
    }
239
}
240