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

codeigniter4 / CodeIgniter4 / 25481830444

07 May 2026 07:18AM UTC coverage: 88.332% (+0.008%) from 88.324%
25481830444

Pull #10158

github

web-flow
Merge af3068c6b into 3a1047073
Pull Request #10158: feat: add typed FormRequest accessors

87 of 96 new or added lines in 5 files covered. (90.63%)

15 existing lines in 2 files now uncovered.

23726 of 26860 relevant lines covered (88.33%)

218.0 hits per line

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

84.78
/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
 * @see \CodeIgniter\Validation\ValidatedInputTest
26
 */
27
class ValidatedInput extends InputData
28
{
29
    /**
30
     * Returns a validated field as a Time instance.
31
     *
32
     * Supports dot-array syntax for nested validated data.
33
     */
34
    public function date(
35
        string $key,
36
        ?string $format = null,
37
        DateTimeZone|string|null $timezone = null,
38
    ): ?Time {
39
        $value = $this->get($key);
4✔
40

41
        if ($value === null) {
4✔
42
            return null;
1✔
43
        }
44

45
        if (! is_string($value) || $value === '') {
3✔
46
            $this->invalidValue($key, 'date', null);
1✔
47
        }
48

49
        try {
50
            if ($format === null) {
2✔
51
                return Time::parse($value, $timezone);
1✔
52
            }
53

54
            return Time::createFromFormat($format, $value, $timezone);
1✔
NEW
55
        } catch (Exception) {
×
NEW
56
            $this->invalidValue($key, 'date', null);
×
57
        }
58
    }
59

60
    /**
61
     * Returns a validated field as an enum instance.
62
     *
63
     * Supports dot-array syntax for nested validated data.
64
     *
65
     * @template TEnum of UnitEnum
66
     *
67
     * @param class-string<TEnum> $enumClass
68
     * @param TEnum|null          $default
69
     *
70
     * @return TEnum|null
71
     */
72
    public function enum(string $key, string $enumClass, ?UnitEnum $default = null): ?UnitEnum
73
    {
74
        if (! enum_exists($enumClass)) {
7✔
NEW
75
            throw new InvalidArgumentException('The "' . $enumClass . '" class is not a valid enum.');
×
76
        }
77

78
        if ($default instanceof UnitEnum && ! $default instanceof $enumClass) {
7✔
79
            $this->invalidValue($key, $enumClass, $default);
1✔
80
        }
81

82
        $value = $this->get($key, $default);
6✔
83

84
        if ($value === null) {
6✔
85
            return null;
1✔
86
        }
87

88
        if ($value instanceof UnitEnum) {
5✔
89
            if ($value instanceof $enumClass) {
1✔
90
                return $value;
1✔
91
            }
92

NEW
93
            $this->invalidValue($key, $enumClass, $default);
×
94
        }
95

96
        $reflection = new ReflectionEnum($enumClass);
4✔
97

98
        if ($reflection->isBacked()) {
4✔
99
            return $this->backedEnum($key, $enumClass, $reflection, $value);
3✔
100
        }
101

102
        if (is_string($value)) {
1✔
103
            foreach ($enumClass::cases() as $case) {
1✔
104
                if ($case->name === $value) {
1✔
105
                    return $case;
1✔
106
                }
107
            }
108
        }
109

NEW
110
        $this->invalidValue($key, $enumClass, $default);
×
111
    }
112

113
    private function backedEnum(string $key, string $enumClass, ReflectionEnum $reflection, mixed $value): UnitEnum
114
    {
115
        $backingType = $reflection->getBackingType()?->getName();
3✔
116

117
        if ($backingType === 'int') {
3✔
118
            if (is_string($value)) {
1✔
119
                $value = filter_var($value, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
1✔
120
            }
121

122
            if (! is_int($value)) {
1✔
NEW
123
                $this->invalidValue($key, $enumClass, null);
×
124
            }
125
        } elseif (! is_int($value) && ! is_string($value)) {
2✔
NEW
126
            $this->invalidValue($key, $enumClass, null);
×
127
        }
128

129
        if ($backingType === 'string') {
3✔
130
            $value = (string) $value;
2✔
131
        }
132

133
        $enum = $enumClass::tryFrom($value);
3✔
134

135
        if ($enum === null) {
3✔
136
            $this->invalidValue($key, $enumClass, null);
1✔
137
        }
138

139
        return $enum;
2✔
140
    }
141

142
    protected function invalidValue(string $key, string $type, mixed $default): never
143
    {
144
        throw new InvalidArgumentException(
8✔
145
            sprintf('The validated "%s" value cannot be read as %s.', $key, $type),
8✔
146
        );
8✔
147
    }
148
}
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