Completed
Push — develop ( 36b61b...31353a )
by Mohamed
10:45 queued 05:01
created

UserController::getIssues()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 5.667

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 27
ccs 5
cts 15
cp 0.3333
rs 8.8571
cc 3
eloc 17
nc 4
nop 2
crap 5.667
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;
13
14
use Illuminate\Database\Eloquent\Collection;
15
use Tinyissue\Form\UserSetting as Form;
16
use Tinyissue\Http\Requests\FormRequest;
17
use Tinyissue\Model\Project;
18
use Tinyissue\Model\Tag;
19
use Tinyissue\Model\User;
20
use Illuminate\Database\Eloquent\Relations\Relation;
21
22
/**
23
 * UserController is the controller class for managing request related to logged in user account
24
 *
25
 * @author Mohamed Alsharaf <[email protected]>
26
 */
27
class UserController extends Controller
28
{
29
    /**
30
     * Edit the user's settings
31
     *
32
     * @param Form $form
33
     *
34
     * @return \Illuminate\View\View
35
     */
36 3
    public function getSettings(Form $form)
37
    {
38 3
        return view('user.settings', [
0 ignored issues
show
Bug Compatibility introduced by
The expression view('user.settings', ar...)->projects()->get())); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 38 which is incompatible with the return type documented by Tinyissue\Http\Controlle...Controller::getSettings of type Illuminate\View\View.
Loading history...
39 3
            'form' => $form,
40 3
            '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...
41
        ]);
42
    }
43
44
    /**
45
     * To update user settings
46
     *
47
     * @param FormRequest\UserSetting $request
48
     *
49
     * @return \Illuminate\Http\RedirectResponse
50
     */
51 2
    public function postSettings(FormRequest\UserSetting $request)
52
    {
53 2
        $this->auth->user()->updateSetting($request->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 updateSetting() 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...
54
55 2
        return redirect('user/settings')->with('notice', trans('tinyissue.settings_updated'));
56
    }
57
58
    /**
59
     * Shows the user's assigned issues
60
     *
61
     * @param string $display
62
     * @param Project $project
63
     *
64
     * @return \Illuminate\View\View
65
     */
66 1
    public function getIssues($display = 'list', Project $project = null)
67
    {
68 1
        $view = $display === 'columns' ? 'columns' : 'list';
69
        $data = [
70 1
            'projects' => $this->auth->user()->projectsWidthIssues(Project::STATUS_OPEN)->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 projectsWidthIssues() 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...
71
        ];
72
73 1
        if ($display === 'columns') {
74
            $data['project'] = $project->find(1);
0 ignored issues
show
Documentation Bug introduced by
The method find 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...
75
            $data['columns'] = $data['project']->kanbanTags()->get();
76
            $ids = $data['columns']->lists('id')->all();
77
            $issues = $data['project']->issues()
78
                ->with('countComments', 'user', 'updatedBy', 'tags', 'tags.parent')
79
                ->with([
80
                    'tags' => function (Relation $query) use ($ids) {
81
                        $query->whereIn('id', $ids);
82
                    },
83
                ])
84
                ->orderBy('id')->get();
85
86
            $data['issues'] = $issues->groupBy(function (Project\Issue $issue) {
87
                return $issue->tags->last()->name;
0 ignored issues
show
Documentation introduced by
The property tags 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...
88
            });
89
        }
90
91 1
        return view('user.issues-' . $view, $data);
0 ignored issues
show
Bug Compatibility introduced by
The expression view('user.issues-' . $view, $data); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 91 which is incompatible with the return type documented by Tinyissue\Http\Controlle...erController::getIssues of type Illuminate\View\View.
Loading history...
92
    }
93
}
94