Completed
Push — master ( 50c6ef...1b86f4 )
by Fèvre
03:12
created

UserController::show()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 21
nc 2
nop 2
1
<?php
2
namespace Xetaravel\Http\Controllers;
3
4
use Illuminate\Http\RedirectResponse;
5
use Illuminate\Http\Request;
6
use Illuminate\Support\Facades\Auth;
7
use Illuminate\Support\Facades\Hash;
8
use Illuminate\Support\Facades\Route;
9
use Illuminate\Support\Str;
10
use Illuminate\View\View;
11
use Xetaravel\Models\Repositories\UserRepository;
12
use Xetaravel\Models\User;
13
use Xetaravel\Models\Validators\UserValidator;
14
15
class UserController extends Controller
16
{
17
    /**
18
     * Constructor
19
     */
20
    public function __construct()
21
    {
22
        parent::__construct();
23
24
        $action = Route::getFacadeRoot()->current()->getActionMethod();
25
26
        if (in_array($action, ['index', 'show'])) {
27
            $this->breadcrumbs->addCrumb('Users', route('users.user.index'));
0 ignored issues
show
Bug introduced by
The property breadcrumbs does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
28
        }
29
    }
30
31
    /**
32
     * Show all the users.
33
     *
34
     * @return \Illuminate\View\View
35
     */
36
    public function index(): View
37
    {
38
        return view('user.index');
39
    }
40
41
    /**
42
     * Show the user profile page.
43
     *
44
     * @param string $slug The slug of the user.
45
     *
46
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
0 ignored issues
show
Documentation introduced by
Should the return type not be RedirectResponse|View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
47
     */
48
    public function show(Request $request, string $slug)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
49
    {
50
        $user = User::with('articles', 'comments')
0 ignored issues
show
Bug introduced by
The method where does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloquent\Model.

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...
51
            ->where('slug', Str::lower($slug))
52
            ->first();
53
54
        if (is_null($user)) {
55
            return redirect()
56
                ->route('page.index')
57
                ->with('danger', 'This user doesn\'t exist or has been deleted !');
58
        }
59
        $articles = $user->articles()
60
            ->latest()
61
            ->take(config('xetaravel.pagination.user.articles_profile_page'))
62
            ->get();
63
64
        $comments = $user->comments()
65
            ->latest()
66
            ->take(config('xetaravel.pagination.user.comments_profile_page'))
67
            ->get();
68
69
        $breadcrumbs = $this->breadcrumbs->addCrumb(
70
            e($user->username),
71
            $user->profile_url
72
        );
73
        $this->breadcrumbs->setCssClasses('breadcrumb');
74
75
        return view('user.show', compact('user', 'articles', 'comments', 'breadcrumbs'));
76
    }
77
78
    /**
79
     * Show the settings form.
80
     *
81
     * @return \Illuminate\View\View
82
     */
83
    public function showSettingsForm(): View
84
    {
85
        $this->breadcrumbs
86
            ->addCrumb('Settings', route('users.user.settings'))
87
            ->setCssClasses('breadcrumb');
88
89
        return view('user.settings', ['breadcrumbs' => $this->breadcrumbs]);
90
    }
91
92
    /**
93
     * Handle an update request for the user.
94
     *
95
     * @param \Illuminate\Http\Request $request
96
     *
97
     * @return \Illuminate\Http\RedirectResponse
98
     */
99
    public function update(Request $request): RedirectResponse
100
    {
101
        $type = $request->input('type');
102
103
        switch ($type) {
104
            case 'email':
105
                return $this->updateEmail($request);
106
107
            case 'password':
108
                return $this->updatePassword($request);
109
110
            default:
111
                return back()
112
                    ->withInput()
113
                    ->with('danger', 'Invalid type.');
114
        }
115
    }
116
117
    /**
118
     * Handle the delete request for the user.
119
     *
120
     * @param \Illuminate\Http\Request $request
121
     *
122
     * @return \Illuminate\Http\RedirectResponse
123
     */
124 View Code Duplication
    public function delete(Request $request): RedirectResponse
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...
125
    {
126
        $user = Auth::user();
127
128
        if (!Hash::check($request->input('password'), $user->password)) {
0 ignored issues
show
Bug introduced by
Accessing password 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...
129
            return redirect()
130
                ->route('users.user.settings')
131
                ->with('danger', 'Your Password does not match !');
132
        }
133
        Auth::logout();
134
135
        if ($user->delete()) {
136
            return redirect()
137
                ->route('page.index')
138
                ->with('success', 'Your Account has been deleted successfully !');
139
        }
140
141
        return redirect()
142
            ->route('page.index')
143
            ->with('danger', 'An error occurred while deleting your account !');
144
    }
145
146
    /**
147
     * Handle a E-mail update request for the user.
148
     *
149
     * @param \Illuminate\Http\Request $request
150
     *
151
     * @return \Illuminate\Http\RedirectResponse
152
     */
153
    protected function updateEmail(Request $request): RedirectResponse
154
    {
155
        UserValidator::updateEmail($request->all())->validate();
156
        UserRepository::updateEmail($request->all(), Auth::user());
0 ignored issues
show
Documentation introduced by
\Illuminate\Support\Facades\Auth::user() is of type object<Illuminate\Contra...h\Authenticatable>|null, but the function expects a object<Xetaravel\Models\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...
157
158
        return redirect()
159
            ->route('users.user.settings')
160
            ->with('success', 'Your E-mail has been updated successfully !');
161
    }
162
163
    /**
164
     * Handle a Password update request for the user.
165
     *
166
     * @param \Illuminate\Http\Request $request
167
     *
168
     * @return \Illuminate\Http\RedirectResponse
169
     */
170
    protected function updatePassword(Request $request): RedirectResponse
171
    {
172
        $user = Auth::user();
173
174
        if (!Hash::check($request->input('oldpassword'), $user->password)) {
0 ignored issues
show
Bug introduced by
Accessing password 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...
175
            return redirect()
176
                ->route('users.user.settings')
177
                ->with('danger', 'Your current Password does not match !');
178
        }
179
180
        UserValidator::updatePassword($request->all())->validate();
181
        UserRepository::updatePassword($request->all(), $user);
0 ignored issues
show
Compatibility introduced by
$user of type object<Illuminate\Contracts\Auth\Authenticatable> is not a sub-type of object<Xetaravel\Models\User>. It seems like you assume a concrete implementation of the interface Illuminate\Contracts\Auth\Authenticatable to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
182
183
        return redirect()
184
            ->route('users.user.settings')
185
            ->with('success', 'Your Password has been updated successfully !');
186
    }
187
}
188