Completed
Branch develop (eec106)
by
unknown
20:48
created

DolibarrModules::insert_tabs()   C

Complexity

Conditions 8
Paths 2

Size

Total Lines 49
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 33
nc 2
nop 0
dl 0
loc 49
rs 6.1403
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2003-2007  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2004       Sebastien Di Cintio     <[email protected]>
4
 * Copyright (C) 2004       Benoit Mortier          <[email protected]>
5
 * Copyright (C) 2004       Eric Seigne             <[email protected]>
6
 * Copyright (C) 2005-2013  Laurent Destailleur     <[email protected]>
7
 * Copyright (C) 2005-2012  Regis Houssin           <[email protected]>
8
 * Copyright (C) 2014       Raphaël Doursenaud      <[email protected]>
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
/**
25
 * \file           htdocs/core/modules/DolibarrModules.class.php
26
 * \brief          File of parent class of module descriptor class files
27
 */
28
29
30
/**
31
 * Class DolibarrModules
32
 *
33
 * Parent class for module descriptor class files
34
 */
35
class DolibarrModules           // Can not be abstract, because we need to instantiate it into unActivateModule to be able to disable a module whose files were removed.
1 ignored issue
show
Coding Style introduced by
Expected 1 space after class name; 11 found
Loading history...
36
{
37
    /**
38
     * @var DoliDb Database handler
39
     */
40
    public $db;
41
42
    /**
43
     * @var int Module unique ID
44
     * @see https://wiki.dolibarr.org/index.php/List_of_modules_id
45
     */
46
    public $numero;
47
48
    /**
49
     * @var string Publisher name
50
     * @since 4.0.0
51
     */
52
    public $editor_name;
53
54
    /**
55
     * @var string URL of module at publisher site
56
     * @since 4.0.0
57
     */
58
    public $editor_url;
59
60
    /**
61
     * @var string Family
62
     * @see familyinfo
63
     *
64
     * Native values: 'crm', 'financial', 'hr', 'projects', 'products', 'ecm', 'technic', 'other'.
65
     * Use familyinfo to declare a custom value.
66
     */
67
    public $family;
68
69
    /**
70
     * @var array Custom family informations
71
     * @see family
72
     *
73
     * e.g.:
74
     * array(
75
     *     'myownfamily' => array(
76
     *         'position' => '001',
77
     *         'label' => $langs->trans("MyOwnFamily")
78
     *     )
79
     * );
80
     *
81
     */
82
    public $familyinfo;
83
84
    /**
85
     * @var int Module position
86
     * @since 3.9.0
87
     */
88
    public $module_position=500;
89
90
    /**
91
     * @var string Module name
92
     *
93
     * Only used if Module[ID]Name translation string is not found.
94
     *
95
     * You can use the following code to automatically derive it from your module's class name:
96
     * preg_replace('/^mod/i', '', get_class($this))
97
     */
98
    public $name;
99
100
    /**
101
     * @var string[] Paths to create when module is activated
102
     *
103
     * e.g.: array('/mymodule/temp')
104
     */
105
    public $dirs = array();
106
107
    /**
108
     * @var array Module boxes
109
     */
110
    public $boxes = array();
111
112
    /**
113
     * @var array Module constants
114
     */
115
    public $const = array();
116
117
    /**
118
     * @var array Module cron jobs entries
119
     */
120
    public $cronjobs = array();
121
122
    /**
123
     * @var array Module access rights
124
     */
125
    public $rights;
126
127
    /**
128
     * @var string Module access rights family
129
     */
130
    public $rights_class;
131
132
    /**
133
     * @var array Module menu entries
134
     */
135
    public $menu = array();
136
137
    /**
138
     * @var array Module parts
139
     *  array(
140
     *      // Set this to 1 if module has its own trigger directory (/mymodule/core/triggers)
141
     *      'triggers' => 0,
142
     *      // Set this to 1 if module has its own login method directory (/mymodule/core/login)
143
     *      'login' => 0,
144
     *      // Set this to 1 if module has its own substitution function file (/mymodule/core/substitutions)
145
     *      'substitutions' => 0,
146
     *      // Set this to 1 if module has its own menus handler directory (/mymodule/core/menus)
147
     *      'menus' => 0,
148
     *      // Set this to 1 if module has its own theme directory (/mymodule/theme)
149
     *      'theme' => 0,
150
     *      // Set this to 1 if module overwrite template dir (/mymodule/core/tpl)
151
     *      'tpl' => 0,
152
     *      // Set this to 1 if module has its own barcode directory (/mymodule/core/modules/barcode)
153
     *      'barcode' => 0,
154
     *      // Set this to 1 if module has its own models directory (/mymodule/core/modules/xxx)
155
     *      'models' => 0,
156
     *      // Set this to relative path of css file if module has its own css file
157
     *      'css' => '/mymodule/css/mymodule.css.php',
158
     *      // Set this to relative path of js file if module must load a js on all pages
159
     *      'js' => '/mymodule/js/mymodule.js',
160
     *      // Set here all hooks context managed by module
161
     *      'hooks' => array('hookcontext1','hookcontext2'),
162
     *      // Set here all workflow context managed by module
163
     *      'workflow' => array(
164
     *          'WORKFLOW_MODULE1_YOURACTIONTYPE_MODULE2' = >array(
165
     *              'enabled' => '! empty($conf->module1->enabled) && ! empty($conf->module2->enabled)',
166
     *              'picto'=>'yourpicto@mymodule'
167
     *          )
168
     *      )
169
     *  )
170
     */
171
    public $module_parts = array();
172
173
    /**
174
     * @var string Module documents ?
175
     * @deprecated Seems unused anywhere
176
     */
177
    public $docs;
178
179
    /**
180
     * @var string ?
181
     * @deprecated Seems unused anywhere
182
     */
183
    public $dbversion = "-";
184
185
    /**
186
     * @var string Error message
187
     */
188
    public $error;
189
190
    /**
191
     * @var string Module version
192
     * @see http://semver.org
193
     *
194
     * The following keywords can also be used:
195
     * 'development'
196
     * 'experimental'
197
     * 'dolibarr': only for core modules that share its version
198
     * 'dolibarr_deprecated': only for deprecated core modules
199
     *
200
     */
201
    public $version;
202
203
    /**
204
     * @var string Module description (short text)
205
     *
206
     * Only used if Module[ID]Desc translation string is not found.
207
     */
208
    public $description;
209
210
    /**
211
     * @var string Module description (long text)
212
     * @since 4.0.0
213
     *
214
     * HTML content supported.
215
     */
216
    public $descriptionlong;
217
218
219
    // For exports
220
221
    /**
222
     * @var string Module export code
223
     */
224
    public $export_code;
225
226
    /**
227
     * @var string Module export label
228
     */
229
    public $export_label;
230
231
    public $export_permission;
232
    public $export_fields_array;
233
    public $export_TypeFields_array;
234
    public $export_entities_array;
235
    public $export_special_array;           // special or computed field
236
    public $export_dependencies_array;
237
    public $export_sql_start;
238
    public $export_sql_end;
239
    public $export_sql_order;
240
241
242
    // For import
243
244
    /**
245
     * @var string Module import code
246
     */
247
    public $import_code;
248
249
    /**
250
     * @var string Module import label
251
     */
252
    public $import_label;
253
254
255
    /**
256
     * @var string Module constant name
257
     */
258
    public $const_name;
259
260
    /**
261
     * @var bool Module can't be disabled
262
     */
263
    public $always_enabled;
264
265
    /**
266
     * @var bool Module is enabled globally (Multicompany support)
267
     */
268
    public $core_enabled;
269
270
    /**
271
     * @var string Relative path to module style sheet
272
     * @deprecated
273
     * @see module_parts
274
     */
275
    public $style_sheet = '';
276
277
	/**
278
	 * @var 0|1|2|3 Where to display the module in setup page
279
	 * @deprecated @since 4.0.0
280
	 * @see family
281
	 * @see familyinfo
282
	 *
283
	 * 0: common
284
	 * 1: interface
285
	 * 2: others
286
	 * 3: very specific
287
	 */
288
	public $special;
289
290
	/**
291
	 * @var string Name of image file used for this module
292
	 *
293
	 * If file is in theme/yourtheme/img directory under name object_pictoname.png use 'pictoname'
294
	 * If file is in module/img directory under name object_pictoname.png use 'pictoname@module'
295
	 */
296
	public $picto;
297
298
	/**
299
	 * @var string[] List of config pages
300
	 *
301
	 * Name of php pages stored into module/admin directory, used to setup module.
302
	 * e.g.: "admin.php@module"
303
	 */
304
	public $config_page_url;
305
306
307
	/**
308
	 * @var string[] List of module class names that must be enabled if this module is enabled.
309
	 *
310
	 * e.g.: array('modAnotherModule', 'modYetAnotherModule')
311
	 */
312
	public $depends;
313
314
	/**
315
	 * @var int[] List of module ids to disable if this one is disabled.
316
	 */
317
	public $requiredby;
318
319
	/**
320
	 * @var string[] List of module class names as string this module is in conflict with.
321
	 * @see depends
322
	 */
323
	public $conflictwith;
324
325
    /**
326
     * @var string[] Module language files
327
     */
328
    public $langfiles;
329
330
    /**
331
     * @var string[] Array of warnings to show when we activate the module
332
     *
333
     * array('always'='text') or array('FR'='text')
334
     */
335
    public $warnings_activation;
336
337
    /**
338
     * @var string[] Array of warnings to show when we activate an external module
339
     *
340
     * array('always'='text') or array('FR'='text')
341
     */
342
    public $warnings_activation_ext;
343
344
345
	/**
346
	 * @var array() Minimum version of PHP required by module.
347
	 * e.g.: PHP ≥ 5.3 = array(5, 3)
348
	 */
349
	public $phpmin;
350
351
	/**
352
	 * @var array Minimum version of Dolibarr required by module.
353
	 * e.g.: Dolibarr ≥ 3.6 = array(3, 6)
354
	 */
355
	public $need_dolibarr_version;
356
357
	/**
358
	 * @var bool Whether to hide the module.
359
	 */
360
	public $hidden = false;
361
362
363
364
365
366
367
368
369
370
	/**
371
	 * Constructor. Define names, constants, directories, boxes, permissions
372
	 *
373
	 * @param DoliDB		$db      Database handler
374
	 */
375
	public function __construct($db)
376
	{
377
		$this->db = $db;
378
	}
379
	// We should but can't set this as abstract because this will make dolibarr hang
380
	// after migration due to old module not implementing. We must wait PHP is able to make
381
	// a try catch on Fatal error to manage this correctly.
382
	// We need constructor into function unActivateModule into admin.lib.php
383
384
    /**
385
     * Enables a module.
386
     * Inserts all informations into database
387
     *
388
	 * @param   array  		$array_sql  SQL requests to be executed when enabling module
389
     * @param   string      $options    String with options when disabling module:
390
     *                                    'noboxes' = Do not insert boxes
391
     *                                    'newboxdefonly' = For boxes, insert def of boxes only and not boxes activation
392
     *
393
     * @return  int                         1 if OK, 0 if KO
394
     */
395
    function _init($array_sql, $options='')
396
    {
397
        global $conf;
398
        $err=0;
399
400
        $this->db->begin();
401
402
        // Insert activation module constant
403
        if (! $err) $err+=$this->_active();
404
405
        // Insert new pages for tabs (into llx_const)
406
        if (! $err) $err+=$this->insert_tabs();
407
408
        // Insert activation of module's parts
409
        if (! $err) $err+=$this->insert_module_parts();
410
411
        // Insert constant defined by modules (into llx_const)
412
        if (! $err) $err+=$this->insert_const();
413
414
        // Insert boxes def into llx_boxes_def and boxes setup (into llx_boxes)
415
        if (! $err && ! preg_match('/noboxes/',$options)) $err+=$this->insert_boxes($options);
416
417
        // Insert cron job entries (entry in llx_cronjobs)
418
        if (! $err) $err+=$this->insert_cronjobs();
419
420
        // Insert permission definitions of module into llx_rights_def. If user is admin, grant this permission to user.
421
        if (! $err) $err+=$this->insert_permissions(1, null, 1);
422
423
        // Insert specific menus entries into database
424
        if (! $err) $err+=$this->insert_menus();
425
426
        // Create module's directories
427
        if (! $err) $err+=$this->create_dirs();
428
429
        // Execute addons requests
430
        $num=count($array_sql);
431
        for ($i = 0; $i < $num; $i++)
432
        {
433
            if (! $err)
434
            {
435
                $val=$array_sql[$i];
436
                $sql=$val;
437
                $ignoreerror=0;
438
                if (is_array($val))
439
                {
440
                    $sql=$val['sql'];
441
                    $ignoreerror=$val['ignoreerror'];
442
                }
443
                // Add current entity id
444
                $sql=str_replace('__ENTITY__', $conf->entity, $sql);
445
446
                dol_syslog(get_class($this)."::_init ignoreerror=".$ignoreerror."", LOG_DEBUG);
447
                $result=$this->db->query($sql, $ignoreerror);
448
                if (! $result)
449
                {
450
                    if (! $ignoreerror)
451
                    {
452
                        $this->error=$this->db->lasterror();
453
                        $err++;
454
                    }
455
                    else
456
                    {
457
                        dol_syslog(get_class($this)."::_init Warning ".$this->db->lasterror(), LOG_WARNING);
458
                    }
459
                }
460
            }
461
        }
462
463
        // Return code
464
        if (! $err)
465
        {
466
            $this->db->commit();
467
            return 1;
468
        }
469
        else
470
        {
471
            $this->db->rollback();
472
            return 0;
473
        }
474
    }
475
476
    /**
477
     * Disable function. Deletes the module constant and boxes from the database.
478
     *
479
     * @param   string[]    $array_sql  SQL requests to be executed when module is disabled
480
     * @param   string      $options	Options when disabling module:
481
     *                                    'newboxdefonly|noboxes' = We don't remove boxes.
482
     *
483
     * @return  int                     1 if OK, 0 if KO
484
     */
485
    function _remove($array_sql, $options='')
486
    {
487
        $err=0;
488
489
        $this->db->begin();
490
491
        // Remove activation module line (constant MAIN_MODULE_MYMODULE in llx_const)
492
        if (! $err) $err+=$this->_unactive();
493
494
        // Remove activation of module's new tabs (MAIN_MODULE_MYMODULE_TABS_XXX in llx_const)
495
        if (! $err) $err+=$this->delete_tabs();
496
497
        // Remove activation of module's parts (MAIN_MODULE_MYMODULE_XXX in llx_const)
498
        if (! $err) $err+=$this->delete_module_parts();
499
500
        // Remove constants defined by modules
501
        if (! $err) $err+=$this->delete_const();
502
503
        // Remove list of module's available boxes (entry in llx_boxes)
504
        if (! $err && ! preg_match('/(newboxdefonly|noboxes)/',$options)) $err+=$this->delete_boxes();	// We don't have to delete if option ask to keep boxes safe or ask to add new box def only
505
506
        // Remove list of module's cron job entries (entry in llx_cronjobs)
507
        if (! $err) $err+=$this->delete_cronjobs();
508
509
        // Remove module's permissions from list of available permissions (entries in llx_rights_def)
510
        if (! $err) $err+=$this->delete_permissions();
511
512
        // Remove module's menus (entries in llx_menu)
513
        if (! $err) $err+=$this->delete_menus();
514
515
        // Remove module's directories
516
        if (! $err) $err+=$this->delete_dirs();
517
518
        // Run complementary sql requests
519
        $num=count($array_sql);
520
        for ($i = 0; $i < $num; $i++)
521
        {
522
            if (! $err)
523
            {
524
                dol_syslog(get_class($this)."::_remove", LOG_DEBUG);
525
                $result=$this->db->query($array_sql[$i]);
526
                if (! $result)
527
                {
528
                    $this->error=$this->db->error();
529
                    $err++;
530
                }
531
            }
532
        }
533
534
        // Return code
535
        if (! $err)
536
        {
537
            $this->db->commit();
538
            return 1;
539
        }
540
        else
541
        {
542
            $this->db->rollback();
543
            return 0;
544
        }
545
    }
546
547
548
    /**
549
     * Gives the translated module name if translation exists in admin.lang or into language files of module.
550
     * Otherwise return the module key name.
551
     *
552
     * @return  string  Translated module name
553
     */
554
    function getName()
555
    {
556
        global $langs;
557
        $langs->load("admin");
558
559
        if ($langs->trans("Module".$this->numero."Name") != ("Module".$this->numero."Name"))
560
        {
561
            // If module name translation exists
562
            return $langs->trans("Module".$this->numero."Name");
563
        }
564
        else
565
        {
566
            // If module name translation using it's unique id does not exists, we try to use its name to find translation
567
            if (is_array($this->langfiles))
568
            {
569
                foreach($this->langfiles as $val)
570
                {
571
                    if ($val) $langs->load($val);
572
                }
573
            }
574
575
            if ($langs->trans("Module".$this->name."Name") != ("Module".$this->name."Name"))
576
            {
577
                // If module name translation exists
578
                return $langs->trans("Module".$this->name."Name");
579
            }
580
581
            // Last change with simple product label
582
            return $langs->trans($this->name);
583
        }
584
    }
585
586
587
    /**
588
     * Gives the translated module description if translation exists in admin.lang or the default module description
589
     *
590
     * @return  string  Translated module description
591
     */
592
    function getDesc()
593
    {
594
        global $langs;
595
        $langs->load("admin");
596
597
        if ($langs->trans("Module".$this->numero."Desc") != ("Module".$this->numero."Desc"))
598
        {
599
            // If module description translation exists
600
            return $langs->trans("Module".$this->numero."Desc");
601
        }
602
        else
603
        {
604
            // If module description translation does not exist using its unique id, we can use its name to find translation
605
            if (is_array($this->langfiles))
606
            {
607
                foreach($this->langfiles as $val)
608
                {
609
                    if ($val) $langs->load($val);
610
                }
611
            }
612
            return $langs->trans($this->description);
613
        }
614
    }
615
616
    /**
617
     * Gives the long description of a module. First check README-la_LA.md then README.md
618
     * If not markdown files found, it return translated value of the key ->descriptionlong.
619
     *
620
     * @return  string                  Long description of a module from README.md of from property.
621
     */
622
    function getDescLong()
623
    {
624
        global $langs;
625
        $langs->load("admin");
626
627
        include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
628
        include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
629
630
        $pathoffile = $this->getDescLongReadmeFound();
631
632
        if ($pathoffile)     // Mostly for external modules
633
        {
634
            $content = file_get_contents($pathoffile);
635
636
            if ((float) DOL_VERSION >= 6.0)
637
            {
638
                @include_once DOL_DOCUMENT_ROOT.'/core/lib/parsemd.lib.php';
639
                $content = dolMd2Html($content, 'parsedown',
640
                    array(
641
                        'doc/'=>dol_buildpath(strtolower($this->name).'/doc/', 1),
642
                        'img/'=>dol_buildpath(strtolower($this->name).'/img/', 1),
643
                        'images/'=>dol_buildpath(strtolower($this->name).'/imgages/', 1),
644
                    ));
645
            }
646
            else
647
            {
648
                $content = nl2br($content);
649
            }
650
        }
651
        else                // Mostly for internal modules
652
        {
653
            if (! empty($this->descriptionlong))
654
            {
655
                if (is_array($this->langfiles))
656
                {
657
                    foreach($this->langfiles as $val)
658
                    {
659
                        if ($val) $langs->load($val);
660
                    }
661
                }
662
663
                $content = $langs->trans($this->descriptionlong);
664
            }
665
        }
666
667
        return $content;
0 ignored issues
show
Bug introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
668
    }
669
670
    /**
671
     * Return path of file if a README file was found.
672
     *
673
     * @return  string      Path of file if a README file was found.
674
     */
675
    function getDescLongReadmeFound()
676
    {
677
        $filefound= false;
678
679
        // Define path to file README.md.
680
        // First check README-la_LA.md then README.md
681
        $pathoffile = dol_buildpath(strtolower($this->name).'/README-'.$langs->defaultlang.'.md', 0);
0 ignored issues
show
Bug introduced by
The variable $langs does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
682
        if (dol_is_file($pathoffile))
683
        {
684
            $filefound = true;
685
        }
686
        if (! $filefound)
687
        {
688
            $pathoffile = dol_buildpath(strtolower($this->name).'/README.md', 0);
689
            if (dol_is_file($pathoffile))
690
            {
691
                $filefound = true;
692
            }
693
        }
694
695
        return ($filefound?$pathoffile:'');
696
    }
697
698
699
    /**
700
     * Gives the changelog. First check ChangeLog-la_LA.md then ChangeLog.md
701
     *
702
     * @return  string  Content of ChangeLog
703
     */
704
    function getChangeLog()
705
    {
706
        global $langs;
707
        $langs->load("admin");
708
709
        include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
710
        include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
711
712
        $filefound= false;
713
714
        // Define path to file README.md.
715
        // First check README-la_LA.md then README.md
716
        $pathoffile = dol_buildpath(strtolower($this->name).'/ChangeLog-'.$langs->defaultlang.'.md', 0);
717
        if (dol_is_file($pathoffile))
718
        {
719
            $filefound = true;
720
        }
721
        if (! $filefound)
722
        {
723
            $pathoffile = dol_buildpath(strtolower($this->name).'/ChangeLog.md', 0);
724
            if (dol_is_file($pathoffile))
725
            {
726
                $filefound = true;
727
            }
728
        }
729
730
        if ($filefound)     // Mostly for external modules
731
        {
732
            $content = file_get_contents($pathoffile);
733
734
            if ((float) DOL_VERSION >= 6.0)
735
            {
736
                @include_once DOL_DOCUMENT_ROOT.'/core/lib/parsemd.lib.php';
737
                $content = dolMd2Html($content, 'parsedown', array('doc/'=>dol_buildpath(strtolower($this->name).'/doc/', 1)));
738
            }
739
            else
740
            {
741
                $content = nl2br($content);
742
            }
743
        }
744
745
        return $content;
0 ignored issues
show
Bug introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
746
    }
747
748
    /**
749
     * Gives the publisher name
750
     *
751
     * @return  string  Publisher name
752
     */
753
    function getPublisher()
754
    {
755
        return $this->editor_name;
756
    }
757
758
    /**
759
     * Gives the publisher url
760
     *
761
     * @return  string  Publisher url
762
     */
763
    function getPublisherUrl()
764
    {
765
        return $this->editor_url;
766
    }
767
768
    /**
769
     * Gives module version (translated if param $translated is on)
770
     * For 'experimental' modules, gives 'experimental' translation
771
     * For 'dolibarr' modules, gives Dolibarr version
772
     *
773
     * @param   int     $translated     1=Special version keys are translated, 0=Special version keys are not translated
774
     * @return  string                  Module version
775
     */
776
    function getVersion($translated=1)
777
    {
778
        global $langs;
779
        $langs->load("admin");
780
781
        $ret='';
782
783
        $newversion=preg_replace('/_deprecated/','',$this->version);
784
        if ($newversion == 'experimental') $ret=($translated?$langs->trans("VersionExperimental"):$newversion);
785
        elseif ($newversion == 'development') $ret=($translated?$langs->trans("VersionDevelopment"):$newversion);
786
        elseif ($newversion == 'dolibarr') $ret=DOL_VERSION;
787
        elseif ($newversion) $ret=$newversion;
788
        else $ret=($translated?$langs->trans("VersionUnknown"):'unknown');
789
790
        if (preg_match('/_deprecated/',$this->version)) $ret.=($translated?' ('.$langs->trans("Deprecated").')':$this->version);
791
        return $ret;
792
    }
793
794
795
    /**
796
     * Tells if module is core or external
797
     *
798
     * @return  string  'core', 'external' or 'unknown'
799
     */
800
    function isCoreOrExternalModule()
801
    {
802
        if ($this->version == 'dolibarr' || $this->version == 'dolibarr_deprecated') return 'core';
803
        if (! empty($this->version) && ! in_array($this->version,array('experimental','development'))) return 'external';
804
        if (! empty($this->editor_name) || ! empty($this->editor_url)) return 'external';
805
        if ($this->numero >= 100000) return 'external';
806
        return 'unknown';
807
    }
808
809
810
    /**
811
     * Gives module related language files list
812
     *
813
     * @return  string[]    Language files list
814
     */
815
    function getLangFilesArray()
816
    {
817
        return $this->langfiles;
818
    }
819
820
    /**
821
     * Gives translated label of an export dataset
822
     *
823
     * @param   int     $r  Dataset index
824
     *
825
     * @return string       Translated databaset label
826
     */
827
    function getExportDatasetLabel($r)
828
    {
829
        global $langs;
830
831
        $langstring="ExportDataset_".$this->export_code[$r];
832
        if ($langs->trans($langstring) == $langstring)
833
        {
834
            // Translation not found
835
            return $langs->trans($this->export_label[$r]);
836
        }
837
        else
838
        {
839
            // Translation found
840
            return $langs->trans($langstring);
841
        }
842
    }
843
844
845
    /**
846
     * Gives translated label of an import dataset
847
     *
848
     * @param   int     $r  Dataset index
849
     *
850
     * @return  string      Translated dataset label
851
     */
852
    function getImportDatasetLabel($r)
853
    {
854
        global $langs;
855
856
        $langstring="ImportDataset_".$this->import_code[$r];
857
        //print "x".$langstring;
858
        if ($langs->trans($langstring) == $langstring)
859
        {
860
            // Translation not found
861
            return $langs->trans($this->import_label[$r]);
862
        }
863
        else
864
        {
865
            // Translation found
866
            return $langs->trans($langstring);
867
        }
868
    }
869
870
871
    /**
872
     * Gives the last date of activation
873
     *
874
     * @return  timestamp       Date of last activation
875
     */
876
    function getLastActivationDate()
877
    {
878
        global $conf;
879
880
        $sql = "SELECT tms FROM ".MAIN_DB_PREFIX."const";
881
        $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'";
882
        $sql.= " AND entity IN (0, ".$conf->entity.")";
883
884
        dol_syslog(get_class($this)."::getLastActiveDate", LOG_DEBUG);
885
        $resql=$this->db->query($sql);
886
        if (! $resql) $err++;
0 ignored issues
show
Bug introduced by
The variable $err does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
887
        else
888
        {
889
            $obj=$this->db->fetch_object($resql);
890
            if ($obj) return $this->db->jdate($obj->tms);
891
        }
892
893
        return '';
894
    }
895
896
897
    /**
898
     * Gives the last author of activation
899
     *
900
     * @return  array       Array array('authorid'=>Id of last activation user, 'lastactivationdate'=>Date of last activation)
901
     */
902
    function getLastActivationInfo()
903
    {
904
        global $conf;
905
906
        $sql = "SELECT tms, note FROM ".MAIN_DB_PREFIX."const";
907
        $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'";
908
        $sql.= " AND entity IN (0, ".$conf->entity.")";
909
910
        dol_syslog(get_class($this)."::getLastActiveDate", LOG_DEBUG);
911
        $resql=$this->db->query($sql);
912
        if (! $resql) $err++;
0 ignored issues
show
Bug introduced by
The variable $err does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
913
        else
914
        {
915
            $obj=$this->db->fetch_object($resql);
916
            $tmp=array();
917
            if ($obj->note)
918
            {
919
                $tmp=json_decode($obj->note, true);
920
            }
921
            if ($obj) return array('authorid'=>$tmp['authorid'], 'ip'=>$tmp['ip'], 'lastactivationdate'=>$this->db->jdate($obj->tms));
922
        }
923
924
        return array();
925
    }
926
927
928
    /**
929
     * Insert constants for module activation
930
     *
931
     * @return  int Error count (0 if OK)
932
     */
933
    function _active()
934
    {
935
        global $conf, $user;
936
937
        $err = 0;
938
939
        // Common module
940
        $entity = ((! empty($this->always_enabled) || ! empty($this->core_enabled)) ? 0 : $conf->entity);
941
942
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
943
        $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'";
944
        $sql.= " AND entity IN (0, ".$entity.")";
945
946
        dol_syslog(get_class($this)."::_active", LOG_DEBUG);
947
        $resql=$this->db->query($sql);
948
        if (! $resql) $err++;
949
950
        $note=json_encode(array('authorid'=>(is_object($user)?$user->id:0), 'ip'=>(empty($_SERVER['REMOTE_ADDR'])?'':$_SERVER['REMOTE_ADDR'])));
951
952
        $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name, value, visible, entity, note) VALUES";
953
        $sql.= " (".$this->db->encrypt($this->const_name,1);
954
        $sql.= ", ".$this->db->encrypt('1',1);
955
        $sql.= ", 0, ".$entity;
956
        $sql.= ", '".$this->db->escape($note)."')";
957
958
        dol_syslog(get_class($this)."::_active", LOG_DEBUG);
959
        $resql=$this->db->query($sql);
960
        if (! $resql) $err++;
961
962
        return $err;
963
    }
964
965
966
    /**
967
     * Module deactivation
968
     *
969
     * @return  int Error count (0 if OK)
970
     */
971
    function _unactive()
972
    {
973
        global $conf;
974
975
        $err = 0;
976
977
        // Common module
978
        $entity = ((! empty($this->always_enabled) || ! empty($this->core_enabled)) ? 0 : $conf->entity);
979
980
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
981
        $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'";
982
        $sql.= " AND entity IN (0, ".$entity.")";
983
984
        dol_syslog(get_class($this)."::_unactive", LOG_DEBUG);
985
        $this->db->query($sql);
986
987
        return $err;
988
    }
989
990
991
    /**
992
     * Create tables and keys required by module.
993
     * Files module.sql and module.key.sql with create table and create keys
994
     * commands must be stored in directory reldir='/module/sql/'
995
     * This function is called by this->init
996
     *
997
     * @param   string  $reldir Relative directory where to scan files
998
     * @return  int             <=0 if KO, >0 if OK
999
     */
1000
    function _load_tables($reldir)
1001
    {
1002
        global $conf;
1003
1004
        $error=0;
1005
        $dirfound=0;
1006
1007
        if (empty($reldir)) return 1;
1008
1009
        include_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php';
1010
1011
        $ok = 1;
1012
        foreach($conf->file->dol_document_root as $dirroot)
1013
        {
1014
            if ($ok)
1015
            {
1016
                $dir = $dirroot.$reldir;
1017
                $ok = 0;
1018
1019
                $handle=@opendir($dir);         // Dir may not exists
1020
                if (is_resource($handle))
1021
                {
1022
                    $dirfound++;
1023
1024
                    // Run llx_mytable.sql files, then llx_mytable_*.sql
1025
                    $files = array();
1026
                    while (($file = readdir($handle))!==false)
1027
                    {
1028
                        $files[] = $file;
1029
                    }
1030
                    sort($files);
1031
                    foreach ($files as $file)
1032
                    {
1033
                        if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data')
1034
                        {
1035
                            $result=run_sql($dir.$file,1,'',1);
1036
                            if ($result <= 0) $error++;
1037
                        }
1038
                    }
1039
1040
                    rewinddir($handle);
1041
1042
                    // Run llx_mytable.key.sql files (Must be done after llx_mytable.sql) then then llx_mytable_*.key.sql
1043
                    $files = array();
1044
                    while (($file = readdir($handle))!==false)
1045
                    {
1046
                        $files[] = $file;
1047
                    }
1048
                    sort($files);
1049
                    foreach ($files as $file)
1050
                    {
1051
                        if (preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'llx_' && substr($file,0,4) != 'data')
1052
                        {
1053
                            $result=run_sql($dir.$file,1,'',1);
1054
                            if ($result <= 0) $error++;
1055
                        }
1056
                    }
1057
1058
                    rewinddir($handle);
1059
1060
                    // Run data_xxx.sql files (Must be done after llx_mytable.key.sql)
1061
                    $files = array();
1062
                    while (($file = readdir($handle))!==false)
1063
                    {
1064
                        $files[] = $file;
1065
                    }
1066
                    sort($files);
1067
                    foreach ($files as $file)
1068
                    {
1069
                        if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,4) == 'data')
1070
                        {
1071
                            $result=run_sql($dir.$file,1,'',1);
1072
                            if ($result <= 0) $error++;
1073
                        }
1074
                    }
1075
1076
                    rewinddir($handle);
1077
1078
                    // Run update_xxx.sql files
1079
                    $files = array();
1080
                    while (($file = readdir($handle))!==false)
1081
                    {
1082
                        $files[] = $file;
1083
                    }
1084
                    sort($files);
1085
                    foreach ($files as $file)
1086
                    {
1087
                        if (preg_match('/\.sql$/i',$file) && ! preg_match('/\.key\.sql$/i',$file) && substr($file,0,6) == 'update')
1088
                        {
1089
                            $result=run_sql($dir.$file,1,'',1);
1090
                            if ($result <= 0) $error++;
1091
                        }
1092
                    }
1093
1094
                    closedir($handle);
1095
                }
1096
1097
                if ($error == 0)
1098
                {
1099
                    $ok = 1;
1100
                }
1101
            }
1102
        }
1103
1104
        if (! $dirfound) dol_syslog("A module ask to load sql files into ".$reldir." but this directory was not found.", LOG_WARNING);
1105
        return $ok;
1106
    }
1107
1108
1109
    /**
1110
     * Adds boxes
1111
     *
1112
     * @param   string  $option Options when disabling module ('newboxdefonly'=insert only boxes definition)
1113
     *
1114
     * @return  int             Error count (0 if OK)
1115
     */
1116
    function insert_boxes($option='')
1117
    {
1118
        require_once DOL_DOCUMENT_ROOT . '/core/class/infobox.class.php';
1119
1120
        global $conf;
1121
1122
        $err=0;
1123
1124
        if (is_array($this->boxes))
1125
        {
1126
            $pos_name = InfoBox::getListOfPagesForBoxes();
1127
1128
            foreach ($this->boxes as $key => $value)
1129
            {
1130
                $file  = isset($this->boxes[$key]['file'])?$this->boxes[$key]['file']:'';
1131
                $note  = isset($this->boxes[$key]['note'])?$this->boxes[$key]['note']:'';
1132
                $enabledbydefaulton = isset($this->boxes[$key]['enabledbydefaulton'])?$this->boxes[$key]['enabledbydefaulton']:'Home';
1133
1134
            	if (empty($file)) $file  = isset($this->boxes[$key][1])?$this->boxes[$key][1]:'';	// For backward compatibility
1135
                if (empty($note)) $note  = isset($this->boxes[$key][2])?$this->boxes[$key][2]:'';	// For backward compatibility
1136
1137
                // Search if boxes def already present
1138
                $sql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."boxes_def";
1139
                $sql.= " WHERE file = '".$this->db->escape($file)."'";
1140
                $sql.= " AND entity = ".$conf->entity;
1141
                if ($note) $sql.=" AND note ='".$this->db->escape($note)."'";
1142
1143
                dol_syslog(get_class($this)."::insert_boxes", LOG_DEBUG);
1144
                $result=$this->db->query($sql);
1145
                if ($result)
1146
                {
1147
                    $obj = $this->db->fetch_object($result);
1148
                    if ($obj->nb == 0)
1149
                    {
1150
                        $this->db->begin();
1151
1152
                        if (! $err)
1153
                        {
1154
                            $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes_def (file, entity, note)";
1155
                            $sql.= " VALUES ('".$this->db->escape($file)."', ";
1156
                            $sql.= $conf->entity.", ";
1157
                            $sql.= $note?"'".$this->db->escape($note)."'":"null";
1158
                            $sql.= ")";
1159
1160
                            dol_syslog(get_class($this)."::insert_boxes", LOG_DEBUG);
1161
                            $resql=$this->db->query($sql);
1162
                            if (! $resql) $err++;
1163
1164
                        }
1165
                        if (! $err && ! preg_match('/newboxdefonly/',$option))
1166
                        {
1167
                            $lastid=$this->db->last_insert_id(MAIN_DB_PREFIX."boxes_def","rowid");
1168
1169
                            foreach ($pos_name as $key2 => $val2)
1170
                            {
1171
                                //print 'key2='.$key2.'-val2='.$val2."<br>\n";
1172
                            	if ($enabledbydefaulton && $val2 != $enabledbydefaulton) continue;		// Not enabled by default onto this page.
1173
1174
                                $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes (box_id,position,box_order,fk_user,entity)";
1175
                                $sql.= " VALUES (".$lastid.", ".$key2.", '0', 0, ".$conf->entity.")";
1176
1177
                                dol_syslog(get_class($this)."::insert_boxes onto page ".$key2."=".$val2."", LOG_DEBUG);
1178
                                $resql=$this->db->query($sql);
1179
                                if (! $resql) $err++;
1180
                            }
1181
                        }
1182
1183
                        if (! $err)
1184
                        {
1185
                            $this->db->commit();
1186
                        }
1187
                        else
1188
                        {
1189
                            $this->error=$this->db->lasterror();
1190
                            $this->db->rollback();
1191
                        }
1192
                    }
1193
                    // else box already registered into database
1194
                }
1195
                else
1196
              {
1197
                    $this->error=$this->db->lasterror();
1198
                    $err++;
1199
                }
1200
            }
1201
        }
1202
1203
        return $err;
1204
    }
1205
1206
1207
    /**
1208
     * Removes boxes
1209
     *
1210
     * @return  int Error count (0 if OK)
1211
     */
1212
    function delete_boxes()
1213
    {
1214
        global $conf;
1215
1216
        $err=0;
1217
1218
        if (is_array($this->boxes))
1219
        {
1220
            foreach ($this->boxes as $key => $value)
1221
            {
1222
                //$titre = $this->boxes[$key][0];
1223
                $file  = $this->boxes[$key]['file'];
1224
                //$note  = $this->boxes[$key][2];
1225
1226
                // TODO If the box is also included by another module and the other module is still on, we should not remove it.
1227
                // For the moment, we manage this with hard coded exception
1228
                //print "Remove box ".$file.'<br>';
1229
                if ($file == 'box_graph_product_distribution.php')
1230
                {
1231
                    if (! empty($conf->produit->enabled) || ! empty($conf->service->enabled))
1232
                    {
1233
                        dol_syslog("We discard disabling of module ".$file." because another module still active require it.");
1234
                        continue;
1235
                    }
1236
                }
1237
1238
                if (empty($file)) $file  = isset($this->boxes[$key][1])?$this->boxes[$key][1]:'';	// For backward compatibility
1239
1240
                if ($this->db->type == 'sqlite3') {
1241
                    // sqlite doesn't support "USING" syntax.
1242
                    // TODO: remove this dependency.
1243
                    $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes ";
1244
                    $sql .= "WHERE ".MAIN_DB_PREFIX."boxes.box_id IN (";
1245
                    $sql .= "SELECT ".MAIN_DB_PREFIX."boxes_def.rowid ";
1246
                    $sql .= "FROM ".MAIN_DB_PREFIX."boxes_def ";
1247
                    $sql .= "WHERE ".MAIN_DB_PREFIX."boxes_def.file = '".$this->db->escape($file)."') ";
1248
                    $sql .= "AND ".MAIN_DB_PREFIX."boxes.entity = ".$conf->entity;
1249
                } else {
1250
                    $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes";
1251
                    $sql.= " USING ".MAIN_DB_PREFIX."boxes, ".MAIN_DB_PREFIX."boxes_def";
1252
                    $sql.= " WHERE ".MAIN_DB_PREFIX."boxes.box_id = ".MAIN_DB_PREFIX."boxes_def.rowid";
1253
                    $sql.= " AND ".MAIN_DB_PREFIX."boxes_def.file = '".$this->db->escape($file)."'";
1254
                    $sql.= " AND ".MAIN_DB_PREFIX."boxes.entity = ".$conf->entity;
1255
                }
1256
1257
                dol_syslog(get_class($this)."::delete_boxes", LOG_DEBUG);
1258
                $resql=$this->db->query($sql);
1259
                if (! $resql)
1260
                {
1261
                    $this->error=$this->db->lasterror();
1262
                    $err++;
1263
                }
1264
1265
                $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes_def";
1266
                $sql.= " WHERE file = '".$this->db->escape($file)."'";
1267
                $sql.= " AND entity = ".$conf->entity;
1268
1269
                dol_syslog(get_class($this)."::delete_boxes", LOG_DEBUG);
1270
                $resql=$this->db->query($sql);
1271
                if (! $resql)
1272
                {
1273
                    $this->error=$this->db->lasterror();
1274
                    $err++;
1275
                }
1276
            }
1277
        }
1278
1279
        return $err;
1280
    }
1281
1282
    /**
1283
     * Adds cronjobs
1284
     *
1285
     * @return  int             Error count (0 if OK)
1286
     */
1287
    function insert_cronjobs()
1288
    {
1289
        require_once DOL_DOCUMENT_ROOT . '/core/class/infobox.class.php';
1290
1291
        global $conf;
1292
1293
        $err=0;
1294
1295
        if (is_array($this->cronjobs))
1296
        {
1297
            foreach ($this->cronjobs as $key => $value)
1298
            {
1299
                $label  = isset($this->cronjobs[$key]['label'])?$this->cronjobs[$key]['label']:'';
1300
                $jobtype  = isset($this->cronjobs[$key]['jobtype'])?$this->cronjobs[$key]['jobtype']:'';
1301
                $class  = isset($this->cronjobs[$key]['class'])?$this->cronjobs[$key]['class']:'';
1302
                $objectname  = isset($this->cronjobs[$key]['objectname'])?$this->cronjobs[$key]['objectname']:'';
1303
                $method = isset($this->cronjobs[$key]['method'])?$this->cronjobs[$key]['method']:'';
1304
                $command  = isset($this->cronjobs[$key]['command'])?$this->cronjobs[$key]['command']:'';
1305
                $parameters  = isset($this->cronjobs[$key]['parameters'])?$this->cronjobs[$key]['parameters']:'';
1306
                $comment = isset($this->cronjobs[$key]['comment'])?$this->cronjobs[$key]['comment']:'';
1307
                $frequency = isset($this->cronjobs[$key]['frequency'])?$this->cronjobs[$key]['frequency']:'';
1308
                $unitfrequency = isset($this->cronjobs[$key]['unitfrequency'])?$this->cronjobs[$key]['unitfrequency']:'';
1309
                $status = isset($this->cronjobs[$key]['status'])?$this->cronjobs[$key]['status']:'';
1310
                $priority = isset($this->cronjobs[$key]['priority'])?$this->cronjobs[$key]['priority']:'';
1311
                $test = isset($this->cronjobs[$key]['test'])?$this->cronjobs[$key]['test']:'';                              // Line must be visible
1312
1313
                // Search if boxes def already present
1314
                $sql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."cronjob";
1315
                $sql.= " WHERE module_name = '".$this->db->escape($this->rights_class)."'";
1316
                if ($class) $sql.= " AND classesname = '".$this->db->escape($class)."'";
1317
                if ($objectname) $sql.= " AND objectname = '".$this->db->escape($objectname)."'";
1318
                if ($method) $sql.= " AND methodename = '".$this->db->escape($method)."'";
1319
                if ($command) $sql.= " AND command = '".$this->db->escape($command)."'";
1320
                $sql.= " AND entity = ".$conf->entity;
1321
1322
                $now=dol_now();
1323
1324
                dol_syslog(get_class($this)."::insert_cronjobs", LOG_DEBUG);
1325
                $result=$this->db->query($sql);
1326
                if ($result)
1327
                {
1328
                    $obj = $this->db->fetch_object($result);
1329
                    if ($obj->nb == 0)
1330
                    {
1331
                        $this->db->begin();
1332
1333
                        if (! $err)
1334
                        {
1335
                            $sql = "INSERT INTO ".MAIN_DB_PREFIX."cronjob (module_name, datec, datestart, label, jobtype, classesname, objectname, methodename, command, params, note,";
1336
                            if(is_int($frequency)){ $sql.= ' frequency,'; }
1337
                            if(is_int($unitfrequency)){ $sql.= ' unitfrequency,'; }
1338
                            if(is_int($priority)){ $sql.= ' priority,'; }
1339
                            if(is_int($status)){ $sql.= ' status,'; }
1340
                            $sql.= " entity, test)";
1341
                            $sql.= " VALUES (";
1342
                            $sql.= "'".$this->db->escape($this->rights_class)."', ";
1343
                            $sql.= "'".$this->db->idate($now)."', ";
1344
                            $sql.= "'".$this->db->idate($now)."', ";
1345
                            $sql.= "'".$this->db->escape($label)."', ";
1346
                            $sql.= "'".$this->db->escape($jobtype)."', ";
1347
                            $sql.= ($class?"'".$this->db->escape($class)."'":"null").",";
1348
                            $sql.= ($objectname?"'".$this->db->escape($objectname)."'":"null").",";
1349
                            $sql.= ($method?"'".$this->db->escape($method)."'":"null").",";
1350
                            $sql.= ($command?"'".$this->db->escape($command)."'":"null").",";
1351
                            $sql.= ($parameters?"'".$this->db->escape($parameters)."'":"null").",";
1352
                            $sql.= ($comment?"'".$this->db->escape($comment)."'":"null").",";
1353
                            if(is_int($frequency)){ $sql.= "'".$this->db->escape($frequency)."', "; }
1354
                            if(is_int($unitfrequency)){ $sql.= "'".$this->db->escape($unitfrequency)."', "; }
1355
                            if(is_int($priority)) {$sql.= "'".$this->db->escape($priority)."', ";}
1356
                            if(is_int($status)){ $sql.= "'".$this->db->escape($status)."', "; }
1357
                            $sql.= $conf->entity.",";
1358
                            $sql.= "'".$this->db->escape($test)."'";
1359
                            $sql.= ")";
1360
1361
                            dol_syslog(get_class($this)."::insert_cronjobs", LOG_DEBUG);
1362
                            $resql=$this->db->query($sql);
1363
                            if (! $resql) $err++;
1364
1365
                        }
1366
1367
                        if (! $err)
1368
                        {
1369
                            $this->db->commit();
1370
                        }
1371
                        else
1372
                        {
1373
                            $this->error=$this->db->lasterror();
1374
                            $this->db->rollback();
1375
                        }
1376
                    }
1377
                    // else box already registered into database
1378
                }
1379
                else
1380
              {
1381
                    $this->error=$this->db->lasterror();
1382
                    $err++;
1383
                }
1384
            }
1385
        }
1386
1387
        return $err;
1388
    }
1389
1390
1391
    /**
1392
     * Removes boxes
1393
     *
1394
     * @return  int Error count (0 if OK)
1395
     */
1396
    function delete_cronjobs()
1397
    {
1398
        global $conf;
1399
1400
        $err=0;
1401
1402
        if (is_array($this->cronjobs))
1403
        {
1404
            $sql = "DELETE FROM ".MAIN_DB_PREFIX."cronjob";
1405
            $sql.= " WHERE module_name = '".$this->db->escape($this->rights_class)."'";
1406
            $sql.= " AND entity = ".$conf->entity;
1407
1408
            dol_syslog(get_class($this)."::delete_cronjobs", LOG_DEBUG);
1409
            $resql=$this->db->query($sql);
1410
            if (! $resql)
1411
            {
1412
                $this->error=$this->db->lasterror();
1413
                $err++;
1414
            }
1415
        }
1416
1417
        return $err;
1418
    }
1419
1420
    /**
1421
     * Removes tabs
1422
     *
1423
     * @return  int Error count (0 if OK)
1424
     */
1425
    function delete_tabs()
1426
    {
1427
        global $conf;
1428
1429
        $err=0;
1430
1431
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
1432
        $sql.= " WHERE ".$this->db->decrypt('name')." like '".$this->const_name."_TABS_%'";
1433
        $sql.= " AND entity = ".$conf->entity;
1434
1435
        dol_syslog(get_class($this)."::delete_tabs", LOG_DEBUG);
1436
        if (! $this->db->query($sql))
1437
        {
1438
            $this->error=$this->db->lasterror();
1439
            $err++;
1440
        }
1441
1442
        return $err;
1443
    }
1444
1445
    /**
1446
     * Adds tabs
1447
     *
1448
     * @return int  Error count (0 if ok)
1449
     */
1450
    function insert_tabs()
1451
    {
1452
        global $conf;
1453
1454
        $err=0;
1455
1456
        if (! empty($this->tabs))
1457
        {
1458
            $i=0;
1459
            foreach ($this->tabs as $key => $value)
1460
            {
1461
            	if (is_array($value) && count($value) == 0) continue;	// Discard empty arrays
1462
1463
            	$entity=$conf->entity;
1464
            	$newvalue = $value;
1465
1466
            	if (is_array($value))
1467
            	{
1468
            		$newvalue = $value['data'];
1469
            		if (isset($value['entity'])) $entity = $value['entity'];
1470
            	}
1471
1472
                if ($newvalue)
1473
                {
1474
                    $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (";
1475
                    $sql.= "name";
1476
                    $sql.= ", type";
1477
                    $sql.= ", value";
1478
                    $sql.= ", note";
1479
                    $sql.= ", visible";
1480
                    $sql.= ", entity";
1481
                    $sql.= ")";
1482
                    $sql.= " VALUES (";
1483
                    $sql.= $this->db->encrypt($this->const_name."_TABS_".$i,1);
1484
                    $sql.= ", 'chaine'";
1485
                    $sql.= ", ".$this->db->encrypt($value,1);
1486
                    $sql.= ", null";
1487
                    $sql.= ", '0'";
1488
                    $sql.= ", ".$conf->entity;
1489
                    $sql.= ")";
1490
1491
                    dol_syslog(get_class($this)."::insert_tabs", LOG_DEBUG);
1492
                    $this->db->query($sql);
1493
                }
1494
                $i++;
1495
            }
1496
        }
1497
        return $err;
1498
    }
1499
1500
    /**
1501
     * Adds constants
1502
     *
1503
     * @return  int Error count (0 if OK)
1504
     */
1505
    function insert_const()
1506
    {
1507
        global $conf;
1508
1509
        $err=0;
1510
1511
        if (empty($this->const)) return 0;
1512
1513
        foreach ($this->const as $key => $value)
1514
        {
1515
            $name      = $this->const[$key][0];
1516
            $type      = $this->const[$key][1];
1517
            $val       = $this->const[$key][2];
1518
            $note      = isset($this->const[$key][3])?$this->const[$key][3]:'';
1519
            $visible   = isset($this->const[$key][4])?$this->const[$key][4]:0;
1520
            $entity    = (! empty($this->const[$key][5]) && $this->const[$key][5]!='current')?0:$conf->entity;
1521
1522
            // Clean
1523
            if (empty($visible)) $visible='0';
1524
            if (empty($val) && $val != '0') $val='';
1525
1526
            $sql = "SELECT count(*)";
1527
            $sql.= " FROM ".MAIN_DB_PREFIX."const";
1528
            $sql.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($name)."'";
1529
            $sql.= " AND entity = ".$entity;
1530
1531
            $result=$this->db->query($sql);
1532
            if ($result)
1533
            {
1534
                $row = $this->db->fetch_row($result);
1535
1536
                if ($row[0] == 0)   // If not found
1537
                {
1538
                    $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)";
1539
                    $sql.= " VALUES (";
1540
                    $sql.= $this->db->encrypt($name,1);
1541
                    $sql.= ",'".$type."'";
1542
                    $sql.= ",".(($val != '')?$this->db->encrypt($val,1):"''");
1543
                    $sql.= ",".($note?"'".$this->db->escape($note)."'":"null");
1544
                    $sql.= ",'".$visible."'";
1545
                    $sql.= ",".$entity;
1546
                    $sql.= ")";
1547
1548
1549
                    dol_syslog(get_class($this)."::insert_const", LOG_DEBUG);
1550
                    if (! $this->db->query($sql) )
1551
                    {
1552
                        $err++;
1553
                    }
1554
                }
1555
                else
1556
                {
1557
                    dol_syslog(get_class($this)."::insert_const constant '".$name."' already exists", LOG_WARNING);
1558
                }
1559
            }
1560
            else
1561
            {
1562
                $err++;
1563
            }
1564
        }
1565
1566
        return $err;
1567
    }
1568
1569
    /**
1570
     * Removes constants tagged 'deleteonunactive'
1571
     *
1572
     * @return  int <0 if KO, 0 if OK
1573
     */
1574
    function delete_const()
1575
    {
1576
        global $conf;
1577
1578
        $err=0;
1579
1580
        if (empty($this->const)) return 0;
1581
1582
        foreach ($this->const as $key => $value)
1583
        {
1584
            $name      = $this->const[$key][0];
1585
            $deleteonunactive = (! empty($this->const[$key][6]))?1:0;
1586
1587
            if ($deleteonunactive)
1588
            {
1589
                $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
1590
                $sql.= " WHERE ".$this->db->decrypt('name')." = '".$name."'";
1591
                $sql.= " AND entity in (0, ".$conf->entity.")";
1592
                dol_syslog(get_class($this)."::delete_const", LOG_DEBUG);
1593
                if (! $this->db->query($sql))
1594
                {
1595
                    $this->error=$this->db->lasterror();
1596
                    $err++;
1597
                }
1598
            }
1599
        }
1600
1601
        return $err;
1602
    }
1603
1604
    /**
1605
     * Adds access rights
1606
     *
1607
     * @param   int $reinitadminperms   If 1, we also grant them to all admin users
1608
     * @param   int $force_entity       Force current entity
1609
     * @param   int	$notrigger			1=Does not execute triggers, 0= execute triggers
1610
     * @return  int                     Error count (0 if OK)
1611
     */
1612
    function insert_permissions($reinitadminperms=0, $force_entity=null, $notrigger=0)
1613
    {
1614
        global $conf,$user;
1615
1616
        $err=0;
1617
        $entity=(! empty($force_entity) ? $force_entity : $conf->entity);
1618
1619
        // Test if module is activated
1620
        $sql_del = "SELECT ".$this->db->decrypt('value')." as value";
1621
        $sql_del.= " FROM ".MAIN_DB_PREFIX."const";
1622
        $sql_del.= " WHERE ".$this->db->decrypt('name')." = '".$this->db->escape($this->const_name)."'";
1623
        $sql_del.= " AND entity IN (0,".$entity.")";
1624
1625
        dol_syslog(get_class($this)."::insert_permissions", LOG_DEBUG);
1626
        $resql=$this->db->query($sql_del);
1627
1628
        if ($resql)
1629
        {
1630
            $obj=$this->db->fetch_object($resql);
1631
            if ($obj !== null && ! empty($obj->value) && ! empty($this->rights))
1632
            {
1633
                // If the module is active
1634
                foreach ($this->rights as $key => $value)
1635
                {
1636
                    $r_id       = $this->rights[$key][0];
1637
                    $r_desc     = $this->rights[$key][1];
1638
                    $r_type     = isset($this->rights[$key][2])?$this->rights[$key][2]:'';
1639
                    $r_def      = $this->rights[$key][3];
1640
                    $r_perms    = $this->rights[$key][4];
1641
                    $r_subperms = isset($this->rights[$key][5])?$this->rights[$key][5]:'';
1642
                    $r_modul    = $this->rights_class;
1643
1644
                    if (empty($r_type)) $r_type='w';
1645
1646
                    // Search if perm already present
1647
                    $sql = "SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."rights_def";
1648
                    $sql.= " WHERE id = ".$r_id." AND entity = ".$entity;
1649
                    $resqlselect=$this->db->query($sql);
1650
1651
                    $obj = $this->db->fetch_object($resqlselect);
1652
                    if ($obj->nb == 0)
1653
                    {
1654
                        if (dol_strlen($r_perms) )
1655
                        {
1656
                            if (dol_strlen($r_subperms) )
1657
                            {
1658
                                $sql = "INSERT INTO ".MAIN_DB_PREFIX."rights_def";
1659
                                $sql.= " (id, entity, libelle, module, type, bydefault, perms, subperms)";
1660
                                $sql.= " VALUES ";
1661
                                $sql.= "(".$r_id.",".$entity.",'".$this->db->escape($r_desc)."','".$r_modul."','".$r_type."',".$r_def.",'".$r_perms."','".$r_subperms."')";
1662
                            }
1663
                            else
1664
                            {
1665
                                $sql = "INSERT INTO ".MAIN_DB_PREFIX."rights_def";
1666
                                $sql.= " (id, entity, libelle, module, type, bydefault, perms)";
1667
                                $sql.= " VALUES ";
1668
                                $sql.= "(".$r_id.",".$entity.",'".$this->db->escape($r_desc)."','".$r_modul."','".$r_type."',".$r_def.",'".$r_perms."')";
1669
                            }
1670
                        }
1671
                        else
1672
                        {
1673
                            $sql = "INSERT INTO ".MAIN_DB_PREFIX."rights_def ";
1674
                            $sql .= " (id, entity, libelle, module, type, bydefault)";
1675
                            $sql .= " VALUES ";
1676
                            $sql .= "(".$r_id.",".$entity.",'".$this->db->escape($r_desc)."','".$r_modul."','".$r_type."',".$r_def.")";
1677
                        }
1678
1679
                        $resqlinsert=$this->db->query($sql,1);
1680
1681
                        if (! $resqlinsert)
1682
                        {
1683
                            if ($this->db->errno() != "DB_ERROR_RECORD_ALREADY_EXISTS")
1684
                            {
1685
                                $this->error=$this->db->lasterror();
1686
                                $err++;
1687
                                break;
1688
                            }
1689
                            else dol_syslog(get_class($this)."::insert_permissions record already exists", LOG_INFO);
1690
1691
                        }
1692
1693
                        $this->db->free($resqlinsert);
1694
                    }
1695
1696
                    $this->db->free($resqlselect);
1697
1698
                    // If we want to init permissions on admin users
1699
                    if ($reinitadminperms)
1700
                    {
1701
                        if (! class_exists('User')) {
1702
                            require_once DOL_DOCUMENT_ROOT . '/user/class/user.class.php';
1703
                        }
1704
                        $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."user WHERE admin = 1";
1705
                        dol_syslog(get_class($this)."::insert_permissions Search all admin users", LOG_DEBUG);
1706
                        $resqlseladmin=$this->db->query($sql,1);
1707
                        if ($resqlseladmin)
1708
                        {
1709
                            $num=$this->db->num_rows($resqlseladmin);
1710
                            $i=0;
1711
                            while ($i < $num)
1712
                            {
1713
                                $obj2=$this->db->fetch_object($resqlseladmin);
1714
                                dol_syslog(get_class($this)."::insert_permissions Add permission to user id=".$obj2->rowid);
1715
                                $tmpuser=new User($this->db);
1716
                                $tmpuser->fetch($obj2->rowid);
1717
                                if (!empty($tmpuser->id)) {
1718
                                    $tmpuser->addrights($r_id, '', '', 0, 1);
1719
                                }
1720
                                $i++;
1721
                            }
1722
                            if (! empty($user->admin))  // Reload permission for current user if defined
1723
                            {
1724
                                // We reload permissions
1725
                                $user->clearrights();
1726
                                $user->getrights();
1727
                            }
1728
                        }
1729
                        else dol_print_error($this->db);
1730
                    }
1731
                }
1732
            }
1733
            $this->db->free($resql);
1734
        }
1735
        else
1736
        {
1737
            $this->error=$this->db->lasterror();
1738
            $err++;
1739
        }
1740
1741
        return $err;
1742
    }
1743
1744
1745
    /**
1746
     * Removes access rights
1747
     *
1748
     * @return  int                     Error count (0 if OK)
1749
     */
1750
    function delete_permissions()
1751
    {
1752
        global $conf;
1753
1754
        $err=0;
1755
1756
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."rights_def";
1757
        $sql.= " WHERE module = '".$this->db->escape($this->rights_class)."'";
1758
        $sql.= " AND entity = ".$conf->entity;
1759
        dol_syslog(get_class($this)."::delete_permissions", LOG_DEBUG);
1760
        if (! $this->db->query($sql))
1761
        {
1762
            $this->error=$this->db->lasterror();
1763
            $err++;
1764
        }
1765
1766
        return $err;
1767
    }
1768
1769
1770
    /**
1771
     * Adds menu entries
1772
     *
1773
     * @return  int     Error count (0 if OK)
1774
     */
1775
    function insert_menus()
1776
    {
1777
        global $user;
1778
1779
        if (! is_array($this->menu) || empty($this->menu)) return 0;
1780
1781
        require_once DOL_DOCUMENT_ROOT . '/core/class/menubase.class.php';
1782
1783
        $err=0;
1784
1785
        $this->db->begin();
1786
1787
        foreach ($this->menu as $key => $value)
1788
        {
1789
            $menu = new Menubase($this->db);
1790
            $menu->menu_handler='all';
1791
            $menu->module=$this->rights_class;
1792
            if (! $this->menu[$key]['fk_menu'])
1793
            {
1794
                $menu->fk_menu=0;
1795
            }
1796
            else
1797
            {
1798
                $foundparent=0;
1799
                $fk_parent=$this->menu[$key]['fk_menu'];
1800
                if (preg_match('/^r=/',$fk_parent))	// old deprecated method
1801
                {
1802
                    $fk_parent=str_replace('r=','',$fk_parent);
1803
                    if (isset($this->menu[$fk_parent]['rowid']))
1804
                    {
1805
                        $menu->fk_menu=$this->menu[$fk_parent]['rowid'];
1806
                        $foundparent=1;
1807
                    }
1808
                }
1809
                elseif (preg_match('/^fk_mainmenu=([a-zA-Z0-9_]+),fk_leftmenu=([a-zA-Z0-9_]+)$/',$fk_parent,$reg))
1810
                {
1811
                    $menu->fk_menu=-1;
1812
                    $menu->fk_mainmenu=$reg[1];
1813
                    $menu->fk_leftmenu=$reg[2];
1814
                    $foundparent=1;
1815
                }
1816
                elseif (preg_match('/^fk_mainmenu=([a-zA-Z0-9_]+)$/',$fk_parent,$reg))
1817
                {
1818
                    $menu->fk_menu=-1;
1819
                    $menu->fk_mainmenu=$reg[1];
1820
                    $menu->fk_leftmenu='';
1821
                    $foundparent=1;
1822
                }
1823
                if (! $foundparent)
1824
                {
1825
                    $this->error="ErrorBadDefinitionOfMenuArrayInModuleDescriptor";
1826
                    dol_syslog(get_class($this)."::insert_menus ".$this->error." ".$this->menu[$key]['fk_menu'], LOG_ERR);
1827
                    $err++;
1828
                }
1829
            }
1830
            $menu->type=$this->menu[$key]['type'];
1831
            $menu->mainmenu=isset($this->menu[$key]['mainmenu'])?$this->menu[$key]['mainmenu']:(isset($menu->fk_mainmenu)?$menu->fk_mainmenu:'');
1832
            $menu->leftmenu=isset($this->menu[$key]['leftmenu'])?$this->menu[$key]['leftmenu']:'';
1833
            $menu->titre=$this->menu[$key]['titre'];
1834
            $menu->url=$this->menu[$key]['url'];
1835
            $menu->langs=$this->menu[$key]['langs'];
1836
            $menu->position=$this->menu[$key]['position'];
1837
            $menu->perms=$this->menu[$key]['perms'];
1838
            $menu->target=$this->menu[$key]['target'];
1839
            $menu->user=$this->menu[$key]['user'];
1840
            $menu->enabled=isset($this->menu[$key]['enabled'])?$this->menu[$key]['enabled']:0;
1841
            $menu->position=$this->menu[$key]['position'];
1842
1843
            if (! $err)
1844
            {
1845
                $result=$menu->create($user);	// Save menu entry into table llx_menu
1846
                if ($result > 0)
1847
                {
1848
                    $this->menu[$key]['rowid']=$result;
1849
                }
1850
                else
1851
                {
1852
                    $this->error=$menu->error;
1853
                    dol_syslog(get_class($this).'::insert_menus result='.$result." ".$this->error, LOG_ERR);
1854
                    $err++;
1855
                    break;
1856
                }
1857
            }
1858
        }
1859
1860
        if (! $err)
1861
        {
1862
            $this->db->commit();
1863
        }
1864
        else
1865
        {
1866
            dol_syslog(get_class($this)."::insert_menus ".$this->error, LOG_ERR);
1867
            $this->db->rollback();
1868
        }
1869
1870
        return $err;
1871
    }
1872
1873
1874
    /**
1875
     * Removes menu entries
1876
     *
1877
     * @return  int Error count (0 if OK)
1878
     */
1879
    function delete_menus()
1880
    {
1881
        global $conf;
1882
1883
        $err=0;
1884
1885
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."menu";
1886
        $sql.= " WHERE module = '".$this->db->escape($this->rights_class)."'";
1887
        $sql.= " AND entity = ".$conf->entity;
1888
1889
        dol_syslog(get_class($this)."::delete_menus", LOG_DEBUG);
1890
        $resql=$this->db->query($sql);
1891
        if (! $resql)
1892
        {
1893
            $this->error=$this->db->lasterror();
1894
            $err++;
1895
        }
1896
1897
        return $err;
1898
    }
1899
1900
    /**
1901
     * Creates directories
1902
     *
1903
     * @return  int Error count (0 if OK)
1904
     */
1905
    function create_dirs()
1906
    {
1907
        global $langs, $conf;
1908
1909
        $err=0;
1910
1911
        if (isset($this->dirs) && is_array($this->dirs))
1912
        {
1913
            foreach ($this->dirs as $key => $value)
1914
            {
1915
                $addtodatabase=0;
1916
1917
                if (! is_array($value)) $dir=$value;    // Default simple mode
1918
                else {
1919
                    $constname = $this->const_name."_DIR_";
1920
                    $dir       = $this->dirs[$key][1];
1921
                    $addtodatabase = empty($this->dirs[$key][2])?'':$this->dirs[$key][2]; // Create constante in llx_const
1922
                    $subname   = empty($this->dirs[$key][3])?'':strtoupper($this->dirs[$key][3]); // Add submodule name (ex: $conf->module->submodule->dir_output)
1923
                    $forcename = empty($this->dirs[$key][4])?'':strtoupper($this->dirs[$key][4]); // Change the module name if different
1924
1925
                    if (! empty($forcename)) $constname = 'MAIN_MODULE_'.$forcename."_DIR_";
1926
                    if (! empty($subname))   $constname = $constname.$subname."_";
1927
1928
                    $name = $constname.strtoupper($this->dirs[$key][0]);
1929
                }
1930
1931
                // Define directory full path ($dir must start with "/")
1932
                if (empty($conf->global->MAIN_MODULE_MULTICOMPANY) || $conf->entity == 1) $fulldir = DOL_DATA_ROOT.$dir;
1933
                else $fulldir = DOL_DATA_ROOT."/".$conf->entity.$dir;
1934
                // Create dir if it does not exists
1935
                if (! empty($fulldir) && ! file_exists($fulldir))
1936
                {
1937
                    if (dol_mkdir($fulldir, DOL_DATA_ROOT) < 0)
1938
                    {
1939
                        $this->error = $langs->trans("ErrorCanNotCreateDir",$fulldir);
1940
                        dol_syslog(get_class($this)."::_init ".$this->error, LOG_ERR);
1941
                        $err++;
1942
                    }
1943
                }
1944
1945
                // Define the constant in database if requested (not the default mode)
1946
                if (! empty($addtodatabase))
1947
                {
1948
                    $result = $this->insert_dirs($name, $dir);
0 ignored issues
show
Bug introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1949
                    if ($result) $err++;
1950
                }
1951
            }
1952
        }
1953
1954
        return $err;
1955
    }
1956
1957
1958
    /**
1959
     * Adds directories definitions
1960
     *
1961
     * @param   string  $name   Name
1962
     * @param   string  $dir    Directory
1963
     *
1964
     * @return  int             Error count (0 if OK)
1965
     */
1966
    function insert_dirs($name,$dir)
1967
    {
1968
        global $conf;
1969
1970
        $err=0;
1971
1972
        $sql = "SELECT count(*)";
1973
        $sql.= " FROM ".MAIN_DB_PREFIX."const";
1974
        $sql.= " WHERE ".$this->db->decrypt('name')." = '".$name."'";
1975
        $sql.= " AND entity = ".$conf->entity;
1976
1977
        dol_syslog(get_class($this)."::insert_dirs", LOG_DEBUG);
1978
        $result=$this->db->query($sql);
1979
        if ($result)
1980
        {
1981
            $row = $this->db->fetch_row($result);
1982
1983
            if ($row[0] == 0)
1984
            {
1985
                $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)";
1986
                $sql.= " VALUES (".$this->db->encrypt($name,1).",'chaine',".$this->db->encrypt($dir,1).",'Directory for module ".$this->name."','0',".$conf->entity.")";
1987
1988
                dol_syslog(get_class($this)."::insert_dirs", LOG_DEBUG);
1989
                $this->db->query($sql);
1990
            }
1991
        }
1992
        else
1993
        {
1994
            $this->error=$this->db->lasterror();
1995
            $err++;
1996
        }
1997
1998
        return $err;
1999
    }
2000
2001
2002
    /**
2003
     * Removes directories
2004
     *
2005
     * @return  int Error count (0 if OK)
2006
     */
2007
    function delete_dirs()
2008
    {
2009
        global $conf;
2010
2011
        $err=0;
2012
2013
        $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
2014
        $sql.= " WHERE ".$this->db->decrypt('name')." LIKE '".$this->const_name."_DIR_%'";
2015
        $sql.= " AND entity = ".$conf->entity;
2016
2017
        dol_syslog(get_class($this)."::delete_dirs", LOG_DEBUG);
2018
        if (! $this->db->query($sql))
2019
        {
2020
            $this->error=$this->db->lasterror();
2021
            $err++;
2022
        }
2023
2024
        return $err;
2025
    }
2026
2027
    /**
2028
     * Adds generic parts
2029
     *
2030
     * @return  int Error count (0 if OK)
2031
     */
2032
    function insert_module_parts()
2033
    {
2034
        global $conf;
2035
2036
        $error=0;
2037
2038
        if (is_array($this->module_parts) && ! empty($this->module_parts))
2039
        {
2040
            foreach($this->module_parts as $key => $value)
2041
            {
2042
    			if (is_array($value) && count($value) == 0) continue;	// Discard empty arrays
2043
2044
    			$entity=$conf->entity; // Reset the current entity
2045
    			$newvalue = $value;
2046
2047
    			// Serialize array parameters
2048
    			if (is_array($value))
2049
    			{
2050
    				// Can defined other parameters
2051
    				if (is_array($value['data']) && ! empty($value['data']))
2052
    				{
2053
    					$newvalue = json_encode($value['data']);
2054
    					if (isset($value['entity'])) $entity = $value['entity'];
2055
    				}
2056
    				else if (isset($value['data']) && !is_array($value['data']))
2057
    				{
2058
    					$newvalue = $value['data'];
2059
    					if (isset($value['entity'])) $entity = $value['entity'];
2060
    				}
2061
    				else
2062
    				{
2063
    					$newvalue = json_encode($value);
2064
    				}
2065
    			}
2066
2067
                $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (";
2068
                $sql.= "name";
2069
                $sql.= ", type";
2070
                $sql.= ", value";
2071
                $sql.= ", note";
2072
                $sql.= ", visible";
2073
                $sql.= ", entity";
2074
                $sql.= ")";
2075
                $sql.= " VALUES (";
2076
                $sql.= $this->db->encrypt($this->const_name."_".strtoupper($key), 1);
2077
                $sql.= ", 'chaine'";
2078
                $sql.= ", ".$this->db->encrypt($newvalue, 1);
2079
                $sql.= ", null";
2080
                $sql.= ", '0'";
2081
                $sql.= ", ".$entity;
2082
                $sql.= ")";
2083
2084
                dol_syslog(get_class($this)."::insert_const_".$key."", LOG_DEBUG);
2085
                $resql=$this->db->query($sql,1);
2086
                if (! $resql)
2087
                {
2088
                    if ($this->db->lasterrno() != 'DB_ERROR_RECORD_ALREADY_EXISTS')
2089
                    {
2090
                        $error++;
2091
                        $this->error=$this->db->lasterror();
2092
                    }
2093
                    else
2094
                    {
2095
                        dol_syslog(get_class($this)."::insert_const_".$key." Record already exists.", LOG_WARNING);
2096
                    }
2097
                }
2098
            }
2099
        }
2100
        return $error;
2101
    }
2102
2103
    /**
2104
     * Removes generic parts
2105
     *
2106
     * @return  int Error count (0 if OK)
2107
     */
2108
    function delete_module_parts()
2109
    {
2110
        global $conf;
2111
2112
        $err=0;
2113
        $entity=$conf->entity;
2114
2115
        if (is_array($this->module_parts) && ! empty($this->module_parts))
2116
        {
2117
            foreach($this->module_parts as $key => $value)
2118
            {
2119
                // If entity is defined
2120
                if (is_array($value) && isset($value['entity'])) $entity = $value['entity'];
2121
2122
                $sql = "DELETE FROM ".MAIN_DB_PREFIX."const";
2123
                $sql.= " WHERE ".$this->db->decrypt('name')." LIKE '".$this->const_name."_".strtoupper($key)."'";
2124
                $sql.= " AND entity = ".$entity;
2125
2126
                dol_syslog(get_class($this)."::delete_const_".$key."", LOG_DEBUG);
2127
                if (! $this->db->query($sql))
2128
                {
2129
                    $this->error=$this->db->lasterror();
2130
                    $err++;
2131
                }
2132
            }
2133
        }
2134
        return $err;
2135
    }
2136
2137
	/**
2138
	 * Function called when module is enabled.
2139
	 * The init function adds tabs, constants, boxes, permissions and menus (defined in constructor) into Dolibarr database.
2140
	 * It also creates data directories
2141
	 *
2142
	 * @param string $options   Options when enabling module ('', 'newboxdefonly', 'noboxes')
2143
     *                          'noboxes' = Do not insert boxes
2144
     *                          'newboxdefonly' = For boxes, insert def of boxes only and not boxes activation
2145
	 * @return int				1 if OK, 0 if KO
2146
	 */
2147
	public function init($options = '')
2148
	{
2149
		return $this->_init(array(), $options);
2150
	}
2151
2152
	/**
2153
	 * Function called when module is disabled.
2154
	 * The remove function removes tabs, constants, boxes, permissions and menus from Dolibarr database.
2155
	 * Data directories are not deleted
2156
	 *
2157
	 * @param      string	$options    Options when enabling module ('', 'noboxes')
2158
	 * @return     int             		1 if OK, 0 if KO
2159
	 */
2160
	public function remove($options = '')
2161
	{
2162
		return $this->_remove(array(), $options);
2163
	}
2164
2165
}
2166