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.
Completed
Push — master ( 54405e...4eecae )
by Marc
02:12 queued 24s
created

setSerializedTranslatedRoutes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
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
     * Creates new instance.
110
     *
111
     * @throws UnsupportedLocaleException
112
     */
113
    public function __construct()
114
    {
115
        $this->app = app();
116
117
        $this->configRepository = $this->app['config'];
118
        $this->view = $this->app['view'];
119
        $this->translator = $this->app['translator'];
120
        $this->router = $this->app['router'];
121
        $this->request = $this->app['request'];
122
        $this->url = $this->app['url'];
123
124
        // set default locale
125
        $this->defaultLocale = $this->configRepository->get('app.locale');
126
        $supportedLocales = $this->getSupportedLocales();
127
128
        if (empty($supportedLocales[$this->defaultLocale])) {
129
            throw new UnsupportedLocaleException('Laravel default locale is not in the supportedLocales array.');
130
        }
131
    }
132
133
    /**
134
     * Set and return current locale.
135
     *
136
     * @param string $locale Locale to set the App to (optional)
137
     *
138
     * @return string Returns locale (if route has any) or null (if route does not have a locale)
139
     */
140
    public function setLocale($locale = null)
141
    {
142
        if (empty($locale) || !\is_string($locale)) {
143
            // If the locale has not been passed through the function
144
            // it tries to get it from the first segment of the url
145
            $locale = $this->request->segment(1);
146
147
            // If the locale is determined by env, use that
148
            // Note that this is how per-locale route caching is performed.
149
            if ( ! $locale) {
150
                $locale = $this->getForcedLocale();
151
            }
152
        }
153
154
        if (!empty($this->supportedLocales[$locale])) {
155
            $this->currentLocale = $locale;
156
        } else {
157
            // if the first segment/locale passed is not valid
158
            // the system would ask which locale have to take
159
            // it could be taken by the browser
160
            // depending on your configuration
161
162
            $locale = null;
163
164
            // if we reached this point and hideDefaultLocaleInURL is true
165
            // we have to assume we are routing to a defaultLocale route.
166
            if ($this->hideDefaultLocaleInURL()) {
167
                $this->currentLocale = $this->defaultLocale;
168
            }
169
            // but if hideDefaultLocaleInURL is false, we have
170
            // to retrieve it from the browser...
171
            else {
172
                $this->currentLocale = $this->getCurrentLocale();
173
            }
174
        }
175
176
        $this->app->setLocale($this->currentLocale);
177
178
        // Regional locale such as de_DE, so formatLocalized works in Carbon
179
        $regional = $this->getCurrentLocaleRegional();
180
        $suffix = $this->configRepository->get('laravellocalization.utf8suffix');
181
        if ($regional) {
182
            setlocale(LC_TIME, $regional . $suffix);
183
            setlocale(LC_MONETARY, $regional . $suffix);
184
        }
185
186
        return $locale;
187
    }
188
189
    /**
190
     * Set and return supported locales.
191
     *
192
     * @param array $locales Locales that the App supports
193
     */
194
    public function setSupportedLocales($locales)
195
    {
196
        $this->supportedLocales = $locales;
197
    }
198
199
    /**
200
     * Returns an URL adapted to $locale or current locale.
201
     *
202
     * @param string      $url    URL to adapt. If not passed, the current url would be taken.
203
     * @param string|bool $locale Locale to adapt, false to remove locale
204
     *
205
     * @throws UnsupportedLocaleException
206
     *
207
     * @return string URL translated
208
     */
209
    public function localizeURL($url = null, $locale = null)
210
    {
211
        return $this->getLocalizedURL($locale, $url);
212
    }
213
214
    /**
215
     * Returns an URL adapted to $locale.
216
     *
217
     *
218
     * @param string|bool  $locale     Locale to adapt, false to remove locale
219
     * @param string|false $url        URL to adapt in the current language. If not passed, the current url would be taken.
220
     * @param array        $attributes Attributes to add to the route, if empty, the system would try to extract them from the url.
221
     * @param bool         $forceDefaultLocation Force to show default location even hideDefaultLocaleInURL set as TRUE
222
     *
223
     * @throws SupportedLocalesNotDefined
224
     * @throws UnsupportedLocaleException
225
     *
226
     * @return string|false URL translated, False if url does not exist
227
     */
228
    public function getLocalizedURL($locale = null, $url = null, $attributes = [], $forceDefaultLocation = false)
229
    {
230
        if ($locale === null) {
231
            $locale = $this->getCurrentLocale();
232
        }
233
234
        if (!$this->checkLocaleInSupportedLocales($locale)) {
235
            throw new UnsupportedLocaleException('Locale \''.$locale.'\' is not in the list of supported locales.');
236
        }
237
238
        if (empty($attributes)) {
239
            $attributes = $this->extractAttributes($url, $locale);
0 ignored issues
show
Bug introduced by
It seems like $locale defined by parameter $locale on line 228 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...
240
        }
241
242
        if (empty($url)) {
243
            if (!empty($this->routeName)) {
244
                return $this->getURLFromRouteNameTranslated($locale, $this->routeName, $attributes, $forceDefaultLocation);
245
            }
246
247
            $url = $this->request->fullUrl();
248
        } else {
249
            $url = $this->url->to($url);
250
        }
251
252
        if ($locale && $translatedRoute = $this->findTranslatedRouteByUrl($url, $attributes, $this->currentLocale)) {
253
            return $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes, $forceDefaultLocation);
254
        }
255
256
        $base_path = $this->request->getBaseUrl();
257
        $parsed_url = parse_url($url);
258
        $url_locale = $this->getDefaultLocale();
259
260
        if (!$parsed_url || empty($parsed_url['path'])) {
261
            $path = $parsed_url['path'] = '';
262
        } else {
263
            $parsed_url['path'] = str_replace($base_path, '', '/'.ltrim($parsed_url['path'], '/'));
264
            $path = $parsed_url['path'];
265
            foreach ($this->getSupportedLocales() as $localeCode => $lang) {
266
                $parsed_url['path'] = preg_replace('%^/?'.$localeCode.'/%', '$1', $parsed_url['path']);
267
                if ($parsed_url['path'] !== $path) {
268
                    $url_locale = $localeCode;
269
                    break;
270
                }
271
272
                $parsed_url['path'] = preg_replace('%^/?'.$localeCode.'$%', '$1', $parsed_url['path']);
273
                if ($parsed_url['path'] !== $path) {
274
                    $url_locale = $localeCode;
275
                    break;
276
                }
277
            }
278
        }
279
280
        $parsed_url['path'] = ltrim($parsed_url['path'], '/');
281
282
        if ($translatedRoute = $this->findTranslatedRouteByPath($parsed_url['path'], $url_locale)) {
283
            return $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes, $forceDefaultLocation);
284
        }
285
286
	    if (!empty($locale)) {
287
            if ($forceDefaultLocation || $locale != $this->getDefaultLocale() || !$this->hideDefaultLocaleInURL()) {
288
                $parsed_url['path'] = $locale.'/'.ltrim($parsed_url['path'], '/');
289
            }
290
        }
291
        $parsed_url['path'] = ltrim(ltrim($base_path, '/').'/'.$parsed_url['path'], '/');
292
293
        //Make sure that the pass path is returned with a leading slash only if it come in with one.
294
        if (starts_with($path, '/') === true) {
295
            $parsed_url['path'] = '/'.$parsed_url['path'];
296
        }
297
        $parsed_url['path'] = rtrim($parsed_url['path'], '/');
298
299
        $url = $this->unparseUrl($parsed_url);
300
301
        if ($this->checkUrl($url)) {
302
            return $url;
303
        }
304
305
        return $this->createUrlFromUri($url);
306
    }
307
308
    /**
309
     * Returns an URL adapted to the route name and the locale given.
310
     *
311
     *
312
     * @param string|bool $locale       Locale to adapt
313
     * @param string      $transKeyName Translation key name of the url to adapt
314
     * @param array       $attributes   Attributes for the route (only needed if transKeyName needs them)
315
     * @param bool        $forceDefaultLocation Force to show default location even hideDefaultLocaleInURL set as TRUE
316
     *
317
     * @throws SupportedLocalesNotDefined
318
     * @throws UnsupportedLocaleException
319
     *
320
     * @return string|false URL translated
321
     */
322
    public function getURLFromRouteNameTranslated($locale, $transKeyName, $attributes = [], $forceDefaultLocation = false)
323
    {
324
        if (!$this->checkLocaleInSupportedLocales($locale)) {
325
            throw new UnsupportedLocaleException('Locale \''.$locale.'\' is not in the list of supported locales.');
326
        }
327
328
        if (!\is_string($locale)) {
329
            $locale = $this->getDefaultLocale();
330
        }
331
332
        $route = '';
333
334
        if ($forceDefaultLocation || !($locale === $this->defaultLocale && $this->hideDefaultLocaleInURL())) {
335
            $route = '/'.$locale;
336
        }
337
        if (\is_string($locale) && $this->translator->has($transKeyName, $locale)) {
338
            $translation = $this->translator->trans($transKeyName, [], $locale);
339
            $route .= '/'.$translation;
340
341
            $route = $this->substituteAttributesInRoute($attributes, $route);
342
        }
343
344
        if (empty($route)) {
345
            // This locale does not have any key for this route name
346
            return false;
347
        }
348
349
        return rtrim($this->createUrlFromUri($route));
350
    }
351
352
    /**
353
     * It returns an URL without locale (if it has it)
354
     * Convenience function wrapping getLocalizedURL(false).
355
     *
356
     * @param string|false $url URL to clean, if false, current url would be taken
357
     *
358
     * @return string URL with no locale in path
359
     */
360
    public function getNonLocalizedURL($url = null)
361
    {
362
        return $this->getLocalizedURL(false, $url);
363
    }
364
365
    /**
366
     * Returns default locale.
367
     *
368
     * @return string
369
     */
370
    public function getDefaultLocale()
371
    {
372
        return $this->defaultLocale;
373
    }
374
375
    /**
376
     * Return an array of all supported Locales.
377
     *
378
     * @throws SupportedLocalesNotDefined
379
     *
380
     * @return array
381
     */
382
    public function getSupportedLocales()
383
    {
384
        if (!empty($this->supportedLocales)) {
385
            return $this->supportedLocales;
386
        }
387
388
        $locales = $this->configRepository->get('laravellocalization.supportedLocales');
389
390
        if (empty($locales) || !\is_array($locales)) {
391
            throw new SupportedLocalesNotDefined();
392
        }
393
394
        $this->supportedLocales = $locales;
395
396
        return $locales;
397
    }
398
399
    /**
400
     * Return an array of all supported Locales but in the order the user
401
     * has specified in the config file. Useful for the language selector.
402
     *
403
     * @return array
404
     */
405
    public function getLocalesOrder()
406
    {
407
        $locales = $this->getSupportedLocales();
408
409
        $order = $this->configRepository->get('laravellocalization.localesOrder');
410
411
        uksort($locales, function ($a, $b) use ($order) {
412
            $pos_a = array_search($a, $order);
413
            $pos_b = array_search($b, $order);
414
            return $pos_a - $pos_b;
415
        });
416
417
        return $locales;
418
    }
419
420
    /**
421
     * Returns current locale name.
422
     *
423
     * @return string current locale name
424
     */
425
    public function getCurrentLocaleName()
426
    {
427
        return $this->supportedLocales[$this->getCurrentLocale()]['name'];
428
    }
429
430
    /**
431
     * Returns current locale native name.
432
     *
433
     * @return string current locale native name
434
     */
435
    public function getCurrentLocaleNative()
436
    {
437
        return $this->supportedLocales[$this->getCurrentLocale()]['native'];
438
    }
439
440
    /**
441
     * Returns current locale direction.
442
     *
443
     * @return string current locale direction
444
     */
445
    public function getCurrentLocaleDirection()
446
    {
447
        if (!empty($this->supportedLocales[$this->getCurrentLocale()]['dir'])) {
448
            return $this->supportedLocales[$this->getCurrentLocale()]['dir'];
449
        }
450
451
        switch ($this->getCurrentLocaleScript()) {
452
            // Other (historic) RTL scripts exist, but this list contains the only ones in current use.
453
            case 'Arab':
454
            case 'Hebr':
455
            case 'Mong':
456
            case 'Tfng':
457
            case 'Thaa':
458
            return 'rtl';
459
            default:
460
            return 'ltr';
461
        }
462
    }
463
464
    /**
465
     * Returns current locale script.
466
     *
467
     * @return string current locale script
468
     */
469
    public function getCurrentLocaleScript()
470
    {
471
        return $this->supportedLocales[$this->getCurrentLocale()]['script'];
472
    }
473
474
    /**
475
     * Returns current language's native reading.
476
     *
477
     * @return string current language's native reading
478
     */
479
    public function getCurrentLocaleNativeReading()
480
    {
481
        return $this->supportedLocales[$this->getCurrentLocale()]['native'];
482
    }
483
484
    /**
485
     * Returns current language.
486
     *
487
     * @return string current language
488
     */
489
    public function getCurrentLocale()
490
    {
491
        if ($this->currentLocale) {
492
            return $this->currentLocale;
493
        }
494
495
        if ($this->useAcceptLanguageHeader() && !$this->app->runningInConsole()) {
496
            $negotiator = new LanguageNegotiator($this->defaultLocale, $this->getSupportedLocales(), $this->request);
497
498
            return $negotiator->negotiateLanguage();
499
        }
500
501
        // or get application default language
502
        return $this->configRepository->get('app.locale');
503
    }
504
505
    /**
506
     * Returns current regional.
507
     *
508
     * @return string current regional
509
     */
510
    public function getCurrentLocaleRegional()
511
    {
512
        // need to check if it exists, since 'regional' has been added
513
        // after version 1.0.11 and existing users will not have it
514
        if (isset($this->supportedLocales[$this->getCurrentLocale()]['regional'])) {
515
            return $this->supportedLocales[$this->getCurrentLocale()]['regional'];
516
        } else {
517
            return;
518
        }
519
    }
520
521
    /**
522
     * Returns supported languages language key.
523
     *
524
     * @return array keys of supported languages
525
     */
526
    public function getSupportedLanguagesKeys()
527
    {
528
        return array_keys($this->supportedLocales);
529
    }
530
531
    /**
532
     * Check if Locale exists on the supported locales array.
533
     *
534
     * @param string|bool $locale string|bool Locale to be checked
535
     *
536
     * @throws SupportedLocalesNotDefined
537
     *
538
     * @return bool is the locale supported?
539
     */
540
    public function checkLocaleInSupportedLocales($locale)
541
    {
542
        $locales = $this->getSupportedLocales();
543
        if ($locale !== false && empty($locales[$locale])) {
544
            return false;
545
        }
546
547
        return true;
548
    }
549
550
    /**
551
     * Change route attributes for the ones in the $attributes array.
552
     *
553
     * @param $attributes array Array of attributes
554
     * @param string $route string route to substitute
555
     *
556
     * @return string route with attributes changed
557
     */
558
    protected function substituteAttributesInRoute($attributes, $route)
559
    {
560
        foreach ($attributes as $key => $value) {
561
            if ($value instanceOf UrlRoutable) {
562
                $value = $value->getRouteKey();
563
            }
564
            $route = str_replace(array('{'.$key.'}', '{'.$key.'?}'), $value, $route);
565
        }
566
567
        // delete empty optional arguments that are not in the $attributes array
568
        $route = preg_replace('/\/{[^)]+\?}/', '', $route);
569
570
        return $route;
571
    }
572
573
    /**
574
     * Returns translated routes.
575
     *
576
     * @return array translated routes
577
     */
578
    protected function getTranslatedRoutes()
579
    {
580
        return $this->translatedRoutes;
581
    }
582
583
    /**
584
     * Set current route name.
585
     *
586
     * @param string $routeName current route name
587
     */
588
    public function setRouteName($routeName)
589
    {
590
        $this->routeName = $routeName;
591
    }
592
593
    /**
594
     * Translate routes and save them to the translated routes array (used in the localize route filter).
595
     *
596
     * @param string $routeName Key of the translated string
597
     *
598
     * @return string Translated string
599
     */
600
    public function transRoute($routeName)
601
    {
602
        if (!\in_array($routeName, $this->translatedRoutes)) {
603
            $this->translatedRoutes[] = $routeName;
604
        }
605
606
        return $this->translator->trans($routeName);
607
    }
608
609
    /**
610
     * Returns the translation key for a given path.
611
     *
612
     * @param string $path Path to get the key translated
613
     *
614
     * @return string|false Key for translation, false if not exist
615
     */
616
    public function getRouteNameFromAPath($path)
617
    {
618
        $attributes = $this->extractAttributes($path);
619
620
        $path = str_replace(url('/'), '', $path);
621
        if ($path[0] !== '/') {
622
            $path = '/'.$path;
623
        }
624
        $path = str_replace('/'.$this->currentLocale.'/', '', $path);
625
        $path = trim($path, '/');
626
627
        foreach ($this->translatedRoutes as $route) {
628
            if ($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...
629
                return $route;
630
            }
631
        }
632
633
        return false;
634
    }
635
636
    /**
637
     * Returns the translated route for the path and the url given.
638
     *
639
     * @param string $path       Path to check if it is a translated route
640
     * @param string $url_locale Language to check if the path exists
641
     *
642
     * @return string|false Key for translation, false if not exist
643
     */
644
    protected function findTranslatedRouteByPath($path, $url_locale)
645
    {
646
        // check if this url is a translated url
647
        foreach ($this->translatedRoutes as $translatedRoute) {
648
            if ($this->translator->trans($translatedRoute, [], $url_locale) == rawurldecode($path)) {
649
                return $translatedRoute;
650
            }
651
        }
652
653
        return false;
654
    }
655
656
    /**
657
     * Returns the translated route for an url and the attributes given and a locale.
658
     *
659
     *
660
     * @param string|false|null $url        Url to check if it is a translated route
661
     * @param array             $attributes Attributes to check if the url exists in the translated routes array
662
     * @param string            $locale     Language to check if the url exists
663
     *
664
     * @throws SupportedLocalesNotDefined
665
     * @throws UnsupportedLocaleException
666
     *
667
     * @return string|false Key for translation, false if not exist
668
     */
669
    protected function findTranslatedRouteByUrl($url, $attributes, $locale)
670
    {
671
        if (empty($url)) {
672
            return false;
673
        }
674
675
        // check if this url is a translated url
676
        foreach ($this->translatedRoutes as $translatedRoute) {
677
            $routeName = $this->getURLFromRouteNameTranslated($locale, $translatedRoute, $attributes);
678
679
            if ($this->getNonLocalizedURL($routeName) == $this->getNonLocalizedURL($url)) {
680
                return $translatedRoute;
681
            }
682
        }
683
684
        return false;
685
    }
686
687
    /**
688
     * Returns true if the string given is a valid url.
689
     *
690
     * @param string $url String to check if it is a valid url
691
     *
692
     * @return bool Is the string given a valid url?
693
     */
694
    protected function checkUrl($url)
695
    {
696
        return filter_var($url, FILTER_VALIDATE_URL);
697
    }
698
699
    /**
700
     * Returns the config repository for this instance.
701
     *
702
     * @return Repository Configuration repository
703
     */
704
    public function getConfigRepository()
705
    {
706
        return $this->configRepository;
707
    }
708
709
    /**
710
     * Returns the translation key for a given path.
711
     *
712
     * @return bool Returns value of useAcceptLanguageHeader in config.
713
     */
714
    protected function useAcceptLanguageHeader()
715
    {
716
        return $this->configRepository->get('laravellocalization.useAcceptLanguageHeader');
717
    }
718
719
    /**
720
     * Returns the translation key for a given path.
721
     *
722
     * @return bool Returns value of hideDefaultLocaleInURL in config.
723
     */
724
    public function hideDefaultLocaleInURL()
725
    {
726
        return $this->configRepository->get('laravellocalization.hideDefaultLocaleInURL');
727
    }
728
729
    /**
730
     * Create an url from the uri.
731
     *
732
     * @param string $uri Uri
733
     *
734
     * @return string Url for the given uri
735
     */
736
    public function createUrlFromUri($uri)
737
    {
738
        $uri = ltrim($uri, '/');
739
740
        if (empty($this->baseUrl)) {
741
            return app('url')->to($uri);
742
        }
743
744
        return $this->baseUrl.$uri;
745
    }
746
747
    /**
748
     * Sets the base url for the site.
749
     *
750
     * @param string $url Base url for the site
751
     */
752
    public function setBaseUrl($url)
753
    {
754
        if (substr($url, -1) != '/') {
755
            $url .= '/';
756
        }
757
758
        $this->baseUrl = $url;
759
    }
760
761
    /**
762
     * Returns serialized translated routes for caching purposes.
763
     *
764
     * @return string
765
     */
766
    public function getSerializedTranslatedRoutes()
767
    {
768
        return base64_encode(serialize($this->translatedRoutes));
769
    }
770
771
    /**
772
     * Sets the translated routes list.
773
     * Only useful from a cached routes context.
774
     *
775
     * @param string $serializedRoutes
776
     */
777
    public function setSerializedTranslatedRoutes($serializedRoutes)
778
    {
779
        if ( ! $serializedRoutes) {
780
            return;
781
        }
782
783
        $this->translatedRoutes = unserialize(base64_decode($serializedRoutes));
784
    }
785
786
    /**
787
     * Extract attributes for current url.
788
     *
789
     * @param bool|false|null|string $url    to extract attributes, if not present, the system will look for attributes in the current call
790
     * @param string                 $locale
791
     *
792
     * @return array Array with attributes
793
     */
794
    protected function extractAttributes($url = false, $locale = '')
795
    {
796
        if (!empty($url)) {
797
            $attributes = [];
798
            $parse = parse_url($url);
799
            if (isset($parse['path'])) {
800
                $parse = explode('/', $parse['path']);
801
            } else {
802
                $parse = [];
803
            }
804
            $url = [];
805
            foreach ($parse as $segment) {
806
                if (!empty($segment)) {
807
                    $url[] = $segment;
808
                }
809
            }
810
811
            foreach ($this->router->getRoutes() as $route) {
812
                $path = method_exists($route, 'uri') ? $route->uri() : $route->getUri();
813
814
                if (!preg_match("/{[\w]+}/", $path)) {
815
                    continue;
816
                }
817
818
                $path = explode('/', $path);
819
                $i = 0;
820
821
                $match = true;
822
                foreach ($path as $j => $segment) {
823
                    if (isset($url[$i])) {
824
                        if ($segment === $url[$i]) {
825
                            $i++;
826
                            continue;
827
                        }
828
                        if (preg_match("/{[\w]+}/", $segment)) {
829
                            // must-have parameters
830
                            $attribute_name = preg_replace(['/}/', '/{/', "/\?/"], '', $segment);
831
                            $attributes[$attribute_name] = $url[$i];
832
                            $i++;
833
                            continue;
834
                        }
835
                        if (preg_match("/{[\w]+\?}/", $segment)) {
836
                            // optional parameters
837
                            if (!isset($path[$j + 1]) || $path[$j + 1] !== $url[$i]) {
838
                                // optional parameter taken
839
                                $attribute_name = preg_replace(['/}/', '/{/', "/\?/"], '', $segment);
840
                                $attributes[$attribute_name] = $url[$i];
841
                                $i++;
842
                                continue;
843
                            }
844
                        }
845
                    } elseif (!preg_match("/{[\w]+\?}/", $segment)) {
846
                        // no optional parameters but no more $url given
847
                        // this route does not match the url
848
                        $match = false;
849
                        break;
850
                    }
851
                }
852
853
                if (isset($url[$i + 1])) {
854
                    $match = false;
855
                }
856
857
                if ($match) {
858
                    return $attributes;
859
                }
860
            }
861
        } else {
862
            if (!$this->router->current()) {
863
                return [];
864
            }
865
866
            $attributes = $this->normalizeAttributes($this->router->current()->parameters());
867
            $response = event('routes.translation', [$locale, $attributes]);
868
869
            if (!empty($response)) {
870
                $response = array_shift($response);
871
            }
872
873
            if (\is_array($response)) {
874
                $attributes = array_merge($attributes, $response);
875
            }
876
        }
877
878
        return $attributes;
879
    }
880
881
    /**
882
     * Build URL using array data from parse_url.
883
     *
884
     * @param array|false $parsed_url Array of data from parse_url function
885
     *
886
     * @return string Returns URL as string.
887
     */
888
    protected function unparseUrl($parsed_url)
889
    {
890
        if (empty($parsed_url)) {
891
            return '';
892
        }
893
894
        $url = '';
895
        $url .= isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://' : '';
896
        $url .= $parsed_url['host'] ?? '';
897
        $url .= isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
898
        $user = $parsed_url['user'] ?? '';
899
        $pass = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
900
        $url .= $user.(($user || $pass) ? "$pass@" : '');
901
902
        if (!empty($url)) {
903
            $url .= isset($parsed_url['path']) ? '/'.ltrim($parsed_url['path'], '/') : '';
904
        } else {
905
            $url .= $parsed_url['path'] ?? '';
906
        }
907
908
        $url .= isset($parsed_url['query']) ? '?'.$parsed_url['query'] : '';
909
        $url .= isset($parsed_url['fragment']) ? '#'.$parsed_url['fragment'] : '';
910
911
        return $url;
912
    }
913
914
    /**
915
    * Normalize attributes gotten from request parameters.
916
    *
917
    * @param      array  $attributes  The attributes
918
    * @return     array  The normalized attributes
919
    */
920
     protected function normalizeAttributes($attributes)
921
     {
922
         if (array_key_exists('data', $attributes) && \is_array($attributes['data']) && ! \count($attributes['data'])) {
923
             $attributes['data'] = null;
924
             return $attributes;
925
         }
926
         return $attributes;
927
     }
928
929
    /**
930
     * Returns the forced environment set route locale.
931
     *
932
     * @return string|null
933
     */
934
    protected function getForcedLocale()
935
    {
936
        return env(static::ENV_ROUTE_KEY);
937
    }
938
}
939