Completed
Pull Request — master (#5)
by Josh
01:55
created

Controller::respondWithPaginatedCollection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 2
1
<?php
2
3
namespace NavJobs\Transmit;
4
5
use Illuminate\Support\Facades\Input;
6
use Illuminate\Database\Eloquent\Builder;
7
use NavJobs\Transmit\Traits\QueryHelperTrait;
8
use NavJobs\Transmit\Traits\ErrorResponsesTrait;
9
use Illuminate\Routing\Controller as BaseController;
10
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
11
12
abstract class Controller extends BaseController
13
{
14
    use QueryHelperTrait, ErrorResponsesTrait;
15
16
    protected $statusCode = 200;
17
    protected $resourceKey = null;
18
    protected $fractal, $transformer;
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
19
20
    public function __construct()
21
    {
22
        $this->fractal = app(Fractal::class);
23
24
        $this->parseIncludes();
25
    }
26
27
    /**
28
     * Sets the fractal transformer
29
     *
30
     * @param $transformer
31
     * @return mixed
32
     */
33
    public function setTransformer($transformer)
34
    {
35
        $this->transformer = $transformer;
36
37
        return $this;
38
    }
39
40
    /**
41
     * Sets resource key for fractal
42
     *
43
     * @param $resourceKey
44
     * @return mixed
45
     */
46
    public function setResourceKey($resourceKey)
47
    {
48
        $this->resourceKey = $resourceKey;
49
50
        return $this;
51
    }
52
53
    /**
54
     * Parses includes from either the header or query string.
55
     *
56
     * @return mixed
57
     */
58
    protected function parseIncludes()
59
    {
60
        if (Input::header('include')) {
61
            return $this->fractal->parseIncludes(Input::header('include'));
62
        }
63
64
        if (Input::get('include')) {
65
            return $this->fractal->parseIncludes(Input::get('include'));
66
        }
67
68
        return null;
69
    }
70
71
    /**
72
     * Returns the current status code.
73
     *
74
     * @return int
75
     */
76
    protected function getStatusCode()
77
    {
78
        return $this->statusCode;
79
    }
80
81
    /**
82
     * Sets the current status code.
83
     *
84
     * @param $statusCode
85
     * @return $this
86
     */
87
    protected function setStatusCode($statusCode)
88
    {
89
        $this->statusCode = $statusCode;
90
91
        return $this;
92
    }
93
94
    /**
95
     * Eager load any available includes and apply query parameters.
96
     *
97
     * @param $builder
98
     * @return mixed
99
     */
100
    protected function withIncludes($builder)
101
    {
102
        $includes = $this->transformer->getEagerLoads($this->fractal->getRequestedIncludes());
103
        $includedItems = $this->eagerLoadIncludes($builder, $includes);
104
        $this->applyParameters($includedItems, request()->query);
105
106
        return $builder;
107
    }
108
109
    /**
110
     * Returns a json response that contains the specified resource
111
     * passed through fractal and optionally a transformer.
112
     *
113
     * @param $item
114
     * @param null $callback
115
     * @return \Illuminate\Http\JsonResponse
116
     */
117 View Code Duplication
    protected function respondWithItem($item, $callback = null)
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...
118
    {
119
        if ($callback) {
120
            $builder = $this->withIncludes($item);
121
            $item = $callback($builder);
122
        }
123
124
        $rootScope = $this->fractal->item($item, $this->transformer, $this->resourceKey);
125
126
        return $this->respondWithArray($rootScope->toArray());
127
    }
128
129
    /**
130
     * Returns a json response that indicates the resource was successfully created also
131
     * returns the resource passed through fractal and optionally a transformer.
132
     *
133
     * @param $item
134
     * @param null $callback
135
     * @return \Illuminate\Http\JsonResponse
136
     */
137 View Code Duplication
    protected function respondWithItemCreated($item, $callback = null)
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...
138
    {
139
        if ($callback) {
140
            $builder = $this->withIncludes($item);
141
            $item = $callback($builder);
142
        }
143
144
        $this->setStatusCode(201);
145
        $rootScope = $this->fractal->item($item, $this->transformer, $this->resourceKey);
146
147
        return $this->respondWithArray($rootScope->toArray());
148
    }
149
150
    /**
151
     * Returns a json response that contains the specified collection
152
     * passed through fractal and optionally a transformer.
153
     *
154
     * @param $collection
155
     * @return \Illuminate\Http\JsonResponse
156
     */
157
    protected function respondWithCollection($collection)
158
    {
159
        if (is_a($collection, Builder::class)) {
160
            $collection = $this->withIncludes($collection);
161
        }
162
163
        $rootScope = $this->fractal->collection($collection, $this->transformer, $this->resourceKey);
164
165
        return $this->respondWithArray($rootScope->toArray());
166
    }
167
168
    /**
169
     * Returns a json response that contains the specified paginated collection
170
     * passed through fractal and optionally a transformer.
171
     *
172
     * @param $builder
173
     * @param int $perPage
174
     * @return \Illuminate\Http\JsonResponse
175
     */
176
    protected function respondWithPaginatedCollection($builder, $perPage = 10)
177
    {
178
        $builder = $this->withIncludes($builder);
179
180
        $paginator = $builder->paginate($perPage);
181
        $paginator->appends($this->getQueryParameters());
182
183
        $rootScope = $this->fractal
184
            ->collection($paginator->getCollection(), $this->transformer, $this->resourceKey)
185
            ->paginateWith(new IlluminatePaginatorAdapter($paginator));
186
187
        return $this->respondWithArray($rootScope->toArray());
188
    }
189
190
    /**
191
     * Returns an array of Query Parameters, not including pagination.
192
     *
193
     * @return array
194
     */
195
    protected function getQueryParameters()
0 ignored issues
show
Coding Style introduced by
getQueryParameters uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
196
    {
197
        return array_diff_key($_GET, array_flip(['page']));
198
    }
199
200
    /**
201
     * Returns a json response that contains the specified array,
202
     * the current status code and optional headers.
203
     *
204
     * @param array $array
205
     * @param array $headers
206
     * @return \Illuminate\Http\JsonResponse
207
     */
208
    protected function respondWithArray(array $array, array $headers = [])
209
    {
210
        return response()->json($array, $this->statusCode, $headers);
211
    }
212
213
    /**
214
     * Returns a response that indicates success but no content returned.
215
     *
216
     * @return \Illuminate\Http\Response
217
     */
218
    protected function respondWithNoContent()
219
    {
220
        return response()->make('', 204);
221
    }
222
}
223