Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.95% covered (warning)
78.95%
15 / 19
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SchemaAttributeProvider
78.95% covered (warning)
78.95%
15 / 19
75.00% covered (warning)
75.00%
3 / 4
12.13
0.00% covered (danger)
0.00%
0 / 1
 supports
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addDisplaySchemaFor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addCreationSchemaFor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSchema
75.00% covered (warning)
75.00%
12 / 16
0.00% covered (danger)
0.00%
0 / 1
9.00
1<?php
2namespace Apie\SchemaGenerator\SchemaProviders;
3
4use Apie\Core\Attributes\SchemaMethod;
5use Apie\Core\Exceptions\InvalidTypeException;
6use Apie\Core\Exceptions\MethodIsNotStaticException;
7use Apie\SchemaGenerator\Builders\ComponentsBuilder;
8use Apie\SchemaGenerator\Enums\SchemaUsages;
9use Apie\SchemaGenerator\Exceptions\ICanNotExtractASchemaFromClassException;
10use Apie\SchemaGenerator\Interfaces\SchemaProvider;
11use cebe\openapi\spec\Components;
12use cebe\openapi\spec\Schema;
13use ReflectionClass;
14
15/**
16 * Reads #SchemaMethod attributes on classes.
17 *
18 * @implements SchemaProvider<object>
19 */
20class SchemaAttributeProvider implements SchemaProvider
21{
22    public function supports(ReflectionClass $class): bool
23    {
24        return !empty($class->getAttributes(SchemaMethod::class));
25    }
26
27    public function addDisplaySchemaFor(
28        ComponentsBuilder $componentsBuilder,
29        string $componentIdentifier,
30        ReflectionClass $class,
31        bool $nullable = false
32    ): Components {
33        return $this->getSchema($componentsBuilder, $componentIdentifier, $class, SchemaUsages::GET, $nullable);
34    }
35    
36    public function addCreationSchemaFor(
37        ComponentsBuilder $componentsBuilder,
38        string $componentIdentifier,
39        ReflectionClass $class,
40        bool $nullable = false
41    ): Components {
42        return $this->getSchema($componentsBuilder, $componentIdentifier, $class, SchemaUsages::CREATE, $nullable);
43    }
44
45    /**
46     * @param ReflectionClass<object> $class
47     */
48    private function getSchema(
49        ComponentsBuilder $componentsBuilder,
50        string $componentIdentifier,
51        ReflectionClass $class,
52        SchemaUsages $usage,
53        bool $nullable
54    ): Components {
55        foreach ($class->getAttributes(SchemaMethod::class) as $schemaMethod) {
56            $method = $class->getMethod($schemaMethod->newInstance()->methodName);
57            if (!$method->isStatic()) {
58                throw new MethodIsNotStaticException($method);
59            }
60            $result = $method->invoke(null, $usage, $componentsBuilder);
61            if (is_array($result)) {
62                $result = new Schema($result);
63            }
64            if ($result === null) {
65                continue;
66            }
67            if (!$result instanceof Schema || !$result->validate()) {
68                throw new InvalidTypeException($result, Schema::class);
69            }
70            if ($nullable) {
71                $result->nullable = true;
72            }
73            $componentsBuilder->setSchema($componentIdentifier, $result);
74
75            return $componentsBuilder->getComponents();
76        }
77        throw new ICanNotExtractASchemaFromClassException($class->name);
78    }
79}