Passed
Push — master ( 8094df...219b00 )
by Ben
08:14
created

LocaleUrl::route()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
nc 10
nop 4
dl 0
loc 34
ccs 15
cts 15
cp 1
crap 7
rs 8.4426
c 0
b 0
f 0
1
<?php
2
3
namespace Thinktomorrow\Locale;
4
5
use Thinktomorrow\Locale\Parsers\LocaleSegmentParameter;
6
use Thinktomorrow\Locale\Parsers\RouteParser;
7
use Thinktomorrow\Locale\Parsers\UrlParser;
8
use Thinktomorrow\Locale\Values\Config;
9
10
class LocaleUrl
11
{
12
    /**
13
     * @var Scope
14
     */
15
    private $scope;
16
17
    /**
18
     * @var ScopeCollection
19
     */
20
    private $scopeCollection;
21
22
    /**
23
     * @var UrlParser
24
     */
25
    private $urlparser;
26
27
    /**
28
     * @var null|string
29
     */
30
    private $routeKey;
31
32
    /**
33
     * @var RouteParser
34
     */
35
    private $routeparser;
36
37
    /**
38
     * @var bool
39
     */
40
    private $forceSecure = false;
41
42 74
    public function __construct(Detect $detect, UrlParser $urlparser, RouteParser $routeparser, Config $config)
43
    {
44
        // TODO check if this still returns proper results when loading before routes
45 74
        $this->scope = $detect->getScope();
46 74
        $this->scopeCollection = ScopeCollection::fromConfig($config);
47 74
        $this->urlparser = $urlparser;
48 74
        $this->routeparser = $routeparser;
49
50 74
        $this->routeKey = $config->get('route_key');
51 74
        $this->forceSecure = $config->get('secure') === true;
52 74
    }
53
54
    /**
55
     * Generate a localized url.
56
     *
57
     * @param $url
58
     * @param null  $locale
59
     * @param array $parameters
60
     * @param null  $secure
61
     *
62
     * @return mixed
63
     */
64 8
    public function to($url, $locale = null, $parameters = [], $secure = null)
65
    {
66 8
        if (is_bool($secure)) {
67 1
            $this->urlparser->secure($secure);
68 7
        } elseif ($this->forceSecure) {
69 1
            $this->urlparser->secure();
70
        }
71
72 8
        return $this->urlparser->set($url)
73 8
            ->localize($this->scope->segment($locale), $this->scope->locales())
74 8
            ->parameters((array) $parameters)
75 8
            ->get();
76
    }
77
78
    /**
79
     * Generate a localized route.
80
     * Note that unlike the Illuminate route() no parameter for 'absolute' path is available
81
     * since urls will always be rendered as absolute ones.
82
     *
83
     * @param $name
84
     * @param null  $locale
85
     * @param array $parameters
86
     * @param bool  $asCanonical
87
     *
88
     * @return mixed
89
     */
90 26
    public function route($name, $locale = null, $parameters = [], $asCanonical = false)
91
    {
92 26
        $scope = $this->scope;
93 26
        $forceSecure = $this->forceSecure;
94 26
        $available_locales = $scope->locales();
95
96 26
        if ($asCanonical && $canonicalScope = $this->getCanonicalScope($locale)) {
97 9
            $scope = $canonicalScope;
98
99
            /**
100
             * In current scope the prefix is /test/ for fr but in passed canonical scope it is the default /
101
             * In canonical scope we have no knowledge of this being a locale segment so it is not removed by the parser.
102
             */
103 9
            $available_locales = array_merge($available_locales, $canonicalScope->locales());
104
105
            /**
106
             * Canonical that has no scheme will be forced as secure if set so in config.
107
             * If an explicit scheme is given, this is left unmodified in case of canonicals.
108
             */
109 9
            $forceSecure = $scope->customRoot() && $scope->customRoot()->scheme() ? false : $forceSecure;
0 ignored issues
show
Bug Best Practice introduced by
The expression $scope->customRoot()->scheme() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
110
        }
111
112 26
        $parameters = array_merge(LocaleSegmentParameter::normalizeLocaleAsParameter($scope, $this->routeKey, $locale), (array) $parameters);
113 26
        $localeSegment = LocaleSegmentParameter::extractLocaleSegmentFromParameters($scope, $this->routeKey, $parameters);
114
115 26
        $parser = $this->routeparser->set($name, $parameters, ($forceSecure) ? true : null)
116 26
            ->localize($localeSegment, $available_locales);
117
118 26
        if ($asCanonical) {
119 9
            $parser = $this->parseWithCanonicalScope($scope, $parser);
120
        }
121
122 26
        return $parser->get();
123
    }
124
125 6
    public function canonicalRoute($name, $locale = null, $parameters = [])
126
    {
127 6
        return $this->route($name, $locale, $parameters, true);
128
    }
129
130 9
    private function getCanonicalScope($locale = null): ?Scope
131
    {
132 9
        if ($canonicalScope = $this->scopeCollection->findCanonical($locale ?? $this->scope->activeLocale())) {
133 9
            return $canonicalScope;
134
        }
135
136 2
        return null;
137
    }
138
139 9
    private function parseWithCanonicalScope(Scope $scope, RouteParser $parser): RouteParser
140
    {
141 9
        if (!$scope->customRoot()) {
142 2
            return $parser;
143
        }
144
145 9
        return $parser->setCustomRoot($scope->customRoot());
146
    }
147
}
148