Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Routing;
4
 
5
use Illuminate\Routing\Exceptions\UrlGenerationException;
6
use Illuminate\Support\Arr;
7
 
8
class RouteUrlGenerator
9
{
10
    /**
11
     * The URL generator instance.
12
     *
13
     * @var \Illuminate\Routing\UrlGenerator
14
     */
15
    protected $url;
16
 
17
    /**
18
     * The request instance.
19
     *
20
     * @var \Illuminate\Http\Request
21
     */
22
    protected $request;
23
 
24
    /**
25
     * The named parameter defaults.
26
     *
27
     * @var array
28
     */
29
    public $defaultParameters = [];
30
 
31
    /**
32
     * Characters that should not be URL encoded.
33
     *
34
     * @var array
35
     */
36
    public $dontEncode = [
37
        '%2F' => '/',
38
        '%40' => '@',
39
        '%3A' => ':',
40
        '%3B' => ';',
41
        '%2C' => ',',
42
        '%3D' => '=',
43
        '%2B' => '+',
44
        '%21' => '!',
45
        '%2A' => '*',
46
        '%7C' => '|',
47
        '%3F' => '?',
48
        '%26' => '&',
49
        '%23' => '#',
50
        '%25' => '%',
51
    ];
52
 
53
    /**
54
     * Create a new Route URL generator.
55
     *
56
     * @param  \Illuminate\Routing\UrlGenerator  $url
57
     * @param  \Illuminate\Http\Request  $request
58
     * @return void
59
     */
60
    public function __construct($url, $request)
61
    {
62
        $this->url = $url;
63
        $this->request = $request;
64
    }
65
 
66
    /**
67
     * Generate a URL for the given route.
68
     *
69
     * @param  \Illuminate\Routing\Route  $route
70
     * @param  array  $parameters
71
     * @param  bool  $absolute
72
     * @return string
73
     *
74
     * @throws \Illuminate\Routing\Exceptions\UrlGenerationException
75
     */
76
    public function to($route, $parameters = [], $absolute = false)
77
    {
78
        $domain = $this->getRouteDomain($route, $parameters);
79
 
80
        // First we will construct the entire URI including the root and query string. Once it
81
        // has been constructed, we'll make sure we don't have any missing parameters or we
82
        // will need to throw the exception to let the developers know one was not given.
83
        $uri = $this->addQueryString($this->url->format(
84
            $root = $this->replaceRootParameters($route, $domain, $parameters),
85
            $this->replaceRouteParameters($route->uri(), $parameters),
86
            $route
87
        ), $parameters);
88
 
89
        if (preg_match_all('/{(.*?)}/', $uri, $matchedMissingParameters)) {
90
            throw UrlGenerationException::forMissingParameters($route, $matchedMissingParameters[1]);
91
        }
92
 
93
        // Once we have ensured that there are no missing parameters in the URI we will encode
94
        // the URI and prepare it for returning to the developer. If the URI is supposed to
95
        // be absolute, we will return it as-is. Otherwise we will remove the URL's root.
96
        $uri = strtr(rawurlencode($uri), $this->dontEncode);
97
 
98
        if (! $absolute) {
99
            $uri = preg_replace('#^(//|[^/?])+#', '', $uri);
100
 
101
            if ($base = $this->request->getBaseUrl()) {
102
                $uri = preg_replace('#^'.$base.'#i', '', $uri);
103
            }
104
 
105
            return '/'.ltrim($uri, '/');
106
        }
107
 
108
        return $uri;
109
    }
110
 
111
    /**
112
     * Get the formatted domain for a given route.
113
     *
114
     * @param  \Illuminate\Routing\Route  $route
115
     * @param  array  $parameters
116
     * @return string
117
     */
118
    protected function getRouteDomain($route, &$parameters)
119
    {
120
        return $route->getDomain() ? $this->formatDomain($route, $parameters) : null;
121
    }
122
 
123
    /**
124
     * Format the domain and port for the route and request.
125
     *
126
     * @param  \Illuminate\Routing\Route  $route
127
     * @param  array  $parameters
128
     * @return string
129
     */
130
    protected function formatDomain($route, &$parameters)
131
    {
132
        return $this->addPortToDomain(
133
            $this->getRouteScheme($route).$route->getDomain()
134
        );
135
    }
136
 
137
    /**
138
     * Get the scheme for the given route.
139
     *
140
     * @param  \Illuminate\Routing\Route  $route
141
     * @return string
142
     */
143
    protected function getRouteScheme($route)
144
    {
145
        if ($route->httpOnly()) {
146
            return 'http://';
147
        } elseif ($route->httpsOnly()) {
148
            return 'https://';
149
        }
150
 
151
        return $this->url->formatScheme();
152
    }
153
 
154
    /**
155
     * Add the port to the domain if necessary.
156
     *
157
     * @param  string  $domain
158
     * @return string
159
     */
160
    protected function addPortToDomain($domain)
161
    {
162
        $secure = $this->request->isSecure();
163
 
164
        $port = (int) $this->request->getPort();
165
 
166
        return ($secure && $port === 443) || (! $secure && $port === 80)
167
                    ? $domain : $domain.':'.$port;
168
    }
169
 
170
    /**
171
     * Replace the parameters on the root path.
172
     *
173
     * @param  \Illuminate\Routing\Route  $route
174
     * @param  string  $domain
175
     * @param  array  $parameters
176
     * @return string
177
     */
178
    protected function replaceRootParameters($route, $domain, &$parameters)
179
    {
180
        $scheme = $this->getRouteScheme($route);
181
 
182
        return $this->replaceRouteParameters(
183
            $this->url->formatRoot($scheme, $domain), $parameters
184
        );
185
    }
186
 
187
    /**
188
     * Replace all of the wildcard parameters for a route path.
189
     *
190
     * @param  string  $path
191
     * @param  array  $parameters
192
     * @return string
193
     */
194
    protected function replaceRouteParameters($path, array &$parameters)
195
    {
196
        $path = $this->replaceNamedParameters($path, $parameters);
197
 
198
        $path = preg_replace_callback('/\{.*?\}/', function ($match) use (&$parameters) {
199
            // Reset only the numeric keys...
200
            $parameters = array_merge($parameters);
201
 
202
            return (! isset($parameters[0]) && ! str_ends_with($match[0], '?}'))
203
                        ? $match[0]
204
                        : Arr::pull($parameters, 0);
205
        }, $path);
206
 
207
        return trim(preg_replace('/\{.*?\?\}/', '', $path), '/');
208
    }
209
 
210
    /**
211
     * Replace all of the named parameters in the path.
212
     *
213
     * @param  string  $path
214
     * @param  array  $parameters
215
     * @return string
216
     */
217
    protected function replaceNamedParameters($path, &$parameters)
218
    {
219
        return preg_replace_callback('/\{(.*?)(\?)?\}/', function ($m) use (&$parameters) {
220
            if (isset($parameters[$m[1]]) && $parameters[$m[1]] !== '') {
221
                return Arr::pull($parameters, $m[1]);
222
            } elseif (isset($this->defaultParameters[$m[1]])) {
223
                return $this->defaultParameters[$m[1]];
224
            } elseif (isset($parameters[$m[1]])) {
225
                Arr::pull($parameters, $m[1]);
226
            }
227
 
228
            return $m[0];
229
        }, $path);
230
    }
231
 
232
    /**
233
     * Add a query string to the URI.
234
     *
235
     * @param  string  $uri
236
     * @param  array  $parameters
237
     * @return mixed|string
238
     */
239
    protected function addQueryString($uri, array $parameters)
240
    {
241
        // If the URI has a fragment we will move it to the end of this URI since it will
242
        // need to come after any query string that may be added to the URL else it is
243
        // not going to be available. We will remove it then append it back on here.
244
        if (! is_null($fragment = parse_url($uri, PHP_URL_FRAGMENT))) {
245
            $uri = preg_replace('/#.*/', '', $uri);
246
        }
247
 
248
        $uri .= $this->getRouteQueryString($parameters);
249
 
250
        return is_null($fragment) ? $uri : $uri."#{$fragment}";
251
    }
252
 
253
    /**
254
     * Get the query string for a given route.
255
     *
256
     * @param  array  $parameters
257
     * @return string
258
     */
259
    protected function getRouteQueryString(array $parameters)
260
    {
261
        // First we will get all of the string parameters that are remaining after we
262
        // have replaced the route wildcards. We'll then build a query string from
263
        // these string parameters then use it as a starting point for the rest.
264
        if (count($parameters) === 0) {
265
            return '';
266
        }
267
 
268
        $query = Arr::query(
269
            $keyed = $this->getStringParameters($parameters)
270
        );
271
 
272
        // Lastly, if there are still parameters remaining, we will fetch the numeric
273
        // parameters that are in the array and add them to the query string or we
274
        // will make the initial query string if it wasn't started with strings.
275
        if (count($keyed) < count($parameters)) {
276
            $query .= '&'.implode(
277
                '&', $this->getNumericParameters($parameters)
278
            );
279
        }
280
 
281
        $query = trim($query, '&');
282
 
283
        return $query === '' ? '' : "?{$query}";
284
    }
285
 
286
    /**
287
     * Get the string parameters from a given list.
288
     *
289
     * @param  array  $parameters
290
     * @return array
291
     */
292
    protected function getStringParameters(array $parameters)
293
    {
294
        return array_filter($parameters, 'is_string', ARRAY_FILTER_USE_KEY);
295
    }
296
 
297
    /**
298
     * Get the numeric parameters from a given list.
299
     *
300
     * @param  array  $parameters
301
     * @return array
302
     */
303
    protected function getNumericParameters(array $parameters)
304
    {
305
        return array_filter($parameters, 'is_numeric', ARRAY_FILTER_USE_KEY);
306
    }
307
 
308
    /**
309
     * Set the default named parameters used by the URL generator.
310
     *
311
     * @param  array  $defaults
312
     * @return void
313
     */
314
    public function defaults(array $defaults)
315
    {
316
        $this->defaultParameters = array_merge(
317
            $this->defaultParameters, $defaults
318
        );
319
    }
320
}