Completed
Push — master ( f22aed...46f558 )
by Chin
03:14
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
            $this->registerRoute($key, $handle, $locale, $options);
43
        }
44
45
        return tap($this->router->getRoutes())->refreshNameLookups();
46
    }
47
48
    /**
49
     * Register a single route.
50
     *
51
     * @param  string  $key
52
     * @param  mixed  $handle
53
     * @param  string  $locale
54
     * @param  array  $options
55
     * @return \Illuminate\Routing\Route
56
     */
57
    protected function registerRoute(string $key, $handle, string $locale, array $options): Route
58
    {
59
        $route = $this->generateRoute($key, $handle, $locale, $options);
60
61
        foreach (Arr::get($options, 'constraints', []) as $name => $expression) {
62
            $route->where($name, $expression);
63
        }
64
65
        if ($prefix = $this->generatePrefixForLocale($key, $locale)) {
66
            $route->setUri("{$prefix}/{$route->uri}");
67
        }
68
69
        $route->name(
70
            $this->generateNameForLocaleFromOptions($locale, $key, $options)
71
        );
72
73
        return $this->cleanUniqueRegistrationKey($route, $locale);
74
    }
75
76
    /**
77
     * Generate a route.
78
     *
79
     * @param  string  $key
80
     * @param  mixed  $handle
81
     * @param  string  $locale
82
     * @param  array  $options
83
     * @return \Illuminate\Routing\Route
84
     */
85
    protected function generateRoute(string $key, $handle, string $locale, array $options): Route
86
    {
87
        $route = $this->router->addRoute(
88
            $this->getRequestMethodFromOptions($options),
89
            $this->applyUniqueRegistrationKey(
90
                $this->generateUriFromKey($key, $locale),
91
                $locale
92
            ),
93
            $handle ?: '\Illuminate\Routing\ViewController'
94
        );
95
96
        if (is_null($handle)) {
97
            return $route
98
                ->defaults('view', Arr::get($options, 'view', $key))
99
                ->defaults('data', Arr::get($options, 'data', []));
100
        }
101
102
        return $route;
103
    }
104
105
    /**
106
     * Retrieve the request method from the options.
107
     *
108
     * @param  array  $options
109
     * @return array
110
     */
111
    protected function getRequestMethodFromOptions(array $options): array
112
    {
113
        $method = $options['method'] ?? 'get';
114
115
        if ($method == 'get') {
116
            return ['GET', 'HEAD'];
117
        }
118
119
        return [strtoupper($method)];
120
    }
121
122
    /**
123
     * Generate the name of the route based on the options.
124
     *
125
     * @param  string  $locale
126
     * @param  string  $key
127
     * @param  array  $options
128
     * @return string
129
     */
130
    protected function generateNameForLocaleFromOptions(string $locale, string $key, array $options): string
131
    {
132
        if ($name = Arr::get($options, "names.$locale")) {
133
            return "$locale.$name";
134
        }
135
136
        return sprintf(
137
            '%s.%s',
138
            $locale,
139
            Arr::get($options, 'name', $key)
140
        );
141
    }
142
143
    /**
144
     * Generate the prefix of the route based on the options.
145
     *
146
     * @param  string  $key
147
     * @param  string  $locale
148
     * @return string|null
149
     */
150
    protected function generatePrefixForLocale(string $key, string $locale): ?string
151
    {
152
        if ($key == '/' || $this->shouldNotPrefixLocale($locale)) {
153
            return null;
154
        }
155
156
        return $locale;
157
    }
158
159
    /**
160
     * Generate the route uri from the translation key and locale.
161
     *
162
     * @param  string  $key
163
     * @param  string  $locale
164
     * @return string
165
     */
166
    protected function generateUriFromKey(string $key, string $locale): string
167
    {
168
        if ($key == '/') {
169
            return $this->shouldNotPrefixLocale($locale) ? '/' : "/$locale";
170
        }
171
172
        return Lang::has("routes.{$key}")
173
            ? trans("routes.{$key}", [], $locale)
174
            : $key;
175
    }
176
177
    /**
178
     * Apply the unique registration key to make sure the route is registered.
179
     *
180
     * @param  string  $uri
181
     * @param  string  $locale
182
     * @return string
183
     */
184
    protected function applyUniqueRegistrationKey(string $uri, string $locale): string
185
    {
186
        return "__{$locale}__".$uri;
187
    }
188
189
    /**
190
     * Clean the unique registration key from the route uri after it has been
191
     * registered in the router.
192
     *
193
     * @param  \Illuminate\Routing\Route  $route
194
     * @param  string  $locale
195
     * @return \Illuminate\Routing\Route
196
     */
197
    protected function cleanUniqueRegistrationKey(Route $route, string $locale): Route
198
    {
199
        return $route->setUri(str_replace("__{$locale}__", '', $route->uri));
200
    }
201
202
    /**
203
     * Verify if we should not prefix the locale.
204
     *
205
     * @param  string  $locale
206
     * @return bool
207
     */
208
    protected function shouldNotPrefixLocale(string $locale): bool
209
    {
210
        return $locale == config('laravel-multilingual-routes.default')
211
            && ! config('laravel-multilingual-routes.prefix_default');
212
    }
213
}
214