Completed
Push — master ( 195b94...858be2 )
by Mohamed
07:34
created

IssueController::getEdit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 15
ccs 9
cts 9
cp 1
rs 9.4285
cc 2
eloc 9
nc 2
nop 3
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\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\Project;
21
use Tinyissue\Model\Project\Issue;
22
use Tinyissue\Model\Project\Issue\Attachment;
23
use Tinyissue\Model\Project\Issue\Comment;
24
use Tinyissue\Model\Tag;
25
use Tinyissue\Model\User\Activity as UserActivity;
26
27
/**
28
 * IssueController is the controller class for managing request related to projects issues.
29
 *
30
 * @author Mohamed Alsharaf <[email protected]>
31
 */
32
class IssueController extends Controller
33
{
34
    /**
35
     * Project issue index page (List project issues).
36
     *
37
     * @param Project     $project
38
     * @param Issue       $issue
39
     * @param CommentForm $form
40
     *
41
     * @return \Illuminate\View\View
42
     */
43 16
    public function getIndex(Project $project, Issue $issue, CommentForm $form)
44
    {
45
        // Projects should be limited to issue-modify
46 16
        $projects = null;
47 16
        if (!$this->auth->guest() && $this->auth->user()->permission('issue-modify')) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Illuminate\Contracts\Auth\Authenticatable as the method permission() does only exist in the following implementations of said interface: Tinyissue\Model\User.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
48 13
            $projects = $this->auth->user()->projects()->get();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Illuminate\Contracts\Auth\Authenticatable as the method projects() does only exist in the following implementations of said interface: Tinyissue\Model\User.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
49
        }
50
51 16
        return view('project.issue.index', [
0 ignored issues
show
Bug Compatibility introduced by
The expression view('project.issue.inde...ojects' => $projects)); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 51 which is incompatible with the return type documented by Tinyissue\Http\Controlle...sueController::getIndex of type Illuminate\View\View.
Loading history...
52 16
            'issue'       => $issue,
53 16
            'project'     => $project,
54 16
            'commentForm' => $form,
55 16
            'sidebar'     => 'project',
56 16
            'projects'    => $projects,
57
        ]);
58
    }
59
60
    /**
61
     * Ajax: Assign new user to an issue.
62
     *
63
     * @param Issue   $issue
64
     * @param Request $request
65
     *
66
     * @return \Symfony\Component\HttpFoundation\Response
67
     */
68 1 View Code Duplication
    public function postAssign(Issue $issue, Request $request)
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...
69
    {
70 1
        $response = ['status' => false];
71 1
        if ($issue->reassign((int) $request->input('user_id'), $this->auth->user()->id)) {
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
72 1
            $response['status'] = true;
73
        }
74
75 1
        return response()->json($response);
76
    }
77
78
    /**
79
     * Ajax: save comment.
80
     *
81
     * @param Comment $comment
82
     * @param Request $request
83
     *
84
     * @return \Symfony\Component\HttpFoundation\Response
85
     */
86 1
    public function postEditComment(Comment $comment, Request $request)
87
    {
88 1
        $body = '';
89 1
        if ($request->has('body')) {
90 1
            $comment->fill(['comment' => $request->input('body')])->save();
91 1
            $body = \Html::format($comment->comment);
92
        }
93
94 1
        return response()->json(['text' => $body]);
95
    }
96
97
    /**
98
     * To add new comment to an issue.
99
     *
100
     * @param Project             $project
101
     * @param Issue               $issue
102
     * @param Comment             $comment
103
     * @param FormRequest\Comment $request
104
     *
105
     * @return \Illuminate\Http\RedirectResponse
106
     */
107 4
    public function getAddComment(Project $project, Issue $issue, Comment $comment, FormRequest\Comment $request)
108
    {
109 4
        $comment->setRelation('project', $project);
110 4
        $comment->setRelation('issue', $issue);
111 4
        $comment->setRelation('user', $this->auth->user());
112 4
        $comment->createComment($request->all());
113
114 4
        return redirect($issue->to() . '#comment' . $comment->id)
115 4
            ->with('notice', trans('tinyissue.your_comment_added'));
116
    }
117
118
    /**
119
     * Ajax: to delete a comment.
120
     *
121
     * @param Comment $comment
122
     *
123
     * @return \Symfony\Component\HttpFoundation\Response
124
     */
125 1
    public function getDeleteComment(Comment $comment)
126
    {
127 1
        $comment->deleteComment();
128
129 1
        return response()->json(['status' => true]);
130
    }
131
132
    /**
133
     * New issue form.
134
     *
135
     * @param Project   $project
136
     * @param IssueForm $form
137
     *
138
     * @return \Illuminate\View\View
139
     */
140 5
    public function getNew(Project $project, IssueForm $form)
141
    {
142 5
        return view('project.issue.new', [
0 ignored issues
show
Bug Compatibility introduced by
The expression view('project.issue.new'...idebar' => 'project')); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 142 which is incompatible with the return type documented by Tinyissue\Http\Controlle...IssueController::getNew of type Illuminate\View\View.
Loading history...
143 5
            'project' => $project,
144 5
            'form'    => $form,
145 5
            'sidebar' => 'project',
146
        ]);
147
    }
148
149
    /**
150
     * To create a new issue.
151
     *
152
     * @param Project           $project
153
     * @param Issue             $issue
154
     * @param FormRequest\Issue $request
155
     *
156
     * @return \Illuminate\Http\RedirectResponse
157
     */
158 2 View Code Duplication
    public function postNew(Project $project, Issue $issue, FormRequest\Issue $request)
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...
159
    {
160 2
        $issue->setRelation('project', $project);
161 2
        $issue->setRelation('user', $this->auth->user());
162 2
        $issue->createIssue($request->all());
163
164 2
        return redirect($issue->to())
165 2
            ->with('notice', trans('tinyissue.issue_has_been_created'));
166
    }
167
168
    /**
169
     * Edit an existing issue form.
170
     *
171
     * @param Project   $project
172
     * @param Issue     $issue
173
     * @param IssueForm $form
174
     *
175
     * @return \Illuminate\View\View
176
     */
177 2
    public function getEdit(Project $project, Issue $issue, IssueForm $form)
178
    {
179
        // Cannot edit closed issue
180 2
        if ($issue->status == Issue::STATUS_CLOSED) {
181 1
            return redirect($issue->to())
0 ignored issues
show
Bug Best Practice introduced by
The return type of return redirect($issue->...t_edit_closed_issue')); (Illuminate\Http\RedirectResponse) is incompatible with the return type documented by Tinyissue\Http\Controlle...ssueController::getEdit of type Illuminate\View\View.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
182 1
                ->with('notice', trans('tinyissue.cant_edit_closed_issue'));
183
        }
184
185 2
        return view('project.issue.edit', [
0 ignored issues
show
Bug Compatibility introduced by
The expression view('project.issue.edit...idebar' => 'project')); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 185 which is incompatible with the return type documented by Tinyissue\Http\Controlle...ssueController::getEdit of type Illuminate\View\View.
Loading history...
186 2
            'issue'   => $issue,
187 2
            'project' => $project,
188 2
            'form'    => $form,
189 2
            'sidebar' => 'project',
190
        ]);
191
    }
192
193
    /**
194
     * To update an existing issue details.
195
     *
196
     * @param Project           $project
197
     * @param Issue             $issue
198
     * @param FormRequest\Issue $request
199
     *
200
     * @return \Illuminate\Http\RedirectResponse
201
     */
202 1 View Code Duplication
    public function postEdit(Project $project, Issue $issue, FormRequest\Issue $request)
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...
203
    {
204 1
        $issue->setRelation('project', $project);
205 1
        $issue->setRelation('updatedBy', $this->auth->user());
206 1
        $issue->updateIssue($request->all());
207
208 1
        return redirect($issue->to())
209 1
            ->with('notice', trans('tinyissue.issue_has_been_updated'));
210
    }
211
212
    /**
213
     * To close or reopen an issue.
214
     *
215
     * @param Project $project
216
     * @param Issue   $issue
217
     * @param int     $status
218
     *
219
     * @return \Illuminate\Http\RedirectResponse
220
     */
221 2
    public function getClose(Project $project, Issue $issue, $status = 0)
222
    {
223 2
        if ($status == 0) {
224 2
            $message = trans('tinyissue.issue_has_been_closed');
225
        } else {
226 1
            $message = trans('tinyissue.issue_has_been_reopened');
227
        }
228
229 2
        $issue->setRelation('project', $project);
230 2
        $issue->changeStatus($status, $this->auth->user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
231
232 2
        return redirect($issue->to())
233 2
            ->with('notice', $message);
234
    }
235
236
    /**
237
     * To upload an attachment file.
238
     *
239
     * @param Project    $project
240
     * @param Attachment $attachment
241
     * @param Request    $request
242
     *
243
     * @return \Symfony\Component\HttpFoundation\Response
244
     */
245 3
    public function postUploadAttachment(Project $project, Attachment $attachment, Request $request)
246
    {
247
        try {
248 3
            if (!$this->auth->user()->permission('project-all')) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Illuminate\Contracts\Auth\Authenticatable as the method permission() does only exist in the following implementations of said interface: Tinyissue\Model\User.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
249
                abort(404);
250
            }
251
252 3
            $attachment->upload($request->all(), $project, $this->auth->user());
0 ignored issues
show
Documentation introduced by
$this->auth->user() is of type object<Illuminate\Contra...h\Authenticatable>|null, but the function expects a object<Tinyissue\Model\User>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
253
254
            $response = [
255
                'upload' => [
256
                    [
257 3
                        'name'   => $attachment->filename,
258 3
                        'size'   => $attachment->filesize,
259 3
                        'fileId' => $attachment->id,
260
                    ],
261
                ],
262
            ];
263
        } catch (\Exception $exception) {
264
            $file = $request->file('upload');
265
266
            $response = [
267
                'status' => false,
268
                'name'   => $file->getClientOriginalName(),
269
                'error'  => $exception->getMessage(),
270
                'trace'  => $exception->getTraceAsString(),
271
            ];
272
        }
273
274 3
        return response()->json($response);
275
    }
276
277
    /**
278
     * Ajax: to remove an attachment file.
279
     *
280
     * @param Project    $project
281
     * @param Attachment $attachment
282
     * @param Request    $request
283
     *
284
     * @return \Symfony\Component\HttpFoundation\Response
285
     */
286 1
    public function postRemoveAttachment(Project $project, Attachment $attachment, Request $request)
287
    {
288 1
        $attachment->remove($request->all(), $project, $this->auth->user());
0 ignored issues
show
Documentation introduced by
$this->auth->user() is of type object<Illuminate\Contra...h\Authenticatable>|null, but the function expects a object<Tinyissue\Model\User>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
289
290 1
        return response()->json(['status' => true]);
291
    }
292
293
    /**
294
     * Display an attachment file such as image.
295
     *
296
     * @param Project    $project
297
     * @param Issue      $issue
298
     * @param Attachment $attachment
299
     * @param Request    $request
300
     *
301
     * @return Response
302
     */
303 2
    public function getDisplayAttachment(Project $project, Issue $issue, Attachment $attachment, Request $request)
304
    {
305 2
        $issue->setRelation('project', $project);
306 2
        $attachment->setRelation('issue', $issue);
307
308 2
        $path    = config('tinyissue.uploads_dir') . '/' . $issue->project_id . '/' . $attachment->upload_token . '/' . $attachment->filename;
309 2
        $storage = \Storage::disk('local');
310 2
        $length  = $storage->size($path);
311 2
        $time    = $storage->lastModified($path);
312 2
        $type    = $storage->getDriver()->getMimetype($path);
313
314 2
        $response = new Response();
315 2
        $response->setEtag(md5($time . $path));
316 2
        $response->setExpires(new \DateTime('@' . ($time + 60)));
317 2
        $response->setLastModified(new \DateTime('@' . $time));
318 2
        $response->setPublic();
319 2
        $response->setStatusCode(200);
320
321 2
        $response->header('Content-Type', $type);
322 2
        $response->header('Content-Length', $length);
323 2
        $response->header('Content-Disposition', 'inline; filename="' . $attachment->filename . '"');
324 2
        $response->header('Cache-Control', 'must-revalidate');
325
326 2
        if ($response->isNotModified($request)) {
327
            // Return empty response if not modified
328
            return $response;
329
        }
330
331
        // Return file if first request / modified
332 2
        $response->setContent($storage->get($path));
333
334 2
        return $response;
335
    }
336
337
    /**
338
     * Download an attachment file.
339
     *
340
     * @param Project    $project
341
     * @param Issue      $issue
342
     * @param Attachment $attachment
343
     *
344
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
345
     */
346 1
    public function getDownloadAttachment(Project $project, Issue $issue, Attachment $attachment)
347
    {
348 1
        $issue->setRelation('project', $project);
349 1
        $attachment->setRelation('issue', $issue);
350
351 1
        $path = config('filesystems.disks.local.root') . '/' . config('tinyissue.uploads_dir') . '/' . $issue->project_id . '/' . $attachment->upload_token . '/' . $attachment->filename;
352
353 1
        return response()->download($path, $attachment->filename);
354
    }
355
356
    /**
357
     * Ajax: move an issue to another project.
358
     *
359
     * @param Issue   $issue
360
     * @param Request $request
361
     *
362
     * @return \Symfony\Component\HttpFoundation\Response
363
     */
364 1
    public function postChangeProject(Issue $issue, Request $request)
365
    {
366 1
        $issue->changeProject($request->input('project_id'));
0 ignored issues
show
Documentation introduced by
$request->input('project_id') is of type string|array, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
367
368 1
        return response()->json(['status' => true, 'url' => $issue->to()]);
369
    }
370
371
    /**
372
     * Ajax: change status of an issue.
373
     *
374
     * @param Issue   $issue
375
     * @param Request $request
376
     *
377
     * @return \Symfony\Component\HttpFoundation\Response
378
     */
379
    public function postChangeKanbanTag(Issue $issue, Request $request)
380
    {
381
        $newTag = Tag::find((int) $request->input('newtag'));
382
        $oldTag = Tag::find((int) $request->input('oldtag'));
383
384
        $issue->changeKanbanTag($newTag, $oldTag);
385
386
        return response()->json(['status' => true, 'issue' => $issue->id]);
387
    }
388
389
    /**
390
     * Ajax: returns comments for an issue.
391
     *
392
     * @param Project $project
393
     * @param Issue   $issue
394
     *
395
     * @return \Symfony\Component\HttpFoundation\Response
396
     */
397 8
    public function getIssueComments(Project $project, Issue $issue)
398
    {
399
        $issue->attachments->each(function (Attachment $attachment) use ($issue) {
0 ignored issues
show
Documentation introduced by
The property attachments does not exist on object<Tinyissue\Model\Project\Issue>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
400
            $attachment->setRelation('issue', $issue);
401 8
        });
402 8
        $activities = $issue->commentActivities()->with('activity', 'user', 'comment', 'assignTo',
403 8
            'comment.attachments')->get();
404
        $activities->each(function (UserActivity $activity) use ($issue) {
405 8
            $activity->setRelation('issue', $issue);
406 8
        });
407
408 View Code Duplication
        $activityString = $activities->map(function (UserActivity $activity) use ($project, $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...
409 8
            return view('project/issue/activity/' . $activity->activity->activity, [
1 ignored issue
show
Documentation introduced by
The property activity does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

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...
410 8
                'issue'           => $issue,
411 8
                'userActivity'    => $activity,
412 8
                'project'         => $project,
413 8
                'user'            => $activity->user,
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
414 8
                'comment'         => $activity->comment,
0 ignored issues
show
Documentation introduced by
The property comment does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
415 8
                'assigned'        => $activity->assignTo,
0 ignored issues
show
Documentation introduced by
The property assignTo does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
416 8
            ])->render();
417 8
        })->implode('');
418
419 8
        if (empty($activityString)) {
420
            $activityString = '<li class="no-records">There are no comments yet on this issue.</li>';
421
        }
422
423 8
        return response()->json(['status' => true, 'activity' => $activityString]);
424
    }
425
426
    /**
427
     * Ajax: returns activities for an issue excluding comments.
428
     *
429
     * @param Project $project
430
     * @param Issue   $issue
431
     *
432
     * @return \Symfony\Component\HttpFoundation\Response
433
     */
434 1
    public function getIssueActivity(Project $project, Issue $issue)
435
    {
436 1
        $activities = $issue->generalActivities()->with('activity', 'user', 'assignTo')->get();
437
        $activities->each(function (UserActivity $activity) use ($issue) {
438 1
            $activity->setRelation('issue', $issue);
439 1
        });
440
441 1 View Code Duplication
        $activityString = $activities->map(function (UserActivity $activity) use ($project, $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...
442 1
            return view('project/issue/activity/' . $activity->activity->activity, [
1 ignored issue
show
Documentation introduced by
The property activity does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

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...
443 1
                'issue'           => $issue,
444 1
                'userActivity'    => $activity,
445 1
                'activity'        => $activity,
446 1
                'project'         => $project,
447 1
                'user'            => $activity->user,
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
448 1
                'comment'         => $activity->comment,
0 ignored issues
show
Documentation introduced by
The property comment does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
449 1
                'assigned'        => $activity->assignTo,
0 ignored issues
show
Documentation introduced by
The property assignTo does not exist on object<Tinyissue\Model\User\Activity>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
450 1
            ])->render();
451 1
        })->implode('');
452
453 1
        if (empty($activityString)) {
454
            $activityString = '<li class="no-records">There are no activity yet on this issue.</li>';
455
        }
456
457 1
        return response()->json(['status' => true, 'activity' => $activityString]);
458
    }
459
}
460