SchemaValidator::validate()   C
last analyzed

Complexity

Conditions 15
Paths 11

Size

Total Lines 76
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 46
CRAP Score 15.0021

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 46
c 1
b 0
f 0
nc 11
nop 2
dl 0
loc 76
ccs 46
cts 47
cp 0.9787
crap 15.0021
rs 5.9166

How to fix   Long Method    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
 * Schema Validator
4
 *
5
 * @author Vlad Shashkov <[email protected]>
6
 * @copyright Copyright (c) 2021, The Myaza Software
7
 */
8
9
declare(strict_types=1);
10
11
namespace SchemaValidator;
12
13
use SchemaValidator\Metadata\ClassMetadataFactoryWrapperInterface;
14
use SchemaValidator\Validator\ValidatorInterface;
15
use Symfony\Component\Validator\Constraint;
16
use Symfony\Component\Validator\ConstraintValidator;
17
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
18
use Symfony\Component\Validator\Exception\UnexpectedValueException;
19
use Symfony\Component\Validator\Util\PropertyPath;
20
21
final class SchemaValidator extends ConstraintValidator
22
{
23
    /**
24
     * SchemaValidator constructor.
25
     *
26
     * @param iterable<ValidatorInterface> $validators
27
     */
28 9
    public function __construct(
29
        private iterable $validators,
30
        private ClassMetadataFactoryWrapperInterface $classMetadataFactory
31
    ) {
32 9
    }
33
34 9
    public function validate(mixed $value, Constraint $constraint): void
35
    {
36 9
        if (!$constraint instanceof Schema) {
37 1
            throw new UnexpectedTypeException($constraint, Schema::class);
38
        }
39
40 8
        if (!is_array($value)) {
41 1
            throw new UnexpectedValueException($value, 'array');
42
        }
43
44 7
        $metadata = $this->classMetadataFactory->getMetadataFor($constraint->type, $value);
45 7
        $mapping  = $metadata->getMapping();
46
47 7
        if ($metadata->isEmpty() && null !== $mapping) {
48 2
            $property = $mapping->getProperty();
49
50 2
            if (!$property->isExits()) {
51 1
                $this->context->buildViolation(Schema::MESSAGE_FILED_MISSING)
52 1
                    ->atPath(PropertyPath::append($constraint->rootPath, $property->getName()))
53 1
                    ->setCode(Schema::MISSING_FILED_CODE)
54 1
                    ->setParameter('{{ field }}', $this->formatValue($property->getName()))
55 1
                    ->setInvalidValue(null)
56 1
                    ->addViolation()
57
                ;
58
59 1
                return;
60
            }
61
62 1
            $this->context->buildViolation(Schema::UNKNOWN_RESOURCE)
63 1
                ->atPath(PropertyPath::append($constraint->rootPath, $property->getName()))
64 1
                ->setParameter('{{ allowed }}', $this->formatValues($mapping->getMapValue()))
65 1
                ->setCode(Schema::UNKNOWN_RESOURCE_CODE)
66 1
                ->setInvalidValue($property->getInvalidValue())
67 1
                ->addViolation()
68
            ;
69
70 1
            return;
71
        }
72
73 5
        $attributes = $metadata->getAttributes();
74
75 5
        foreach ($metadata->getParameters() as $parameter) {
76 5
            $reflectionType = $parameter->getType();
77 5
            $propertyName   = ($attributes[$parameter->name] ?? null)?->getSerializedName() ?? $parameter->name;
78
79 5
            if (null === $reflectionType) {
80
                continue;
81
            }
82
83 5
            if (!array_key_exists($propertyName, $value) && !$parameter->isOptional()) {
84 1
                $this->context->buildViolation(Schema::MESSAGE_FILED_MISSING)
85 1
                    ->setParameter('{{ field }}', $this->formatValue($propertyName))
86 1
                    ->atPath(PropertyPath::append($constraint->rootPath, $propertyName))
87 1
                    ->setCode(Schema::MISSING_FILED_CODE)
88 1
                    ->setInvalidValue(null)
89 1
                    ->addViolation()
90
                ;
91
92 1
                continue;
93
            }
94
95 4
            if (!$parameter->isOptional() && $parameter->allowsNull() && null === $value[$propertyName]) {
96 3
                continue;
97
            }
98
99 3
            foreach ($this->validators as $validator) {
100 1
                if (!$validator->support($reflectionType)) {
101 1
                    continue;
102
                }
103
104 1
                $argument = new Argument($propertyName, $value, $reflectionType);
105 1
                $context  = new Context($constraint->rootPath, $constraint->type, $constraint->strictTypes, $this->context);
106
107 1
                $validator->validate($argument, $context);
108
109 1
                break;
110
            }
111
        }
112 5
    }
113
}
114