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\Http;
4
 
5
use ArrayAccess;
6
use Closure;
7
use Illuminate\Contracts\Support\Arrayable;
8
use Illuminate\Session\SymfonySessionDecorator;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\Str;
11
use Illuminate\Support\Traits\Macroable;
12
use RuntimeException;
13
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
14
use Symfony\Component\HttpFoundation\ParameterBag;
15
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
16
use Symfony\Component\HttpFoundation\Session\SessionInterface;
17
 
18
/**
19
 * @method array validate(array $rules, ...$params)
20
 * @method array validateWithBag(string $errorBag, array $rules, ...$params)
21
 * @method bool hasValidSignature(bool $absolute = true)
22
 */
23
class Request extends SymfonyRequest implements Arrayable, ArrayAccess
24
{
25
    use Concerns\CanBePrecognitive,
26
        Concerns\InteractsWithContentTypes,
27
        Concerns\InteractsWithFlashData,
28
        Concerns\InteractsWithInput,
29
        Macroable;
30
 
31
    /**
32
     * The decoded JSON content for the request.
33
     *
34
     * @var \Symfony\Component\HttpFoundation\ParameterBag|null
35
     */
36
    protected $json;
37
 
38
    /**
39
     * All of the converted files for the request.
40
     *
41
     * @var array
42
     */
43
    protected $convertedFiles;
44
 
45
    /**
46
     * The user resolver callback.
47
     *
48
     * @var \Closure
49
     */
50
    protected $userResolver;
51
 
52
    /**
53
     * The route resolver callback.
54
     *
55
     * @var \Closure
56
     */
57
    protected $routeResolver;
58
 
59
    /**
60
     * Create a new Illuminate HTTP request from server variables.
61
     *
62
     * @return static
63
     */
64
    public static function capture()
65
    {
66
        static::enableHttpMethodParameterOverride();
67
 
68
        return static::createFromBase(SymfonyRequest::createFromGlobals());
69
    }
70
 
71
    /**
72
     * Return the Request instance.
73
     *
74
     * @return $this
75
     */
76
    public function instance()
77
    {
78
        return $this;
79
    }
80
 
81
    /**
82
     * Get the request method.
83
     *
84
     * @return string
85
     */
86
    public function method()
87
    {
88
        return $this->getMethod();
89
    }
90
 
91
    /**
92
     * Get the root URL for the application.
93
     *
94
     * @return string
95
     */
96
    public function root()
97
    {
98
        return rtrim($this->getSchemeAndHttpHost().$this->getBaseUrl(), '/');
99
    }
100
 
101
    /**
102
     * Get the URL (no query string) for the request.
103
     *
104
     * @return string
105
     */
106
    public function url()
107
    {
108
        return rtrim(preg_replace('/\?.*/', '', $this->getUri()), '/');
109
    }
110
 
111
    /**
112
     * Get the full URL for the request.
113
     *
114
     * @return string
115
     */
116
    public function fullUrl()
117
    {
118
        $query = $this->getQueryString();
119
 
120
        $question = $this->getBaseUrl().$this->getPathInfo() === '/' ? '/?' : '?';
121
 
122
        return $query ? $this->url().$question.$query : $this->url();
123
    }
124
 
125
    /**
126
     * Get the full URL for the request with the added query string parameters.
127
     *
128
     * @param  array  $query
129
     * @return string
130
     */
131
    public function fullUrlWithQuery(array $query)
132
    {
133
        $question = $this->getBaseUrl().$this->getPathInfo() === '/' ? '/?' : '?';
134
 
135
        return count($this->query()) > 0
136
            ? $this->url().$question.Arr::query(array_merge($this->query(), $query))
137
            : $this->fullUrl().$question.Arr::query($query);
138
    }
139
 
140
    /**
141
     * Get the full URL for the request without the given query string parameters.
142
     *
143
     * @param  array|string  $keys
144
     * @return string
145
     */
146
    public function fullUrlWithoutQuery($keys)
147
    {
148
        $query = Arr::except($this->query(), $keys);
149
 
150
        $question = $this->getBaseUrl().$this->getPathInfo() === '/' ? '/?' : '?';
151
 
152
        return count($query) > 0
153
            ? $this->url().$question.Arr::query($query)
154
            : $this->url();
155
    }
156
 
157
    /**
158
     * Get the current path info for the request.
159
     *
160
     * @return string
161
     */
162
    public function path()
163
    {
164
        $pattern = trim($this->getPathInfo(), '/');
165
 
166
        return $pattern === '' ? '/' : $pattern;
167
    }
168
 
169
    /**
170
     * Get the current decoded path info for the request.
171
     *
172
     * @return string
173
     */
174
    public function decodedPath()
175
    {
176
        return rawurldecode($this->path());
177
    }
178
 
179
    /**
180
     * Get a segment from the URI (1 based index).
181
     *
182
     * @param  int  $index
183
     * @param  string|null  $default
184
     * @return string|null
185
     */
186
    public function segment($index, $default = null)
187
    {
188
        return Arr::get($this->segments(), $index - 1, $default);
189
    }
190
 
191
    /**
192
     * Get all of the segments for the request path.
193
     *
194
     * @return array
195
     */
196
    public function segments()
197
    {
198
        $segments = explode('/', $this->decodedPath());
199
 
200
        return array_values(array_filter($segments, function ($value) {
201
            return $value !== '';
202
        }));
203
    }
204
 
205
    /**
206
     * Determine if the current request URI matches a pattern.
207
     *
208
     * @param  mixed  ...$patterns
209
     * @return bool
210
     */
211
    public function is(...$patterns)
212
    {
213
        $path = $this->decodedPath();
214
 
215
        return collect($patterns)->contains(fn ($pattern) => Str::is($pattern, $path));
216
    }
217
 
218
    /**
219
     * Determine if the route name matches a given pattern.
220
     *
221
     * @param  mixed  ...$patterns
222
     * @return bool
223
     */
224
    public function routeIs(...$patterns)
225
    {
226
        return $this->route() && $this->route()->named(...$patterns);
227
    }
228
 
229
    /**
230
     * Determine if the current request URL and query string match a pattern.
231
     *
232
     * @param  mixed  ...$patterns
233
     * @return bool
234
     */
235
    public function fullUrlIs(...$patterns)
236
    {
237
        $url = $this->fullUrl();
238
 
239
        return collect($patterns)->contains(fn ($pattern) => Str::is($pattern, $url));
240
    }
241
 
242
    /**
243
     * Get the host name.
244
     *
245
     * @return string
246
     */
247
    public function host()
248
    {
249
        return $this->getHost();
250
    }
251
 
252
    /**
253
     * Get the HTTP host being requested.
254
     *
255
     * @return string
256
     */
257
    public function httpHost()
258
    {
259
        return $this->getHttpHost();
260
    }
261
 
262
    /**
263
     * Get the scheme and HTTP host.
264
     *
265
     * @return string
266
     */
267
    public function schemeAndHttpHost()
268
    {
269
        return $this->getSchemeAndHttpHost();
270
    }
271
 
272
    /**
273
     * Determine if the request is the result of an AJAX call.
274
     *
275
     * @return bool
276
     */
277
    public function ajax()
278
    {
279
        return $this->isXmlHttpRequest();
280
    }
281
 
282
    /**
283
     * Determine if the request is the result of a PJAX call.
284
     *
285
     * @return bool
286
     */
287
    public function pjax()
288
    {
289
        return $this->headers->get('X-PJAX') == true;
290
    }
291
 
292
    /**
293
     * Determine if the request is the result of a prefetch call.
294
     *
295
     * @return bool
296
     */
297
    public function prefetch()
298
    {
299
        return strcasecmp($this->server->get('HTTP_X_MOZ') ?? '', 'prefetch') === 0 ||
300
               strcasecmp($this->headers->get('Purpose') ?? '', 'prefetch') === 0;
301
    }
302
 
303
    /**
304
     * Determine if the request is over HTTPS.
305
     *
306
     * @return bool
307
     */
308
    public function secure()
309
    {
310
        return $this->isSecure();
311
    }
312
 
313
    /**
314
     * Get the client IP address.
315
     *
316
     * @return string|null
317
     */
318
    public function ip()
319
    {
320
        return $this->getClientIp();
321
    }
322
 
323
    /**
324
     * Get the client IP addresses.
325
     *
326
     * @return array
327
     */
328
    public function ips()
329
    {
330
        return $this->getClientIps();
331
    }
332
 
333
    /**
334
     * Get the client user agent.
335
     *
336
     * @return string|null
337
     */
338
    public function userAgent()
339
    {
340
        return $this->headers->get('User-Agent');
341
    }
342
 
343
    /**
344
     * Merge new input into the current request's input array.
345
     *
346
     * @param  array  $input
347
     * @return $this
348
     */
349
    public function merge(array $input)
350
    {
351
        $this->getInputSource()->add($input);
352
 
353
        return $this;
354
    }
355
 
356
    /**
357
     * Merge new input into the request's input, but only when that key is missing from the request.
358
     *
359
     * @param  array  $input
360
     * @return $this
361
     */
362
    public function mergeIfMissing(array $input)
363
    {
364
        return $this->merge(collect($input)->filter(function ($value, $key) {
365
            return $this->missing($key);
366
        })->toArray());
367
    }
368
 
369
    /**
370
     * Replace the input for the current request.
371
     *
372
     * @param  array  $input
373
     * @return $this
374
     */
375
    public function replace(array $input)
376
    {
377
        $this->getInputSource()->replace($input);
378
 
379
        return $this;
380
    }
381
 
382
    /**
383
     * This method belongs to Symfony HttpFoundation and is not usually needed when using Laravel.
384
     *
385
     * Instead, you may use the "input" method.
386
     *
387
     * @param  string  $key
388
     * @param  mixed  $default
389
     * @return mixed
390
     */
391
    public function get(string $key, mixed $default = null): mixed
392
    {
393
        return parent::get($key, $default);
394
    }
395
 
396
    /**
397
     * Get the JSON payload for the request.
398
     *
399
     * @param  string|null  $key
400
     * @param  mixed  $default
401
     * @return \Symfony\Component\HttpFoundation\ParameterBag|mixed
402
     */
403
    public function json($key = null, $default = null)
404
    {
405
        if (! isset($this->json)) {
406
            $this->json = new ParameterBag((array) json_decode($this->getContent(), true));
407
        }
408
 
409
        if (is_null($key)) {
410
            return $this->json;
411
        }
412
 
413
        return data_get($this->json->all(), $key, $default);
414
    }
415
 
416
    /**
417
     * Get the input source for the request.
418
     *
419
     * @return \Symfony\Component\HttpFoundation\ParameterBag
420
     */
421
    protected function getInputSource()
422
    {
423
        if ($this->isJson()) {
424
            return $this->json();
425
        }
426
 
427
        return in_array($this->getRealMethod(), ['GET', 'HEAD']) ? $this->query : $this->request;
428
    }
429
 
430
    /**
431
     * Create a new request instance from the given Laravel request.
432
     *
433
     * @param  \Illuminate\Http\Request  $from
434
     * @param  \Illuminate\Http\Request|null  $to
435
     * @return static
436
     */
437
    public static function createFrom(self $from, $to = null)
438
    {
439
        $request = $to ?: new static;
440
 
441
        $files = array_filter($from->files->all());
442
 
443
        $request->initialize(
444
            $from->query->all(),
445
            $from->request->all(),
446
            $from->attributes->all(),
447
            $from->cookies->all(),
448
            $files,
449
            $from->server->all(),
450
            $from->getContent()
451
        );
452
 
453
        $request->headers->replace($from->headers->all());
454
 
455
        $request->setRequestLocale($from->getLocale());
456
 
457
        $request->setDefaultRequestLocale($from->getDefaultLocale());
458
 
459
        $request->setJson($from->json());
460
 
461
        if ($from->hasSession() && $session = $from->session()) {
462
            $request->setLaravelSession($session);
463
        }
464
 
465
        $request->setUserResolver($from->getUserResolver());
466
 
467
        $request->setRouteResolver($from->getRouteResolver());
468
 
469
        return $request;
470
    }
471
 
472
    /**
473
     * Create an Illuminate request from a Symfony instance.
474
     *
475
     * @param  \Symfony\Component\HttpFoundation\Request  $request
476
     * @return static
477
     */
478
    public static function createFromBase(SymfonyRequest $request)
479
    {
480
        $newRequest = (new static)->duplicate(
481
            $request->query->all(), $request->request->all(), $request->attributes->all(),
482
            $request->cookies->all(), $request->files->all(), $request->server->all()
483
        );
484
 
485
        $newRequest->headers->replace($request->headers->all());
486
 
487
        $newRequest->content = $request->content;
488
 
489
        if ($newRequest->isJson()) {
490
            $newRequest->request = $newRequest->json();
491
        }
492
 
493
        return $newRequest;
494
    }
495
 
496
    /**
497
     * {@inheritdoc}
498
     *
499
     * @return static
500
     */
501
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null): static
502
    {
503
        return parent::duplicate($query, $request, $attributes, $cookies, $this->filterFiles($files), $server);
504
    }
505
 
506
    /**
507
     * Filter the given array of files, removing any empty values.
508
     *
509
     * @param  mixed  $files
510
     * @return mixed
511
     */
512
    protected function filterFiles($files)
513
    {
514
        if (! $files) {
515
            return;
516
        }
517
 
518
        foreach ($files as $key => $file) {
519
            if (is_array($file)) {
520
                $files[$key] = $this->filterFiles($files[$key]);
521
            }
522
 
523
            if (empty($files[$key])) {
524
                unset($files[$key]);
525
            }
526
        }
527
 
528
        return $files;
529
    }
530
 
531
    /**
532
     * {@inheritdoc}
533
     */
534
    public function hasSession(bool $skipIfUninitialized = false): bool
535
    {
536
        return ! is_null($this->session);
537
    }
538
 
539
    /**
540
     * {@inheritdoc}
541
     */
542
    public function getSession(): SessionInterface
543
    {
544
        return $this->hasSession()
545
                    ? new SymfonySessionDecorator($this->session())
546
                    : throw new SessionNotFoundException;
547
    }
548
 
549
    /**
550
     * Get the session associated with the request.
551
     *
552
     * @return \Illuminate\Contracts\Session\Session
553
     *
554
     * @throws \RuntimeException
555
     */
556
    public function session()
557
    {
558
        if (! $this->hasSession()) {
559
            throw new RuntimeException('Session store not set on request.');
560
        }
561
 
562
        return $this->session;
563
    }
564
 
565
    /**
566
     * Set the session instance on the request.
567
     *
568
     * @param  \Illuminate\Contracts\Session\Session  $session
569
     * @return void
570
     */
571
    public function setLaravelSession($session)
572
    {
573
        $this->session = $session;
574
    }
575
 
576
    /**
577
     * Set the locale for the request instance.
578
     *
579
     * @param  string  $locale
580
     * @return void
581
     */
582
    public function setRequestLocale(string $locale)
583
    {
584
        $this->locale = $locale;
585
    }
586
 
587
    /**
588
     * Set the default locale for the request instance.
589
     *
590
     * @param  string  $locale
591
     * @return void
592
     */
593
    public function setDefaultRequestLocale(string $locale)
594
    {
595
        $this->defaultLocale = $locale;
596
    }
597
 
598
    /**
599
     * Get the user making the request.
600
     *
601
     * @param  string|null  $guard
602
     * @return mixed
603
     */
604
    public function user($guard = null)
605
    {
606
        return call_user_func($this->getUserResolver(), $guard);
607
    }
608
 
609
    /**
610
     * Get the route handling the request.
611
     *
612
     * @param  string|null  $param
613
     * @param  mixed  $default
614
     * @return \Illuminate\Routing\Route|object|string|null
615
     */
616
    public function route($param = null, $default = null)
617
    {
618
        $route = call_user_func($this->getRouteResolver());
619
 
620
        if (is_null($route) || is_null($param)) {
621
            return $route;
622
        }
623
 
624
        return $route->parameter($param, $default);
625
    }
626
 
627
    /**
628
     * Get a unique fingerprint for the request / route / IP address.
629
     *
630
     * @return string
631
     *
632
     * @throws \RuntimeException
633
     */
634
    public function fingerprint()
635
    {
636
        if (! $route = $this->route()) {
637
            throw new RuntimeException('Unable to generate fingerprint. Route unavailable.');
638
        }
639
 
640
        return sha1(implode('|', array_merge(
641
            $route->methods(),
642
            [$route->getDomain(), $route->uri(), $this->ip()]
643
        )));
644
    }
645
 
646
    /**
647
     * Set the JSON payload for the request.
648
     *
649
     * @param  \Symfony\Component\HttpFoundation\ParameterBag  $json
650
     * @return $this
651
     */
652
    public function setJson($json)
653
    {
654
        $this->json = $json;
655
 
656
        return $this;
657
    }
658
 
659
    /**
660
     * Get the user resolver callback.
661
     *
662
     * @return \Closure
663
     */
664
    public function getUserResolver()
665
    {
666
        return $this->userResolver ?: function () {
667
            //
668
        };
669
    }
670
 
671
    /**
672
     * Set the user resolver callback.
673
     *
674
     * @param  \Closure  $callback
675
     * @return $this
676
     */
677
    public function setUserResolver(Closure $callback)
678
    {
679
        $this->userResolver = $callback;
680
 
681
        return $this;
682
    }
683
 
684
    /**
685
     * Get the route resolver callback.
686
     *
687
     * @return \Closure
688
     */
689
    public function getRouteResolver()
690
    {
691
        return $this->routeResolver ?: function () {
692
            //
693
        };
694
    }
695
 
696
    /**
697
     * Set the route resolver callback.
698
     *
699
     * @param  \Closure  $callback
700
     * @return $this
701
     */
702
    public function setRouteResolver(Closure $callback)
703
    {
704
        $this->routeResolver = $callback;
705
 
706
        return $this;
707
    }
708
 
709
    /**
710
     * Get all of the input and files for the request.
711
     *
712
     * @return array
713
     */
714
    public function toArray(): array
715
    {
716
        return $this->all();
717
    }
718
 
719
    /**
720
     * Determine if the given offset exists.
721
     *
722
     * @param  string  $offset
723
     * @return bool
724
     */
725
    public function offsetExists($offset): bool
726
    {
727
        $route = $this->route();
728
 
729
        return Arr::has(
730
            $this->all() + ($route ? $route->parameters() : []),
731
            $offset
732
        );
733
    }
734
 
735
    /**
736
     * Get the value at the given offset.
737
     *
738
     * @param  string  $offset
739
     * @return mixed
740
     */
741
    public function offsetGet($offset): mixed
742
    {
743
        return $this->__get($offset);
744
    }
745
 
746
    /**
747
     * Set the value at the given offset.
748
     *
749
     * @param  string  $offset
750
     * @param  mixed  $value
751
     * @return void
752
     */
753
    public function offsetSet($offset, $value): void
754
    {
755
        $this->getInputSource()->set($offset, $value);
756
    }
757
 
758
    /**
759
     * Remove the value at the given offset.
760
     *
761
     * @param  string  $offset
762
     * @return void
763
     */
764
    public function offsetUnset($offset): void
765
    {
766
        $this->getInputSource()->remove($offset);
767
    }
768
 
769
    /**
770
     * Check if an input element is set on the request.
771
     *
772
     * @param  string  $key
773
     * @return bool
774
     */
775
    public function __isset($key)
776
    {
777
        return ! is_null($this->__get($key));
778
    }
779
 
780
    /**
781
     * Get an input element from the request.
782
     *
783
     * @param  string  $key
784
     * @return mixed
785
     */
786
    public function __get($key)
787
    {
788
        return Arr::get($this->all(), $key, fn () => $this->route($key));
789
    }
790
}