ArrayAccessPhpTypeSchemaResolver   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 24
c 2
b 0
f 0
dl 0
loc 70
ccs 27
cts 27
cp 1
rs 10
wmc 11

5 Methods

Rating   Name   Duplication   Size   Complexity  
A supportsPhpType() 0 3 1
A setOpenApiPhpTypeSchemaResolverManager() 0 4 1
A getWeight() 0 3 1
A getCollectionElementPhpType() 0 10 3
A resolvePhpTypeSchema() 0 26 5
1
<?php
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Nekhay <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Nekhay
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sunrise\Http\Router\OpenApi\PhpTypeSchemaResolver;
15
16
use ArrayAccess;
17
use ReflectionClass;
18
use ReflectionException;
19
use ReflectionParameter;
20
use ReflectionProperty;
21
use Reflector;
22
use Sunrise\Http\Router\OpenApi\Exception\UnsupportedPhpTypeException;
23
use Sunrise\Http\Router\OpenApi\OpenApiPhpTypeSchemaResolverInterface;
24
use Sunrise\Http\Router\OpenApi\OpenApiPhpTypeSchemaResolverManagerAwareInterface;
25
use Sunrise\Http\Router\OpenApi\OpenApiPhpTypeSchemaResolverManagerInterface;
26
use Sunrise\Http\Router\OpenApi\Type;
27
use Sunrise\Http\Router\OpenApi\TypeFactory;
28
use Sunrise\Hydrator\Annotation\Subtype;
29
30
use function end;
31
use function is_subclass_of;
32
33
/**
34
 * @since 3.0.0
35
 */
36
final class ArrayAccessPhpTypeSchemaResolver implements
37
    OpenApiPhpTypeSchemaResolverInterface,
38
    OpenApiPhpTypeSchemaResolverManagerAwareInterface
39
{
40
    private readonly OpenApiPhpTypeSchemaResolverManagerInterface $openApiPhpTypeSchemaResolverManager;
41
42 5
    public function setOpenApiPhpTypeSchemaResolverManager(
43
        OpenApiPhpTypeSchemaResolverManagerInterface $openApiPhpTypeSchemaResolverManager,
44
    ): void {
45 5
        $this->openApiPhpTypeSchemaResolverManager = $openApiPhpTypeSchemaResolverManager;
0 ignored issues
show
Bug introduced by
The property openApiPhpTypeSchemaResolverManager is declared read-only in Sunrise\Http\Router\Open...ssPhpTypeSchemaResolver.
Loading history...
46
    }
47
48 3
    public function supportsPhpType(Type $phpType, Reflector $phpTypeHolder): bool
49
    {
50 3
        return is_subclass_of($phpType->name, ArrayAccess::class);
51
    }
52
53
    /**
54
     * @inheritDoc
55
     *
56
     * @throws ReflectionException
57
     */
58 3
    public function resolvePhpTypeSchema(Type $phpType, Reflector $phpTypeHolder): array
59
    {
60 3
        $this->supportsPhpType($phpType, $phpTypeHolder) or throw new UnsupportedPhpTypeException();
61
62
        /** @var class-string<ArrayAccess<array-key, mixed>> $phpTypeName */
63 3
        $phpTypeName = $phpType->name;
64
65 3
        $arrayPhpType = new Type(Type::PHP_TYPE_NAME_ARRAY, $phpType->allowsNull);
66
        /** @var array{oneOf: array{0: array{type: 'array'}, 1: array{type: 'object'}}} $phpTypeSchema */
67 3
        $phpTypeSchema = $this->openApiPhpTypeSchemaResolverManager
68 3
            ->resolvePhpTypeSchema($arrayPhpType, $phpTypeHolder);
69
70
        if (
71 3
            ! $phpTypeHolder instanceof ReflectionParameter
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (! $phpTypeHolder instan...ype::class) === array(), Probably Intended Meaning: ! $phpTypeHolder instanc...pe::class) === array())
Loading history...
72 3
            && ! $phpTypeHolder instanceof ReflectionProperty
73 3
            || $phpTypeHolder->getAttributes(Subtype::class) === []
74
        ) {
75 3
            $collectionElementPhpType = self::getCollectionElementPhpType($phpTypeName);
76 3
            $collectionElementPhpTypeSchema = $this->openApiPhpTypeSchemaResolverManager
77 3
                ->resolvePhpTypeSchema($collectionElementPhpType, $phpTypeHolder);
78
79 3
            $phpTypeSchema['oneOf'][0]['items'] = $collectionElementPhpTypeSchema;
80 3
            $phpTypeSchema['oneOf'][1]['additionalProperties'] = $collectionElementPhpTypeSchema;
81
        }
82
83 3
        return $phpTypeSchema;
84
    }
85
86 3
    public function getWeight(): int
87
    {
88 3
        return 0;
89
    }
90
91
    /**
92
     * @param class-string $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
93
     *
94
     * @throws ReflectionException
95
     */
96 3
    private static function getCollectionElementPhpType(string $className): Type
97
    {
98 3
        $constructorParameters = (new ReflectionClass($className))->getConstructor()?->getParameters() ?? [];
99
100
        /** @var ReflectionParameter|false $lastConstructorParameter */
101 3
        $lastConstructorParameter = end($constructorParameters);
102
103 3
        return ($lastConstructorParameter instanceof ReflectionParameter && $lastConstructorParameter->isVariadic())
104 3
            ? TypeFactory::fromPhpTypeReflection($lastConstructorParameter->getType())
105 3
            : TypeFactory::mixedPhpType();
106
    }
107
}
108