1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Backend\Modules\Profiles\Actions; |
4
|
|
|
|
5
|
|
|
use Backend\Core\Engine\Base\ActionEdit as BackendBaseActionEdit; |
6
|
|
|
use Backend\Core\Engine\Authentication as BackendAuthentication; |
7
|
|
|
use Backend\Core\Engine\DataGridDatabase as BackendDataGridDatabase; |
8
|
|
|
use Backend\Core\Engine\DataGridFunctions as BackendDataGridFunctions; |
9
|
|
|
use Backend\Core\Engine\Form as BackendForm; |
10
|
|
|
use Backend\Core\Language\Language as BL; |
11
|
|
|
use Backend\Core\Engine\Model as BackendModel; |
12
|
|
|
use Backend\Form\Type\DeleteType; |
13
|
|
|
use Backend\Modules\Profiles\Engine\Model as BackendProfilesModel; |
14
|
|
|
use Symfony\Component\Intl\Intl as Intl; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* This is the edit-action, it will display a form to edit an existing profile. |
18
|
|
|
*/ |
19
|
|
|
class Edit extends BackendBaseActionEdit |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* Groups data grid. |
23
|
|
|
* |
24
|
|
|
* @var BackendDataGridDatabase |
25
|
|
|
*/ |
26
|
|
|
private $dgGroups; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var bool |
30
|
|
|
*/ |
31
|
|
|
private $notifyProfile; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Info about the current profile. |
35
|
|
|
* |
36
|
|
|
* @var array |
37
|
|
|
*/ |
38
|
|
|
private $profile; |
39
|
|
|
|
40
|
|
|
public function execute(): void |
41
|
|
|
{ |
42
|
|
|
$this->id = $this->getRequest()->query->getInt('id'); |
43
|
|
|
|
44
|
|
|
// does the item exist? |
45
|
|
|
if ($this->id !== 0 && BackendProfilesModel::exists($this->id)) { |
46
|
|
|
parent::execute(); |
47
|
|
|
$this->getData(); |
48
|
|
|
$this->loadGroups(); |
49
|
|
|
$this->loadForm(); |
50
|
|
|
$this->validateForm(); |
51
|
|
|
$this->loadDeleteForm(); |
52
|
|
|
$this->parse(); |
53
|
|
|
$this->display(); |
54
|
|
|
} else { |
55
|
|
|
$this->redirect(BackendModel::createUrlForAction('Index') . '&error=non-existing'); |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
private function getData(): void |
60
|
|
|
{ |
61
|
|
|
// get general info |
62
|
|
|
$this->profile = BackendProfilesModel::get($this->id); |
63
|
|
|
|
64
|
|
|
$this->notifyProfile = $this->get('fork.settings')->get( |
65
|
|
|
$this->url->getModule(), |
66
|
|
|
'send_new_profile_mail', |
67
|
|
|
false |
68
|
|
|
); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
private function loadForm(): void |
72
|
|
|
{ |
73
|
|
|
// gender dropdown values |
74
|
|
|
$genderValues = [ |
75
|
|
|
'male' => \SpoonFilter::ucfirst(BL::getLabel('Male')), |
76
|
|
|
'female' => \SpoonFilter::ucfirst(BL::getLabel('Female')), |
77
|
|
|
]; |
78
|
|
|
|
79
|
|
|
// birthdate dropdown values |
80
|
|
|
$days = range(1, 31); |
81
|
|
|
$months = \SpoonLocale::getMonths(BL::getInterfaceLanguage()); |
82
|
|
|
$years = range(date('Y'), 1900); |
83
|
|
|
|
84
|
|
|
// get settings |
85
|
|
|
$birthDate = BackendProfilesModel::getSetting($this->id, 'birth_date'); |
86
|
|
|
|
87
|
|
|
// get day, month and year |
88
|
|
|
if ($birthDate) { |
89
|
|
|
list($birthYear, $birthMonth, $birthDay) = explode('-', $birthDate); |
90
|
|
|
} else { |
91
|
|
|
// no birth date setting |
92
|
|
|
$birthDay = ''; |
93
|
|
|
$birthMonth = ''; |
94
|
|
|
$birthYear = ''; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
// create form |
98
|
|
|
$this->form = new BackendForm('edit'); |
99
|
|
|
|
100
|
|
|
// create elements |
101
|
|
|
$this->form->addCheckbox('new_email'); |
102
|
|
|
$this->form->addText('email', $this->profile['email']); |
103
|
|
|
$this->form->addCheckbox('new_password'); |
104
|
|
|
$this->form->addPassword('password'); |
105
|
|
|
$this->form->addPassword('password_repeat'); |
106
|
|
|
$this->form->addText('display_name', $this->profile['display_name'])->makeRequired(); |
107
|
|
|
$this->form->addText('first_name', BackendProfilesModel::getSetting($this->id, 'first_name')); |
108
|
|
|
$this->form->addText('last_name', BackendProfilesModel::getSetting($this->id, 'last_name')); |
109
|
|
|
$this->form->addText('city', BackendProfilesModel::getSetting($this->id, 'city')); |
110
|
|
|
$this->form->addDropdown('gender', $genderValues, BackendProfilesModel::getSetting($this->id, 'gender')); |
111
|
|
|
$this->form->addDropdown('day', array_combine($days, $days), $birthDay); |
|
|
|
|
112
|
|
|
$this->form->addDropdown('month', $months, $birthMonth); |
113
|
|
|
$this->form->addDropdown('year', array_combine($years, $years), (int) $birthYear); |
114
|
|
|
$this->form->addDropdown( |
115
|
|
|
'country', |
116
|
|
|
Intl::getRegionBundle()->getCountryNames(BL::getInterfaceLanguage()), |
117
|
|
|
BackendProfilesModel::getSetting($this->id, 'country') |
118
|
|
|
); |
119
|
|
|
$this->form->addTextarea('about', BackendProfilesModel::getSetting($this->id, 'about')); |
120
|
|
|
|
121
|
|
|
// set default elements dropdowns |
122
|
|
|
$this->form->getField('gender')->setDefaultElement(''); |
123
|
|
|
$this->form->getField('day')->setDefaultElement(''); |
124
|
|
|
$this->form->getField('month')->setDefaultElement(''); |
125
|
|
|
$this->form->getField('year')->setDefaultElement(''); |
126
|
|
|
$this->form->getField('country')->setDefaultElement(''); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
private function loadGroups(): void |
130
|
|
|
{ |
131
|
|
|
// create the data grid |
132
|
|
|
$this->dgGroups = new BackendDataGridDatabase( |
133
|
|
|
BackendProfilesModel::QUERY_DATAGRID_BROWSE_PROFILE_GROUPS, |
134
|
|
|
[$this->profile['id']] |
135
|
|
|
); |
136
|
|
|
$this->dgGroups->setColumnFunction('htmlspecialchars', ['[group_name]'], 'group_name', false); |
137
|
|
|
|
138
|
|
|
// sorting columns |
139
|
|
|
$this->dgGroups->setSortingColumns(['group_name'], 'group_name'); |
140
|
|
|
|
141
|
|
|
// disable paging |
142
|
|
|
$this->dgGroups->setPaging(false); |
143
|
|
|
|
144
|
|
|
// set column function |
145
|
|
|
$this->dgGroups->setColumnFunction( |
146
|
|
|
[new BackendDataGridFunctions(), 'getLongDate'], |
147
|
|
|
['[expires_on]'], |
148
|
|
|
'expires_on', |
149
|
|
|
true |
150
|
|
|
); |
151
|
|
|
|
152
|
|
|
// check if this action is allowed |
153
|
|
|
if (BackendAuthentication::isAllowedAction('EditProfileGroup')) { |
154
|
|
|
// set column URLs |
155
|
|
|
$this->dgGroups->setColumnURL( |
156
|
|
|
'group_name', |
157
|
|
|
BackendModel::createUrlForAction('EditProfileGroup') . '&id=[id]&profile_id=' . $this->id |
158
|
|
|
); |
159
|
|
|
|
160
|
|
|
// edit column |
161
|
|
|
$this->dgGroups->addColumn( |
162
|
|
|
'edit', |
163
|
|
|
null, |
164
|
|
|
BL::getLabel('Edit'), |
165
|
|
|
BackendModel::createUrlForAction('EditProfileGroup') . '&id=[id]&profile_id=' . $this->id, |
166
|
|
|
BL::getLabel('Edit') |
167
|
|
|
); |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
protected function parse(): void |
172
|
|
|
{ |
173
|
|
|
parent::parse(); |
174
|
|
|
|
175
|
|
|
$this->template->assign('notifyProfile', $this->notifyProfile); |
176
|
|
|
|
177
|
|
|
// assign the active record and additional variables |
178
|
|
|
$this->template->assign('profile', $this->profile); |
179
|
|
|
|
180
|
|
|
// parse data grids |
181
|
|
|
$this->template->assign('dgGroups', ($this->dgGroups->getNumResults() != 0) ? $this->dgGroups->getContent() : false); |
182
|
|
|
|
183
|
|
|
// show delete or undelete button? |
184
|
|
|
if ($this->profile['status'] === 'deleted') { |
185
|
|
|
$this->template->assign('deleted', true); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// show block or unblock button? |
189
|
|
|
if ($this->profile['status'] === 'blocked') { |
190
|
|
|
$this->template->assign('blocked', true); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
$this->header->appendDetailToBreadcrumbs($this->profile['display_name']); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
private function validateForm(): void |
197
|
|
|
{ |
198
|
|
|
// is the form submitted? |
199
|
|
|
if ($this->form->isSubmitted()) { |
200
|
|
|
// cleanup the submitted fields, ignore fields that were added by hackers |
201
|
|
|
$this->form->cleanupFields(); |
202
|
|
|
|
203
|
|
|
// get fields |
204
|
|
|
$chkNewEmail = $this->form->getField('new_email'); |
205
|
|
|
$txtEmail = $this->form->getField('email'); |
206
|
|
|
$txtDisplayName = $this->form->getField('display_name'); |
207
|
|
|
$chkNewPassword = $this->form->getField('new_password'); |
208
|
|
|
$txtPassword = $this->form->getField('password'); |
209
|
|
|
$txtPasswordRepeat = $this->form->getField('password_repeat'); |
210
|
|
|
$txtFirstName = $this->form->getField('first_name'); |
211
|
|
|
$txtLastName = $this->form->getField('last_name'); |
212
|
|
|
$txtCity = $this->form->getField('city'); |
213
|
|
|
$ddmGender = $this->form->getField('gender'); |
214
|
|
|
$ddmDay = $this->form->getField('day'); |
215
|
|
|
$ddmMonth = $this->form->getField('month'); |
216
|
|
|
$ddmYear = $this->form->getField('year'); |
217
|
|
|
$ddmCountry = $this->form->getField('country'); |
218
|
|
|
$txtAbout = $this->form->getField('about'); |
219
|
|
|
|
220
|
|
|
// email filled in? |
221
|
|
|
if ($chkNewEmail->isChecked() && $txtEmail->isFilled(BL::getError('EmailIsRequired'))) { |
222
|
|
|
// email must not be the same as previous one |
223
|
|
|
if ($txtEmail->getValue() == $this->profile['email']) { |
224
|
|
|
$txtEmail->addError(BL::getError('EmailMatchesPrevious')); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
// valid email? |
228
|
|
|
if ($txtEmail->isEmail(BL::getError('EmailIsInvalid'))) { |
229
|
|
|
// email already exists? |
230
|
|
|
if (BackendProfilesModel::existsByEmail($txtEmail->getValue(), $this->id)) { |
231
|
|
|
// set error |
232
|
|
|
$txtEmail->addError(BL::getError('EmailExists')); |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
// display name filled in? |
238
|
|
|
if ($txtDisplayName->isFilled(BL::getError('DisplayNameIsRequired'))) { |
239
|
|
|
// display name already exists? |
240
|
|
|
if (BackendProfilesModel::existsDisplayName($txtDisplayName->getValue(), $this->id)) { |
241
|
|
|
// set error |
242
|
|
|
$txtDisplayName->addError(BL::getError('DisplayNameExists')); |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
// new_password is checked, so verify new password (only if profile should not be notified) |
247
|
|
|
// because then if the password field is empty, it will generate a new password |
248
|
|
|
if ($chkNewPassword->isChecked() && !$this->notifyProfile) { |
249
|
|
|
$txtPassword->isFilled(BL::err('FieldIsRequired')); |
250
|
|
|
$txtPasswordRepeat->isFilled(BL::err('FieldIsRequired')); |
251
|
|
|
|
252
|
|
|
// both password fields are filled in and should match |
253
|
|
|
if ($txtPassword->isFilled() && $txtPasswordRepeat->isFilled() |
254
|
|
|
&& ($txtPassword->getValue() != $txtPasswordRepeat->getValue())) { |
255
|
|
|
$txtPasswordRepeat->addError(BL::err('PasswordRepeatIsRequired')); |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
// one of the bday fields are filled in |
260
|
|
|
if ($ddmDay->isFilled() || $ddmMonth->isFilled() || $ddmYear->isFilled()) { |
261
|
|
|
// valid date? |
262
|
|
|
if (!checkdate($ddmMonth->getValue(), $ddmDay->getValue(), $ddmYear->getValue())) { |
263
|
|
|
// set error |
264
|
|
|
$ddmYear->addError(BL::getError('DateIsInvalid')); |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
// no errors? |
269
|
|
|
if ($this->form->isCorrect()) { |
270
|
|
|
// build item |
271
|
|
|
$values = ['email' => $chkNewEmail->isChecked() ? $txtEmail->getValue() : $this->profile['email']]; |
272
|
|
|
$password = BL::lbl('YourExistingPassword'); |
273
|
|
|
|
274
|
|
|
// only update if display name changed |
275
|
|
|
if ($txtDisplayName->getValue() != $this->profile['display_name']) { |
276
|
|
|
$values['display_name'] = $txtDisplayName->getValue(); |
277
|
|
|
$values['url'] = BackendProfilesModel::getUrl( |
278
|
|
|
$txtDisplayName->getValue(), |
279
|
|
|
$this->id |
280
|
|
|
); |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
// new password filled in? |
284
|
|
|
if ($chkNewPassword->isChecked()) { |
285
|
|
|
// new password filled in? otherwise generate a password |
286
|
|
|
$password = ($txtPassword->isFilled()) ? |
287
|
|
|
$txtPassword->getValue() : BackendModel::generatePassword(8); |
288
|
|
|
|
289
|
|
|
// build password |
290
|
|
|
$values['password'] = BackendProfilesModel::encryptPassword($password); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
// update values |
294
|
|
|
BackendProfilesModel::update($this->id, $values); |
295
|
|
|
|
296
|
|
|
// birthday is filled in |
297
|
|
|
if ($ddmYear->isFilled()) { |
298
|
|
|
// mysql format |
299
|
|
|
$birthDate = $ddmYear->getValue() . '-'; |
300
|
|
|
$birthDate .= str_pad($ddmMonth->getValue(), 2, '0', STR_PAD_LEFT) . '-'; |
301
|
|
|
$birthDate .= str_pad($ddmDay->getValue(), 2, '0', STR_PAD_LEFT); |
302
|
|
|
} else { |
303
|
|
|
$birthDate = null; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
// update settings |
307
|
|
|
BackendProfilesModel::setSetting($this->id, 'first_name', $txtFirstName->getValue()); |
308
|
|
|
BackendProfilesModel::setSetting($this->id, 'last_name', $txtLastName->getValue()); |
309
|
|
|
BackendProfilesModel::setSetting($this->id, 'gender', $ddmGender->getValue()); |
310
|
|
|
BackendProfilesModel::setSetting($this->id, 'birth_date', $birthDate); |
311
|
|
|
BackendProfilesModel::setSetting($this->id, 'city', $txtCity->getValue()); |
312
|
|
|
BackendProfilesModel::setSetting($this->id, 'country', $ddmCountry->getValue()); |
313
|
|
|
BackendProfilesModel::setSetting($this->id, 'about', $txtAbout->getValue()); |
314
|
|
|
|
315
|
|
|
$displayName = $values['display_name'] ?? $this->profile['display_name']; |
316
|
|
|
|
317
|
|
|
$redirectUrl = BackendModel::createUrlForAction('Index') . |
318
|
|
|
'&var=' . rawurlencode($values['email']) . |
319
|
|
|
'&highlight=row-' . $this->id . |
320
|
|
|
'&var=' . rawurlencode($displayName) . |
321
|
|
|
'&report=' |
322
|
|
|
; |
323
|
|
|
|
324
|
|
|
if ($this->notifyProfile && |
325
|
|
|
($chkNewEmail->isChecked() || $chkNewPassword->isChecked()) |
326
|
|
|
) { |
327
|
|
|
// notify values |
328
|
|
|
$notifyValues = array_merge( |
329
|
|
|
$values, |
330
|
|
|
[ |
331
|
|
|
'id' => $this->id, |
332
|
|
|
'first_name' => $txtFirstName->getValue(), |
333
|
|
|
'last_name' => $txtLastName->getValue(), |
334
|
|
|
'unencrypted_password' => $password, |
335
|
|
|
] |
336
|
|
|
); |
337
|
|
|
|
338
|
|
|
if (!isset($notifyValues['display_name'])) { |
339
|
|
|
$notifyValues['display_name'] = $this->profile['display_name']; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
BackendProfilesModel::notifyProfile($notifyValues, true); |
343
|
|
|
|
344
|
|
|
$redirectUrl .= 'saved-and-notified'; |
345
|
|
|
} else { |
346
|
|
|
$redirectUrl .= 'saved'; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
// everything is saved, so redirect to the overview |
350
|
|
|
$this->redirect($redirectUrl); |
351
|
|
|
} |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
private function loadDeleteForm(): void |
356
|
|
|
{ |
357
|
|
|
$deleteForm = $this->createForm( |
358
|
|
|
DeleteType::class, |
359
|
|
|
['id' => $this->profile['id']], |
360
|
|
|
['module' => $this->getModule()] |
361
|
|
|
); |
362
|
|
|
$this->template->assign('deleteForm', $deleteForm->createView()); |
363
|
|
|
} |
364
|
|
|
} |
365
|
|
|
|