Completed
Push — master ( bb58d0...11d1cc )
by ARCANEDEV
9s
created

Localization::getAllLocales()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php namespace Arcanedev\Localization;
2
3
use Arcanedev\Localization\Contracts\LocalesManager as LocalesManagerContract;
4
use Arcanedev\Localization\Contracts\Localization as LocalizationContract;
5
use Arcanedev\Localization\Contracts\RouteTranslator as RouteTranslatorContract;
6
use Arcanedev\Localization\Exceptions\UnsupportedLocaleException;
7
use Arcanedev\Localization\Utilities\Url;
8
use Illuminate\Foundation\Application;
9
use Illuminate\Http\Request;
10
11
/**
12
 * Class     Localization
13
 *
14
 * @package  Arcanedev\Localization
15
 * @author   ARCANEDEV <[email protected]>
16
 */
17
class Localization implements LocalizationContract
18
{
19
    /* ------------------------------------------------------------------------------------------------
20
     |  Properties
21
     | ------------------------------------------------------------------------------------------------
22
     */
23
    /**
24
     * Base url.
25
     *
26
     * @var string
27
     */
28
    protected $baseUrl;
29
30
    /**
31
     * Laravel application instance.
32
     *
33
     * @var \Illuminate\Foundation\Application
34
     */
35
    private $app;
36
37
    /**
38
     * The RouteTranslator instance.
39
     *
40
     * @var \Arcanedev\Localization\Contracts\RouteTranslator
41
     */
42
    protected $routeTranslator;
43
44
    /**
45
     * The LocalesManager instance.
46
     *
47
     * @var \Arcanedev\Localization\Contracts\LocalesManager
48
     */
49
    private $localesManager;
50
51
    /* ------------------------------------------------------------------------------------------------
52
     |  Constructor
53
     | ------------------------------------------------------------------------------------------------
54
     */
55
    /**
56
     * Creates new instance.
57
     *
58
     * @param  \Illuminate\Foundation\Application                          $app
59
     * @param  \Arcanedev\Localization\Contracts\RouteTranslator  $routeTranslator
60
     * @param  \Arcanedev\Localization\Contracts\LocalesManager   $localesManager
61
     */
62 504
    public function __construct(
63
        Application             $app,
64
        RouteTranslatorContract $routeTranslator,
65
        LocalesManagerContract  $localesManager
66
    ) {
67 504
        $this->app             = $app;
68 504
        $this->routeTranslator = $routeTranslator;
69 504
        $this->localesManager  = $localesManager;
70
71 504
        $this->localesManager->setDefaultLocale(
72 504
            $this->app->getLocale()
73 252
        );
74 504
    }
75
76
    /* ------------------------------------------------------------------------------------------------
77
     |  Getters & Setters
78
     | ------------------------------------------------------------------------------------------------
79
     */
80
    /**
81
     * Get Request instance.
82
     *
83
     * @return \Illuminate\Http\Request
84
     */
85 72
    private function request()
86
    {
87 72
        return $this->app['request'];
88
    }
89
90
    /**
91
     * Returns default locale.
92
     *
93
     * @return string
94
     */
95 104
    public function getDefaultLocale()
96
    {
97 104
        return $this->localesManager->getDefaultLocale();
98
    }
99
100
    /**
101
     * Return an array of all supported Locales.
102
     *
103
     * @return \Arcanedev\Localization\Entities\LocaleCollection
104
     */
105 80
    public function getSupportedLocales()
106
    {
107 80
        return $this->localesManager->getSupportedLocales();
108
    }
109
110
    /**
111
     * Set the supported locales.
112
     *
113
     * @param  array  $supportedLocales
114
     *
115
     * @return self
116
     */
117 16
    public function setSupportedLocales(array $supportedLocales)
118
    {
119 16
        $this->localesManager->setSupportedLocales($supportedLocales);
120
121 8
        return $this;
122
    }
123
124
    /**
125
     * Get supported locales keys.
126
     *
127
     * @return array
128
     */
129 8
    public function getSupportedLocalesKeys()
130
    {
131 8
        return $this->localesManager->getSupportedLocalesKeys();
132
    }
133
134
    /**
135
     * Returns current language.
136
     *
137
     * @return string
138
     */
139 504
    public function getCurrentLocale()
140
    {
141 504
        return $this->localesManager->getCurrentLocale();
142
    }
143
144
    /**
145
     * Returns current language.
146
     *
147
     * @return \Arcanedev\Localization\Entities\Locale
148
     */
149 40
    public function getCurrentLocaleEntity()
150
    {
151 40
        return $this->localesManager->getCurrentLocaleEntity();
152
    }
153
154
    /**
155
     * Returns current locale name.
156
     *
157
     * @return string
158
     */
159 8
    public function getCurrentLocaleName()
160
    {
161 8
        return $this->getCurrentLocaleEntity()->name();
162
    }
163
164
    /**
165
     * Returns current locale script.
166
     *
167
     * @return string
168
     */
169 8
    public function getCurrentLocaleScript()
170
    {
171 8
        return $this->getCurrentLocaleEntity()->script();
172
    }
173
174
    /**
175
     * Returns current locale direction.
176
     *
177
     * @return string
178
     */
179 8
    public function getCurrentLocaleDirection()
180
    {
181 8
        return $this->getCurrentLocaleEntity()->direction();
182
    }
183
184
    /**
185
     * Returns current locale native name.
186
     *
187
     * @return string
188
     */
189 8
    public function getCurrentLocaleNative()
190
    {
191 8
        return $this->getCurrentLocaleEntity()->native();
192
    }
193
194
    /**
195
     * Returns current locale regional.
196
     *
197
     * @return string
198
     */
199 8
    public function getCurrentLocaleRegional()
200
    {
201 8
        return $this->getCurrentLocaleEntity()->regional();
202
    }
203
204
    /**
205
     * Get all locales.
206
     *
207
     * @return \Arcanedev\Localization\Entities\LocaleCollection
208
     */
209 8
    public function getAllLocales()
210
    {
211 8
        return $this->localesManager->getAllLocales();
212
    }
213
214
    /**
215
     * Set and return current locale.
216
     *
217
     * @param  string|null  $locale
218
     *
219
     * @return string
220
     */
221 504
    public function setLocale($locale = null)
222
    {
223 504
        return $this->localesManager->setLocale($locale);
224
    }
225
226
    /**
227
     * Sets the base url for the site.
228
     *
229
     * @param  string  $url
230
     *
231
     * @return self
232
     */
233 504
    public function setBaseUrl($url)
234 4
    {
235 504
        if (substr($url, -1) !== '/') $url .= '/';
236
237 504
        $this->baseUrl = $url;
238
239 504
        return $this;
240
    }
241
242
    /* ------------------------------------------------------------------------------------------------
243
     |  Main Functions
244
     | ------------------------------------------------------------------------------------------------
245
     */
246
    /**
247
     * Translate routes and save them to the translated routes array (used in the localize route filter).
248
     *
249
     * @param  string  $routeName
250
     *
251
     * @return string
252
     */
253 504
    public function transRoute($routeName)
254
    {
255 504
        return $this->routeTranslator->trans($routeName);
256
    }
257
258
    /**
259
     * Returns an URL adapted to $locale or current locale.
260
     *
261
     * @param  string|null  $url
262
     * @param  string|null  $locale
263
     *
264
     * @return string
265
     */
266 16
    public function localizeURL($url = null, $locale = null)
267
    {
268 16
        return $this->getLocalizedURL($locale, $url);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->getLocalizedURL($locale, $url); of type string|false adds false to the return on line 268 which is incompatible with the return type declared by the interface Arcanedev\Localization\C...calization::localizeURL of type string. It seems like you forgot to handle an error condition.
Loading history...
269
    }
270
271
    /**
272
     * It returns an URL without locale (if it has it).
273
     *
274
     * @param  string|null  $url
275
     *
276
     * @return string
277
     */
278 72
    public function getNonLocalizedURL($url = null)
279
    {
280 72
        return $this->getLocalizedURL(false, $url);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Comprehensibility Best Practice introduced by
The expression $this->getLocalizedURL(false, $url); of type string|false adds false to the return on line 280 which is incompatible with the return type declared by the interface Arcanedev\Localization\C...ion::getNonLocalizedURL of type string. It seems like you forgot to handle an error condition.
Loading history...
281
    }
282
283
    /**
284
     * Returns an URL adapted to $locale or current locale.
285
     *
286
     * @todo: Refactor this beast
287
     *
288
     * @param  string|null  $locale
289
     * @param  string|null  $url
290
     * @param  array        $attributes
291
     *
292
     * @return string|false
293
     */
294 72
    public function getLocalizedURL($locale = null, $url = null, $attributes = [])
295
    {
296 72
        if (is_null($locale)) {
297 40
            $locale = $this->getCurrentLocale();
298 20
        }
299
300 72
        $this->isLocaleSupportedOrFail($locale);
301
302 72
        if (empty($attributes)) {
303 72
            $attributes = Url::extractAttributes($url);
304 36
        }
305
306 72
        if (empty($url)) {
307 40
            if ($this->routeTranslator->hasCurrentRoute()) {
308 8
                if (empty($attributes)) {
309 8
                    $attributes = $this->request()->route()->parameters();
310 4
                }
311
312 8
                return $this->getUrlFromRouteName(
313 4
                    $locale,
314 8
                    $this->routeTranslator->getCurrentRoute(),
315
                    $attributes
316 4
                );
317
            }
318
319 40
            $url = $this->request()->fullUrl();
320 20
        }
321
322
        if (
323 72
            $locale &&
324 68
            $translatedRoute = $this->findTranslatedRouteByUrl($url, $attributes, $this->getCurrentLocale())
325 36
        ) {
326 16
            return $this->getUrlFromRouteName($locale, $translatedRoute, $attributes);
327
        }
328
329 72
        $baseUrl    = $this->request()->getBaseUrl();
330 72
        $parsedUrl  = parse_url($url);
331
332 72
        $translatedRoute = $this->routeTranslator->getTranslatedRoute(
333 72
            $baseUrl, $parsedUrl, $this->getDefaultLocale(), $this->getSupportedLocales()
334 36
        );
335
336 72
        if ($translatedRoute !== false) {
337 64
            return $this->getUrlFromRouteName($locale, $translatedRoute, $attributes);
338
        }
339
340
        if (
341 72
            ! empty($locale) &&
342 68
            ($locale !== $this->getDefaultLocale() || ! $this->isDefaultLocaleHiddenInUrl())
343 36
        ) {
344 64
            $parsedUrl['path'] = $locale . '/' . ltrim($parsedUrl['path'], '/');
345 32
        }
346
347 72
        $parsedUrl['path'] = ltrim(ltrim($baseUrl, '/') . '/' . $parsedUrl['path'], '/');
348 72
        $parsedUrl['path'] = rtrim($parsedUrl['path'], '/');
349
350 72
        $url = Url::unparse($parsedUrl);
351
352 72
        if (filter_var($url, FILTER_VALIDATE_URL)) {
353 72
            return $url;
354
        }
355
356 8
        if (empty($url)) {
357 8
            $url = $parsedUrl['path'];
358 4
        }
359
360 8
        return $this->createUrlFromUri($url);
361
    }
362
363
    /**
364
     * Create an url from the uri.
365
     *
366
     * @param  string  $uri
367
     *
368
     * @return string
369
     */
370 80
    public function createUrlFromUri($uri)
371
    {
372 80
        $uri = ltrim($uri, '/');
373
374 80
        return empty($this->baseUrl) ? app('url')->to($uri) : $this->baseUrl.$uri;
375
    }
376
377
    /**
378
     * Get locales navigation bar.
379
     *
380
     * @return string
381
     */
382 8
    public function localesNavbar()
383
    {
384 8
        $supportedLocales = $this->getSupportedLocales();
385
386 8
        return view('localization::navbar', compact('supportedLocales'))->render();
387
    }
388
389
    /* ------------------------------------------------------------------------------------------------
390
     |  Translation Functions
391
     | ------------------------------------------------------------------------------------------------
392
     */
393
    /**
394
     * Returns the translated route for an url and the attributes given and a locale
395
     *
396
     * @param  string  $url
397
     * @param  array   $attributes
398
     * @param  string  $locale
399
     *
400
     * @return string|false
401
     */
402 64
    private function findTranslatedRouteByUrl($url, $attributes, $locale)
403
    {
404 64
        if (empty($url)) return false;
405
406
        // check if this url is a translated url
407 64
        foreach ($this->routeTranslator->getTranslatedRoutes() as $translatedRoute) {
408 64
            $translatedUrl = $this->getUrlFromRouteName($locale, $translatedRoute, $attributes);
409
410 64
            if ($this->getNonLocalizedURL($translatedUrl) === $this->getNonLocalizedURL($url))  {
0 ignored issues
show
Security Bug introduced by
It seems like $translatedUrl defined by $this->getUrlFromRouteNa...atedRoute, $attributes) on line 408 can also be of type false; however, Arcanedev\Localization\L...n::getNonLocalizedURL() does only seem to accept string|null, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
411 40
                return $translatedRoute;
412
            }
413 32
        }
414
415 64
        return false;
416
    }
417
418
    /**
419
     * Returns an URL adapted to the route name and the locale given.
420
     *
421
     * @param  string  $locale
422
     * @param  string  $transKey
423
     * @param  array   $attributes
424
     *
425
     * @return string|false
426
     */
427 80
    public function getUrlFromRouteName($locale, $transKey, $attributes = [])
428
    {
429 80
        $this->isLocaleSupportedOrFail($locale);
430
431 72
        $route = $this->routeTranslator->getUrlFromRouteName(
432 36
            $locale,
433 72
            $this->getDefaultLocale(),
434 36
            $transKey,
435 36
            $attributes,
436 72
            $this->isDefaultLocaleHiddenInUrl()
437 36
        );
438
439
        // This locale does not have any key for this route name
440 72
        if (empty($route)) return false;
441
442 72
        return rtrim($this->createUrlFromUri($route));
443
    }
444
445
    /**
446
     * Set route name from request.
447
     *
448
     * @param  \Illuminate\Http\Request  $request
449
     */
450 8
    public function setRouteNameFromRequest(Request $request)
451
    {
452 8
        $routeName = $this->routeTranslator->getRouteNameFromPath(
453 8
            $request->getUri(), $this->getCurrentLocale()
454 4
        );
455
456 8
        $this->routeTranslator->setCurrentRoute($routeName);
457 8
    }
458
459
    /* ------------------------------------------------------------------------------------------------
460
     |  Check Functions
461
     | ------------------------------------------------------------------------------------------------
462
     */
463
    /**
464
     * Hide the default locale in URL ??
465
     *
466
     * @return bool
467
     */
468 72
    public function isDefaultLocaleHiddenInUrl()
469
    {
470 72
        return $this->localesManager->isDefaultLocaleHiddenInUrl();
471
    }
472
473
    /**
474
     * Check if Locale exists on the supported locales collection.
475
     *
476
     * @param  string|bool  $locale
477
     *
478
     * @return bool
479
     */
480 88
    public function isLocaleSupported($locale)
481
    {
482 88
        return ! ($locale !== false && ! $this->localesManager->isSupportedLocale($locale));
0 ignored issues
show
Bug introduced by
It seems like $locale defined by parameter $locale on line 480 can also be of type boolean; however, Arcanedev\Localization\C...er::isSupportedLocale() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
483
    }
484
485
    /**
486
     * Check if the locale is supported or fail if not.
487
     *
488
     * @param  string  $locale
489
     *
490
     * @throws \Arcanedev\Localization\Exceptions\UnsupportedLocaleException
491
     */
492 88
    private function isLocaleSupportedOrFail($locale)
493
    {
494 88
        if ( ! $this->isLocaleSupported($locale)) {
495 8
            throw new UnsupportedLocaleException(
496 8
                "Locale '$locale' is not in the list of supported locales."
497 4
            );
498
        }
499 80
    }
500
}
501