Test Failed
Push — develop ( 8a31ce...8fcf9d )
by nguereza
02:43
created

EditAction::handle()   C

Complexity

Conditions 12
Paths 55

Size

Total Lines 130
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 82
nc 55
nop 1
dl 0
loc 130
rs 5.966
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Platine Framework
5
 *
6
 * Platine Framework is a lightweight, high-performance, simple and elegant
7
 * PHP Web framework
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Framework
12
 *
13
 * Permission is hereby granted, free of charge, to any person obtaining a copy
14
 * of this software and associated documentation files (the "Software"), to deal
15
 * in the Software without restriction, including without limitation the rights
16
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
 * copies of the Software, and to permit persons to whom the Software is
18
 * furnished to do so, subject to the following conditions:
19
 *
20
 * The above copyright notice and this permission notice shall be included in all
21
 * copies or substantial portions of the Software.
22
 *
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
 * SOFTWARE.
30
 */
31
32
/**
33
 *  @file EditAction.php
34
 *
35
 *  The Edit action class
36
 *
37
 *  @package    Platine\Framework\Demo\Action\User
38
 *  @author Platine Developers team
39
 *  @copyright  Copyright (c) 2020
40
 *  @license    http://opensource.org/licenses/MIT  MIT License
41
 *  @link   http://www.iacademy.cf
42
 *  @version 1.0.0
43
 *  @filesource
44
 */
45
46
declare(strict_types=1);
47
48
namespace Platine\Framework\Demo\Action\User;
49
50
use Platine\Framework\Auth\Entity\User;
51
use Platine\Framework\Auth\Repository\RoleRepository;
52
use Platine\Framework\Auth\Repository\UserRepository;
53
use Platine\Framework\Demo\Form\Param\UserParam;
54
use Platine\Framework\Demo\Form\Validator\UserValidator;
55
use Platine\Framework\Http\RequestData;
56
use Platine\Framework\Http\Response\RedirectResponse;
57
use Platine\Framework\Http\Response\TemplateResponse;
58
use Platine\Framework\Http\RouteHelper;
59
use Platine\Http\Handler\RequestHandlerInterface;
60
use Platine\Http\ResponseInterface;
61
use Platine\Http\ServerRequestInterface;
62
use Platine\Logger\LoggerInterface;
63
use Platine\Security\Hash\HashInterface;
64
use Platine\Session\Session;
65
use Platine\Stdlib\Helper\Str;
66
use Platine\Template\Template;
67
68
/**
69
 * @class EditAction
70
 * @package Platine\Framework\Demo\Action\User
71
 * @template T
72
 */
73
class EditAction implements RequestHandlerInterface
74
{
75
76
    /**
77
     * The logger instance
78
     * @var LoggerInterface
79
     */
80
    protected LoggerInterface $logger;
81
82
    /**
83
     * The session instance
84
     * @var Session
85
     */
86
    protected Session $session;
87
88
    /**
89
     * The user repository
90
     * @var UserRepository
91
     */
92
    protected UserRepository $userRepository;
93
94
    /**
95
     * The role repository
96
     * @var RoleRepository
97
     */
98
    protected RoleRepository $roleRepository;
99
100
    /**
101
     * The template instance
102
     * @var Template
103
     */
104
    protected Template $template;
105
106
    /**
107
     * The route helper instance
108
     * @var RouteHelper
109
     */
110
    protected RouteHelper $routeHelper;
111
112
     /**
113
     * The password hash to be used
114
     * @var HashInterface
115
     */
116
    protected HashInterface $hash;
117
118
    /**
119
     * Create new instance
120
     * @param LoggerInterface $logger
121
     * @param Session $session
122
     * @param Template $template
123
     * @param UserRepository $userRepository
124
     * @param RoleRepository $roleRepository
125
     * @param RouteHelper $routeHelper
126
     * @param HashInterface $hash
127
     */
128
    public function __construct(
129
        LoggerInterface $logger,
130
        Session $session,
131
        Template $template,
132
        UserRepository $userRepository,
133
        RoleRepository $roleRepository,
134
        RouteHelper $routeHelper,
135
        HashInterface $hash
136
    ) {
137
        $this->logger = $logger;
138
        $this->session = $session;
139
        $this->userRepository = $userRepository;
140
        $this->roleRepository = $roleRepository;
141
        $this->template = $template;
142
        $this->routeHelper = $routeHelper;
143
        $this->hash = $hash;
144
    }
145
146
    /**
147
     * {@inheritodc}
148
     */
149
    public function handle(ServerRequestInterface $request): ResponseInterface
150
    {
151
        $id = (int) $request->getAttribute('id');
152
153
        /** @var User $user */
154
        $user = $this->userRepository
155
                                    ->with('roles')
156
                                    ->find($id);
157
        if (!$user) {
0 ignored issues
show
introduced by
$user is of type Platine\Framework\Auth\Entity\User, thus it always evaluated to true.
Loading history...
158
            $this->session->setFlash('error', 'Can not find the user');
159
            $this->logger->warning('Can not find user with id {id}', ['id' => $id]);
160
161
            return new RedirectResponse(
162
                $this->routeHelper->generateUrl('user_list')
163
            );
164
        }
165
166
        $statusList = [
167
            '0' => 'Deactive',
168
            '1' => 'Active',
169
        ];
170
171
        $roles = $this->roleRepository->all();
172
173
        $currentRolesId = [];
174
        foreach ($user->roles as $entity) {
0 ignored issues
show
Bug Best Practice introduced by
The property roles does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __get, consider adding a @property annotation.
Loading history...
175
            $currentRolesId[] = $entity->id;
176
        }
177
178
        $entityToFormParam = (new UserParam())->fromEntity($user);
179
        $entityToFormParam->setRoles($currentRolesId);
180
181
        if ($request->getMethod() === 'GET') {
182
            return new TemplateResponse(
183
                $this->template,
184
                'user/edit',
185
                [
186
                    'param' => $entityToFormParam,
187
                    'status' => $statusList,
188
                    'roles' => $roles
189
                ]
190
            );
191
        }
192
193
        $param = new RequestData($request);
194
        $formParam = new UserParam($param->posts());
195
        $validator = new UserValidator($formParam);
196
197
        if (!$validator->validate()) {
198
            return new TemplateResponse(
199
                $this->template,
200
                'user/edit',
201
                [
202
                    'errors' => $validator->getErrors(),
203
                    'param' => $formParam,
204
                    'status' => $statusList,
205
                    'roles' => $roles
206
                ]
207
            );
208
        }
209
210
        $username = $param->post('username');
211
        $userExist = $this->userRepository->findBy(['username' => $username]);
212
213
        if ($userExist && $userExist->id != $id) {
214
            $this->session->setFlash('error', 'This user already exists');
215
            $this->logger->error('User with username {username} already exists', ['username' => $username]);
216
            return new TemplateResponse(
217
                $this->template,
218
                'user/edit',
219
                [
220
                   'param' => $formParam,
221
                   'status' => $statusList,
222
                   'roles' => $roles
223
                ]
224
            );
225
        }
226
227
        $password = $param->post('password');
228
229
        $user->username = $formParam->getUsername();
0 ignored issues
show
Bug Best Practice introduced by
The property username does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
230
        $user->firstname = Str::ucfirst($formParam->getFirstname());
0 ignored issues
show
Bug Best Practice introduced by
The property firstname does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
231
        $user->lastname = Str::upper($formParam->getLastname());
0 ignored issues
show
Bug Best Practice introduced by
The property lastname does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
232
        $user->role = $formParam->getRole();
0 ignored issues
show
Bug Best Practice introduced by
The property role does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
233
        $user->email = $formParam->getEmail();
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
234
        $user->status = (bool) $formParam->getStatus();
0 ignored issues
show
Bug Best Practice introduced by
The property status does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
235
        $user->updated_at = date('Y-m-d H::s');
0 ignored issues
show
Bug Best Practice introduced by
The property updated_at does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
236
237
        if (!empty($password)) {
238
            $passwordHash = $this->hash->hash($password);
239
            $user->password = $passwordHash;
0 ignored issues
show
Bug Best Practice introduced by
The property password does not exist on Platine\Framework\Auth\Entity\User. Since you implemented __set, consider adding a @property annotation.
Loading history...
240
        }
241
242
        //Handle roles
243
        $rolesId = $param->post('roles', []);
244
        $rolesIdToDelete = array_diff($currentRolesId, $rolesId);
245
        if (!empty($rolesIdToDelete)) {
246
            $deletedRoles = $this->roleRepository->findAll(...$rolesIdToDelete);
247
            $user->removeRoles($deletedRoles);
248
        }
249
        $newRolesId = array_diff($rolesId, $currentRolesId);
250
        if (!empty($newRolesId)) {
251
            $newRoles = $this->roleRepository->findAll(...$newRolesId);
252
            $user->setRoles($newRoles);
253
        }
254
        /////////////////
255
256
        $result = $this->userRepository->save($user);
257
258
        if (!$result) {
259
            $this->session->setFlash('error', 'Error when saved the user');
260
            $this->logger->error('Error when saved the user');
261
            return new TemplateResponse(
262
                $this->template,
263
                'user/edit',
264
                [
265
                   'param' => $formParam,
266
                   'status' => $statusList,
267
                   'roles' => $roles
268
                ]
269
            );
270
        }
271
272
        $this->session->setFlash('success', 'User saved successfully');
273
274
        $returnUrl = $this->routeHelper->generateUrl('user_list');
275
        if ($param->get('from_detail')) {
276
            $returnUrl = $this->routeHelper->generateUrl('user_detail', ['id' => $id]);
277
        }
278
        return new RedirectResponse($returnUrl);
279
    }
280
}
281