Passed
Pull Request — 2.2 (#1960)
by
unknown
04:17
created

SwaggerUiAction::getContext()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 48
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 48
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 32
nc 10
nop 2
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[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 ApiPlatform\Core\Bridge\Symfony\Bundle\Action;
15
16
use ApiPlatform\Core\Documentation\Documentation;
17
use ApiPlatform\Core\Exception\RuntimeException;
18
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
19
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
20
use Symfony\Component\Asset\Packages;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\Response;
23
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
24
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
25
26
/**
27
 * Displays the documentation in Swagger UI.
28
 *
29
 * @author Kévin Dunglas <[email protected]>
30
 */
31
final class SwaggerUiAction
32
{
33
    private $resourceNameCollectionFactory;
34
    private $resourceMetadataFactory;
35
    private $normalizer;
36
    private $twig;
37
    private $urlGenerator;
38
    private $assetPackages;
39
    private $title;
40
    private $description;
41
    private $version;
42
    private $formats;
43
    private $oauthEnabled;
44
    private $oauthClientId;
45
    private $oauthClientSecret;
46
    private $oauthType;
47
    private $oauthFlow;
48
    private $oauthTokenUrl;
49
    private $oauthAuthorizationUrl;
50
    private $oauthRedirectUrl;
51
    private $oauthScopes;
52
53
    public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, \Twig_Environment $twig, UrlGeneratorInterface $urlGenerator, Packages $assetPackages, string $title = '', string $description = '', string $version = '', array $formats = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthRedirectUrl = NULL, $oauthScopes = [])
54
    {
55
        $this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
56
        $this->resourceMetadataFactory = $resourceMetadataFactory;
57
        $this->normalizer = $normalizer;
58
        $this->twig = $twig;
59
        $this->urlGenerator = $urlGenerator;
60
        $this->assetPackages = $assetPackages;
61
        $this->title = $title;
62
        $this->description = $description;
63
        $this->version = $version;
64
        $this->formats = $formats;
65
        $this->oauthEnabled = $oauthEnabled;
66
        $this->oauthClientId = $oauthClientId;
67
        $this->oauthClientSecret = $oauthClientSecret;
68
        $this->oauthType = $oauthType;
69
        $this->oauthFlow = $oauthFlow;
70
        $this->oauthTokenUrl = $oauthTokenUrl;
71
        $this->oauthAuthorizationUrl = $oauthAuthorizationUrl;
72
        $this->oauthRedirectUrl = $oauthRedirectUrl;
73
        $this->oauthScopes = $oauthScopes;
74
    }
75
76
    public function __invoke(Request $request)
77
    {
78
        $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats);
79
80
        return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation)));
81
    }
82
83
    /**
84
     * Gets the base Twig context.
85
     *
86
     * @param Request $request
87
     *
88
     * @return array
89
     */
90
    private function getContext(Request $request, Documentation $documentation): array
91
    {
92
        $context = [
93
            'title' => $this->title,
94
            'description' => $this->description,
95
            'formats' => $this->formats,
96
        ];
97
98
        $swaggerData = [
99
            'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']),
100
            'spec' => $this->normalizer->normalize($documentation, 'json', ['base_url' => $request->getBaseUrl()]),
101
        ];
102
103
        if (!$this->oauthRedirectUrl) {
104
            $this->oauthRedirectUrl = $this->assetPackages->getUrl('bundles/apiplatform/swagger-ui/oauth2-redirect.html');
105
        }
106
107
        $swaggerData['oauth'] = [
108
            'enabled' => $this->oauthEnabled,
109
            'clientId' => $this->oauthClientId,
110
            'clientSecret' => $this->oauthClientSecret,
111
            'type' => $this->oauthType,
112
            'flow' => $this->oauthFlow,
113
            'tokenUrl' => $this->oauthTokenUrl,
114
            'authorizationUrl' => $this->oauthAuthorizationUrl,
115
            'redirectUrl' => $this->oauthRedirectUrl,
116
            'scopes' => $this->oauthScopes,
117
        ];
118
119
        if ($request->isMethodSafe(false) && null !== $resourceClass = $request->attributes->get('_api_resource_class')) {
120
            $swaggerData['id'] = $request->attributes->get('id');
121
            $swaggerData['queryParameters'] = $request->query->all();
122
123
            $metadata = $this->resourceMetadataFactory->create($resourceClass);
124
            $swaggerData['shortName'] = $metadata->getShortName();
125
126
            if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) {
127
                $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, $swaggerData['shortName']);
128
            } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) {
129
                $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, $swaggerData['shortName']);
130
            } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) {
131
                $swaggerData['operationId'] = $subresourceOperationContext['operationId'];
132
            }
133
134
            list($swaggerData['path'], $swaggerData['method']) = $this->getPathAndMethod($swaggerData);
135
        }
136
137
        return $context + ['swagger_data' => $swaggerData];
138
    }
139
140
    private function getPathAndMethod(array $swaggerData): array
141
    {
142
        foreach ($swaggerData['spec']['paths'] as $path => $operations) {
143
            foreach ($operations as $method => $operation) {
144
                if ($operation['operationId'] === $swaggerData['operationId']) {
145
                    return [$path, $method];
146
                }
147
            }
148
        }
149
150
        throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId']));
151
    }
152
}
153