Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
41.46% covered (danger)
41.46%
34 / 82
16.67% covered (danger)
16.67%
3 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
BaseController
41.46% covered (danger)
41.46%
34 / 82
16.67% covered (danger)
16.67%
3 / 18
280.71
0.00% covered (danger)
0.00%
0 / 1
 sendResponse
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 sendError
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createUser
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 updateUserPassword
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
12
 getLoggedInUserId
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
 __validateJson
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 __validateContentTypeApplicationJson
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createPaginationFromOrm
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
3.04
 saltHash
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __validateSaltHash
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __dateMidnightZeroOne
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 __dateMidnightZeroZero
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 __dateElevenFiftyNine
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 __getAllDates
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 __validYYYYMMDDFormat
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 __validateDateTime
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 __validateAndExtractPaginationData
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
5.39
 __getMe
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Http\Controllers\api;
4
5use Illuminate\Http\Request;
6use Illuminate\Http\JsonResponse;
7use App\Http\Controllers\Controller as Controller;
8use Validator;
9use App\Models\User;
10use App\Models\Role;
11
12class BaseController extends Controller
13{
14    /**
15     * success response method.
16     *
17     * @param   Int   $status  The HTTP status code of the response, ie 200
18     * @param   Mixed $data    The data object to return under 'data'
19     * @param   Array $hateoas An array of HATEOAS data, optional
20     * @return  JsonResponse
21     */
22    public function sendResponse(int $status, $data, array $hateoas = array()):JsonResponse
23    {
24        $response = [
25            'data'      => $data,
26        ];
27
28        if (count($hateoas) > 0) {
29            $response['links'] = $hateoas;
30        }
31
32        return response()->json($response, $status);
33    } // sendResponse
34
35
36    /**
37     * return error response.
38     *
39     * @param  Int   $status
40     * @param  Mixed $error
41     * @param  Mixed $details
42     * @return JsonResponse
43     */
44    public function sendError(int $status, $error, $details=null):JsonResponse
45    {
46        $response = [
47            'error' => $error,
48            'details' => $details,
49        ];
50
51        return response()->json($response, $status);
52    } // sendError
53
54
55    /**
56     * Creates a login user of a given role
57     *
58     * @param Array $userData ["name", "email", "password", "c_password"]
59     * @param Int $roleId
60     * @return Int  The user id
61     */
62    protected function createUser(array $userData, Int $roleId = 2):Int
63    {
64        $userData['password'] =  bcrypt($userData['password']);
65
66        // did you run php artisan passport:install?
67        try {
68            $user = User::create($userData);
69            //$user->createToken('MyApp')->accessToken;
70            //$user->role_id = $roleId;
71            $user->save();
72            return $user->id;
73        }
74        // catch duplicate entry
75        catch (\Illuminate\Database\QueryException $e) {
76            return -1;
77        }
78    } // createUser
79
80
81    /**
82     * Updates the login password for a user. Used with putCustomersCorporateContact.
83     *
84     * @param string $password
85     * @return Boolean
86     */
87    protected function updateUserPassword(string $email, string $password)
88    {
89        $enc = bcrypt($password);
90
91        // did you run php artisan passport:install?
92        try {
93            /**
94             * Update user login account
95             */
96            $user = User::where('email', $email)->first();
97            if (!$user) {
98                return false;
99            }
100            $user->password = $enc;
101            $user->save();
102            return true;
103        }
104        // catch any errors
105        catch (\Illuminate\Database\QueryException $e) {
106            return false;
107        }
108    } // updateUserPassword
109
110
111    /**
112     * Tests if the role of the logged-in user is the same as the role passed as arg
113     *
114     * Modified: also returns true if the user is 'admin'
115     *
116     * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table.
117     *
118     * @param String $role  The role of the user, ie 'installer', 'lead_manager' or 'admin'
119     * @return bool
120     * @author gbh
121    protected function permissionsEqual(string $role):bool
122    {
123        $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0]; // @not-phpstan-ignore-line
124        $admin_id = Role::where('name', config('app.roles.admin'))->get()->pluck('id')[0]; // @not-phpstan-ignore-line
125        return (auth()->guard('api')->user()->role_id == $role_id || auth()->guard('api')->user()->role_id == $admin_id);
126    }
127     */
128
129
130    /**
131     * Tests if the role of the logged-in user is exactly the same as role arg, excluding admin.
132     *
133     * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table.
134     *
135     * @param String $role  The role of the user, ie 'installer', 'lead_manager' or 'admin'
136     * @return bool
137     * @author arn
138    protected function permissionsExactly(string $role):bool
139    {
140        $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0];  // @not-phpstan-ignore-line
141        return auth()->guard('api')->user()->role_id == $role_id;
142    }
143     */
144
145
146    /**
147     * Tests if the role of the logged-in user is the same or greater than the role passed as arg
148     *
149     * Roles are stored as env constants in .env where they are mapped to the name in the `roles` table.
150     *
151     * @param String $role  The role of the user, ie 'employee', 'support' or 'admin'
152     * @return bool
153     * @author gbh
154    protected function permissionsAtLeast(string $role)
155    {
156        $role_id = Role::where('name', config('app.roles.'.$role))->get()->pluck('id')[0];  // @not-phpstan-ignore-line
157        return (int)auth()->guard('api')->user()->role_id >= $role_id;
158    }
159     */
160
161    /**
162     * Get user id of logged-in user.
163     *
164     * @return Mixed    Int user_id or false
165     * @author arn
166     */
167    protected function getLoggedInUserId()
168    {
169        $currentUser = auth()->guard('api')->user();
170
171        /**
172         * If authenticated user is not found, do not authenticate.
173         */
174        if (!$currentUser) {
175            return false;
176        }
177
178        return $currentUser->id;
179    } // getLoggedInUserId
180
181
182    /**
183     * Validates a json string against a set of Laravel validation rules.
184     *
185     * @note Only flat json at this point
186     *
187     * @param Array $rules The Laravel validator ruleset to validate against
188     * @param Request $request The request object laravel injects into the controller
189     * @return mixed `boolean` true on success, `Array` on failure
190     */
191    protected function __validateJson(array $rules, Request $request)
192    {
193        $requestContent = $request->getContent();
194        $data = json_decode($requestContent, true);
195        $data = $data ? $data : [];
196        $validator = Validator::make($data, $rules);
197
198        if ($validator->passes()) {
199            return true;
200        } else {
201            $errors = $validator->errors();
202            $errorArray = [];
203            foreach ($errors->getMessages() as $key => $message) {
204                $errorArray[$key] = $message;
205            }
206            return $errorArray;
207        }
208    } //validateJson
209
210
211    /**
212     * Returns true if the header for Content-Type is 'application/json'
213     *
214     * @param   Request $request
215     * @return  bool
216     */
217    protected function __validateContentTypeApplicationJson(Request $request):bool
218    {
219        return strtolower($request->headers->get('Content-Type')) == "application/json";
220    } // validateContentTypeApplicationJson
221
222
223    /**
224     * Makes a nice hateoas array from LengthAwarePaginator collection
225     *
226     * @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginationCollection The return collection from Model::paginate()
227     * @return Array
228     */
229    protected function createPaginationFromOrm(\Illuminate\Contracts\Pagination\LengthAwarePaginator $paginationCollection)
230    {
231        $hateoas = [];
232        if ($paginationCollection->hasMorePages()) {
233            $hateoas['next_page'] = $paginationCollection->nextPageUrl().
234                                    "&size=".
235                                    $paginationCollection->count();
236        }
237        if ($paginationCollection->previousPageUrl()) {
238            $hateoas['previous_page'] = $paginationCollection->previousPageUrl().
239                                    "&size=".
240                                    $paginationCollection->count();
241        }
242        $hateoas['has_more'] = $paginationCollection->hasMorePages();
243        $hateoas['current_page'] = $paginationCollection->currentPage();
244        $hateoas['last_page'] = $paginationCollection->lastPage();
245        $hateoas['current_size'] = $paginationCollection->perPage();
246
247        return $hateoas;
248    } // createPaginationFromOrm
249
250
251    /**
252     * Hashes a value with our configured secret_salt
253     *
254     * @param   String $toHash The value to hash
255     * @return  String
256     */
257    protected function saltHash(String $toHash):String
258    {
259        return md5($toHash.config('app.secret_salt'));
260    } // saltHash
261
262
263    /**
264     * Tests if the hash $hash is valid for the value $value
265     *
266     * @param   String $value
267     * @param   String $hash
268     * @return  boolean
269     */
270    protected function __validateSaltHash(String $value, String $hash):bool
271    {
272        return md5($value.config('app.secret_salt')) == $hash;
273    } // validateSaltHash
274
275
276
277    /**
278     * Sets the time of a date string to midnight plus one second.
279     *
280     * eg. '2020-02-23 13:45:23' => '2020-02-23 00:00:01'
281     *
282     * @param   String  $date
283     * @return  String
284     */
285    protected function __dateMidnightZeroOne(String $date):String
286    {
287        $dateObj = new \DateTime($date);
288        $dateObj->setTime(00, 00, 01);
289        return $dateObj->format('Y-m-d H:i:s');
290    }
291
292    /**
293     * Sets the time of a date string to midnight
294     *
295     * eg. '2020-02-23 13:45:23' => '2020-02-23 00:00:00'
296     *
297     * @param   String  $date
298     * @return  String
299     */
300    protected function __dateMidnightZeroZero(String $date):String
301    {
302        $dateObj = new \DateTime($date);
303        $dateObj->setTime(00, 00, 00);
304        return $dateObj->format('Y-m-d H:i:s');
305    }
306
307
308    /**
309     * Sets the time of a date string to 11:59:59
310     *
311     * eg. '2020-02-23 13:45:23' => '2020-02-23 23:59:59'
312     *
313     * @param   String  $date
314     * @return  String
315     */
316    protected function __dateElevenFiftyNine(String $date):String
317    {
318        $dateObj = new \DateTime($date);
319        $dateObj->setTime(23, 59, 59);
320        return $dateObj->format('Y-m-d H:i:s');
321    }
322
323
324    /**
325     * Get an array of all dates as YYYY-MM-DD between start date and end date
326     *
327     * @param   String  $startdate
328     * @param   String  $enddate
329     * @return  Array
330     */
331    protected function __getAllDates(String $startdate, String $enddate):array
332    {
333        $begin      = new \DateTime($startdate);
334        $end        = new \DateTime($enddate);
335        $end        = $end->modify('+1 day');
336        $interval   = new \DateInterval('P1D');
337        $daterange  = new \DatePeriod($begin, $interval, $end);
338
339        $returnableDateRange = [];
340        foreach ($daterange as $d) {
341            $returnableDateRange[] = $d->format("Y-m-d");
342        }
343
344        return $returnableDateRange;
345    } // __getAllDates
346
347
348    /**
349     * Validates that a string is in yyyy-mm-dd format
350     *
351     * @param String $date The string to validate
352     * @return boolean
353     */
354    public function __validYYYYMMDDFormat($date):bool
355    {
356        $format = 'Y-m-d';
357        $d = \DateTime::createFromFormat($format, $date);
358        return $d && $d->format($format) == $date;
359    } // __validYYYYMMDDFormat
360
361
362   /**
363    * Validates that a string is in yyyy-mm-dd h:i:s format
364    */
365    public function __validateDateTime(String $date, String $format = 'Y-m-d H:i:s'):bool
366    {
367        $d = \DateTime::createFromFormat($format, $date);
368        return $d && $d->format($format) == $date;
369    } // __validateDateTime
370
371
372   /**
373    * Validate pagination query string in a request.
374    * This will return the object [ 'page' => A, 'size' => B ] on a valid request,
375    * or an error response on failure.
376    *
377    * @return Mixed
378    */
379    protected function __validateAndExtractPaginationData(Request $request):array
380    {
381        $page = $request->query('page') !== null ? (int)$request->query('page') : config('app.pagination.default_page_number');
382        $size = $request->query('size') !== null ? (int)$request->query('size') : config('app.pagination.default_page_size');
383
384        if ($page < 1) {
385            $page = 1;
386        }
387
388        if ($size < 1) {
389            $size = 1;
390        }
391
392        $request->page = $page;
393
394        return [
395            'page' => $page,
396            'size' => $size
397        ];
398    } // __validateAndExtractPaginationData
399
400
401    /**
402     * Selects and returns the current session user
403     *
404     * @return User
405     */
406    protected function __getMe():User
407    {
408        $user = User::whereMe()->first();
409        return $user;
410    }
411} // BaseController