GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

getURLFromRouteNameTranslated()   B
last analyzed

Complexity

Conditions 9
Paths 17

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.0555
c 0
b 0
f 0
cc 9
nc 17
nop 4
1
<?php
2
3
namespace Mcamara\LaravelLocalization;
4
5
use Illuminate\Config\Repository;
6
use Illuminate\Contracts\Routing\UrlRoutable;
7
use Mcamara\LaravelLocalization\Exceptions\SupportedLocalesNotDefined;
8
use Mcamara\LaravelLocalization\Exceptions\UnsupportedLocaleException;
9
10
class LaravelLocalization
11
{
12
    /**
13
     * The env key that the forced locale for routing is stored in.
14
     */
15
    const ENV_ROUTE_KEY = 'ROUTING_LOCALE';
16
17
    /**
18
     * Config repository.
19
     *
20
     * @var \Illuminate\Config\Repository
21
     */
22
    protected $configRepository;
23
24
    /**
25
     * Illuminate view Factory.
26
     *
27
     * @var \Illuminate\View\Factory
28
     */
29
    protected $view;
30
31
    /**
32
     * Illuminate translator class.
33
     *
34
     * @var \Illuminate\Translation\Translator
35
     */
36
    protected $translator;
37
38
    /**
39
     * Illuminate router class.
40
     *
41
     * @var \Illuminate\Routing\Router
42
     */
43
    protected $router;
44
45
    /**
46
     * Illuminate request class.
47
     *
48
     * @var \Illuminate\Routing\Request
49
     */
50
    protected $request;
51
52
    /**
53
     * Illuminate url class.
54
     *
55
     * @var \Illuminate\Routing\UrlGenerator
56
     */
57
    protected $url;
58
59
    /**
60
     * Illuminate request class.
61
     *
62
     * @var Illuminate\Foundation\Application
63
     */
64
    protected $app;
65
66
    /**
67
     * Illuminate request class.
68
     *
69
     * @var string
70
     */
71
    protected $baseUrl;
72
73
    /**
74
     * Default locale.
75
     *
76
     * @var string
77
     */
78
    protected $defaultLocale;
79
80
    /**
81
     * Supported Locales.
82
     *
83
     * @var array
84
     */
85
    protected $supportedLocales;
86
87
    /**
88
     * Current locale.
89
     *
90
     * @var string
91
     */
92
    protected $currentLocale = false;
93
94
    /**
95
     * An array that contains all routes that should be translated.
96
     *
97
     * @var array
98
     */
99
    protected $translatedRoutes = [];
100
101
    /**
102
     * Name of the translation key of the current route, it is used for url translations.
103
     *
104
     * @var string
105
     */
106
    protected $routeName;
107
108
    /**
109
     * An array that contains all translated routes by url
110
     *
111
     * @var array
112
     */
113
    protected $cachedTranslatedRoutesByUrl = [];
114
115
    /**
116
     * Creates new instance.
117
     *
118
     * @throws UnsupportedLocaleException
119
     */
120
    public function __construct()
121
    {
122
        $this->app = app();
123
124
        $this->configRepository = $this->app['config'];
125
        $this->view = $this->app['view'];
126
        $this->translator = $this->app['translator'];
127
        $this->router = $this->app['router'];
128
        $this->request = $this->app['request'];
129
        $this->url = $this->app['url'];
130
131
        // set default locale
132
        $this->defaultLocale = $this->configRepository->get('app.locale');
133
        $supportedLocales = $this->getSupportedLocales();
134
135
        if (empty($supportedLocales[$this->defaultLocale])) {
136
            throw new UnsupportedLocaleException('Laravel default locale is not in the supportedLocales array.');
137
        }
138
    }
139
140
    /**
141
     * Set and return current locale.
142
     *
143
     * @param string $locale Locale to set the App to (optional)
144
     *
145
     * @return string Returns locale (if route has any) or null (if route does not have a locale)
146
     */
147
    public function setLocale($locale = null)
148
    {
149
        if (empty($locale) || !\is_string($locale)) {
150
            // If the locale has not been passed through the function
151
            // it tries to get it from the first segment of the url
152
            $locale = $this->request->segment(1);
153
154
            // If the locale is determined by env, use that
155
            // Note that this is how per-locale route caching is performed.
156
            if ( ! $locale) {
157
                $locale = $this->getForcedLocale();
158
            }
159
        }
160
161
        if (!empty($this->supportedLocales[$locale])) {
162
            $this->currentLocale = $locale;
163
        } else {
164
            // if the first segment/locale passed is not valid
165
            // the system would ask which locale have to take
166
            // it could be taken by the browser
167
            // depending on your configuration
168
169
            $locale = null;
170
171
            // if we reached this point and hideDefaultLocaleInURL is true
172
            // we have to assume we are routing to a defaultLocale route.
173
            if ($this->hideDefaultLocaleInURL()) {
174
                $this->currentLocale = $this->defaultLocale;
175
            }
176
            // but if hideDefaultLocaleInURL is false, we have
177
            // to retrieve it from the browser...
178
            else {
179
                $this->currentLocale = $this->getCurrentLocale();
180
            }
181
        }
182
183
        $this->app->setLocale($this->currentLocale);
184
185
        // Regional locale such as de_DE, so formatLocalized works in Carbon
186
        $regional = $this->getCurrentLocaleRegional();
187
        $suffix = $this->configRepository->get('laravellocalization.utf8suffix');
188
        if ($regional) {
189
            setlocale(LC_TIME, $regional . $suffix);
190
            setlocale(LC_MONETARY, $regional . $suffix);
191
        }
192
193
        return $locale;
194
    }
195
196
    /**
197
     * Check if $locale is default locale and supposed to be hidden in url
198
     *
199
     * @param string $locale Locale to be checked
200
     *
201
     * @return boolean Returns true if above requirement are met, otherwise false
202
     */
203
204
     public function isHiddenDefault($locale)
205
     {
206
       return  ($this->getDefaultLocale() === $locale && $this->hideDefaultLocaleInURL());
207
     }
208
209
    /**
210
     * Set and return supported locales.
211
     *
212
     * @param array $locales Locales that the App supports
213
     */
214
    public function setSupportedLocales($locales)
215
    {
216
        $this->supportedLocales = $locales;
217
    }
218
219
    /**
220
     * Returns an URL adapted to $locale or current locale.
221
     *
222
     * @param string      $url    URL to adapt. If not passed, the current url would be taken.
223
     * @param string|bool $locale Locale to adapt, false to remove locale
224
     *
225
     * @throws UnsupportedLocaleException
226
     *
227
     * @return string URL translated
228
     */
229
    public function localizeURL($url = null, $locale = null)
230
    {
231
        return $this->getLocalizedURL($locale, $url);
232
    }
233
234
    /**
235
     * Returns an URL adapted to $locale.
236
     *
237
     *
238
     * @param string|bool  $locale     Locale to adapt, false to remove locale
239
     * @param string|false $url        URL to adapt in the current language. If not passed, the current url would be taken.
240
     * @param array        $attributes Attributes to add to the route, if empty, the system would try to extract them from the url.
241
     * @param bool         $forceDefaultLocation Force to show default location even hideDefaultLocaleInURL set as TRUE
242
     *
243
     * @throws SupportedLocalesNotDefined
244
     * @throws UnsupportedLocaleException
245
     *
246
     * @return string|false URL translated, False if url does not exist
247
     */
248
    public function getLocalizedURL($locale = null, $url = null, $attributes = [], $forceDefaultLocation = false)
249
    {
250
        if ($locale === null) {
251
            $locale = $this->getCurrentLocale();
252
        }
253
254
        if (!$this->checkLocaleInSupportedLocales($locale)) {
255
            throw new UnsupportedLocaleException('Locale \''.$locale.'\' is not in the list of supported locales.');
256
        }
257
258
        if (empty($attributes)) {
259
            $attributes = $this->extractAttributes($url, $locale);
0 ignored issues
show
Bug introduced by
It seems like $locale defined by parameter $locale on line 248 can also be of type boolean; however, Mcamara\LaravelLocalizat...on::extractAttributes() 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...
260
        }
261
        $urlQuery = parse_url($url, PHP_URL_QUERY);
262
        $urlQuery = $urlQuery ? '?'.$urlQuery : '';
263
264
        if (empty($url)) {
265
            if (!empty($this->routeName)) {
266
                return $this->getURLFromRouteNameTranslated($locale, $this->routeName, $attributes, $forceDefaultLocation);
267
            }
268
269
            $url = $this->request->fullUrl();
270
        } else {
271
            $url = $this->url->to($url);
272
            $url = preg_replace('/'. preg_quote($urlQuery, '/') . '$/', '', $url);
273
        }
274
275
        if ($locale && $translatedRoute = $this->findTranslatedRouteByUrl($url, $attributes, $this->currentLocale)) {
276
            return $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes, $forceDefaultLocation).$urlQuery;
277
        }
278
279
        $base_path = $this->request->getBaseUrl();
280
        $parsed_url = parse_url($url);
281
        $url_locale = $this->getDefaultLocale();
282
283
        if (!$parsed_url || empty($parsed_url['path'])) {
284
            $path = $parsed_url['path'] = '';
285
        } else {
286
            $parsed_url['path'] = str_replace($base_path, '', '/'.ltrim($parsed_url['path'], '/'));
287
            $path = $parsed_url['path'];
288
            foreach ($this->getSupportedLocales() as $localeCode => $lang) {
289
                $parsed_url['path'] = preg_replace('%^/?'.$localeCode.'/%', '$1', $parsed_url['path']);
290
                if ($parsed_url['path'] !== $path) {
291
                    $url_locale = $localeCode;
292
                    break;
293
                }
294
295
                $parsed_url['path'] = preg_replace('%^/?'.$localeCode.'$%', '$1', $parsed_url['path']);
296
                if ($parsed_url['path'] !== $path) {
297
                    $url_locale = $localeCode;
298
                    break;
299
                }
300
            }
301
        }
302
303
        $parsed_url['path'] = ltrim($parsed_url['path'], '/');
304
305
        if ($translatedRoute = $this->findTranslatedRouteByPath($parsed_url['path'], $url_locale)) {
306
            return $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes, $forceDefaultLocation).$urlQuery;
307
        }
308
309
	    if (!empty($locale)) {
310
            if ($forceDefaultLocation || $locale != $this->getDefaultLocale() || !$this->hideDefaultLocaleInURL()) {
311
                $parsed_url['path'] = $locale.'/'.ltrim($parsed_url['path'], '/');
312
            }
313
        }
314
        $parsed_url['path'] = ltrim(ltrim($base_path, '/').'/'.$parsed_url['path'], '/');
315
316
        //Make sure that the pass path is returned with a leading slash only if it come in with one.
317
        if (starts_with($path, '/') === true) {
0 ignored issues
show
Deprecated Code introduced by
The function starts_with() has been deprecated with message: Str::startsWith() should be used directly instead. Will be removed in Laravel 5.9.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
318
            $parsed_url['path'] = '/'.$parsed_url['path'];
319
        }
320
        $parsed_url['path'] = rtrim($parsed_url['path'], '/');
321
322
        $url = $this->unparseUrl($parsed_url);
323
324
        if ($this->checkUrl($url)) {
325
            return $url.$urlQuery;
326
        }
327
328
        return $this->createUrlFromUri($url).$urlQuery;
329
    }
330
331
    /**
332
     * Returns an URL adapted to the route name and the locale given.
333
     *
334
     *
335
     * @param string|bool $locale       Locale to adapt
336
     * @param string      $transKeyName Translation key name of the url to adapt
337
     * @param array       $attributes   Attributes for the route (only needed if transKeyName needs them)
338
     * @param bool        $forceDefaultLocation Force to show default location even hideDefaultLocaleInURL set as TRUE
339
     *
340
     * @throws SupportedLocalesNotDefined
341
     * @throws UnsupportedLocaleException
342
     *
343
     * @return string|false URL translated
344
     */
345
    public function getURLFromRouteNameTranslated($locale, $transKeyName, $attributes = [], $forceDefaultLocation = false)
346
    {
347
        if (!$this->checkLocaleInSupportedLocales($locale)) {
348
            throw new UnsupportedLocaleException('Locale \''.$locale.'\' is not in the list of supported locales.');
349
        }
350
351
        if (!\is_string($locale)) {
352
            $locale = $this->getDefaultLocale();
353
        }
354
355
        $route = '';
356
357
        if ($forceDefaultLocation || !($locale === $this->defaultLocale && $this->hideDefaultLocaleInURL())) {
358
            $route = '/'.$locale;
359
        }
360
        if (\is_string($locale) && $this->translator->has($transKeyName, $locale)) {
361
            $translation = $this->translator->trans($transKeyName, [], $locale);
362
            $route .= '/'.$translation;
363
364
            $route = $this->substituteAttributesInRoute($attributes, $route);
365
        }
366
367
        if (empty($route)) {
368
            // This locale does not have any key for this route name
369
            return false;
370
        }
371
372
        return rtrim($this->createUrlFromUri($route), '/');
373
    }
374
375
    /**
376
     * It returns an URL without locale (if it has it)
377
     * Convenience function wrapping getLocalizedURL(false).
378
     *
379
     * @param string|false $url URL to clean, if false, current url would be taken
380
     *
381
     * @return string URL with no locale in path
382
     */
383
    public function getNonLocalizedURL($url = null)
384
    {
385
        return $this->getLocalizedURL(false, $url);
386
    }
387
388
    /**
389
     * Returns default locale.
390
     *
391
     * @return string
392
     */
393
    public function getDefaultLocale()
394
    {
395
        return $this->defaultLocale;
396
    }
397
398
    /**
399
     * Return an array of all supported Locales.
400
     *
401
     * @throws SupportedLocalesNotDefined
402
     *
403
     * @return array
404
     */
405
    public function getSupportedLocales()
406
    {
407
        if (!empty($this->supportedLocales)) {
408
            return $this->supportedLocales;
409
        }
410
411
        $locales = $this->configRepository->get('laravellocalization.supportedLocales');
412
413
        if (empty($locales) || !\is_array($locales)) {
414
            throw new SupportedLocalesNotDefined();
415
        }
416
417
        $this->supportedLocales = $locales;
418
419
        return $locales;
420
    }
421
422
    /**
423
     * Return an array of all supported Locales but in the order the user
424
     * has specified in the config file. Useful for the language selector.
425
     *
426
     * @return array
427
     */
428
    public function getLocalesOrder()
429
    {
430
        $locales = $this->getSupportedLocales();
431
432
        $order = $this->configRepository->get('laravellocalization.localesOrder');
433
434
        uksort($locales, function ($a, $b) use ($order) {
435
            $pos_a = array_search($a, $order);
436
            $pos_b = array_search($b, $order);
437
            return $pos_a - $pos_b;
438
        });
439
440
        return $locales;
441
    }
442
443
    /**
444
     * Returns current locale name.
445
     *
446
     * @return string current locale name
447
     */
448
    public function getCurrentLocaleName()
449
    {
450
        return $this->supportedLocales[$this->getCurrentLocale()]['name'];
451
    }
452
453
    /**
454
     * Returns current locale native name.
455
     *
456
     * @return string current locale native name
457
     */
458
    public function getCurrentLocaleNative()
459
    {
460
        return $this->supportedLocales[$this->getCurrentLocale()]['native'];
461
    }
462
463
    /**
464
     * Returns current locale direction.
465
     *
466
     * @return string current locale direction
467
     */
468
    public function getCurrentLocaleDirection()
469
    {
470
        if (!empty($this->supportedLocales[$this->getCurrentLocale()]['dir'])) {
471
            return $this->supportedLocales[$this->getCurrentLocale()]['dir'];
472
        }
473
474
        switch ($this->getCurrentLocaleScript()) {
475
            // Other (historic) RTL scripts exist, but this list contains the only ones in current use.
476
            case 'Arab':
477
            case 'Hebr':
478
            case 'Mong':
479
            case 'Tfng':
480
            case 'Thaa':
481
            return 'rtl';
482
            default:
483
            return 'ltr';
484
        }
485
    }
486
487
    /**
488
     * Returns current locale script.
489
     *
490
     * @return string current locale script
491
     */
492
    public function getCurrentLocaleScript()
493
    {
494
        return $this->supportedLocales[$this->getCurrentLocale()]['script'];
495
    }
496
497
    /**
498
     * Returns current language's native reading.
499
     *
500
     * @return string current language's native reading
501
     */
502
    public function getCurrentLocaleNativeReading()
503
    {
504
        return $this->supportedLocales[$this->getCurrentLocale()]['native'];
505
    }
506
507
    /**
508
     * Returns current language.
509
     *
510
     * @return string current language
511
     */
512
    public function getCurrentLocale()
513
    {
514
        if ($this->currentLocale) {
515
            return $this->currentLocale;
516
        }
517
518
        if ($this->useAcceptLanguageHeader() && !$this->app->runningInConsole()) {
519
            $negotiator = new LanguageNegotiator($this->defaultLocale, $this->getSupportedLocales(), $this->request);
520
521
            return $negotiator->negotiateLanguage();
522
        }
523
524
        // or get application default language
525
        return $this->configRepository->get('app.locale');
526
    }
527
528
    /**
529
     * Returns current regional.
530
     *
531
     * @return string current regional
532
     */
533
    public function getCurrentLocaleRegional()
534
    {
535
        // need to check if it exists, since 'regional' has been added
536
        // after version 1.0.11 and existing users will not have it
537
        if (isset($this->supportedLocales[$this->getCurrentLocale()]['regional'])) {
538
            return $this->supportedLocales[$this->getCurrentLocale()]['regional'];
539
        } else {
540
            return;
541
        }
542
    }
543
544
    /**
545
     * Returns supported languages language key.
546
     *
547
     * @return array keys of supported languages
548
     */
549
    public function getSupportedLanguagesKeys()
550
    {
551
        return array_keys($this->supportedLocales);
552
    }
553
554
    /**
555
     * Check if Locale exists on the supported locales array.
556
     *
557
     * @param string|bool $locale string|bool Locale to be checked
558
     *
559
     * @throws SupportedLocalesNotDefined
560
     *
561
     * @return bool is the locale supported?
562
     */
563
    public function checkLocaleInSupportedLocales($locale)
564
    {
565
        $locales = $this->getSupportedLocales();
566
        if ($locale !== false && empty($locales[$locale])) {
567
            return false;
568
        }
569
570
        return true;
571
    }
572
573
    /**
574
     * Change route attributes for the ones in the $attributes array.
575
     *
576
     * @param $attributes array Array of attributes
577
     * @param string $route string route to substitute
578
     *
579
     * @return string route with attributes changed
580
     */
581
    protected function substituteAttributesInRoute($attributes, $route)
582
    {
583
        foreach ($attributes as $key => $value) {
584
            if ($value instanceOf UrlRoutable) {
585
                $value = $value->getRouteKey();
586
            }
587
            $route = str_replace(array('{'.$key.'}', '{'.$key.'?}'), $value, $route);
588
        }
589
590
        // delete empty optional arguments that are not in the $attributes array
591
        $route = preg_replace('/\/{[^)]+\?}/', '', $route);
592
593
        return $route;
594
    }
595
596
    /**
597
     * Returns translated routes.
598
     *
599
     * @return array translated routes
600
     */
601
    protected function getTranslatedRoutes()
602
    {
603
        return $this->translatedRoutes;
604
    }
605
606
    /**
607
     * Set current route name.
608
     *
609
     * @param string $routeName current route name
610
     */
611
    public function setRouteName($routeName)
612
    {
613
        $this->routeName = $routeName;
614
    }
615
616
    /**
617
     * Translate routes and save them to the translated routes array (used in the localize route filter).
618
     *
619
     * @param string $routeName Key of the translated string
620
     *
621
     * @return string Translated string
622
     */
623
    public function transRoute($routeName)
624
    {
625
        if (!\in_array($routeName, $this->translatedRoutes)) {
626
            $this->translatedRoutes[] = $routeName;
627
        }
628
629
        return $this->translator->trans($routeName);
630
    }
631
632
    /**
633
     * Returns the translation key for a given path.
634
     *
635
     * @param string $path Path to get the key translated
636
     *
637
     * @return string|false Key for translation, false if not exist
638
     */
639
    public function getRouteNameFromAPath($path)
640
    {
641
        $attributes = $this->extractAttributes($path);
642
643
        $path = parse_url($path)['path'];
644
        $path = trim(str_replace('/'.$this->currentLocale.'/', '', $path), "/");
645
646
        foreach ($this->translatedRoutes as $route) {
647
            if (trim($this->substituteAttributesInRoute($attributes, $this->translator->trans($route)), '/') === $path) {
0 ignored issues
show
Bug introduced by
It seems like $this->translator->trans($route) targeting Illuminate\Translation\Translator::trans() can also be of type array; however, Mcamara\LaravelLocalizat...tuteAttributesInRoute() does only seem to accept string, maybe add an additional type check?

This check looks at variables that 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...
648
                return $route;
649
            }
650
        }
651
652
        return false;
653
    }
654
655
    /**
656
     * Returns the translated route for the path and the url given.
657
     *
658
     * @param string $path       Path to check if it is a translated route
659
     * @param string $url_locale Language to check if the path exists
660
     *
661
     * @return string|false Key for translation, false if not exist
662
     */
663
    protected function findTranslatedRouteByPath($path, $url_locale)
664
    {
665
        // check if this url is a translated url
666
        foreach ($this->translatedRoutes as $translatedRoute) {
667
            if ($this->translator->trans($translatedRoute, [], $url_locale) == rawurldecode($path)) {
668
                return $translatedRoute;
669
            }
670
        }
671
672
        return false;
673
    }
674
675
    /**
676
     * Returns the translated route for an url and the attributes given and a locale.
677
     *
678
     *
679
     * @param string|false|null $url        Url to check if it is a translated route
680
     * @param array             $attributes Attributes to check if the url exists in the translated routes array
681
     * @param string            $locale     Language to check if the url exists
682
     *
683
     * @throws SupportedLocalesNotDefined
684
     * @throws UnsupportedLocaleException
685
     *
686
     * @return string|false Key for translation, false if not exist
687
     */
688
    protected function findTranslatedRouteByUrl($url, $attributes, $locale)
689
    {
690
        if (empty($url)) {
691
            return false;
692
        }
693
694
        if (isset($this->cachedTranslatedRoutesByUrl[$locale][$url])) {
695
            return $this->cachedTranslatedRoutesByUrl[$locale][$url];
696
        }
697
698
        // check if this url is a translated url
699
        foreach ($this->translatedRoutes as $translatedRoute) {
700
            $routeName = $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes);
701
702
            // We can ignore extra url parts and compare only their url_path (ignore arguments that are not attributes)
703
            if (parse_url($this->getNonLocalizedURL($routeName), PHP_URL_PATH) == parse_url($this->getNonLocalizedURL($url), PHP_URL_PATH)) {
704
                $this->cachedTranslatedRoutesByUrl[$locale][$url] = $translatedRoute;
705
706
                return $translatedRoute;
707
            }
708
        }
709
710
        return false;
711
    }
712
713
    /**
714
     * Returns true if the string given is a valid url.
715
     *
716
     * @param string $url String to check if it is a valid url
717
     *
718
     * @return bool Is the string given a valid url?
719
     */
720
    protected function checkUrl($url)
721
    {
722
        return filter_var($url, FILTER_VALIDATE_URL);
723
    }
724
725
    /**
726
     * Returns the config repository for this instance.
727
     *
728
     * @return Repository Configuration repository
729
     */
730
    public function getConfigRepository()
731
    {
732
        return $this->configRepository;
733
    }
734
735
    /**
736
     * Returns the translation key for a given path.
737
     *
738
     * @return bool Returns value of useAcceptLanguageHeader in config.
739
     */
740
    protected function useAcceptLanguageHeader()
741
    {
742
        return $this->configRepository->get('laravellocalization.useAcceptLanguageHeader');
743
    }
744
745
    public function hideUrlAndAcceptHeader()
746
    {
747
      return $this->hideDefaultLocaleInURL() && $this->useAcceptLanguageHeader();
748
    }
749
750
    /**
751
     * Returns the translation key for a given path.
752
     *
753
     * @return bool Returns value of hideDefaultLocaleInURL in config.
754
     */
755
    public function hideDefaultLocaleInURL()
756
    {
757
        return $this->configRepository->get('laravellocalization.hideDefaultLocaleInURL');
758
    }
759
760
    /**
761
     * Create an url from the uri.
762
     *
763
     * @param string $uri Uri
764
     *
765
     * @return string Url for the given uri
766
     */
767
    public function createUrlFromUri($uri)
768
    {
769
        $uri = ltrim($uri, '/');
770
771
        if (empty($this->baseUrl)) {
772
            return app('url')->to($uri);
773
        }
774
775
        return $this->baseUrl.$uri;
776
    }
777
778
    /**
779
     * Sets the base url for the site.
780
     *
781
     * @param string $url Base url for the site
782
     */
783
    public function setBaseUrl($url)
784
    {
785
        if (substr($url, -1) != '/') {
786
            $url .= '/';
787
        }
788
789
        $this->baseUrl = $url;
790
    }
791
792
    /**
793
     * Returns serialized translated routes for caching purposes.
794
     *
795
     * @return string
796
     */
797
    public function getSerializedTranslatedRoutes()
798
    {
799
        return base64_encode(serialize($this->translatedRoutes));
800
    }
801
802
    /**
803
     * Sets the translated routes list.
804
     * Only useful from a cached routes context.
805
     *
806
     * @param string $serializedRoutes
807
     */
808
    public function setSerializedTranslatedRoutes($serializedRoutes)
809
    {
810
        if ( ! $serializedRoutes) {
811
            return;
812
        }
813
814
        $this->translatedRoutes = unserialize(base64_decode($serializedRoutes));
815
    }
816
817
    /**
818
     * Extract attributes for current url.
819
     *
820
     * @param bool|false|null|string $url    to extract attributes, if not present, the system will look for attributes in the current call
821
     * @param string                 $locale
822
     *
823
     * @return array Array with attributes
824
     */
825
    protected function extractAttributes($url = false, $locale = '')
826
    {
827
        if (!empty($url)) {
828
            $attributes = [];
829
            $parse = parse_url($url);
830
            if (isset($parse['path'])) {
831
                $parse['path'] = trim(str_replace('/'.$this->currentLocale.'/', '', $parse['path']), "/");
832
                $url = explode('/', trim($parse['path'], '/'));
833
            } else {
834
                $url = [];
835
            }
836
837
            foreach ($this->router->getRoutes() as $route) {
838
                $attributes = [];
839
                $path = method_exists($route, 'uri') ? $route->uri() : $route->getUri();
840
841
                if (!preg_match("/{[\w]+\??}/", $path)) {
842
                    continue;
843
                }
844
845
                $path = explode('/', $path);
846
                $i = 0;
847
848
                // The system's route can't be smaller
849
                // only the $url can be missing segments (optional parameters)
850
                // We can assume it's the wrong route
851
                if (count($path) < count($url)) {
852
                    continue;
853
                }
854
855
                $match = true;
856
                foreach ($path as $j => $segment) {
857
                    if (isset($url[$i])) {
858
                        if ($segment === $url[$i]) {
859
                            $i++;
860
                            continue;
861 View Code Duplication
                        } elseif (preg_match("/{[\w]+}/", $segment)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
862
                            // must-have parameters
863
                            $attribute_name = preg_replace(['/}/', '/{/', "/\?/"], '', $segment);
864
                            $attributes[$attribute_name] = $url[$i];
865
                            $i++;
866
                            continue;
867
                        } elseif (preg_match("/{[\w]+\?}/", $segment)) {
868
                            // optional parameters
869
                            if (!isset($path[$j + 1]) || $path[$j + 1] !== $url[$i]) {
870
                                // optional parameter taken
871
                                $attribute_name = preg_replace(['/}/', '/{/', "/\?/"], '', $segment);
872
                                $attributes[$attribute_name] = $url[$i];
873
                                $i++;
874
                                continue;
875
                            } else {
876
                                $match = false;
877
                                break;
878
                            }
879
                        } else {
880
                            // As soon as one segment doesn't match, then we have the wrong route
881
                            $match = false;
882
                            break;
883
                        }
884 View Code Duplication
                    } elseif (preg_match("/{[\w]+\?}/", $segment)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
885
                        $attribute_name = preg_replace(['/}/', '/{/', "/\?/"], '', $segment);
886
                        $attributes[$attribute_name] = null;
887
                        $i++;
888
                    } else {
889
                        // no optional parameters but no more $url given
890
                        // this route does not match the url
891
                        $match = false;
892
                        break;
893
                    }
894
                }
895
896
                if (isset($url[$i + 1])) {
897
                    $match = false;
898
                }
899
900
                if ($match) {
901
                    return $attributes;
902
                }
903
            }
904
        } else {
905
            if (!$this->router->current()) {
906
                return [];
907
            }
908
909
            $attributes = $this->normalizeAttributes($this->router->current()->parameters());
910
            $response = event('routes.translation', [$locale, $attributes]);
911
912
            if (!empty($response)) {
913
                $response = array_shift($response);
914
            }
915
916
            if (\is_array($response)) {
917
                $attributes = array_merge($attributes, $response);
918
            }
919
        }
920
921
        return $attributes;
922
    }
923
924
    /**
925
     * Build URL using array data from parse_url.
926
     *
927
     * @param array|false $parsed_url Array of data from parse_url function
928
     *
929
     * @return string Returns URL as string.
930
     */
931
    protected function unparseUrl($parsed_url)
932
    {
933
        if (empty($parsed_url)) {
934
            return '';
935
        }
936
937
        $url = '';
938
        $url .= isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://' : '';
939
        $url .= $parsed_url['host'] ?? '';
940
        $url .= isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
941
        $user = $parsed_url['user'] ?? '';
942
        $pass = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
943
        $url .= $user.(($user || $pass) ? "$pass@" : '');
944
945
        if (!empty($url)) {
946
            $url .= isset($parsed_url['path']) ? '/'.ltrim($parsed_url['path'], '/') : '';
947
        } else {
948
            $url .= $parsed_url['path'] ?? '';
949
        }
950
951
        $url .= isset($parsed_url['query']) ? '?'.$parsed_url['query'] : '';
952
        $url .= isset($parsed_url['fragment']) ? '#'.$parsed_url['fragment'] : '';
953
954
        return $url;
955
    }
956
957
    /**
958
    * Normalize attributes gotten from request parameters.
959
    *
960
    * @param      array  $attributes  The attributes
961
    * @return     array  The normalized attributes
962
    */
963
     protected function normalizeAttributes($attributes)
964
     {
965
         if (array_key_exists('data', $attributes) && \is_array($attributes['data']) && ! \count($attributes['data'])) {
966
             $attributes['data'] = null;
967
             return $attributes;
968
         }
969
         return $attributes;
970
     }
971
972
    /**
973
     * Returns the forced environment set route locale.
974
     *
975
     * @return string|null
976
     */
977
    protected function getForcedLocale()
978
    {
979
        return env(static::ENV_ROUTE_KEY, function () {
980
            $value = getenv(static::ENV_ROUTE_KEY);
981
982
            if ($value !== false) {
983
                return $value;
984
            }
985
        });
986
    }
987
}
988