Completed
Push — master ( ff6361...375f0f )
by Matthew
04:31
created

getFiltersFromQueryString()   D

Complexity

Conditions 10
Paths 19

Size

Total Lines 45
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
c 2
b 0
f 2
dl 0
loc 45
rs 4.8196
cc 10
eloc 22
nc 19
nop 3

How to fix   Complexity   

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
namespace Ps2alerts\Api\Controller\Endpoint;
4
5
use League\Fractal\Resource\Collection;
6
use League\Fractal\Resource\Item;
7
use Ps2alerts\Api\Contract\ConfigAwareInterface;
8
use Ps2alerts\Api\Contract\ConfigAwareTrait;
9
use Ps2alerts\Api\Contract\DatabaseAwareInterface;
10
use Ps2alerts\Api\Contract\DatabaseAwareTrait;
11
use Ps2alerts\Api\Exception\InvalidArgumentException;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
15
abstract class AbstractEndpointController implements
16
    ConfigAwareInterface,
17
    DatabaseAwareInterface
18
{
19
    use ConfigAwareTrait;
20
    use DatabaseAwareTrait;
21
22
    /**
23
     * Contains the repository used for interfacing with the database
24
     *
25
     * @var \Ps2alerts\Api\Repository\AbstractEndpointRepository
26
     */
27
    protected $repository;
28
29
    /**
30
     * Stores the status code
31
     *
32
     * @var integer
33
     */
34
    protected $statusCode = 200;
35
36
    /**
37
     * Holds Fractal
38
     *
39
     * @var \League\Fractal\Manager
40
     */
41
    protected $fractal;
42
43
    /**
44
     * Holds the transformer we're going to use
45
     *
46
     * @var mixed|\Leage\Fractal\TransformerAbstract
47
     */
48
    protected $transformer;
49
50
    const CODE_WRONG_ARGS     = 'API-MALFORMED-REQUEST';
51
    const CODE_NOT_FOUND      = 'API-NOT-FOUND';
52
    const CODE_INTERNAL_ERROR = 'API-DOH';
53
    const CODE_UNAUTHORIZED   = 'API-UNAUTHORIZED';
54
    const CODE_FORBIDDEN      = 'API-DENIED';
55
    const CODE_EMPTY          = 'API-EMPTY';
56
57
    /**
58
     * Getter for statusCode
59
     *
60
     * @return int
61
     */
62
    public function getStatusCode()
63
    {
64
        return $this->statusCode;
65
    }
66
67
    /**
68
     * Setter for statusCode
69
     *
70
     * @param int $statusCode Value to set
71
     *
72
     * @return self
73
     */
74
    public function setStatusCode($statusCode)
75
    {
76
        $this->statusCode = $statusCode;
77
        return $this;
78
    }
79
80
    /**
81
     * Master function to split out appropiate calls
82
     *
83
     * @param  string                                     $kind     The kind of data we wish to return
84
     * @param  array                                      $data     The data itself
85
     * @param  \League\Fractal\TransformerAbstract        $callback The transformer class to call
86
     * @param  \Symfony\Component\HttpFoundation\Request  $request  The request itself
87
     * @param  \Symfony\Component\HttpFoundation\Response $response The response object to eventually call
88
     *
89
     * @return \Symfony\Component\HttpFoundation\Response
90
     */
91
    protected function respond($kind, $data, $callback, Request $request, Response $response)
92
    {
93
        // Detect what embeds we need
94
        $this->getIncludesFromRequest($request);
95
        switch ($kind) {
96
            case 'item':
97
                return $this->respondWithItem($data, $callback, $response);
98
            case 'collection':
99
                return $this->respondWithCollection($data, $callback, $response);
100
            default:
101
                return $this->errorInternalError('No Response was defined. Please report this.');
0 ignored issues
show
Documentation introduced by
'No Response was defined. Please report this.' is of type string, but the function expects a object<Symfony\Component\HttpFoundation\Response>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
102
        }
103
    }
104
105
    /**
106
     * Builds an item response in Fractal then hands off to the responder
107
     *
108
     * @param  array                                      $item     The item to transform
109
     * @param  \League\Fractal\TransformerAbstract        $transformer The Transformer to pass through to Fractal
110
     * @param  \Symfony\Component\HttpFoundation\Response $response The client's response
111
     *
112
     * @return array
113
     */
114
    protected function respondWithItem($item, $transformer, Response $response)
115
    {
116
        return $this->respondWithArray($response, $this->createItem($item, $transformer));
117
    }
118
119
    /**
120
     * Creates the item array and returns it hence it came.
121
     *
122
     * @param  array                               $item     The data to parse
123
     * @param  \League\Fractal\TransformerAbstract $transformer
124
     *
125
     * @return array
126
     */
127
    public function createItem($item, $transformer)
128
    {
129
        $resource = new Item($item, $transformer);
130
        $rootScope = $this->fractal->createData($resource);
131
132
        return $rootScope->toArray();
133
    }
134
135
    /**
136
     * Builds a collection of items from Fractal then hands off to the responder
137
     *
138
     * @param  array                                      $collection  The collection to transform
139
     * @param  \League\Fractal\TransformerAbstract        $transformer The Transformer to pass through to Fractal
140
     * @param  \Symfony\Component\HttpFoundation\Response $response    The client's response
141
     *
142
     * @return array
143
     */
144
    protected function respondWithCollection($collection, $transformer, Response $response)
145
    {
146
        return $this->respondWithArray($response, $this->createCollection($collection, $transformer));
147
    }
148
149
    /**
150
     * Creates a collection array and sends it back to hence it came.
151
     *
152
     * @param  array                               $collection
153
     * @param  \League\Fractal\TransformerAbstract $transformer
154
     *
155
     * @return array
156
     */
157
    public function createCollection($collection, $transformer)
158
    {
159
        $resource = new Collection($collection, $transformer);
160
        $rootScope = $this->fractal->createData($resource);
161
162
        return $rootScope->toArray();
163
    }
164
165
    /**
166
     * The final step where the formatted array is now sent back as a response in JSON form
167
     *
168
     * @param  \Symfony\Component\HttpFoundation\Response $response
169
     * @param  array                                      $array
170
     *
171
     * @return \Symfony\Component\HttpFoundation\Response
172
     */
173
    protected function respondWithArray(Response $response, array $array)
174
    {
175
        $response->setStatusCode($this->getStatusCode());
176
        $response->setContent(json_encode($array));
177
        $response->headers->set('Content-Type', 'application/json');
178
179
        // This is the end of the road. FIRE ZE RESPONSE!
180
        return $response;
181
    }
182
183
    /**
184
     * Responds gracefully with an error.
185
     *
186
     * @param  \Symfony\Component\HttpFoundation\Response $response
187
     * @param  string                                     $message   Response message to put in the error
188
     * @param  int                                        $errorCode Error code to set
189
     *
190
     * @return array
191
     */
192
    protected function respondWithError(Response $response, $message, $errorCode)
193
    {
194
        if ($this->statusCode === 200) {
195
            trigger_error(
196
                "This Error code 200 should never be sent. Please report this to the developer.",
197
                E_USER_WARNING
198
            );
199
        }
200
201
        // Pass to responder
202
        return $this->respondWithArray($response, [
203
            'error' => [
204
                'code'      => $errorCode,
205
                'http_code' => $this->statusCode,
206
                'message'   => $message,
207
            ]
208
        ]);
209
    }
210
211
    /**
212
     * Generates a response with a 404 HTTP error and a given message.
213
     *
214
     * @param  \Symfony\Component\HttpFoundation\Response $response
215
     * @param  string                                     $message
216
     *
217
     * @return void
218
     */
219
    public function errorEmpty(Response $response, $message = 'No data / Empty')
220
    {
221
        return $this->setStatusCode(404)
222
                    ->respondWithError($response, $message, self::CODE_EMPTY);
223
    }
224
225
    /**
226
     * Generates a Response with a 403 HTTP header and a given message.
227
     *
228
     * @param  \Symfony\Component\HttpFoundation\Response $response
229
     * @param  string                                     $message
230
     *
231
     * @return void
232
     */
233
    public function errorForbidden(Response $response, $message = 'Forbidden')
234
    {
235
        return $this->setStatusCode(403)
236
                    ->respondWithError($response, $message, self::CODE_FORBIDDEN);
237
    }
238
239
    /**
240
     * Generates a Response with a 500 HTTP header and a given message.
241
     *
242
     * @param  \Symfony\Component\HttpFoundation\Response $response
243
     * @param  string                                     $message
244
     *
245
     * @return void
246
     */
247
    public function errorInternalError(Response $response, $message = 'Internal Error')
248
    {
249
        return $this->setStatusCode(500)
250
                    ->respondWithError($response, $message, self::CODE_INTERNAL_ERROR);
251
    }
252
253
    /**
254
     * Generates a Response with a 404 HTTP header and a given message.
255
     *
256
     * @param  \Symfony\Component\HttpFoundation\Response $response
257
     * @param  string                                     $message
258
     *
259
     * @return void
260
     */
261
    public function errorNotFound(Response $response, $message = 'Resource Not Found')
262
    {
263
        return $this->setStatusCode(404)
264
                    ->respondWithError($response, $message, self::CODE_NOT_FOUND);
265
    }
266
267
    /**
268
     * Generates a Response with a 401 HTTP header and a given message.
269
     *
270
     * @param  \Symfony\Component\HttpFoundation\Response $response
271
     * @param  string                                     $message
272
     *
273
     * @return void
274
     */
275
    public function errorUnauthorized(Response $response, $message = 'Unauthorized')
276
    {
277
        return $this->setStatusCode(401)
278
                    ->respondWithError($response, $message, self::CODE_UNAUTHORIZED);
279
    }
280
281
    /**
282
     * Generates a Response with a 400 HTTP header and a given message.
283
     *
284
     * @param \Symfony\Component\HttpFoundation\Response $response
285
     * @param string                                     $message
286
     *
287
     * @return \Symfony\Component\HttpFoundation\Response
288
     */
289
    public function errorWrongArgs(Response $response, $message = 'Wrong Arguments')
290
    {
291
        return $this->setStatusCode(400)
292
                    ->respondWithError($response, $message, self::CODE_WRONG_ARGS);
293
    }
294
295
    /**
296
     * Reads any requested includes and adds them to the item / collection
297
     *
298
     * @param  Symfony\Component\HttpFoundation\Request $request
299
     *
300
     * @return void
301
     */
302
    public function getIncludesFromRequest(Request $request)
303
    {
304
        $queryString = $request->query->get('embed');
305
306
        if (! empty($queryString)) {
307
            $this->fractal->parseIncludes($request->query->get('embed'));
308
        }
309
    }
310
311
    /**
312
     * Gets the Server or Zone filters and runs a check to make sure the request validates. Also formats the list
313
     * correctly for inclusion in query strings.
314
     *
315
     * @param  string                                     $queryString
316
     * @param  string                                     $mode
317
     * @param  \Symfony\Component\HttpFoundation\Response $response
318
     *
319
     * @return string
320
     */
321
    public function getFiltersFromQueryString($queryString, $mode, $response)
0 ignored issues
show
Unused Code introduced by
The parameter $response is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
322
    {
323
        $filters = $this->getConfigItem($mode);
324
        $numericals = ['servers', 'zones'];
325
        $strings = ['factions', 'brackets'];
326
327
        if (! empty($queryString)) {
328
            $check = explode(',', $queryString);
329
330
            // Run a check on the IDs provided to make sure they're valid and no naughty things are being passed
331
            foreach ($check as $id) {
332
                // If the query string should contain only numbers
333
                if (in_array($mode, $numericals)) {
334
                    if (! is_numeric($id)) {
335
                        throw new InvalidArgumentException("Non numerical ID detected. Only numerical IDs are accepted with this request.");
336
                    }
337
                }
338
                if (in_array($mode, $strings)) {
339
                    if (is_numeric($id)) {
340
                        throw new InvalidArgumentException("Numerical input detected. Only string inputs are accepted with this request.");
341
                    }
342
                }
343
344
                if (! in_array($id, $filters)) {
345
                    throw new InvalidArgumentException("Unrecognized {$mode}. Please check the IDs you sent.");
346
                }
347
            }
348
349
            // Format into strings comma seperated for SQL
350
            if (in_array($mode, $strings)) {
351
                $queryString = "'" . implode("','", $check) . "'";
352
            }
353
354
            return $queryString;
355
        }
356
357
        $return = implode(',', $filters);
358
359
        if (in_array($mode, $strings)) {
360
            $return = "'" . implode("','", $filters) . "'";
361
        }
362
363
        // If no string was provided, returns all data encoded as a comma seperated string
364
        return $return;
365
    }
366
}
367