Issue::readOnlyMessage()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 16
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 9
nc 2
nop 0
crap 2
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
49
     */
50 9 View Code Duplication
    protected function getTags($type)
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...
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);
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();
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