• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 26277730247

22 May 2026 08:41AM UTC coverage: 88.444%. First build
26277730247

Pull #10216

github

web-flow
Merge b712df7ad into 1a3987fdb
Pull Request #10216: feat: add source-specific typed request input

7 of 9 new or added lines in 1 file covered. (77.78%)

24161 of 27318 relevant lines covered (88.44%)

220.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.97
/system/HTTP/IncomingRequest.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter\HTTP;
15

16
use CodeIgniter\Exceptions\InvalidArgumentException;
17
use CodeIgniter\HTTP\Exceptions\HTTPException;
18
use CodeIgniter\HTTP\Files\FileCollection;
19
use CodeIgniter\HTTP\Files\UploadedFile;
20
use CodeIgniter\Input\InputData;
21
use Config\App;
22
use Config\Services;
23
use Locale;
24
use stdClass;
25

26
/**
27
 * Class IncomingRequest
28
 *
29
 * Represents an incoming, server-side HTTP request.
30
 *
31
 * Per the HTTP specification, this interface includes properties for
32
 * each of the following:
33
 *
34
 * - Protocol version
35
 * - HTTP method
36
 * - URI
37
 * - Headers
38
 * - Message body
39
 *
40
 * Additionally, it encapsulates all data as it has arrived to the
41
 * application from the CGI and/or PHP environment, including:
42
 *
43
 * - The values represented in $_SERVER.
44
 * - Any cookies provided (generally via $_COOKIE)
45
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
46
 * - Upload files, if any (as represented by $_FILES)
47
 * - Deserialized body binds (generally from $_POST)
48
 *
49
 * @see \CodeIgniter\HTTP\IncomingRequestTest
50
 */
51
class IncomingRequest extends Request
52
{
53
    /**
54
     * The URI for this request.
55
     *
56
     * Note: This WILL NOT match the actual URL in the browser since for
57
     * everything this cares about (and the router, etc) is the portion
58
     * AFTER the baseURL. So, if hosted in a sub-folder this will
59
     * appear different than actual URI path. If you need that use getPath().
60
     *
61
     * @var URI
62
     */
63
    protected $uri;
64

65
    /**
66
     * The detected URI path (relative to the baseURL).
67
     *
68
     * Note: current_url() uses this to build its URI,
69
     * so this becomes the source for the "current URL"
70
     * when working with the share request instance.
71
     *
72
     * @var string|null
73
     */
74
    protected $path;
75

76
    /**
77
     * File collection
78
     *
79
     * @var FileCollection|null
80
     */
81
    protected $files;
82

83
    /**
84
     * Negotiator
85
     *
86
     * @var Negotiate|null
87
     */
88
    protected $negotiator;
89

90
    /**
91
     * The default Locale this request
92
     * should operate under.
93
     *
94
     * @var string
95
     */
96
    protected $defaultLocale;
97

98
    /**
99
     * The current locale of the application.
100
     * Default value is set in app/Config/App.php
101
     *
102
     * @var string
103
     */
104
    protected $locale;
105

106
    /**
107
     * Stores the valid locale codes.
108
     *
109
     * @var array
110
     */
111
    protected $validLocales = [];
112

113
    /**
114
     * Holds the old data from a redirect.
115
     *
116
     * @var array
117
     */
118
    protected $oldInput = [];
119

120
    /**
121
     * The user agent this request is from.
122
     *
123
     * @var UserAgent
124
     */
125
    protected $userAgent;
126

127
    /**
128
     * Constructor
129
     *
130
     * @param App         $config
131
     * @param string|null $body
132
     */
133
    public function __construct($config, ?URI $uri = null, $body = 'php://input', ?UserAgent $userAgent = null)
134
    {
135
        if (! $uri instanceof URI || ! $userAgent instanceof UserAgent) {
3,414✔
136
            throw new InvalidArgumentException('You must supply the parameters: uri, userAgent.');
×
137
        }
138

139
        $this->populateHeaders();
3,414✔
140

141
        if (
142
            $body === 'php://input'
3,414✔
143
            // php://input is not available with enctype="multipart/form-data".
144
            // See https://www.php.net/manual/en/wrappers.php.php#wrappers.php.input
145
            && ! str_contains($this->getHeaderLine('Content-Type'), 'multipart/form-data')
3,414✔
146
            && (int) $this->getHeaderLine('Content-Length') <= $this->getPostMaxSize()
3,414✔
147
        ) {
148
            // Get our body from php://input
149
            $body = file_get_contents('php://input');
3,043✔
150
        }
151

152
        // If file_get_contents() returns false or empty string, set null.
153
        if ($body === false || $body === '') {
3,414✔
154
            $body = null;
3,046✔
155
        }
156

157
        $this->uri          = $uri;
3,414✔
158
        $this->body         = $body;
3,414✔
159
        $this->userAgent    = $userAgent;
3,414✔
160
        $this->validLocales = $config->supportedLocales;
3,414✔
161

162
        parent::__construct($config);
3,414✔
163

164
        if ($uri instanceof SiteURI) {
3,414✔
165
            $this->setPath($uri->getRoutePath());
3,414✔
166
        } else {
167
            $this->setPath($uri->getPath());
×
168
        }
169

170
        $this->detectLocale($config);
3,414✔
171
    }
172

173
    private function getPostMaxSize(): int
174
    {
175
        $postMaxSize = ini_get('post_max_size');
3,043✔
176

177
        return match (strtoupper(substr($postMaxSize, -1))) {
3,043✔
NEW
178
            'G'     => (int) str_replace('G', '', $postMaxSize) * 1024 ** 3,
×
179
            'M'     => (int) str_replace('M', '', $postMaxSize) * 1024 ** 2,
3,043✔
NEW
180
            'K'     => (int) str_replace('K', '', $postMaxSize) * 1024,
×
181
            default => (int) $postMaxSize,
3,043✔
182
        };
3,043✔
183
    }
184

185
    /**
186
     * Handles setting up the locale, perhaps auto-detecting through
187
     * content negotiation.
188
     *
189
     * @param App $config
190
     *
191
     * @return void
192
     */
193
    public function detectLocale($config)
194
    {
195
        $this->locale = $this->defaultLocale = $config->defaultLocale;
3,414✔
196

197
        if (! $config->negotiateLocale) {
3,414✔
198
            return;
3,414✔
199
        }
200

201
        $this->setLocale($this->negotiate('language', $config->supportedLocales));
2✔
202
    }
203

204
    /**
205
     * Provides a convenient way to work with the Negotiate class
206
     * for content negotiation.
207
     */
208
    public function negotiate(string $type, array $supported, bool $strictMatch = false): string
209
    {
210
        if ($this->negotiator === null) {
8✔
211
            $this->negotiator = Services::negotiator($this, true);
8✔
212
        }
213

214
        return match (strtolower($type)) {
8✔
215
            'media'    => $this->negotiator->media($supported, $strictMatch),
2✔
216
            'charset'  => $this->negotiator->charset($supported),
1✔
217
            'encoding' => $this->negotiator->encoding($supported),
1✔
218
            'language' => $this->negotiator->language($supported),
3✔
219
            default    => throw HTTPException::forInvalidNegotiationType($type),
8✔
220
        };
8✔
221
    }
222

223
    /**
224
     * Checks this request type.
225
     */
226
    public function is(string $type): bool
227
    {
228
        $valueUpper = strtoupper($type);
55✔
229

230
        $httpMethods = Method::all();
55✔
231

232
        if (in_array($valueUpper, $httpMethods, true)) {
55✔
233
            return $this->getMethod() === $valueUpper;
44✔
234
        }
235

236
        if ($valueUpper === 'JSON') {
11✔
237
            return str_contains($this->getHeaderLine('Content-Type'), 'application/json');
9✔
238
        }
239

240
        if ($valueUpper === 'AJAX') {
2✔
241
            return $this->isAJAX();
1✔
242
        }
243

244
        throw new InvalidArgumentException('Unknown type: ' . $type);
1✔
245
    }
246

247
    /**
248
     * Determines if this request was made from the command line (CLI).
249
     */
250
    public function isCLI(): bool
251
    {
252
        return false;
1✔
253
    }
254

255
    /**
256
     * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
257
     */
258
    public function isAJAX(): bool
259
    {
260
        return $this->hasHeader('X-Requested-With')
93✔
261
            && strtolower($this->header('X-Requested-With')->getValue()) === 'xmlhttprequest';
93✔
262
    }
263

264
    /**
265
     * Attempts to detect if the current connection is secure through
266
     * a few different methods.
267
     */
268
    public function isSecure(): bool
269
    {
270
        $https = service('superglobals')->server('HTTPS');
6✔
271

272
        if ($https !== null && strtolower($https) !== 'off') {
6✔
273
            return true;
1✔
274
        }
275

276
        if ($this->hasHeader('X-Forwarded-Proto') && $this->header('X-Forwarded-Proto')->getValue() === 'https') {
5✔
277
            return true;
1✔
278
        }
279

280
        return $this->hasHeader('Front-End-Https') && ! empty($this->header('Front-End-Https')->getValue()) && strtolower($this->header('Front-End-Https')->getValue()) !== 'off';
4✔
281
    }
282

283
    /**
284
     * Sets the URI path relative to baseURL.
285
     *
286
     * Note: Since current_url() accesses the shared request
287
     * instance, this can be used to change the "current URL"
288
     * for testing.
289
     *
290
     * @param string $path URI path relative to baseURL
291
     *
292
     * @return $this
293
     */
294
    private function setPath(string $path)
295
    {
296
        $this->path = $path;
3,414✔
297

298
        return $this;
3,414✔
299
    }
300

301
    /**
302
     * Returns the URI path relative to baseURL,
303
     * running detection as necessary.
304
     */
305
    public function getPath(): string
306
    {
307
        return $this->path;
110✔
308
    }
309

310
    /**
311
     * Sets the locale string for this request.
312
     *
313
     * @return IncomingRequest
314
     */
315
    public function setLocale(string $locale)
316
    {
317
        // If it's not a valid locale, set it
318
        // to the default locale for the site.
319
        if (! in_array($locale, $this->validLocales, true)) {
5✔
320
            $locale = $this->defaultLocale;
1✔
321
        }
322

323
        $this->locale = $locale;
5✔
324
        Locale::setDefault($locale);
5✔
325

326
        return $this;
5✔
327
    }
328

329
    /**
330
     * Set the valid locales.
331
     *
332
     * @return $this
333
     */
334
    public function setValidLocales(array $locales)
335
    {
336
        $this->validLocales = $locales;
1✔
337

338
        return $this;
1✔
339
    }
340

341
    /**
342
     * Gets the current locale, with a fallback to the default
343
     * locale if none is set.
344
     */
345
    public function getLocale(): string
346
    {
347
        return $this->locale;
552✔
348
    }
349

350
    /**
351
     * Returns the default locale as set in app/Config/App.php
352
     */
353
    public function getDefaultLocale(): string
354
    {
355
        return $this->defaultLocale;
3✔
356
    }
357

358
    /**
359
     * Fetch an item from JSON input stream with fallback to $_REQUEST object. This is the simplest way
360
     * to grab data from the request object and can be used in lieu of the
361
     * other get* methods in most cases.
362
     *
363
     * @param array|string|null $index
364
     * @param int|null          $filter Filter constant
365
     * @param array|int|null    $flags
366
     *
367
     * @return array|bool|float|int|stdClass|string|null
368
     */
369
    public function getVar($index = null, $filter = null, $flags = null)
370
    {
371
        if (
372
            str_contains($this->getHeaderLine('Content-Type'), 'application/json')
18✔
373
            && $this->body !== null
18✔
374
        ) {
375
            return $this->getJsonVar($index, false, $filter, $flags);
1✔
376
        }
377

378
        return $this->fetchGlobal('request', $index, $filter, $flags);
17✔
379
    }
380

381
    /**
382
     * A convenience method that grabs the raw input stream and decodes
383
     * the JSON into an array.
384
     *
385
     * If $assoc == true, then all objects in the response will be converted
386
     * to associative arrays.
387
     *
388
     * @param bool $assoc   Whether to return objects as associative arrays
389
     * @param int  $depth   How many levels deep to decode
390
     * @param int  $options Bitmask of options
391
     *
392
     * @see http://php.net/manual/en/function.json-decode.php
393
     *
394
     * @return array|bool|float|int|stdClass|null
395
     *
396
     * @throws HTTPException When the body is invalid as JSON.
397
     */
398
    public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0)
399
    {
400
        if ($this->body === null) {
29✔
401
            return null;
4✔
402
        }
403

404
        $result = json_decode($this->body, $assoc, $depth, $options);
25✔
405

406
        if (json_last_error() !== JSON_ERROR_NONE) {
24✔
407
            throw HTTPException::forInvalidJSON(json_last_error_msg());
4✔
408
        }
409

410
        return $result;
20✔
411
    }
412

413
    /**
414
     * Get a specific variable from a JSON input stream
415
     *
416
     * @param array|string|null $index  The variable that you want which can use dot syntax for getting specific values.
417
     * @param bool              $assoc  If true, return the result as an associative array.
418
     * @param int|null          $filter Filter Constant
419
     * @param array|int|null    $flags  Option
420
     *
421
     * @return array|bool|float|int|stdClass|string|null
422
     */
423
    public function getJsonVar($index = null, bool $assoc = false, ?int $filter = null, $flags = null)
424
    {
425
        helper('array');
6✔
426

427
        $data = $this->getJSON(true);
6✔
428
        if (! is_array($data)) {
6✔
429
            return null;
1✔
430
        }
431

432
        if (is_string($index)) {
5✔
433
            $data = dot_array_search($index, $data);
5✔
434
        } elseif (is_array($index)) {
2✔
435
            $result = [];
2✔
436

437
            foreach ($index as $key) {
2✔
438
                $result[$key] = dot_array_search($key, $data);
2✔
439
            }
440

441
            [$data, $result] = [$result, null];
2✔
442
        }
443

444
        if ($data === null) {
5✔
445
            return null;
2✔
446
        }
447

448
        $filter ??= FILTER_UNSAFE_RAW;
5✔
449
        $flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
5✔
450

451
        if ($filter !== FILTER_UNSAFE_RAW
5✔
452
            || (
453
                (is_numeric($flags) && $flags !== 0)
5✔
454
                || is_array($flags) && $flags !== []
5✔
455
            )
456
        ) {
457
            if (is_array($data)) {
2✔
458
                // Iterate over array and append filter and flags
459
                array_walk_recursive($data, static function (&$val) use ($filter, $flags): void {
1✔
460
                    $valType = gettype($val);
1✔
461
                    $val     = filter_var($val, $filter, $flags);
1✔
462

463
                    if (in_array($valType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $val !== false) {
1✔
464
                        settype($val, $valType);
1✔
465
                    }
466
                });
1✔
467
            } else {
468
                $dataType = gettype($data);
1✔
469
                $data     = filter_var($data, $filter, $flags);
1✔
470

471
                if (in_array($dataType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $data !== false) {
1✔
472
                    settype($data, $dataType);
×
473
                }
474
            }
475
        }
476

477
        if (! $assoc) {
5✔
478
            if (is_array($index)) {
4✔
479
                foreach ($data as &$val) {
2✔
480
                    $val = is_array($val) ? json_decode(json_encode($val)) : $val;
2✔
481
                }
482

483
                return $data;
2✔
484
            }
485

486
            return json_decode(json_encode($data));
3✔
487
        }
488

489
        return $data;
2✔
490
    }
491

492
    /**
493
     * A convenience method that grabs the raw input stream(send method in PUT, PATCH, DELETE) and decodes
494
     * the String into an array.
495
     *
496
     * @return array
497
     */
498
    public function getRawInput()
499
    {
500
        parse_str($this->body ?? '', $output);
16✔
501

502
        return $output;
16✔
503
    }
504

505
    /**
506
     * Gets a specific variable from raw input stream (send method in PUT, PATCH, DELETE).
507
     *
508
     * @param array|string|null $index  The variable that you want which can use dot syntax for getting specific values.
509
     * @param int|null          $filter Filter Constant
510
     * @param array|int|null    $flags  Option
511
     *
512
     * @return array|bool|float|int|object|string|null
513
     */
514
    public function getRawInputVar($index = null, ?int $filter = null, $flags = null)
515
    {
516
        helper('array');
10✔
517

518
        parse_str($this->body ?? '', $output);
10✔
519

520
        if (is_string($index)) {
10✔
521
            $output = dot_array_search($index, $output);
6✔
522
        } elseif (is_array($index)) {
4✔
523
            $data = [];
2✔
524

525
            foreach ($index as $key) {
2✔
526
                $data[$key] = dot_array_search($key, $output);
2✔
527
            }
528

529
            [$output, $data] = [$data, null];
2✔
530
        }
531

532
        $filter ??= FILTER_UNSAFE_RAW;
10✔
533
        $flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
10✔
534

535
        if (is_array($output)
10✔
536
            && (
537
                $filter !== FILTER_UNSAFE_RAW
10✔
538
                || (
10✔
539
                    (is_numeric($flags) && $flags !== 0)
10✔
540
                    || is_array($flags) && $flags !== []
10✔
541
                )
10✔
542
            )
543
        ) {
544
            // Iterate over array and append filter and flags
545
            array_walk_recursive($output, static function (&$val) use ($filter, $flags): void {
×
546
                $val = filter_var($val, $filter, $flags);
×
547
            });
×
548

549
            return $output;
×
550
        }
551

552
        if (is_string($output)) {
10✔
553
            return filter_var($output, $filter, $flags);
5✔
554
        }
555

556
        return $output;
5✔
557
    }
558

559
    /**
560
     * Returns query-string parameters as a typed input object.
561
     */
562
    public function getQueryInput(): InputData
563
    {
564
        $data = $this->getGet();
1✔
565

566
        return service('inputdatafactory')->create(is_array($data) ? $data : []);
1✔
567
    }
568

569
    /**
570
     * Returns POST body parameters as a typed input object.
571
     */
572
    public function getPostInput(): InputData
573
    {
574
        $data = $this->getPost();
1✔
575

576
        return service('inputdatafactory')->create(is_array($data) ? $data : []);
1✔
577
    }
578

579
    /**
580
     * Returns request body payload parameters as a typed input object.
581
     */
582
    public function getPayloadInput(): InputData
583
    {
584
        $contentType = $this->getHeaderLine('Content-Type');
9✔
585

586
        if (str_contains($contentType, 'application/json')) {
9✔
587
            $data = $this->getJSON(true) ?? [];
4✔
588

589
            if (! is_array($data)) {
3✔
590
                throw HTTPException::forUnsupportedJSONFormat();
1✔
591
            }
592

593
            return service('inputdatafactory')->create($data);
2✔
594
        }
595

596
        if (
597
            in_array($this->getMethod(), [Method::PUT, Method::PATCH, Method::DELETE], true)
5✔
598
            && ! str_contains($contentType, 'multipart/form-data')
5✔
599
        ) {
600
            return service('inputdatafactory')->create($this->getRawInput());
3✔
601
        }
602

603
        if (in_array($this->getMethod(), [Method::GET, Method::HEAD], true)) {
2✔
604
            return service('inputdatafactory')->create([]);
1✔
605
        }
606

607
        $data = $this->getPost();
1✔
608

609
        return service('inputdatafactory')->create(is_array($data) ? $data : []);
1✔
610
    }
611

612
    /**
613
     * Fetch an item from GET data.
614
     *
615
     * @param array|string|null $index  Index for item to fetch from $_GET.
616
     * @param int|null          $filter A filter name to apply.
617
     * @param array|int|null    $flags
618
     *
619
     * @return array|bool|float|int|object|string|null
620
     */
621
    public function getGet($index = null, $filter = null, $flags = null)
622
    {
623
        return $this->fetchGlobal('get', $index, $filter, $flags);
70✔
624
    }
625

626
    /**
627
     * Fetch an item from POST.
628
     *
629
     * @param array|string|null $index  Index for item to fetch from $_POST.
630
     * @param int|null          $filter A filter name to apply
631
     * @param array|int|null    $flags
632
     *
633
     * @return array|bool|float|int|object|string|null
634
     */
635
    public function getPost($index = null, $filter = null, $flags = null)
636
    {
637
        return $this->fetchGlobal('post', $index, $filter, $flags);
124✔
638
    }
639

640
    /**
641
     * Fetch an item from POST data with fallback to GET.
642
     *
643
     * @param array|string|null $index  Index for item to fetch from $_POST or $_GET
644
     * @param int|null          $filter A filter name to apply
645
     * @param array|int|null    $flags
646
     *
647
     * @return array|bool|float|int|object|string|null
648
     */
649
    public function getPostGet($index = null, $filter = null, $flags = null)
650
    {
651
        if ($index === null) {
5✔
652
            return array_merge($this->getGet($index, $filter, $flags), $this->getPost($index, $filter, $flags));
3✔
653
        }
654

655
        // Use $_POST directly here, since filter_has_var only
656
        // checks the initial POST data, not anything that might
657
        // have been added since.
658
        return service('superglobals')->post($index) !== null
2✔
659
            ? $this->getPost($index, $filter, $flags)
1✔
660
            : (service('superglobals')->get($index) !== null ? $this->getGet($index, $filter, $flags) : $this->getPost($index, $filter, $flags));
2✔
661
    }
662

663
    /**
664
     * Fetch an item from GET data with fallback to POST.
665
     *
666
     * @param array|string|null $index  Index for item to be fetched from $_GET or $_POST
667
     * @param int|null          $filter A filter name to apply
668
     * @param array|int|null    $flags
669
     *
670
     * @return array|bool|float|int|object|string|null
671
     */
672
    public function getGetPost($index = null, $filter = null, $flags = null)
673
    {
674
        if ($index === null) {
5✔
675
            return array_merge($this->getPost($index, $filter, $flags), $this->getGet($index, $filter, $flags));
3✔
676
        }
677

678
        // Use $_GET directly here, since filter_has_var only
679
        // checks the initial GET data, not anything that might
680
        // have been added since.
681
        return service('superglobals')->get($index) !== null
2✔
682
            ? $this->getGet($index, $filter, $flags)
1✔
683
            : (service('superglobals')->post($index) !== null ? $this->getPost($index, $filter, $flags) : $this->getGet($index, $filter, $flags));
2✔
684
    }
685

686
    /**
687
     * Fetch an item from the COOKIE array.
688
     *
689
     * @param array|string|null $index  Index for item to be fetched from $_COOKIE
690
     * @param int|null          $filter A filter name to be applied
691
     * @param array|int|null    $flags
692
     *
693
     * @return array|bool|float|int|object|string|null
694
     */
695
    public function getCookie($index = null, $filter = null, $flags = null)
696
    {
697
        return $this->fetchGlobal('cookie', $index, $filter, $flags);
135✔
698
    }
699

700
    /**
701
     * Fetch the user agent string
702
     *
703
     * @return UserAgent
704
     */
705
    public function getUserAgent()
706
    {
707
        return $this->userAgent;
1✔
708
    }
709

710
    /**
711
     * Attempts to get old Input data that has been flashed to the session
712
     * with redirect_with_input(). It first checks for the data in the old
713
     * POST data, then the old GET data and finally check for dot arrays
714
     *
715
     * @return array|string|null
716
     */
717
    public function getOldInput(string $key)
718
    {
719
        // If the session hasn't been started, we're done.
720
        if (! isset($_SESSION)) {
20✔
721
            return null;
×
722
        }
723

724
        // Get previously saved in session
725
        $old = session('_ci_old_input');
20✔
726

727
        // If no data was previously saved, we're done.
728
        if ($old === null) {
20✔
729
            return null;
6✔
730
        }
731

732
        // Check for the value in the POST array first.
733
        if (isset($old['post'][$key])) {
16✔
734
            return $old['post'][$key];
13✔
735
        }
736

737
        // Next check in the GET array.
738
        if (isset($old['get'][$key])) {
8✔
739
            return $old['get'][$key];
3✔
740
        }
741

742
        helper('array');
6✔
743

744
        // Check for an array value in POST.
745
        if (isset($old['post'])) {
6✔
746
            $value = dot_array_search($key, $old['post']);
6✔
747
            if ($value !== null) {
6✔
748
                return $value;
1✔
749
            }
750
        }
751

752
        // Check for an array value in GET.
753
        if (isset($old['get'])) {
6✔
754
            $value = dot_array_search($key, $old['get']);
3✔
755
            if ($value !== null) {
3✔
756
                return $value;
1✔
757
            }
758
        }
759

760
        // requested session key not found
761
        return null;
5✔
762
    }
763

764
    /**
765
     * Returns an array of all files that have been uploaded with this
766
     * request. Each file is represented by an UploadedFile instance.
767
     */
768
    public function getFiles(): array
769
    {
770
        if ($this->files === null) {
1✔
771
            $this->files = new FileCollection();
1✔
772
        }
773

774
        return $this->files->all(); // return all files
1✔
775
    }
776

777
    /**
778
     * Verify if a file exist, by the name of the input field used to upload it, in the collection
779
     * of uploaded files and if is have been uploaded with multiple option.
780
     *
781
     * @return array|null
782
     */
783
    public function getFileMultiple(string $fileID)
784
    {
785
        if ($this->files === null) {
53✔
786
            $this->files = new FileCollection();
53✔
787
        }
788

789
        return $this->files->getFileMultiple($fileID);
53✔
790
    }
791

792
    /**
793
     * Retrieves a single file by the name of the input field used
794
     * to upload it.
795
     *
796
     * @return UploadedFile|null
797
     */
798
    public function getFile(string $fileID)
799
    {
800
        if ($this->files === null) {
49✔
801
            $this->files = new FileCollection();
1✔
802
        }
803

804
        return $this->files->getFile($fileID);
49✔
805
    }
806
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc