ConstraintValueValidator   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 12
eloc 32
c 1
b 0
f 0
dl 0
loc 109
ccs 34
cts 34
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A empty() 0 7 2
A onTransformerException() 0 19 3
A validate() 0 22 4
A constraints() 0 3 1
A hasConstraints() 0 3 1
1
<?php
2
3
namespace Bdf\Form\Validator;
4
5
use Bdf\Form\ElementInterface;
6
use Bdf\Form\Error\FormError;
7
use Exception;
8
use Symfony\Component\Validator\Constraint;
9
10
/**
11
 * Value validator using symfony constraint
12
 * The element will be used as "root" context object on the symfony validator
13
 *
14
 * @template T
15
 * @implements ValueValidatorInterface<T>
16
 */
17
final class ConstraintValueValidator implements ValueValidatorInterface
18
{
19
    /**
20
     * @var self
21
     */
22
    private static $emptyInstance;
23
24
    /**
25
     * @var Constraint[]
26
     */
27
    private $constraints;
28
29
    /**
30
     * @var TransformerExceptionConstraint
31
     */
32
    private $transformerExceptionConstraint;
33
34
35
    /**
36
     * ConstraintValueValidator constructor.
37
     *
38
     * @param Constraint[] $constraints
39
     * @param TransformerExceptionConstraint|null $transformerExceptionConstraint
40
     */
41 434
    public function __construct(array $constraints = [], ?TransformerExceptionConstraint $transformerExceptionConstraint = null)
42
    {
43 434
        $this->constraints = $constraints;
44 434
        $this->transformerExceptionConstraint = $transformerExceptionConstraint ?? new TransformerExceptionConstraint();
45 434
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 414
    public function validate($value, ElementInterface $element): FormError
51
    {
52 414
        if (!$this->constraints) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->constraints of type Symfony\Component\Validator\Constraint[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
53 211
            return FormError::null();
54
        }
55
56 233
        $root = $element->root();
57 233
        $groups = $root->constraintGroups();
58
59
        /** @psalm-suppress TooManyArguments */
60
        // Note: Wrapping the element into a WeakReference will cause a BC break
61 233
        $context = $root->getValidator()->startContext(\WeakReference::create($element));
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Component\Valida...terface::startContext() has too many arguments starting with WeakReference::create($element). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

61
        $context = $root->getValidator()->/** @scrutinizer ignore-call */ startContext(\WeakReference::create($element));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
62
63 233
        foreach ($this->constraints as $constraint) {
64 233
            $errors = $context->validate($value, $constraint, $groups)->getViolations();
65
66 233
            if ($errors->has(0)) {
67 195
                return FormError::violation($errors->get(0));
68
            }
69
        }
70
71 117
        return FormError::null();
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 38
    public function onTransformerException(Exception $exception, $value, ElementInterface $element): FormError
78
    {
79 38
        if ($this->transformerExceptionConstraint->ignoreException) {
80 17
            return FormError::null();
81
        }
82
83
        /** @psalm-suppress TooManyArguments */
84 22
        $errors = $element->root()
85 22
            ->getValidator()
86 22
            ->startContext($element)
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Component\Valida...terface::startContext() has too many arguments starting with $element. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
            ->/** @scrutinizer ignore-call */ startContext($element)

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
87 22
            ->validate($value, $this->transformerExceptionConstraint->withException($exception))
88 22
            ->getViolations()
89
        ;
90
91 22
        if ($errors->has(0)) {
92 22
            return FormError::violation($errors->get(0));
93
        }
94
95 1
        return FormError::null();
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 47
    public function constraints(): array
102
    {
103 47
        return $this->constraints;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 58
    public function hasConstraints(): bool
110
    {
111 58
        return !empty($this->constraints);
112
    }
113
114
    /**
115
     * Get the empty value validator instance
116
     *
117
     * @return ConstraintValueValidator<mixed>
118
     */
119 413
    public static function empty(): self
120
    {
121 413
        if (self::$emptyInstance) {
122 413
            return self::$emptyInstance;
123
        }
124
125 1
        return self::$emptyInstance = new self();
126
    }
127
}
128