Passed
Pull Request — 2.4 (#2530)
by Gonzalo
03:30
created

SwaggerUiAction::__construct()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 37
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 37
rs 9.472
c 0
b 0
f 0
cc 4
nc 4
nop 21

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Api\FormatsProviderInterface;
17
use ApiPlatform\Core\Documentation\Documentation;
18
use ApiPlatform\Core\Exception\InvalidArgumentException;
19
use ApiPlatform\Core\Exception\RuntimeException;
20
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
21
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
22
use ApiPlatform\Core\Util\RequestAttributesExtractor;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\HttpFoundation\Response;
25
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
26
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
27
28
/**
29
 * Displays the documentation.
30
 *
31
 * @author Kévin Dunglas <[email protected]>
32
 */
33
final class SwaggerUiAction
34
{
35
    private $resourceNameCollectionFactory;
36
    private $resourceMetadataFactory;
37
    private $normalizer;
38
    private $twig;
39
    private $urlGenerator;
40
    private $title;
41
    private $description;
42
    private $version;
43
    private $showWebby;
44
    private $formats = [];
45
    private $oauthEnabled;
46
    private $oauthClientId;
47
    private $oauthClientSecret;
48
    private $oauthType;
49
    private $oauthFlow;
50
    private $oauthTokenUrl;
51
    private $oauthAuthorizationUrl;
52
    private $oauthScopes;
53
    private $formatsProvider;
54
    private $swaggerUiEnabled;
55
    private $reDocEnabled;
56
    private $graphqlEnabled;
57
58
    /**
59
     * @throws InvalidArgumentException
60
     */
61
    public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, ResourceMetadataFactoryInterface $resourceMetadataFactory, NormalizerInterface $normalizer, \Twig_Environment $twig, UrlGeneratorInterface $urlGenerator, string $title = '', string $description = '', string $version = '', /* FormatsProviderInterface */ $formatsProvider = [], $oauthEnabled = false, $oauthClientId = '', $oauthClientSecret = '', $oauthType = '', $oauthFlow = '', $oauthTokenUrl = '', $oauthAuthorizationUrl = '', $oauthScopes = [], bool $showWebby = true, bool $swaggerUiEnabled = false, bool $reDocEnabled = false, bool $graphqlEnabled = false)
62
    {
63
        $this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
64
        $this->resourceMetadataFactory = $resourceMetadataFactory;
65
        $this->normalizer = $normalizer;
66
        $this->twig = $twig;
67
        $this->urlGenerator = $urlGenerator;
68
        $this->title = $title;
69
        $this->showWebby = $showWebby;
70
        $this->description = $description;
71
        $this->version = $version;
72
        $this->oauthEnabled = $oauthEnabled;
73
        $this->oauthClientId = $oauthClientId;
74
        $this->oauthClientSecret = $oauthClientSecret;
75
        $this->oauthType = $oauthType;
76
        $this->oauthFlow = $oauthFlow;
77
        $this->oauthTokenUrl = $oauthTokenUrl;
78
        $this->oauthAuthorizationUrl = $oauthAuthorizationUrl;
79
        $this->oauthScopes = $oauthScopes;
80
        $this->swaggerUiEnabled = $swaggerUiEnabled;
81
        $this->reDocEnabled = $reDocEnabled;
82
        $this->graphqlEnabled = $graphqlEnabled;
83
84
        if (\is_array($formatsProvider)) {
85
            if ($formatsProvider) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $formatsProvider of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
86
                // Only trigger notification for non-default argument
87
                @trigger_error('Using an array as formats provider is deprecated since API Platform 2.3 and will not be possible anymore in API Platform 3', E_USER_DEPRECATED);
88
            }
89
            $this->formats = $formatsProvider;
90
91
            return;
92
        }
93
        if (!$formatsProvider instanceof FormatsProviderInterface) {
94
            throw new InvalidArgumentException(sprintf('The "$formatsProvider" argument is expected to be an implementation of the "%s" interface.', FormatsProviderInterface::class));
95
        }
96
97
        $this->formatsProvider = $formatsProvider;
98
    }
99
100
    public function __invoke(Request $request)
101
    {
102
        // BC check to be removed in 3.0
103
        if (null !== $this->formatsProvider) {
104
            $this->formats = $this->formatsProvider->getFormatsFromAttributes(RequestAttributesExtractor::extractAttributes($request));
105
        }
106
107
        $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats);
108
109
        return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation)));
110
    }
111
112
    /**
113
     * Gets the base Twig context.
114
     */
115
    private function getContext(Request $request, Documentation $documentation): array
116
    {
117
        $context = [
118
            'title' => $this->title,
119
            'description' => $this->description,
120
            'formats' => $this->formats,
121
            'showWebby' => $this->showWebby,
122
            'swaggerUiEnabled' => $this->swaggerUiEnabled,
123
            'reDocEnabled' => $this->reDocEnabled,
124
            'graphqlEnabled' => $this->graphqlEnabled,
125
        ];
126
127
        $swaggerContext = ['spec_version' => $request->query->getInt('spec_version', 2)];
128
        if ('' !== $baseUrl = $request->getBaseUrl()) {
129
            $swaggerContext['base_url'] = $baseUrl;
130
        }
131
132
        $swaggerData = [
133
            'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']),
134
            'spec' => $this->normalizer->normalize($documentation, 'json', $swaggerContext),
135
        ];
136
137
        $swaggerData['oauth'] = [
138
            'enabled' => $this->oauthEnabled,
139
            'clientId' => $this->oauthClientId,
140
            'clientSecret' => $this->oauthClientSecret,
141
            'type' => $this->oauthType,
142
            'flow' => $this->oauthFlow,
143
            'tokenUrl' => $this->oauthTokenUrl,
144
            'authorizationUrl' => $this->oauthAuthorizationUrl,
145
            'scopes' => $this->oauthScopes,
146
        ];
147
148
        if ($request->isMethodSafe(false) && null !== $resourceClass = $request->attributes->get('_api_resource_class')) {
149
            $swaggerData['id'] = $request->attributes->get('id');
150
            $swaggerData['queryParameters'] = $request->query->all();
151
152
            $metadata = $this->resourceMetadataFactory->create($resourceClass);
153
            $swaggerData['shortName'] = $metadata->getShortName();
154
155
            if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) {
156
                $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, ucfirst($swaggerData['shortName']));
157
            } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) {
158
                $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, ucfirst($swaggerData['shortName']));
159
            } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) {
160
                $swaggerData['operationId'] = $subresourceOperationContext['operationId'];
161
            }
162
163
            list($swaggerData['path'], $swaggerData['method']) = $this->getPathAndMethod($swaggerData);
164
        }
165
166
        return $context + ['swagger_data' => $swaggerData];
167
    }
168
169
    private function getPathAndMethod(array $swaggerData): array
170
    {
171
        foreach ($swaggerData['spec']['paths'] as $path => $operations) {
172
            foreach ($operations as $method => $operation) {
173
                if ($operation['operationId'] === $swaggerData['operationId']) {
174
                    return [$path, $method];
175
                }
176
            }
177
        }
178
179
        throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId']));
180
    }
181
}
182