Completed
Push — master ( c762b0...684d44 )
by John
02:56
created

RamlBuilder::build()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 1
nop 0
1
<?php declare(strict_types = 1);
2
/*
3
 * This file is part of the KleijnWeb\ApiDescriptions package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
namespace KleijnWeb\ApiDescriptions\Description\Builder;
9
10
use KleijnWeb\ApiDescriptions\Description\Description;
11
use KleijnWeb\ApiDescriptions\Description\Operation;
12
use KleijnWeb\ApiDescriptions\Description\Parameter;
13
use KleijnWeb\ApiDescriptions\Description\Path;
14
use KleijnWeb\ApiDescriptions\Description\Response;
15
use KleijnWeb\ApiDescriptions\Description\Schema\Schema;
16
17
/**
18
 * @author John Kleijn <[email protected]>
19
 */
20
class RamlBuilder extends Builder
21
{
22
23
    /**
24
     * @return Description
25
     */
26
    public function build(): Description
27
    {
28
        $schemes = array_map('strtolower', isset($this->document->protocols) ? $this->document->protocols : []);
29
        $paths   = [];
30
31
        $this->document->apply(function ($definition, $attributeName, $parent, $parentAttributeName) use (&$paths) {
32
            if (substr((string)$attributeName, 0, 1) === '/') {
33
                $pathName         = "{$parentAttributeName}{$attributeName}";
34
                $paths[$pathName] = $this->createPath($pathName, $definition);
35
            }
36
        });
37
38
        return new Description($paths, [], '', $schemes, $this->document);
0 ignored issues
show
Compatibility introduced by
$this->document of type object<stdClass> is not a sub-type of object<KleijnWeb\ApiDesc...tion\Document\Document>. It seems like you assume a child class of the class stdClass to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
39
    }
40
41
    /**
42
     * @param string      $pathName
43
     * @param \stdClass   $definition
44
     *
45
     * @param Parameter[] $pathParameters
46
     *
47
     * @return Path
48
     */
49 View Code Duplication
    protected function createPath(string $pathName, \stdClass $definition, array $pathParameters = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
50
    {
51
        /** @var Operation[] $operations */
52
        $operations = [];
53
        foreach (self::$methodNames as $method) {
54
            if (isset($definition->$method)) {
55
                $operations[$method] = $this->createOperation($definition->$method, $pathName, $method);
56
            }
57
        }
58
        $pathParameters = array_merge($pathParameters, $this->extractParameters($definition));
59
60
        return new Path($pathName, $operations, $pathParameters);
61
    }
62
63
    /**
64
     * @param \stdClass $definition
65
     * @param string    $path
66
     * @param string    $method
67
     * @param array     $pathParameters
68
     *
69
     * @return Operation
70
     */
71
    protected function createOperation(
72
        \stdClass $definition,
73
        string $path,
74
        string $method,
75
        array $pathParameters = []
76
    ): Operation {
77
    
78
79
80
        /** @var Parameter[] $parameters */
81
        $parameters = array_merge($pathParameters, $this->extractParameters($definition));
82
        $responses  = [];
83
84
        if (isset($definition->responses)) {
85
            $hasOkResponse = false;
86
            foreach ($definition->responses as $code => $responseDefinition) {
87
                $code             = (int)$code;
88
                $responses[$code] = $this->createResponse($code, $responseDefinition);
89
            }
90
            if (!$hasOkResponse) {
91
                $responses[200] = $this->createResponse(200, (object)[]);
92
            }
93
        }
94
95
        $schemaDefinition             = (object)[];
96
        $schemaDefinition->type       = 'object';
97
        $schemaDefinition->required   = [];
98
        $schemaDefinition->properties = (object)[];
99
100 View Code Duplication
        foreach ($parameters as $parameter) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
            if ($parameter->isRequired()) {
102
                $schemaDefinition->required[] = $parameter->getName();
103
            }
104
            $schemaDefinition->properties->{$parameter->getName()} = $parameter->getSchema()->getDefinition();
105
        }
106
107
        $requestSchema = $this->schemaFactory->create($schemaDefinition);
108
109
        return new Operation($path, $method, $parameters, $requestSchema, $responses);
110
    }
111
112
    /**
113
     * @param \stdClass $definition
114
     *
115
     * @return array
116
     */
117
    protected function extractParameters(\stdClass $definition)
118
    {
119
        $parameters = [];
120
121 View Code Duplication
        if (isset($definition->queryParameters)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
            foreach ($definition->queryParameters as $name => $parameterDefinition) {
123
                $parameters[] = $this->createParameter($name, Parameter::IN_QUERY, $parameterDefinition);
124
            }
125
        }
126 View Code Duplication
        if (isset($definition->uriParameters)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
            foreach ($definition->uriParameters as $name => $parameterDefinition) {
128
                $parameters[] = $this->createParameter($name, Parameter::IN_PATH, $parameterDefinition);
129
            }
130
        }
131
132
        return $parameters;
133
    }
134
135
    /**
136
     * @param string    $name
137
     * @param string    $in
138
     * @param \stdClass $definition
139
     *
140
     * @return Parameter
141
     */
142
    protected function createParameter(string $name, string $in, \stdClass $definition)
143
    {
144
        $schema   = $this->createParameterSchema($definition);
145
        $required = isset($definition->required) && $definition->required;
146
147
        return new Parameter($name, $required, $schema, $in);
148
    }
149
150 View Code Duplication
    protected function createResponse(int $code, \stdClass $definition)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
    {
152
        return new Response(
153
            $code,
154
            $this->schemaFactory->create(isset($definition->schema) ? $definition->schema : null)
155
        );
156
    }
157
158
    /**
159
     * @param \stdClass $definition
160
     *
161
     * @return Schema
162
     */
163 View Code Duplication
    protected function createParameterSchema(\stdClass $definition): Schema
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
    {
165
        // Remove non-JSON-Schema properties
166
        $schemaDefinition     = clone $definition;
167
        $swaggerPropertyNames = [
168
            'name',
169
            'in',
170
            'description',
171
            'required',
172
            'allowEmptyValue',
173
            'collectionFormat'
174
        ];
175
        foreach ($swaggerPropertyNames as $propertyName) {
176
            if (property_exists($schemaDefinition, $propertyName)) {
177
                unset($schemaDefinition->$propertyName);
178
            }
179
        }
180
181
        return $this->schemaFactory->create($schemaDefinition);
182
    }
183
}
184