Passed
Pull Request — master (#4)
by Adam
02:03
created

UrlGenerator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Endeavors\Components\Routing;
4
5
use Illuminate\Contracts\Routing\UrlGenerator as UrlGeneratorContract;
6
use DateInterval;
7
use DateTimeInterface;
8
use Carbon\Carbon;
9
use Illuminate\Http\Request;
10
use Illuminate\Routing\RouteCollection;
11
use Illuminate\Contracts\Routing\UrlRoutable;
12
13
/**
14
 * Decorate the UrlGenerator for simplicity
15
 */
16
class UrlGenerator implements UrlGeneratorContract, IEnableRoutes
17
{
18
    private $originalUrlGenerator;
19
20
    public function __construct(UrlGeneratorContract $originalUrlGenerator)
21
    {
22
        $this->originalUrlGenerator = $originalUrlGenerator;
23
    }
24
25
    /**
26
     * Get the full URL for the current request.
27
     *
28
     * @return string
29
     */
30
    public function full()
31
    {
32
        return $this->originalUrlGenerator->full();
33
    }
34
35
    /**
36
     * Get the current URL for the request.
37
     *
38
     * @return string
39
     */
40
    public function current()
41
    {
42
        return $this->originalUrlGenerator->current();
43
    }
44
45
    /**
46
     * Get the URL for the previous request.
47
     *
48
     * @return string
49
     */
50
    public function previous($fallback = false)
51
    {
52
        return $this->originalUrlGenerator->previous($fallback);
53
    }
54
55
    /**
56
     * Generate a absolute URL to the given path.
57
     *
58
     * @param  string  $path
59
     * @param  mixed  $extra
60
     * @param  bool|null  $secure
61
     * @return string
62
     */
63
    public function to($path, $extra = array(), $secure = null)
64
    {
65
        return $this->originalUrlGenerator->to($path, $extra, $secure);
66
    }
67
68
    /**
69
     * Generate a secure, absolute URL to the given path.
70
     *
71
     * @param  string  $path
72
     * @param  array   $parameters
73
     * @return string
74
     */
75
    public function secure($path, $parameters = array())
76
    {
77
        return $this->originalUrlGenerator->secure($path, $parameters);
78
    }
79
80
    /**
81
     * Generate a URL to an application asset.
82
     *
83
     * @param  string  $path
84
     * @param  bool|null  $secure
85
     * @return string
86
     */
87
    public function asset($path, $secure = null)
88
    {
89
        return $this->originalUrlGenerator->asset($path, $secure);
90
    }
91
92
    /**
93
     * Generate a URL to a secure asset.
94
     *
95
     * @param  string  $path
96
     * @return string
97
     */
98
    public function secureAsset($path)
99
    {
100
        return $this->originalUrlGenerator->secureAsset($path);
101
    }
102
103
    /**
104
     * Force the schema for URLs.
105
     *
106
     * @param  string  $schema
107
     * @return void
108
     */
109
    public function forceSchema($schema)
110
    {
111
        $this->originalUrlGenerator->forceSchema($schema);
112
    }
113
114
    /**
115
     * Get the URL to a named route.
116
     *
117
     * @param  string  $name
118
     * @param  mixed   $parameters
119
     * @param  bool  $absolute
120
     * @param  \Illuminate\Routing\Route  $route
121
     * @return string
122
     *
123
     * @throws \InvalidArgumentException
124
     */
125
    public function route($name, $parameters = array(), $absolute = true, $route = null)
126
    {
127
        return $this->originalUrlGenerator->route($name, $parameters, $absolute, $route);
128
    }
129
130
    /**
131
     * Get the URL to a controller action.
132
     *
133
     * @param  string  $action
134
     * @param  mixed   $parameters
135
     * @param  bool    $absolute
136
     * @return string
137
     */
138
    public function action($action, $parameters = array(), $absolute = true)
139
    {
140
        return $this->originalUrlGenerator->action($action, $parameters, $absolute);
141
    }
142
143
    /**
144
     * Set the forced root URL.
145
     *
146
     * @param  string  $root
147
     * @return void
148
     */
149
    public function forceRootUrl($root)
150
    {
151
        $this->originalUrlGenerator->forceRootUrl($root);
152
    }
153
154
    /**
155
     * Determine if the given path is a valid URL.
156
     *
157
     * @param  string  $path
158
     * @return bool
159
     */
160
    public function isValidUrl($path)
161
    {
162
        return $this->originalUrlGenerator->isValidUrl($path);
163
    }
164
165
    /**
166
     * Get the request instance.
167
     *
168
     * @return \Symfony\Component\HttpFoundation\Request
169
     */
170
    public function getRequest()
171
    {
172
        return $this->originalUrlGenerator->getRequest();
173
    }
174
175
    /**
176
     * Set the current request instance.
177
     *
178
     * @param  \Illuminate\Http\Request  $request
179
     * @return void
180
     */
181
    public function setRequest(Request $request)
182
    {
183
        $this->originalUrlGenerator->setRequest($request);
184
    }
185
186
    public function setRoutes(RouteCollection $routes)
187
    {
188
        return $this->originalUrlGenerator->setRoutes($routes);
189
    }
190
191
    public function setSessionResolver(callable $sessionResolver)
192
    {
193
        return $this->originalUrlGenerator->setSessionResolver($sessionResolver);
194
    }
195
196
    public function setRootControllerNamespace($rootNamespace)
197
    {
198
        return $this->originalUrlGenerator->setRootControllerNamespace($rootNamespace);
199
    }
200
201
    public function getOriginalUrlGenerator()
202
    {
203
        return $this->originalUrlGenerator;
204
    }
205
206
    /**
207
     * @return bool
208
     */
209
    public function hasValidSignature(Request $request)
210
    {
211
        $original = rtrim($request->url().'?'.http_build_query(
212
            Arr::except($request->query(), 'signature')
213
        ), '?');
214
215
        $expires = Arr::get($request->query(), 'expires');
216
        $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
217
        return  hash_equals($signature, $request->query('signature', '')) && !($expires && Carbon::now()->getTimestamp() > $expires);
218
    }
219
    
220
    /**
221
     * Only check validity of signature if specified parameters exist
222
     */
223
    public function hasValidParameterSignature(Request $request, array $parameters = [])
224
    {
225
        // we'll bail here as we need at least one
226
        if (count($parameters) === 0) {
227
            return true;
228
        } 
229
230
        foreach ($parameters as $parameter) {
231
            // if the request has the parameter or
232
            // the route has the parameter we check the signature
233
            if ($request->has($parameter)) { 
234
                return $this->hasValidSignature($request); 
235
            }
236
237
            if ($this->routeHasParameter($request, $parameter)) {
238
                return $this->hasValidSignature($request);
239
            }
240
        }
241
242
        return true;
243
    }
244
245
    /**
246
     * Create a signed route URL for a named route.
247
     *
248
     * @param  string  $name
249
     * @param  array  $parameters
250
     * @param  \DateTimeInterface|int  $expiration
251
     * @return string
252
     */
253
    public function signedRoute($name, $parameters = [], $expiration = null)
254
    {
255
        $parameters = $this->formatParameters($parameters);
256
        if ($expiration) {
257
            $parameters = $parameters + ['expires' => $this->availableAt($expiration)];
258
        }
259
        ksort($parameters);
260
        $key = call_user_func($this->keyResolver);
261
        return $this->route($name, $parameters + [
262
            'signature' => hash_hmac('sha256', $this->route($name, $parameters), $key),
263
        ]);
264
    }
265
    /**
266
     * Create a temporary signed route URL for a named route.
267
     *
268
     * @param  string  $name
269
     * @param  \DateTimeInterface|int  $expiration
270
     * @param  array  $parameters
271
     * @return string
272
     */
273
    public function temporarySignedRoute($name, $expiration, $parameters = [])
274
    {
275
        return $this->signedRoute($name, $parameters, $expiration);
276
    }
277
278
    /**
279
     * Format the array of URL parameters.
280
     *
281
     * @param  mixed|array  $parameters
282
     * @return array
283
     */
284
    public function formatParameters($parameters)
285
    {
286
        $parameters = Arr::wrap($parameters);
287
        foreach ($parameters as $key => $parameter) {
288
            if ($parameter instanceof UrlRoutable) {
289
                $parameters[$key] = $parameter->getRouteKey();
290
            }
291
        }
292
        return $parameters;
293
    }
294
295
    /**
296
     * Get the "available at" UNIX timestamp.
297
     *
298
     * @param  \DateTimeInterface|\DateInterval|int  $delay
299
     * @return int
300
     */
301
    protected function availableAt($delay = 0)
302
    {
303
        $delay = $this->parseDateInterval($delay);
304
        return $delay instanceof DateTimeInterface
0 ignored issues
show
introduced by
$delay is always a sub-type of DateTimeInterface.
Loading history...
305
                            ? $delay->getTimestamp()
306
                            : Carbon::now()->addSeconds($delay)->getTimestamp();
307
    }
308
309
    /**
310
     * If the given value is an interval, convert it to a DateTime instance.
311
     *
312
     * @param  \DateTimeInterface|\DateInterval|int  $delay
313
     * @return \DateTimeInterface|int
314
     */
315
    protected function parseDateInterval($delay)
316
    {
317
        if ($delay instanceof DateInterval) {
318
            $delay = Carbon::now()->add($delay);
319
        }
320
        return $delay;
321
    }
322
    
323
    /**
324
     * Determine if the route from a request has a parameter
325
     * 
326
     * @param \Illuminate\Http\Request $request
327
     * @param string  $parameter
328
     */
329
    protected function routeHasParameter(Request $request, $parameter)
330
    {
331
        $result = false;
332
333
        $route = $request->route($parameter);
334
335
        if ($route instanceof \Illuminate\Routing\Route && $route->hasParameter($parameter)) {
336
            $result = true;
337
        } elseif (is_string($route) && strlen($route) > 0) {
338
            $result = true;
339
        }
340
341
        return $result;
342
    }
343
344
    /**
345
     * The encryption key resolver callable.
346
     *
347
     * @var callable
348
     */
349
    protected $keyResolver;
350
351
    /**
352
     * Set the encryption key resolver.
353
     *
354
     * @param  callable  $keyResolver
355
     * @return $this
356
     */
357
    public function setKeyResolver(callable $keyResolver)
358
    {
359
        $this->keyResolver = $keyResolver;
360
        return $this;
361
    }
362
}
363