Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
61.54% covered (warning)
61.54%
16 / 26
64.29% covered (warning)
64.29%
18 / 28
28.57% covered (danger)
28.57%
6 / 21
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ValidationErrors
61.54% covered (warning)
61.54%
16 / 26
64.29% covered (warning)
64.29%
18 / 28
28.57% covered (danger)
28.57%
6 / 21
83.33% covered (warning)
83.33%
5 / 6
85.43
0.00% covered (danger)
0.00%
0 / 1
 add
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 hasErrors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addValidationError
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 merge
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
9 / 9
0.00% covered (danger)
0.00%
0 / 8
100.00% covered (success)
100.00%
1 / 1
4
 __toString
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace App\Shared\Domain\Validation;
4
5use stdClass;
6use Symfony\Component\Validator\Constraints\Valid;
7
8/**
9 * A collection of validation errors
10 * @see ValidationError
11 *
12 * @author Wilhelm Zwertvaegher
13 *
14 */
15class ValidationErrors
16{
17    /**
18     * A list of errors, with a field as key
19     * The values are a list of ValidationError with an ErrorCode as key and a built ValidationError as value
20     * @var array<string, array<string, ValidationError>> $errors
21     *
22     */
23    private array $errors = [];
24
25    public function add(ValidationError $error): void
26    {
27        if (!isset($this->errors[$error->field()])) {
28            $this->errors[$error->field()] = [];
29        }
30        $this->addValidationError($error);
31    }
32
33    public function hasErrors(): bool
34    {
35        return count($this->errors) > 0;
36    }
37
38    /**
39     * @return array<string, array<string, ValidationError>>
40     */
41    public function getErrors(): array
42    {
43        return $this->errors;
44    }
45
46    private function addValidationError(ValidationError $error): void
47    {
48        // merge the ValidationError to keep details if provided
49        $lookupField = $error->field();
50        $lookupCode = $error->code()->getCode();
51
52        if (isset($this->errors[$lookupField][$lookupCode])) {
53            $this->errors[$lookupField][$lookupCode]->merge($error);
54        } else {
55            // we create a new ValidationError to prevent original $error to be modified
56            // if it is merged with other ValidationError in the future
57            $addedError = new ValidationError($error->field(), $error->code(), $error->details());
58            $this->errors[$lookupField][$lookupCode] = $addedError;
59        }
60    }
61
62    public function merge(ValidationErrors $validationErrors): void
63    {
64        foreach ($validationErrors->getErrors() as $field => $errors) {
65            if (!isset($this->errors[$field])) {
66                $this->errors[$field] = [];
67            }
68            foreach ($errors as $error) {
69                $this->addValidationError($error);
70            }
71        }
72    }
73
74
75    public function __toString(): string
76    {
77        $result = 'ValidationErrors{errors=';
78        foreach ($this->errors as $field => $errors) {
79            $result .= '{field='.$field.', details={';
80
81            foreach ($errors as $code => $error) {
82                $result .= '{code:'.$code.', details:{';
83                foreach ($error->details() as $key => $message) {
84                    $result .= '{key:'.$key.', message:{'.$message.'}}';
85                }
86                $result .= '}';
87            }
88            $result .= '}';
89        }
90
91        return $result;
92    }
93}