Passed
Push — master ( 7315fc...1ee6e1 )
by Vlad
03:07
created

UuidValidator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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