OpenApiFactory::getExtendedVersion()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentsBundle\OpenApi;
15
16
use ApiPlatform\Exception\ResourceClassNotFoundException as LegacyResourceClassNotFoundException;
17
use ApiPlatform\Metadata\Exception\ResourceClassNotFoundException;
18
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
19
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
20
use ApiPlatform\OpenApi\Model\PathItem;
21
use ApiPlatform\OpenApi\OpenApi;
22
use PackageVersions\Versions;
23
use Silverback\ApiComponentsBundle\Entity\Core\AbstractComponent;
24
use Silverback\ApiComponentsBundle\Entity\Core\AbstractPageData;
25
use Silverback\ApiComponentsBundle\Model\Uploadable\MediaObject;
26
use Symfony\Component\Form\Forms;
27
28
/**
29
 * @author Daniel West <[email protected]>
30
 */
31
class OpenApiFactory implements OpenApiFactoryInterface
32
{
33
    private OpenApiFactoryInterface $decorated;
34
    private ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory;
35
36
    public function __construct(OpenApiFactoryInterface $decorated, ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory)
37
    {
38
        $this->decorated = $decorated;
39
        $this->resourceMetadataFactory = $resourceMetadataFactory;
40
    }
41
42
    private function getResourceClassShortNames(array $resourceClassNames): array
43
    {
44
        $shortNames = [];
45
        foreach ($resourceClassNames as $resourceClassName) {
46
            try {
47
                $metadata = $this->resourceMetadataFactory->create($resourceClassName);
48
                foreach ($metadata as $metadatum) {
49
                    $shortNames[] = $metadatum->getShortName();
50
                }
51
            } catch (LegacyResourceClassNotFoundException|ResourceClassNotFoundException $exception) {
52
                // the component may not be enabled
53
            }
54
        }
55
56
        return $shortNames;
57
    }
58
59
    private function removeResources(OpenApi $openApi, array $resourceClassNames): void
60
    {
61
        $shortNames = $this->getResourceClassShortNames($resourceClassNames);
62
        $openApiPaths = $openApi->getPaths();
63
        $paths = $openApiPaths->getPaths();
64
        foreach ($paths as $path => $pathItem) {
65
            $operation = $pathItem->getGet() ?: $pathItem->getPost();
66
            if (!$operation) {
67
                continue;
68
            }
69
            $tags = $operation->getTags();
70
            if (!empty(array_intersect($tags, $shortNames))) {
71
                $openApiPaths->addPath($path, new PathItem());
72
            }
73
        }
74
    }
75
76
    public static function getExtendedVersion(string $version): string
77
    {
78
        return sprintf('%s (%s)', $version, Versions::getVersion('components-web-app/api-components-bundle'));
79
    }
80
81
    public function __invoke(array $context = []): OpenApi
82
    {
83
        $openApi = $this->decorated->__invoke($context);
84
        $version = self::getExtendedVersion($openApi->getInfo()->getVersion());
85
86
        $this->removeResources($openApi, [
87
            AbstractComponent::class,
88
            AbstractPageData::class,
89
            Forms::class,
90
            MediaObject::class,
91
        ]);
92
93
        return $openApi->withInfo($openApi->getInfo()->withVersion($version));
94
    }
95
}
96