SummaryController::index()   F
last analyzed

Complexity

Conditions 40
Paths > 20000

Size

Total Lines 204

Duplication

Lines 26
Ratio 12.75 %

Importance

Changes 0
Metric Value
dl 26
loc 204
rs 0
c 0
b 0
f 0
cc 40
nc 8643024
nop 1

How to fix   Long Method    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 Fabrica\Http\Api;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Event;
7
8
use Fabrica\Http\Requests;
9
use Fabrica\Http\Api\Controller;
10
11
use Sentinel;
12
use DB;
13
use Fabrica\Project\Provider;
14
15
class SummaryController extends Controller
16
{
17
    /**
18
     * get the top four filters info.
19
     *
20
     * @param  string $project_key
21
     * @return array
22
     */
23
    public function getTopFourFilters($project_key)
24
    {
25
        $filters = Provider::getIssueFilters($project_key, $this->user->id);
26
        $filters = array_slice($filters, 0, 4);
27
        foreach ($filters as $key => $filter)
28
        {
29
            $query = [];
30
            if (isset($filter['query']) && $filter['query']) {
31
                $query = $filter['query'];
32
            }
33
34
            $where = $this->getIssueQueryWhere($project_key, $query);
35
            $count = DB::collection('issue_' . $project_key)
36
                ->where($where)
37
                ->count();
38
39
            $filters[$key]['count'] = $count;
40
        }
41
42
        return $filters;
43
    }
44
45
    /**
46
     * get the past two week trend data.
47
     *
48
     * @param  string $project_key
49
     * @return \Illuminate\Http\Response
50
     */
51
    public function getPulseData($project_key)
52
    {
53
        // initialize the results
54
        $trend = [];
55
56
        // initialize the pulse data
57
        $t = strtotime('-2 week');
58
        while($t <= time())
59
        {
60
            $ymd = date('Y/m/d', $t);
61
            $trend[$ymd] = [ 'new' => 0, 'resolved' => 0, 'closed' => 0 ];
62
            $t += 24 * 3600;
63
        }
64
65
        $issues = DB::collection('issue_' . $project_key)
66
            ->where(
67
                function ($query) {
68
                    $twoWeeksAgo = strtotime(date('Ymd', strtotime('-2 week')));
69
                    $query->where('created_at', '>=', $twoWeeksAgo)
70
                        ->orWhere('resolved_at', '>=', $twoWeeksAgo)
71
                        ->orWhere('closed_at', '>=', $twoWeeksAgo);
72
                }
73
            )
74
            ->where('del_flg', '<>', 1)
75
            ->get([ 'created_at', 'resolved_at', 'closed_at' ]);
76
77
        foreach ($issues as $issue)
78
        {
79
            if (isset($issue['created_at']) && $issue['created_at']) {
80
                $created_date = date('Y/m/d', $issue['created_at']);
81
                if (isset($trend[$created_date])) {
82
                    $trend[$created_date]['new'] += 1;
83
                }
84
            }
85
86
            if (isset($issue['resolved_at']) && $issue['resolved_at']) {
87
                $resolved_date = date('Y/m/d', $issue['resolved_at']);
88
                if (isset($trend[$resolved_date])) {
89
                    $trend[$resolved_date]['resolved'] += 1;
90
                }
91
            }
92
            if (isset($issue['closed_at']) && $issue['closed_at']) {
93
                $closed_date = date('Y/m/d', $issue['closed_at']);
94
                if (isset($trend[$closed_date])) {
95
                    $trend[$closed_date]['closed'] += 1;
96
                }
97
            }
98
        }
99
100
        $new_trend = [];
101
        foreach ($trend as $key => $val)
102
        {
103
            $new_trend[] = [ 'day' => $key ] + $val;
104
        }
105
        return $new_trend;
106
    }
107
108
    /**
109
     * Display a listing of the resource.
110
     *
111
     * @return \Illuminate\Http\Response
112
     */
113
    public function index($project_key)
114
    {
115
        // the top four filters
116
        $filters = $this->getTopFourFilters($project_key);
117
        // the two weeks issuepulse
118
        $trend = $this->getPulseData($project_key);
119
120
        $types = Provider::getTypeList($project_key); 
121
        
122
        $optPriorities = [];
123
        $priorities = Provider::getPriorityList($project_key); 
124
        foreach ($priorities as $priority)
125
        {
126
            if (isset($priority['key'])) {
127
                $optPriorities[$priority['key']] = $priority['name'];
128
            }
129
            else
130
            {
131
                $optPriorities[$priority['_id']] = $priority['name'];
132
            }
133
        }
134
135
        $optModules = [];
136
        $modules = Provider::getModuleList($project_key);
137
        foreach ($modules as $module)
138
        {
139
            $optModules[$module->id] = $module->name;
140
        }
141
142
        //$users = Provider::getUserList($project_key); 
143
144
        $issues = DB::collection('issue_' . $project_key)
145
            ->where('created_at', '>=', strtotime(date('Ymd', strtotime('-1 week'))))
146
            ->where('del_flg', '<>', 1)
147
            ->get([ 'type' ]);
148
149
        $new_issues = [ 'total' => 0 ];
150 View Code Duplication
        foreach ($issues as $issue)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
151
        {
152
            if (!isset($new_issues[$issue['type']])) {
153
                $new_issues[$issue['type']] = 0;
154
            }
155
            $new_issues[$issue['type']] += 1;
156
            $new_issues['total'] += 1;
157
        }
158
159
        $issues = DB::collection('issue_' . $project_key)
160
            ->where('state', 'Closed')
161
            ->where('updated_at', '>=', strtotime(date('Ymd', strtotime('-1 week'))))
162
            ->where('del_flg', '<>', 1)
163
            ->get([ 'type' ]);
164
165
        $closed_issues = [ 'total' => 0 ];
166 View Code Duplication
        foreach ($issues as $issue)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
167
        {
168
            if (!isset($closed_issues[$issue['type']])) {
169
                $closed_issues[$issue['type']] = 0;
170
            }
171
            $closed_issues['total'] += 1;
172
            $closed_issues[$issue['type']] += 1;
173
        }
174
175
        $new_percent = $closed_percent = 0;
176
        if ($new_issues['total'] > 0 || $closed_issues['total'] > 0) {
177
            $new_percent = $new_issues['total'] * 100 / ($new_issues['total'] + $closed_issues['total']);
178
            if ($new_percent > 0 && $new_percent < 1) {
179
                $new_percent = 1;
180
            }
181
            else 
182
            {
183
                $new_percent = floor($new_percent);
184
            }
185
            $closed_percent = 100 - $new_percent;
186
        }
187
        
188
        $new_issues['percent'] = $new_percent;
189
        $closed_issues['percent'] = $closed_percent;
190
191
        $issues = DB::collection('issue_' . $project_key)
192
            ->where('resolution', 'Unresolved')
193
            ->where('del_flg', '<>', 1)
194
            ->get([ 'priority', 'assignee', 'type', 'module' ]);
195
196
        $users = [];
197
        $assignee_unresolved_issues = [];
198
        foreach ($issues as $issue)
199
        {
200
            if (!isset($issue['assignee']) || !$issue['assignee']) {
201
                continue;
202
            }
203
204
            $users[$issue['assignee']['id']] = $issue['assignee']['name'];
205 View Code Duplication
            if (!isset($assignee_unresolved_issues[$issue['assignee']['id']][$issue['type']])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
206
                $assignee_unresolved_issues[$issue['assignee']['id']][$issue['type']] = 0;
207
            }
208 View Code Duplication
            if (!isset($assignee_unresolved_issues[$issue['assignee']['id']]['total'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
209
                $assignee_unresolved_issues[$issue['assignee']['id']]['total'] = 0;
210
            }
211
            $assignee_unresolved_issues[$issue['assignee']['id']][$issue['type']] += 1;
212
            $assignee_unresolved_issues[$issue['assignee']['id']]['total'] += 1;
213
        }
214
        $assignee_unresolved_issues = $this->calPercent($assignee_unresolved_issues);
215
216
        $priority_unresolved_issues = [];
217
        foreach ($issues as $issue)
218
        {
219
            if (!isset($issue['priority']) || !$issue['priority']) {
220
                $priority_id = '-1';
221
            }
222
            else
223
            {
224
                $priority_id = isset($optPriorities[$issue['priority']]) ? $issue['priority'] : '-1'; 
225
            }
226
227
            if (!isset($priority_unresolved_issues[$priority_id][$issue['type']])) {
228
                $priority_unresolved_issues[$priority_id][$issue['type']] = 0;
229
            }
230
            if (!isset($priority_unresolved_issues[$priority_id]['total'])) {
231
                $priority_unresolved_issues[$priority_id]['total'] = 0;
232
            }
233
            $priority_unresolved_issues[$priority_id][$issue['type']] += 1;
234
            $priority_unresolved_issues[$priority_id]['total'] += 1;
235
        }
236
237
        $sorted_priority_unresolved_issues = [];
238
        foreach ($optPriorities as $key => $val)
239
        {
240
            if (isset($priority_unresolved_issues[$key])) {
241
                $sorted_priority_unresolved_issues[$key] = $priority_unresolved_issues[$key];
242
            }
243
        }
244
        if (isset($priority_unresolved_issues['-1'])) {
245
            $sorted_priority_unresolved_issues['-1'] = $priority_unresolved_issues['-1'];
246
        }
247
248
        $sorted_priority_unresolved_issues = $this->calPercent($sorted_priority_unresolved_issues);
249
250
        $module_unresolved_issues = [];
251
        foreach ($issues as $issue)
252
        {
253
            $module_ids = [];
254
            if (!isset($issue['module']) || !$issue['module']) {
255
                $module_ids = [ '-1' ];
256
            }
257
            else
258
            {
259
                $ms = is_string($issue['module']) ? explode(',', $issue['module']) : $issue['module'];
260
                foreach ($ms as $m)
261
                {
262
                    $module_ids[] = isset($optModules[$m]) ? $m : '-1';
263
                }
264
                $module_ids = array_unique($module_ids);
265
            }
266
267
            foreach ($module_ids as $module_id)
268
            {
269
                if (count($module_ids) > 1 && $module_id === '-1') {
270
                    continue;
271
                }
272
                if (!isset($module_unresolved_issues[$module_id][$issue['type']])) {
273
                    $module_unresolved_issues[$module_id][$issue['type']] = 0;
274
                }
275
                if (!isset($module_unresolved_issues[$module_id]['total'])) {
276
                    $module_unresolved_issues[$module_id]['total'] = 0;
277
                }
278
                $module_unresolved_issues[$module_id][$issue['type']] += 1;
279
                $module_unresolved_issues[$module_id]['total'] += 1;
280
            }
281
        }
282
283
        $sorted_module_unresolved_issues = [];
284
        foreach ($optModules as $key => $val)
285
        {   
286
            if (isset($module_unresolved_issues[$key])) {   
287
                $sorted_module_unresolved_issues[$key] = $module_unresolved_issues[$key];
288
            }
289
        }
290
        if (isset($module_unresolved_issues['-1'])) {
291
            $sorted_module_unresolved_issues['-1'] = $module_unresolved_issues['-1'];
292
        }
293
294
        $sorted_module_unresolved_issues = $this->calPercent($sorted_module_unresolved_issues);
295
296
        return response()->json(
0 ignored issues
show
Bug introduced by
The method json does only exist in Illuminate\Contracts\Routing\ResponseFactory, but not in Illuminate\Http\Response.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
297
            [ 
298
            'ecode' => 0, 
299
            'data' => [ 
300
                'filters' => $filters,
301
                'trend' => $trend,
302
                'new_issues' => $new_issues, 
303
                'closed_issues' => $closed_issues, 
304
                'assignee_unresolved_issues' => $assignee_unresolved_issues, 
305
                'priority_unresolved_issues' => $sorted_priority_unresolved_issues, 
306
                'module_unresolved_issues' => $sorted_module_unresolved_issues ], 
307
            'options' => [ 
308
                'types' => $types, 
309
                'users' => $users, 
310
                'priorities' => $optPriorities, 
311
                'modules' => $optModules, 
312
                'twoWeeksAgo' => date('m/d', strtotime('-2 week')) 
313
            ] 
314
            ]
315
        );
316
    }
317
318
    function calPercent($arr)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
319
    {
320
        $total = 0;
321
        $counts = [];
322
        $quotients = [];
323
        $remainders = [];
324
325
        foreach ($arr as $key => $val)
326
        {
327
            $counts[$key] = isset($val['total']) && $val['total'] ? $val['total'] : 0;
328
            $total += $counts[$key];
329
        }
330
331
        foreach ($counts as $key => $count)
332
        {
333
            $quotient = $count * 100 / $total;
334
            if ($quotient > 0 && $quotient <= 1) {
335
                $quotients[$key] = 1;
336
            }
337
            else
338
            {
339
                $quotients[$key] = floor($quotient);
340
            }
341
            $remainders[$key] = ($count * 100) % $total;
342
        }
343
344
        $sum = array_sum($quotients);
345
        if ($sum < 100) {
346
            $less = 100 - $sum;
347
            arsort($remainders);
348
349
            $i = 1;
350
            foreach ($remainders as $key => $remainder)
351
            {
352
                $quotients[$key] += 1;
353
                if ($i >= $less) {
354
                    break;
355
                }
356
                $i++;
357
            }
358
        }
359
360
        foreach ($arr as $key => $val)
361
        {
362
            $arr[$key]['percent'] = $quotients[$key];
363
        }
364
        return $arr;
365
    }
366
}
367