Completed
Pull Request — master (#25)
by Michal
15:14 queued 12:43
created

SwaggerHandler::getBasePath()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 23
ccs 0
cts 23
cp 0
rs 8.5906
cc 6
eloc 16
nc 12
nop 1
crap 42
1
<?php
2
3
namespace Tomaj\NetteApi\Handlers;
4
5
use Nette\Http\Request;
6
use Tomaj\NetteApi\ApiDecider;
7
use Tomaj\NetteApi\Link\ApiLink;
8
use Tomaj\NetteApi\Params\InputParam;
9
use Tomaj\NetteApi\Response\JsonApiResponse;
10
11
class SwaggerHandler extends BaseHandler
12
{
13
    /** @var ApiDecider */
14
    private $apiDecider;
15
16
    /** @var ApiLink */
17
    private $apiLink;
18
19
    /** @var Request */
20
    private $request;
21
    
22
    /** @var string */
23
    private $basePath;
24
    
25
    /**
26
     * ApiListingHandler constructor.
27
     *
28
     * @param ApiDecider  $apiDecider
29
     * @param ApiLink     $apiLink
30
     */
31
    public function __construct(ApiDecider $apiDecider, ApiLink $apiLink, Request $request)
32
    {
33
        parent::__construct();
34
        $this->apiDecider = $apiDecider;
35
        $this->apiLink = $apiLink;
36
        $this->request = $request;
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function description()
43
    {
44
        return 'Swagger API specification';
45
    }
46
    
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function tags()
51
    {
52
        return ['swagger', 'specification'];
53
    }
54
    
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function handle($params)
59
    {
60
        $version = $this->getEndpoint()->getVersion();
61
        $handlers = $this->getHandlers($version);
62
        $data = [
63
            'swagger' => '2.0', // ?
64
            'info' => [
65
                'title' => $this->apiDecider->getTitle(),
66
                'description' => $this->apiDecider->getDescription(),
67
                'version' => $version,
68
            ],
69
            'host' => $this->request->getUrl()->getHost(),
70
            'schemes' => [
71
                $this->request->getUrl()->getScheme(),
72
            ],
73
            'basePath' => $this->getBasePath($handlers),
74
            'produces' => [
75
                'application/json'
76
            ],
77
            'paths' => $this->getHandlersList($handlers),
78
        ];
79
80
        return new JsonApiResponse(200, $data);
81
    }
82
83
    /**
84
     * @param int $version
85
     * @return []
0 ignored issues
show
Documentation introduced by
The doc-type [] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
86
     */
87
    private function getHandlers($version)
88
    {
89
        $versionHandlers = array_filter($this->apiDecider->getHandlers(), function ($handler) use ($version) {
90
            return $version == $handler['endpoint']->getVersion();
91
        });
92
        return $versionHandlers;
93
    }
94
    
95
    /**
96
     * Create handler list for specified version
97
     *
98
     * @param array $versionHandlers
99
     *
100
     * @return array
101
     */
102
    private function getHandlersList($versionHandlers)
103
    {
104
        $list = [];
105
        $baseUrl = $this->request->getUrl()->getScheme() . '://' . $this->request->getUrl()->getHost() . $this->basePath;
106
        foreach ($versionHandlers as $handler) {
107
            $path = str_replace($baseUrl, '', $this->apiLink->link($handler['endpoint']));
108
            $list[$path][strtolower($handler['endpoint']->getMethod())] = [
109
                'summary' => $handler['handler']->description(),
110
                'operationId' => get_class($handler['handler']), // TODO zistit co to moze byt,
111
                'tags' => $handler['handler']->tags(),
112
                'parameters' => $this->createParamsList($handler['handler']),
113
                'responses' => [
114
                    // TODO,
115
                ],
116
            ];
117
        }
118
        return $list;
119
    }
120
    
121
    private function getBasePath($handlers)
122
    {
123
        $baseUrl = $this->request->getUrl()->getScheme() . '://' . $this->request->getUrl()->getHost();
124
        foreach ($handlers as $handler) {
125
            if (!$handler instanceof SwaggerHandler) {
126
                $link = $this->apiLink->link($handler['endpoint']);
127
                break;
128
            }
129
        }
130
        $commonPath = '';
131
        $actualPath = $this->request->getUrl()->getPath();
132
        $link = str_replace($baseUrl, '', $link);
0 ignored issues
show
Bug introduced by
The variable $link does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
133
        for ($i = 0; $i < strlen($link); $i++) {
134
            if ($link[$i] != $actualPath[$i]) {
135
                break;
136
            }
137
            if ($link[$i] == $actualPath[$i]) {
138
                $commonPath .= $link[$i];
139
            }
140
        }
141
        $this->basePath = rtrim($commonPath, '/');
142
        return $this->basePath;
143
    }
144
145
    /**
146
     * Create array with params for specified handler
147
     *
148
     * @param ApiHandlerInterface $handler
149
     *
150
     * @return array
151
     */
152
    private function createParamsList(ApiHandlerInterface $handler)
153
    {
154
        return array_map(function (InputParam $param) {
155
            $parameter = [
156
                'name' => $param->getKey(),
157
                'in' => $this->createIn($param->getType()),
158
                'required' => $param->isRequired(),
159
                'description' => $param->getDescription(),
160
                'type' => $param->getAvailableValues() ? 'list' : 'string',  // TODO - vsetko okrem listu je zatial string, nevieme rozlisit ine typy
161
            ];
162
            if ($param->getAvailableValues()) {
163
                $parameter['enum'] = $param->getAvailableValues();
164
            }
165
            return $parameter;
166
        }, $handler->params());
167
    }
168
    
169
    private function createIn($type)
170
    {
171
        if ($type == InputParam::TYPE_GET) {
172
            return 'query';
173
        }
174
        if ($type == InputParam::TYPE_COOKIE) {
175
            return 'cookie';
176
        }
177
        return 'body';
178
    }
179
}
180