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 |
||
103 | ->addText('email', $this->profile['email']) |
||
104 | ; |
||
105 | $this->form->addCheckbox('new_password'); |
||
106 | $this->form |
||
107 | ->addPassword('password') |
||
108 | ->setAttribute('autocomplete', 'new-password') |
||
109 | ; |
||
110 | $this->form |
||
111 | ->addPassword('password_repeat') |
||
112 | ->setAttribute('autocomplete', 'new-password') |
||
113 | ; |
||
114 | $this->form |
||
115 | ->addText('display_name', $this->profile['display_name']) |
||
116 | ->makeRequired() |
||
117 | ; |
||
118 | $this->form |
||
119 | ->addText('first_name', BackendProfilesModel::getSetting($this->id, 'first_name')) |
||
120 | ; |
||
121 | $this->form |
||
122 | ->addText('last_name', BackendProfilesModel::getSetting($this->id, 'last_name')) |
||
123 | ; |
||
124 | $this->form |
||
125 | ->addText('city', BackendProfilesModel::getSetting($this->id, 'city')) |
||
126 | ; |
||
127 | $this->form |
||
128 | ->addDropdown('gender', $genderValues, BackendProfilesModel::getSetting($this->id, 'gender')) |
||
129 | ; |
||
130 | $this->form |
||
131 | ->addDropdown('day', array_combine($days, $days), $birthDay) |
||
132 | ; |
||
133 | $this->form |
||
134 | ->addDropdown('month', $months, $birthMonth) |
||
135 | ; |
||
136 | $this->form |
||
137 | ->addDropdown('year', array_combine($years, $years), (int) $birthYear) |
||
138 | ; |
||
139 | $this->form |
||
140 | ->addDropdown( |
||
141 | 'country', |
||
142 | Intl::getRegionBundle()->getCountryNames(BL::getInterfaceLanguage()), |
||
0 ignored issues
–
show
|
|||
143 | BackendProfilesModel::getSetting($this->id, 'country') |
||
144 | ) |
||
145 | ->setAttribute('autocomplete', 'country-name') |
||
146 | ; |
||
147 | $this->form->addTextarea('about', BackendProfilesModel::getSetting($this->id, 'about')); |
||
148 | |||
149 | // set default elements dropdowns |
||
150 | $this->form->getField('gender')->setDefaultElement(''); |
||
151 | $this->form->getField('day')->setDefaultElement(''); |
||
152 | $this->form->getField('month')->setDefaultElement(''); |
||
153 | $this->form->getField('year')->setDefaultElement(''); |
||
154 | $this->form->getField('country')->setDefaultElement(''); |
||
155 | } |
||
156 | |||
157 | private function loadGroups(): void |
||
158 | { |
||
159 | // create the data grid |
||
160 | $this->dgGroups = new BackendDataGridDatabase( |
||
161 | BackendProfilesModel::QUERY_DATAGRID_BROWSE_PROFILE_GROUPS, |
||
162 | [$this->profile['id']] |
||
163 | ); |
||
164 | $this->dgGroups->setColumnFunction('htmlspecialchars', ['[group_name]'], 'group_name', false); |
||
165 | |||
166 | // sorting columns |
||
167 | $this->dgGroups->setSortingColumns(['group_name'], 'group_name'); |
||
168 | |||
169 | // disable paging |
||
170 | $this->dgGroups->setPaging(false); |
||
171 | |||
172 | // set column function |
||
173 | $this->dgGroups->setColumnFunction( |
||
174 | [new BackendDataGridFunctions(), 'getLongDate'], |
||
175 | ['[expires_on]'], |
||
176 | 'expires_on', |
||
177 | true |
||
178 | ); |
||
179 | |||
180 | // check if this action is allowed |
||
181 | if (BackendAuthentication::isAllowedAction('EditProfileGroup')) { |
||
182 | // set column URLs |
||
183 | $this->dgGroups->setColumnURL( |
||
184 | 'group_name', |
||
185 | BackendModel::createUrlForAction('EditProfileGroup') . '&id=[id]&profile_id=' . $this->id |
||
186 | ); |
||
187 | |||
188 | // edit column |
||
189 | $this->dgGroups->addColumn( |
||
190 | 'edit', |
||
191 | null, |
||
192 | BL::getLabel('Edit'), |
||
193 | BackendModel::createUrlForAction('EditProfileGroup') . '&id=[id]&profile_id=' . $this->id, |
||
194 | BL::getLabel('Edit') |
||
195 | ); |
||
196 | } |
||
197 | } |
||
198 | |||
199 | protected function parse(): void |
||
200 | { |
||
201 | parent::parse(); |
||
202 | |||
203 | $this->template->assign('notifyProfile', $this->notifyProfile); |
||
204 | |||
205 | // assign the active record and additional variables |
||
206 | $this->template->assign('profile', $this->profile); |
||
207 | |||
208 | // parse data grids |
||
209 | $this->template->assign('dgGroups', ($this->dgGroups->getNumResults() != 0) ? $this->dgGroups->getContent() : false); |
||
210 | |||
211 | // show delete or undelete button? |
||
212 | if ($this->profile['status'] === 'deleted') { |
||
213 | $this->template->assign('deleted', true); |
||
214 | } |
||
215 | |||
216 | // show block or unblock button? |
||
217 | if ($this->profile['status'] === 'blocked') { |
||
218 | $this->template->assign('blocked', true); |
||
219 | } |
||
220 | |||
221 | $this->header->appendDetailToBreadcrumbs($this->profile['display_name']); |
||
222 | } |
||
223 | |||
224 | private function validateForm(): void |
||
225 | { |
||
226 | // is the form submitted? |
||
227 | if ($this->form->isSubmitted()) { |
||
228 | // cleanup the submitted fields, ignore fields that were added by hackers |
||
229 | $this->form->cleanupFields(); |
||
230 | |||
231 | // get fields |
||
232 | $chkNewEmail = $this->form->getField('new_email'); |
||
233 | $txtEmail = $this->form->getField('email'); |
||
234 | $txtDisplayName = $this->form->getField('display_name'); |
||
235 | $chkNewPassword = $this->form->getField('new_password'); |
||
236 | $txtPassword = $this->form->getField('password'); |
||
237 | $txtPasswordRepeat = $this->form->getField('password_repeat'); |
||
238 | $txtFirstName = $this->form->getField('first_name'); |
||
239 | $txtLastName = $this->form->getField('last_name'); |
||
240 | $txtCity = $this->form->getField('city'); |
||
241 | $ddmGender = $this->form->getField('gender'); |
||
242 | $ddmDay = $this->form->getField('day'); |
||
243 | $ddmMonth = $this->form->getField('month'); |
||
244 | $ddmYear = $this->form->getField('year'); |
||
245 | $ddmCountry = $this->form->getField('country'); |
||
246 | $txtAbout = $this->form->getField('about'); |
||
247 | |||
248 | // email filled in? |
||
249 | if ($chkNewEmail->isChecked() && $txtEmail->isFilled(BL::getError('EmailIsRequired'))) { |
||
250 | // email must not be the same as previous one |
||
251 | if ($txtEmail->getValue() == $this->profile['email']) { |
||
252 | $txtEmail->addError(BL::getError('EmailMatchesPrevious')); |
||
253 | } |
||
254 | |||
255 | // valid email? |
||
256 | if ($txtEmail->isEmail(BL::getError('EmailIsInvalid'))) { |
||
257 | // email already exists? |
||
258 | if (BackendProfilesModel::existsByEmail($txtEmail->getValue(), $this->id)) { |
||
259 | // set error |
||
260 | $txtEmail->addError(BL::getError('EmailExists')); |
||
261 | } |
||
262 | } |
||
263 | } |
||
264 | |||
265 | // display name filled in? |
||
266 | if ($txtDisplayName->isFilled(BL::getError('DisplayNameIsRequired'))) { |
||
267 | // display name already exists? |
||
268 | if (BackendProfilesModel::existsDisplayName($txtDisplayName->getValue(), $this->id)) { |
||
269 | // set error |
||
270 | $txtDisplayName->addError(BL::getError('DisplayNameExists')); |
||
271 | } |
||
272 | } |
||
273 | |||
274 | // new_password is checked, so verify new password (only if profile should not be notified) |
||
275 | // because then if the password field is empty, it will generate a new password |
||
276 | if ($chkNewPassword->isChecked() && !$this->notifyProfile) { |
||
277 | $txtPassword->isFilled(BL::err('FieldIsRequired')); |
||
278 | $txtPasswordRepeat->isFilled(BL::err('FieldIsRequired')); |
||
279 | |||
280 | // both password fields are filled in and should match |
||
281 | if ($txtPassword->isFilled() && $txtPasswordRepeat->isFilled() |
||
282 | && ($txtPassword->getValue() != $txtPasswordRepeat->getValue())) { |
||
283 | $txtPasswordRepeat->addError(BL::err('PasswordRepeatIsRequired')); |
||
284 | } |
||
285 | } |
||
286 | |||
287 | // one of the bday fields are filled in |
||
288 | if ($ddmDay->isFilled() || $ddmMonth->isFilled() || $ddmYear->isFilled()) { |
||
289 | // valid date? |
||
290 | if (!checkdate($ddmMonth->getValue(), $ddmDay->getValue(), $ddmYear->getValue())) { |
||
291 | // set error |
||
292 | $ddmYear->addError(BL::getError('DateIsInvalid')); |
||
293 | } |
||
294 | } |
||
295 | |||
296 | // no errors? |
||
297 | if ($this->form->isCorrect()) { |
||
298 | // build item |
||
299 | $values = ['email' => $chkNewEmail->isChecked() ? $txtEmail->getValue() : $this->profile['email']]; |
||
300 | $password = BL::lbl('YourExistingPassword'); |
||
301 | |||
302 | // only update if display name changed |
||
303 | if ($txtDisplayName->getValue() != $this->profile['display_name']) { |
||
304 | $values['display_name'] = $txtDisplayName->getValue(); |
||
305 | $values['url'] = BackendProfilesModel::getUrl( |
||
306 | $txtDisplayName->getValue(), |
||
307 | $this->id |
||
308 | ); |
||
309 | } |
||
310 | |||
311 | // new password filled in? |
||
312 | if ($chkNewPassword->isChecked()) { |
||
313 | // new password filled in? otherwise generate a password |
||
314 | $password = ($txtPassword->isFilled()) ? |
||
315 | $txtPassword->getValue() : BackendModel::generatePassword(8); |
||
316 | |||
317 | // build password |
||
318 | $values['password'] = BackendProfilesModel::encryptPassword($password); |
||
319 | } |
||
320 | |||
321 | // update values |
||
322 | BackendProfilesModel::update($this->id, $values); |
||
323 | |||
324 | // birthday is filled in |
||
325 | if ($ddmYear->isFilled()) { |
||
326 | // mysql format |
||
327 | $birthDate = $ddmYear->getValue() . '-'; |
||
328 | $birthDate .= str_pad($ddmMonth->getValue(), 2, '0', STR_PAD_LEFT) . '-'; |
||
329 | $birthDate .= str_pad($ddmDay->getValue(), 2, '0', STR_PAD_LEFT); |
||
330 | } else { |
||
331 | $birthDate = null; |
||
332 | } |
||
333 | |||
334 | // update settings |
||
335 | BackendProfilesModel::setSetting($this->id, 'first_name', $txtFirstName->getValue()); |
||
336 | BackendProfilesModel::setSetting($this->id, 'last_name', $txtLastName->getValue()); |
||
337 | BackendProfilesModel::setSetting($this->id, 'gender', $ddmGender->getValue()); |
||
338 | BackendProfilesModel::setSetting($this->id, 'birth_date', $birthDate); |
||
339 | BackendProfilesModel::setSetting($this->id, 'city', $txtCity->getValue()); |
||
340 | BackendProfilesModel::setSetting($this->id, 'country', $ddmCountry->getValue()); |
||
341 | BackendProfilesModel::setSetting($this->id, 'about', $txtAbout->getValue()); |
||
342 | |||
343 | $displayName = $values['display_name'] ?? $this->profile['display_name']; |
||
344 | |||
345 | $redirectUrl = BackendModel::createUrlForAction('Index') . |
||
346 | '&var=' . rawurlencode($values['email']) . |
||
347 | '&highlight=row-' . $this->id . |
||
348 | '&var=' . rawurlencode($displayName) . |
||
349 | '&report=' |
||
350 | ; |
||
351 | |||
352 | if ($this->notifyProfile && |
||
353 | ($chkNewEmail->isChecked() || $chkNewPassword->isChecked()) |
||
354 | ) { |
||
355 | // notify values |
||
356 | $notifyValues = array_merge( |
||
357 | $values, |
||
358 | [ |
||
359 | 'id' => $this->id, |
||
360 | 'first_name' => $txtFirstName->getValue(), |
||
361 | 'last_name' => $txtLastName->getValue(), |
||
362 | 'unencrypted_password' => $password, |
||
363 | ] |
||
364 | ); |
||
365 | |||
366 | if (!isset($notifyValues['display_name'])) { |
||
367 | $notifyValues['display_name'] = $this->profile['display_name']; |
||
368 | } |
||
369 | |||
370 | BackendProfilesModel::notifyProfile($notifyValues, true); |
||
371 | |||
372 | $redirectUrl .= 'saved-and-notified'; |
||
373 | } else { |
||
374 | $redirectUrl .= 'saved'; |
||
375 | } |
||
376 | |||
377 | // everything is saved, so redirect to the overview |
||
378 | $this->redirect($redirectUrl); |
||
379 | } |
||
380 | } |
||
381 | } |
||
382 | |||
383 | private function loadDeleteForm(): void |
||
384 | { |
||
385 | $deleteForm = $this->createForm( |
||
386 | DeleteType::class, |
||
387 | ['id' => $this->profile['id']], |
||
388 | ['module' => $this->getModule()] |
||
389 | ); |
||
390 | $this->template->assign('deleteForm', $deleteForm->createView()); |
||
391 | } |
||
392 | } |
||
393 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.