Field   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 93.75%

Importance

Changes 0
Metric Value
wmc 19
eloc 51
dl 0
loc 141
ccs 30
cts 32
cp 0.9375
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A addRule() 0 16 3
A getName() 0 3 1
A __construct() 0 5 1
A isRequired() 0 8 3
A getRules() 0 3 1
A validate() 0 19 6
A parseNumericValue() 0 9 3
A getValidator() 0 3 1
1
<?php
2
3
namespace kalanis\Restful\Validation;
4
5
6
use kalanis\Restful\Validation\Exceptions\ValidationException;
7
use Nette\Utils\Validators;
8
9
10
/**
11
 * Validation field
12
 * @package kalanis\Restful\Validation
13
 */
14 1
class Field implements IField
15
{
16
17
    /** @var array<string, string> Default field error messages for validator */
18
    public static array $defaultMessages = [
19
        IValidator::EQUAL => 'Please enter %s.',
20
        IValidator::MIN_LENGTH => 'Please enter a value of at least %d characters.',
21
        IValidator::MAX_LENGTH => 'Please enter a value no longer than %d characters.',
22
        IValidator::LENGTH => 'Please enter a value between %d and %d characters long.',
23
        IValidator::EMAIL => 'Please enter a valid email address.',
24
        IValidator::URL => 'Please enter a valid URL.',
25
        IValidator::INTEGER => 'Please enter a numeric value.',
26
        IValidator::FLOAT => 'Please enter a numeric value.',
27
        IValidator::RANGE => 'Please enter a value between %d and %d.',
28
        IValidator::UUID => 'Please enter a valid UUID.'
29
    ];
30
31
    /** @var string[] Numeric expressions that needs to convert value from string (because of x-www-form-urlencoded) */
32
    protected static array $numericExpressions = [
33
        IValidator::INTEGER,
34
        IValidator::FLOAT,
35
        IValidator::NUMERIC,
36
        IValidator::RANGE
37
    ];
38
39
    /** @var Rule[] */
40
    protected array $rules = [];
41
42 1
    public function __construct(
43
        protected readonly string     $name,
44
        protected readonly IValidator $validator,
45
    )
46
    {
47 1
    }
48
49
    /**
50
     * Add validation rule for this field
51
     * @param string $expression
52
     * @param string|null $message
53
     * @param array<bool|float|int|string|null> $argument
54
     * @param int $code
55
     * @return IField
56
     */
57
    public function addRule(string $expression, ?string $message = null, array $argument = [], int $code = 0): IField
58
    {
59 1
        $rule = new Rule(
60 1
            $this->name,
61 1
            strval($message),
62
            $code,
63
            $expression,
64
            $argument,
65
        );
66
67 1
        if (is_null($message) && isset(self::$defaultMessages[$expression])) {
68 1
            $rule->setMessage(self::$defaultMessages[$expression]);
69
        }
70
71 1
        $this->rules[] = $rule;
72 1
        return $this;
73
    }
74
75
    /**
76
     * Validate field for given value
77
     * @param mixed $value
78
     * @return Error[]
79
     */
80
    public function validate(mixed $value): array
81
    {
82 1
        if (!$this->isRequired() && is_null($value)) {
83 1
            return [];
84
        }
85
86 1
        $errors = [];
87 1
        foreach ($this->rules as $rule) {
88
            try {
89 1
                if (in_array($rule->getExpression(), static::$numericExpressions)) {
90 1
                    $value = $this->parseNumericValue($value);
91
                }
92
93 1
                $this->validator->validate($value, $rule);
94 1
            } catch (ValidationException $e) {
95 1
                $errors[] = new Error($e->getField(), $e->getMessage(), $e->getCode());
96
            }
97
        }
98 1
        return $errors;
99
    }
100
101
    /**
102
     * Is field required
103
     */
104
    public function isRequired(): bool
105
    {
106 1
        foreach ($this->rules as $rule) {
107 1
            if (IValidator::REQUIRED === $rule->getExpression()) {
108 1
                return true;
109
            }
110
        }
111 1
        return false;
112
    }
113
114
    /**
115
     * Convert string -> int, string -> float because of textual x-www-form-data
116
     * @param mixed $value
117
     * @return mixed
118
     */
119
    protected function parseNumericValue(mixed $value): mixed
120
    {
121 1
        if (Validators::isNumericInt($value)) {
122
            return intval($value);
123
        }
124 1
        if (Validators::isNumeric($value)) {
125
            return floatval($value);
126
        }
127 1
        return $value;
128
    }
129
130
    /**
131
     * Get field case-sensitive name
132
     * @return string
133
     */
134
    public function getName(): string
135
    {
136 1
        return $this->name;
137
    }
138
139
    /**
140
     * Get field rules
141
     * @return Rule[]
142
     */
143
    public function getRules(): array
144
    {
145 1
        return $this->rules;
146
    }
147
148
    /**
149
     * Get validator
150
     * @return IValidator
151
     */
152
    public function getValidator(): IValidator
153
    {
154 1
        return $this->validator;
155
    }
156
}
157