Completed
Push — develop-3.0 ( 4fe777...24fc5d )
by Mohamed
09:15
created

IssueController::getEdit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 15
rs 9.4285
c 1
b 0
f 0
cc 2
eloc 9
nc 2
nop 3
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\Http\Controllers\Project;
13
14
use Illuminate\Http\Request;
15
use Illuminate\Http\Response;
16
use Tinyissue\Form\Comment as CommentForm;
17
use Tinyissue\Form\Issue as IssueForm;
18
use Tinyissue\Http\Controllers\Controller;
19
use Tinyissue\Http\Requests\FormRequest;
20
use Tinyissue\Model\Permission;
21
use Tinyissue\Model\Project\Issue;
22
use Tinyissue\Model\Project\Issue\Comment;
23
use Tinyissue\Model\Project;
24
use Tinyissue\Model\Project\Issue\Attachment;
25
use Tinyissue\Model\Tag;
26
27
28
/**
29
 * IssueController is the controller class for managing request related to projects issues.
30
 *
31
 * @author Mohamed Alsharaf <[email protected]>
32
 */
33
class IssueController extends Controller
34
{
35
    /**
36
     * Project issue index page (List project issues).
37
     *
38
     * @param Project $project
39
     * @param Issue   $issue
40
     * @param CommentForm       $form
41
     *
42
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
43
     */
44
    public function getIndex(Project $project, Issue $issue, CommentForm $form)
45
    {
46
        $canEdit           = $this->allows('update', $issue);
47
        $usersCanFixIssues = $canEdit && $issue->status == Issue::STATUS_OPEN ? $project->getUsersCanFixIssue() : [];
0 ignored issues
show
Documentation Bug introduced by
The method getUsersCanFixIssue does not exist on object<Tinyissue\Model\Project>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
48
49
        // Projects should be limited to issue-modify
50
        $projects = null;
51
        if ($canEdit) {
52
            $projects = $this->getLoggedUser()->getProjects();
0 ignored issues
show
Bug introduced by
The method getProjects() does not seem to exist on object<Tinyissue\Contracts\Model\UserInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
53
        }
54
55
        return view('project.issue.index', [
56
            'issue'               => $issue,
57
            'usersCanFixIssues'   => $usersCanFixIssues,
58
            'project'             => $project,
59
            'closed_issues_count' => $project->countClosedIssues($this->getLoggedUser()),
0 ignored issues
show
Bug introduced by
The method countClosedIssues() does not exist on Tinyissue\Model\Project. Did you maybe mean issues()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
60
            'open_issues_count'   => $project->countOpenIssues($this->getLoggedUser()),
0 ignored issues
show
Bug introduced by
The method countOpenIssues() does not exist on Tinyissue\Model\Project. Did you maybe mean issues()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
61
            'commentForm'         => $form,
62
            'sidebar'             => 'project',
63
            'projects'            => $projects,
64
        ]);
65
    }
66
67
    /**
68
     * Ajax: Assign new user to an issue.
69
     *
70
     * @param Issue $issue
71
     * @param Request         $request
72
     *
73
     * @return \Symfony\Component\HttpFoundation\Response
74
     */
75
    public function postAssign(Issue $issue, Request $request)
76
    {
77
        $response = [
78
            'status' => $issue->reassign((int) $request->input('user_id'), $this->getLoggedUser()),
0 ignored issues
show
Documentation Bug introduced by
The method reassign does not exist on object<Tinyissue\Model\Project\Issue>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
79
        ];
80
81
        return response()->json($response);
82
    }
83
84
    /**
85
     * Ajax: save comment.
86
     *
87
     * @param Comment $comment
88
     * @param Request           $request
89
     *
90
     * @return \Symfony\Component\HttpFoundation\Response
91
     */
92
    public function postEditComment(Comment $comment, Request $request)
93
    {
94
        $body = '';
95
        if ($request->has('body')) {
96
            $comment->updateBody((string) $request->input('body'), $this->getLoggedUser());
0 ignored issues
show
Documentation Bug introduced by
The method updateBody does not exist on object<Tinyissue\Model\Project\Issue\Comment>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
97
            $body = \Html::format($comment->comment);
98
        }
99
100
        return response()->json(['text' => $body]);
101
    }
102
103
    /**
104
     * To add new comment to an issue.
105
     *
106
     * @param Project   $project
107
     * @param Issue     $issue
108
     * @param Comment   $comment
109
     * @param FormRequest\Comment $request
110
     *
111
     * @return \Illuminate\Http\RedirectResponse
112
     */
113
    public function postAddComment(Project $project, Issue $issue, Comment $comment, FormRequest\Comment $request)
114
    {
115
        $comment->setRelations([
116
            'project' => $project,
117
            'issue'   => $issue,
118
            'user'    => $this->getLoggedUser(),
119
        ]);
120
        $comment->updater()->create($request->all());
121
122
        return redirect($issue->to() . '#comment' . $comment->id)->with('notice', trans('tinyissue.your_comment_added'));
123
    }
124
125
    /**
126
     * Ajax: to delete a comment.
127
     *
128
     * @param Comment $comment
129
     *
130
     * @return \Symfony\Component\HttpFoundation\Response
131
     */
132
    public function getDeleteComment(Comment $comment)
133
    {
134
        // TODO logged user need for the notifications
135
//        $comment->setRelation('user', $this->getLoggedUser());
136
        $comment->updater()->delete();
137
138
        return response()->json(['status' => true]);
139
    }
140
141
    /**
142
     * New issue form.
143
     *
144
     * @param Project $project
145
     * @param IssueForm         $form
146
     *
147
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
148
     */
149
    public function getNew(Project $project, IssueForm $form)
150
    {
151
        return view('project.issue.new', [
152
            'project' => $project,
153
            'form'    => $form,
154
            'sidebar' => 'project',
155
        ]);
156
    }
157
158
    /**
159
     * To create a new issue.
160
     *
161
     * @param Project $project
162
     * @param Issue   $issue
163
     * @param FormRequest\Issue $request
164
     *
165
     * @return \Illuminate\Http\RedirectResponse
166
     */
167
    public function postNew(Project $project, Issue $issue, FormRequest\Issue $request)
168
    {
169
        $issue->setRelations([
170
            'project' => $project,
171
            'user'    => $this->getLoggedUser(),
172
        ]);
173
        $issue->updater()->create($request->all());
174
175
        return redirect($issue->to())->with('notice', trans('tinyissue.issue_has_been_created'));
176
    }
177
178
    /**
179
     * Edit an existing issue form.
180
     *
181
     * @param Project $project
182
     * @param Issue   $issue
183
     * @param IssueForm         $form
184
     *
185
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
186
     */
187
    public function getEdit(Project $project, Issue $issue, IssueForm $form)
188
    {
189
        // Cannot edit closed issue
190
        if ($issue->status == Issue::STATUS_CLOSED) {
191
            return redirect($issue->to())
192
                ->with('notice', trans('tinyissue.cant_edit_closed_issue'));
193
        }
194
195
        return view('project.issue.edit', [
196
            'issue'   => $issue,
197
            'project' => $project,
198
            'form'    => $form,
199
            'sidebar' => 'project',
200
        ]);
201
    }
202
203
    /**
204
     * To update an existing issue details.
205
     *
206
     * @param Project $project
207
     * @param Issue   $issue
208
     * @param FormRequest\Issue $request
209
     *
210
     * @return \Illuminate\Http\RedirectResponse
211
     */
212
    public function postEdit(Project $project, Issue $issue, FormRequest\Issue $request)
213
    {
214
        // Delete the issue
215
        if ($request->has('delete-issue')) {
216
            $issue->updater()->delete();
217
218
            return redirect($project->to())->with('notice', trans('tinyissue.issue_has_been_deleted'));
219
        }
220
221
        $issue->setRelations([
222
            'project'   => $project,
223
            'updatedBy' => $this->getLoggedUser(),
224
        ]);
225
        $issue->updater()->update($request->all());
226
227
        return redirect($issue->to())
228
            ->with('notice', trans('tinyissue.issue_has_been_updated'));
229
    }
230
231
    /**
232
     * To close or reopen an issue.
233
     *
234
     * @param Project $project
235
     * @param Issue   $issue
236
     * @param int               $status
237
     *
238
     * @return \Illuminate\Http\RedirectResponse
239
     */
240
    public function getClose(Project $project, Issue $issue, $status = 0)
241
    {
242
        if ($status == 0) {
243
            $message = trans('tinyissue.issue_has_been_closed');
244
        } else {
245
            $message = trans('tinyissue.issue_has_been_reopened');
246
        }
247
248
        $issue->setRelation('project', $project);
249
        $issue->changeStatus($status, $this->getLoggedUser());
0 ignored issues
show
Documentation Bug introduced by
The method changeStatus does not exist on object<Tinyissue\Model\Project\Issue>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
250
251
        return redirect($issue->to())
252
            ->with('notice', $message);
253
    }
254
255
    /**
256
     * To upload an attachment file.
257
     *
258
     * @param Project    $project
259
     * @param Attachment $attachment
260
     * @param Request              $request
261
     *
262
     * @return \Symfony\Component\HttpFoundation\Response
263
     */
264
    public function postUploadAttachment(Project $project, Attachment $attachment, Request $request)
265
    {
266
        try {
267
            if (!$this->allows('create', $attachment)) {
268
                abort(404);
269
            }
270
271
            $attachment->upload($request->all(), $project, $this->getLoggedUser());
0 ignored issues
show
Documentation Bug introduced by
The method upload does not exist on object<Tinyissue\Model\Project\Issue\Attachment>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
272
273
            $response = [
274
                'upload' => [
275
                    [
276
                        'name'   => $attachment->filename,
277
                        'size'   => $attachment->filesize,
278
                        'fileId' => $attachment->id,
279
                    ],
280
                ],
281
            ];
282
        } catch (\Exception $exception) {
283
            $file = $request->file('upload');
284
285
            $response = [
286
                'status' => false,
287
                'name'   => $file->getClientOriginalName(),
288
                'error'  => $exception->getMessage(),
289
                'trace'  => $exception->getTraceAsString(),
290
            ];
291
        }
292
293
        return response()->json($response);
294
    }
295
296
    /**
297
     * Ajax: to remove an attachment file.
298
     *
299
     * @param Project    $project
300
     * @param Attachment $attachment
301
     * @param Request              $request
302
     *
303
     * @return \Symfony\Component\HttpFoundation\Response
304
     */
305
    public function postRemoveAttachment(Project $project, Attachment $attachment, Request $request)
306
    {
307
        $attachment->remove($request->all(), $project, $this->getLoggedUser());
0 ignored issues
show
Bug introduced by
The method remove() does not exist on Tinyissue\Model\Project\Issue\Attachment. Did you maybe mean removeObservableEvents()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
308
309
        return response()->json(['status' => true]);
310
    }
311
312
    /**
313
     * Delete attachment.
314
     *
315
     * @param Project    $project
316
     * @param Issue      $issue
317
     * @param Attachment $attachment
318
     *
319
     * @return \Illuminate\Http\RedirectResponse
320
     */
321 View Code Duplication
    public function getDeleteAttachment(Project $project, Issue $issue, Attachment $attachment)
1 ignored issue
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...
322
    {
323
        $issue->setRelation('project', $project);
324
        $attachment->setRelation('issue', $issue);
325
        $attachment->updater()->delete();
326
327
        return redirect($issue->to())->with('notice', trans('tinyissue.attachment_has_been_deleted'));
328
    }
329
330
    /**
331
     * Display an attachment file such as image.
332
     *
333
     * @param Project    $project
334
     * @param Issue      $issue
335
     * @param Attachment $attachment
336
     * @param Request              $request
337
     *
338
     * @return Response
339
     */
340
    public function getDisplayAttachment(Project $project, Issue $issue, Attachment $attachment, Request $request)
341
    {
342
        $issue->setRelation('project', $project);
343
        $attachment->setRelation('issue', $issue);
344
345
        $path    = config('tinyissue.uploads_dir') . '/' . $issue->project_id . '/' . $attachment->upload_token . '/' . $attachment->filename;
346
        $storage = \Storage::disk('local');
347
        $length  = $storage->size($path);
348
        $time    = $storage->lastModified($path);
349
        $type    = $storage->getDriver()->getMimetype($path);
350
351
        $response = new Response();
352
        $response->setEtag(md5($time . $path));
353
        $response->setExpires(new \DateTime('@' . ($time + 60)));
354
        $response->setLastModified(new \DateTime('@' . $time));
355
        $response->setPublic();
356
        $response->setStatusCode(200);
357
358
        $response->header('Content-Type', $type);
359
        $response->header('Content-Length', $length);
360
        $response->header('Content-Disposition', 'inline; filename="' . $attachment->filename . '"');
361
        $response->header('Cache-Control', 'must-revalidate');
362
363
        if ($response->isNotModified($request)) {
364
            // Return empty response if not modified
365
            return $response;
366
        }
367
368
        // Return file if first request / modified
369
        $response->setContent($storage->get($path));
370
371
        return $response;
372
    }
373
374
    /**
375
     * Download an attachment file.
376
     *
377
     * @param Project    $project
378
     * @param Issue      $issue
379
     * @param Attachment $attachment
380
     *
381
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
382
     */
383
    public function getDownloadAttachment(Project $project, Issue $issue, Attachment $attachment)
384
    {
385
        $issue->setRelation('project', $project);
386
        $attachment->setRelation('issue', $issue);
387
388
        $path = config('filesystems.disks.local.root') . '/' . config('tinyissue.uploads_dir') . '/' . $issue->project_id . '/' . $attachment->upload_token . '/' . $attachment->filename;
389
390
        return response()->download($path, $attachment->filename);
391
    }
392
393
    /**
394
     * Ajax: move an issue to another project.
395
     *
396
     * @param Issue   $issue
397
     * @param Request $request
398
     *
399
     * @return \Symfony\Component\HttpFoundation\Response
400
     */
401
    public function postChangeProject(Issue $issue, Request $request)
402
    {
403
        $issue->changeProject((int) $request->input('project_id'));
0 ignored issues
show
Bug introduced by
The method changeProject() does not exist on Tinyissue\Model\Project\Issue. Did you maybe mean project()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
404
405
        return response()->json(['status' => true, 'url' => $issue->to()]);
406
    }
407
408
    /**
409
     * Ajax: change status of an issue.
410
     *
411
     * @param Issue $issue
412
     * @param Request         $request
413
     *
414
     * @return \Symfony\Component\HttpFoundation\Response
415
     */
416
    public function postChangeKanbanTag(Issue $issue, Request $request)
417
    {
418
        $newTag = Tag::find((int) $request->input('newtag'));
419
        $oldTag = Tag::find((int) $request->input('oldtag'));
420
421
        $issue->changeKanbanTag($newTag, $oldTag);
0 ignored issues
show
Documentation Bug introduced by
The method changeKanbanTag does not exist on object<Tinyissue\Model\Project\Issue>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
422
423
        return response()->json(['status' => true, 'issue' => $issue->id]);
424
    }
425
426
    /**
427
     * Ajax: returns comments for an issue.
428
     *
429
     * @param Project $project
430
     * @param Issue   $issue
431
     *
432
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\Vie
433
     */
434 View Code Duplication
    public function getIssueComments(Project $project, Issue $issue)
1 ignored issue
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...
435
    {
436
        $issue->setRelation('project', $project);
437
        $activities = $issue->getCommentActivities();
0 ignored issues
show
Bug introduced by
The method getCommentActivities() does not exist on Tinyissue\Model\Project\Issue. Did you maybe mean activities()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
438
439
        return view('project.issue.partials.activities', [
440
            'no_data'     => trans('tinyissue.no_comments'),
441
            'activities' => $activities,
442
            'project'    => $project,
443
            'issue'      => $issue,
444
        ]);
445
    }
446
447
    /**
448
     * Ajax: returns activities for an issue excluding comments.
449
     *
450
     * @param Project $project
451
     * @param Issue   $issue
452
     *
453
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\Vie
454
     */
455 View Code Duplication
    public function getIssueActivity(Project $project, Issue $issue)
1 ignored issue
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...
456
    {
457
        $issue->setRelation('project', $project);
458
        $activities = $issue->getGeneralActivities();
0 ignored issues
show
Bug introduced by
The method getGeneralActivities() does not exist on Tinyissue\Model\Project\Issue. Did you maybe mean activities()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
459
460
        return view('project.issue.partials.activities', [
461
            'no_data'     => trans('tinyissue.no_activities'),
462
            'activities' => $activities,
463
            'project'    => $project,
464
            'issue'      => $issue,
465
        ]);
466
    }
467
}
468