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

codeigniter4 / CodeIgniter4 / 9728735524

30 Jun 2024 02:32AM UTC coverage: 84.414% (-0.02%) from 84.434%
9728735524

push

github

web-flow
Merge pull request #8767 from kenjis/feat-resetTransStatus

feat: add BaseConnection::resetTransStatus()

2 of 2 new or added lines in 1 file covered. (100.0%)

6 existing lines in 5 files now uncovered.

20445 of 24220 relevant lines covered (84.41%)

188.91 hits per line

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

94.67
/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 Config\App;
21
use Config\Services;
22
use Locale;
23
use stdClass;
24

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

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

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

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

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

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

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

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

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

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

138
        $this->populateHeaders();
1,324✔
139

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

151
        // If file_get_contents() returns false or empty string, set null.
152
        if ($body === false || $body === '') {
1,324✔
153
            $body = null;
999✔
154
        }
155

156
        $this->uri          = $uri;
1,324✔
157
        $this->body         = $body;
1,324✔
158
        $this->userAgent    = $userAgent;
1,324✔
159
        $this->validLocales = $config->supportedLocales;
1,324✔
160

161
        parent::__construct($config);
1,324✔
162

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

169
        $this->detectLocale($config);
1,324✔
170
    }
171

172
    private function getPostMaxSize(): int
173
    {
174
        $postMaxSize = ini_get('post_max_size');
994✔
175

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

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

196
        if (! $config->negotiateLocale) {
1,324✔
197
            return;
1,324✔
198
        }
199

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

203
    /**
204
     * Sets up our URI object based on the information we have. This is
205
     * either provided by the user in the baseURL Config setting, or
206
     * determined from the environment as needed.
207
     *
208
     * @return void
209
     *
210
     * @deprecated 4.4.0 No longer used.
211
     */
212
    protected function detectURI(string $protocol, string $baseURL)
213
    {
214
        $this->setPath($this->detectPath($this->config->uriProtocol), $this->config);
×
215
    }
216

217
    /**
218
     * Detects the relative path based on
219
     * the URIProtocol Config setting.
220
     *
221
     * @deprecated 4.4.0 Moved to SiteURIFactory.
222
     */
223
    public function detectPath(string $protocol = ''): string
224
    {
225
        if ($protocol === '') {
16✔
226
            $protocol = 'REQUEST_URI';
4✔
227
        }
228

229
        $this->path = match ($protocol) {
16✔
230
            'REQUEST_URI'  => $this->parseRequestURI(),
11✔
231
            'QUERY_STRING' => $this->parseQueryString(),
3✔
232
            default        => $this->fetchGlobal('server', $protocol) ?? $this->parseRequestURI(),
2✔
233
        };
16✔
234

235
        return $this->path;
16✔
236
    }
237

238
    /**
239
     * Will parse the REQUEST_URI and automatically detect the URI from it,
240
     * fixing the query string if necessary.
241
     *
242
     * @return string The URI it found.
243
     *
244
     * @deprecated 4.4.0 Moved to SiteURIFactory.
245
     */
246
    protected function parseRequestURI(): string
247
    {
248
        if (! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) {
12✔
249
            return '';
×
250
        }
251

252
        // parse_url() returns false if no host is present, but the path or query string
253
        // contains a colon followed by a number. So we attach a dummy host since
254
        // REQUEST_URI does not include the host. This allows us to parse out the query string and path.
255
        $parts = parse_url('http://dummy' . $_SERVER['REQUEST_URI']);
12✔
256
        $query = $parts['query'] ?? '';
12✔
257
        $uri   = $parts['path'] ?? '';
12✔
258

259
        // Strip the SCRIPT_NAME path from the URI
260
        if (
261
            $uri !== '' && isset($_SERVER['SCRIPT_NAME'][0])
12✔
262
            && pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_EXTENSION) === 'php'
12✔
263
        ) {
264
            // Compare each segment, dropping them until there is no match
265
            $segments = $keep = explode('/', $uri);
11✔
266

267
            foreach (explode('/', $_SERVER['SCRIPT_NAME']) as $i => $segment) {
11✔
268
                // If these segments are not the same then we're done
269
                if (! isset($segments[$i]) || $segment !== $segments[$i]) {
11✔
270
                    break;
3✔
271
                }
272

273
                array_shift($keep);
11✔
274
            }
275

276
            $uri = implode('/', $keep);
11✔
277
        }
278

279
        // This section ensures that even on servers that require the URI to contain the query string (Nginx) a correct
280
        // URI is found, and also fixes the QUERY_STRING Server var and $_GET array.
281
        if (trim($uri, '/') === '' && str_starts_with($query, '/')) {
12✔
282
            $query                   = explode('?', $query, 2);
1✔
283
            $uri                     = $query[0];
1✔
284
            $_SERVER['QUERY_STRING'] = $query[1] ?? '';
1✔
285
        } else {
286
            $_SERVER['QUERY_STRING'] = $query;
11✔
287
        }
288

289
        // Update our globals for values likely to been have changed
290
        parse_str($_SERVER['QUERY_STRING'], $_GET);
12✔
291
        $this->populateGlobals('server');
12✔
292
        $this->populateGlobals('get');
12✔
293

294
        $uri = URI::removeDotSegments($uri);
12✔
295

296
        return ($uri === '/' || $uri === '') ? '/' : ltrim($uri, '/');
12✔
297
    }
298

299
    /**
300
     * Parse QUERY_STRING
301
     *
302
     * Will parse QUERY_STRING and automatically detect the URI from it.
303
     *
304
     * @deprecated 4.4.0 Moved to SiteURIFactory.
305
     */
306
    protected function parseQueryString(): string
307
    {
308
        $uri = $_SERVER['QUERY_STRING'] ?? @getenv('QUERY_STRING');
3✔
309

310
        if (trim($uri, '/') === '') {
3✔
311
            return '/';
1✔
312
        }
313

314
        if (str_starts_with($uri, '/')) {
2✔
315
            $uri                     = explode('?', $uri, 2);
2✔
316
            $_SERVER['QUERY_STRING'] = $uri[1] ?? '';
2✔
317
            $uri                     = $uri[0];
2✔
318
        }
319

320
        // Update our globals for values likely to been have changed
321
        parse_str($_SERVER['QUERY_STRING'], $_GET);
2✔
322
        $this->populateGlobals('server');
2✔
323
        $this->populateGlobals('get');
2✔
324

325
        $uri = URI::removeDotSegments($uri);
2✔
326

327
        return ($uri === '/' || $uri === '') ? '/' : ltrim($uri, '/');
2✔
328
    }
329

330
    /**
331
     * Provides a convenient way to work with the Negotiate class
332
     * for content negotiation.
333
     */
334
    public function negotiate(string $type, array $supported, bool $strictMatch = false): string
335
    {
336
        if ($this->negotiator === null) {
8✔
337
            $this->negotiator = Services::negotiator($this, true);
8✔
338
        }
339

340
        return match (strtolower($type)) {
8✔
341
            'media'    => $this->negotiator->media($supported, $strictMatch),
2✔
342
            'charset'  => $this->negotiator->charset($supported),
1✔
343
            'encoding' => $this->negotiator->encoding($supported),
1✔
344
            'language' => $this->negotiator->language($supported),
3✔
345
            default    => throw HTTPException::forInvalidNegotiationType($type),
8✔
346
        };
8✔
347
    }
348

349
    /**
350
     * Checks this request type.
351
     *
352
     * @param         string                                                                    $type HTTP verb or 'json' or 'ajax'
353
     * @phpstan-param string|'get'|'post'|'put'|'delete'|'head'|'patch'|'options'|'json'|'ajax' $type
354
     */
355
    public function is(string $type): bool
356
    {
357
        $valueUpper = strtoupper($type);
45✔
358

359
        $httpMethods = Method::all();
45✔
360

361
        if (in_array($valueUpper, $httpMethods, true)) {
45✔
362
            return $this->getMethod() === $valueUpper;
42✔
363
        }
364

365
        if ($valueUpper === 'JSON') {
3✔
366
            return str_contains($this->getHeaderLine('Content-Type'), 'application/json');
1✔
367
        }
368

369
        if ($valueUpper === 'AJAX') {
2✔
370
            return $this->isAJAX();
1✔
371
        }
372

373
        throw new InvalidArgumentException('Unknown type: ' . $type);
1✔
374
    }
375

376
    /**
377
     * Determines if this request was made from the command line (CLI).
378
     */
379
    public function isCLI(): bool
380
    {
381
        return false;
1✔
382
    }
383

384
    /**
385
     * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
386
     */
387
    public function isAJAX(): bool
388
    {
389
        return $this->hasHeader('X-Requested-With')
69✔
390
            && strtolower($this->header('X-Requested-With')->getValue()) === 'xmlhttprequest';
69✔
391
    }
392

393
    /**
394
     * Attempts to detect if the current connection is secure through
395
     * a few different methods.
396
     */
397
    public function isSecure(): bool
398
    {
399
        if (! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
3✔
400
            return true;
1✔
401
        }
402

403
        if ($this->hasHeader('X-Forwarded-Proto') && $this->header('X-Forwarded-Proto')->getValue() === 'https') {
2✔
404
            return true;
1✔
405
        }
406

407
        return $this->hasHeader('Front-End-Https') && ! empty($this->header('Front-End-Https')->getValue()) && strtolower($this->header('Front-End-Https')->getValue()) !== 'off';
1✔
408
    }
409

410
    /**
411
     * Sets the URI path relative to baseURL.
412
     *
413
     * Note: Since current_url() accesses the shared request
414
     * instance, this can be used to change the "current URL"
415
     * for testing.
416
     *
417
     * @param string   $path   URI path relative to baseURL
418
     * @param App|null $config Optional alternate config to use
419
     *
420
     * @return $this
421
     *
422
     * @deprecated 4.4.0 This method will be private. The parameter $config is deprecated. No longer used.
423
     */
424
    public function setPath(string $path, ?App $config = null)
425
    {
426
        $this->path = $path;
1,324✔
427

428
        return $this;
1,324✔
429
    }
430

431
    /**
432
     * Returns the URI path relative to baseURL,
433
     * running detection as necessary.
434
     */
435
    public function getPath(): string
436
    {
437
        return $this->path;
90✔
438
    }
439

440
    /**
441
     * Sets the locale string for this request.
442
     *
443
     * @return IncomingRequest
444
     */
445
    public function setLocale(string $locale)
446
    {
447
        // If it's not a valid locale, set it
448
        // to the default locale for the site.
449
        if (! in_array($locale, $this->validLocales, true)) {
5✔
450
            $locale = $this->defaultLocale;
1✔
451
        }
452

453
        $this->locale = $locale;
5✔
454
        Locale::setDefault($locale);
5✔
455

456
        return $this;
5✔
457
    }
458

459
    /**
460
     * Set the valid locales.
461
     *
462
     * @return $this
463
     */
464
    public function setValidLocales(array $locales)
465
    {
466
        $this->validLocales = $locales;
1✔
467

468
        return $this;
1✔
469
    }
470

471
    /**
472
     * Gets the current locale, with a fallback to the default
473
     * locale if none is set.
474
     */
475
    public function getLocale(): string
476
    {
477
        return $this->locale;
421✔
478
    }
479

480
    /**
481
     * Returns the default locale as set in app/Config/App.php
482
     */
483
    public function getDefaultLocale(): string
484
    {
485
        return $this->defaultLocale;
3✔
486
    }
487

488
    /**
489
     * Fetch an item from JSON input stream with fallback to $_REQUEST object. This is the simplest way
490
     * to grab data from the request object and can be used in lieu of the
491
     * other get* methods in most cases.
492
     *
493
     * @param array|string|null $index
494
     * @param int|null          $filter Filter constant
495
     * @param array|int|null    $flags
496
     *
497
     * @return array|bool|float|int|stdClass|string|null
498
     */
499
    public function getVar($index = null, $filter = null, $flags = null)
500
    {
501
        if (
502
            str_contains($this->getHeaderLine('Content-Type'), 'application/json')
18✔
503
            && $this->body !== null
18✔
504
        ) {
505
            return $this->getJsonVar($index, false, $filter, $flags);
1✔
506
        }
507

508
        return $this->fetchGlobal('request', $index, $filter, $flags);
17✔
509
    }
510

511
    /**
512
     * A convenience method that grabs the raw input stream and decodes
513
     * the JSON into an array.
514
     *
515
     * If $assoc == true, then all objects in the response will be converted
516
     * to associative arrays.
517
     *
518
     * @param bool $assoc   Whether to return objects as associative arrays
519
     * @param int  $depth   How many levels deep to decode
520
     * @param int  $options Bitmask of options
521
     *
522
     * @see http://php.net/manual/en/function.json-decode.php
523
     *
524
     * @return array|bool|float|int|stdClass|null
525
     *
526
     * @throws HTTPException When the body is invalid as JSON.
527
     */
528
    public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0)
529
    {
530
        if ($this->body === null) {
20✔
531
            return null;
2✔
532
        }
533

534
        $result = json_decode($this->body, $assoc, $depth, $options);
18✔
535

536
        if (json_last_error() !== JSON_ERROR_NONE) {
17✔
537
            throw HTTPException::forInvalidJSON(json_last_error_msg());
3✔
538
        }
539

540
        return $result;
14✔
541
    }
542

543
    /**
544
     * Get a specific variable from a JSON input stream
545
     *
546
     * @param array|string|null $index  The variable that you want which can use dot syntax for getting specific values.
547
     * @param bool              $assoc  If true, return the result as an associative array.
548
     * @param int|null          $filter Filter Constant
549
     * @param array|int|null    $flags  Option
550
     *
551
     * @return array|bool|float|int|stdClass|string|null
552
     */
553
    public function getJsonVar($index = null, bool $assoc = false, ?int $filter = null, $flags = null)
554
    {
555
        helper('array');
6✔
556

557
        $data = $this->getJSON(true);
6✔
558
        if (! is_array($data)) {
6✔
559
            return null;
1✔
560
        }
561

562
        if (is_string($index)) {
5✔
563
            $data = dot_array_search($index, $data);
5✔
564
        } elseif (is_array($index)) {
2✔
565
            $result = [];
2✔
566

567
            foreach ($index as $key) {
2✔
568
                $result[$key] = dot_array_search($key, $data);
2✔
569
            }
570

571
            [$data, $result] = [$result, null];
2✔
572
        }
573

574
        if ($data === null) {
5✔
575
            return null;
2✔
576
        }
577

578
        $filter ??= FILTER_DEFAULT;
5✔
579
        $flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
5✔
580

581
        if ($filter !== FILTER_DEFAULT
5✔
582
            || (
583
                (is_numeric($flags) && $flags !== 0)
5✔
584
                || is_array($flags) && $flags !== []
5✔
585
            )
586
        ) {
587
            if (is_array($data)) {
2✔
588
                // Iterate over array and append filter and flags
589
                array_walk_recursive($data, static function (&$val) use ($filter, $flags) {
1✔
590
                    $valType = gettype($val);
1✔
591
                    $val     = filter_var($val, $filter, $flags);
1✔
592

593
                    if (in_array($valType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $val !== false) {
1✔
594
                        settype($val, $valType);
1✔
595
                    }
596
                });
1✔
597
            } else {
598
                $dataType = gettype($data);
1✔
599
                $data     = filter_var($data, $filter, $flags);
1✔
600

601
                if (in_array($dataType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $data !== false) {
1✔
602
                    settype($data, $dataType);
×
603
                }
604
            }
605
        }
606

607
        if (! $assoc) {
5✔
608
            if (is_array($index)) {
4✔
609
                foreach ($data as &$val) {
2✔
610
                    $val = is_array($val) ? json_decode(json_encode($val)) : $val;
2✔
611
                }
612

613
                return $data;
2✔
614
            }
615

616
            return json_decode(json_encode($data));
3✔
617
        }
618

619
        return $data;
2✔
620
    }
621

622
    /**
623
     * A convenience method that grabs the raw input stream(send method in PUT, PATCH, DELETE) and decodes
624
     * the String into an array.
625
     *
626
     * @return array
627
     */
628
    public function getRawInput()
629
    {
630
        parse_str($this->body ?? '', $output);
13✔
631

632
        return $output;
13✔
633
    }
634

635
    /**
636
     * Gets a specific variable from raw input stream (send method in PUT, PATCH, DELETE).
637
     *
638
     * @param array|string|null $index  The variable that you want which can use dot syntax for getting specific values.
639
     * @param int|null          $filter Filter Constant
640
     * @param array|int|null    $flags  Option
641
     *
642
     * @return array|bool|float|int|object|string|null
643
     */
644
    public function getRawInputVar($index = null, ?int $filter = null, $flags = null)
645
    {
646
        helper('array');
9✔
647

648
        parse_str($this->body ?? '', $output);
9✔
649

650
        if (is_string($index)) {
9✔
651
            $output = dot_array_search($index, $output);
5✔
652
        } elseif (is_array($index)) {
4✔
653
            $data = [];
2✔
654

655
            foreach ($index as $key) {
2✔
656
                $data[$key] = dot_array_search($key, $output);
2✔
657
            }
658

659
            [$output, $data] = [$data, null];
2✔
660
        }
661

662
        $filter ??= FILTER_DEFAULT;
9✔
663
        $flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
9✔
664

665
        if (is_array($output)
9✔
666
            && (
667
                $filter !== FILTER_DEFAULT
9✔
668
                || (
9✔
669
                    (is_numeric($flags) && $flags !== 0)
9✔
670
                    || is_array($flags) && $flags !== []
9✔
671
                )
9✔
672
            )
673
        ) {
674
            // Iterate over array and append filter and flags
675
            array_walk_recursive($output, static function (&$val) use ($filter, $flags) {
×
676
                $val = filter_var($val, $filter, $flags);
×
677
            });
×
678

679
            return $output;
×
680
        }
681

682
        if (is_string($output)) {
9✔
683
            return filter_var($output, $filter, $flags);
4✔
684
        }
685

686
        return $output;
5✔
687
    }
688

689
    /**
690
     * Fetch an item from GET data.
691
     *
692
     * @param array|string|null $index  Index for item to fetch from $_GET.
693
     * @param int|null          $filter A filter name to apply.
694
     * @param array|int|null    $flags
695
     *
696
     * @return array|bool|float|int|object|string|null
697
     */
698
    public function getGet($index = null, $filter = null, $flags = null)
699
    {
700
        return $this->fetchGlobal('get', $index, $filter, $flags);
20✔
701
    }
702

703
    /**
704
     * Fetch an item from POST.
705
     *
706
     * @param array|string|null $index  Index for item to fetch from $_POST.
707
     * @param int|null          $filter A filter name to apply
708
     * @param array|int|null    $flags
709
     *
710
     * @return array|bool|float|int|object|string|null
711
     */
712
    public function getPost($index = null, $filter = null, $flags = null)
713
    {
714
        return $this->fetchGlobal('post', $index, $filter, $flags);
84✔
715
    }
716

717
    /**
718
     * Fetch an item from POST data with fallback to GET.
719
     *
720
     * @param array|string|null $index  Index for item to fetch from $_POST or $_GET
721
     * @param int|null          $filter A filter name to apply
722
     * @param array|int|null    $flags
723
     *
724
     * @return array|bool|float|int|object|string|null
725
     */
726
    public function getPostGet($index = null, $filter = null, $flags = null)
727
    {
728
        if ($index === null) {
5✔
729
            return array_merge($this->getGet($index, $filter, $flags), $this->getPost($index, $filter, $flags));
3✔
730
        }
731

732
        // Use $_POST directly here, since filter_has_var only
733
        // checks the initial POST data, not anything that might
734
        // have been added since.
735
        return isset($_POST[$index])
2✔
736
            ? $this->getPost($index, $filter, $flags)
1✔
737
            : (isset($_GET[$index]) ? $this->getGet($index, $filter, $flags) : $this->getPost($index, $filter, $flags));
2✔
738
    }
739

740
    /**
741
     * Fetch an item from GET data with fallback to POST.
742
     *
743
     * @param array|string|null $index  Index for item to be fetched from $_GET or $_POST
744
     * @param int|null          $filter A filter name to apply
745
     * @param array|int|null    $flags
746
     *
747
     * @return array|bool|float|int|object|string|null
748
     */
749
    public function getGetPost($index = null, $filter = null, $flags = null)
750
    {
751
        if ($index === null) {
5✔
752
            return array_merge($this->getPost($index, $filter, $flags), $this->getGet($index, $filter, $flags));
3✔
753
        }
754

755
        // Use $_GET directly here, since filter_has_var only
756
        // checks the initial GET data, not anything that might
757
        // have been added since.
758
        return isset($_GET[$index])
2✔
759
            ? $this->getGet($index, $filter, $flags)
1✔
760
            : (isset($_POST[$index]) ? $this->getPost($index, $filter, $flags) : $this->getGet($index, $filter, $flags));
2✔
761
    }
762

763
    /**
764
     * Fetch an item from the COOKIE array.
765
     *
766
     * @param array|string|null $index  Index for item to be fetched from $_COOKIE
767
     * @param int|null          $filter A filter name to be applied
768
     * @param array|int|null    $flags
769
     *
770
     * @return array|bool|float|int|object|string|null
771
     */
772
    public function getCookie($index = null, $filter = null, $flags = null)
773
    {
774
        return $this->fetchGlobal('cookie', $index, $filter, $flags);
114✔
775
    }
776

777
    /**
778
     * Fetch the user agent string
779
     *
780
     * @return UserAgent
781
     */
782
    public function getUserAgent()
783
    {
784
        return $this->userAgent;
1✔
785
    }
786

787
    /**
788
     * Attempts to get old Input data that has been flashed to the session
789
     * with redirect_with_input(). It first checks for the data in the old
790
     * POST data, then the old GET data and finally check for dot arrays
791
     *
792
     * @return array|string|null
793
     */
794
    public function getOldInput(string $key)
795
    {
796
        // If the session hasn't been started, we're done.
797
        if (! isset($_SESSION)) {
20✔
798
            return null;
×
799
        }
800

801
        // Get previously saved in session
802
        $old = session('_ci_old_input');
20✔
803

804
        // If no data was previously saved, we're done.
805
        if ($old === null) {
20✔
806
            return null;
6✔
807
        }
808

809
        // Check for the value in the POST array first.
810
        if (isset($old['post'][$key])) {
16✔
811
            return $old['post'][$key];
13✔
812
        }
813

814
        // Next check in the GET array.
815
        if (isset($old['get'][$key])) {
8✔
816
            return $old['get'][$key];
3✔
817
        }
818

819
        helper('array');
6✔
820

821
        // Check for an array value in POST.
822
        if (isset($old['post'])) {
6✔
823
            $value = dot_array_search($key, $old['post']);
6✔
824
            if ($value !== null) {
6✔
825
                return $value;
1✔
826
            }
827
        }
828

829
        // Check for an array value in GET.
830
        if (isset($old['get'])) {
6✔
831
            $value = dot_array_search($key, $old['get']);
3✔
832
            if ($value !== null) {
3✔
833
                return $value;
1✔
834
            }
835
        }
836

837
        // requested session key not found
838
        return null;
5✔
839
    }
840

841
    /**
842
     * Returns an array of all files that have been uploaded with this
843
     * request. Each file is represented by an UploadedFile instance.
844
     */
845
    public function getFiles(): array
846
    {
847
        if ($this->files === null) {
1✔
848
            $this->files = new FileCollection();
1✔
849
        }
850

851
        return $this->files->all(); // return all files
1✔
852
    }
853

854
    /**
855
     * Verify if a file exist, by the name of the input field used to upload it, in the collection
856
     * of uploaded files and if is have been uploaded with multiple option.
857
     *
858
     * @return array|null
859
     */
860
    public function getFileMultiple(string $fileID)
861
    {
862
        if ($this->files === null) {
51✔
863
            $this->files = new FileCollection();
51✔
864
        }
865

866
        return $this->files->getFileMultiple($fileID);
51✔
867
    }
868

869
    /**
870
     * Retrieves a single file by the name of the input field used
871
     * to upload it.
872
     *
873
     * @return UploadedFile|null
874
     */
875
    public function getFile(string $fileID)
876
    {
877
        if ($this->files === null) {
47✔
878
            $this->files = new FileCollection();
1✔
879
        }
880

881
        return $this->files->getFile($fileID);
47✔
882
    }
883
}
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

© 2025 Coveralls, Inc