Completed
Push — master ( c81543...bd2ead )
by Kévin
15s queued 10s
created

SwaggerUiAction::__construct()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 24
nc 4
nop 17

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 in Swagger UI.
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 $formats = [];
44
    private $oauthEnabled;
45
    private $oauthClientId;
46
    private $oauthClientSecret;
47
    private $oauthType;
48
    private $oauthFlow;
49
    private $oauthTokenUrl;
50
    private $oauthAuthorizationUrl;
51
    private $oauthScopes;
52
    private $formatsProvider;
53
54
    /**
55
     * @throws InvalidArgumentException
56
     */
57
    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 = [])
58
    {
59
        $this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
60
        $this->resourceMetadataFactory = $resourceMetadataFactory;
61
        $this->normalizer = $normalizer;
62
        $this->twig = $twig;
63
        $this->urlGenerator = $urlGenerator;
64
        $this->title = $title;
65
        $this->description = $description;
66
        $this->version = $version;
67
        $this->oauthEnabled = $oauthEnabled;
68
        $this->oauthClientId = $oauthClientId;
69
        $this->oauthClientSecret = $oauthClientSecret;
70
        $this->oauthType = $oauthType;
71
        $this->oauthFlow = $oauthFlow;
72
        $this->oauthTokenUrl = $oauthTokenUrl;
73
        $this->oauthAuthorizationUrl = $oauthAuthorizationUrl;
74
        $this->oauthScopes = $oauthScopes;
75
76
        if (\is_array($formatsProvider)) {
77
            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...
78
                // Only trigger notification for non-default argument
79
                @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);
80
            }
81
            $this->formats = $formatsProvider;
82
83
            return;
84
        }
85
        if (!$formatsProvider instanceof FormatsProviderInterface) {
86
            throw new InvalidArgumentException(sprintf('The "$formatsProvider" argument is expected to be an implementation of the "%s" interface.', FormatsProviderInterface::class));
87
        }
88
89
        $this->formatsProvider = $formatsProvider;
90
    }
91
92
    public function __invoke(Request $request)
93
    {
94
        // BC check to be removed in 3.0
95
        if (null !== $this->formatsProvider) {
96
            $this->formats = $this->formatsProvider->getFormatsFromAttributes(RequestAttributesExtractor::extractAttributes($request));
97
        }
98
99
        $documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version, $this->formats);
100
101
        return new Response($this->twig->render('@ApiPlatform/SwaggerUi/index.html.twig', $this->getContext($request, $documentation)));
102
    }
103
104
    /**
105
     * Gets the base Twig context.
106
     *
107
     * @param Request $request
108
     *
109
     * @return array
110
     */
111
    private function getContext(Request $request, Documentation $documentation): array
112
    {
113
        $context = [
114
            'title' => $this->title,
115
            'description' => $this->description,
116
            'formats' => $this->formats,
117
        ];
118
119
        $swaggerData = [
120
            'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']),
121
            'spec' => $this->normalizer->normalize($documentation, 'json', ['base_url' => $request->getBaseUrl()]),
122
        ];
123
124
        $swaggerData['oauth'] = [
125
            'enabled' => $this->oauthEnabled,
126
            'clientId' => $this->oauthClientId,
127
            'clientSecret' => $this->oauthClientSecret,
128
            'type' => $this->oauthType,
129
            'flow' => $this->oauthFlow,
130
            'tokenUrl' => $this->oauthTokenUrl,
131
            'authorizationUrl' => $this->oauthAuthorizationUrl,
132
            'scopes' => $this->oauthScopes,
133
        ];
134
135
        if ($request->isMethodSafe(false) && null !== $resourceClass = $request->attributes->get('_api_resource_class')) {
136
            $swaggerData['id'] = $request->attributes->get('id');
137
            $swaggerData['queryParameters'] = $request->query->all();
138
139
            $metadata = $this->resourceMetadataFactory->create($resourceClass);
140
            $swaggerData['shortName'] = $metadata->getShortName();
141
142
            if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) {
143
                $swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, $swaggerData['shortName']);
144
            } elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) {
145
                $swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, $swaggerData['shortName']);
146
            } elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) {
147
                $swaggerData['operationId'] = $subresourceOperationContext['operationId'];
148
            }
149
150
            list($swaggerData['path'], $swaggerData['method']) = $this->getPathAndMethod($swaggerData);
151
        }
152
153
        return $context + ['swagger_data' => $swaggerData];
154
    }
155
156
    private function getPathAndMethod(array $swaggerData): array
157
    {
158
        foreach ($swaggerData['spec']['paths'] as $path => $operations) {
159
            foreach ($operations as $method => $operation) {
160
                if ($operation['operationId'] === $swaggerData['operationId']) {
161
                    return [$path, $method];
162
                }
163
            }
164
        }
165
166
        throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId']));
167
    }
168
}
169