FormDisplay::displayFieldInput()   F
last analyzed

Complexity

Conditions 31
Paths 2584

Size

Total Lines 138
Code Lines 96

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 992

Importance

Changes 0
Metric Value
cc 31
eloc 96
nc 2584
nop 7
dl 0
loc 138
ccs 0
cts 96
cp 0
crap 992
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
 * Form management class, displays and processes forms
4
 *
5
 * Explanation of used terms:
6
 * o work_path - original field path, eg. Servers/4/verbose
7
 * o system_path - work_path modified so that it points to the first server,
8
 *                 eg. Servers/1/verbose
9
 * o translated_path - work_path modified for HTML field name, a path with
10
 *                     slashes changed to hyphens, eg. Servers-4-verbose
11
 */
12
13
declare(strict_types=1);
14
15
namespace PhpMyAdmin\Config;
16
17
use PhpMyAdmin\Config;
18
use PhpMyAdmin\Config\Forms\User\UserFormList;
19
use PhpMyAdmin\Html\MySQLDocumentation;
20
use PhpMyAdmin\Sanitize;
21
use PhpMyAdmin\Util;
22
23
use function __;
24
use function array_flip;
25
use function array_keys;
26
use function array_search;
27
use function explode;
28
use function function_exists;
29
use function gettype;
30
use function implode;
31
use function is_array;
32
use function is_bool;
33
use function is_numeric;
34
use function mb_substr;
35
use function preg_match;
36
use function settype;
37
use function sprintf;
38
use function str_ends_with;
39
use function str_replace;
40
use function str_starts_with;
41
use function trigger_error;
42
use function trim;
43
44
use const E_USER_WARNING;
45
46
/**
47
 * Form management class, displays and processes forms
48
 */
49
class FormDisplay
50
{
51
    /**
52
     * Form list
53
     *
54
     * @var array<string, Form>
55
     */
56
    private array $forms = [];
57
58
    /**
59
     * Stores validation errors, indexed by paths
60
     * [ Form_name ] is an array of form errors
61
     * [path] is a string storing error associated with single field
62
     *
63
     * @var mixed[]
64
     */
65
    private array $errors = [];
66
67
    /**
68
     * Paths changed so that they can be used as HTML ids, indexed by paths
69
     *
70
     * @var mixed[]
71
     */
72
    private array $translatedPaths = [];
73
74
    /**
75
     * Server paths change indexes so we define maps from current server
76
     * path to the first one, indexed by work path
77
     *
78
     * @var mixed[]
79
     */
80
    private array $systemPaths = [];
81
82
    /**
83
     * Tells whether forms have been validated
84
     */
85
    private bool $isValidated = true;
86
87
    /**
88
     * Dictionary with user preferences keys
89
     */
90
    private array|null $userprefsKeys = null;
91
92
    /**
93
     * Dictionary with disallowed user preferences keys
94
     *
95
     * @var mixed[]
96
     */
97
    private array $userprefsDisallow = [];
98
99
    private FormDisplayTemplate $formDisplayTemplate;
100
101
    private bool $isSetupScript;
102
103 40
    public function __construct(private ConfigFile $configFile)
104
    {
105 40
        $this->formDisplayTemplate = new FormDisplayTemplate(Config::getInstance());
0 ignored issues
show
Deprecated Code introduced by
The function PhpMyAdmin\Config::getInstance() has been deprecated: Use dependency injection instead. ( Ignorable by Annotation )

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

105
        $this->formDisplayTemplate = new FormDisplayTemplate(/** @scrutinizer ignore-deprecated */ Config::getInstance());

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...
106 40
        $this->isSetupScript = Sanitize::isSetup();
107
        // initialize validators
108 40
        Validator::getValidators($this->configFile);
109
    }
110
111
    /**
112
     * Returns {@link ConfigFile} associated with this instance
113
     */
114
    public function getConfigFile(): ConfigFile
115
    {
116
        return $this->configFile;
117
    }
118
119
    /**
120
     * Registers form in form manager
121
     *
122
     * @param string   $formName Form name
123
     * @param mixed[]  $form     Form data
124
     * @param int|null $serverId 0 if new server, validation; >= 1 if editing a server
125
     */
126 4
    public function registerForm(string $formName, array $form, int|null $serverId = null): void
127
    {
128 4
        $this->forms[$formName] = new Form($formName, $form, $this->configFile, $serverId);
129 4
        $this->isValidated = false;
130 4
        foreach ($this->forms[$formName]->fields as $path) {
131 4
            $workPath = $serverId === null
132
                ? $path
133 4
                : str_replace('Servers/1/', 'Servers/' . $serverId . '/', $path);
134 4
            $this->systemPaths[$workPath] = $path;
135 4
            $this->translatedPaths[$workPath] = str_replace('/', '-', $workPath);
136
        }
137
    }
138
139
    /**
140
     * Processes forms, returns true on successful save
141
     *
142
     * @param bool $allowPartialSave allows for partial form saving
143
     *                               on failed validation
144
     * @param bool $checkFormSubmit  whether check for $_POST['submit_save']
145
     */
146 4
    public function process(bool $allowPartialSave = true, bool $checkFormSubmit = true): bool
147
    {
148 4
        if ($checkFormSubmit && ! isset($_POST['submit_save'])) {
149 4
            return false;
150
        }
151
152
        // save forms
153 4
        if ($this->forms !== []) {
154 4
            return $this->save(array_keys($this->forms), $allowPartialSave);
155
        }
156
157 4
        return false;
158
    }
159
160
    /**
161
     * Runs validation for all registered forms
162
     */
163 8
    private function validate(): void
164
    {
165 8
        if ($this->isValidated) {
166 8
            return;
167
        }
168
169
        $paths = [];
170
        $values = [];
171
        foreach ($this->forms as $form) {
172
            $paths[] = $form->name;
173
            // collect values and paths
174
            foreach ($form->fields as $path) {
175
                $workPath = array_search($path, $this->systemPaths);
176
                $values[$path] = $this->configFile->getValue($workPath);
177
                $paths[] = $path;
178
            }
179
        }
180
181
        // run validation
182
        $errors = Validator::validate($this->configFile, $paths, $values, false);
183
184
        // change error keys from canonical paths to work paths
185
        if (is_array($errors) && $errors !== []) {
186
            $this->errors = [];
187
            foreach ($errors as $path => $errorList) {
188
                $workPath = array_search($path, $this->systemPaths);
189
                // field error
190
                if (! $workPath) {
191
                    // form error, fix path
192
                    $workPath = $path;
193
                }
194
195
                $this->errors[$workPath] = $errorList;
196
            }
197
        }
198
199
        $this->isValidated = true;
200
    }
201
202
    /**
203
     * Outputs HTML for forms
204
     *
205
     * @param bool         $showButtons  whether show submit and reset button
206
     * @param string|null  $formAction   action attribute for the form
207
     * @param mixed[]|null $hiddenFields array of form hidden fields (key: field
208
     *                                 name)
209
     *
210
     * @return string HTML for forms
211
     */
212
    public function getDisplay(
213
        bool $showButtons = true,
214
        string|null $formAction = null,
215
        array|null $hiddenFields = null,
216
    ): string {
217
        $js = [];
218
        $jsDefault = [];
219
220
        /**
221
         * We do validation on page refresh when browser remembers field values,
222
         * add a field with known value which will be used for checks.
223
         */
224
        static $hasCheckPageRefresh = false;
225
        if (! $hasCheckPageRefresh) {
226
            $hasCheckPageRefresh = true;
227
        }
228
229
        $tabs = [];
230
        foreach ($this->forms as $form) {
231
            $tabs[$form->name] = Descriptions::get('Form_' . $form->name);
232
        }
233
234
        // validate only when we aren't displaying a "new server" form
235
        $isNewServer = false;
236
        foreach ($this->forms as $form) {
237
            if ($form->index === 0) {
238
                $isNewServer = true;
239
                break;
240
            }
241
        }
242
243
        if (! $isNewServer) {
244
            $this->validate();
245
        }
246
247
        // user preferences
248
        $this->loadUserprefsInfo();
249
250
        $validators = Validator::getValidators($this->configFile);
251
        $forms = [];
252
253
        foreach ($this->forms as $key => $form) {
254
            $this->formDisplayTemplate->group = 0;
255
            $forms[$key] = [
256
                'name' => $form->name,
257
                'descriptions' => [
258
                    'name' => Descriptions::get('Form_' . $form->name),
259
                    'desc' => Descriptions::get('Form_' . $form->name, 'desc'),
260
                ],
261
                'errors' => $this->errors[$form->name] ?? null,
262
                'fields_html' => '',
263
            ];
264
265
            foreach ($form->fields as $field => $path) {
266
                $workPath = array_search($path, $this->systemPaths);
267
                $translatedPath = $this->translatedPaths[$workPath];
268
                // always true/false for user preferences display
269
                // otherwise null
270
                $userPrefsAllow = isset($this->userprefsKeys[$path])
271
                    ? ! isset($this->userprefsDisallow[$path])
272
                    : null;
273
                // display input
274
                $forms[$key]['fields_html'] .= $this->displayFieldInput(
275
                    $form,
276
                    $field,
277
                    $path,
278
                    $workPath,
279
                    $translatedPath,
280
                    $userPrefsAllow,
281
                    $jsDefault,
282
                );
283
                // register JS validators for this field
284
                if (! isset($validators[$path])) {
285
                    continue;
286
                }
287
288
                $this->formDisplayTemplate->addJsValidate($translatedPath, $validators[$path], $js);
289
            }
290
        }
291
292
        return $this->formDisplayTemplate->display([
293
            'action' => $formAction,
294
            'has_check_page_refresh' => $hasCheckPageRefresh,
295
            'hidden_fields' => (array) $hiddenFields,
296
            'tabs' => $tabs,
297
            'forms' => $forms,
298
            'show_buttons' => $showButtons,
299
            'js_array' => $js,
300
            'js_default' => $jsDefault,
301
        ]);
302
    }
303
304
    /**
305
     * Prepares data for input field display and outputs HTML code
306
     *
307
     * @param string    $field          field name as it appears in $form
308
     * @param string    $systemPath     field path, eg. Servers/1/verbose
309
     * @param string    $workPath       work path, eg. Servers/4/verbose
310
     * @param string    $translatedPath work path changed so that it can be
311
     *                                  used as XHTML id
312
     *                                  besides the input field
313
     * @param bool|null $userPrefsAllow whether user preferences are enabled
314
     *                                  for this field (null - no support,
315
     *                                  true/false - enabled/disabled)
316
     * @param mixed[]   $jsDefault      array which stores JavaScript code
317
     *                                to be displayed
318
     *
319
     * @return string|null HTML for input field
320
     */
321
    private function displayFieldInput(
322
        Form $form,
323
        string $field,
324
        string $systemPath,
325
        string $workPath,
326
        string $translatedPath,
327
        bool|null $userPrefsAllow,
328
        array &$jsDefault,
329
    ): string|null {
330
        $name = Descriptions::get($systemPath);
331
        $description = Descriptions::get($systemPath, 'desc');
332
333
        $value = $this->configFile->get($workPath);
334
        $valueDefault = $this->configFile->getDefault($systemPath);
335
        $valueIsDefault = false;
336
        if ($value === null || $value === $valueDefault) {
337
            $value = $valueDefault;
338
            $valueIsDefault = true;
339
        }
340
341
        $opts = [
342
            'doc' => $this->getDocLink($systemPath),
343
            'show_restore_default' => true,
344
            'userprefs_allow' => $userPrefsAllow,
345
            'userprefs_comment' => Descriptions::get($systemPath, 'cmt'),
346
        ];
347
        if (isset($form->default[$systemPath])) {
348
            $opts['setvalue'] = (string) $form->default[$systemPath];
349
        }
350
351
        if (isset($this->errors[$workPath])) {
352
            $opts['errors'] = $this->errors[$workPath];
353
        }
354
355
        $type = '';
356
        switch ($form->getOptionType($field)) {
357
            case 'string':
358
                $type = 'text';
359
                break;
360
            case 'short_string':
361
                $type = 'short_text';
362
                break;
363
            case 'double':
364
            case 'integer':
365
                $type = 'number_text';
366
                break;
367
            case 'boolean':
368
                $type = 'checkbox';
369
                break;
370
            case 'select':
371
                $type = 'select';
372
                $opts['values'] = $form->getOptionValueList($form->fields[$field]);
373
                break;
374
            case 'array':
375
                $type = 'list';
376
                $value = (array) $value;
377
                $valueDefault = (array) $valueDefault;
378
                break;
379
            case 'group':
380
                // :group:end is changed to :group:end:{unique id} in Form class
381
                $htmlOutput = '';
382
                if (mb_substr($field, 7, 4) !== 'end:') {
383
                    $htmlOutput .= $this->formDisplayTemplate->displayGroupHeader(
384
                        mb_substr($field, 7),
385
                    );
386
                } else {
387
                    $this->formDisplayTemplate->displayGroupFooter();
388
                }
389
390
                return $htmlOutput;
391
392
            case 'NULL':
393
                trigger_error('Field ' . $systemPath . ' has no type', E_USER_WARNING);
394
395
                return null;
396
        }
397
398
        // detect password fields
399
        if (
400
            $type === 'text'
401
            && (str_ends_with($translatedPath, '-password')
402
               || str_ends_with($translatedPath, 'pass')
403
               || str_ends_with($translatedPath, 'Pass'))
404
        ) {
405
            $type = 'password';
406
        }
407
408
        // TrustedProxies requires changes before displaying
409
        if ($systemPath === 'TrustedProxies') {
410
            foreach ($value as $ip => &$v) {
411
                if (preg_match('/^-\d+$/', $ip)) {
412
                    continue;
413
                }
414
415
                $v = $ip . ': ' . $v;
416
            }
417
        }
418
419
        $this->setComments($systemPath, $opts);
420
421
        // send default value to form's JS
422
        $jsLine = '';
423
        switch ($type) {
424
            case 'text':
425
            case 'short_text':
426
            case 'number_text':
427
            case 'password':
428
                $jsLine = (string) $valueDefault;
429
                break;
430
            case 'checkbox':
431
                $jsLine = (bool) $valueDefault;
432
                break;
433
            case 'select':
434
                $valueDefaultJs = is_bool($valueDefault)
435
                ? (int) $valueDefault
436
                : $valueDefault;
437
                $jsLine = (array) $valueDefaultJs;
438
                break;
439
            case 'list':
440
                $val = $valueDefault;
441
                if (isset($val['wrapper_params'])) {
442
                    unset($val['wrapper_params']);
443
                }
444
445
                $jsLine = implode("\n", $val);
446
                break;
447
        }
448
449
        $jsDefault[$translatedPath] = $jsLine;
450
451
        return $this->formDisplayTemplate->displayInput(
452
            $translatedPath,
453
            $name,
454
            $type,
455
            $value,
456
            $description,
457
            $valueIsDefault,
458
            $opts,
459
        );
460
    }
461
462
    /**
463
     * Displays errors
464
     *
465
     * @return string HTML for errors
466
     */
467 4
    public function displayErrors(): string
468
    {
469 4
        $this->validate();
470
471 4
        $htmlOutput = '';
472
473 4
        foreach ($this->errors as $systemPath => $errorList) {
474 4
            if (isset($this->systemPaths[$systemPath])) {
475 4
                $name = Descriptions::get($this->systemPaths[$systemPath]);
476
            } else {
477 4
                $name = Descriptions::get('Form_' . $systemPath);
478
            }
479
480 4
            $htmlOutput .= $this->formDisplayTemplate->displayErrors($name, $errorList);
481
        }
482
483 4
        return $htmlOutput;
484
    }
485
486
    /**
487
     * Reverts erroneous fields to their default values
488
     */
489 4
    public function fixErrors(): void
490
    {
491 4
        $this->validate();
492 4
        if ($this->errors === []) {
493 4
            return;
494
        }
495
496 4
        foreach (array_keys($this->errors) as $workPath) {
497 4
            if (! isset($this->systemPaths[$workPath])) {
498 4
                continue;
499
            }
500
501 4
            $canonicalPath = $this->systemPaths[$workPath];
502 4
            $this->configFile->set($workPath, $this->configFile->getDefault($canonicalPath));
503
        }
504
    }
505
506
    /**
507
     * Validates select field and casts $value to correct type
508
     *
509
     * @param string|bool $value   Current value
510
     * @param mixed[]     $allowed List of allowed values
511
     */
512 4
    private function validateSelect(string|bool &$value, array $allowed): bool
513
    {
514 4
        $valueCmp = is_bool($value)
515
            ? (int) $value
516 4
            : $value;
517 4
        foreach (array_keys($allowed) as $vk) {
518
            // equality comparison only if both values are numeric or not numeric
519
            // (allows to skip 0 == 'string' equalling to true)
520
            // or identity (for string-string)
521 4
            if (! ($vk == $value && ! (is_numeric($valueCmp) xor is_numeric($vk))) && $vk !== $value) {
522 4
                continue;
523
            }
524
525
            // keep boolean value as boolean
526 4
            if (! is_bool($value)) {
527
                // phpcs:ignore Generic.PHP.ForbiddenFunctions
528 4
                settype($value, gettype($vk));
529
            }
530
531 4
            return true;
532
        }
533
534 4
        return false;
535
    }
536
537
    /**
538
     * Validates and saves form data to session
539
     *
540
     * @param string[] $forms            List of form names.
541
     * @param bool     $allowPartialSave Allows for partial form saving on failed validation.
542
     */
543
    public function save(array $forms, bool $allowPartialSave = true): bool
544
    {
545
        $result = true;
546
        $values = [];
547
        $toSave = [];
548
        $isSetupScript = Config::getInstance()->get('is_setup');
0 ignored issues
show
Deprecated Code introduced by
The function PhpMyAdmin\Config::getInstance() has been deprecated: Use dependency injection instead. ( Ignorable by Annotation )

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

548
        $isSetupScript = /** @scrutinizer ignore-deprecated */ Config::getInstance()->get('is_setup');

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...
549
        if ($isSetupScript) {
550
            $this->loadUserprefsInfo();
551
        }
552
553
        $this->errors = [];
554
        foreach ($forms as $formName) {
555
            if (! isset($this->forms[$formName])) {
556
                continue;
557
            }
558
559
            $form = $this->forms[$formName];
560
            // get current server id
561
            $changeIndex = $form->index === 0
562
                ? $this->configFile->getServerCount() + 1
563
                : false;
564
            // grab POST values
565
            foreach ($form->fields as $field => $systemPath) {
566
                $workPath = array_search($systemPath, $this->systemPaths);
567
                $key = $this->translatedPaths[$workPath];
568
                $type = (string) $form->getOptionType($field);
569
570
                // skip groups
571
                if ($type === 'group') {
572
                    continue;
573
                }
574
575
                // ensure the value is set
576
                if (! isset($_POST[$key])) {
577
                    // checkboxes aren't set by browsers if they're off
578
                    if ($type !== 'boolean') {
579
                        $this->errors[$form->name][] = sprintf(
580
                            __('Missing data for %s'),
581
                            '<i>' . Descriptions::get($systemPath) . '</i>',
582
                        );
583
                        $result = false;
584
                        continue;
585
                    }
586
587
                    $_POST[$key] = false;
588
                }
589
590
                // user preferences allow/disallow
591
                if ($isSetupScript && isset($this->userprefsKeys[$systemPath])) {
592
                    if (isset($this->userprefsDisallow[$systemPath], $_POST[$key . '-userprefs-allow'])) {
593
                        unset($this->userprefsDisallow[$systemPath]);
594
                    } elseif (! isset($_POST[$key . '-userprefs-allow'])) {
595
                        $this->userprefsDisallow[$systemPath] = true;
596
                    }
597
                }
598
599
                // cast variables to correct type
600
                switch ($type) {
601
                    case 'double':
602
                        $_POST[$key] = Util::requestString($_POST[$key]);
603
                        $_POST[$key] = (float) $_POST[$key];
604
                        break;
605
                    case 'boolean':
606
                    case 'integer':
607
                        if ($_POST[$key] !== '') {
608
                            $_POST[$key] = Util::requestString($_POST[$key]);
609
                            // phpcs:ignore Generic.PHP.ForbiddenFunctions
610
                            settype($_POST[$key], $type);
611
                        }
612
613
                        break;
614
                    case 'select':
615
                        $successfullyValidated = $this->validateSelect(
616
                            $_POST[$key],
617
                            $form->getOptionValueList($systemPath),
618
                        );
619
                        if (! $successfullyValidated) {
620
                            $this->errors[$workPath][] = __('Incorrect value!');
621
                            $result = false;
622
                            // "continue" for the $form->fields foreach-loop
623
                            continue 2;
624
                        }
625
626
                        break;
627
                    case 'string':
628
                    case 'short_string':
629
                        $_POST[$key] = Util::requestString($_POST[$key]);
630
                        break;
631
                    case 'array':
632
                        // eliminate empty values and ensure we have an array
633
                        $postValues = is_array($_POST[$key])
634
                        ? $_POST[$key]
635
                        : explode("\n", $_POST[$key]);
636
                        $_POST[$key] = [];
637
                        $this->fillPostArrayParameters($postValues, $key);
638
                        break;
639
                }
640
641
                // now we have value with proper type
642
                $values[$systemPath] = $_POST[$key];
643
                if ($changeIndex !== false) {
644
                    $workPath = str_replace(
645
                        'Servers/' . $form->index . '/',
646
                        'Servers/' . $changeIndex . '/',
647
                        $workPath,
648
                    );
649
                }
650
651
                $toSave[$workPath] = $systemPath;
652
            }
653
        }
654
655
        // save forms
656
        if (! $allowPartialSave && $this->errors !== []) {
657
            // don't look for non-critical errors
658
            $this->validate();
659
660
            return $result;
661
        }
662
663
        foreach ($toSave as $workPath => $path) {
664
            // TrustedProxies requires changes before saving
665
            if ($path === 'TrustedProxies') {
666
                $proxies = [];
667
                $i = 0;
668
                foreach ($values[$path] as $value) {
669
                    $matches = [];
670
                    $match = preg_match('/^(.+):(?:[ ]?)(\\w+)$/', $value, $matches);
671
                    if ($match) {
672
                        // correct 'IP: HTTP header' pair
673
                        $ip = trim($matches[1]);
674
                        $proxies[$ip] = trim($matches[2]);
675
                    } else {
676
                        // save also incorrect values
677
                        $proxies['-' . $i] = $value;
678
                        $i++;
679
                    }
680
                }
681
682
                $values[$path] = $proxies;
683
            }
684
685
            $this->configFile->set($workPath, $values[$path], $path);
686
        }
687
688
        if ($isSetupScript) {
689
            $this->configFile->set(
690
                'UserprefsDisallow',
691
                array_keys($this->userprefsDisallow),
692
            );
693
        }
694
695
        // don't look for non-critical errors
696
        $this->validate();
697
698
        return $result;
699
    }
700
701
    /**
702
     * Tells whether form validation failed
703
     */
704 4
    public function hasErrors(): bool
705
    {
706 4
        return $this->errors !== [];
707
    }
708
709
    /**
710
     * Returns link to documentation
711
     *
712
     * @param string $path Path to documentation
713
     */
714 4
    public function getDocLink(string $path): string
715
    {
716 4
        if (str_starts_with($path, 'Import') || str_starts_with($path, 'Export')) {
717 4
            return '';
718
        }
719
720 4
        return MySQLDocumentation::getDocumentationLink(
721 4
            'config',
722 4
            'cfg_' . $this->getOptName($path),
723 4
            $this->isSetupScript ? '../' : './',
724 4
        );
725
    }
726
727
    /**
728
     * Changes path so it can be used in URLs
729
     *
730
     * @param string $path Path
731
     */
732 8
    private function getOptName(string $path): string
733
    {
734 8
        return str_replace(['Servers/1/', '/'], ['Servers/', '_'], $path);
735
    }
736
737
    /**
738
     * Fills out {@link userprefs_keys} and {@link userprefs_disallow}
739
     */
740 4
    private function loadUserprefsInfo(): void
741
    {
742 4
        if ($this->userprefsKeys !== null) {
743
            return;
744
        }
745
746 4
        $this->userprefsKeys = array_flip(UserFormList::getFields());
747
        // read real config for user preferences display
748 4
        $config = Config::getInstance();
0 ignored issues
show
Deprecated Code introduced by
The function PhpMyAdmin\Config::getInstance() has been deprecated: Use dependency injection instead. ( Ignorable by Annotation )

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

748
        $config = /** @scrutinizer ignore-deprecated */ Config::getInstance();

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...
749 4
        $userPrefsDisallow = $config->get('is_setup')
750
            ? $this->configFile->get('UserprefsDisallow', [])
751 4
            : $config->settings['UserprefsDisallow'];
752 4
        $this->userprefsDisallow = array_flip($userPrefsDisallow ?? []);
753
    }
754
755
    /**
756
     * Sets field comments and warnings based on current environment
757
     *
758
     * @param string  $systemPath Path to settings
759
     * @param mixed[] $opts       Chosen options
760
     */
761 4
    private function setComments(string $systemPath, array &$opts): void
762
    {
763
        // RecodingEngine - mark unavailable types
764 4
        if ($systemPath === 'RecodingEngine') {
765 4
            $comment = '';
766 4
            if (! function_exists('iconv')) {
767
                $opts['values']['iconv'] .= ' (' . __('unavailable') . ')';
768
                $comment = sprintf(
769
                    __('"%s" requires %s extension'),
770
                    'iconv',
771
                    'iconv',
772
                );
773
            }
774
775
            /* mbstring is always there thanks to polyfill */
776 4
            $opts['comment'] = $comment;
777 4
            $opts['comment_warning'] = true;
778
        }
779
780
        // ZipDump, GZipDump, BZipDump - check function availability
781 4
        if ($systemPath === 'ZipDump' || $systemPath === 'GZipDump' || $systemPath === 'BZipDump') {
782 4
            $comment = '';
783 4
            $funcs = [
784 4
                'ZipDump' => ['zip_open', 'gzcompress'],
785 4
                'GZipDump' => ['gzopen', 'gzencode'],
786 4
                'BZipDump' => ['bzopen', 'bzcompress'],
787 4
            ];
788 4
            if (! function_exists($funcs[$systemPath][0])) {
789
                $comment = sprintf(
790
                    __(
791
                        'Compressed import will not work due to missing function %s.',
792
                    ),
793
                    $funcs[$systemPath][0],
794
                );
795
            }
796
797 4
            if (! function_exists($funcs[$systemPath][1])) {
798
                $comment .= ($comment !== '' ? '; ' : '') . sprintf(
799
                    __(
800
                        'Compressed export will not work due to missing function %s.',
801
                    ),
802
                    $funcs[$systemPath][1],
803
                );
804
            }
805
806 4
            $opts['comment'] = $comment;
807 4
            $opts['comment_warning'] = true;
808
        }
809
810 4
        $config = Config::getInstance();
0 ignored issues
show
Deprecated Code introduced by
The function PhpMyAdmin\Config::getInstance() has been deprecated: Use dependency injection instead. ( Ignorable by Annotation )

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

810
        $config = /** @scrutinizer ignore-deprecated */ Config::getInstance();

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...
811 4
        if ($config->get('is_setup')) {
812
            return;
813
        }
814
815 4
        if ($systemPath !== 'MaxDbList' && $systemPath !== 'MaxTableList' && $systemPath !== 'QueryHistoryMax') {
816 4
            return;
817
        }
818
819 4
        $opts['comment'] = sprintf(
820 4
            __('maximum %s'),
821 4
            $config->settings[$systemPath],
822 4
        );
823
    }
824
825
    /**
826
     * Copy items of an array to $_POST variable
827
     *
828
     * @param mixed[] $postValues List of parameters
829
     * @param string  $key        Array key
830
     */
831
    private function fillPostArrayParameters(array $postValues, string $key): void
832
    {
833
        foreach ($postValues as $v) {
834
            $v = Util::requestString($v);
835
            if ($v === '') {
836
                continue;
837
            }
838
839
            $_POST[$key][] = $v;
840
        }
841
    }
842
}
843