1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace LmcUser\Service; |
4
|
|
|
|
5
|
|
|
use Interop\Container\ContainerInterface; |
6
|
|
|
use Laminas\Authentication\AuthenticationService; |
7
|
|
|
use Laminas\Form\Form; |
8
|
|
|
use Laminas\ServiceManager\ServiceManager; |
9
|
|
|
use Laminas\Crypt\Password\Bcrypt; |
10
|
|
|
use Laminas\Hydrator; |
11
|
|
|
use LmcUser\EventManager\EventProvider; |
12
|
|
|
use LmcUser\Mapper\UserInterface as UserMapperInterface; |
13
|
|
|
use LmcUser\Options\UserServiceOptionsInterface; |
14
|
|
|
|
15
|
|
|
class User extends EventProvider |
16
|
|
|
{ |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* @var UserMapperInterface |
20
|
|
|
*/ |
21
|
|
|
protected $userMapper; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* @var AuthenticationService |
25
|
|
|
*/ |
26
|
|
|
protected $authService; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var Form |
30
|
|
|
*/ |
31
|
|
|
protected $loginForm; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var Form |
35
|
|
|
*/ |
36
|
|
|
protected $registerForm; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var Form |
40
|
|
|
*/ |
41
|
|
|
protected $changePasswordForm; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var ServiceManager |
45
|
|
|
*/ |
46
|
|
|
protected $serviceManager; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var UserServiceOptionsInterface |
50
|
|
|
*/ |
51
|
|
|
protected $options; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var Hydrator\ClassMethods |
55
|
|
|
*/ |
56
|
|
|
protected $formHydrator; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* createFromForm |
60
|
|
|
* |
61
|
|
|
* @param array $data |
62
|
|
|
* @return \LmcUser\Entity\UserInterface |
63
|
|
|
* @throws Exception\InvalidArgumentException |
64
|
|
|
*/ |
65
|
|
|
public function register(array $data) |
66
|
|
|
{ |
67
|
|
|
$class = $this->getOptions()->getUserEntityClass(); |
68
|
|
|
$user = new $class; |
69
|
|
|
$form = $this->getRegisterForm(); |
70
|
|
|
$form->setHydrator($this->getFormHydrator()); |
71
|
|
|
$form->bind($user); |
72
|
|
|
$form->setData($data); |
73
|
|
|
if (!$form->isValid()) { |
74
|
|
|
return false; |
|
|
|
|
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
$user = $form->getData(); |
78
|
|
|
/* @var $user \LmcUser\Entity\UserInterface */ |
79
|
|
|
|
80
|
|
|
$bcrypt = new Bcrypt; |
81
|
|
|
$bcrypt->setCost($this->getOptions()->getPasswordCost()); |
82
|
|
|
$user->setPassword($bcrypt->create($user->getPassword())); |
83
|
|
|
|
84
|
|
|
if ($this->getOptions()->getEnableUsername()) { |
85
|
|
|
$user->setUsername($data['username']); |
86
|
|
|
} |
87
|
|
|
if ($this->getOptions()->getEnableDisplayName()) { |
88
|
|
|
$user->setDisplayName($data['display_name']); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// If user state is enabled, set the default state value |
92
|
|
|
if ($this->getOptions()->getEnableUserState()) { |
93
|
|
|
$user->setState($this->getOptions()->getDefaultUserState()); |
94
|
|
|
} |
95
|
|
|
$this->getEventManager()->trigger(__FUNCTION__, $this, array('user' => $user, 'form' => $form)); |
96
|
|
|
$this->getUserMapper()->insert($user); |
97
|
|
|
$this->getEventManager()->trigger(__FUNCTION__.'.post', $this, array('user' => $user, 'form' => $form)); |
98
|
|
|
return $user; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* change the current users password |
103
|
|
|
* |
104
|
|
|
* @param array $data |
105
|
|
|
* @return boolean |
106
|
|
|
*/ |
107
|
|
|
public function changePassword(array $data) |
108
|
|
|
{ |
109
|
|
|
$currentUser = $this->getAuthService()->getIdentity(); |
110
|
|
|
|
111
|
|
|
$oldPass = $data['credential']; |
112
|
|
|
$newPass = $data['newCredential']; |
113
|
|
|
|
114
|
|
|
$bcrypt = new Bcrypt; |
115
|
|
|
$bcrypt->setCost($this->getOptions()->getPasswordCost()); |
116
|
|
|
|
117
|
|
|
if (!$bcrypt->verify($oldPass, $currentUser->getPassword())) { |
118
|
|
|
return false; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
$pass = $bcrypt->create($newPass); |
122
|
|
|
$currentUser->setPassword($pass); |
123
|
|
|
|
124
|
|
|
$this->getEventManager()->trigger(__FUNCTION__, $this, array('user' => $currentUser, 'data' => $data)); |
125
|
|
|
$this->getUserMapper()->update($currentUser); |
126
|
|
|
$this->getEventManager()->trigger(__FUNCTION__.'.post', $this, array('user' => $currentUser, 'data' => $data)); |
127
|
|
|
|
128
|
|
|
return true; |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
public function changeEmail(array $data) |
132
|
|
|
{ |
133
|
|
|
$currentUser = $this->getAuthService()->getIdentity(); |
134
|
|
|
|
135
|
|
|
$bcrypt = new Bcrypt; |
136
|
|
|
$bcrypt->setCost($this->getOptions()->getPasswordCost()); |
137
|
|
|
|
138
|
|
|
if (!$bcrypt->verify($data['credential'], $currentUser->getPassword())) { |
139
|
|
|
return false; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
$currentUser->setEmail($data['newIdentity']); |
143
|
|
|
|
144
|
|
|
$this->getEventManager()->trigger(__FUNCTION__, $this, array('user' => $currentUser, 'data' => $data)); |
145
|
|
|
$this->getUserMapper()->update($currentUser); |
146
|
|
|
$this->getEventManager()->trigger(__FUNCTION__.'.post', $this, array('user' => $currentUser, 'data' => $data)); |
147
|
|
|
|
148
|
|
|
return true; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* getUserMapper |
153
|
|
|
* |
154
|
|
|
* @return UserMapperInterface |
155
|
|
|
*/ |
156
|
|
|
public function getUserMapper() |
157
|
|
|
{ |
158
|
|
|
if (null === $this->userMapper) { |
159
|
|
|
$this->userMapper = $this->getServiceManager()->get('lmcuser_user_mapper'); |
160
|
|
|
} |
161
|
|
|
return $this->userMapper; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* setUserMapper |
166
|
|
|
* |
167
|
|
|
* @param UserMapperInterface $userMapper |
168
|
|
|
* @return User |
169
|
|
|
*/ |
170
|
|
|
public function setUserMapper(UserMapperInterface $userMapper) |
171
|
|
|
{ |
172
|
|
|
$this->userMapper = $userMapper; |
173
|
|
|
return $this; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* getAuthService |
178
|
|
|
* |
179
|
|
|
* @return AuthenticationService |
180
|
|
|
*/ |
181
|
|
|
public function getAuthService() |
182
|
|
|
{ |
183
|
|
|
if (null === $this->authService) { |
184
|
|
|
$this->authService = $this->getServiceManager()->get('lmcuser_auth_service'); |
185
|
|
|
} |
186
|
|
|
return $this->authService; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* setAuthenticationService |
191
|
|
|
* |
192
|
|
|
* @param AuthenticationService $authService |
193
|
|
|
* @return User |
194
|
|
|
*/ |
195
|
|
|
public function setAuthService(AuthenticationService $authService) |
196
|
|
|
{ |
197
|
|
|
$this->authService = $authService; |
198
|
|
|
return $this; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* @return Form |
203
|
|
|
*/ |
204
|
|
|
public function getRegisterForm() |
205
|
|
|
{ |
206
|
|
|
if (null === $this->registerForm) { |
207
|
|
|
$this->registerForm = $this->getServiceManager()->get('lmcuser_register_form'); |
208
|
|
|
} |
209
|
|
|
return $this->registerForm; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param Form $registerForm |
214
|
|
|
* @return User |
215
|
|
|
*/ |
216
|
|
|
public function setRegisterForm(Form $registerForm) |
217
|
|
|
{ |
218
|
|
|
$this->registerForm = $registerForm; |
219
|
|
|
return $this; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
/** |
223
|
|
|
* @return Form |
224
|
|
|
*/ |
225
|
|
|
public function getChangePasswordForm() |
226
|
|
|
{ |
227
|
|
|
if (null === $this->changePasswordForm) { |
228
|
|
|
$this->changePasswordForm = $this->getServiceManager()->get('lmcuser_change_password_form'); |
229
|
|
|
} |
230
|
|
|
return $this->changePasswordForm; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* @param Form $changePasswordForm |
235
|
|
|
* @return User |
236
|
|
|
*/ |
237
|
|
|
public function setChangePasswordForm(Form $changePasswordForm) |
238
|
|
|
{ |
239
|
|
|
$this->changePasswordForm = $changePasswordForm; |
240
|
|
|
return $this; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* get service options |
245
|
|
|
* |
246
|
|
|
* @return UserServiceOptionsInterface |
247
|
|
|
*/ |
248
|
|
|
public function getOptions() |
249
|
|
|
{ |
250
|
|
|
if (!$this->options instanceof UserServiceOptionsInterface) { |
251
|
|
|
$this->setOptions($this->getServiceManager()->get('lmcuser_module_options')); |
252
|
|
|
} |
253
|
|
|
return $this->options; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* set service options |
258
|
|
|
* |
259
|
|
|
* @param UserServiceOptionsInterface $options |
260
|
|
|
*/ |
261
|
|
|
public function setOptions(UserServiceOptionsInterface $options) |
262
|
|
|
{ |
263
|
|
|
$this->options = $options; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Retrieve service manager instance |
268
|
|
|
* |
269
|
|
|
* @return ServiceManager |
270
|
|
|
*/ |
271
|
|
|
public function getServiceManager() |
272
|
|
|
{ |
273
|
|
|
return $this->serviceManager; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Set service manager instance |
278
|
|
|
* |
279
|
|
|
* @param ContainerInterface $serviceManager |
280
|
|
|
* @return User |
281
|
|
|
*/ |
282
|
|
|
public function setServiceManager(ContainerInterface $serviceManager) |
283
|
|
|
{ |
284
|
|
|
$this->serviceManager = $serviceManager; |
|
|
|
|
285
|
|
|
return $this; |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
/** |
289
|
|
|
* Return the Form Hydrator |
290
|
|
|
* |
291
|
|
|
* @return \Laminas\Hydrator\HydratorInterface |
292
|
|
|
*/ |
293
|
|
|
public function getFormHydrator() |
294
|
|
|
{ |
295
|
|
|
if (!$this->formHydrator instanceof Hydrator\HydratorInterface) { |
296
|
|
|
$this->setFormHydrator($this->getServiceManager()->get('lmcuser_register_form_hydrator')); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
return $this->formHydrator; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Set the Form Hydrator to use |
304
|
|
|
* |
305
|
|
|
* @param Hydrator\HydratorInterface $formHydrator |
306
|
|
|
* @return User |
307
|
|
|
*/ |
308
|
|
|
public function setFormHydrator(Hydrator\HydratorInterface $formHydrator) |
309
|
|
|
{ |
310
|
|
|
$this->formHydrator = $formHydrator; |
|
|
|
|
311
|
|
|
return $this; |
312
|
|
|
} |
313
|
|
|
} |
314
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.