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

codeigniter4 / CodeIgniter4 / 25607760430

09 May 2026 05:49PM UTC coverage: 88.404% (+0.08%) from 88.324%
25607760430

Pull #10158

github

web-flow
Merge 4dbd48845 into 2c774cae8
Pull Request #10158: feat: add typed FormRequest accessors

90 of 97 new or added lines in 6 files covered. (92.78%)

91 existing lines in 3 files now uncovered.

23839 of 26966 relevant lines covered (88.4%)

218.33 hits per line

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

85.42
/system/Validation/ValidatedInput.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\Validation;
15

16
use CodeIgniter\Exceptions\InvalidArgumentException;
17
use CodeIgniter\I18n\Time;
18
use CodeIgniter\Input\InputData;
19
use DateTimeZone;
20
use Exception;
21
use ReflectionEnum;
22
use UnitEnum;
23

24
/**
25
 * Represents validated input data.
26
 *
27
 * This class is stricter than InputData: missing values may use defaults and
28
 * null values remain null, but invalid present values throw.
29
 *
30
 * @see \CodeIgniter\Validation\ValidatedInputTest
31
 */
32
class ValidatedInput extends InputData
33
{
34
    /**
35
     * Returns a validated field as a Time instance.
36
     *
37
     * Supports dot-array syntax for nested validated data.
38
     *
39
     * @throws InvalidArgumentException
40
     */
41
    public function date(
42
        string $key,
43
        ?string $format = null,
44
        DateTimeZone|string|null $timezone = null,
45
        ?Time $default = null,
46
    ): ?Time {
47
        if (! $this->has($key)) {
5✔
48
            return $default;
1✔
49
        }
50

51
        $value = $this->get($key);
4✔
52

53
        if ($value === null) {
4✔
54
            return null;
1✔
55
        }
56

57
        if (! is_string($value) || $value === '') {
3✔
58
            $this->invalidValue($key, 'date', null);
1✔
59
        }
60

61
        try {
62
            if ($format === null) {
2✔
63
                return Time::parse($value, $timezone);
1✔
64
            }
65

66
            return Time::createFromFormat($format, $value, $timezone);
1✔
NEW
67
        } catch (Exception) {
×
NEW
68
            $this->invalidValue($key, 'date', null);
×
69
        }
70
    }
71

72
    /**
73
     * Returns a validated field as an enum instance.
74
     *
75
     * Supports dot-array syntax for nested validated data.
76
     *
77
     * @template TEnum of UnitEnum
78
     *
79
     * @param class-string<TEnum> $enumClass
80
     * @param TEnum|null          $default
81
     *
82
     * @return TEnum|null
83
     *
84
     * @throws InvalidArgumentException
85
     */
86
    public function enum(string $key, string $enumClass, ?UnitEnum $default = null): ?UnitEnum
87
    {
88
        if (! enum_exists($enumClass)) {
7✔
NEW
89
            throw new InvalidArgumentException('The "' . $enumClass . '" class is not a valid enum.');
×
90
        }
91

92
        if ($default instanceof UnitEnum && ! $default instanceof $enumClass) {
7✔
93
            $this->invalidValue($key, $enumClass, $default);
1✔
94
        }
95

96
        $value = $this->get($key, $default);
6✔
97

98
        if ($value === null) {
6✔
99
            return null;
1✔
100
        }
101

102
        if ($value instanceof UnitEnum) {
5✔
103
            if ($value instanceof $enumClass) {
1✔
104
                return $value;
1✔
105
            }
106

NEW
107
            $this->invalidValue($key, $enumClass, $default);
×
108
        }
109

110
        $reflection = new ReflectionEnum($enumClass);
4✔
111

112
        if ($reflection->isBacked()) {
4✔
113
            return $this->backedEnum($key, $enumClass, $reflection, $value);
3✔
114
        }
115

116
        if (is_string($value)) {
1✔
117
            foreach ($enumClass::cases() as $case) {
1✔
118
                if ($case->name === $value) {
1✔
119
                    return $case;
1✔
120
                }
121
            }
122
        }
123

NEW
124
        $this->invalidValue($key, $enumClass, $default);
×
125
    }
126

127
    private function backedEnum(string $key, string $enumClass, ReflectionEnum $reflection, mixed $value): UnitEnum
128
    {
129
        $backingType = $reflection->getBackingType()?->getName();
3✔
130

131
        if ($backingType === 'int') {
3✔
132
            if (is_string($value)) {
1✔
133
                $value = filter_var($value, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
1✔
134
            }
135

136
            if (! is_int($value)) {
1✔
NEW
137
                $this->invalidValue($key, $enumClass, null);
×
138
            }
139
        } elseif (! is_int($value) && ! is_string($value)) {
2✔
NEW
140
            $this->invalidValue($key, $enumClass, null);
×
141
        }
142

143
        if ($backingType === 'string') {
3✔
144
            $value = (string) $value;
2✔
145
        }
146

147
        $enum = $enumClass::tryFrom($value);
3✔
148

149
        if ($enum === null) {
3✔
150
            $this->invalidValue($key, $enumClass, null);
1✔
151
        }
152

153
        return $enum;
2✔
154
    }
155

156
    protected function invalidValue(string $key, string $type, mixed $default): never
157
    {
158
        throw new InvalidArgumentException(
8✔
159
            sprintf('The validated "%s" value cannot be read as %s.', $key, $type),
8✔
160
        );
8✔
161
    }
162
}
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