FormAdmin   F
last analyzed

Complexity

Total Complexity 108

Size/Duplication

Total Lines 508
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 258
dl 0
loc 508
rs 2
c 0
b 0
f 0
wmc 108

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
F select_menu() 0 106 30
F selectLanguage() 0 105 37
A select_timezone() 0 41 4
D select_menu_families() 0 66 18
B selectTypeOfFields() 0 26 8
B select_paper_format() 0 57 10

How to fix   Complexity   

Complex Class

Complex classes like FormAdmin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormAdmin, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* Copyright (C) 2004-2014  Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2005-2011  Regis Houssin               <[email protected]>
5
 * Copyright (C) 2007       Patrick Raguin 		        <[email protected]>
6
 * Copyright (C) 2024       Frédéric France             <[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
namespace Dolibarr\Code\Core\Classes;
24
25
use DoliDB;
26
27
/**
28
 *      \file       htdocs/core/class/html.formadmin.class.php
29
 *      \ingroup    core
30
 *      \brief      File of class for html functions for admin pages
31
 */
32
33
34
/**
35
 *      Class to generate html code for admin pages
36
 */
37
class FormAdmin
38
{
39
    /**
40
     * @var DoliDB Database handler.
41
     */
42
    public $db;
43
44
    /**
45
     * @var string error message
46
     */
47
    public $error;
48
49
50
    /**
51
     *  Constructor
52
     *
53
     * @param DoliDB|null $db Database handler
54
     */
55
    public function __construct($db)
56
    {
57
        $this->db = $db;
58
    }
59
60
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
61
62
    /**
63
     *  Return html select list with available languages (key='en_US', value='United States' for example)
64
     *
65
     * @param string|array $selected Language pre-selected. Can be an array if $multiselect is 1.
66
     * @param string $htmlname Name of HTML select
67
     * @param int $showauto Show 'auto' choice
68
     * @param array $filter Array of keys to exclude in list (opposite of $onlykeys)
69
     * @param int|string $showempty '1'=Add empty value or 'string to show'
70
     * @param int $showwarning Show a warning if language is not complete
71
     * @param int $disabled Disable edit of select
72
     * @param string $morecss Add more css styles
73
     * @param int $showcode 1=Add language code into label at beginning, 2=Add language code into label at end
74
     * @param int $forcecombo Force to use combo box (so no ajax beautify effect)
75
     * @param int $multiselect Make the combo a multiselect
76
     * @param array $onlykeys Array of language keys to restrict list with the following keys (opposite of $filter). Example array('fr', 'es', ...)
77
     * @param int $mainlangonly 1=Show only main languages ('fr_FR' no' fr_BE', 'es_ES' not 'es_MX', ...)
78
     * @return     string                          Return HTML select string with list of languages
79
     */
80
    public static function selectLanguage($selected = '', $htmlname = 'lang_id', $showauto = 0, $filter = array(), $showempty = '', $showwarning = 0, $disabled = 0, $morecss = '', $showcode = 0, $forcecombo = 0, $multiselect = 0, $onlykeys = array(), $mainlangonly = 0)
81
    {
82
        // phpcs:enable
83
        global $langs;
84
85
        if (getDolGlobalString('MAIN_DEFAULT_LANGUAGE_FILTER')) {
86
            if (!is_array($filter)) {
87
                $filter = array();
88
            }
89
            $filter[getDolGlobalString('MAIN_DEFAULT_LANGUAGE_FILTER')] = 1;
90
        }
91
92
        $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 12, 0, $mainlangonly);
93
94
        // If empty value is not allowed and the language to select is not inside the list of available language and we must find
95
        // an alternative of the language code to pre-select (to avoid to have first element in list pre-selected).
96
        if ($selected && empty($showempty)) {
97
            if (!is_array($selected) && !array_key_exists($selected, $langs_available)) {
98
                $tmparray = explode('_', $selected);
99
                if (!empty($tmparray[1])) {
100
                    $selected = getLanguageCodeFromCountryCode($tmparray[1]);
101
                }
102
                if (empty($selected)) {
103
                    $selected = $langs->defaultlang;
104
                }
105
            } else {
106
                // If the preselected value is an array, we do not try to find alternative to preselect
107
            }
108
        }
109
110
        $out = '';
111
112
        $out .= '<select ' . ($multiselect ? 'multiple="multiple" ' : '') . 'class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiselect ? '[]' : '') . '"' . ($disabled ? ' disabled' : '') . '>';
113
        if ($showempty && !$multiselect) {
114
            if (is_numeric($showempty)) {
115
                $out .= '<option value="0"';
116
            } else {
117
                $out .= '<option value="-1"';
118
            }
119
            if ($selected === '') {
120
                $out .= ' selected';
121
            }
122
            $out .= '>';
123
            if ($showempty != '1') {
124
                $out .= $showempty;
125
            } else {
126
                $out .= '&nbsp;';
127
            }
128
            $out .= '</option>';
129
        }
130
        if ($showauto) {
131
            $out .= '<option value="auto"';
132
            if ($selected === 'auto') {
133
                $out .= ' selected';
134
            }
135
            $out .= '>' . $langs->trans("AutoDetectLang") . '</option>';
136
        }
137
138
        asort($langs_available);    // array('XX' => 'Language (Country)', ...)
139
140
        foreach ($langs_available as $key => $value) {
141
            $valuetoshow = $value;
142
            if ($showcode == 1) {
143
                if ($mainlangonly) {
144
                    $valuetoshow = '<span class="opacitymedium">' . preg_replace('/[_-].*$/', '', $key) . '</span> - ' . $value;
145
                } else {
146
                    $valuetoshow = '<span class="opacitymedium">' . $key . '</span> - ' . $value;
147
                }
148
            }
149
            if ($showcode == 2) {
150
                if ($mainlangonly) {
151
                    $valuetoshow = $value . ' <span class="opacitymedium">(' . preg_replace('/[_-].*$/', '', $key) . ')</span>';
152
                } else {
153
                    $valuetoshow = $value . ' <span class="opacitymedium">(' . $key . ')</span>';
154
                }
155
            }
156
157
            $keytouse = $key;
158
            if ($mainlangonly) {
159
                $keytouse = preg_replace('/[_-].*$/', '', $key);
160
            }
161
162
            if ($filter && is_array($filter) && array_key_exists($keytouse, $filter)) {
163
                continue;
164
            }
165
            if ($onlykeys && is_array($onlykeys) && !array_key_exists($keytouse, $onlykeys)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $onlykeys of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
166
                continue;
167
            }
168
169
            $valuetoshow = picto_from_langcode($key, 'class="saturatemedium"') . ' ' . $valuetoshow;
170
            if ((is_string($selected) && (string)$selected == (string)$keytouse) || (is_array($selected) && in_array($keytouse, $selected))) {
171
                $out .= '<option value="' . $keytouse . '" selected data-html="' . dol_escape_htmltag($valuetoshow) . '">' . $valuetoshow . '</option>';
172
            } else {
173
                $out .= '<option value="' . $keytouse . '" data-html="' . dol_escape_htmltag($valuetoshow) . '">' . $valuetoshow . '</option>';
174
            }
175
        }
176
        $out .= '</select>';
177
178
        // Make select dynamic
179
        if (!$forcecombo) {
180
            include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
181
            $out .= ajax_combobox($htmlname);
182
        }
183
184
        return $out;
185
    }
186
187
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
188
189
    /**
190
     *    Return list of available menus (eldy_backoffice, ...)
191
     *
192
     * @param string $selected Preselected menu value
193
     * @param string $htmlname Name of html select
194
     * @param array $dirmenuarray Array of directories to scan
195
     * @param string $moreattrib More attributes on html select tag
196
     * @return   integer|void
197
     */
198
    public function select_menu($selected, $htmlname, $dirmenuarray, $moreattrib = '')
199
    {
200
        // phpcs:enable
201
        global $langs, $conf;
202
203
        // Clean parameters
204
205
206
        // Check parameters
207
        if (!is_array($dirmenuarray)) {
208
            return -1;
209
        }
210
211
        $menuarray = array();
212
        foreach ($conf->file->dol_document_root as $dirroot) {
213
            foreach ($dirmenuarray as $dirtoscan) {
214
                $dir = $dirroot . $dirtoscan;
215
                //print $dir.'<br>';
216
                if (is_dir($dir)) {
217
                    $handle = opendir($dir);
218
                    if (is_resource($handle)) {
219
                        while (($file = readdir($handle)) !== false) {
220
                            if (is_file($dir . "/" . $file) && substr($file, 0, 1) != '.' && substr($file, 0, 3) != 'CVS' && substr($file, 0, 5) != 'index') {
221
                                if (preg_match('/lib\.php$/i', $file)) {
222
                                    continue; // We exclude library files
223
                                }
224
                                if (preg_match('/eldy_(backoffice|frontoffice)\.php$/i', $file)) {
225
                                    continue; // We exclude all menu manager files
226
                                }
227
                                if (preg_match('/auguria_(backoffice|frontoffice)\.php$/i', $file)) {
228
                                    continue; // We exclude all menu manager files
229
                                }
230
                                if (preg_match('/smartphone_(backoffice|frontoffice)\.php$/i', $file)) {
231
                                    continue; // We exclude all menu manager files
232
                                }
233
234
                                $filelib = preg_replace('/\.php$/i', '', $file);
235
                                $prefix = '';
236
                                // 0=Recommended, 1=Experimental, 2=Development, 3=Other
237
                                if (preg_match('/^eldy/i', $file)) {
238
                                    $prefix = '0';
239
                                } elseif (preg_match('/^smartphone/i', $file)) {
240
                                    $prefix = '2';
241
                                } else {
242
                                    $prefix = '3';
243
                                }
244
245
                                $morelabel = '';
246
                                if (preg_match('/^auguria/i', $file)) {
247
                                    $morelabel .= ' <span class="opacitymedium">(' . $langs->trans("Unstable") . ')</span>';
248
                                }
249
                                if ($file == $selected) {
250
                                    $menuarray[$prefix . '_' . $file] = '<option value="' . $file . '" selected data-html="' . dol_escape_htmltag($filelib . $morelabel) . '">' . $filelib . $morelabel;
251
                                    $menuarray[$prefix . '_' . $file] .= '</option>';
252
                                } else {
253
                                    $menuarray[$prefix . '_' . $file] = '<option value="' . $file . '" data-html="' . dol_escape_htmltag($filelib . $morelabel) . '">' . $filelib . $morelabel;
254
                                    $menuarray[$prefix . '_' . $file] .= '</option>';
255
                                }
256
                            }
257
                        }
258
                        closedir($handle);
259
                    }
260
                }
261
            }
262
        }
263
        ksort($menuarray);
264
265
        // Output combo list of menus
266
        print '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
267
        $oldprefix = '';
268
        foreach ($menuarray as $key => $val) {
269
            $tab = explode('_', $key);
270
            $newprefix = $tab[0];
271
272
            if ($newprefix == '1' && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1)) {
273
                continue;
274
            }
275
            if ($newprefix == '2' && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2)) {
276
                continue;
277
            }
278
            if ($newprefix != $oldprefix) { // Add separators
279
                // Affiche titre
280
                print '<option value="-2" disabled>';
281
                if ($newprefix == '0') {
282
                    print '-- ' . $langs->trans("VersionRecommanded") . ' --';
283
                }
284
                if ($newprefix == '1') {
285
                    print '-- ' . $langs->trans("VersionExperimental") . ' --';
286
                }
287
                if ($newprefix == '2') {
288
                    print '-- ' . $langs->trans("VersionDevelopment") . ' --';
289
                }
290
                if ($newprefix == '3') {
291
                    print '-- ' . $langs->trans("Other") . ' --';
292
                }
293
                print '</option>';
294
                $oldprefix = $newprefix;
295
            }
296
297
            print $val . "\n"; // Show menu entry ($val contains the <option> tags
298
        }
299
        print '</select>';
300
301
        print ajax_combobox($htmlname);
302
303
        return;
304
    }
305
306
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
307
308
    /**
309
     *  Return combo list of available menu families
310
     *
311
     * @param string $selected Menu pre-selected
312
     * @param string $htmlname Name of html select
313
     * @param string[] $dirmenuarray Directories to scan
314
     * @return void
315
     */
316
    public function select_menu_families($selected, $htmlname, $dirmenuarray)
317
    {
318
        // phpcs:enable
319
        global $langs, $conf;
320
321
        //$expdevmenu=array('smartphone_backoffice.php','smartphone_frontoffice.php');  // Menu to disable if $conf->global->MAIN_FEATURES_LEVEL is not set
322
        $expdevmenu = array();
323
324
        $menuarray = array();
325
326
        foreach ($dirmenuarray as $dirmenu) {
327
            foreach ($conf->file->dol_document_root as $dirroot) {
328
                $dir = $dirroot . $dirmenu;
329
                if (is_dir($dir)) {
330
                    $handle = opendir($dir);
331
                    if (is_resource($handle)) {
332
                        while (($file = readdir($handle)) !== false) {
333
                            if (is_file($dir . "/" . $file) && substr($file, 0, 1) != '.' && substr($file, 0, 3) != 'CVS') {
334
                                $filelib = preg_replace('/(_backoffice|_frontoffice)?\.php$/i', '', $file);
335
                                if (preg_match('/^index/i', $filelib)) {
336
                                    continue;
337
                                }
338
                                if (preg_match('/^default/i', $filelib)) {
339
                                    continue;
340
                                }
341
                                if (preg_match('/^empty/i', $filelib)) {
342
                                    continue;
343
                                }
344
                                if (preg_match('/\.lib/i', $filelib)) {
345
                                    continue;
346
                                }
347
                                if (getDolGlobalInt('MAIN_FEATURES_LEVEL') == 0 && in_array($file, $expdevmenu)) {
348
                                    continue;
349
                                }
350
351
                                $menuarray[$filelib] = 1;
352
                            }
353
                            $menuarray['all'] = 1;
354
                        }
355
                        closedir($handle);
356
                    }
357
                }
358
            }
359
        }
360
361
        ksort($menuarray);
362
363
        // Show combo list of menu handlers
364
        print '<select class="flat maxwidth150" id="' . $htmlname . '" name="' . $htmlname . '">';
365
        foreach ($menuarray as $key => $val) {
366
            $tab = explode('_', $key);
367
            print '<option value="' . $key . '"';
368
            if ($key == $selected) {
369
                print '	selected';
370
            }
371
            print '>';
372
            if ($key == 'all') {
373
                print $langs->trans("AllMenus");
374
            } else {
375
                print $key;
376
            }
377
            print '</option>' . "\n";
378
        }
379
        print '</select>';
380
381
        print ajax_combobox($htmlname);
382
    }
383
384
385
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
386
387
    /**
388
     *  Return a HTML select list of timezones
389
     *
390
     * @param string $selected Menu pre-selectionnee
391
     * @param string $htmlname Nom de la zone select
392
     * @return void
393
     */
394
    public function select_timezone($selected, $htmlname)
395
    {
396
        // phpcs:enable
397
        print '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
398
        print '<option value="-1">&nbsp;</option>';
399
400
        $arraytz = array(
401
            "Pacific/Midway" => "GMT-11:00",
402
            "Pacific/Fakaofo" => "GMT-10:00",
403
            "America/Anchorage" => "GMT-09:00",
404
            "America/Los_Angeles" => "GMT-08:00",
405
            "America/Dawson_Creek" => "GMT-07:00",
406
            "America/Chicago" => "GMT-06:00",
407
            "America/Bogota" => "GMT-05:00",
408
            "America/Anguilla" => "GMT-04:00",
409
            "America/Araguaina" => "GMT-03:00",
410
            "America/Noronha" => "GMT-02:00",
411
            "Atlantic/Azores" => "GMT-01:00",
412
            "Africa/Abidjan" => "GMT+00:00",
413
            "Europe/Paris" => "GMT+01:00",
414
            "Europe/Helsinki" => "GMT+02:00",
415
            "Europe/Moscow" => "GMT+03:00",
416
            "Asia/Dubai" => "GMT+04:00",
417
            "Asia/Karachi" => "GMT+05:00",
418
            "Indian/Chagos" => "GMT+06:00",
419
            "Asia/Jakarta" => "GMT+07:00",
420
            "Asia/Hong_Kong" => "GMT+08:00",
421
            "Asia/Tokyo" => "GMT+09:00",
422
            "Australia/Sydney" => "GMT+10:00",
423
            "Pacific/Noumea" => "GMT+11:00",
424
            "Pacific/Auckland" => "GMT+12:00",
425
            "Pacific/Enderbury" => "GMT+13:00"
426
        );
427
        foreach ($arraytz as $lib => $gmt) {
428
            print '<option value="' . $lib . '"';
429
            if ($selected == $lib || $selected == $gmt) {
430
                print ' selected';
431
            }
432
            print '>' . $gmt . '</option>' . "\n";
433
        }
434
        print '</select>';
435
    }
436
437
438
439
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
440
441
    /**
442
     *  Return html select list with available languages (key='en_US', value='United States' for example)
443
     *
444
     * @param string $selected Paper format pre-selected
445
     * @param string $htmlname Name of HTML select field
446
     * @param string $filter Value to filter on code
447
     * @param int $showempty Add empty value
448
     * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification)
449
     * @return     string                  Return HTML output
450
     */
451
    public function select_paper_format($selected = '', $htmlname = 'paperformat_id', $filter = '', $showempty = 0, $forcecombo = 0)
452
    {
453
        // phpcs:enable
454
        global $langs;
455
456
        $langs->load("dict");
457
458
        $sql = "SELECT code, label, width, height, unit";
459
        $sql .= " FROM " . $this->db->prefix() . "c_paper_format";
460
        $sql .= " WHERE active=1";
461
        if ($filter) {
462
            $sql .= " AND code LIKE '%" . $this->db->escape($filter) . "%'";
463
        }
464
465
        $paperformat = array();
466
467
        $resql = $this->db->query($sql);
468
        if ($resql) {
469
            $num = $this->db->num_rows($resql);
470
            $i = 0;
471
            while ($i < $num) {
472
                $obj = $this->db->fetch_object($resql);
473
                $unitKey = $langs->trans('SizeUnit' . $obj->unit);
474
475
                $paperformat[$obj->code] = $langs->trans('PaperFormat' . strtoupper($obj->code)) . ' - ' . round($obj->width) . 'x' . round($obj->height) . ' ' . ($unitKey == 'SizeUnit' . $obj->unit ? $obj->unit : $unitKey);
476
477
                $i++;
478
            }
479
        } else {
480
            dol_print_error($this->db);
481
            return '';
482
        }
483
        $out = '';
484
485
        $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
486
        if ($showempty) {
487
            $out .= '<option value=""';
488
            if ($selected == '') {
489
                $out .= ' selected';
490
            }
491
            $out .= '>&nbsp;</option>';
492
        }
493
        foreach ($paperformat as $key => $value) {
494
            if ($selected == $key) {
495
                $out .= '<option value="' . $key . '" selected>' . $value . '</option>';
496
            } else {
497
                $out .= '<option value="' . $key . '">' . $value . '</option>';
498
            }
499
        }
500
        $out .= '</select>';
501
502
        if (!$forcecombo) {
503
            include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
504
            $out .= ajax_combobox($htmlname);
505
        }
506
507
        return $out;
508
    }
509
510
511
    /**
512
     * Function to show the combo select to chose a type of field (varchar, int, email, ...)
513
     *
514
     * @param string $htmlname Name of HTML select component
515
     * @param string $type Type preselected
516
     * @param array $typewecanchangeinto Array of possible switch combination from 1 type to another one. This will grey not possible combinations.
517
     * @return  string                          The combo HTML select component
518
     */
519
    public function selectTypeOfFields($htmlname, $type, $typewecanchangeinto = array())
520
    {
521
        global $type2label; // TODO Remove this
522
523
        $out = '';
524
525
        $out .= '<select class="flat type" id="' . $htmlname . '" name="' . $htmlname . '">';
526
        foreach ($type2label as $key => $val) {
527
            $selected = '';
528
            if ($key == $type) {
529
                $selected = ' selected="selected"';
530
            }
531
532
            // Set $valhtml with the picto for the type
533
            $valhtml = ($key ? getPictoForType($key) : '') . $val;
534
535
            if (empty($typewecanchangeinto) || in_array($key, $typewecanchangeinto[$type])) {
536
                $out .= '<option value="' . $key . '"' . $selected . ' data-html="' . dol_escape_htmltag($valhtml) . '">' . ($val ? $val : '&nbsp;') . '</option>';
537
            } else {
538
                $out .= '<option value="' . $key . '" disabled="disabled"' . $selected . ' data-html="' . dol_escape_htmltag($valhtml) . '">' . ($val ? $val : '&nbsp;') . '</option>';
539
            }
540
        }
541
        $out .= '</select>';
542
        $out .= ajax_combobox('type');
543
544
        return $out;
545
    }
546
}
547