Completed
Push — master ( 74c8e8...4a6a4e )
by Iakov
06:36 queued 03:08
created

Stenographer::getStenography()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 146
Code Lines 95

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 95
nc 1
nop 2
dl 0
loc 146
ccs 0
cts 146
cp 0
crap 2
rs 8.2857
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
4
namespace Kami\ApiCoreBundle\Stenographer;
5
6
7
use Doctrine\Common\Annotations\Reader;
8
use Doctrine\Common\Util\Inflector;
9
use Doctrine\ORM\Mapping\Column;
10
use EXSyst\Component\Swagger\Path;
11
use EXSyst\Component\Swagger\Swagger;
12
use Kami\ApiCoreBundle\Annotation\Access;
13
use Kami\ApiCoreBundle\Annotation\AnonymousAccess;
14
use Kami\ApiCoreBundle\Annotation\AnonymousCreate;
15
use Kami\ApiCoreBundle\Annotation\AnonymousUpdate;
16
use Kami\ApiCoreBundle\Annotation\CanBeCreatedBy;
17
use Kami\ApiCoreBundle\Annotation\CanBeUpdatedBy;
18
use Symfony\Component\Routing\Route;
19
20
class Stenographer
21
{
22
    /**
23
     * @var Reader
24
     */
25
    protected $reader;
26
27
    /**
28
     * Stenographer constructor.
29
     *
30
     * @param Reader $reader
31
     */
32
    public function __construct(Reader $reader)
33
    {
34
        $this->reader = $reader;
35
    }
36
37
    /**
38
     * @param Swagger $api
39
     *
40
     * @param Route $route
41
     */
42
    public function getStenography(Swagger $api, Route $route)
43
    {
44
        $paths = $api->getPaths();
45
        $paths->set(sprintf('/api/%s', $route->getDefault('_resource_name')), new Path([
46
            'get' => [
47
                'summary' => sprintf('Get %s index', $route->getDefault('_resource_name')),
48
                'parameters' => [
49
                    [
50
                        'name' => 'page',
51
                        'description' => 'Page to return',
52
                        'in' => 'integer'
53
                    ],
54
                    [
55
                        'name' => 'sort',
56
                        'description' => 'Field to sort',
57
                        'in' => 'string'
58
                    ],
59
                    [
60
                        'name' => 'direction',
61
                        'description' => 'Sort direction',
62
                        'in' => 'string (asc|desc)'
63
                    ]
64
                ],
65
                'responses' => [
66
                    '200' => [
67
                        'description' => 'Successful operation',
68
                    ],
69
                    '403' => [
70
                        'description' => 'Access denied'
71
                    ],
72
                    '401' => [
73
                        'description' => 'Authorization required'
74
                    ]
75
                ],
76
                'tags' => [$route->getDefault('_resource_name')]
77
            ],
78
            'post' => [
79
                'summary' => sprintf('Create %s', $route->getDefault('_resource_name')),
80
                'parameters' => $this->getCreateFormFields($route->getDefault('_entity')),
81
                'tags' => [$route->getDefault('_resource_name')],
82
                'responses' => [
83
                    '200' => [
84
                        'description' => 'Successful operation',
85
                    ],
86
                    '403' => [
87
                        'description' => 'Access denied'
88
                    ],
89
                    '401' => [
90
                        'description' => 'Authorization required'
91
                    ]
92
                ],
93
            ]
94
        ]));
95
        $paths->set(sprintf('/api/%s/{id}', $route->getDefault('_resource_name')), new Path([
96
            'get' => [
97
                'summary' => sprintf('Get single %s', $route->getDefault('_resource_name')),
98
                'parameters' => [
99
                    [
100
                        'name' => 'id',
101
                        'description' => 'Resource identifier',
102
                        'in' => 'integer'
103
                    ]
104
                ],
105
                'responses' => [
106
                    '200' => [
107
                        'description' => 'Successful operation'
108
                    ],
109
                    '403' => [
110
                        'description' => 'Access denied'
111
                    ],
112
                    '401' => [
113
                        'description' => 'Authorization required'
114
                    ]
115
                ],
116
                'tags' => [$route->getDefault('_resource_name')]
117
            ],
118
            'put' => [
119
                'summary' => sprintf('Update %s', $route->getDefault('_resource_name')),
120
                'parameters' => array_merge(
121
                    [[
122
                        'name' => 'id',
123
                        'description' => 'Resource identifier',
124
                        'in' => 'integer'
125
                    ]],
126
                    $this->getUpdateFormFields($route->getDefault('_entity'))),
127
                'tags' => [$route->getDefault('_resource_name')]
128
            ],
129
            'delete' => [
130
                'summary' => sprintf('Delete %s', $route->getDefault('_resource_name')),
131
                'parameters' => [
132
                    [
133
                        'name' => 'id',
134
                        'description' => 'Resource identifier',
135
                        'in' => 'integer'
136
                    ]
137
                ],
138
                'responses' => [
139
                    '204' => [
140
                        'description' => 'Successful operation'
141
                    ],
142
                    '403' => [
143
                        'description' => 'Access denied'
144
                    ],
145
                    '401' => [
146
                        'description' => 'Authorization required'
147
                    ]
148
                ],
149
                'tags' => [$route->getDefault('_resource_name')]
150
            ]
151
        ]));
152
        $paths->set(sprintf('/api/%s/filter', $route->getDefault('_resource_name')), new Path([
153
            'get' => [
154
                'summary' => 'Filter operation',
155
                'description' => "Filters payload should be base64 encoded json string\n Available filters are:\n"
156
                    ."|Parameter|Access|Type|\n"
157
                    ."|---------|------|----|\n".
158
                    implode("\n", $this->getAvailableFilterParams($route->getDefault('_entity'))),
159
                'parameters' => [
160
                    [
161
                        'name' => 'page',
162
                        'description' => 'Page to return',
163
                        'in' => 'integer'
164
                    ],
165
                    [
166
                        'name' => 'sort',
167
                        'description' => 'Field to sort',
168
                        'in' => 'string'
169
                    ],
170
                    [
171
                        'name' => 'direction',
172
                        'description' => 'Sort direction',
173
                        'in' => 'string (asc|desc)'
174
                    ]
175
                ],
176
                'responses' => [
177
                    '200' => [
178
                        'description' => 'Successful operation',
179
                    ],
180
                    '403' => [
181
                        'description' => 'Access denied'
182
                    ],
183
                    '401' => [
184
                        'description' => 'Authorization required'
185
                    ]
186
                ],
187
                'tags' => [$route->getDefault('_resource_name')]
188
            ],
189
        ]));
190
    }
191
192
193
    protected function getAvailableFilterParams($entity)
194
    {
195
        $reflection = $this->getEntityReflection($entity);
196
        $availableParams = [];
197
198
        foreach ($reflection->getProperties() as $property) {
199
            $anonymousAccess = $this->reader->getPropertyAnnotation($property, AnonymousAccess::class);
200
            $access = $this->reader->getPropertyAnnotation($property, Access::class);
201
            $column = $this->reader->getPropertyAnnotation($property, Column::class);
202
            if (($anonymousAccess || $access) && $column) {
203
                $param = ['name' => $property->getName()];
204
                $param['access'] = $anonymousAccess ? ['Any'] : [];
205
                $param['access'] = $access ? $access->roles : $param['access'];
206
                $param['access'] = implode(' ', $param['access']);
207
                $param['type'] = $column->type;
208
                $availableParams[] = sprintf('|%s|%s|%s|', $param['name'], $param['access'], $param['type']);
209
            }
210
        }
211
212
        return $availableParams;
213
    }
214
215
    public function getCreateFormFields($entity)
216
    {
217
        $reflection = $this->getEntityReflection($entity);
218
        $availableParams = [];
219
220
        foreach ($reflection->getProperties() as $property) {
221
            $anonymousCreate = $this->reader->getPropertyAnnotation($property, AnonymousCreate::class);
222
            $canBeCreatedBy = $this->reader->getPropertyAnnotation($property, CanBeCreatedBy::class);
223
            if ($anonymousCreate || $canBeCreatedBy) {
224
                $param = ['name' => sprintf('%s[%s]',
225
                    Inflector::tableize($reflection->getShortName()),
226
                    $property->getName()
227
                )];
228
                $param['in'] = $this->reader->getPropertyAnnotation($property, Column::class)->type;
229
                $availableParams[] = $param;
230
            }
231
        }
232
233
        return $availableParams;
234
    }
235
236
    public function getUpdateFormFields($entity)
237
    {
238
        $reflection = $this->getEntityReflection($entity);
239
        $availableParams = [];
240
241
        foreach ($reflection->getProperties() as $property) {
242
            $anonymousUpdate = $this->reader->getPropertyAnnotation($property, AnonymousUpdate::class);
243
            $canBeUpdatedBy = $this->reader->getPropertyAnnotation($property, CanBeUpdatedBy::class);
244
            if ($canBeUpdatedBy || $anonymousUpdate) {
245
                $param = ['name' => sprintf('%s[%s]',
246
                    Inflector::tableize($reflection->getShortName()),
247
                    $property->getName()
248
                )];
249
                $column = $this->reader->getPropertyAnnotation($property, Column::class);
250
251
                $param['in'] = $column ? $column->type : 'Unknown'; // todo: refactor this, so you can generate proper doc
252
                $availableParams[] = $param;
253
            }
254
        }
255
256
        return $availableParams;
257
    }
258
259
    /**
260
     * @param string $entity
261
     * @return \ReflectionClass
262
     */
263
    protected function getEntityReflection($entity)
264
    {
265
        try {
266
            $reflection = new \ReflectionClass($entity);
267
        } catch (\ReflectionException $e) {
268
            throw new \InvalidArgumentException('Route default entity can not be found');
269
        }
270
        return $reflection;
271
    }
272
}
273