Completed
Pull Request — master (#666)
by Guy
02:18 queued 34s
created

PostmanCollectionWriter::generateEndpointItem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
1
<?php
2
3
namespace Mpociot\ApiDoc\Writing;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Support\Facades\URL;
7
use Illuminate\Support\Str;
8
use Ramsey\Uuid\Uuid;
9
10
class PostmanCollectionWriter
11
{
12
    /**
13
     * @var Collection
14
     */
15
    private $routeGroups;
16
17
    /**
18
     * @var string
19
     */
20
    private $baseUrl;
21
22
    /**
23
     * @var string
24
     */
25
    private $protocol;
26
27
    /**
28
     * @var array|null
29
     */
30
    private $auth;
31
32
    /**
33
     * CollectionWriter constructor.
34
     *
35
     * @param Collection $routeGroups
36
     */
37
    public function __construct(Collection $routeGroups, $baseUrl)
38
    {
39
        $this->routeGroups = $routeGroups;
40
        $this->protocol = Str::startsWith($baseUrl, 'https') ? 'https' : 'http';
41
        $this->baseUrl = URL::formatRoot('', $baseUrl);
42
        $this->auth = config('apidoc.postman.auth');
43
    }
44
45
    public function getCollection()
46
    {
47
        $collection = [
48
            'variables' => [],
49
            'info' => [
50
                'name' => config('apidoc.postman.name') ?: config('app.name').' API',
51
                '_postman_id' => Uuid::uuid4()->toString(),
52
                'description' => config('apidoc.postman.description') ?: '',
53
                'schema' => 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json',
54
            ],
55
            'item' => $this->routeGroups->map(function (Collection $routes, $groupName) {
56
                return [
57
                    'name' => $groupName,
58
                    'description' => $routes->first()['metadata']['groupDescription'],
59
                    'item' => $routes->map(\Closure::fromCallable([$this, 'generateEndpointItem']))->toArray(),
60
                ];
61
            })->values()->toArray(),
62
        ];
63
64
        if (! empty($this->auth)) {
65
            $collection['auth'] = $this->auth;
66
        }
67
68
        return json_encode($collection, JSON_PRETTY_PRINT);
69
    }
70
71
    protected function generateEndpointItem($route)
72
    {
73
        $mode = 'raw';
74
75
        $method = $route['methods'][0];
76
77
        return [
78
            'name' => $route['metadata']['title'] != '' ? $route['metadata']['title'] : $route['uri'],
79
            'request' => [
80
                'url' => $this->makeUrlData($route),
81
                'method' => $method,
82
                'header' => $this->resolveHeadersForRoute($route),
83
                'body' => [
84
                    'mode' => $mode,
85
                    $mode => json_encode($route['cleanBodyParameters'], JSON_PRETTY_PRINT),
86
                ],
87
                'description' => $route['metadata']['description'] ?? null,
88
                'response' => [],
89
            ],
90
        ];
91
    }
92
93
    protected function resolveHeadersForRoute($route)
94
    {
95
        $headers = collect($route['headers']);
96
97
        // Exclude authentication headers if they're handled by Postman auth
98
        $authHeader = $this->getAuthHeader();
99
        if (! empty($authHeader)) {
100
            $headers = $headers->except($authHeader);
101
        }
102
103
        return $headers
104
            ->union([
105
                'Accept' => 'application/json',
106
            ])
107
            ->map(function ($value, $header) {
108
                return [
109
                    'key' => $header,
110
                    'value' => $value,
111
                ];
112
            })
113
            ->values()
114
            ->all();
115
    }
116
117
    protected function makeUrlData($route)
118
    {
119
        [$urlParams, $queryParams] = collect($route['urlParameters'])->partition(function ($_, $key) use ($route) {
0 ignored issues
show
Bug introduced by
The variable $urlParams does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $queryParams does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
120
            return Str::contains($route['uri'], '{'.$key.'}');
121
        });
122
123
        /** @var Collection $queryParams */
124
        $base = [
125
            'protocol' => $this->protocol,
126
            'host' => $this->baseUrl,
127
            // Substitute laravel/symfony query params ({example}) to Postman style, prefixed with a colon
128
            'path' => preg_replace_callback('/\/{(\w+)\??}(?=\/|$)/', function ($matches) {
129
                return '/:'.$matches[1];
130
            }, $route['uri']),
131
            'query' => $queryParams->union($route['queryParameters'])->map(function ($parameter, $key) {
132
                return [
133
                    'key' => $key,
134
                    'value' => $parameter['value'],
135
                    'description' => $parameter['description'],
136
                    // Default query params to disabled if they aren't required and have empty values
137
                    'disabled' => ! $parameter['required'] && empty($parameter['value']),
138
                ];
139
            })->values()->toArray(),
140
        ];
141
142
        // If there aren't any url parameters described then return what we've got
143
        /** @var $urlParams Collection */
144
        if ($urlParams->isEmpty()) {
145
            return $base;
146
        }
147
148
        $base['variable'] = $urlParams->map(function ($parameter, $key) {
149
            return [
150
                'id' => $key,
151
                'key' => $key,
152
                'value' => $parameter['value'],
153
                'description' => $parameter['description'],
154
            ];
155
        })->values()->toArray();
156
157
        return $base;
158
    }
159
160
    protected function getAuthHeader()
161
    {
162
        $auth = $this->auth;
163
        if (empty($auth) || ! is_string($auth['type'] ?? null)) {
164
            return null;
165
        }
166
167
        switch ($auth['type']) {
168
            case 'bearer':
169
                return 'Authorization';
170
            case 'apikey':
171
                $spec = $auth['apikey'];
172
173
                if (isset($spec['in']) && $spec['in'] !== 'header') {
174
                    return null;
175
                }
176
177
                return $spec['key'];
178
            default:
179
                return null;
180
        }
181
    }
182
}
183