Completed
Push — 2.x ( a081e5 )
by Daniel
15:13
created

UserController::setServiceLocator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
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);
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
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);
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
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);
0 ignored issues
show
Documentation Bug introduced by
The method prg does not exist on object<ZfcUser\Controller\UserController>? 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...
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);
0 ignored issues
show
Documentation Bug introduced by
The method prg does not exist on object<ZfcUser\Controller\UserController>? 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...
261
262
        $fm = $this->flashMessenger()->setNamespace('change-password')->getMessages();
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
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);
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
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();
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
311
        if (isset($fm[0])) {
312
            $status = $fm[0];
313
        } else {
314
            $status = null;
315
        }
316
317
        $prg = $this->prg(static::ROUTE_CHANGEEMAIL);
0 ignored issues
show
Documentation Bug introduced by
The method prg does not exist on object<ZfcUser\Controller\UserController>? 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...
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);
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
340
            return array(
341
                'status' => false,
342
                'changeEmailForm' => $form,
343
            );
344
        }
345
346
        $this->flashMessenger()->setNamespace('change-email')->addMessage(true);
0 ignored issues
show
Documentation Bug introduced by
The method flashMessenger does not exist on object<ZfcUser\Controller\UserController>? 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...
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
        return $this;
393
    }
394
395
    public function getChangePasswordForm()
396
    {
397
        if (!$this->changePasswordForm) {
398
            $this->setChangePasswordForm($this->serviceLocator->get('zfcuser_change_password_form'));
399
        }
400
        return $this->changePasswordForm;
401
    }
402
403
    public function setChangePasswordForm(FormInterface $changePasswordForm)
404
    {
405
        $this->changePasswordForm = $changePasswordForm;
406
        return $this;
407
    }
408
409
    /**
410
     * set options
411
     *
412
     * @param UserControllerOptionsInterface $options
413
     * @return UserController
414
     */
415
    public function setOptions(UserControllerOptionsInterface $options)
416
    {
417
        $this->options = $options;
418
        return $this;
419
    }
420
421
    /**
422
     * get options
423
     *
424
     * @return UserControllerOptionsInterface
425
     */
426
    public function getOptions()
427
    {
428
        if (!$this->options instanceof UserControllerOptionsInterface) {
429
            $this->setOptions($this->serviceLocator->get('zfcuser_module_options'));
430
        }
431
        return $this->options;
432
    }
433
434
    /**
435
     * Get changeEmailForm.
436
     * @return ChangeEmailForm
437
     */
438
    public function getChangeEmailForm()
439
    {
440
        if (!$this->changeEmailForm) {
441
            $this->setChangeEmailForm($this->serviceLocator->get('zfcuser_change_email_form'));
442
        }
443
        return $this->changeEmailForm;
444
    }
445
446
    /**
447
     * Set changeEmailForm.
448
     *
449
     * @param $changeEmailForm - the value to set.
450
     * @return $this
451
     */
452
    public function setChangeEmailForm($changeEmailForm)
453
    {
454
        $this->changeEmailForm = $changeEmailForm;
455
        return $this;
456
    }
457
458
    /**
459
     * @param $serviceLocator
460
     */
461
    public function setServiceLocator($serviceLocator)
462
    {
463
        $this->serviceLocator = $serviceLocator;
464
    }
465
}
466