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

UrlGenerator::routeHasParameter()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 13
rs 9.6111
c 0
b 0
f 0
cc 5
nc 3
nop 2
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
12
/**
13
 * Decorate the UrlGenerator for simplicity
14
 */
15
class UrlGenerator implements UrlGeneratorContract, IEnableRoutes
16
{
17
    private $originalUrlGenerator;
18
19
    public function __construct(UrlGeneratorContract $originalUrlGenerator)
20
    {
21
        $this->originalUrlGenerator = $originalUrlGenerator;
22
    }
23
24
    /**
25
     * Get the full URL for the current request.
26
     *
27
     * @return string
28
     */
29
    public function full()
30
    {
31
        return $this->originalUrlGenerator->full();
32
    }
33
34
    /**
35
     * Get the current URL for the request.
36
     *
37
     * @return string
38
     */
39
    public function current()
40
    {
41
        return $this->originalUrlGenerator->current();
42
    }
43
44
    /**
45
     * Get the URL for the previous request.
46
     *
47
     * @return string
48
     */
49
    public function previous($fallback = false)
50
    {
51
        return $this->originalUrlGenerator->previous($fallback);
52
    }
53
54
    /**
55
     * Generate a absolute URL to the given path.
56
     *
57
     * @param  string  $path
58
     * @param  mixed  $extra
59
     * @param  bool|null  $secure
60
     * @return string
61
     */
62
    public function to($path, $extra = array(), $secure = null)
63
    {
64
        return $this->originalUrlGenerator->to($path, $extra, $secure);
65
    }
66
67
    /**
68
     * Generate a secure, absolute URL to the given path.
69
     *
70
     * @param  string  $path
71
     * @param  array   $parameters
72
     * @return string
73
     */
74
    public function secure($path, $parameters = array())
75
    {
76
        return $this->originalUrlGenerator->secure($path, $parameters);
77
    }
78
79
    /**
80
     * Generate a URL to an application asset.
81
     *
82
     * @param  string  $path
83
     * @param  bool|null  $secure
84
     * @return string
85
     */
86
    public function asset($path, $secure = null)
87
    {
88
        return $this->originalUrlGenerator->asset($path, $secure);
89
    }
90
91
    /**
92
     * Generate a URL to a secure asset.
93
     *
94
     * @param  string  $path
95
     * @return string
96
     */
97
    public function secureAsset($path)
98
    {
99
        return $this->originalUrlGenerator->secureAsset($path);
100
    }
101
102
    /**
103
     * Force the schema for URLs.
104
     *
105
     * @param  string  $schema
106
     * @return void
107
     */
108
    public function forceSchema($schema)
109
    {
110
        $this->originalUrlGenerator->forceSchema($schema);
111
    }
112
113
    /**
114
     * Get the URL to a named route.
115
     *
116
     * @param  string  $name
117
     * @param  mixed   $parameters
118
     * @param  bool  $absolute
119
     * @param  \Illuminate\Routing\Route  $route
120
     * @return string
121
     *
122
     * @throws \InvalidArgumentException
123
     */
124
    public function route($name, $parameters = array(), $absolute = true, $route = null)
125
    {
126
        return $this->originalUrlGenerator->route($name, $parameters, $absolute, $route);
127
    }
128
129
    /**
130
     * Get the URL to a controller action.
131
     *
132
     * @param  string  $action
133
     * @param  mixed   $parameters
134
     * @param  bool    $absolute
135
     * @return string
136
     */
137
    public function action($action, $parameters = array(), $absolute = true)
138
    {
139
        return $this->originalUrlGenerator->action($action, $parameters, $absolute);
140
    }
141
142
    /**
143
     * Set the forced root URL.
144
     *
145
     * @param  string  $root
146
     * @return void
147
     */
148
    public function forceRootUrl($root)
149
    {
150
        $this->originalUrlGenerator->forceRootUrl($root);
151
    }
152
153
    /**
154
     * Determine if the given path is a valid URL.
155
     *
156
     * @param  string  $path
157
     * @return bool
158
     */
159
    public function isValidUrl($path)
160
    {
161
        return $this->originalUrlGenerator->isValidUrl($path);
162
    }
163
164
    /**
165
     * Get the request instance.
166
     *
167
     * @return \Symfony\Component\HttpFoundation\Request
168
     */
169
    public function getRequest()
170
    {
171
        return $this->originalUrlGenerator->getRequest();
172
    }
173
174
    /**
175
     * Set the current request instance.
176
     *
177
     * @param  \Illuminate\Http\Request  $request
178
     * @return void
179
     */
180
    public function setRequest(Request $request)
181
    {
182
        $this->originalUrlGenerator->setRequest($request);
183
    }
184
185
    public function setRoutes(RouteCollection $routes)
186
    {
187
        return $this->originalUrlGenerator->setRoutes($routes);
188
    }
189
190
    public function setSessionResolver(callable $sessionResolver)
191
    {
192
        return $this->originalUrlGenerator->setSessionResolver($sessionResolver);
193
    }
194
195
    public function setRootControllerNamespace($rootNamespace)
196
    {
197
        return $this->originalUrlGenerator->setRootControllerNamespace($rootNamespace);
198
    }
199
200
    public function getOriginalUrlGenerator()
201
    {
202
        return $this->originalUrlGenerator;
203
    }
204
205
    /**
206
     * @return bool
207
     */
208
    public function hasValidSignature(Request $request)
209
    {
210
        $original = rtrim($request->url().'?'.http_build_query(
211
            Arr::except($request->query(), 'signature')
212
        ), '?');
213
214
        $expires = Arr::get($request->query(), 'expires');
215
        $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
216
        return  hash_equals($signature, $request->query('signature', '')) && !($expires && Carbon::now()->getTimestamp() > $expires);
217
    }
218
    
219
    /**
220
     * Only check validity of signature if specified parameters exist
221
     */
222
    public function hasValidParameterSignature(Request $request, array $parameters = [])
223
    {
224
        // we'll bail here as we need at least one
225
        if (count($parameters) === 0) {
226
            return true;
227
        } 
228
229
        foreach ($parameters as $parameter) {
230
            // if the request has the parameter or
231
            // the route has the parameter we check the signature
232
            if ($request->has($parameter)) { 
233
                return $this->hasValidSignature($request); 
234
            }
235
236
            if ($this->routeHasParameter($request, $parameter)) {
237
                return $this->hasValidSignature($request);
238
            }
239
        }
240
241
        return true;
242
    }
243
244
    /**
245
     * Create a signed route URL for a named route.
246
     *
247
     * @param  string  $name
248
     * @param  array  $parameters
249
     * @param  \DateTimeInterface|int  $expiration
250
     * @return string
251
     */
252
    public function signedRoute($name, $parameters = [], $expiration = null)
253
    {
254
        $parameters = $this->formatParameters($parameters);
255
        if ($expiration) {
256
            $parameters = $parameters + ['expires' => $this->availableAt($expiration)];
257
        }
258
        ksort($parameters);
259
        $key = call_user_func($this->keyResolver);
260
        return $this->route($name, $parameters + [
261
            'signature' => hash_hmac('sha256', $this->route($name, $parameters), $key),
262
        ]);
263
    }
264
    /**
265
     * Create a temporary signed route URL for a named route.
266
     *
267
     * @param  string  $name
268
     * @param  \DateTimeInterface|int  $expiration
269
     * @param  array  $parameters
270
     * @return string
271
     */
272
    public function temporarySignedRoute($name, $expiration, $parameters = [])
273
    {
274
        return $this->signedRoute($name, $parameters, $expiration);
275
    }
276
277
    /**
278
     * Format the array of URL parameters.
279
     *
280
     * @param  mixed|array  $parameters
281
     * @return array
282
     */
283
    public function formatParameters($parameters)
284
    {
285
        $parameters = Arr::wrap($parameters);
286
        foreach ($parameters as $key => $parameter) {
287
            if ($parameter instanceof UrlRoutable) {
0 ignored issues
show
Bug introduced by
The type Endeavors\Components\Routing\UrlRoutable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
288
                $parameters[$key] = $parameter->getRouteKey();
289
            }
290
        }
291
        return $parameters;
292
    }
293
294
    /**
295
     * Get the "available at" UNIX timestamp.
296
     *
297
     * @param  \DateTimeInterface|\DateInterval|int  $delay
298
     * @return int
299
     */
300
    protected function availableAt($delay = 0)
301
    {
302
        $delay = $this->parseDateInterval($delay);
303
        return $delay instanceof DateTimeInterface
0 ignored issues
show
introduced by
$delay is always a sub-type of DateTimeInterface.
Loading history...
304
                            ? $delay->getTimestamp()
305
                            : Carbon::now()->addSeconds($delay)->getTimestamp();
306
    }
307
308
    /**
309
     * If the given value is an interval, convert it to a DateTime instance.
310
     *
311
     * @param  \DateTimeInterface|\DateInterval|int  $delay
312
     * @return \DateTimeInterface|int
313
     */
314
    protected function parseDateInterval($delay)
315
    {
316
        if ($delay instanceof DateInterval) {
317
            $delay = Carbon::now()->add($delay);
318
        }
319
        return $delay;
320
    }
321
    
322
    /**
323
     * Determine if the route from a request has a parameter
324
     * 
325
     * @param \Illuminate\Http\Request $request
326
     * @param string  $parameter
327
     */
328
    protected function routeHasParameter(Request $request, $parameter)
329
    {
330
        $result = false;
331
332
        $route = $request->route($parameter);
333
334
        if ($route instanceof \Illuminate\Routing\Route && $route->hasParameter($parameter)) {
335
            $result = true;
336
        } elseif (is_string($route) && strlen($route) > 0) {
337
            $result = true;
338
        }
339
340
        return $result;
341
    }
342
343
    /**
344
     * The encryption key resolver callable.
345
     *
346
     * @var callable
347
     */
348
    protected $keyResolver;
349
350
    /**
351
     * Set the encryption key resolver.
352
     *
353
     * @param  callable  $keyResolver
354
     * @return $this
355
     */
356
    public function setKeyResolver(callable $keyResolver)
357
    {
358
        $this->keyResolver = $keyResolver;
359
        return $this;
360
    }
361
}
362