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 ( c5671c...6d0865 )
by Marc
20:32 queued 05:03
created

LaravelLocalization::isHiddenDefault()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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