Passed
Push — dev ( 3becbd...634f81 )
by Rafael
53:25
created

FormAdmin   F

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
/**
29
 *      \file       htdocs/core/class/html.formadmin.class.php
30
 *      \ingroup    core
31
 *      \brief      File of class for html functions for admin pages
32
 */
33
34
35
/**
36
 *      Class to generate html code for admin pages
37
 */
38
class FormAdmin
39
{
40
    /**
41
     * @var DoliDB Database handler.
42
     */
43
    public $db;
44
45
    /**
46
     * @var string error message
47
     */
48
    public $error;
49
50
51
    /**
52
     *  Constructor
53
     *
54
     * @param DoliDB|null $db Database handler
55
     */
56
    public function __construct($db)
57
    {
58
        $this->db = $db;
59
    }
60
61
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
62
63
    /**
64
     *  Return html select list with available languages (key='en_US', value='United States' for example)
65
     *
66
     * @param string|array $selected Language pre-selected. Can be an array if $multiselect is 1.
67
     * @param string $htmlname Name of HTML select
68
     * @param int $showauto Show 'auto' choice
69
     * @param array $filter Array of keys to exclude in list (opposite of $onlykeys)
70
     * @param int|string $showempty '1'=Add empty value or 'string to show'
71
     * @param int $showwarning Show a warning if language is not complete
72
     * @param int $disabled Disable edit of select
73
     * @param string $morecss Add more css styles
74
     * @param int $showcode 1=Add language code into label at beginning, 2=Add language code into label at end
75
     * @param int $forcecombo Force to use combo box (so no ajax beautify effect)
76
     * @param int $multiselect Make the combo a multiselect
77
     * @param array $onlykeys Array of language keys to restrict list with the following keys (opposite of $filter). Example array('fr', 'es', ...)
78
     * @param int $mainlangonly 1=Show only main languages ('fr_FR' no' fr_BE', 'es_ES' not 'es_MX', ...)
79
     * @return     string                          Return HTML select string with list of languages
80
     */
81
    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)
82
    {
83
        // phpcs:enable
84
        global $langs;
85
86
        if (getDolGlobalString('MAIN_DEFAULT_LANGUAGE_FILTER')) {
87
            if (!is_array($filter)) {
88
                $filter = array();
89
            }
90
            $filter[getDolGlobalString('MAIN_DEFAULT_LANGUAGE_FILTER')] = 1;
91
        }
92
93
        $langs_available = $langs->get_available_languages(DOL_DOCUMENT_ROOT, 12, 0, $mainlangonly);
94
95
        // If empty value is not allowed and the language to select is not inside the list of available language and we must find
96
        // an alternative of the language code to pre-select (to avoid to have first element in list pre-selected).
97
        if ($selected && empty($showempty)) {
98
            if (!is_array($selected) && !array_key_exists($selected, $langs_available)) {
99
                $tmparray = explode('_', $selected);
100
                if (!empty($tmparray[1])) {
101
                    $selected = getLanguageCodeFromCountryCode($tmparray[1]);
102
                }
103
                if (empty($selected)) {
104
                    $selected = $langs->defaultlang;
105
                }
106
            } else {
107
                // If the preselected value is an array, we do not try to find alternative to preselect
108
            }
109
        }
110
111
        $out = '';
112
113
        $out .= '<select ' . ($multiselect ? 'multiple="multiple" ' : '') . 'class="flat' . ($morecss ? ' ' . $morecss : '') . '" id="' . $htmlname . '" name="' . $htmlname . ($multiselect ? '[]' : '') . '"' . ($disabled ? ' disabled' : '') . '>';
114
        if ($showempty && !$multiselect) {
115
            if (is_numeric($showempty)) {
116
                $out .= '<option value="0"';
117
            } else {
118
                $out .= '<option value="-1"';
119
            }
120
            if ($selected === '') {
121
                $out .= ' selected';
122
            }
123
            $out .= '>';
124
            if ($showempty != '1') {
125
                $out .= $showempty;
126
            } else {
127
                $out .= '&nbsp;';
128
            }
129
            $out .= '</option>';
130
        }
131
        if ($showauto) {
132
            $out .= '<option value="auto"';
133
            if ($selected === 'auto') {
134
                $out .= ' selected';
135
            }
136
            $out .= '>' . $langs->trans("AutoDetectLang") . '</option>';
137
        }
138
139
        asort($langs_available);    // array('XX' => 'Language (Country)', ...)
140
141
        foreach ($langs_available as $key => $value) {
142
            $valuetoshow = $value;
143
            if ($showcode == 1) {
144
                if ($mainlangonly) {
145
                    $valuetoshow = '<span class="opacitymedium">' . preg_replace('/[_-].*$/', '', $key) . '</span> - ' . $value;
146
                } else {
147
                    $valuetoshow = '<span class="opacitymedium">' . $key . '</span> - ' . $value;
148
                }
149
            }
150
            if ($showcode == 2) {
151
                if ($mainlangonly) {
152
                    $valuetoshow = $value . ' <span class="opacitymedium">(' . preg_replace('/[_-].*$/', '', $key) . ')</span>';
153
                } else {
154
                    $valuetoshow = $value . ' <span class="opacitymedium">(' . $key . ')</span>';
155
                }
156
            }
157
158
            $keytouse = $key;
159
            if ($mainlangonly) {
160
                $keytouse = preg_replace('/[_-].*$/', '', $key);
161
            }
162
163
            if ($filter && is_array($filter) && array_key_exists($keytouse, $filter)) {
164
                continue;
165
            }
166
            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...
167
                continue;
168
            }
169
170
            $valuetoshow = picto_from_langcode($key, 'class="saturatemedium"') . ' ' . $valuetoshow;
171
            if ((is_string($selected) && (string)$selected == (string)$keytouse) || (is_array($selected) && in_array($keytouse, $selected))) {
172
                $out .= '<option value="' . $keytouse . '" selected data-html="' . dol_escape_htmltag($valuetoshow) . '">' . $valuetoshow . '</option>';
173
            } else {
174
                $out .= '<option value="' . $keytouse . '" data-html="' . dol_escape_htmltag($valuetoshow) . '">' . $valuetoshow . '</option>';
175
            }
176
        }
177
        $out .= '</select>';
178
179
        // Make select dynamic
180
        if (!$forcecombo) {
181
            include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
182
            $out .= ajax_combobox($htmlname);
183
        }
184
185
        return $out;
186
    }
187
188
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
189
190
    /**
191
     *    Return list of available menus (eldy_backoffice, ...)
192
     *
193
     * @param string $selected Preselected menu value
194
     * @param string $htmlname Name of html select
195
     * @param array $dirmenuarray Array of directories to scan
196
     * @param string $moreattrib More attributes on html select tag
197
     * @return   integer|void
198
     */
199
    public function select_menu($selected, $htmlname, $dirmenuarray, $moreattrib = '')
200
    {
201
        // phpcs:enable
202
        global $langs, $conf;
203
204
        // Clean parameters
205
206
207
        // Check parameters
208
        if (!is_array($dirmenuarray)) {
209
            return -1;
210
        }
211
212
        $menuarray = array();
213
        foreach ($conf->file->dol_document_root as $dirroot) {
214
            foreach ($dirmenuarray as $dirtoscan) {
215
                $dir = $dirroot . $dirtoscan;
216
                //print $dir.'<br>';
217
                if (is_dir($dir)) {
218
                    $handle = opendir($dir);
219
                    if (is_resource($handle)) {
220
                        while (($file = readdir($handle)) !== false) {
221
                            if (is_file($dir . "/" . $file) && substr($file, 0, 1) != '.' && substr($file, 0, 3) != 'CVS' && substr($file, 0, 5) != 'index') {
222
                                if (preg_match('/lib\.php$/i', $file)) {
223
                                    continue; // We exclude library files
224
                                }
225
                                if (preg_match('/eldy_(backoffice|frontoffice)\.php$/i', $file)) {
226
                                    continue; // We exclude all menu manager files
227
                                }
228
                                if (preg_match('/auguria_(backoffice|frontoffice)\.php$/i', $file)) {
229
                                    continue; // We exclude all menu manager files
230
                                }
231
                                if (preg_match('/smartphone_(backoffice|frontoffice)\.php$/i', $file)) {
232
                                    continue; // We exclude all menu manager files
233
                                }
234
235
                                $filelib = preg_replace('/\.php$/i', '', $file);
236
                                $prefix = '';
237
                                // 0=Recommended, 1=Experimental, 2=Development, 3=Other
238
                                if (preg_match('/^eldy/i', $file)) {
239
                                    $prefix = '0';
240
                                } elseif (preg_match('/^smartphone/i', $file)) {
241
                                    $prefix = '2';
242
                                } else {
243
                                    $prefix = '3';
244
                                }
245
246
                                $morelabel = '';
247
                                if (preg_match('/^auguria/i', $file)) {
248
                                    $morelabel .= ' <span class="opacitymedium">(' . $langs->trans("Unstable") . ')</span>';
249
                                }
250
                                if ($file == $selected) {
251
                                    $menuarray[$prefix . '_' . $file] = '<option value="' . $file . '" selected data-html="' . dol_escape_htmltag($filelib . $morelabel) . '">' . $filelib . $morelabel;
252
                                    $menuarray[$prefix . '_' . $file] .= '</option>';
253
                                } else {
254
                                    $menuarray[$prefix . '_' . $file] = '<option value="' . $file . '" data-html="' . dol_escape_htmltag($filelib . $morelabel) . '">' . $filelib . $morelabel;
255
                                    $menuarray[$prefix . '_' . $file] .= '</option>';
256
                                }
257
                            }
258
                        }
259
                        closedir($handle);
260
                    }
261
                }
262
            }
263
        }
264
        ksort($menuarray);
265
266
        // Output combo list of menus
267
        print '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '"' . ($moreattrib ? ' ' . $moreattrib : '') . '>';
268
        $oldprefix = '';
269
        foreach ($menuarray as $key => $val) {
270
            $tab = explode('_', $key);
271
            $newprefix = $tab[0];
272
273
            if ($newprefix == '1' && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1)) {
274
                continue;
275
            }
276
            if ($newprefix == '2' && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2)) {
277
                continue;
278
            }
279
            if ($newprefix != $oldprefix) { // Add separators
280
                // Affiche titre
281
                print '<option value="-2" disabled>';
282
                if ($newprefix == '0') {
283
                    print '-- ' . $langs->trans("VersionRecommanded") . ' --';
284
                }
285
                if ($newprefix == '1') {
286
                    print '-- ' . $langs->trans("VersionExperimental") . ' --';
287
                }
288
                if ($newprefix == '2') {
289
                    print '-- ' . $langs->trans("VersionDevelopment") . ' --';
290
                }
291
                if ($newprefix == '3') {
292
                    print '-- ' . $langs->trans("Other") . ' --';
293
                }
294
                print '</option>';
295
                $oldprefix = $newprefix;
296
            }
297
298
            print $val . "\n"; // Show menu entry ($val contains the <option> tags
299
        }
300
        print '</select>';
301
302
        print ajax_combobox($htmlname);
303
304
        return;
305
    }
306
307
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
308
309
    /**
310
     *  Return combo list of available menu families
311
     *
312
     * @param string $selected Menu pre-selected
313
     * @param string $htmlname Name of html select
314
     * @param string[] $dirmenuarray Directories to scan
315
     * @return void
316
     */
317
    public function select_menu_families($selected, $htmlname, $dirmenuarray)
318
    {
319
        // phpcs:enable
320
        global $langs, $conf;
321
322
        //$expdevmenu=array('smartphone_backoffice.php','smartphone_frontoffice.php');  // Menu to disable if $conf->global->MAIN_FEATURES_LEVEL is not set
323
        $expdevmenu = array();
324
325
        $menuarray = array();
326
327
        foreach ($dirmenuarray as $dirmenu) {
328
            foreach ($conf->file->dol_document_root as $dirroot) {
329
                $dir = $dirroot . $dirmenu;
330
                if (is_dir($dir)) {
331
                    $handle = opendir($dir);
332
                    if (is_resource($handle)) {
333
                        while (($file = readdir($handle)) !== false) {
334
                            if (is_file($dir . "/" . $file) && substr($file, 0, 1) != '.' && substr($file, 0, 3) != 'CVS') {
335
                                $filelib = preg_replace('/(_backoffice|_frontoffice)?\.php$/i', '', $file);
336
                                if (preg_match('/^index/i', $filelib)) {
337
                                    continue;
338
                                }
339
                                if (preg_match('/^default/i', $filelib)) {
340
                                    continue;
341
                                }
342
                                if (preg_match('/^empty/i', $filelib)) {
343
                                    continue;
344
                                }
345
                                if (preg_match('/\.lib/i', $filelib)) {
346
                                    continue;
347
                                }
348
                                if (getDolGlobalInt('MAIN_FEATURES_LEVEL') == 0 && in_array($file, $expdevmenu)) {
349
                                    continue;
350
                                }
351
352
                                $menuarray[$filelib] = 1;
353
                            }
354
                            $menuarray['all'] = 1;
355
                        }
356
                        closedir($handle);
357
                    }
358
                }
359
            }
360
        }
361
362
        ksort($menuarray);
363
364
        // Show combo list of menu handlers
365
        print '<select class="flat maxwidth150" id="' . $htmlname . '" name="' . $htmlname . '">';
366
        foreach ($menuarray as $key => $val) {
367
            $tab = explode('_', $key);
368
            print '<option value="' . $key . '"';
369
            if ($key == $selected) {
370
                print '	selected';
371
            }
372
            print '>';
373
            if ($key == 'all') {
374
                print $langs->trans("AllMenus");
375
            } else {
376
                print $key;
377
            }
378
            print '</option>' . "\n";
379
        }
380
        print '</select>';
381
382
        print ajax_combobox($htmlname);
383
    }
384
385
386
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
387
388
    /**
389
     *  Return a HTML select list of timezones
390
     *
391
     * @param string $selected Menu pre-selectionnee
392
     * @param string $htmlname Nom de la zone select
393
     * @return void
394
     */
395
    public function select_timezone($selected, $htmlname)
396
    {
397
        // phpcs:enable
398
        print '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
399
        print '<option value="-1">&nbsp;</option>';
400
401
        $arraytz = array(
402
            "Pacific/Midway" => "GMT-11:00",
403
            "Pacific/Fakaofo" => "GMT-10:00",
404
            "America/Anchorage" => "GMT-09:00",
405
            "America/Los_Angeles" => "GMT-08:00",
406
            "America/Dawson_Creek" => "GMT-07:00",
407
            "America/Chicago" => "GMT-06:00",
408
            "America/Bogota" => "GMT-05:00",
409
            "America/Anguilla" => "GMT-04:00",
410
            "America/Araguaina" => "GMT-03:00",
411
            "America/Noronha" => "GMT-02:00",
412
            "Atlantic/Azores" => "GMT-01:00",
413
            "Africa/Abidjan" => "GMT+00:00",
414
            "Europe/Paris" => "GMT+01:00",
415
            "Europe/Helsinki" => "GMT+02:00",
416
            "Europe/Moscow" => "GMT+03:00",
417
            "Asia/Dubai" => "GMT+04:00",
418
            "Asia/Karachi" => "GMT+05:00",
419
            "Indian/Chagos" => "GMT+06:00",
420
            "Asia/Jakarta" => "GMT+07:00",
421
            "Asia/Hong_Kong" => "GMT+08:00",
422
            "Asia/Tokyo" => "GMT+09:00",
423
            "Australia/Sydney" => "GMT+10:00",
424
            "Pacific/Noumea" => "GMT+11:00",
425
            "Pacific/Auckland" => "GMT+12:00",
426
            "Pacific/Enderbury" => "GMT+13:00"
427
        );
428
        foreach ($arraytz as $lib => $gmt) {
429
            print '<option value="' . $lib . '"';
430
            if ($selected == $lib || $selected == $gmt) {
431
                print ' selected';
432
            }
433
            print '>' . $gmt . '</option>' . "\n";
434
        }
435
        print '</select>';
436
    }
437
438
439
440
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
441
442
    /**
443
     *  Return html select list with available languages (key='en_US', value='United States' for example)
444
     *
445
     * @param string $selected Paper format pre-selected
446
     * @param string $htmlname Name of HTML select field
447
     * @param string $filter Value to filter on code
448
     * @param int $showempty Add empty value
449
     * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification)
450
     * @return     string                  Return HTML output
451
     */
452
    public function select_paper_format($selected = '', $htmlname = 'paperformat_id', $filter = '', $showempty = 0, $forcecombo = 0)
453
    {
454
        // phpcs:enable
455
        global $langs;
456
457
        $langs->load("dict");
458
459
        $sql = "SELECT code, label, width, height, unit";
460
        $sql .= " FROM " . $this->db->prefix() . "c_paper_format";
461
        $sql .= " WHERE active=1";
462
        if ($filter) {
463
            $sql .= " AND code LIKE '%" . $this->db->escape($filter) . "%'";
464
        }
465
466
        $paperformat = array();
467
468
        $resql = $this->db->query($sql);
469
        if ($resql) {
470
            $num = $this->db->num_rows($resql);
471
            $i = 0;
472
            while ($i < $num) {
473
                $obj = $this->db->fetch_object($resql);
474
                $unitKey = $langs->trans('SizeUnit' . $obj->unit);
475
476
                $paperformat[$obj->code] = $langs->trans('PaperFormat' . strtoupper($obj->code)) . ' - ' . round($obj->width) . 'x' . round($obj->height) . ' ' . ($unitKey == 'SizeUnit' . $obj->unit ? $obj->unit : $unitKey);
477
478
                $i++;
479
            }
480
        } else {
481
            dol_print_error($this->db);
482
            return '';
483
        }
484
        $out = '';
485
486
        $out .= '<select class="flat" id="' . $htmlname . '" name="' . $htmlname . '">';
487
        if ($showempty) {
488
            $out .= '<option value=""';
489
            if ($selected == '') {
490
                $out .= ' selected';
491
            }
492
            $out .= '>&nbsp;</option>';
493
        }
494
        foreach ($paperformat as $key => $value) {
495
            if ($selected == $key) {
496
                $out .= '<option value="' . $key . '" selected>' . $value . '</option>';
497
            } else {
498
                $out .= '<option value="' . $key . '">' . $value . '</option>';
499
            }
500
        }
501
        $out .= '</select>';
502
503
        if (!$forcecombo) {
504
            include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
505
            $out .= ajax_combobox($htmlname);
506
        }
507
508
        return $out;
509
    }
510
511
512
    /**
513
     * Function to show the combo select to chose a type of field (varchar, int, email, ...)
514
     *
515
     * @param string $htmlname Name of HTML select component
516
     * @param string $type Type preselected
517
     * @param array $typewecanchangeinto Array of possible switch combination from 1 type to another one. This will grey not possible combinations.
518
     * @return  string                          The combo HTML select component
519
     */
520
    public function selectTypeOfFields($htmlname, $type, $typewecanchangeinto = array())
521
    {
522
        global $type2label; // TODO Remove this
523
524
        $out = '';
525
526
        $out .= '<select class="flat type" id="' . $htmlname . '" name="' . $htmlname . '">';
527
        foreach ($type2label as $key => $val) {
528
            $selected = '';
529
            if ($key == $type) {
530
                $selected = ' selected="selected"';
531
            }
532
533
            // Set $valhtml with the picto for the type
534
            $valhtml = ($key ? getPictoForType($key) : '') . $val;
535
536
            if (empty($typewecanchangeinto) || in_array($key, $typewecanchangeinto[$type])) {
537
                $out .= '<option value="' . $key . '"' . $selected . ' data-html="' . dol_escape_htmltag($valhtml) . '">' . ($val ? $val : '&nbsp;') . '</option>';
538
            } else {
539
                $out .= '<option value="' . $key . '" disabled="disabled"' . $selected . ' data-html="' . dol_escape_htmltag($valhtml) . '">' . ($val ? $val : '&nbsp;') . '</option>';
540
            }
541
        }
542
        $out .= '</select>';
543
        $out .= ajax_combobox('type');
544
545
        return $out;
546
    }
547
}
548