1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace ZfcUser\Controller; |
4
|
|
|
|
5
|
|
|
use Zend\Form\FormInterface; |
6
|
|
|
use Zend\Mvc\Controller\AbstractActionController; |
7
|
|
|
use Zend\ServiceManager\ServiceLocatorInterface; |
8
|
|
|
use Zend\Stdlib\ResponseInterface as Response; |
9
|
|
|
use Zend\Stdlib\Parameters; |
10
|
|
|
use Zend\View\Model\ViewModel; |
11
|
|
|
use ZfcUser\Service\User as UserService; |
12
|
|
|
use ZfcUser\Options\UserControllerOptionsInterface; |
13
|
|
|
|
14
|
|
|
class UserController extends AbstractActionController |
15
|
|
|
{ |
16
|
|
|
const ROUTE_CHANGEPASSWD = 'zfcuser/changepassword'; |
17
|
|
|
const ROUTE_LOGIN = 'zfcuser/login'; |
18
|
|
|
const ROUTE_REGISTER = 'zfcuser/register'; |
19
|
|
|
const ROUTE_CHANGEEMAIL = 'zfcuser/changeemail'; |
20
|
|
|
|
21
|
|
|
const CONTROLLER_NAME = 'zfcuser'; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @var UserService |
25
|
|
|
*/ |
26
|
|
|
protected $userService; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var FormInterface |
30
|
|
|
*/ |
31
|
|
|
protected $loginForm; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var FormInterface |
35
|
|
|
*/ |
36
|
|
|
protected $registerForm; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var FormInterface |
40
|
|
|
*/ |
41
|
|
|
protected $changePasswordForm; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var FormInterface |
45
|
|
|
*/ |
46
|
|
|
protected $changeEmailForm; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @todo Make this dynamic / translation-friendly |
50
|
|
|
* @var string |
51
|
|
|
*/ |
52
|
|
|
protected $failedLoginMessage = 'Authentication failed. Please try again.'; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @var UserControllerOptionsInterface |
56
|
|
|
*/ |
57
|
|
|
protected $options; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @var callable $redirectCallback |
61
|
|
|
*/ |
62
|
|
|
protected $redirectCallback; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @var ServiceLocatorInterface |
66
|
|
|
*/ |
67
|
|
|
protected $serviceLocator; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @param callable $redirectCallback |
71
|
|
|
*/ |
72
|
|
|
public function __construct($redirectCallback) |
73
|
|
|
{ |
74
|
|
|
if (!is_callable($redirectCallback)) { |
75
|
|
|
throw new \InvalidArgumentException('You must supply a callable redirectCallback'); |
76
|
|
|
} |
77
|
|
|
$this->redirectCallback = $redirectCallback; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* User page |
82
|
|
|
*/ |
83
|
|
|
public function indexAction() |
84
|
|
|
{ |
85
|
|
|
if (!$this->zfcUserAuthentication()->hasIdentity()) { |
86
|
|
|
return $this->redirect()->toRoute(static::ROUTE_LOGIN); |
87
|
|
|
} |
88
|
|
|
return new ViewModel(); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Login form |
93
|
|
|
*/ |
94
|
|
|
public function loginAction() |
95
|
|
|
{ |
96
|
|
|
if ($this->zfcUserAuthentication()->hasIdentity()) { |
97
|
|
|
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute()); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$request = $this->getRequest(); |
101
|
|
|
$form = $this->getLoginForm(); |
102
|
|
|
|
103
|
|
|
if ($this->getOptions()->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) { |
104
|
|
|
$redirect = $request->getQuery()->get('redirect'); |
105
|
|
|
} else { |
106
|
|
|
$redirect = false; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
if (!$request->isPost()) { |
110
|
|
|
return array( |
111
|
|
|
'loginForm' => $form, |
112
|
|
|
'redirect' => $redirect, |
113
|
|
|
'enableRegistration' => $this->getOptions()->getEnableRegistration(), |
114
|
|
|
); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$form->setData($request->getPost()); |
118
|
|
|
|
119
|
|
|
if (!$form->isValid()) { |
120
|
|
|
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage); |
121
|
|
|
return $this->redirect()->toUrl($this->url()->fromRoute(static::ROUTE_LOGIN).($redirect ? '?redirect='. rawurlencode($redirect) : '')); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
// clear adapters |
125
|
|
|
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters(); |
126
|
|
|
$this->zfcUserAuthentication()->getAuthService()->clearIdentity(); |
127
|
|
|
|
128
|
|
|
return $this->forward()->dispatch(static::CONTROLLER_NAME, array('action' => 'authenticate')); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Logout and clear the identity |
133
|
|
|
*/ |
134
|
|
|
public function logoutAction() |
135
|
|
|
{ |
136
|
|
|
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters(); |
137
|
|
|
$this->zfcUserAuthentication()->getAuthAdapter()->logoutAdapters(); |
138
|
|
|
$this->zfcUserAuthentication()->getAuthService()->clearIdentity(); |
139
|
|
|
|
140
|
|
|
$redirect = $this->redirectCallback; |
141
|
|
|
|
142
|
|
|
return $redirect(); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* General-purpose authentication action |
147
|
|
|
*/ |
148
|
|
|
public function authenticateAction() |
149
|
|
|
{ |
150
|
|
|
if ($this->zfcUserAuthentication()->hasIdentity()) { |
151
|
|
|
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute()); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
$adapter = $this->zfcUserAuthentication()->getAuthAdapter(); |
155
|
|
|
$redirect = $this->params()->fromPost('redirect', $this->params()->fromQuery('redirect', false)); |
156
|
|
|
|
157
|
|
|
$result = $adapter->prepareForAuthentication($this->getRequest()); |
158
|
|
|
|
159
|
|
|
// Return early if an adapter returned a response |
160
|
|
|
if ($result instanceof Response) { |
161
|
|
|
return $result; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$auth = $this->zfcUserAuthentication()->getAuthService()->authenticate($adapter); |
165
|
|
|
|
166
|
|
|
if (!$auth->isValid()) { |
167
|
|
|
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage); |
168
|
|
|
$adapter->resetAdapters(); |
169
|
|
|
return $this->redirect()->toUrl( |
170
|
|
|
$this->url()->fromRoute(static::ROUTE_LOGIN) . |
171
|
|
|
($redirect ? '?redirect='. rawurlencode($redirect) : '') |
172
|
|
|
); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
$redirect = $this->redirectCallback; |
176
|
|
|
|
177
|
|
|
return $redirect(); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Register new user |
182
|
|
|
*/ |
183
|
|
|
public function registerAction() |
184
|
|
|
{ |
185
|
|
|
// if the user is logged in, we don't need to register |
186
|
|
|
if ($this->zfcUserAuthentication()->hasIdentity()) { |
187
|
|
|
// redirect to the login redirect route |
188
|
|
|
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute()); |
189
|
|
|
} |
190
|
|
|
// if registration is disabled |
191
|
|
|
if (!$this->getOptions()->getEnableRegistration()) { |
192
|
|
|
return array('enableRegistration' => false); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$request = $this->getRequest(); |
196
|
|
|
$service = $this->getUserService(); |
197
|
|
|
$form = $this->getRegisterForm(); |
198
|
|
|
|
199
|
|
|
if ($this->getOptions()->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) { |
200
|
|
|
$redirect = $request->getQuery()->get('redirect'); |
201
|
|
|
} else { |
202
|
|
|
$redirect = false; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
$redirectUrl = $this->url()->fromRoute(static::ROUTE_REGISTER) |
206
|
|
|
. ($redirect ? '?redirect=' . rawurlencode($redirect) : ''); |
207
|
|
|
$prg = $this->prg($redirectUrl, true); |
208
|
|
|
|
209
|
|
|
if ($prg instanceof Response) { |
210
|
|
|
return $prg; |
211
|
|
|
} elseif ($prg === false) { |
212
|
|
|
return array( |
213
|
|
|
'registerForm' => $form, |
214
|
|
|
'enableRegistration' => $this->getOptions()->getEnableRegistration(), |
215
|
|
|
'redirect' => $redirect, |
216
|
|
|
); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
$post = $prg; |
220
|
|
|
$user = $service->register($post); |
221
|
|
|
|
222
|
|
|
$redirect = isset($prg['redirect']) ? $prg['redirect'] : null; |
223
|
|
|
|
224
|
|
|
if (!$user) { |
225
|
|
|
return array( |
226
|
|
|
'registerForm' => $form, |
227
|
|
|
'enableRegistration' => $this->getOptions()->getEnableRegistration(), |
228
|
|
|
'redirect' => $redirect, |
229
|
|
|
); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
if ($service->getOptions()->getLoginAfterRegistration()) { |
233
|
|
|
$identityFields = $service->getOptions()->getAuthIdentityFields(); |
234
|
|
|
if (in_array('email', $identityFields)) { |
235
|
|
|
$post['identity'] = $user->getEmail(); |
236
|
|
|
} elseif (in_array('username', $identityFields)) { |
237
|
|
|
$post['identity'] = $user->getUsername(); |
238
|
|
|
} |
239
|
|
|
$post['credential'] = $post['password']; |
240
|
|
|
$request->setPost(new Parameters($post)); |
241
|
|
|
return $this->forward()->dispatch(static::CONTROLLER_NAME, array('action' => 'authenticate')); |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
// TODO: Add the redirect parameter here... |
245
|
|
|
return $this->redirect()->toUrl($this->url()->fromRoute(static::ROUTE_LOGIN) . ($redirect ? '?redirect='. rawurlencode($redirect) : '')); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Change the users password |
250
|
|
|
*/ |
251
|
|
|
public function changepasswordAction() |
252
|
|
|
{ |
253
|
|
|
// if the user isn't logged in, we can't change password |
254
|
|
|
if (!$this->zfcUserAuthentication()->hasIdentity()) { |
255
|
|
|
// redirect to the login redirect route |
256
|
|
|
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute()); |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
$form = $this->getChangePasswordForm(); |
260
|
|
|
$prg = $this->prg(static::ROUTE_CHANGEPASSWD); |
261
|
|
|
|
262
|
|
|
$fm = $this->flashMessenger()->setNamespace('change-password')->getMessages(); |
263
|
|
|
if (isset($fm[0])) { |
264
|
|
|
$status = $fm[0]; |
265
|
|
|
} else { |
266
|
|
|
$status = null; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
if ($prg instanceof Response) { |
270
|
|
|
return $prg; |
271
|
|
|
} elseif ($prg === false) { |
272
|
|
|
return array( |
273
|
|
|
'status' => $status, |
274
|
|
|
'changePasswordForm' => $form, |
275
|
|
|
); |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
$form->setData($prg); |
279
|
|
|
|
280
|
|
|
if (!$form->isValid()) { |
281
|
|
|
return array( |
282
|
|
|
'status' => false, |
283
|
|
|
'changePasswordForm' => $form, |
284
|
|
|
); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
if (!$this->getUserService()->changePassword($form->getData())) { |
288
|
|
|
return array( |
289
|
|
|
'status' => false, |
290
|
|
|
'changePasswordForm' => $form, |
291
|
|
|
); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
$this->flashMessenger()->setNamespace('change-password')->addMessage(true); |
295
|
|
|
return $this->redirect()->toRoute(static::ROUTE_CHANGEPASSWD); |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
public function changeEmailAction() |
299
|
|
|
{ |
300
|
|
|
// if the user isn't logged in, we can't change email |
301
|
|
|
if (!$this->zfcUserAuthentication()->hasIdentity()) { |
302
|
|
|
// redirect to the login redirect route |
303
|
|
|
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute()); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
$form = $this->getChangeEmailForm(); |
307
|
|
|
$request = $this->getRequest(); |
308
|
|
|
$request->getPost()->set('identity', $this->getUserService()->getAuthService()->getIdentity()->getEmail()); |
309
|
|
|
|
310
|
|
|
$fm = $this->flashMessenger()->setNamespace('change-email')->getMessages(); |
311
|
|
|
if (isset($fm[0])) { |
312
|
|
|
$status = $fm[0]; |
313
|
|
|
} else { |
314
|
|
|
$status = null; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
$prg = $this->prg(static::ROUTE_CHANGEEMAIL); |
318
|
|
|
if ($prg instanceof Response) { |
319
|
|
|
return $prg; |
320
|
|
|
} elseif ($prg === false) { |
321
|
|
|
return array( |
322
|
|
|
'status' => $status, |
323
|
|
|
'changeEmailForm' => $form, |
324
|
|
|
); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
$form->setData($prg); |
328
|
|
|
|
329
|
|
|
if (!$form->isValid()) { |
330
|
|
|
return array( |
331
|
|
|
'status' => false, |
332
|
|
|
'changeEmailForm' => $form, |
333
|
|
|
); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
$change = $this->getUserService()->changeEmail($prg); |
337
|
|
|
|
338
|
|
|
if (!$change) { |
339
|
|
|
$this->flashMessenger()->setNamespace('change-email')->addMessage(false); |
340
|
|
|
return array( |
341
|
|
|
'status' => false, |
342
|
|
|
'changeEmailForm' => $form, |
343
|
|
|
); |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
$this->flashMessenger()->setNamespace('change-email')->addMessage(true); |
347
|
|
|
return $this->redirect()->toRoute(static::ROUTE_CHANGEEMAIL); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Getters/setters for DI stuff |
352
|
|
|
*/ |
353
|
|
|
|
354
|
|
|
public function getUserService() |
355
|
|
|
{ |
356
|
|
|
if (!$this->userService) { |
357
|
|
|
$this->userService = $this->serviceLocator->get('zfcuser_user_service'); |
|
|
|
|
358
|
|
|
} |
359
|
|
|
return $this->userService; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
public function setUserService(UserService $userService) |
363
|
|
|
{ |
364
|
|
|
$this->userService = $userService; |
365
|
|
|
return $this; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
public function getRegisterForm() |
369
|
|
|
{ |
370
|
|
|
if (!$this->registerForm) { |
371
|
|
|
$this->setRegisterForm($this->serviceLocator->get('zfcuser_register_form')); |
|
|
|
|
372
|
|
|
} |
373
|
|
|
return $this->registerForm; |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
public function setRegisterForm(FormInterface$registerForm) |
377
|
|
|
{ |
378
|
|
|
$this->registerForm = $registerForm; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
public function getLoginForm() |
382
|
|
|
{ |
383
|
|
|
if (!$this->loginForm) { |
384
|
|
|
$this->setLoginForm($this->serviceLocator->get('zfcuser_login_form')); |
|
|
|
|
385
|
|
|
} |
386
|
|
|
return $this->loginForm; |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
public function setLoginForm(FormInterface $loginForm) |
390
|
|
|
{ |
391
|
|
|
$this->loginForm = $loginForm; |
392
|
|
|
$fm = $this->flashMessenger()->setNamespace('zfcuser-login-form')->getMessages(); |
393
|
|
|
if (isset($fm[0])) { |
394
|
|
|
$this->loginForm->setMessages( |
395
|
|
|
array('identity' => array($fm[0])) |
396
|
|
|
); |
397
|
|
|
} |
398
|
|
|
return $this; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
public function getChangePasswordForm() |
402
|
|
|
{ |
403
|
|
|
if (!$this->changePasswordForm) { |
404
|
|
|
$this->setChangePasswordForm($this->serviceLocator->get('zfcuser_change_password_form')); |
|
|
|
|
405
|
|
|
} |
406
|
|
|
return $this->changePasswordForm; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
public function setChangePasswordForm(FormInterface $changePasswordForm) |
410
|
|
|
{ |
411
|
|
|
$this->changePasswordForm = $changePasswordForm; |
412
|
|
|
return $this; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* set options |
417
|
|
|
* |
418
|
|
|
* @param UserControllerOptionsInterface $options |
419
|
|
|
* @return UserController |
420
|
|
|
*/ |
421
|
|
|
public function setOptions(UserControllerOptionsInterface $options) |
422
|
|
|
{ |
423
|
|
|
$this->options = $options; |
424
|
|
|
return $this; |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* get options |
429
|
|
|
* |
430
|
|
|
* @return UserControllerOptionsInterface |
431
|
|
|
*/ |
432
|
|
|
public function getOptions() |
433
|
|
|
{ |
434
|
|
|
if (!$this->options instanceof UserControllerOptionsInterface) { |
435
|
|
|
$this->setOptions($this->serviceLocator->get('zfcuser_module_options')); |
|
|
|
|
436
|
|
|
} |
437
|
|
|
return $this->options; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Get changeEmailForm. |
442
|
|
|
* @return ChangeEmailForm |
443
|
|
|
*/ |
444
|
|
|
public function getChangeEmailForm() |
445
|
|
|
{ |
446
|
|
|
if (!$this->changeEmailForm) { |
447
|
|
|
$this->setChangeEmailForm($this->serviceLocator->get('zfcuser_change_email_form')); |
448
|
|
|
} |
449
|
|
|
return $this->changeEmailForm; |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
/** |
453
|
|
|
* Set changeEmailForm. |
454
|
|
|
* |
455
|
|
|
* @param $changeEmailForm - the value to set. |
456
|
|
|
* @return $this |
457
|
|
|
*/ |
458
|
|
|
public function setChangeEmailForm($changeEmailForm) |
459
|
|
|
{ |
460
|
|
|
$this->changeEmailForm = $changeEmailForm; |
461
|
|
|
return $this; |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.