Passed
Push — master ( fbb10f...c0768e )
by Vlad
03:01
created

UuidValidator::validate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 15
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 25
ccs 16
cts 16
cp 1
crap 3
rs 9.7666
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\Validator;
12
13
use Ramsey\Uuid\UuidInterface;
14
use SchemaValidator\Argument;
15
use SchemaValidator\Context;
16
use function SchemaValidator\findUuidVersion;
17
use Symfony\Component\Uid\AbstractUid;
18
use Symfony\Component\Validator\Constraints\Uuid as SymfonyUuidConstraint;
19
use Symfony\Component\Validator\Util\PropertyPath;
20
use Symfony\Component\Validator\Validator\ValidatorInterface as SymfonyValidator;
21
22
final class UuidValidator implements ValidatorInterface
23
{
24
    private const INVALID_UUID_VERSION = 'This is not a valid UUID. Allowed Versions: %s';
25
    private const UUID_TYPES           = [
26
        UuidInterface::class,
27
        AbstractUid::class,
28
    ];
29
30
    /**
31
     * UuidValidator constructor.
32
     *
33
     * @param array<class-string|string> $uuids
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string|string> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string|string>.
Loading history...
34
     */
35 41
    public function __construct(
36
        private SymfonyValidator $validator,
37
        private array $uuids = self::UUID_TYPES,
38
    ) {
39 41
    }
40
41 14
    public function support(\ReflectionType $type): bool
42
    {
43 14
        if (!$type instanceof \ReflectionNamedType || $type->isBuiltin()) {
44 1
            return false;
45
        }
46
47 13
        $typeName = $type->getName();
48
49 13
        foreach ($this->uuids as $uuid) {
50 13
            if ((interface_exists($uuid) || class_exists($uuid)) && is_subclass_of($typeName, $uuid)) {
51 13
                return true;
52
            }
53
        }
54
55
        return false;
56
    }
57
58 27
    public function validate(Argument $argument, Context $context): void
59
    {
60 27
        $type = $argument->getType();
61
62 27
        if (!$type instanceof \ReflectionNamedType) {
63 1
            throw new \InvalidArgumentException('Type expected:' . \ReflectionNamedType::class);
64
        }
65
66
        /** @var string $value */
67 26
        $value = $argument->getValueByArgumentName();
68
        /** @var class-string $uuid */
69 26
        $uuid      = $type->getName();
70 26
        $execution = $context->getExecution();
71 26
        $version   = findUuidVersion($uuid);
72 26
        $options   = [];
73
74 26
        if (null !== $version) {
75 22
            $options['versions'] = [$version];
76 22
            $options['message']  = sprintf(self::INVALID_UUID_VERSION, $version);
77
        }
78
79 26
        $this->validator->inContext($execution)
80 26
            ->atPath(PropertyPath::append($context->getRootPath(), $argument->getName()))
81 26
            ->validate($value, [
82 26
                new SymfonyUuidConstraint($options),
83
            ])
84
        ;
85 26
    }
86
}
87