I18nService::url()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.6111
c 0
b 0
f 0
cc 5
nc 3
nop 2
1
<?php
2
3
namespace RichanFongdasen\I18n;
4
5
use Carbon\Carbon;
6
use Illuminate\Http\Request;
7
use Illuminate\Support\Collection;
8
use RichanFongdasen\I18n\Exceptions\InvalidFallbackLanguageException;
9
use RichanFongdasen\I18n\Exceptions\InvalidLocaleException;
10
11
class I18nService
12
{
13
    /**
14
     * I18n configuration.
15
     *
16
     * @var array
17
     */
18
    protected $config;
19
20
    /**
21
     * Default locale key.
22
     *
23
     * @var string
24
     */
25
    protected $defaultKey;
26
27
    /**
28
     * Locale collection object.
29
     *
30
     * @var \Illuminate\Support\Collection
31
     */
32
    protected $locale;
33
34
    /**
35
     * All of possible locale keys.
36
     *
37
     * @var array
38
     */
39
    protected $possibleKeys = ['ietfCode', 'language'];
40
41
    /**
42
     * HTTP Request Object.
43
     *
44
     * @var \Illuminate\Http\Request
45
     */
46
    protected $request;
47
48
    /**
49
     * URL Generator object.
50
     *
51
     * @var \RichanFongdasen\I18n\UrlGenerator
52
     */
53
    protected $urlGenerator;
54
55
    /**
56
     * Class constructor.
57
     *
58
     * @param \Illuminate\Http\Request $request
59
     */
60
    public function __construct(Request $request)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
61
    {
62
        $this->request = $request;
63
        $this->loadConfig();
64
65
        $this->defaultKey = $this->getConfig('language_key');
66
67
        $this->locale = $this->loadLocale();
68
69
        $this->urlGenerator = new UrlGenerator($this, $this->defaultKey);
70
    }
71
72
    /**
73
     * Get default locale.
74
     *
75
     * @throws InvalidFallbackLanguageException
76
     *
77
     * @return \RichanFongdasen\I18n\Locale
78
     */
79
    public function defaultLocale(): Locale
80
    {
81
        $fallback = $this->getConfig('fallback_language');
82
        $locale = $this->getLocale($fallback);
83
84
        if (!$locale instanceof Locale) {
85
            throw new InvalidFallbackLanguageException('Can\'t find the fallback locale object');
86
        }
87
88
        return $locale;
89
    }
90
91
    /**
92
     * Format the IETF locale string.
93
     *
94
     * @param string $string
95
     *
96
     * @return string
97
     */
98
    protected function formatIetf(string $string): string
99
    {
100
        return str_replace('_', '-', $string);
101
    }
102
103
    /**
104
     * Get configuration value for a specific key.
105
     *
106
     * @param string $key
107
     * @param mixed  $default
108
     *
109
     * @return mixed
110
     */
111
    public function getConfig(string $key, $default = null)
112
    {
113
        return data_get($this->config, $key, $default);
114
    }
115
116
    /**
117
     * Get any locale matched to the given keyword.
118
     * It will return all available locales when
119
     * there is no keyword.
120
     *
121
     * @param string|null $keyword
122
     *
123
     * @return mixed
124
     */
125
    public function getLocale(?string $keyword = null)
126
    {
127
        if ($keyword === null) {
128
            return $this->locale;
129
        }
130
        $keyword = $this->formatIetf($keyword);
131
132
        foreach ($this->possibleKeys as $key) {
133
            if ($locale = $this->locale->keyBy($key)->get($keyword)) {
134
                return $locale;
135
            }
136
        }
137
138
        return null;
139
    }
140
141
    /**
142
     * Get all of available locale keys.
143
     *
144
     * @param string|null $key
145
     *
146
     * @return null|array
147
     */
148
    public function getLocaleKeys(?string $key = null): ?array
149
    {
150
        if (empty($key)) {
151
            $key = $this->defaultKey;
152
        }
153
        $keys = $this->locale->keyBy($key)->keys()->all();
154
155
        if ((count($keys) == 1) && empty($keys[0])) {
156
            return null;
157
        }
158
159
        return $keys;
160
    }
161
162
    /**
163
     * Load I18n configurations.
164
     *
165
     * @return void
166
     */
167
    public function loadConfig(): void
168
    {
169
        $this->config = \Config::get('i18n');
170
    }
171
172
    /**
173
     * Load locale from repository.
174
     *
175
     * @return \Illuminate\Support\Collection
176
     */
177
    protected function loadLocale(): Collection
178
    {
179
        $cacheKey = 'laravel-i18n-locale-'.$this->getConfig('driver');
180
        $duration = $this->getConfig('cache_duration', 86400);
181
        $ttl = Carbon::now()->addSeconds($duration);
182
183
        if (!$this->getConfig('enable_cache')) {
184
            return app(RepositoryManager::class)->collect();
185
        }
186
187
        return \Cache::remember($cacheKey, $ttl, function () {
188
            return app(RepositoryManager::class)->collect();
189
        });
190
    }
191
192
    /**
193
     * Get the current routed locale.
194
     *
195
     * @param null|\Illuminate\Http\Request $request
196
     *
197
     * @return \RichanFongdasen\I18n\Locale|null
198
     */
199
    public function routedLocale(Request $request = null): ?Locale
200
    {
201
        if (!$request) {
202
            $request = $this->request;
203
        }
204
205
        $index = $this->getConfig('locale_url_segment');
206
        $language = $request->segment($index);
207
        if (empty($language)) {
208
            return null;
209
        }
210
211
        if ($locale = $this->getLocale($language)) {
212
            \App::setLocale($locale->{$this->defaultKey});
213
        }
214
215
        return $locale;
216
    }
217
218
    /**
219
     * Get the route prefix.
220
     *
221
     * @return string
222
     */
223
    public function routePrefix(): string
224
    {
225
        $locale = $this->routedLocale() ? $this->routedLocale() : $this->defaultLocale();
226
227
        return $locale->{$this->defaultKey};
228
    }
229
230
    /**
231
     * Generate a localized URL for the application.
232
     *
233
     * @param string     $url
234
     * @param mixed|null $locale
235
     *
236
     * @throws InvalidLocaleException|InvalidFallbackLanguageException
237
     *
238
     * @return string
239
     */
240
    public function url(string $url, $locale = null): string
241
    {
242
        if (is_string($locale) && !($locale = $this->getLocale($locale))) {
243
            throw new InvalidLocaleException('Failed to generate URL with the given locale');
244
        }
245
        if (($locale === null) && !($locale = $this->routedLocale())) {
246
            $locale = $this->defaultLocale();
247
        }
248
249
        return $this->urlGenerator->setUrl($url)->localize($locale);
250
    }
251
}
252