Completed
Push — develop ( d8ba64...7d836d )
by Mohamed
08:56
created

Issue::extractQuoteValue()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 15
c 0
b 0
f 0
ccs 8
cts 8
cp 1
rs 9.2
cc 4
eloc 8
nc 4
nop 1
crap 4
1
<?php
2
3
/*
4
 * This file is part of the Tinyissue package.
5
 *
6
 * (c) Mohamed Alsharaf <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tinyissue\Form;
13
14
use Illuminate\Support\Collection;
15
use Tinyissue\Model;
16
17
/**
18
 * Issue is a class to defines fields & rules for add/edit issue form.
19
 *
20
 * @author Mohamed Alsharaf <[email protected]>
21
 */
22
class Issue extends FormAbstract
23
{
24
    /**
25
     * An instance of project model.
26
     *
27
     * @var Model\Project
28
     */
29
    protected $project;
30
31
    /**
32
     * Collection of all tags.
33
     *
34
     * @var \Illuminate\Database\Eloquent\Collection
35
     */
36
    protected $tags = null;
37
38
    /**
39
     * Is issue readonly.
40
     *
41
     * @var bool
42
     */
43
    protected $readOnly = false;
44
45
    /**
46
     * @param string $type
47
     *
48
     * @return \Illuminate\Database\Eloquent\Collection|null
49
     */
50 9
    protected function getTags($type)
51
    {
52 9
        if ($this->tags === null) {
53 9
            $this->tags = (new Model\Tag())->getGroupTags();
54
        }
55
56 9
        return $this->tags->where('name', $type)->first()->tags;
57
    }
58
59
    /**
60
     * Returns an array of tags to be used as the selectable options.
61
     *
62
     * @param string $type
63
     *
64
     * @return array
65
     */
66 9
    protected function getSelectableTags($type = null)
67
    {
68 9
        $currentTag = $this->getIssueTag($type);
69
70 9
        if ($currentTag->id && (!$currentTag->canView() || $this->readOnly)) {
71 1
            $tags = [$currentTag];
72 9
        } elseif ($this->readOnly) {
73 1
            $tags = [];
74
        } else {
75 9
            $tags = $this->getTags($type);
76
        }
77
78 9
        return $this->generateTagRadioButtonOptions($tags, $type);
0 ignored issues
show
Bug introduced by
It seems like $tags defined by $this->getTags($type) on line 75 can also be of type null; however, Tinyissue\Form\Issue::ge...TagRadioButtonOptions() does only seem to accept object<Illuminate\Support\Collection>|array, 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...
79
    }
80
81
    /**
82
     * Get issue tag for specific type/group.
83
     *
84
     * @param string $type
85
     *
86
     * @return Model\Tag
87
     */
88 9
    protected function getIssueTag($type)
89
    {
90 9
        if ($this->isEditing()) {
91 4
            $groupId     = $this->getTags($type)->first()->parent_id;
92 4
            $selectedTag = $this->getModel()->tags->where('parent_id', $groupId);
93
94 4
            if ($selectedTag->count() > 0) {
95 1
                return $selectedTag->last();
96
            }
97
        }
98
99 9
        return new Model\Tag();
100
    }
101
102
    /**
103
     * @param array $params
104
     *
105
     * @return void
106
     */
107 8
    public function setup(array $params)
108
    {
109 8
        $this->project = $params['project'];
110 8
        if (!empty($params['issue'])) {
111 4
            $this->editingModel($params['issue']);
112 4
            $this->readOnly = $this->getModel()->hasReadOnlyTag($this->getLoggedUser());
113
        }
114 8
    }
115
116
    /**
117
     * @return array
118
     */
119 6
    public function actions()
120
    {
121 6
        $actions = [];
122
123
        // Check if issue is in readonly tag
124 6
        if (!$this->readOnly) {
125
            $actions = [
126 6
                'submit' => $this->isEditing() ? 'update_issue' : 'create_issue',
127
            ];
128
129 6
            if ($this->isEditing() && $this->getLoggedUser()->permission(Model\Permission::PERM_ISSUE_MODIFY)) {
130 2
                $actions['delete'] = [
131 2
                    'type'         => 'danger_submit',
132 2
                    'label'        => trans('tinyissue.delete_something', ['name' => '#' . $this->getModel()->id]),
133 2
                    'class'        => 'close-issue',
134 2
                    'name'         => 'delete-issue',
135 2
                    'data-message' => trans('tinyissue.delete_issue_confirm'),
136
                ];
137
            }
138
        }
139
140 6
        return $actions;
141
    }
142
143
    /**
144
     * @return array
145
     */
146 8
    public function fields()
147
    {
148 8
        $issueModify = $this->getLoggedUser()->permission('issue-modify');
149
150 8
        $fields = [];
151 8
        $fields += $this->readOnlyMessage();
152 8
        $fields += $this->fieldTitle();
153 8
        $fields += $this->fieldBody();
154 8
        $fields += $this->fieldTag('type');
155
156
        // Only on creating new issue
157 8
        if (!$this->isEditing()) {
158 5
            $fields += $this->fieldUpload();
159
        }
160
161
        // Show fields for users with issue modify permission
162 8
        if ($issueModify) {
163 8
            $fields += $this->issueModifyFields();
164
        }
165
166 8
        return $fields;
167
    }
168
169
    /**
170
     * Return a list of fields for users with issue modify permission.
171
     *
172
     * @return array
173
     */
174 8
    protected function issueModifyFields()
175
    {
176 8
        $fields = [];
177
178 8
        $fields['internal_status'] = [
179
            'type' => 'legend',
180
        ];
181
182
        // Status tags
183 8
        $fields += $this->fieldTag('status');
184
185
        // Assign users
186 8
        $fields += $this->fieldAssignedTo();
187
188
        // Quotes
189 8
        $fields += $this->fieldTimeQuote();
190
191
        // Resolution tags
192 8
        $fields += $this->fieldResolutionTags();
193
194 8
        return $fields;
195
    }
196
197
    /**
198
     * Returns message about read only issue.
199
     *
200
     * @return array
201
     */
202 8
    protected function readOnlyMessage()
203
    {
204 8
        $field = [];
205
206 8
        if ($this->readOnly) {
207
            $field = [
208
                'readonly' => [
209 1
                    'type'  => 'plaintext',
210 1
                    'label' => ' ',
211 1
                    'value' => '<div class="alert alert-warning">' . trans('tinyissue.readonly_issue_message') . '</div>',
212
                ],
213
            ];
214
        }
215
216 8
        return $field;
217
    }
218
219
    /**
220
     * Returns title field.
221
     *
222
     * @return array
223
     */
224 9
    protected function fieldTitle()
225
    {
226
        return [
227
            'title' => [
228
                'type'  => 'text',
229
                'label' => 'title',
230 9
            ],
231
        ];
232
    }
233
234
    /**
235
     * Returns body field.
236
     *
237
     * @return array
238
     */
239 9
    protected function fieldBody()
240
    {
241
        return [
242
            'body' => [
243
                'type'  => 'textarea',
244
                'label' => 'issue',
245 9
            ],
246
        ];
247
    }
248
249
    /**
250
     * Returns tag field.
251
     *
252
     * @param string $type
253
     * @param array  $prepend
254
     *
255
     * @return array
256
     */
257 9
    protected function fieldTag($type, array $prepend = [])
258
    {
259 9
        $options = $prepend + $this->getSelectableTags($type);
260 9
        $name    = 'tag_' . $type;
261
262
        return [
263
            $name => [
264 9
                'label'  => $type,
265 9
                'type'   => 'radioButton',
266 9
                'radios' => $options,
267 9
                'check'  => $this->getIssueTag($type)->id,
268
            ],
269
        ];
270
    }
271
272
    /**
273
     * Returns tags field.
274
     *
275
     * @return array
276
     */
277 8
    protected function fieldResolutionTags()
278
    {
279 8
        return $this->fieldTag('resolution', [
280 8
            trans('tinyissue.none') => [
281
                'name'      => 'tag_resolution',
282
                'value'     => 0,
283
                'data-tags' => 0,
284
                'color'     => '#62CFFC',
285 8
            ],
286
        ]);
287
    }
288
289
    /**
290
     * Returns assigned to field.
291
     *
292
     * @return array
293
     */
294 8
    protected function fieldAssignedTo()
295
    {
296
        return [
297
            'assigned_to' => [
298 8
                'type'    => 'select',
299 8
                'label'   => 'assigned_to',
300 8
                'options' => [0 => ''] + $this->project->usersCanFixIssue()->get()->lists('fullname', 'id')->all(),
301 8
                'value'   => (int) $this->project->default_assignee,
302
            ],
303
        ];
304
    }
305
306
    /**
307
     * Returns upload field.
308
     *
309
     * @return array
310
     */
311 6
    protected function fieldUpload()
312
    {
313 6
        $user                      = !$this->getLoggedUser() ? new Model\User() : $this->getLoggedUser();
314 6
        $fields                    = $this->projectUploadFields('upload', $this->project, $user);
315 6
        $fields['upload']['label'] = 'attachments';
316
317 6
        return $fields;
318
    }
319
320
    /**
321
     * Returns time quote field.
322
     *
323
     * @return array
324
     */
325 8
    protected function fieldTimeQuote()
326
    {
327
        $fields = [
328
            'time_quote' => [
329 8
                'type'     => 'groupField',
330 8
                'label'    => 'quote',
331
                'fields'   => [
332
                    'h'    => [
333 8
                        'type'          => 'number',
334 8
                        'append'        => trans('tinyissue.hours'),
335 8
                        'value'         => $this->extractQuoteValue('h'),
336 8
                        'addGroupClass' => 'col-sm-5 col-md-5 col-lg-4',
337
                    ],
338
                    'm'    => [
339 8
                        'type'          => 'number',
340 8
                        'append'        => trans('tinyissue.minutes'),
341 8
                        'value'         => $this->extractQuoteValue('m'),
342 8
                        'addGroupClass' => 'col-sm-5 col-md-5 col-lg-4',
343
                    ],
344
                    'lock' => [
345 8
                        'type'          => 'checkboxButton',
346 8
                        'label'         => '',
347
                        'noLabel'       => true,
348 8
                        'class'         => 'eee',
349 8
                        'addGroupClass' => 'sss col-sm-12 col-md-12 col-lg-4',
350
                        'checkboxes'    => [
351
                            'Lock Quote' => [
352 8
                                'value'     => 1,
353 8
                                'data-tags' => 1,
354 8
                                'color'     => 'red',
355 8
                                'checked'   => $this->isEditing() && $this->getModel()->isQuoteLocked(),
356
                            ],
357
                        ],
358
                        'grouped'       => true,
359
                    ],
360
                ],
361 8
                'addClass' => 'row issue-quote',
362 8
            ],
363
        ];
364
365
        // If user does not have access to lock quote, then remove the field
366 8
        if (!$this->getLoggedUser()->permission(Model\Permission::PERM_ISSUE_LOCK_QUOTE)) {
367 3
            unset($fields['time_quote']['fields']['lock']);
368
369
            // If quote is locked then remove quote fields
370 3
            if ($this->isEditing() && $this->getModel()->isQuoteLocked()) {
371 1
                return [];
372
            }
373
        }
374
375 8
        return $fields;
376
    }
377
378
    /**
379
     * @return array
380
     */
381 7
    public function rules()
382
    {
383
        $rules = [
384 7
            'title' => 'required|max:200',
385
            'body'  => 'required',
386
        ];
387
388 7
        return $rules;
389
    }
390
391
    /**
392
     * @return string
393
     */
394
    public function getRedirectUrl()
395
    {
396
        if ($this->isEditing()) {
397
            return $this->getModel()->to('edit');
398
        }
399
400
        return 'project/' . $this->project->id . '/issue/new';
401
    }
402
403
    /**
404
     * Extract number of hours, or minutes, or seconds from a quote.
405
     *
406
     * @param string $part
407
     *
408
     * @return float|int
409
     */
410 8
    protected function extractQuoteValue($part)
411
    {
412 8
        if ($this->getModel() instanceof Model\Project\Issue) {
413 4
            $seconds = $this->getModel()->time_quote;
414 4
            if ($part === 'h') {
415 4
                return floor($seconds / 3600);
416
            }
417
418 4
            if ($part === 'm') {
419 4
                return ($seconds / 60) % 60;
420
            }
421
        }
422
423 5
        return 0;
424
    }
425
426
    /**
427
     * Returns an array structured for radio button element.
428
     *
429
     * @param Collection|array $tags
430
     * @param string           $type
431
     *
432
     * @return array
433
     */
434 9
    protected function generateTagRadioButtonOptions($tags, $type)
435
    {
436 9
        $options = [];
437
438 9
        if (is_array($tags) || $tags instanceof Collection) {
439 9
            foreach ($tags as $tag) {
440 9
                $options[ucwords($tag->name)] = [
441 9
                    'name'      => 'tag_' . $type,
442 9
                    'value'     => $tag->id,
443 9
                    'data-tags' => $tag->id,
444 9
                    'color'     => $tag->bgcolor,
445
                ];
446
            }
447
        }
448
449 9
        return $options;
450
    }
451
}
452