Completed
Push — master ( 7860e0...d3b4dd )
by Matthew
02:30 queued 24s
created

AbstractEndpointController   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 268
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 8
Bugs 2 Features 2
Metric Value
wmc 18
c 8
b 2
f 2
lcom 1
cbo 9
dl 0
loc 268
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getStatusCode() 0 4 1
A setStatusCode() 0 5 1
A errorWrongArgs() 0 5 1
A getIncludesFromRequest() 0 8 2
A respond() 0 13 3
A respondWithItem() 0 7 1
A respondWithCollection() 0 7 1
A respondWithArray() 0 9 1
A respondWithError() 0 18 2
A errorEmpty() 0 5 1
A errorForbidden() 0 5 1
A errorInternalError() 0 5 1
A errorNotFound() 0 5 1
A errorUnauthorized() 0 5 1
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\DatabaseAwareInterface;
8
use Ps2alerts\Api\Contract\DatabaseAwareTrait;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Response;
11
12
abstract class AbstractEndpointController implements
13
    DatabaseAwareInterface
14
{
15
    use DatabaseAwareTrait;
16
17
    /**
18
     * Contains the repository used for interfacing with the database
19
     *
20
     * @var \Ps2alerts\Api\Repository\AbstractEndpointRepository
21
     */
22
    protected $repository;
23
24
    /**
25
     * Stores the status code
26
     *
27
     * @var integer
28
     */
29
    protected $statusCode = 200;
30
31
    /**
32
     * Holds Fractal
33
     *
34
     * @var \League\Fractal\Manager
35
     */
36
    protected $fractal;
37
38
    /**
39
     * Holds the transformer we're going to use
40
     *
41
     * @var mixed|\Leage\Fractal\TransformerAbstract
42
     */
43
    protected $transformer;
44
45
    const CODE_WRONG_ARGS     = 'API-MALFORMED-REQUEST';
46
    const CODE_NOT_FOUND      = 'API-NOT-FOUND';
47
    const CODE_INTERNAL_ERROR = 'API-DOH';
48
    const CODE_UNAUTHORIZED   = 'API-UNAUTHORIZED';
49
    const CODE_FORBIDDEN      = 'API-DENIED';
50
    const CODE_EMPTY          = 'API-EMPTY';
51
52
    /**
53
     * Getter for statusCode
54
     *
55
     * @return int
56
     */
57
    public function getStatusCode()
58
    {
59
        return $this->statusCode;
60
    }
61
62
    /**
63
     * Setter for statusCode
64
     *
65
     * @param int $statusCode Value to set
66
     *
67
     * @return self
68
     */
69
    public function setStatusCode($statusCode)
70
    {
71
        $this->statusCode = $statusCode;
72
        return $this;
73
    }
74
75
    /**
76
     * Master function to split out appropiate calls
77
     *
78
     * @param  string                                     $kind     The kind of data we wish to return
79
     * @param  array                                      $data     The data itself
80
     * @param  \League\Fractal\TransformerAbstract        $callback The transformer class to call
81
     * @param  \Symfony\Component\HttpFoundation\Request  $request  The request itself
82
     * @param  \Symfony\Component\HttpFoundation\Response $response The response object to eventually call
83
     *
84
     * @return \Symfony\Component\HttpFoundation\Response
85
     */
86
    protected function respond($kind, $data, $callback, Request $request, Response $response)
87
    {
88
        // Detect what embeds we need
89
        $this->getIncludesFromRequest($request);
90
        switch ($kind) {
91
            case 'item':
92
                return $this->respondWithItem($data, $callback, $response);
93
            case 'collection':
94
                return $this->respondWithCollection($data, $callback, $response);
95
            default:
96
                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...
97
        }
98
    }
99
100
    /**
101
     * Builds an item response in Fractal then hands off to the responder
102
     *
103
     * @param  array                                      $item     The item to transform
104
     * @param  \League\Fractal\TransformerAbstract        $callback The Transformer to pass through to Fractal
105
     * @param  \Symfony\Component\HttpFoundation\Response $response The client's response
106
     *
107
     * @return array
108
     */
109
    protected function respondWithItem($item, $callback, Response $response)
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...
110
    {
111
        $resource = new Item($item, $callback);
112
        $rootScope = $this->fractal->createData($resource);
113
114
        return $this->respondWithArray($response, $rootScope->toArray());
115
    }
116
117
    /**
118
     * Builds a collection of items from Fractal then hands off to the responder
119
     *
120
     * @param  array                                      $collection The collection to transform
121
     * @param  \League\Fractal\TransformerAbstract        $callback   The Transformer to pass through to Fractal
122
     * @param  \Symfony\Component\HttpFoundation\Response $response   The client's response
123
     *
124
     * @return array
125
     */
126
    protected function respondWithCollection($collection, $callback, Response $response)
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...
127
    {
128
        $resource = new Collection($collection, $callback);
129
        $rootScope = $this->fractal->createData($resource);
130
131
        return $this->respondWithArray($response, $rootScope->toArray());
132
    }
133
134
    /**
135
     * The final step where the formatted array is now sent back as a response in JSON form
136
     *
137
     * @param  \Symfony\Component\HttpFoundation\Response $response
138
     * @param  array                                      $array
139
     *
140
     * @return \Symfony\Component\HttpFoundation\Response
141
     */
142
    protected function respondWithArray(Response $response, array $array)
143
    {
144
        $response->setStatusCode($this->getStatusCode());
145
        $response->setContent(json_encode($array));
146
        $response->headers->set('Content-Type', 'application/json');
147
148
        // This is the end of the road. FIRE ZE RESPONSE!
149
        return $response;
150
    }
151
152
    /**
153
     * Responds gracefully with an error.
154
     *
155
     * @param  \Symfony\Component\HttpFoundation\Response $response
156
     * @param  string                                     $message   Response message to put in the error
157
     * @param  int                                        $errorCode Error code to set
158
     *
159
     * @return array
160
     */
161
    protected function respondWithError(Response $response, $message, $errorCode)
162
    {
163
        if ($this->statusCode === 200) {
164
            trigger_error(
165
                "This Error code 200 should never be sent. Please report this to the developer.",
166
                E_USER_WARNING
167
            );
168
        }
169
170
        // Pass to responder
171
        return $this->respondWithArray($response, [
172
            'error' => [
173
                'code'      => $errorCode,
174
                'http_code' => $this->statusCode,
175
                'message'   => $message,
176
            ]
177
        ]);
178
    }
179
180
    /**
181
     * Generates a response with a 404 HTTP error and a given message.
182
     *
183
     * @param  \Symfony\Component\HttpFoundation\Response $response
184
     * @param  string                                     $message
185
     *
186
     * @return void
187
     */
188
    public function errorEmpty(Response $response, $message = 'No data / Empty')
189
    {
190
        return $this->setStatusCode(404)
191
                    ->respondWithError($response, $message, self::CODE_EMPTY);
192
    }
193
194
    /**
195
     * Generates a Response with a 403 HTTP header and a given message.
196
     *
197
     * @param  \Symfony\Component\HttpFoundation\Response $response
198
     * @param  string                                     $message
199
     *
200
     * @return void
201
     */
202
    public function errorForbidden(Response $response, $message = 'Forbidden')
203
    {
204
        return $this->setStatusCode(403)
205
                    ->respondWithError($response, $message, self::CODE_FORBIDDEN);
206
    }
207
208
    /**
209
     * Generates a Response with a 500 HTTP header and a given message.
210
     *
211
     * @param  \Symfony\Component\HttpFoundation\Response $response
212
     * @param  string                                     $message
213
     *
214
     * @return void
215
     */
216
    public function errorInternalError(Response $response, $message = 'Internal Error')
217
    {
218
        return $this->setStatusCode(500)
219
                    ->respondWithError($response, $message, self::CODE_INTERNAL_ERROR);
220
    }
221
222
    /**
223
     * Generates a Response with a 404 HTTP header and a given message.
224
     *
225
     * @param  \Symfony\Component\HttpFoundation\Response $response
226
     * @param  string                                     $message
227
     *
228
     * @return void
229
     */
230
    public function errorNotFound(Response $response, $message = 'Resource Not Found')
231
    {
232
        return $this->setStatusCode(404)
233
                    ->respondWithError($response, $message, self::CODE_NOT_FOUND);
234
    }
235
236
    /**
237
     * Generates a Response with a 401 HTTP header and a given message.
238
     *
239
     * @param  \Symfony\Component\HttpFoundation\Response $response
240
     * @param  string                                     $message
241
     *
242
     * @return void
243
     */
244
    public function errorUnauthorized(Response $response, $message = 'Unauthorized')
245
    {
246
        return $this->setStatusCode(401)
247
                    ->respondWithError($response, $message, self::CODE_UNAUTHORIZED);
248
    }
249
250
    /**
251
     * Generates a Response with a 400 HTTP header and a given message.
252
     *
253
     * @param \Symfony\Component\HttpFoundation\Response $response
254
     * @param string                                     $message
255
     *
256
     * @return \Symfony\Component\HttpFoundation\Response
257
     */
258
    public function errorWrongArgs(Response $response, $message = 'Wrong Arguments')
259
    {
260
        return $this->setStatusCode(400)
261
                    ->respondWithError($response, $message, self::CODE_WRONG_ARGS);
262
    }
263
264
    /**
265
     * Reads any requested includes and adds them to the item / collection
266
     *
267
     * @param  Symfony\Component\HttpFoundation\Request $request
268
     *
269
     * @return void
270
     */
271
    public function getIncludesFromRequest(Request $request)
272
    {
273
        $queryString = $request->query->get('embed');
274
275
        if (! empty($queryString)) {
276
            $this->fractal->parseIncludes($request->query->get('embed'));
277
        }
278
    }
279
}
280