TimelogController   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 327
Duplicated Lines 11.01 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 24.43%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 5
dl 36
loc 327
ccs 32
cts 131
cp 0.2443
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B index() 0 37 3
A startOfMonth() 0 6 2
A endOfMonth() 0 6 2
A dateRangeFormat() 0 15 4
A totalHours() 0 9 2
A setupDataTable() 0 17 1
A serverTime() 0 6 1
A attemptTimeIn() 18 18 2
A html() 0 13 2
A attemptTimeOut() 18 18 2
A timeIn() 0 17 1
B timeOut() 0 27 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the HRis Software package.
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * Licensed under the 3-clause BSD License.
9
 *
10
 * This source file is subject to the 3-clause BSD License that is
11
 * bundled with this package in the LICENSE file.
12
 *
13
 * @version    alpha
14
 *
15
 * @author     Bertrand Kintanar <[email protected]>
16
 * @license    BSD License (3-clause)
17
 * @copyright  (c) 2014-2016, b8 Studios, Ltd
18
 *
19
 * @link       http://github.com/HB-Co/HRis
20
 */
21
22
namespace HRis\Api\Controllers\Presence;
23
24
use Carbon\Carbon;
25
use Dingo\Api\Http\Request;
26
use Exception;
27
use HRis\Api\Repositories\Time\TimelogRepository;
28
use Irradiate\Api\Controllers\BaseController;
29
use Irradiate\Eloquent\Employee;
30
use Irradiate\Eloquent\Timelog;
31
use Symfony\Component\HttpFoundation\Response;
32
use Tymon\JWTAuth\Facades\JWTAuth;
33
34
class TimelogController extends BaseController
35
{
36
    /**
37
     * @var TimelogRepository
38
     */
39
    public $timelog;
40
41
    /**
42
     * @var Employee
43
     */
44
    public $employee;
45
46
    /**
47
     * @var int
48
     */
49
    public $rows_per_page = 10;
50
51
    /**
52
     * TimelogController constructor.
53
     *
54
     * @param Employee $employee
55
     */
56 6
    public function __construct(Employee $employee)
57
    {
58 6
        $this->timelog = new TimelogRepository();
59 6
        $this->employee = $employee;
60 6
    }
61
62
    /**
63
     * @param Request $request
64
     *
65
     * @return \Dingo\Api\Http\Response
66
     *
67
     * @author Bertrand Kintanar <[email protected]>
68
     */
69
    public function index(Request $request)
70
    {
71
        $query_params = $request->only('start', 'end', 'offset', 'employee_id');
72
        $query_params = array_filter($query_params);
73
74
        $query_params['offset'] = array_key_exists('offset', $query_params) ?: 0;
75
76
        $employee = $this->employee->whereEmployeeId($query_params['employee_id'])->first();
77
78
        $start = $this->startOfMonth($query_params);
79
        $end = $this->endOfMonth($query_params);
80
        $dateRange = $this->dateRangeFormat($start, $end);
81
        $timelogs = $this->timelog->range(
82
            $start->subMinutes($query_params['offset']),
0 ignored issues
show
Bug introduced by
It seems like $query_params['offset'] can also be of type boolean; however, Carbon\Carbon::subMinutes() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
83
            $end->subMinutes($query_params['offset']),
0 ignored issues
show
Bug introduced by
It seems like $query_params['offset'] can also be of type boolean; however, Carbon\Carbon::subMinutes() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
84
            $employee->id,
85
            $this->rows_per_page
86
        );
87
88
        foreach ($query_params as $key => $value) {
89
            $timelogs->appends($key, $value);
90
        }
91
92
        $data = [
93
            'timelogs'       => $timelogs,
94
            'date_range'     => $dateRange,
95
            'summary_report' => [
96
                'total_hours' => $this->totalHours($timelogs),
97
                'late'        => 0,
98
                'undertime'   => 0,
99
                'overtime'    => 0,
100
            ],
101
        ];
102
103
        return $this->responseAPI(Response::HTTP_OK, SUCCESS_RETRIEVE_MESSAGE,
104
            ['data' => $data, 'table' => $this->setupDataTable($timelogs)]);
105
    }
106
107
    /**
108
     * @param        $input
109
     * @param string $format
110
     *
111
     * @return static
112
     *
113
     * @author Bertrand Kintanar <[email protected]>
114
     */
115
    private function startOfMonth($input, $format = 'Y-m-d H:i:s')
116
    {
117
        return isset($input['start']) ?
118
            Carbon::createFromFormat($format, $input['start'].' 00:00:00') :
119
            Carbon::now()->startOfMonth();
120
    }
121
122
    /**
123
     * @param        $input
124
     * @param string $format
125
     *
126
     * @return static
127
     *
128
     * @author Bertrand Kintanar <[email protected]>
129
     */
130 4
    private function endOfMonth($input, $format = 'Y-m-d H:i:s')
131
    {
132
        return isset($input['end']) ?
133 4
            Carbon::createFromFormat($format, $input['end'].' 23:59:59') :
134
            Carbon::now()->endOfMonth();
135
    }
136
137
    /**
138
     * @param $start
139
     * @param $end
140
     *
141
     * @return string
142
     *
143
     * @author Bertrand Kintanar <[email protected]>
144
     */
145
    private function dateRangeFormat($start, $end)
146
    {
147
        if ($start->month == $end->month &&
148
            $start->day == 1 &&
149
            $end->day == $end->format('t')
150
        ) {
151
            $this->rows_per_page = cal_days_in_month(CAL_GREGORIAN, $start->month, $start->year);
152
153
            return $start->format('F Y');
154
        } else {
155
            $this->rows_per_page = $start->diffInDays($end);
156
157
            return $start->format('F d, Y').' - '.$end->format('F d, Y');
158
        }
159
    }
160
161
    /**
162
     * @param $timelogs
163
     *
164
     * @return int
165
     *
166
     * @author Bertrand Kintanar <[email protected]>
167
     */
168
    private function totalHours($timelogs)
169
    {
170
        $total = 0;
171
        foreach ($timelogs as $timelog) {
172
            $total += $timelog->rendered_hours;
173
        }
174
175
        return $total;
176
    }
177
178
    /**
179
     * Setup table for timelogs.
180
     *
181
     * @param $timelogs
182
     *
183
     * @return array
184
     *
185
     * @author Bertrand Kintanar <[email protected]>
186
     */
187
    protected function setupDataTable($timelogs)
188
    {
189
        $table = [];
190
191
        $table['div_size'] = 'col-md-9';
192
        $table['title'] = 'Timesheet';
193
        $table['permission'] = '';
194
        $table['headers'] = ['Date', 'Time In', 'Time Out', 'Hours'];
195
        $table['model'] = [
196
            'singular' => 'timelog',
197
            'plural'   => 'timelogs',
198
            'dashed'   => 'timelogs',
199
        ];
200
        $table['items'] = $timelogs;
201
202
        return $table;
203
    }
204
205
    /**
206
     * @return \Dingo\Api\Http\Response
207
     */
208
    public function serverTime()
209
    {
210
        $server = Carbon::now();
211
212
        return $this->responseAPI(Response::HTTP_OK, SUCCESS_RETRIEVE_MESSAGE, ['server' => $server]);
213
    }
214
215
    /**
216
     * Alert configuration of time in.
217
     *
218
     * @return string
219
     *
220
     * @author Harlequin Doyon <[email protected]>
221
     * @author Bertrand Kintanar <[email protected]>
222
     */
223 2 View Code Duplication
    public function attemptTimeIn()
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...
224
    {
225 2
        $note = '';
226
227 2
        if (!$this->timelog->hasNoLatestTimein($this->loggedEmployee())) {
228
            $note = "You have an active timelog that doesn't have a time out yet";
229
        }
230
231
        $data = [
232 2
            'title'              => 'Are you sure?',
233 2
            'html'               => $this->html('You want to time in!', $note),
234 2
            'showCancelButton'   => true,
235 2
            'confirmButtonColor' => '#DD6B55',
236 2
            'closeOnConfirm'     => false,
237 2
        ];
238
239 2
        return $this->responseAPI(Response::HTTP_OK, SUCCESS_RETRIEVE_MESSAGE, $data);
240
    }
241
242
    /**
243
     * Alert HTML helper.
244
     *
245
     * @param string $msg
246
     * @param string $note
247
     *
248
     * @return string
249
     *
250
     * @author Harlequin Doyon <[email protected]>
251
     * @author Bertrand Kintanar <[email protected]>
252
     */
253 2
    private function html($msg, $note = '')
254
    {
255 2
        $output = $msg;
256 2
        $output .= '<br>';
257
258 2
        if ($note !== '') {
259
            $output .= '<span style="font-size:12px" class="text-muted">';
260
            $output .= 'Note: '.$note;
261
            $output .= '</span>';
262
        }
263
264 2
        return $output;
265
    }
266
267
    /**
268
     * Alert configuration of time out.
269
     *
270
     * @return string
271
     *
272
     * @author Harlequin Doyon <[email protected]>
273
     * @author Bertrand Kintanar <[email protected]>
274
     */
275 View Code Duplication
    public function attemptTimeOut()
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...
276
    {
277
        $note = '';
278
279
        if (!$this->timelog->hasNoLatestTimeout($this->loggedEmployee())) {
280
            $note = "You don't have an active time in log";
281
        }
282
283
        $data = [
284
            'title'              => 'Are you sure?',
285
            'html'               => $this->html('You want to time out!', $note),
286
            'showCancelButton'   => true,
287
            'confirmButtonColor' => '#DD6B55',
288
            'closeOnConfirm'     => false,
289
        ];
290
291
        return $this->responseAPI(Response::HTTP_OK, SUCCESS_RETRIEVE_MESSAGE, $data);
292
    }
293
294
    /**
295
     * Save time in log in the database.
296
     *
297
     * @param Timelog $timelog
298
     *
299
     * @return \Dingo\Api\Http\Response
300
     *
301
     * @author Harlequin Doyon <[email protected]>
302
     * @author Bertrand Kintanar <[email protected]>
303
     */
304 2
    public function timeIn(Timelog $timelog)
0 ignored issues
show
Unused Code introduced by
The parameter $timelog 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...
305
    {
306 2
        $user = JWTAuth::parseToken()->authenticate();
307
308 2
        $timelog = Timelog::create([
309 2
            'employee_id' => $user->employee->id,
310 2
            'in'          => Carbon::now(),
311 2
        ]);
312
313
        $data = [
314 2
            'title'      => 'Punch In',
315 2
            'text'       => 'You have successfully submitted your timelog.',
316 2
            'timelog_id' => $timelog->id,
317 2
        ];
318
319 2
        return $this->responseAPI(Response::HTTP_CREATED, SUCCESS_ADD_MESSAGE, $data);
320
    }
321
322
    /**
323
     * Save time out log in the database.
324
     *
325
     * @param Timelog $timelog
326
     * @param Request $request
327
     *
328
     * @return \Dingo\Api\Http\Response
329
     *
330
     * @author Harlequin Doyon <[email protected]>
331
     * @author Bertrand Kintanar <[email protected]>
332
     */
333
    public function timeOut(Timelog $timelog, Request $request)
334
    {
335
        $id = $request->has('id') ? $request->get('id') : null;
336
        $user = JWTAuth::parseToken()->authenticate();
337
338
        try {
339
            if (is_null($id)) {
340
                $timelog->create([
341
                    'employee_id' => $user->employee->id,
342
                    'out'         => Carbon::now(),
343
                ]);
344
            } else {
345
                $t = $timelog->find($id);
346
                $t->out = Carbon::now();
347
                $t->save();
348
            }
349
        } catch (Exception $e) {
350
            abort(404, 'cannot_update_timelog');
351
        }
352
353
        $data = [
354
            'title' => 'Punch Out',
355
            'text'  => 'You have successfully submitted your timelog.',
356
        ];
357
358
        return $this->responseAPI(Response::HTTP_CREATED, SUCCESS_ADD_MESSAGE, $data);
359
    }
360
}
361