Passed
Push — master ( 34c1c4...4da024 )
by jelmer
05:21 queued 15s
created

Edit::loadForm()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 93
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 62
nc 2
nop 0
dl 0
loc 93
ccs 0
cts 66
cp 0
crap 6
rs 8.829
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
            ->setAttribute('autocomplete', 'email')
105
        ;
106
        $this->form->addCheckbox('new_password');
107
        $this->form
108
            ->addPassword('password')
109
            ->setAttribute('autocomplete', 'new-password')
110
        ;
111
        $this->form
112
            ->addPassword('password_repeat')
113
            ->setAttribute('autocomplete', 'new-password')
114
        ;
115
        $this->form
116
            ->addText('display_name', $this->profile['display_name'])
117
            ->setAttribute('autocomplete', 'username')
118
            ->makeRequired()
119
        ;
120
        $this->form
121
            ->addText('first_name', BackendProfilesModel::getSetting($this->id, 'first_name'))
122
            ->setAttribute('autocomplete', 'given-name')
123
        ;
124
        $this->form
125
            ->addText('last_name', BackendProfilesModel::getSetting($this->id, 'last_name'))
126
            ->setAttribute('autocomplete', 'family-name')
127
        ;
128
        $this->form
129
            ->addText('city', BackendProfilesModel::getSetting($this->id, 'city'))
130
            ->setAttribute('autocomplete', 'address-level2')
131
        ;
132
        $this->form
133
            ->addDropdown('gender', $genderValues, BackendProfilesModel::getSetting($this->id, 'gender'))
134
            ->setAttribute('autocomplete', 'sex')
135
        ;
136
        $this->form
137
            ->addDropdown('day', array_combine($days, $days), $birthDay)
138
            ->setAttribute('autocomplete', 'bday-day')
139
        ;
140
        $this->form
141
            ->addDropdown('month', $months, $birthMonth)
142
            ->setAttribute('autocomplete', 'bday-month')
143
        ;
144
        $this->form
145
            ->addDropdown('year', array_combine($years, $years), (int) $birthYear)
146
            ->setAttribute('autocomplete', 'bday-year')
147
        ;
148
        $this->form
149
            ->addDropdown(
150
                'country',
151
                Intl::getRegionBundle()->getCountryNames(BL::getInterfaceLanguage()),
0 ignored issues
show
Deprecated Code introduced by
The function Symfony\Component\Intl\Intl::getRegionBundle() has been deprecated: since Symfony 4.3, to be removed in 5.0. Use {@see Countries} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

151
                /** @scrutinizer ignore-deprecated */ Intl::getRegionBundle()->getCountryNames(BL::getInterfaceLanguage()),

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.

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