Completed
Pull Request — develop (#39)
by Abdelrahman
22:06 queued 19:57
created

UsersController::form()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 21
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 15
c 2
b 0
f 0
nc 16
nop 2
dl 0
loc 21
rs 8.7624
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cortex\Fort\Http\Controllers\Managerarea;
6
7
use Illuminate\Http\Request;
8
use Spatie\MediaLibrary\Models\Media;
9
use Rinvex\Fort\Contracts\UserContract;
10
use Illuminate\Foundation\Http\FormRequest;
11
use Cortex\Foundation\DataTables\LogsDataTable;
12
use Cortex\Foundation\DataTables\ActivitiesDataTable;
13
use Cortex\Fort\DataTables\Managerarea\UsersDataTable;
14
use Cortex\Fort\Http\Requests\Managerarea\UserFormRequest;
15
use Cortex\Foundation\Http\Controllers\AuthorizedController;
16
17
class UsersController extends AuthorizedController
18
{
19
    /**
20
     * {@inheritdoc}
21
     */
22
    protected $resource = 'users';
23
24
    /**
25
     * Display a listing of the resource.
26
     *
27
     * @param \Cortex\Fort\DataTables\Managerarea\UsersDataTable $usersDataTable
28
     *
29
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
30
     */
31
    public function index(UsersDataTable $usersDataTable)
32
    {
33
        return $usersDataTable->with([
34
            'id' => 'cortex-users',
35
            'phrase' => trans('cortex/fort::common.users'),
36
        ])->render('cortex/tenants::managerarea.pages.datatable');
37
    }
38
39
    /**
40
     * Get a listing of the resource logs.
41
     *
42
     * @param \Rinvex\Fort\Contracts\UserContract $user
43
     *
44
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
45
     */
46
    public function logs(UserContract $user)
47
    {
48
        return request()->ajax() && request()->wantsJson()
49
            ? app(LogsDataTable::class)->with(['resource' => $user])->ajax()
50
            : intend(['url' => route('adminarea.users.edit', ['user' => $user]).'#logs-tab']);
51
    }
52
53
    /**
54
     * Get a listing of the resource activities.
55
     *
56
     * @param \Rinvex\Fort\Contracts\UserContract $user
57
     *
58
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
59
     */
60
    public function activities(UserContract $user)
61
    {
62
        return request()->ajax() && request()->wantsJson()
63
            ? app(ActivitiesDataTable::class)->with(['resource' => $user])->ajax()
64
            : intend(['url' => route('adminarea.users.edit', ['user' => $user]).'#activities-tab']);
65
    }
66
67
    /**
68
     * Show the form for create/update of the given resource.
69
     *
70
     * @param \Illuminate\Http\Request            $request
71
     * @param \Rinvex\Fort\Contracts\UserContract $user
72
     *
73
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\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...
74
     */
75
    public function form(Request $request, UserContract $user)
76
    {
77
        $countries = countries();
78
        $authUser = $request->user($this->getGuard());
79
        $languages = collect(languages())->pluck('name', 'iso_639_1');
80
        $genders = ['m' => trans('cortex/fort::common.male'), 'f' => trans('cortex/fort::common.female')];
81
        $owner = optional(optional(config('rinvex.tenants.active'))->owner)->id;
0 ignored issues
show
Bug introduced by
The property id does not seem to exist in Illuminate\Support\Optional.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
82
83
        $roles = $authUser->isSuperadmin() || $authUser->id === $owner
84
            ? app('rinvex.fort.role')->all()->pluck('name', 'id')->toArray()
85
            : $authUser->roles->pluck('name', 'id')->toArray();
86
87
        $abilities = $authUser->isSuperadmin() || $authUser->id === $owner
88
            ? app('rinvex.fort.role')->forAllTenants()->where('slug', 'manager')->first()->abilities->groupBy('resource')->map->pluck('name', 'id')->toArray()
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 158 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
89
            : $authUser->allAbilities->groupBy('resource')->map->pluck('name', 'id')->toArray();
90
91
        $logs = app(LogsDataTable::class)->with(['id' => 'logs-table'])->html()->minifiedAjax(route('managerarea.users.logs', ['user' => $user]));
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 146 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
92
        $activities = app(ActivitiesDataTable::class)->with(['id' => 'activities-table'])->html()->minifiedAjax(route('managerarea.users.activities', ['user' => $user]));
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 170 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
93
94
        return view('cortex/fort::managerarea.pages.user', compact('user', 'abilities', 'roles', 'countries', 'languages', 'genders', 'logs', 'activities'));
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 157 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
95
    }
96
97
    /**
98
     * Store a newly created resource in storage.
99
     *
100
     * @param \Cortex\Fort\Http\Requests\Managerarea\UserFormRequest $request
101
     *
102
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Http\Redirec...inate\Http\JsonResponse?

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...
103
     */
104
    public function store(UserFormRequest $request)
105
    {
106
        return $this->process($request, app('rinvex.fort.user'));
107
    }
108
109
    /**
110
     * Update the given resource in storage.
111
     *
112
     * @param \Cortex\Fort\Http\Requests\Managerarea\UserFormRequest $request
113
     * @param \Rinvex\Fort\Contracts\UserContract                    $user
114
     *
115
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Http\Redirec...inate\Http\JsonResponse?

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...
116
     */
117
    public function update(UserFormRequest $request, UserContract $user)
118
    {
119
        return $this->process($request, $user);
120
    }
121
122
    /**
123
     * Process the form for store/update of the given resource.
124
     *
125
     * @param \Illuminate\Foundation\Http\FormRequest $request
126
     * @param \Rinvex\Fort\Contracts\UserContract     $user
127
     *
128
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Http\Redirec...inate\Http\JsonResponse?

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...
129
     */
130
    protected function process(FormRequest $request, UserContract $user)
131
    {
132
        // Prepare required input fields
133
        $data = $request->validated();
134
135
        ! $request->hasFile('profile_picture')
136
        || $user->addMediaFromRequest('profile_picture')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Rinvex\Fort\Contracts\UserContract as the method addMediaFromRequest() does only exist in the following implementations of said interface: Cortex\Fort\Models\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...
137
                ->sanitizingFileName(function ($fileName) {
138
                    return md5($fileName).'.'.pathinfo($fileName, PATHINFO_EXTENSION);
139
                })
140
                ->toMediaCollection('profile_picture', config('cortex.fort.media.disk'));
141
142
        ! $request->hasFile('cover_photo')
143
        || $user->addMediaFromRequest('cover_photo')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Rinvex\Fort\Contracts\UserContract as the method addMediaFromRequest() does only exist in the following implementations of said interface: Cortex\Fort\Models\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...
144
                ->sanitizingFileName(function ($fileName) {
145
                    return md5($fileName).'.'.pathinfo($fileName, PATHINFO_EXTENSION);
146
                })
147
                ->toMediaCollection('cover_photo', config('cortex.fort.media.disk'));
148
149
        // Save user
150
        $user->fill($data)->save();
151
152
        return intend([
153
            'url' => route('managerarea.users.index'),
154
            'with' => ['success' => trans('cortex/fort::messages.user.saved', ['username' => $user->username])],
0 ignored issues
show
Bug introduced by
Accessing username on the interface Rinvex\Fort\Contracts\UserContract 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...
155
        ]);
156
    }
157
158
    /**
159
     * Delete the given resource from storage.
160
     *
161
     * @param \Rinvex\Fort\Contracts\UserContract $user
162
     *
163
     * @return \Illuminate\Http\Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\Http\Redirec...inate\Http\JsonResponse?

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...
164
     */
165
    public function delete(UserContract $user)
166
    {
167
        $user->delete();
168
169
        return intend([
170
            'url' => route('managerarea.users.index'),
171
            'with' => ['warning' => trans('cortex/fort::messages.user.deleted', ['username' => $user->username])],
0 ignored issues
show
Bug introduced by
Accessing username on the interface Rinvex\Fort\Contracts\UserContract 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...
172
        ]);
173
    }
174
175
    /**
176
     * Delete the given resource from storage.
177
     *
178
     * @param \Rinvex\Fort\Contracts\UserContract $user
179
     * @param \Spatie\MediaLibrary\Models\Media   $media
180
     *
181
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
182
     */
183
    public function deleteMedia(UserContract $user, Media $media)
184
    {
185
        $user->media()->where('id', $media->id)->first()->delete();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Rinvex\Fort\Contracts\UserContract as the method media() does only exist in the following implementations of said interface: Cortex\Fort\Models\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...
186
187
        return intend([
188
            'url' => route('adminarea.users.edit', ['user' => $user]),
189
            'with' => ['warning' => trans('cortex/fort::messages.user.media_deleted')],
190
        ]);
191
    }
192
}
193