Completed
Push — develop ( 0660be...71868c )
by Freddie
04:14
created

PropertyConstraintsValidator::validate()   B

Complexity

Conditions 10
Paths 29

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 10

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 21
c 1
b 0
f 0
nc 29
nop 1
dl 0
loc 41
ccs 22
cts 22
cp 1
crap 10
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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