Test Failed
Push — develop ( bc3cc3...cc6a8c )
by Freddie
05:32
created

getConstraintsFromString()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 6
nop 1
dl 0
loc 32
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
namespace FlexPHP\Generator\Domain\Validators;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Symfony\Component\Validator\Constraints\Choice;
8
use Symfony\Component\Validator\Constraints\NotBlank;
9
use Symfony\Component\Validator\ConstraintViolationList;
10
use Symfony\Component\Validator\Validation;
11
12
/**
13
 * @Annotation
14
 */
15
class PropertyConstraintsValidator
16
{
17
    const ALLOWED_RULES = [
18
        'required',
19
        'minlength',
20
        'maxlength',
21
        'length',
22
        'mincheck',
23
        'maxcheck',
24
        'check',
25
        'min',
26
        'max',
27
        'equalto',
28
        'type',
29
    ];
30
31
    public function validate($constraints)
32
    {
33
        $violations = new ConstraintViolationList();
34
35
        if (empty($constraints)) {
36
            return $violations;
37
        }
38
39
        if (is_string($constraints)) {
40
            $constraints = $this->getConstraintsFromString($constraints);
41
        }
42
43
        if (!is_array($constraints)) {
44
            throw new InvalidArgumentException('Constraints: Format not supported');
45
        }
46
47
        $validator = Validation::createValidator();
48
49
        foreach ($constraints as $rule => $options) {
50
            if (is_string($options) && $options == 'required') {
51
                $rule = $options;
52
                $options = true;
53
            }
54
55
            $errors = $validator->validate($rule, [
56
                new NotBlank(),
57
                new Choice(self::ALLOWED_RULES),
58
            ]);
59
60
            if (count($errors) === 0) {
61
                $errors = $this->validateRule($rule, $options);
62
            }
63
64
            if (count($errors) !== 0) {
65
                foreach ($errors as $error) {
66
                    $violations->add($error);
67
                }
68
            }
69
        }
70
71
        return $violations;
72
    }
73
74
    private function getConstraintsFromString(string $constraints)
75
    {
76
        // Json syntax
77
        $_constraints = \json_decode($constraints, true);
78
79
        if (\is_null($_constraints) && \strpos($constraints, '[') === 0) {
80
            // Array syntax
81
            eval(sprintf('$_constraints = %1$s;', $constraints));
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
82
        }
83
84
        if (!\is_array($_constraints)) {
85
            // String syntax
86
            $_constraints = \explode('|', $constraints);
87
88
            if (\count($_constraints) > 0) {
89
                /** @var string $_constraint */
90
                foreach ($_constraints as $index => $_constraint) {
91
                    $_rule = \explode(':', $_constraint);
92
93
                    if (\count($_rule) == 2) {
94
                        list($_name, $_options) = $_rule;
95
                        $_constraints[$_name] = $_options;
96
                    } else {
97
                        $_constraints[$_rule[0]] = true;
98
                    }
99
100
                    unset($_constraints[$index]);
101
                }
102
            }
103
        }
104
105
        return $_constraints;
106
    }
107
108
    private function validateRule(string $rule, $options): ConstraintViolationList
109
    {
110
        $errors = new ConstraintViolationList();
111
112
        switch ($rule) {
113
            case 'required':
114
                $errors = (new RequiredConstraintValidator())->validate($options);
115
                break;
116
            case 'max':
117
            case 'maxlength':
118
            case 'maxcheck':
119
                $errors = (new MaxConstraintValidator())->validate($options);
120
                break;
121
            case 'min':
122
            case 'minlength':
123
            case 'mincheck':
124
                $errors = (new MinConstraintValidator())->validate($options);
125
                break;
126
            case 'equalto':
127
                $errors = (new EqualToConstraintValidator())->validate($options);
128
                break;
129
            case 'type':
130
                $errors = (new TypeConstraintValidator())->validate($options);
131
                break;
132
            case 'length':
133
            case 'check':
134
                $errors = (new RangeConstraintValidator())->validate($options);
135
                break;
136
        }
137
138
        return $errors;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $errors could return the type Symfony\Component\Valida...tViolationListInterface which includes types incompatible with the type-hinted return Symfony\Component\Valida...ConstraintViolationList. Consider adding an additional type-check to rule them out.
Loading history...
139
    }
140
}
141