Completed
Branch develop (9ce07b)
by
unknown
26:31
created

User::setCategories()   B

Complexity

Conditions 7
Paths 36

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 36
nop 1
dl 0
loc 35
rs 8.4266
c 0
b 0
f 0
1
<?php
2
/* Copyright (c) 2002-2007 Rodolphe Quiedeville <[email protected]>
3
 * Copyright (c) 2002-2003 Jean-Louis Bergamo   <[email protected]>
4
 * Copyright (c) 2004-2012 Laurent Destailleur  <[email protected]>
5
 * Copyright (C) 2004      Sebastien Di Cintio  <[email protected]>
6
 * Copyright (C) 2004      Benoit Mortier       <[email protected]>
7
 * Copyright (C) 2005-2017 Regis Houssin        <[email protected]>
8
 * Copyright (C) 2005      Lionel Cousteix      <[email protected]>
9
 * Copyright (C) 2011      Herve Prot           <[email protected]>
10
 * Copyright (C) 2013-2018 Philippe Grand       <[email protected]>
11
 * Copyright (C) 2013-2015 Alexandre Spangaro   <[email protected]>
12
 * Copyright (C) 2015      Marcos García        <[email protected]>
13
 * Copyright (C) 2018      charlene Benke       <[email protected]>
14
 * Copyright (C) 2018      Nicolas ZABOURI      <[email protected]>
15
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 3 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28
 */
29
30
/**
31
 *  \file       htdocs/user/class/user.class.php
32
 *	\brief      File of class to manage users
33
 *  \ingroup	core
34
 */
35
36
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
37
38
/**
39
 *	Class to manage Dolibarr users
40
 */
41
class User extends CommonObject
42
{
43
	/**
44
	 * @var string ID to identify managed object
45
	 */
46
	public $element='user';
47
48
	/**
49
	 * @var string Name of table without prefix where object is stored
50
	 */
51
	public $table_element='user';
52
53
	/**
54
	 * @var int Field with ID of parent key if this field has a parent
55
	 */
56
	public $fk_element='fk_user';
57
58
	/**
59
	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
60
	 * @var int
61
	 */
62
	public $ismultientitymanaged = 1;
63
64
	public $id=0;
65
	public $statut;
66
	public $ldap_sid;
67
	public $search_sid;
68
	public $employee;
69
	public $gender;
70
	public $birth;
71
	public $email;
72
73
	public $skype;
74
	public $twitter;
75
	public $facebook;
76
77
	public $job;			// job position
78
	public $signature;
79
80
	/**
81
	 * @var string Address
82
	 */
83
	public $address;
84
85
	public $zip;
86
	public $town;
87
	public $state_id;		// The state/department
88
	public $state_code;
89
	public $state;
90
	public $office_phone;
91
	public $office_fax;
92
	public $user_mobile;
93
	public $admin;
94
	public $login;
95
	public $api_key;
96
97
	/**
98
	 * @var int Entity
99
	 */
100
	public $entity;
101
102
	//! Clear password in memory
103
	public $pass;
104
	//! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
105
	public $pass_indatabase;
106
	//! Encrypted password in database (always defined)
107
	public $pass_indatabase_crypted;
108
109
	public $datec;
110
	public $datem;
111
112
	//! If this is defined, it is an external user
113
	/**
114
	 * @deprecated
115
	 * @see socid
116
	 */
117
	public $societe_id;
118
	/**
119
	 * @deprecated
120
	 * @see contactid
121
	 */
122
	public $contact_id;
123
	public $socid;
124
	public $contactid;
125
126
	/**
127
     * @var int ID
128
     */
129
	public $fk_member;
130
131
	/**
132
	 * @var int User ID
133
	 */
134
	public $fk_user;
135
136
	public $clicktodial_url;
137
	public $clicktodial_login;
138
	public $clicktodial_password;
139
	public $clicktodial_poste;
140
141
	public $datelastlogin;
142
	public $datepreviouslogin;
143
	public $photo;
144
	public $lang;
145
146
	public $rights;                        // Array of permissions user->rights->permx
147
	public $all_permissions_are_loaded;	   // All permission are loaded
148
	public $nb_rights;			           // Number of rights granted to the user
149
	private $_tab_loaded=array();		   // Cache array of already loaded permissions
150
151
	public $conf;           		// To store personal config
152
	public $default_values;         // To store default values for user
153
	public $lastsearch_values_tmp;  // To store current search criterias for user
154
	public $lastsearch_values;      // To store last saved search criterias for user
155
156
	public $users = array();		// To store all tree of users hierarchy
157
	public $parentof;				// To store an array of all parents for all ids.
158
	private $cache_childids;
159
160
	public $accountancy_code;			// Accountancy code in prevision of the complete accountancy module
161
162
	public $thm;					// Average cost of employee - Used for valuation of time spent
163
	public $tjm;					// Average cost of employee
164
165
	public $salary;					// Monthly salary       - Denormalized value from llx_user_employment
166
	public $salaryextra;				// Monthly salary extra - Denormalized value from llx_user_employment
167
	public $weeklyhours;				// Weekly hours         - Denormalized value from llx_user_employment
168
169
	public $color;						// Define background color for user in agenda
170
171
	public $dateemployment;			// Define date of employment by company
172
	public $dateemploymentend;		// Define date of employment end by company
173
174
	public $default_c_exp_tax_cat;
175
	public $default_range;
176
177
	public $fields = array(
178
        'rowid'=>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1,  'index'=>1, 'position'=>1, 'comment'=>'Id'),
179
        'lastname'=>array('type'=>'varchar(50)', 'label'=>'Name', 'enabled'=>1, 'visible'=>1,  'notnull'=>1,  'showoncombobox'=>1, 'index'=>1, 'position'=>20, 'searchall'=>1, 'comment'=>'Reference of object'),
180
        'firstname'=>array('type'=>'varchar(50)', 'label'=>'Name','enabled'=>1, 'visible'=>1,  'notnull'=>1,  'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'),
181
    );
182
183
	/**
184
	 *    Constructor of the class
185
	 *
186
	 *    @param   DoliDb  $db     Database handler
187
	 */
188
	function __construct($db)
189
	{
190
		$this->db = $db;
191
192
		// User preference
193
		$this->liste_limit = 0;
194
		$this->clicktodial_loaded = 0;
195
196
		// For cache usage
197
		$this->all_permissions_are_loaded = 0;
198
		$this->nb_rights = 0;
199
200
		// Force some default values
201
		$this->admin = 0;
202
		$this->employee = 1;
203
204
		$this->conf				    = new stdClass();
205
		$this->rights				= new stdClass();
206
		$this->rights->user			= new stdClass();
207
		$this->rights->user->user	= new stdClass();
208
		$this->rights->user->self	= new stdClass();
209
	}
210
211
	/**
212
	 *	Load a user from database with its id or ref (login).
213
	 *  This function does not load permissions, only user properties. Use getrights() for this just after the fetch.
214
	 *
215
	 *	@param	int		$id		       		If defined, id to used for search
216
	 * 	@param  string	$login       		If defined, login to used for search
217
	 *	@param  string	$sid				If defined, sid to used for search
218
	 * 	@param	int		$loadpersonalconf	1=also load personal conf of user (in $user->conf->xxx), 0=do not load personal conf.
219
	 *  @param  int     $entity             If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup.
220
	 * 	@return	int							<0 if KO, 0 not found, >0 if OK
221
	 */
222
	function fetch($id='', $login='', $sid='', $loadpersonalconf=0, $entity=-1)
223
	{
224
		global $conf, $user;
225
226
		// Clean parameters
227
		$login=trim($login);
228
229
		// Get user
230
		$sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.birth, u.email, u.job, u.skype, u.twitter, u.facebook,";
231
		$sql.= " u.signature, u.office_phone, u.office_fax, u.user_mobile,";
232
		$sql.= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
233
		$sql.= " u.admin, u.login, u.note,";
234
		$sql.= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,";
235
		$sql.= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid,";
236
		$sql.= " u.statut, u.lang, u.entity,";
237
		$sql.= " u.datec as datec,";
238
		$sql.= " u.tms as datem,";
239
		$sql.= " u.datelastlogin as datel,";
240
		$sql.= " u.datepreviouslogin as datep,";
241
		$sql.= " u.photo as photo,";
242
		$sql.= " u.openid as openid,";
243
		$sql.= " u.accountancy_code,";
244
		$sql.= " u.thm,";
245
		$sql.= " u.tjm,";
246
		$sql.= " u.salary,";
247
		$sql.= " u.salaryextra,";
248
		$sql.= " u.weeklyhours,";
249
		$sql.= " u.color,";
250
		$sql.= " u.dateemployment, u.dateemploymentend,";
251
		$sql.= " u.ref_int, u.ref_ext,";
252
		$sql.= " u.default_range, u.default_c_exp_tax_cat,";			// Expense report default mode
253
		$sql.= " c.code as country_code, c.label as country,";
254
		$sql.= " d.code_departement as state_code, d.nom as state";
255
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
256
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON u.fk_country = c.rowid";
257
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON u.fk_state = d.rowid";
258
259
		if ($entity < 0)
260
		{
261
			if ((empty($conf->multicompany->enabled) || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) && (! empty($user->entity)))
262
			{
263
				$sql.= " WHERE u.entity IN (0,".$conf->entity.")";
264
			}
265
			else
266
			{
267
				$sql.= " WHERE u.entity IS NOT NULL";    // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database
268
			}
269
		}
270
		else  // The fetch was forced on an entity
271
		{
272
			if (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))
273
				$sql.= " WHERE u.entity IS NOT NULL";    // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database
274
			else
275
				$sql.= " WHERE u.entity IN (0, ".(($entity!='' && $entity >= 0)?$entity:$conf->entity).")";   // search in entity provided in parameter
276
		}
277
278
		if ($sid)    // permet une recherche du user par son SID ActiveDirectory ou Samba
279
		{
280
			$sql.= " AND (u.ldap_sid = '".$this->db->escape($sid)."' OR u.login = '".$this->db->escape($login)."') LIMIT 1";
281
		}
282
		else if ($login)
283
		{
284
			$sql.= " AND u.login = '".$this->db->escape($login)."'";
285
		}
286
		else
287
		{
288
			$sql.= " AND u.rowid = ".$id;
289
		}
290
		$sql.= " ORDER BY u.entity ASC";    // Avoid random result when there is 2 login in 2 different entities
291
292
		$result = $this->db->query($sql);
293
		if ($result)
294
		{
295
			$obj = $this->db->fetch_object($result);
296
			if ($obj)
297
			{
298
				$this->id 			= $obj->rowid;
299
				$this->ref 			= $obj->rowid;
300
301
				$this->ref_int 		= $obj->ref_int;
302
				$this->ref_ext 		= $obj->ref_ext;
303
304
				$this->ldap_sid 	= $obj->ldap_sid;
305
				$this->lastname		= $obj->lastname;
306
				$this->firstname 	= $obj->firstname;
307
308
				$this->employee		= $obj->employee;
309
310
				$this->login		= $obj->login;
311
				$this->gender       = $obj->gender;
312
				$this->birth        = $this->db->jdate($obj->birth);
313
				$this->pass_indatabase = $obj->pass;
314
				$this->pass_indatabase_crypted = $obj->pass_crypted;
315
				$this->pass			= $obj->pass;
316
				$this->pass_temp	= $obj->pass_temp;
317
				$this->api_key		= $obj->api_key;
318
319
				$this->address 		= $obj->address;
320
				$this->zip 			= $obj->zip;
321
				$this->town 		= $obj->town;
322
323
				$this->country_id   = $obj->country_id;
324
				$this->country_code = $obj->country_id?$obj->country_code:'';
325
				//$this->country 		= $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
326
327
				$this->state_id     = $obj->state_id;
328
				$this->state_code   = $obj->state_code;
329
				$this->state        = ($obj->state!='-'?$obj->state:'');
330
331
				$this->office_phone	= $obj->office_phone;
332
				$this->office_fax   = $obj->office_fax;
333
				$this->user_mobile  = $obj->user_mobile;
334
				$this->email		= $obj->email;
335
				$this->skype		= $obj->skype;
336
				$this->twitter		= $obj->twitter;
337
				$this->facebook		= $obj->facebook;
338
				$this->job			= $obj->job;
339
				$this->signature	= $obj->signature;
340
				$this->admin		= $obj->admin;
341
				$this->note			= $obj->note;
342
				$this->statut		= $obj->statut;
343
				$this->photo		= $obj->photo;
344
				$this->openid		= $obj->openid;
345
				$this->lang			= $obj->lang;
346
				$this->entity		= $obj->entity;
347
				$this->accountancy_code		= $obj->accountancy_code;
348
				$this->thm			= $obj->thm;
349
				$this->tjm			= $obj->tjm;
350
				$this->salary		= $obj->salary;
351
				$this->salaryextra	= $obj->salaryextra;
352
				$this->weeklyhours	= $obj->weeklyhours;
353
				$this->color		= $obj->color;
354
				$this->dateemployment	= $this->db->jdate($obj->dateemployment);
355
				$this->dateemploymentend = $this->db->jdate($obj->dateemploymentend);
356
357
				$this->datec				= $this->db->jdate($obj->datec);
358
				$this->datem				= $this->db->jdate($obj->datem);
359
				$this->datelastlogin		= $this->db->jdate($obj->datel);
360
				$this->datepreviouslogin	= $this->db->jdate($obj->datep);
361
362
				$this->societe_id           = $obj->fk_soc;		// deprecated
363
				$this->contact_id           = $obj->fk_socpeople;	// deprecated
364
				$this->socid                = $obj->fk_soc;
365
				$this->contactid            = $obj->fk_socpeople;
366
				$this->fk_member            = $obj->fk_member;
367
				$this->fk_user        		= $obj->fk_user;
368
369
				$this->default_range		= $obj->default_range;
370
				$this->default_c_exp_tax_cat	= $obj->default_c_exp_tax_cat;
371
372
				// Protection when module multicompany was set, admin was set to first entity and then, the module was disabled,
373
				// in such case, this admin user must be admin for ALL entities.
374
				if (empty($conf->multicompany->enabled) && $this->admin && $this->entity == 1) $this->entity = 0;
375
376
				// Retreive all extrafield
377
				// fetch optionals attributes and labels
378
				$this->fetch_optionals();
379
380
				$this->db->free($result);
381
			}
382
			else
383
			{
384
				$this->error="USERNOTFOUND";
385
				dol_syslog(get_class($this)."::fetch user not found", LOG_DEBUG);
386
387
				$this->db->free($result);
388
				return 0;
389
			}
390
		}
391
		else
392
		{
393
			$this->error=$this->db->lasterror();
394
			return -1;
395
		}
396
397
		// To get back the global configuration unique to the user
398
		if ($loadpersonalconf)
399
		{
400
			// Load user->conf for user
401
			$sql = "SELECT param, value FROM ".MAIN_DB_PREFIX."user_param";
402
			$sql.= " WHERE fk_user = ".$this->id;
403
			$sql.= " AND entity = ".$conf->entity;
404
			//dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
405
			$resql=$this->db->query($sql);
406
			if ($resql)
407
			{
408
				$num = $this->db->num_rows($resql);
409
				$i = 0;
410
				while ($i < $num)
411
				{
412
					$obj = $this->db->fetch_object($resql);
413
					$p=(! empty($obj->param)?$obj->param:'');
414
					if (! empty($p)) $this->conf->$p = $obj->value;
415
					$i++;
416
				}
417
				$this->db->free($resql);
418
			}
419
			else
420
			{
421
				$this->error=$this->db->lasterror();
422
				return -2;
423
			}
424
425
			$result = $this->loadDefaultValues();
426
427
			if ($result < 0)
428
			{
429
				$this->error=$this->db->lasterror();
430
				return -3;
431
			}
432
		}
433
434
		return 1;
435
	}
436
437
	/**
438
	 *  Load default value in property ->default_values
439
	 *
440
	 *  @return int						> 0 if OK, < 0 if KO
441
	 */
442
	function loadDefaultValues()
443
	{
444
		global $conf;
445
446
		// Load user->default_values for user. TODO Save this in memcached ?
447
		$sql = "SELECT rowid, entity, type, page, param, value";
448
		$sql.= " FROM ".MAIN_DB_PREFIX."default_values";
449
		$sql.= " WHERE entity IN (".($this->entity > 0 ? $this->entity.", " : "").$conf->entity.")";	// Entity of user (if defined) + current entity
450
		$sql.= " AND user_id IN (0".($this->id > 0 ? ", ".$this->id : "").")";							// User 0 (all) + me (if defined)
451
		$resql = $this->db->query($sql);
452
		if ($resql)
453
		{
454
			while ($obj = $this->db->fetch_object($resql))
455
			{
456
				if (! empty($obj->page) && ! empty($obj->type) && ! empty($obj->param))
457
				{
458
					// $obj->page is relative URL with or without params
459
					// $obj->type can be 'filters', 'sortorder', 'createform', ...
460
					// $obj->param is key or param
461
					$pagewithoutquerystring=$obj->page;
462
					$pagequeries='';
463
					if (preg_match('/^([^\?]+)\?(.*)$/', $pagewithoutquerystring, $reg))	// There is query param
464
					{
465
						$pagewithoutquerystring=$reg[1];
466
						$pagequeries=$reg[2];
467
					}
468
					$this->default_values[$pagewithoutquerystring][$obj->type][$pagequeries?$pagequeries:'_noquery_'][$obj->param]=$obj->value;
469
					//if ($pagequeries) $this->default_values[$pagewithoutquerystring][$obj->type.'_queries']=$pagequeries;
470
				}
471
			}
472
			// Sort by key, so _noquery_ is last
473
			if(!empty($this->default_values)) {
474
				foreach($this->default_values as $a => $b)
475
				{
476
					foreach($b as $c => $d)
477
					{
478
						krsort($this->default_values[$a][$c]);
479
					}
480
				}
481
			}
482
			$this->db->free($resql);
483
484
			return 1;
485
		}
486
		else
487
		{
488
			dol_print_error($this->db);
489
			return -1;
490
		}
491
	}
492
493
	/**
494
	 *  Add a right to the user
495
	 *
496
	 * 	@param	int		$rid			Id of permission to add or 0 to add several permissions
497
	 *  @param  string	$allmodule		Add all permissions of module $allmodule
498
	 *  @param  string	$allperms		Add all permissions of module $allmodule, subperms $allperms only
499
	 *  @param	int		$entity			Entity to use
500
	 *  @param  int	    $notrigger		1=Does not execute triggers, 0=Execute triggers
501
	 *  @return int						> 0 if OK, < 0 if KO
502
	 *  @see	clearrights, delrights, getrights
503
	 */
504
	function addrights($rid, $allmodule='', $allperms='', $entity=0, $notrigger=0)
505
	{
506
		global $conf, $user, $langs;
507
508
		$entity = (! empty($entity)?$entity:$conf->entity);
509
510
		dol_syslog(get_class($this)."::addrights $rid, $allmodule, $allperms, $entity");
511
		$error=0;
512
		$whereforadd='';
513
514
		$this->db->begin();
515
516
		if (! empty($rid))
517
		{
518
			// Si on a demande ajout d'un droit en particulier, on recupere
519
			// les caracteristiques (module, perms et subperms) de ce droit.
520
			$sql = "SELECT module, perms, subperms";
521
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
522
			$sql.= " WHERE id = '".$this->db->escape($rid)."'";
523
			$sql.= " AND entity = ".$entity;
524
525
			$result=$this->db->query($sql);
526
			if ($result) {
527
				$obj = $this->db->fetch_object($result);
528
				$module=$obj->module;
529
				$perms=$obj->perms;
530
				$subperms=$obj->subperms;
531
			}
532
			else {
533
				$error++;
534
				dol_print_error($this->db);
535
			}
536
537
			// Where pour la liste des droits a ajouter
538
			$whereforadd="id=".$this->db->escape($rid);
539
			// Ajout des droits induits
540
			if (! empty($subperms))   $whereforadd.=" OR (module='$module' AND perms='$perms' AND (subperms='lire' OR subperms='read'))";
0 ignored issues
show
Bug introduced by
The variable $module 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...
Bug introduced by
The variable $perms 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...
541
			else if (! empty($perms)) $whereforadd.=" OR (module='$module' AND (perms='lire' OR perms='read') AND subperms IS NULL)";
542
		}
543
		else {
544
			// On a pas demande un droit en particulier mais une liste de droits
545
			// sur la base d'un nom de module de de perms
546
			// Where pour la liste des droits a ajouter
547
			if (! empty($allmodule))
548
			{
549
				if ($allmodule == 'allmodules')
550
				{
551
					$whereforadd='allmodules';
552
				}
553
				else
554
				{
555
					$whereforadd="module='".$this->db->escape($allmodule)."'";
556
					if (! empty($allperms))  $whereforadd.=" AND perms='".$this->db->escape($allperms)."'";
557
				}
558
			}
559
		}
560
561
		// Ajout des droits trouves grace au critere whereforadd
562
		if (! empty($whereforadd))
563
		{
564
			//print "$module-$perms-$subperms";
565
			$sql = "SELECT id";
566
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
567
			$sql.= " WHERE entity = ".$entity;
568
			if (! empty($whereforadd) && $whereforadd != 'allmodules') {
569
				$sql.= " AND ".$whereforadd;
570
			}
571
572
			$result=$this->db->query($sql);
573
			if ($result)
574
			{
575
				$num = $this->db->num_rows($result);
576
				$i = 0;
577
				while ($i < $num)
578
				{
579
					$obj = $this->db->fetch_object($result);
580
					$nid = $obj->id;
581
582
					$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = ".$this->id." AND fk_id=".$nid." AND entity = ".$entity;
583
					if (! $this->db->query($sql)) $error++;
584
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_rights (entity, fk_user, fk_id) VALUES (".$entity.", ".$this->id.", ".$nid.")";
585
					if (! $this->db->query($sql)) $error++;
586
587
					$i++;
588
				}
589
			}
590
			else
591
			{
592
				$error++;
593
				dol_print_error($this->db);
594
			}
595
		}
596
597
		if (! $error && ! $notrigger)
598
		{
599
			$langs->load("other");
600
			$this->context = array('audit'=>$langs->trans("PermissionsAdd").($rid?' (id='.$rid.')':''));
601
602
			// Call trigger
603
			$result=$this->call_trigger('USER_MODIFY',$user);
604
			if ($result < 0) { $error++; }
605
			// End call triggers
606
		}
607
608
		if ($error) {
609
			$this->db->rollback();
610
			return -$error;
611
		}
612
		else {
613
			$this->db->commit();
614
			return 1;
615
		}
616
	}
617
618
619
	/**
620
	 *  Remove a right to the user
621
	 *
622
	 *  @param	int		$rid        Id du droit a retirer
623
	 *  @param  string	$allmodule  Retirer tous les droits du module allmodule
624
	 *  @param  string	$allperms   Retirer tous les droits du module allmodule, perms allperms
625
	 *  @param	int		$entity		Entity to use
626
	 *  @param  int	    $notrigger	1=Does not execute triggers, 0=Execute triggers
627
	 *  @return int         		> 0 if OK, < 0 if OK
628
	 *  @see	clearrights, addrights, getrights
629
	 */
630
	function delrights($rid, $allmodule='', $allperms='', $entity=0, $notrigger=0)
631
	{
632
		global $conf, $user, $langs;
633
634
		$error=0;
635
		$wherefordel='';
636
		$entity = (! empty($entity)?$entity:$conf->entity);
637
638
		$this->db->begin();
639
640
		if (! empty($rid))
641
		{
642
			// Si on a demande supression d'un droit en particulier, on recupere
643
			// les caracteristiques module, perms et subperms de ce droit.
644
			$sql = "SELECT module, perms, subperms";
645
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
646
			$sql.= " WHERE id = '".$this->db->escape($rid)."'";
647
			$sql.= " AND entity = ".$entity;
648
649
			$result=$this->db->query($sql);
650
			if ($result) {
651
				$obj = $this->db->fetch_object($result);
652
				$module=$obj->module;
653
				$perms=$obj->perms;
654
				$subperms=$obj->subperms;
655
			}
656
			else {
657
				$error++;
658
				dol_print_error($this->db);
659
			}
660
661
			// Where pour la liste des droits a supprimer
662
			$wherefordel="id=".$this->db->escape($rid);
663
			// Suppression des droits induits
664
			if ($subperms=='lire' || $subperms=='read') $wherefordel.=" OR (module='$module' AND perms='$perms' AND subperms IS NOT NULL)";
0 ignored issues
show
Bug introduced by
The variable $module 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...
Bug introduced by
The variable $perms 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...
Bug introduced by
The variable $subperms 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...
665
			if ($perms=='lire' || $perms=='read')       $wherefordel.=" OR (module='$module')";
666
		}
667
		else {
668
			// On a demande suppression d'un droit sur la base d'un nom de module ou perms
669
			// Where pour la liste des droits a supprimer
670
			if (! empty($allmodule))
671
			{
672
				if ($allmodule == 'allmodules')
673
				{
674
					$wherefordel='allmodules';
675
				}
676
				else
677
				{
678
					$wherefordel="module='".$this->db->escape($allmodule)."'";
679
					if (! empty($allperms))  $whereforadd.=" AND perms='".$this->db->escape($allperms)."'";
0 ignored issues
show
Bug introduced by
The variable $whereforadd 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...
680
				}
681
			}
682
		}
683
684
		// Suppression des droits selon critere defini dans wherefordel
685
		if (! empty($wherefordel))
686
		{
687
			//print "$module-$perms-$subperms";
688
			$sql = "SELECT id";
689
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
690
			$sql.= " WHERE entity = ".$entity;
691
			if (! empty($wherefordel) && $wherefordel != 'allmodules') {
692
				$sql.= " AND ".$wherefordel;
693
			}
694
695
			$result=$this->db->query($sql);
696
			if ($result)
697
			{
698
				$num = $this->db->num_rows($result);
699
				$i = 0;
700
				while ($i < $num)
701
				{
702
					$obj = $this->db->fetch_object($result);
703
					$nid = $obj->id;
704
705
					$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights";
706
					$sql.= " WHERE fk_user = ".$this->id." AND fk_id=".$nid;
707
					$sql.= " AND entity = ".$entity;
708
					if (! $this->db->query($sql)) $error++;
709
710
					$i++;
711
				}
712
			}
713
			else
714
			{
715
				$error++;
716
				dol_print_error($this->db);
717
			}
718
		}
719
720
		if (! $error && ! $notrigger)
721
		{
722
			$langs->load("other");
723
			$this->context = array('audit'=>$langs->trans("PermissionsDelete").($rid?' (id='.$rid.')':''));
724
725
			// Call trigger
726
			$result=$this->call_trigger('USER_MODIFY',$user);
727
			if ($result < 0) { $error++; }
728
			// End call triggers
729
		}
730
731
		if ($error) {
732
			$this->db->rollback();
733
			return -$error;
734
		}
735
		else {
736
			$this->db->commit();
737
			return 1;
738
		}
739
	}
740
741
742
	/**
743
	 *  Clear all permissions array of user
744
	 *
745
	 *  @return	void
746
	 *  @see	getrights
747
	 */
748
	function clearrights()
749
	{
750
		dol_syslog(get_class($this)."::clearrights reset user->rights");
751
		$this->rights='';
752
		$this->all_permissions_are_loaded=false;
753
		$this->_tab_loaded=array();
754
	}
755
756
757
	/**
758
	 *	Load permissions granted to user into object user
759
	 *
760
	 *	@param  string	$moduletag		Limit permission for a particular module ('' by default means load all permissions)
761
	 *  @param	int		$forcereload	Force reload of permissions even if they were already loaded (ignore cache)
762
	 *	@return	void
763
	 *  @see	clearrights, delrights, addrights
764
	 */
765
	function getrights($moduletag='', $forcereload=0)
766
	{
767
		global $conf;
768
769
		if (empty($forcereload))
770
		{
771
			if ($moduletag && isset($this->_tab_loaded[$moduletag]) && $this->_tab_loaded[$moduletag])
772
			{
773
				// Rights for this module are already loaded, so we leave
774
				return;
775
			}
776
777
			if ($this->all_permissions_are_loaded)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->all_permissions_are_loaded of type integer|false is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
778
			{
779
				// We already loaded all rights for this user, so we leave
780
				return;
781
			}
782
		}
783
784
		// Recuperation des droits utilisateurs + recuperation des droits groupes
785
786
		// D'abord les droits utilisateurs
787
		$sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
788
		$sql.= " FROM ".MAIN_DB_PREFIX."user_rights as ur";
789
		$sql.= ", ".MAIN_DB_PREFIX."rights_def as r";
790
		$sql.= " WHERE r.id = ur.fk_id";
791
		if (! empty($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY))
792
		{
793
			$sql.= " AND r.entity IN (0,".(! empty($conf->multicompany->enabled) && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)?"1,":"").$conf->entity.")";
794
		}
795
		else
796
		{
797
			$sql.= " AND ur.entity = ".$conf->entity;
798
		}
799
		$sql.= " AND ur.fk_user= ".$this->id;
800
		$sql.= " AND r.perms IS NOT NULL";
801
		if ($moduletag) $sql.= " AND r.module = '".$this->db->escape($moduletag)."'";
802
803
		$resql = $this->db->query($sql);
804
		if ($resql)
805
		{
806
			$num = $this->db->num_rows($resql);
807
			$i = 0;
808
			while ($i < $num)
809
			{
810
				$obj = $this->db->fetch_object($resql);
811
812
				$module=$obj->module;
813
				$perms=$obj->perms;
814
				$subperms=$obj->subperms;
815
816
				if ($perms)
817
				{
818
					if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error
819
					if ($module)
820
					{
821
						if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass();
822
						if ($subperms)
823
						{
824
							if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass();
825
							if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++;
826
							$this->rights->$module->$perms->$subperms = 1;
827
						}
828
						else
829
						{
830
							if(empty($this->rights->$module->$perms)) $this->nb_rights++;
831
							$this->rights->$module->$perms = 1;
832
						}
833
					}
834
				}
835
				$i++;
836
			}
837
			$this->db->free($resql);
838
		}
839
840
		// Maintenant les droits groupes
841
		$sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
842
		$sql.= " FROM ".MAIN_DB_PREFIX."usergroup_rights as gr,";
843
		$sql.= " ".MAIN_DB_PREFIX."usergroup_user as gu,";
844
		$sql.= " ".MAIN_DB_PREFIX."rights_def as r";
845
		$sql.= " WHERE r.id = gr.fk_id";
846
		if (! empty($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY))
847
		{
848
			if (! empty($conf->multicompany->enabled) && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
849
				$sql.= " AND gu.entity IN (0,".$conf->entity.")";
850
			} else {
851
				$sql.= " AND r.entity = ".$conf->entity;
852
			}
853
		}
854
		else
855
		{
856
			$sql.= " AND gr.entity = ".$conf->entity;
857
			$sql.= " AND r.entity = ".$conf->entity;
858
		}
859
		$sql.= " AND gr.fk_usergroup = gu.fk_usergroup";
860
		$sql.= " AND gu.fk_user = ".$this->id;
861
		$sql.= " AND r.perms IS NOT NULL";
862
		if ($moduletag) $sql.= " AND r.module = '".$this->db->escape($moduletag)."'";
863
864
		$resql = $this->db->query($sql);
865
		if ($resql)
866
		{
867
			$num = $this->db->num_rows($resql);
868
			$i = 0;
869
			while ($i < $num)
870
			{
871
				$obj = $this->db->fetch_object($resql);
872
873
				$module=$obj->module;
874
				$perms=$obj->perms;
875
				$subperms=$obj->subperms;
876
877
				if ($perms)
878
				{
879
					if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error
880
					if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass();
881
					if ($subperms)
882
					{
883
						if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass();
884
						if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++;
885
						$this->rights->$module->$perms->$subperms = 1;
886
					}
887
					else
888
					{
889
						if(empty($this->rights->$module->$perms)) $this->nb_rights++;
890
						// if we have already define a subperm like this $this->rights->$module->level1->level2 with llx_user_rights, we don't want override level1 because the level2 can be not define on user group
891
						if (!is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = 1;
892
					}
893
				}
894
				$i++;
895
			}
896
			$this->db->free($resql);
897
		}
898
899
		// For backward compatibility
900
		if (isset($this->rights->propale) && ! isset($this->rights->propal)) $this->rights->propal = $this->rights->propale;
901
		if (isset($this->rights->propal) && ! isset($this->rights->propale)) $this->rights->propale = $this->rights->propal;
902
903
		if (! $moduletag)
904
		{
905
			// Si module etait non defini, alors on a tout charge, on peut donc considerer
906
			// que les droits sont en cache (car tous charges) pour cet instance de user
907
			$this->all_permissions_are_loaded=1;
908
		}
909
		else
910
		{
911
			// Si module defini, on le marque comme charge en cache
912
			$this->_tab_loaded[$moduletag]=1;
913
		}
914
	}
915
916
	/**
917
	 *  Change status of a user
918
	 *
919
	 *	@param	int		$statut		Status to set
920
	 *  @return int     			<0 if KO, 0 if nothing is done, >0 if OK
921
	 */
922
	function setstatus($statut)
923
	{
924
		global $conf,$langs,$user;
925
926
		$error=0;
927
928
		// Check parameters
929
		if ($this->statut == $statut) return 0;
930
		else $this->statut = $statut;
931
932
		$this->db->begin();
933
934
		// Deactivate user
935
		$sql = "UPDATE ".MAIN_DB_PREFIX."user";
936
		$sql.= " SET statut = ".$this->statut;
937
		$sql.= " WHERE rowid = ".$this->id;
938
		$result = $this->db->query($sql);
939
940
		dol_syslog(get_class($this)."::setstatus", LOG_DEBUG);
941
		if ($result)
942
		{
943
			// Call trigger
944
			$result=$this->call_trigger('USER_ENABLEDISABLE',$user);
945
			if ($result < 0) { $error++; }
946
			// End call triggers
947
		}
948
949
		if ($error)
950
		{
951
			$this->db->rollback();
952
			return -$error;
953
		}
954
		else
955
		{
956
			$this->db->commit();
957
			return 1;
958
		}
959
	}
960
961
	/**
962
	 * Sets object to supplied categories.
963
	 *
964
	 * Deletes object from existing categories not supplied.
965
	 * Adds it to non existing supplied categories.
966
	 * Existing categories are left untouch.
967
	 *
968
	 * @param int[]|int $categories Category or categories IDs
969
     * @return void
970
	 */
971
	public function setCategories($categories)
972
	{
973
		// Handle single category
974
		if (!is_array($categories)) {
975
			$categories = array($categories);
976
		}
977
978
		// Get current categories
979
		require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
980
		$c = new Categorie($this->db);
981
		$existing = $c->containing($this->id, Categorie::TYPE_USER, 'id');
982
983
		// Diff
984
		if (is_array($existing)) {
985
			$to_del = array_diff($existing, $categories);
986
			$to_add = array_diff($categories, $existing);
987
		} else {
988
			$to_del = array(); // Nothing to delete
989
			$to_add = $categories;
990
		}
991
992
		// Process
993
		foreach ($to_del as $del) {
994
			if ($c->fetch($del) > 0) {
995
				$c->del_type($this, 'user');
996
			}
997
		}
998
		foreach ($to_add as $add) {
999
			if ($c->fetch($add) > 0) {
1000
				$c->add_type($this, 'user');
1001
			}
1002
		}
1003
1004
		return;
1005
	}
1006
1007
	/**
1008
	 *    	Delete the user
1009
	 *
1010
	 * 		@return		int		<0 if KO, >0 if OK
1011
	 */
1012
	function delete()
1013
	{
1014
		global $user,$conf,$langs;
1015
1016
		$error=0;
1017
1018
		$this->db->begin();
1019
1020
		$this->fetch($this->id);
1021
1022
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1023
1024
		// Remove rights
1025
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = ".$this->id;
1026
1027
		if (! $error && ! $this->db->query($sql))
1028
		{
1029
			$error++;
1030
			$this->error = $this->db->lasterror();
1031
		}
1032
1033
		// Remove group
1034
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user WHERE fk_user  = ".$this->id;
1035
		if (! $error && ! $this->db->query($sql))
1036
		{
1037
			$error++;
1038
			$this->error = $this->db->lasterror();
1039
		}
1040
1041
		// If contact, remove link
1042
		if ($this->contact_id)
1043
		{
1044
			$sql = "UPDATE ".MAIN_DB_PREFIX."socpeople SET fk_user_creat = null WHERE rowid = ".$this->contact_id;
1045
			if (! $error && ! $this->db->query($sql))
1046
			{
1047
				$error++;
1048
				$this->error = $this->db->lasterror();
1049
			}
1050
		}
1051
1052
		// Remove extrafields
1053
		if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
1054
		{
1055
			$result=$this->deleteExtraFields();
1056
			if ($result < 0)
1057
			{
1058
		   		$error++;
1059
		   		dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
1060
		   	}
1061
		}
1062
1063
		// Remove user
1064
		if (! $error)
1065
		{
1066
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".$this->id;
1067
		   	dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1068
		   	if (! $this->db->query($sql))
1069
		   	{
1070
		   		$error++;
1071
		   		$this->error = $this->db->lasterror();
1072
		   	}
1073
		}
1074
1075
		if (! $error)
1076
		{
1077
			// Call trigger
1078
			$result=$this->call_trigger('USER_DELETE',$user);
1079
			if ($result < 0)
1080
			{
1081
				$error++;
1082
				$this->db->rollback();
1083
				return -1;
1084
			}
1085
			// End call triggers
1086
1087
			$this->db->commit();
1088
			return 1;
1089
		}
1090
		else
1091
		{
1092
			$this->db->rollback();
1093
			return -1;
1094
		}
1095
	}
1096
1097
	/**
1098
	 *  Create a user into database
1099
	 *
1100
	 *  @param	User	$user        	Objet user doing creation
1101
	 *  @param  int		$notrigger		1=do not execute triggers, 0 otherwise
1102
	 *  @return int			         	<0 if KO, id of created user if OK
1103
	 */
1104
	function create($user, $notrigger=0)
1105
	{
1106
		global $conf,$langs;
1107
		global $mysoc;
1108
1109
		// Clean parameters
1110
		$this->login = trim($this->login);
1111
		if (! isset($this->entity)) $this->entity=$conf->entity;	// If not defined, we use default value
1112
1113
		dol_syslog(get_class($this)."::create login=".$this->login.", user=".(is_object($user)?$user->id:''), LOG_DEBUG);
1114
1115
		// Check parameters
1116
		if (! empty($conf->global->USER_MAIL_REQUIRED) && ! isValidEMail($this->email))
1117
		{
1118
			$langs->load("errors");
1119
			$this->error = $langs->trans("ErrorBadEMail",$this->email);
1120
			return -1;
1121
		}
1122
		if (empty($this->login))
1123
		{
1124
			$langs->load("errors");
1125
			$this->error = $langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Login"));
1126
			return -1;
1127
		}
1128
1129
		$this->datec = dol_now();
1130
1131
		$error=0;
1132
		$this->db->begin();
1133
1134
		$sql = "SELECT login FROM ".MAIN_DB_PREFIX."user";
1135
		$sql.= " WHERE login ='".$this->db->escape($this->login)."'";
1136
		$sql.= " AND entity IN (0,".$this->db->escape($conf->entity).")";
1137
1138
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
1139
		$resql=$this->db->query($sql);
1140
		if ($resql)
1141
		{
1142
			$num = $this->db->num_rows($resql);
1143
			$this->db->free($resql);
1144
1145
			if ($num)
1146
			{
1147
				$this->error = 'ErrorLoginAlreadyExists';
1148
				dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
1149
				$this->db->rollback();
1150
				return -6;
1151
			}
1152
			else
1153
			{
1154
				$sql = "INSERT INTO ".MAIN_DB_PREFIX."user (datec,login,ldap_sid,entity)";
1155
				$sql.= " VALUES('".$this->db->idate($this->datec)."','".$this->db->escape($this->login)."','".$this->db->escape($this->ldap_sid)."',".$this->db->escape($this->entity).")";
1156
				$result=$this->db->query($sql);
1157
1158
				dol_syslog(get_class($this)."::create", LOG_DEBUG);
1159
				if ($result)
1160
				{
1161
					$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."user");
1162
1163
					// Set default rights
1164
					if ($this->set_default_rights() < 0)
1165
					{
1166
						$this->error='ErrorFailedToSetDefaultRightOfUser';
1167
						$this->db->rollback();
1168
						return -5;
1169
					}
1170
1171
					// Update minor fields
1172
					$result = $this->update($user,1,1);
1173
					if ($result < 0)
1174
					{
1175
						$this->db->rollback();
1176
						return -4;
1177
					}
1178
1179
					if (! empty($conf->global->STOCK_USERSTOCK_AUTOCREATE))
1180
					{
1181
						require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1182
						$langs->load("stocks");
1183
						$entrepot = new Entrepot($this->db);
1184
						$entrepot->libelle = $langs->trans("PersonalStock",$this->getFullName($langs));
1185
						$entrepot->description = $langs->trans("ThisWarehouseIsPersonalStock",$this->getFullName($langs));
1186
						$entrepot->statut = 1;
1187
						$entrepot->country_id = $mysoc->country_id;
1188
						$entrepot->create($user);
1189
					}
1190
1191
					if (! $notrigger)
1192
					{
1193
						// Call trigger
1194
						$result=$this->call_trigger('USER_CREATE',$user);
1195
						if ($result < 0) { $error++; }
1196
						// End call triggers
1197
					}
1198
1199
					if (! $error)
1200
					{
1201
						$this->db->commit();
1202
						return $this->id;
1203
					}
1204
					else
1205
					{
1206
						//$this->error=$interface->error;
1207
						dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
1208
						$this->db->rollback();
1209
						return -3;
1210
					}
1211
				}
1212
				else
1213
				{
1214
					$this->error=$this->db->lasterror();
1215
					$this->db->rollback();
1216
					return -2;
1217
				}
1218
			}
1219
		}
1220
		else
1221
		{
1222
			$this->error=$this->db->lasterror();
1223
			$this->db->rollback();
1224
			return -1;
1225
		}
1226
	}
1227
1228
1229
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1230
	/**
1231
	 *  Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
1232
	 *
1233
	 *  @param	Contact	$contact    Object for source contact
1234
	 * 	@param  string	$login      Login to force
1235
	 *  @param  string	$password   Password to force
1236
	 *  @return int 				<0 if error, if OK returns id of created user
1237
	 */
1238
	function create_from_contact($contact,$login='',$password='')
1239
	{
1240
        // phpcs:enable
1241
		global $conf,$user,$langs;
1242
1243
		$error=0;
1244
1245
		// Define parameters
1246
		$this->admin		= 0;
1247
		$this->lastname		= $contact->lastname;
1248
		$this->firstname	= $contact->firstname;
1249
		$this->gender		= $contact->gender;
1250
		$this->email		= $contact->email;
1251
		$this->skype 		= $contact->skype;
1252
		$this->twitter 		= $contact->twitter;
1253
		$this->facebook		= $contact->facebook;
1254
		$this->office_phone	= $contact->phone_pro;
1255
		$this->office_fax	= $contact->fax;
1256
		$this->user_mobile	= $contact->phone_mobile;
1257
		$this->address      = $contact->address;
1258
		$this->zip          = $contact->zip;
1259
		$this->town         = $contact->town;
1260
		$this->state_id     = $contact->state_id;
1261
		$this->country_id   = $contact->country_id;
1262
		$this->employee     = 0;
1263
1264
		if (empty($login)) $login=strtolower(substr($contact->firstname, 0, 4)) . strtolower(substr($contact->lastname, 0, 4));
1265
		$this->login = $login;
1266
1267
		$this->db->begin();
1268
1269
		// Cree et positionne $this->id
1270
		$result=$this->create($user);
1271
		if ($result > 0)
1272
		{
1273
			$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1274
			$sql.= " SET fk_socpeople=".$contact->id;
1275
			if ($contact->socid) $sql.=", fk_soc=".$contact->socid;
1276
			$sql.= " WHERE rowid=".$this->id;
1277
			$resql=$this->db->query($sql);
1278
1279
			dol_syslog(get_class($this)."::create_from_contact", LOG_DEBUG);
1280
			if ($resql)
1281
			{
1282
				$this->context['createfromcontact']='createfromcontact';
1283
1284
				// Call trigger
1285
				$result=$this->call_trigger('USER_CREATE',$user);
1286
				if ($result < 0) { $error++; $this->db->rollback(); return -1; }
1287
				// End call triggers
1288
1289
				$this->db->commit();
1290
				return $this->id;
1291
			}
1292
			else
1293
			{
1294
				$this->error=$this->db->error();
1295
1296
				$this->db->rollback();
1297
				return -1;
1298
			}
1299
		}
1300
		else
1301
		{
1302
			// $this->error deja positionne
1303
			dol_syslog(get_class($this)."::create_from_contact - 0");
1304
1305
			$this->db->rollback();
1306
			return $result;
1307
		}
1308
	}
1309
1310
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1311
	/**
1312
	 *  Create a user into database from a member object
1313
	 *
1314
	 *  @param	Adherent	$member		Object member source
1315
	 * 	@param	string		$login		Login to force
1316
	 *  @return int						<0 if KO, if OK, return id of created account
1317
	 */
1318
	function create_from_member($member,$login='')
1319
	{
1320
        // phpcs:enable
1321
		global $conf,$user,$langs;
1322
1323
		// Positionne parametres
1324
		$this->admin = 0;
1325
		$this->lastname     = $member->lastname;
1326
		$this->firstname    = $member->firstname;
1327
		$this->gender		= $member->gender;
1328
		$this->email        = $member->email;
1329
		$this->fk_member    = $member->id;
1330
		$this->pass         = $member->pass;
1331
		$this->address      = $member->address;
1332
		$this->zip          = $member->zip;
1333
		$this->town         = $member->town;
1334
		$this->state_id     = $member->state_id;
1335
		$this->country_id   = $member->country_id;
1336
1337
		if (empty($login)) $login=strtolower(substr($member->firstname, 0, 4)) . strtolower(substr($member->lastname, 0, 4));
1338
		$this->login = $login;
1339
1340
		$this->db->begin();
1341
1342
		// Create and set $this->id
1343
		$result=$this->create($user);
1344
		if ($result > 0)
1345
		{
1346
			$newpass=$this->setPassword($user,$this->pass);
1347
			if (is_numeric($newpass) && $newpass < 0) $result=-2;
1348
1349
			if ($result > 0 && $member->fk_soc)	// If member is linked to a thirdparty
1350
			{
1351
				$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1352
				$sql.= " SET fk_soc=".$member->fk_soc;
1353
				$sql.= " WHERE rowid=".$this->id;
1354
1355
				dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG);
1356
				$resql=$this->db->query($sql);
1357
				if ($resql)
1358
				{
1359
					$this->db->commit();
1360
					return $this->id;
1361
				}
1362
				else
1363
				{
1364
					$this->error=$this->db->lasterror();
1365
1366
					$this->db->rollback();
1367
					return -1;
1368
				}
1369
			}
1370
		}
1371
1372
		if ($result > 0)
1373
		{
1374
			$this->db->commit();
1375
			return $this->id;
1376
		}
1377
		else
1378
		{
1379
			// $this->error deja positionne
1380
			$this->db->rollback();
1381
			return -2;
1382
		}
1383
	}
1384
1385
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1386
	/**
1387
	 *    Assign rights by default
1388
	 *
1389
	 *    @return     integer erreur <0, si ok renvoi le nbre de droits par defaut positionnes
1390
	 */
1391
	function set_default_rights()
1392
	{
1393
        // phpcs:enable
1394
		global $conf;
1395
1396
		$sql = "SELECT id FROM ".MAIN_DB_PREFIX."rights_def";
1397
		$sql.= " WHERE bydefault = 1";
1398
		$sql.= " AND entity = ".$conf->entity;
1399
1400
		$resql=$this->db->query($sql);
1401
		if ($resql)
1402
		{
1403
			$num = $this->db->num_rows($resql);
1404
			$i = 0;
1405
			$rd = array();
1406
			while ($i < $num)
1407
			{
1408
				$row = $this->db->fetch_row($resql);
1409
				$rd[$i] = $row[0];
1410
				$i++;
1411
			}
1412
			$this->db->free($resql);
1413
		}
1414
		$i = 0;
1415
		while ($i < $num)
0 ignored issues
show
Bug introduced by
The variable $num 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...
1416
		{
1417
1418
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = $this->id AND fk_id=$rd[$i]";
0 ignored issues
show
Bug introduced by
The variable $rd 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...
1419
			$result=$this->db->query($sql);
1420
1421
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_rights (fk_user, fk_id) VALUES ($this->id, $rd[$i])";
1422
			$result=$this->db->query($sql);
1423
			if (! $result) return -1;
1424
			$i++;
1425
		}
1426
1427
		return $i;
1428
	}
1429
1430
	/**
1431
	 *  	Update a user into database (and also password if this->pass is defined)
1432
	 *
1433
	 *		@param	User	$user				User qui fait la mise a jour
1434
	 *    	@param  int		$notrigger			1 ne declenche pas les triggers, 0 sinon
1435
	 *		@param	int		$nosyncmember		0=Synchronize linked member (standard info), 1=Do not synchronize linked member
1436
	 *		@param	int		$nosyncmemberpass	0=Synchronize linked member (password), 1=Do not synchronize linked member
1437
	 *		@param	int		$nosynccontact		0=Synchronize linked contact, 1=Do not synchronize linked contact
1438
	 *    	@return int 		        		<0 si KO, >=0 si OK
1439
	 */
1440
	function update($user, $notrigger=0, $nosyncmember=0, $nosyncmemberpass=0, $nosynccontact=0)
1441
	{
1442
		global $conf, $langs;
1443
1444
		$nbrowsaffected=0;
1445
		$error=0;
1446
1447
		dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncmember=".$nosyncmember.", nosyncmemberpass=".$nosyncmemberpass);
1448
1449
		// Clean parameters
1450
		$this->lastname     = trim($this->lastname);
1451
		$this->firstname    = trim($this->firstname);
1452
		$this->employee    	= $this->employee?$this->employee:0;
1453
		$this->login        = trim($this->login);
1454
		$this->gender       = trim($this->gender);
1455
		$this->birth        = trim($this->birth);
1456
		$this->pass         = trim($this->pass);
1457
		$this->api_key      = trim($this->api_key);
1458
		$this->address		= $this->address?trim($this->address):trim($this->address);
1459
		$this->zip			= $this->zip?trim($this->zip):trim($this->zip);
1460
		$this->town			= $this->town?trim($this->town):trim($this->town);
1461
		$this->state_id		= trim($this->state_id);
1462
		$this->country_id	= ($this->country_id > 0)?$this->country_id:0;
1463
		$this->office_phone = trim($this->office_phone);
1464
		$this->office_fax   = trim($this->office_fax);
1465
		$this->user_mobile  = trim($this->user_mobile);
1466
		$this->email        = trim($this->email);
1467
1468
		$this->skype        = trim($this->skype);
1469
		$this->twitter      = trim($this->twitter);
1470
		$this->facebook     = trim($this->facebook);
1471
1472
		$this->job    		= trim($this->job);
1473
		$this->signature    = trim($this->signature);
1474
		$this->note         = trim($this->note);
1475
		$this->openid       = trim(empty($this->openid)?'':$this->openid);    // Avoid warning
1476
		$this->admin        = $this->admin?$this->admin:0;
1477
		$this->address		= empty($this->address)?'':$this->address;
1478
		$this->zip			= empty($this->zip)?'':$this->zip;
1479
		$this->town			= empty($this->town)?'':$this->town;
1480
		$this->accountancy_code = trim($this->accountancy_code);
1481
		$this->color 		= empty($this->color)?'':$this->color;
1482
		$this->dateemployment 	= empty($this->dateemployment)?'':$this->dateemployment;
1483
		$this->dateemploymentend = empty($this->dateemploymentend)?'':$this->dateemploymentend;
1484
1485
		// Check parameters
1486
		if (! empty($conf->global->USER_MAIL_REQUIRED) && ! isValidEMail($this->email))
1487
		{
1488
			$langs->load("errors");
1489
			$this->error = $langs->trans("ErrorBadEMail",$this->email);
1490
			return -1;
1491
		}
1492
		if (empty($this->login))
1493
		{
1494
			$langs->load("errors");
1495
			$this->error = $langs->trans("ErrorFieldRequired",$this->login);
1496
			return -1;
1497
		}
1498
1499
		$this->db->begin();
1500
1501
		// Update datas
1502
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
1503
		$sql.= " lastname = '".$this->db->escape($this->lastname)."'";
1504
		$sql.= ", firstname = '".$this->db->escape($this->firstname)."'";
1505
		$sql.= ", employee = ".$this->employee;
1506
		$sql.= ", login = '".$this->db->escape($this->login)."'";
1507
		$sql.= ", api_key = ".($this->api_key ? "'".$this->db->escape($this->api_key)."'" : "null");
1508
		$sql.= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null");	// 'man' or 'woman'
1509
		$sql.= ", birth=".(strval($this->birth)!='' ? "'".$this->db->idate($this->birth)."'" : 'null');
1510
		if (! empty($user->admin)) $sql.= ", admin = ".$this->admin;	// admin flag can be set/unset only by an admin user
1511
		$sql.= ", address = '".$this->db->escape($this->address)."'";
1512
		$sql.= ", zip = '".$this->db->escape($this->zip)."'";
1513
		$sql.= ", town = '".$this->db->escape($this->town)."'";
1514
		$sql.= ", fk_state = ".((! empty($this->state_id) && $this->state_id > 0)?"'".$this->db->escape($this->state_id)."'":"null");
1515
		$sql.= ", fk_country = ".((! empty($this->country_id) && $this->country_id > 0)?"'".$this->db->escape($this->country_id)."'":"null");
1516
		$sql.= ", office_phone = '".$this->db->escape($this->office_phone)."'";
1517
		$sql.= ", office_fax = '".$this->db->escape($this->office_fax)."'";
1518
		$sql.= ", user_mobile = '".$this->db->escape($this->user_mobile)."'";
1519
		$sql.= ", email = '".$this->db->escape($this->email)."'";
1520
		$sql.= ", skype = '".$this->db->escape($this->skype)."'";
1521
		$sql.= ", twitter = '".$this->db->escape($this->twitter)."'";
1522
		$sql.= ", facebook = '".$this->db->escape($this->facebook)."'";
1523
		$sql.= ", job = '".$this->db->escape($this->job)."'";
1524
		$sql.= ", signature = '".$this->db->escape($this->signature)."'";
1525
		$sql.= ", accountancy_code = '".$this->db->escape($this->accountancy_code)."'";
1526
		$sql.= ", color = '".$this->db->escape($this->color)."'";
1527
		$sql.= ", dateemployment=".(strval($this->dateemployment)!='' ? "'".$this->db->idate($this->dateemployment)."'" : 'null');
1528
		$sql.= ", dateemploymentend=".(strval($this->dateemploymentend)!='' ? "'".$this->db->idate($this->dateemploymentend)."'" : 'null');
1529
		$sql.= ", note = '".$this->db->escape($this->note)."'";
1530
		$sql.= ", photo = ".($this->photo?"'".$this->db->escape($this->photo)."'":"null");
1531
		$sql.= ", openid = ".($this->openid?"'".$this->db->escape($this->openid)."'":"null");
1532
		$sql.= ", fk_user = ".($this->fk_user > 0?"'".$this->db->escape($this->fk_user)."'":"null");
1533
		if (isset($this->thm) || $this->thm != '')                 $sql.= ", thm= ".($this->thm != ''?"'".$this->db->escape($this->thm)."'":"null");
1534
		if (isset($this->tjm) || $this->tjm != '')                 $sql.= ", tjm= ".($this->tjm != ''?"'".$this->db->escape($this->tjm)."'":"null");
1535
		if (isset($this->salary) || $this->salary != '')           $sql.= ", salary= ".($this->salary != ''?"'".$this->db->escape($this->salary)."'":"null");
1536
		if (isset($this->salaryextra) || $this->salaryextra != '') $sql.= ", salaryextra= ".($this->salaryextra != ''?"'".$this->db->escape($this->salaryextra)."'":"null");
1537
		$sql.= ", weeklyhours= ".($this->weeklyhours != ''?"'".$this->db->escape($this->weeklyhours)."'":"null");
1538
		$sql.= ", entity = '".$this->db->escape($this->entity)."'";
1539
		$sql.= ", default_range = ".($this->default_range > 0 ? $this->default_range : 'null');
1540
		$sql.= ", default_c_exp_tax_cat = ".($this->default_c_exp_tax_cat > 0 ? $this->default_c_exp_tax_cat : 'null');
1541
1542
		$sql.= " WHERE rowid = ".$this->id;
1543
1544
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1545
		$resql = $this->db->query($sql);
1546
		if ($resql)
1547
		{
1548
			$nbrowsaffected+=$this->db->affected_rows($resql);
1549
1550
			// Update password
1551
			if (!empty($this->pass))
1552
			{
1553
				if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted)
1554
				{
1555
					// Si mot de passe saisi et different de celui en base
1556
					$result=$this->setPassword($user,$this->pass,0,$notrigger,$nosyncmemberpass);
1557
					if (! $nbrowsaffected) $nbrowsaffected++;
1558
				}
1559
			}
1560
1561
			// If user is linked to a member, remove old link to this member
1562
			if ($this->fk_member > 0)
1563
			{
1564
				dol_syslog(get_class($this)."::update remove link with member. We will recreate it later", LOG_DEBUG);
1565
				$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL where fk_member = ".$this->fk_member;
1566
				$resql = $this->db->query($sql);
1567
				if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
1568
			}
1569
			// Set link to user
1570
			dol_syslog(get_class($this)."::update set link with member", LOG_DEBUG);
1571
			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member =".($this->fk_member>0?$this->fk_member:'null')." where rowid = ".$this->id;
1572
			$resql = $this->db->query($sql);
1573
			if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
1574
1575
			if ($nbrowsaffected)	// If something has changed in data
1576
			{
1577
				if ($this->fk_member > 0 && ! $nosyncmember)
1578
				{
1579
					dol_syslog(get_class($this)."::update user is linked with a member. We try to update member too.", LOG_DEBUG);
1580
1581
					require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1582
1583
					// This user is linked with a member, so we also update member information
1584
					// if this is an update.
1585
					$adh=new Adherent($this->db);
1586
					$result=$adh->fetch($this->fk_member);
1587
1588
					if ($result >= 0)
1589
					{
1590
						$adh->firstname=$this->firstname;
1591
						$adh->lastname=$this->lastname;
1592
						$adh->login=$this->login;
1593
						$adh->gender=$this->gender;
1594
						$adh->birth=$this->birth;
1595
1596
						$adh->pass=$this->pass;
1597
1598
						$adh->societe=(empty($adh->societe) && $this->societe_id ? $this->societe_id : $adh->societe);
1599
1600
						$adh->address=$this->address;
1601
						$adh->town=$this->town;
1602
						$adh->zip=$this->zip;
1603
						$adh->state_id=$this->state_id;
1 ignored issue
show
Documentation Bug introduced by
The property $state_id was declared of type integer, but $this->state_id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1604
						$adh->country_id=$this->country_id;
1605
1606
						$adh->email=$this->email;
1607
1608
						$adh->skype=$this->skype;
1609
						$adh->twitter=$this->twitter;
1610
						$adh->facebook=$this->facebook;
1611
1612
						$adh->phone=$this->office_phone;
1613
						$adh->phone_mobile=$this->user_mobile;
1614
1615
						$adh->user_id=$this->id;
1616
						$adh->user_login=$this->login;
1617
1618
						$result=$adh->update($user,0,1,0);
1619
						if ($result < 0)
1620
						{
1621
							$this->error=$adh->error;
1622
							$this->errors=$adh->errors;
1623
							dol_syslog(get_class($this)."::update error after calling adh->update to sync it with user: ".$this->error, LOG_ERR);
1624
							$error++;
1625
						}
1626
					}
1627
					else
1628
					{
1629
						$this->error=$adh->error;
1630
						$this->errors=$adh->errors;
1631
						$error++;
1632
					}
1633
				}
1634
1635
				if ($this->contact_id > 0 && ! $nosynccontact)
1636
				{
1637
					dol_syslog(get_class($this)."::update user is linked with a contact. We try to update contact too.", LOG_DEBUG);
1638
1639
					require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1640
1641
					// This user is linked with a contact, so we also update contact information
1642
					// if this is an update.
1643
					$tmpobj=new Contact($this->db);
1644
					$result=$tmpobj->fetch($this->contact_id);
1645
1646
					if ($result >= 0)
1647
					{
1648
						$tmpobj->firstname=$this->firstname;
1649
						$tmpobj->lastname=$this->lastname;
1650
						$tmpobj->login=$this->login;
1651
						$tmpobj->gender=$this->gender;
1652
						$tmpobj->birth=$this->birth;
1653
1654
						//$tmpobj->pass=$this->pass;
1655
1656
						//$tmpobj->societe=(empty($tmpobj->societe) && $this->societe_id ? $this->societe_id : $tmpobj->societe);
1657
1658
						$tmpobj->email=$this->email;
1659
1660
						$tmpobj->skype=$this->skype;
1661
						$tmpobj->twitter=$this->twitter;
1662
						$tmpobj->facebook=$this->facebook;
1663
1664
						$tmpobj->phone_pro=$this->office_phone;
1665
						$tmpobj->phone_mobile=$this->user_mobile;
1666
						$tmpobj->fax=$this->office_fax;
1667
1668
						$tmpobj->address=$this->address;
1669
						$tmpobj->town=$this->town;
1670
						$tmpobj->zip=$this->zip;
1671
						$tmpobj->state_id=$this->state_id;
1672
						$tmpobj->country_id=$this->country_id;
1673
1674
						$tmpobj->user_id=$this->id;
1675
						$tmpobj->user_login=$this->login;
1676
1677
						$result=$tmpobj->update($tmpobj->id, $user, 0, 'update', 1);
1678
						if ($result < 0)
1679
						{
1680
							$this->error=$tmpobj->error;
1681
							$this->errors=$tmpobj->errors;
1682
							dol_syslog(get_class($this)."::update error after calling adh->update to sync it with user: ".$this->error, LOG_ERR);
1683
							$error++;
1684
						}
1685
					}
1686
					else
1687
					{
1688
						$this->error=$tmpobj->error;
1689
						$this->errors=$tmpobj->errors;
1690
						$error++;
1691
					}
1692
				}
1693
			}
1694
1695
			$action='update';
1696
1697
			// Actions on extra fields
1698
			if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
1699
			{
1700
				$result=$this->insertExtraFields();
1701
				if ($result < 0)
1702
				{
1703
					$error++;
1704
				}
1705
			}
1706
1707
			if (! $error && ! $notrigger)
1708
			{
1709
				// Call trigger
1710
				$result=$this->call_trigger('USER_MODIFY',$user);
1711
				if ($result < 0) { $error++; }
1712
				// End call triggers
1713
			}
1714
1715
			if (! $error)
1716
			{
1717
				$this->db->commit();
1718
				return $nbrowsaffected;
1719
			}
1720
			else
1721
			{
1722
				dol_syslog(get_class($this)."::update error=".$this->error,LOG_ERR);
1723
				$this->db->rollback();
1724
				return -1;
1725
			}
1726
		}
1727
		else
1728
		{
1729
			$this->error=$this->db->lasterror();
1730
			$this->db->rollback();
1731
			return -2;
1732
		}
1733
	}
1734
1735
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1736
	/**
1737
	 *    Mise a jour en base de la date de derniere connexion d'un utilisateur
1738
	 *	  Fonction appelee lors d'une nouvelle connexion
1739
	 *
1740
	 *    @return     <0 si echec, >=0 si ok
1741
	 */
1742
	function update_last_login_date()
1743
	{
1744
        // phpcs:enable
1745
		$now=dol_now();
1746
1747
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
1748
		$sql.= " datepreviouslogin = datelastlogin,";
1749
		$sql.= " datelastlogin = '".$this->db->idate($now)."',";
1750
		$sql.= " tms = tms";    // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion
1751
		$sql.= " WHERE rowid = ".$this->id;
1752
1753
		dol_syslog(get_class($this)."::update_last_login_date user->id=".$this->id." ".$sql, LOG_DEBUG);
1754
		$resql = $this->db->query($sql);
1755
		if ($resql)
1756
		{
1757
			$this->datepreviouslogin=$this->datelastlogin;
1758
			$this->datelastlogin=$now;
1759
			return 1;
1760
		}
1761
		else
1762
		{
1763
			$this->error=$this->db->lasterror().' sql='.$sql;
1764
			return -1;
1765
		}
1766
	}
1767
1768
1769
	/**
1770
	 *  Change password of a user
1771
	 *
1772
	 *  @param	User	$user             		Object user of user making change
1773
	 *  @param  string	$password         		New password in clear text (to generate if not provided)
1774
	 *	@param	int		$changelater			1=Change password only after clicking on confirm email
1775
	 *	@param	int		$notrigger				1=Does not launch triggers
1776
	 *	@param	int		$nosyncmember	        Do not synchronize linked member
1777
	 *  @return string 			          		If OK return clear password, 0 if no change, < 0 if error
1778
	 */
1779
	function setPassword($user, $password='', $changelater=0, $notrigger=0, $nosyncmember=0)
1780
	{
1781
		global $conf, $langs;
1782
		require_once DOL_DOCUMENT_ROOT .'/core/lib/security2.lib.php';
1783
1784
		$error=0;
1785
1786
		dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i','*',$password)." changelater=".$changelater." notrigger=".$notrigger." nosyncmember=".$nosyncmember, LOG_DEBUG);
1787
1788
		// If new password not provided, we generate one
1789
		if (! $password)
1790
		{
1791
			$password=getRandomPassword(false);
1792
		}
1793
1794
		// Crypt password
1795
		$password_crypted = dol_hash($password);
1796
1797
		// Mise a jour
1798
		if (! $changelater)
1799
		{
1800
			if (! is_object($this->oldcopy)) $this->oldcopy = clone $this;
1801
1802
			$this->db->begin();
1803
1804
			$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1805
			$sql.= " SET pass_crypted = '".$this->db->escape($password_crypted)."',";
1806
			$sql.= " pass_temp = null";
1807
			if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
1808
			{
1809
				$sql.= ", pass = null";
1810
			}
1811
			else
1812
			{
1813
				$sql.= ", pass = '".$this->db->escape($password)."'";
1814
			}
1815
			$sql.= " WHERE rowid = ".$this->id;
1816
1817
			dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1818
			$result = $this->db->query($sql);
1819
			if ($result)
1820
			{
1821
				if ($this->db->affected_rows($result))
1822
				{
1823
					$this->pass=$password;
1824
					$this->pass_indatabase=$password;
1825
					$this->pass_indatabase_crypted=$password_crypted;
1826
1827
					if ($this->fk_member && ! $nosyncmember)
1828
					{
1829
						require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1830
1831
						// This user is linked with a member, so we also update members informations
1832
						// if this is an update.
1833
						$adh=new Adherent($this->db);
1834
						$result=$adh->fetch($this->fk_member);
1835
1836
						if ($result >= 0)
1837
						{
1838
							$result=$adh->setPassword($user,$this->pass,(empty($conf->global->DATABASE_PWD_ENCRYPTED)?0:1),1);	// Cryptage non gere dans module adherent
1839
							if ($result < 0)
1840
							{
1841
								$this->error=$adh->error;
1842
								dol_syslog(get_class($this)."::setPassword ".$this->error,LOG_ERR);
1843
								$error++;
1844
							}
1845
						}
1846
						else
1847
						{
1848
							$this->error=$adh->error;
1849
							$error++;
1850
						}
1851
					}
1852
1853
					dol_syslog(get_class($this)."::setPassword notrigger=".$notrigger." error=".$error,LOG_DEBUG);
1854
1855
					if (! $error && ! $notrigger)
1856
					{
1857
						// Call trigger
1858
						$result=$this->call_trigger('USER_NEW_PASSWORD',$user);
1859
						if ($result < 0) { $error++; $this->db->rollback(); return -1; }
1860
						// End call triggers
1861
					}
1862
1863
					$this->db->commit();
1864
					return $this->pass;
1865
				}
1866
				else
1867
				{
1868
					$this->db->rollback();
1869
					return 0;
1870
				}
1871
			}
1872
			else
1873
			{
1874
				$this->db->rollback();
1875
				dol_print_error($this->db);
1876
				return -1;
1877
			}
1878
		}
1879
		else
1880
		{
1881
			// We store clear password in password temporary field.
1882
			// After receiving confirmation link, we will crypt it and store it in pass_crypted
1883
			$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1884
			$sql.= " SET pass_temp = '".$this->db->escape($password)."'";
1885
			$sql.= " WHERE rowid = ".$this->id;
1886
1887
			dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);	// No log
1888
			$result = $this->db->query($sql);
1889
			if ($result)
1890
			{
1891
				return $password;
1892
			}
1893
			else
1894
			{
1895
				dol_print_error($this->db);
1896
				return -3;
1897
			}
1898
		}
1899
	}
1900
1901
1902
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1903
	/**
1904
	 *  Send new password by email
1905
	 *
1906
	 *  @param	User	$user           Object user that send email
1907
	 *  @param	string	$password       New password
1908
	 *	@param	int		$changelater	0=Send clear passwod into email, 1=Change password only after clicking on confirm email. @TODO Add method 2 = Send link to reset password
1909
	 *  @return int 		            < 0 si erreur, > 0 si ok
1910
	 */
1911
	function send_password($user, $password='', $changelater=0)
1912
	{
1913
        // phpcs:enable
1914
		global $conf, $langs;
1915
		global $dolibarr_main_url_root;
1916
1917
		require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
1918
1919
		$msgishtml=0;
1920
1921
		// Define $msg
1922
		$mesg = '';
1923
1924
		$outputlangs=new Translate("",$conf);
1925
		if (isset($this->conf->MAIN_LANG_DEFAULT)
1926
		&& $this->conf->MAIN_LANG_DEFAULT != 'auto')
1927
		{	// If user has defined its own language (rare because in most cases, auto is used)
1928
			$outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT);
1929
		}
1930
		else
1931
		{	// If user has not defined its own language, we used current language
1932
			$outputlangs=$langs;
1933
		}
1934
1935
		// Load translation files required by the page
1936
		$outputlangs->loadLangs(array("main", "errors", "users", "other"));
1937
1938
		$appli=constant('DOL_APPLICATION_TITLE');
1939
		if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE;
1940
1941
		$subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli);
1942
1943
		// Define $urlwithroot
1944
		$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
1945
		$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
1946
1947
		if (! $changelater)
1948
		{
1949
			$url = $urlwithroot.'/';
1950
1951
			$mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived").".\n";
1952
			$mesg.= $outputlangs->transnoentitiesnoconv("NewKeyIs")." :\n\n";
1953
			$mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n";
1954
			$mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n";
1955
			$mesg.= "\n";
1956
1957
			$mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli).': '.$url."\n\n";
1958
			$mesg.= "--\n";
1959
			$mesg.= $user->getFullName($outputlangs);	// Username that make then sending
1960
1961
			dol_syslog(get_class($this)."::send_password changelater is off, url=".$url);
1962
		}
1963
		else
1964
		{
1965
			$url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password);
1966
1967
			$mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."\n";
1968
			$mesg.= $outputlangs->transnoentitiesnoconv("NewKeyWillBe")." :\n\n";
1969
			$mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n";
1970
			$mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n";
1971
			$mesg.= "\n";
1972
			$mesg.= $outputlangs->transnoentitiesnoconv("YouMustClickToChange")." :\n";
1973
			$mesg.= $url."\n\n";
1974
			$mesg.= $outputlangs->transnoentitiesnoconv("ForgetIfNothing")."\n\n";
1975
1976
			dol_syslog(get_class($this)."::send_password changelater is on, url=".$url);
1977
		}
1978
1979
		$mailfile = new CMailFile(
1980
			$subject,
1981
			$this->email,
1982
			$conf->global->MAIN_MAIL_EMAIL_FROM,
1983
			$mesg,
1984
			array(),
1985
			array(),
1986
			array(),
1987
			'',
1988
			'',
1989
			0,
1990
			$msgishtml
1991
		);
1992
1993
		if ($mailfile->sendfile())
1994
		{
1995
			return 1;
1996
		}
1997
		else
1998
		{
1999
			$langs->trans("errors");
2000
			$this->error=$langs->trans("ErrorFailedToSendPassword").' '.$mailfile->error;
2001
			return -1;
2002
		}
2003
	}
2004
2005
	/**
2006
	 * 		Renvoie la derniere erreur fonctionnelle de manipulation de l'objet
2007
	 *
2008
	 * 		@return    string      chaine erreur
2009
	 */
2010
	function error()
2011
	{
2012
		return $this->error;
2013
	}
2014
2015
2016
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2017
	/**
2018
	 *    	Read clicktodial information for user
2019
	 *
2020
	 * 		@return		<0 if KO, >0 if OK
2021
	 */
2022
	function fetch_clicktodial()
2023
	{
2024
        // phpcs:enable
2025
		$sql = "SELECT url, login, pass, poste ";
2026
		$sql.= " FROM ".MAIN_DB_PREFIX."user_clicktodial as u";
2027
		$sql.= " WHERE u.fk_user = ".$this->id;
2028
2029
		$resql = $this->db->query($sql);
2030
		if ($resql)
2031
		{
2032
			if ($this->db->num_rows($resql))
2033
			{
2034
				$obj = $this->db->fetch_object($resql);
2035
2036
				$this->clicktodial_url = $obj->url;
2037
				$this->clicktodial_login = $obj->login;
2038
				$this->clicktodial_password = $obj->pass;
2039
				$this->clicktodial_poste = $obj->poste;
2040
			}
2041
2042
			$this->clicktodial_loaded = 1;	// Data loaded (found or not)
2043
2044
			$this->db->free($resql);
2045
			return 1;
2046
		}
2047
		else
2048
		{
2049
			$this->error=$this->db->error();
2050
			return -1;
2051
		}
2052
	}
2053
2054
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2055
	/**
2056
	 *  Update clicktodial info
2057
	 *
2058
	 *  @return	integer
2059
	 */
2060
	function update_clicktodial()
2061
	{
2062
        // phpcs:enable
2063
		$this->db->begin();
2064
2065
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_clicktodial";
2066
		$sql .= " WHERE fk_user = ".$this->id;
2067
2068
		dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
2069
		$result = $this->db->query($sql);
2070
2071
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_clicktodial";
2072
		$sql .= " (fk_user,url,login,pass,poste)";
2073
		$sql .= " VALUES (".$this->id;
2074
		$sql .= ", '". $this->db->escape($this->clicktodial_url) ."'";
2075
		$sql .= ", '". $this->db->escape($this->clicktodial_login) ."'";
2076
		$sql .= ", '". $this->db->escape($this->clicktodial_password) ."'";
2077
		$sql .= ", '". $this->db->escape($this->clicktodial_poste) ."')";
2078
2079
		dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
2080
		$result = $this->db->query($sql);
2081
		if ($result)
2082
		{
2083
			$this->db->commit();
2084
			return 1;
2085
		}
2086
		else
2087
		{
2088
			$this->db->rollback();
2089
			$this->error=$this->db->lasterror();
2090
			return -1;
2091
		}
2092
	}
2093
2094
2095
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2096
	/**
2097
	 *  Add user into a group
2098
	 *
2099
	 *  @param	int	$group      Id of group
2100
	 *  @param  int		$entity     Entity
2101
	 *  @param  int		$notrigger  Disable triggers
2102
	 *  @return int  				<0 if KO, >0 if OK
2103
	 */
2104
	function SetInGroup($group, $entity, $notrigger=0)
2105
	{
2106
        // phpcs:enable
2107
		global $conf, $langs, $user;
2108
2109
		$error=0;
2110
2111
		$this->db->begin();
2112
2113
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user";
2114
		$sql.= " WHERE fk_user  = ".$this->id;
2115
		$sql.= " AND fk_usergroup = ".$group;
2116
		$sql.= " AND entity = ".$entity;
2117
2118
		$result = $this->db->query($sql);
2119
2120
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."usergroup_user (entity, fk_user, fk_usergroup)";
2121
		$sql.= " VALUES (".$entity.",".$this->id.",".$group.")";
2122
2123
		$result = $this->db->query($sql);
2124
		if ($result)
2125
		{
2126
			if (! $error && ! $notrigger)
2127
			{
2128
				$this->newgroupid=$group;    // deprecated. Remove this.
2129
				$this->context = array('audit'=>$langs->trans("UserSetInGroup"), 'newgroupid'=>$group);
2130
2131
				// Call trigger
2132
				$result=$this->call_trigger('USER_MODIFY',$user);
2133
				if ($result < 0) { $error++; }
2134
				// End call triggers
2135
			}
2136
2137
			if (! $error)
2138
			{
2139
				$this->db->commit();
2140
				return 1;
2141
			}
2142
			else
2143
			{
2144
				dol_syslog(get_class($this)."::SetInGroup ".$this->error, LOG_ERR);
2145
				$this->db->rollback();
2146
				return -2;
2147
			}
2148
		}
2149
		else
2150
		{
2151
			$this->error=$this->db->lasterror();
2152
			$this->db->rollback();
2153
			return -1;
2154
		}
2155
	}
2156
2157
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2158
	/**
2159
	 *  Remove a user from a group
2160
	 *
2161
	 *  @param	int   $group       Id of group
2162
	 *  @param  int		$entity      Entity
2163
	 *  @param  int		$notrigger   Disable triggers
2164
	 *  @return int  			     <0 if KO, >0 if OK
2165
	 */
2166
	function RemoveFromGroup($group, $entity, $notrigger=0)
2167
	{
2168
        // phpcs:enable
2169
		global $conf,$langs,$user;
2170
2171
		$error=0;
2172
2173
		$this->db->begin();
2174
2175
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user";
2176
		$sql.= " WHERE fk_user  = ".$this->id;
2177
		$sql.= " AND fk_usergroup = ".$group;
2178
		$sql.= " AND entity = ".$entity;
2179
2180
		$result = $this->db->query($sql);
2181
		if ($result)
2182
		{
2183
			if (! $error && ! $notrigger)
2184
			{
2185
				$this->oldgroupid=$group;    // deprecated. Remove this.
2186
				$this->context = array('audit'=>$langs->trans("UserRemovedFromGroup"), 'oldgroupid'=>$group);
2187
2188
				// Call trigger
2189
				$result=$this->call_trigger('USER_MODIFY',$user);
2190
				if ($result < 0) { $error++; }
2191
				// End call triggers
2192
			}
2193
2194
			if (! $error)
2195
			{
2196
				$this->db->commit();
2197
				return 1;
2198
			}
2199
			else
2200
			{
2201
				$this->error=$interface->error;
0 ignored issues
show
Bug introduced by
The variable $interface 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...
2202
				dol_syslog(get_class($this)."::RemoveFromGroup ".$this->error, LOG_ERR);
2203
				$this->db->rollback();
2204
				return -2;
2205
			}
2206
		}
2207
		else
2208
		{
2209
			$this->error=$this->db->lasterror();
2210
			$this->db->rollback();
2211
			return -1;
2212
		}
2213
	}
2214
2215
2216
	/**
2217
	 *  Return a link with photo
2218
	 * 	Use this->id,this->photo
2219
	 *
2220
	 *	@param	int		$width			Width of image
2221
	 *	@param	int		$height			Height of image
2222
	 *  @param	string	$cssclass		Force a css class
2223
	 * 	@param	string	$imagesize		'mini', 'small' or '' (original)
2224
	 *	@return	string					String with URL link
2225
	 */
2226
	function getPhotoUrl($width, $height, $cssclass='', $imagesize='')
2227
	{
2228
		$result ='<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2229
		$result.=Form::showphoto('userphoto', $this, $width, $height, 0, $cssclass, $imagesize);
2230
		$result.='</a>';
2231
2232
		return $result;
2233
	}
2234
2235
	/**
2236
	 *  Return a link to the user card (with optionaly the picto)
2237
	 * 	Use this->id,this->lastname, this->firstname
2238
	 *
2239
	 *	@param	int		$withpictoimg				Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small)
2240
	 *	@param	string	$option						On what the link point to ('leave', 'nolink', )
2241
	 *  @param  integer $infologin      			0=Add default info tooltip, 1=Add complete info tooltip, -1=No info tooltip
2242
	 *  @param	integer	$notooltip					1=Disable tooltip on picto and name
2243
	 *  @param	int		$maxlen						Max length of visible user name
2244
	 *  @param	int		$hidethirdpartylogo			Hide logo of thirdparty if user is external user
2245
	 *  @param  string  $mode               		''=Show firstname and lastname, 'firstname'=Show only firstname, 'login'=Show login
2246
	 *  @param  string  $morecss            		Add more css on link
2247
	 *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2248
	 *	@return	string								String with URL
2249
	 */
2250
	function getNomUrl($withpictoimg=0, $option='', $infologin=0, $notooltip=0, $maxlen=24, $hidethirdpartylogo=0, $mode='',$morecss='', $save_lastsearch_value=-1)
2251
	{
2252
		global $langs, $conf, $db, $hookmanager, $user;
2253
		global $dolibarr_main_authentication, $dolibarr_main_demo;
2254
		global $menumanager;
2255
2256
        if(!$user->rights->user->user->lire && $user->id !=$this->id) $option='nolink';
2257
2258
		if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) $withpictoimg=0;
2259
2260
		$result=''; $label='';
2261
		$link=''; $linkstart=''; $linkend='';
2262
2263
		if (! empty($this->photo))
2264
		{
2265
			$label.= '<div class="photointooltip">';
2266
			$label.= Form::showphoto('userphoto', $this, 0, 60, 0, 'photowithmargin photologintooltip', 'small', 0, 1);	// Force height to 60 so we total height of tooltip can be calculated and collision can be managed
2267
			$label.= '</div><div style="clear: both;"></div>';
2268
		}
2269
2270
		// Info Login
2271
		$label.= '<div class="centpercent">';
2272
		$label.= '<u>' . $langs->trans("User") . '</u><br>';
2273
		$label.= '<b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs,'');
2274
		if (! empty($this->login))
2275
			$label.= '<br><b>' . $langs->trans('Login') . ':</b> ' . $this->login;
2276
		$label.= '<br><b>' . $langs->trans("EMail").':</b> '.$this->email;
2277
		if (! empty($this->admin))
2278
			$label.= '<br><b>' . $langs->trans("Administrator").'</b>: '.yn($this->admin);
2279
		if (! empty($this->socid) )	// Add thirdparty for external users
2280
		{
2281
			$thirdpartystatic = new Societe($db);
2282
			$thirdpartystatic->fetch($this->socid);
2283
			if (empty($hidethirdpartylogo)) $companylink = ' '.$thirdpartystatic->getNomUrl(2, (($option == 'nolink')?'nolink':''));	// picto only of company
2284
			$company=' ('.$langs->trans("Company").': '.$thirdpartystatic->name.')';
2285
		}
2286
		$type=($this->socid?$langs->trans("External").$company:$langs->trans("Internal"));
0 ignored issues
show
Bug introduced by
The variable $company 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...
2287
		$label.= '<br><b>' . $langs->trans("Type") . ':</b> ' . $type;
2288
		$label.= '<br><b>' . $langs->trans("Status").'</b>: '.$this->getLibStatut(0);
2289
		$label.='</div>';
2290
		if ($infologin > 0)
2291
		{
2292
			$label.= '<br>';
2293
			$label.= '<br><u>'.$langs->trans("Connection").'</u>';
2294
			$label.= '<br><b>'.$langs->trans("IPAddress").'</b>: '.$_SERVER["REMOTE_ADDR"];
2295
			if (! empty($conf->global->MAIN_MODULE_MULTICOMPANY)) $label.= '<br><b>'.$langs->trans("ConnectedOnMultiCompany").':</b> '.$conf->entity.' (user entity '.$this->entity.')';
2296
			$label.= '<br><b>'.$langs->trans("AuthenticationMode").':</b> '.$_SESSION["dol_authmode"].(empty($dolibarr_main_demo)?'':' (demo)');
2297
			$label.= '<br><b>'.$langs->trans("ConnectedSince").':</b> '.dol_print_date($this->datelastlogin,"dayhour",'tzuser');
2298
			$label.= '<br><b>'.$langs->trans("PreviousConnexion").':</b> '.dol_print_date($this->datepreviouslogin,"dayhour",'tzuser');
2299
			$label.= '<br><b>'.$langs->trans("CurrentTheme").':</b> '.$conf->theme;
2300
			$label.= '<br><b>'.$langs->trans("CurrentMenuManager").':</b> '.$menumanager->name;
2301
			$s=picto_from_langcode($langs->getDefaultLang());
2302
			$label.= '<br><b>'.$langs->trans("CurrentUserLanguage").':</b> '.($s?$s.' ':'').$langs->getDefaultLang();
2303
			$label.= '<br><b>'.$langs->trans("Browser").':</b> '.$conf->browser->name.($conf->browser->version?' '.$conf->browser->version:'').' ('.$_SERVER['HTTP_USER_AGENT'].')';
2304
			$label.= '<br><b>'.$langs->trans("Layout").':</b> '.$conf->browser->layout;
2305
			$label.= '<br><b>'.$langs->trans("Screen").':</b> '.$_SESSION['dol_screenwidth'].' x '.$_SESSION['dol_screenheight'];
2306
			if ($conf->browser->layout == 'phone') $label.= '<br><b>'.$langs->trans("Phone").':</b> '.$langs->trans("Yes");
2307
			if (! empty($_SESSION["disablemodules"])) $label.= '<br><b>'.$langs->trans("DisabledModules").':</b> <br>'.join(', ',explode(',',$_SESSION["disablemodules"]));
2308
		}
2309
		if ($infologin < 0) $label='';
2310
2311
		$url = DOL_URL_ROOT.'/user/card.php?id='.$this->id;
2312
		if ($option == 'leave') $url = DOL_URL_ROOT.'/holiday/list.php?id='.$this->id;
2313
2314
		if ($option != 'nolink')
2315
		{
2316
			// Add param to save lastsearch_values or not
2317
			$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
2318
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
2319
			if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
2320
		}
2321
2322
		$linkstart='<a href="'.$url.'"';
2323
		$linkclose="";
2324
		if (empty($notooltip))
2325
		{
2326
			if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2327
			{
2328
				$langs->load("users");
2329
				$label=$langs->trans("ShowUser");
2330
				$linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
2331
			}
2332
			$linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
2333
			$linkclose.= ' class="classfortooltip'.($morecss?' '.$morecss:'').'"';
2334
2335
			/*
2336
			 $hookmanager->initHooks(array('userdao'));
2337
			 $parameters=array('id'=>$this->id);
2338
			 $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
2339
			 if ($reshook > 0) $linkclose = $hookmanager->resPrint;
2340
			 */
2341
		}
2342
2343
		$linkstart.=$linkclose.'>';
2344
		$linkend='</a>';
2345
2346
		//if ($withpictoimg == -1) $result.='<div class="nowrap">';
2347
		$result.=(($option == 'nolink')?'':$linkstart);
2348
		if ($withpictoimg)
2349
		{
2350
		  	$paddafterimage='';
2351
			if (abs($withpictoimg) == 1) $paddafterimage='style="margin-right: 3px;"';
2352
			// Only picto
2353
			if ($withpictoimg > 0) $picto='<!-- picto user --><div class="inline-block nopadding userimg'.($morecss?' '.$morecss:'').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).'</div>';
2354
			// Picto must be a photo
2355
			else $picto='<!-- picto photo user --><div class="inline-block nopadding userimg'.($morecss?' '.$morecss:'').'"'.($paddafterimage?' '.$paddafterimage:'').'>'.Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg==-3?'small':''), 'mini', 0, 1).'</div>';
2356
			$result.=$picto;
2357
		}
2358
		if ($withpictoimg > -2 && $withpictoimg != 2)
2359
		{
2360
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='<div class="inline-block nopadding valignmiddle usertext'.((! isset($this->statut) || $this->statut)?'':' strikefordisabled').($morecss?' '.$morecss:'').'">';
2361
			if ($mode == 'login') $result.=dol_trunc($this->login, $maxlen);
2362
			else $result.=$this->getFullName($langs,'',($mode == 'firstname' ? 2 : -1),$maxlen);
2363
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='</div>';
2364
		}
2365
		$result.=(($option == 'nolink')?'':$linkend);
2366
		//if ($withpictoimg == -1) $result.='</div>';
2367
2368
		$result.=$companylink;
0 ignored issues
show
Bug introduced by
The variable $companylink 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...
2369
2370
		global $action;
2371
		$hookmanager->initHooks(array('userdao'));
2372
		$parameters=array('id'=>$this->id, 'getnomurl'=>$result);
2373
		$reshook=$hookmanager->executeHooks('getNomUrl',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
2374
		if ($reshook > 0) $result = $hookmanager->resPrint;
2375
		else $result .= $hookmanager->resPrint;
2376
2377
		return $result;
2378
	}
2379
2380
	/**
2381
	 *  Return clickable link of login (eventualy with picto)
2382
	 *
2383
	 *	@param	int		$withpicto		Include picto into link
2384
	 *	@param	string	$option			Sur quoi pointe le lien
2385
	 *	@return	string					Chaine avec URL
2386
	 */
2387
	function getLoginUrl($withpicto=0,$option='')
2388
	{
2389
		global $langs, $user;
2390
2391
		$result='';
2392
2393
		$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2394
		$linkend='</a>';
2395
2396
                //Check user's rights to see an other user
2397
                if((!$user->rights->user->user->lire && $this->id !=$user->id)) $option='nolink';
2398
2399
		if ($option == 'xxx')
2400
		{
2401
			$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2402
			$linkend='</a>';
2403
		}
2404
2405
        if ($option == 'nolink')
2406
		{
2407
			$linkstart = '';
2408
			$linkend='';
2409
		}
2410
2411
		$result.=$linkstart;
2412
		if ($withpicto) $result.=img_object($langs->trans("ShowUser"), 'user', 'class="paddingright"');
2413
		$result.=$this->login;
2414
		$result.=$linkend;
2415
		return $result;
2416
	}
2417
2418
	/**
2419
	 *  Return label of status of user (active, inactive)
2420
	 *
2421
	 *  @param	int		$mode          0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2422
	 *  @return	string 			       Label of status
2423
	 */
2424
	function getLibStatut($mode=0)
2425
	{
2426
		return $this->LibStatut($this->statut,$mode);
2427
	}
2428
2429
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2430
	/**
2431
	 *  Renvoi le libelle d'un statut donne
2432
	 *
2433
	 *  @param	int		$statut        	Id statut
2434
	 *  @param  int		$mode          	0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2435
	 *  @return string 			       	Label of status
2436
	 */
2437
	function LibStatut($statut,$mode=0)
2438
	{
2439
        // phpcs:enable
2440
		global $langs;
2441
		$langs->load('users');
2442
2443
		if ($mode == 0)
2444
		{
2445
			if ($statut == 1) return $langs->trans('Enabled');
2446
			elseif ($statut == 0) return $langs->trans('Disabled');
2447
		}
2448
		elseif ($mode == 1)
2449
		{
2450
			if ($statut == 1) return $langs->trans('Enabled');
2451
			elseif ($statut == 0) return $langs->trans('Disabled');
2452
		}
2453
		elseif ($mode == 2)
2454
		{
2455
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"').' '.$langs->trans('Enabled');
2456
			elseif ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"').' '.$langs->trans('Disabled');
2457
		}
2458
		elseif ($mode == 3)
2459
		{
2460
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"');
2461
			elseif ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"');
2462
		}
2463
		elseif ($mode == 4)
2464
		{
2465
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"').' '.$langs->trans('Enabled');
2466
			elseif ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"').' '.$langs->trans('Disabled');
2467
		}
2468
		elseif ($mode == 5)
2469
		{
2470
			if ($statut == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"');
2471
			elseif ($statut == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"');
2472
		}
2473
	}
2474
2475
2476
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2477
	/**
2478
	 *	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2479
	 *
2480
	 *	@param	array	$info		Info array loaded by _load_ldap_info
2481
	 *	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2482
	 *								1=Return parent (ou=xxx,dc=aaa,dc=bbb)
2483
	 *								2=Return key only (RDN) (uid=qqq)
2484
	 *	@return	string				DN
2485
	 */
2486
	function _load_ldap_dn($info,$mode=0)
2487
	{
2488
        // phpcs:enable
2489
		global $conf;
2490
		$dn='';
2491
		if ($mode==0) $dn=$conf->global->LDAP_KEY_USERS."=".$info[$conf->global->LDAP_KEY_USERS].",".$conf->global->LDAP_USER_DN;
2492
		elseif ($mode==1) $dn=$conf->global->LDAP_USER_DN;
2493
		elseif ($mode==2) $dn=$conf->global->LDAP_KEY_USERS."=".$info[$conf->global->LDAP_KEY_USERS];
2494
		return $dn;
2495
	}
2496
2497
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2498
	/**
2499
	 *	Initialize the info array (array of LDAP values) that will be used to call LDAP functions
2500
	 *
2501
	 *	@return		array		Tableau info des attributs
2502
	 */
2503
	function _load_ldap_info()
2504
	{
2505
        // phpcs:enable
2506
		global $conf,$langs;
2507
2508
		$info=array();
2509
		$keymodified=false;
2510
2511
		// Object classes
2512
		$info["objectclass"]=explode(',',$conf->global->LDAP_USER_OBJECT_CLASS);
2513
2514
		$this->fullname=$this->getFullName($langs);
2515
2516
		// Possible LDAP KEY (constname => varname)
2517
		$ldapkey = array(
2518
			'LDAP_FIELD_FULLNAME'	=> 'fullname',
2519
			'LDAP_FIELD_NAME'		=> 'lastname',
2520
			'LDAP_FIELD_FIRSTNAME'	=> 'firstname',
2521
			'LDAP_FIELD_LOGIN'		=> 'login',
2522
			'LDAP_FIELD_LOGIN_SAMBA'=> 'login',
2523
			'LDAP_FIELD_PHONE'		=> 'office_phone',
2524
			'LDAP_FIELD_MOBILE'		=> 'user_mobile',
2525
			'LDAP_FIELD_FAX'		=> 'office_fax',
2526
			'LDAP_FIELD_MAIL'		=> 'email',
2527
			'LDAP_FIELD_SID'		=> 'ldap_sid',
2528
			'LDAP_FIELD_SKYPE'		=> 'skype',
2529
			'LDAP_FIELD_TWITTER'	=> 'twitter',
2530
			'LDAP_FIELD_FACEBOOK'	=> 'facebook'
2531
		);
2532
2533
		// Champs
2534
		foreach ($ldapkey as $constname => $varname)
2535
		{
2536
			if (! empty($this->$varname) && ! empty($conf->global->$constname))
2537
			{
2538
				$info[$conf->global->$constname] = $this->$varname;
2539
2540
				// Check if it is the LDAP key and if its value has been changed
2541
				if (! empty($conf->global->LDAP_KEY_USERS) && $conf->global->LDAP_KEY_USERS == $conf->global->$constname)
2542
				{
2543
					if (! empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) $keymodified=true; // For check if LDAP key has been modified
2544
				}
2545
			}
2546
		}
2547
		if ($this->address && ! empty($conf->global->LDAP_FIELD_ADDRESS))			$info[$conf->global->LDAP_FIELD_ADDRESS] = $this->address;
2548
		if ($this->zip && ! empty($conf->global->LDAP_FIELD_ZIP))					$info[$conf->global->LDAP_FIELD_ZIP] = $this->zip;
2549
		if ($this->town && ! empty($conf->global->LDAP_FIELD_TOWN))					$info[$conf->global->LDAP_FIELD_TOWN] = $this->town;
2550
		if ($this->note_public && ! empty($conf->global->LDAP_FIELD_DESCRIPTION))	$info[$conf->global->LDAP_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_public, 2);
2551
		if ($this->socid > 0)
2552
		{
2553
			$soc = new Societe($this->db);
2554
			$soc->fetch($this->socid);
2555
2556
			$info[$conf->global->LDAP_FIELD_COMPANY] = $soc->name;
2557
			if ($soc->client == 1)      $info["businessCategory"] = "Customers";
2558
			if ($soc->client == 2)      $info["businessCategory"] = "Prospects";
2559
			if ($soc->fournisseur == 1) $info["businessCategory"] = "Suppliers";
2560
		}
2561
2562
		// When password is modified
2563
		if (! empty($this->pass))
2564
		{
2565
			if (! empty($conf->global->LDAP_FIELD_PASSWORD))				$info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass;	// this->pass = mot de passe non crypte
2566
			if (! empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED))		$info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
2567
		}
2568
		// Set LDAP password if possible
2569
		elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2570
		{
2571
			if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
2572
			{
2573
				// Just for the default MD5 !
2574
				if (empty($conf->global->MAIN_SECURITY_HASH_ALGO))
2575
				{
2576
					if ($this->pass_indatabase_crypted && ! empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED))	{
2577
						$info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase_crypted, 5); // Create OpenLDAP MD5 password from Dolibarr MD5 password
2578
					}
2579
				}
2580
			}
2581
			// Use $this->pass_indatabase value if exists
2582
			elseif (! empty($this->pass_indatabase))
2583
			{
2584
				if (! empty($conf->global->LDAP_FIELD_PASSWORD))				$info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass_indatabase;	// $this->pass_indatabase = mot de passe non crypte
2585
				if (! empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED))		$info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
2586
			}
2587
		}
2588
2589
		if ($conf->global->LDAP_SERVER_TYPE == 'egroupware')
2590
		{
2591
			$info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
2592
2593
			$info['uidnumber'] = $this->id;
2594
2595
			$info['phpgwTz']      = 0;
2596
			$info['phpgwMailType'] = 'INTERNET';
2597
			$info['phpgwMailHomeType'] = 'INTERNET';
2598
2599
			$info["phpgwContactTypeId"] = 'n';
2600
			$info["phpgwContactCatId"] = 0;
2601
			$info["phpgwContactAccess"] = "public";
2602
2603
			if (dol_strlen($this->egroupware_id) == 0)
2604
			{
2605
				$this->egroupware_id = 1;
2606
			}
2607
2608
			$info["phpgwContactOwner"] = $this->egroupware_id;
2609
2610
			if ($this->email) $info["rfc822Mailbox"] = $this->email;
2611
			if ($this->phone_mobile) $info["phpgwCellTelephoneNumber"] = $this->phone_mobile;
2612
		}
2613
2614
		return $info;
2615
	}
2616
2617
2618
	/**
2619
	 *  Initialise an instance with random values.
2620
	 *  Used to build previews or test instances.
2621
	 *	id must be 0 if object instance is a specimen.
2622
	 *
2623
	 *  @return	void
2624
	 */
2625
	function initAsSpecimen()
2626
	{
2627
		global $user,$langs;
2628
2629
		$now=dol_now();
2630
2631
		// Initialise parametres
2632
		$this->id=0;
2633
		$this->ref = 'SPECIMEN';
2634
		$this->specimen=1;
2635
2636
		$this->lastname='DOLIBARR';
2637
		$this->firstname='SPECIMEN';
2638
		$this->gender='man';
2639
		$this->note='This is a note';
2640
		$this->email='[email protected]';
2641
		$this->skype='skypepseudo';
2642
		$this->twitter='twitterpseudo';
2643
		$this->facebook='facebookpseudo';
2644
		$this->office_phone='0999999999';
2645
		$this->office_fax='0999999998';
2646
		$this->user_mobile='0999999997';
2647
		$this->admin=0;
2648
		$this->login='dolibspec';
2649
		$this->pass='dolibspec';
2650
		//$this->pass_indatabase='dolibspec';									Set after a fetch
2651
		//$this->pass_indatabase_crypted='e80ca5a88c892b0aaaf7e154853bccab';	Set after a fetch
2652
		$this->datec=$now;
2653
		$this->datem=$now;
2654
2655
		$this->datelastlogin=$now;
2656
		$this->datepreviouslogin=$now;
2657
		$this->statut=1;
2658
2659
		//$this->societe_id = 1;	For external users
2660
		//$this->contact_id = 1;	For external users
2661
		$this->entity = 1;
2662
	}
2663
2664
	/**
2665
	 *  Load info of user object
2666
	 *
2667
	 *  @param  int		$id     Id of user to load
2668
	 *  @return	void
2669
	 */
2670
	function info($id)
2671
	{
2672
		$sql = "SELECT u.rowid, u.login as ref, u.datec,";
2673
		$sql.= " u.tms as date_modification, u.entity";
2674
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
2675
		$sql.= " WHERE u.rowid = ".$id;
2676
2677
		$result=$this->db->query($sql);
2678
		if ($result)
2679
		{
2680
			if ($this->db->num_rows($result))
2681
			{
2682
				$obj = $this->db->fetch_object($result);
2683
2684
				$this->id = $obj->rowid;
2685
2686
				$this->ref			     = (! $obj->ref) ? $obj->rowid : $obj->ref;
2687
				$this->date_creation     = $this->db->jdate($obj->datec);
2688
				$this->date_modification = $this->db->jdate($obj->date_modification);
2689
				$this->entity            = $obj->entity;
2690
			}
2691
2692
			$this->db->free($result);
2693
		}
2694
		else
2695
		{
2696
			dol_print_error($this->db);
2697
		}
2698
	}
2699
2700
2701
	/**
2702
	 *    Return number of mass Emailing received by this contacts with its email
2703
	 *
2704
	 *    @return       int     Number of EMailings
2705
	 */
2706
	function getNbOfEMailings()
2707
	{
2708
		$sql = "SELECT count(mc.email) as nb";
2709
		$sql.= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2710
		$sql.= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2711
		$sql.= " AND mc.statut NOT IN (-1,0)";      // -1 erreur, 0 non envoye, 1 envoye avec succes
2712
2713
		$resql=$this->db->query($sql);
2714
		if ($resql)
2715
		{
2716
			$obj = $this->db->fetch_object($resql);
2717
			$nb=$obj->nb;
2718
2719
			$this->db->free($resql);
2720
			return $nb;
2721
		}
2722
		else
2723
		{
2724
			$this->error=$this->db->error();
2725
			return -1;
2726
		}
2727
	}
2728
2729
	/**
2730
	 *  Return number of existing users
2731
	 *
2732
	 *  @param	string	$limitTo	Limit to '' or 'active'
2733
	 *  @param	string	$option		'superadmin' = return for entity 0 only
2734
	 *  @param	int		$admin		Filter on admin tag
2735
	 *  @return int  				Number of users
2736
	 */
2737
	function getNbOfUsers($limitTo, $option='', $admin=-1)
2738
	{
2739
		global $conf;
2740
2741
		$sql = "SELECT count(rowid) as nb";
2742
		$sql.= " FROM ".MAIN_DB_PREFIX."user";
2743
		if ($option == 'superadmin')
2744
		{
2745
			$sql.= " WHERE entity = 0";
2746
			if ($admin >= 0) $sql.= " AND admin = ".$admin;
2747
		}
2748
		else
2749
		{
2750
			$sql.=" WHERE entity IN (".getEntity('user',0).")";
2751
			if ($limitTo == 'active') $sql.= " AND statut = 1";
2752
			if ($admin >= 0) $sql.= " AND admin = ".$admin;
2753
		}
2754
2755
		$resql=$this->db->query($sql);
2756
		if ($resql)
2757
		{
2758
			$obj = $this->db->fetch_object($resql);
2759
			$nb=$obj->nb;
2760
2761
			$this->db->free($resql);
2762
			return $nb;
2763
		}
2764
		else
2765
		{
2766
			$this->error=$this->db->lasterror();
2767
			return -1;
2768
		}
2769
	}
2770
2771
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2772
	/**
2773
	 *  Update user using data from the LDAP
2774
	 *
2775
	 *  @param	ldapuser	$ldapuser	Ladp User
2776
	 *
2777
	 *  @return int  				<0 if KO, >0 if OK
2778
	 */
2779
	function update_ldap2dolibarr(&$ldapuser)
2780
	{
2781
        // phpcs:enable
2782
		// TODO: Voir pourquoi le update met à jour avec toutes les valeurs vide (global $user écrase ?)
2783
		global $user, $conf;
2784
2785
		$this->firstname=$ldapuser->{$conf->global->LDAP_FIELD_FIRSTNAME};
2786
		$this->lastname=$ldapuser->{$conf->global->LDAP_FIELD_NAME};
2787
		$this->login=$ldapuser->{$conf->global->LDAP_FIELD_LOGIN};
2788
		$this->pass=$ldapuser->{$conf->global->LDAP_FIELD_PASSWORD};
2789
		$this->pass_indatabase_crypted=$ldapuser->{$conf->global->LDAP_FIELD_PASSWORD_CRYPTED};
2790
2791
		$this->office_phone=$ldapuser->{$conf->global->LDAP_FIELD_PHONE};
2792
		$this->user_mobile=$ldapuser->{$conf->global->LDAP_FIELD_MOBILE};
2793
		$this->office_fax=$ldapuser->{$conf->global->LDAP_FIELD_FAX};
2794
		$this->email=$ldapuser->{$conf->global->LDAP_FIELD_MAIL};
2795
		$this->skype=$ldapuser->{$conf->global->LDAP_FIELD_SKYPE};
2796
		$this->twitter=$ldapuser->{$conf->global->LDAP_FIELD_TWITTER};
2797
		$this->facebook=$ldapuser->{$conf->global->LDAP_FIELD_FACEBOOK};
2798
		$this->ldap_sid=$ldapuser->{$conf->global->LDAP_FIELD_SID};
2799
2800
		$this->job=$ldapuser->{$conf->global->LDAP_FIELD_TITLE};
2801
		$this->note=$ldapuser->{$conf->global->LDAP_FIELD_DESCRIPTION};
2802
2803
		$result = $this->update($user);
2804
2805
		dol_syslog(get_class($this)."::update_ldap2dolibarr result=".$result, LOG_DEBUG);
2806
2807
		return $result;
2808
	}
2809
2810
2811
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2812
	/**
2813
	 * Return and array with all instanciated first level children users of current user
2814
	 *
2815
	 * @return	void
2816
	 * @see getAllChildIds
2817
	 */
2818
	function get_children()
2819
	{
2820
        // phpcs:enable
2821
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."user";
2822
		$sql.= " WHERE fk_user = ".$this->id;
2823
2824
		dol_syslog(get_class($this)."::get_children result=".$result, LOG_DEBUG);
0 ignored issues
show
Bug introduced by
The variable $result 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...
2825
		$res  = $this->db->query($sql);
2826
		if ($res)
2827
		{
2828
			$users = array ();
2829
			while ($rec = $this->db->fetch_array($res))
2830
			{
2831
				$user = new User($this->db);
2832
				$user->fetch($rec['rowid']);
2833
				$users[] = $user;
2834
			}
2835
			return $users;
2836
		}
2837
		else
2838
		{
2839
			dol_print_error($this->db);
2840
			return -1;
2841
		}
2842
	}
2843
2844
2845
	/**
2846
	 * 	Load this->parentof that is array(id_son=>id_parent, ...)
2847
	 *
2848
	 *	@return		int		<0 if KO, >0 if OK
2849
	 */
2850
	private function loadParentOf()
2851
	{
2852
		global $conf;
2853
2854
		$this->parentof=array();
2855
2856
		// Load array[child]=parent
2857
		$sql = "SELECT fk_user as id_parent, rowid as id_son";
2858
		$sql.= " FROM ".MAIN_DB_PREFIX."user";
2859
		$sql.= " WHERE fk_user <> 0";
2860
		$sql.= " AND entity IN (".getEntity('user').")";
2861
2862
		dol_syslog(get_class($this)."::loadParentOf", LOG_DEBUG);
2863
		$resql = $this->db->query($sql);
2864
		if ($resql)
2865
		{
2866
			while ($obj= $this->db->fetch_object($resql))
2867
			{
2868
				$this->parentof[$obj->id_son]=$obj->id_parent;
2869
			}
2870
			return 1;
2871
		}
2872
		else
2873
		{
2874
			dol_print_error($this->db);
2875
			return -1;
2876
		}
2877
	}
2878
2879
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2880
	/**
2881
	 * 	Reconstruit l'arborescence hierarchique des users sous la forme d'un tableau
2882
	 *	Set and return this->users that is an array sorted according to tree with arrays of:
2883
	 *				id = id user
2884
	 *				lastname
2885
	 *				firstname
2886
	 *				fullname = nom avec chemin complet du user
2887
	 *				fullpath = chemin complet compose des id: "_grandparentid_parentid_id"
2888
	 *
2889
	 *  @param      int		$deleteafterid      Removed all users including the leaf $deleteafterid (and all its child) in user tree.
2890
	 *  @param		string	$filter				SQL filter on users
2891
	 *	@return		array		      		  	Array of users $this->users. Note: $this->parentof is also set.
2892
	 */
2893
	function get_full_tree($deleteafterid=0, $filter='')
2894
	{
2895
        // phpcs:enable
2896
		global $conf, $user;
2897
		global $hookmanager;
2898
2899
		// Actions hooked (by external module)
2900
		$hookmanager->initHooks(array('userdao'));
2901
2902
		$this->users = array();
2903
2904
		// Init this->parentof that is array(id_son=>id_parent, ...)
2905
		$this->loadParentOf();
2906
2907
		// Init $this->users array
2908
		$sql = "SELECT DISTINCT u.rowid, u.firstname, u.lastname, u.fk_user, u.fk_soc, u.login, u.email, u.gender, u.admin, u.statut, u.photo, u.entity";	// Distinct reduce pb with old tables with duplicates
2909
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
2910
		// Add fields from hooks
2911
		$parameters=array();
2912
		$reshook=$hookmanager->executeHooks('printUserListWhere',$parameters);    // Note that $action and $object may have been modified by hook
2913
		if ($reshook > 0) {
2914
			$sql.=$hookmanager->resPrint;
2915
		} else {
2916
			$sql.= " WHERE u.entity IN (".getEntity('user').")";
2917
		}
2918
		if ($filter) $sql.=" AND ".$filter;
2919
2920
		dol_syslog(get_class($this)."::get_full_tree get user list", LOG_DEBUG);
2921
		$resql = $this->db->query($sql);
2922
		if ($resql)
2923
		{
2924
			$i=0;
2925
			while ($obj = $this->db->fetch_object($resql))
2926
			{
2927
				$this->users[$obj->rowid]['rowid'] = $obj->rowid;
2928
				$this->users[$obj->rowid]['id'] = $obj->rowid;
2929
				$this->users[$obj->rowid]['fk_user'] = $obj->fk_user;
2930
				$this->users[$obj->rowid]['fk_soc'] = $obj->fk_soc;
2931
				$this->users[$obj->rowid]['firstname'] = $obj->firstname;
2932
				$this->users[$obj->rowid]['lastname'] = $obj->lastname;
2933
				$this->users[$obj->rowid]['login'] = $obj->login;
2934
				$this->users[$obj->rowid]['statut'] = $obj->statut;
2935
				$this->users[$obj->rowid]['entity'] = $obj->entity;
2936
				$this->users[$obj->rowid]['email'] = $obj->email;
2937
				$this->users[$obj->rowid]['gender'] = $obj->gender;
2938
				$this->users[$obj->rowid]['admin'] = $obj->admin;
2939
				$this->users[$obj->rowid]['photo'] = $obj->photo;
2940
				$i++;
2941
			}
2942
		}
2943
		else
2944
		{
2945
			dol_print_error($this->db);
2946
			return -1;
2947
		}
2948
2949
		// We add the fullpath property to each elements of first level (no parent exists)
2950
		dol_syslog(get_class($this)."::get_full_tree call to build_path_from_id_user", LOG_DEBUG);
2951
		foreach($this->users as $key => $val)
2952
		{
2953
			$result = $this->build_path_from_id_user($key,0);	// Process a branch from the root user key (this user has no parent)
2954
			if ($result < 0)
2955
			{
2956
				$this->error='ErrorLoopInHierarchy';
2957
				return -1;
2958
			}
2959
		}
2960
2961
		// Exclude leaf including $deleteafterid from tree
2962
		if ($deleteafterid)
2963
		{
2964
			//print "Look to discard user ".$deleteafterid."\n";
2965
			$keyfilter1='^'.$deleteafterid.'$';
2966
			$keyfilter2='_'.$deleteafterid.'$';
2967
			$keyfilter3='^'.$deleteafterid.'_';
2968
			$keyfilter4='_'.$deleteafterid.'_';
2969
			foreach($this->users as $key => $val)
2970
			{
2971
				if (preg_match('/'.$keyfilter1.'/',$val['fullpath']) || preg_match('/'.$keyfilter2.'/',$val['fullpath'])
2972
					|| preg_match('/'.$keyfilter3.'/',$val['fullpath']) || preg_match('/'.$keyfilter4.'/',$val['fullpath']))
2973
				{
2974
					unset($this->users[$key]);
2975
				}
2976
			}
2977
		}
2978
2979
		dol_syslog(get_class($this)."::get_full_tree dol_sort_array", LOG_DEBUG);
2980
		$this->users=dol_sort_array($this->users, 'fullname', 'asc', true, false);
2981
2982
		//var_dump($this->users);
2983
2984
		return $this->users;
2985
	}
2986
2987
	/**
2988
	 * 	Return list of all child users id in herarchy (all sublevels).
2989
	 *  Note: Calling this function also reset full list of users into $this->users.
2990
	 *
2991
	 *  @param      int      $addcurrentuser    1=Add also current user id to the list.
2992
	 *	@return		array		      		  	Array of user id lower than user (all levels under user). This overwrite this->users.
2993
	 *  @see get_children
2994
	 */
2995
	function getAllChildIds($addcurrentuser=0)
2996
	{
2997
		$childids=array();
2998
2999
		if (isset($this->cache_childids[$this->id]))
3000
		{
3001
			$childids = $this->cache_childids[$this->id];
3002
		}
3003
		else
3004
		{
3005
			// Init this->users
3006
			$this->get_full_tree();
3007
3008
			$idtoscan=$this->id;
3009
3010
			dol_syslog("Build childid for id = ".$idtoscan);
3011
			foreach($this->users as $id => $val)
3012
			{
3013
				//var_dump($val['fullpath']);
3014
				if (preg_match('/_'.$idtoscan.'_/', $val['fullpath'])) $childids[$val['id']]=$val['id'];
3015
			}
3016
		}
3017
		$this->cache_childids[$this->id] = $childids;
3018
3019
		if ($addcurrentuser) $childids[$this->id]=$this->id;
3020
3021
		return $childids;
3022
	}
3023
3024
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3025
	/**
3026
	 *	For user id_user and its childs available in this->users, define property fullpath and fullname.
3027
	 *  Function called by get_full_tree().
3028
	 *
3029
	 * 	@param		int		$id_user		id_user entry to update
3030
	 * 	@param		int		$protection		Deep counter to avoid infinite loop (no more required, a protection is added with array useridfound)
3031
	 *	@return		int                     < 0 if KO (infinit loop), >= 0 if OK
3032
	 */
3033
	function build_path_from_id_user($id_user,$protection=0)
3034
	{
3035
        // phpcs:enable
3036
		dol_syslog(get_class($this)."::build_path_from_id_user id_user=".$id_user." protection=".$protection, LOG_DEBUG);
3037
3038
		if (! empty($this->users[$id_user]['fullpath']))
3039
		{
3040
			// Already defined
3041
			dol_syslog(get_class($this)."::build_path_from_id_user fullpath and fullname already defined", LOG_WARNING);
3042
			return 0;
3043
		}
3044
3045
		// Define fullpath and fullname
3046
		$this->users[$id_user]['fullpath'] = '_'.$id_user;
3047
		$this->users[$id_user]['fullname'] = $this->users[$id_user]['lastname'];
3048
		$i=0; $cursor_user=$id_user;
3049
3050
		$useridfound=array($id_user);
3051
		while (! empty($this->parentof[$cursor_user]))
3052
		{
3053
			if (in_array($this->parentof[$cursor_user], $useridfound))
3054
			{
3055
				dol_syslog("The hierarchy of user has a recursive loop", LOG_WARNING);
3056
				return -1;     // Should not happen. Protection against looping hierarchy
3057
			}
3058
			$useridfound[]=$this->parentof[$cursor_user];
3059
			$this->users[$id_user]['fullpath'] = '_'.$this->parentof[$cursor_user].$this->users[$id_user]['fullpath'];
3060
			$this->users[$id_user]['fullname'] = $this->users[$this->parentof[$cursor_user]]['lastname'].' >> '.$this->users[$id_user]['fullname'];
3061
			$i++; $cursor_user=$this->parentof[$cursor_user];
3062
		}
3063
3064
		// We count number of _ to have level
3065
		$this->users[$id_user]['level']=dol_strlen(preg_replace('/[^_]/i','',$this->users[$id_user]['fullpath']));
3066
3067
		return 1;
3068
	}
3069
3070
	/**
3071
	 * Function used to replace a thirdparty id with another one.
3072
	 *
3073
	 * @param DoliDB $db Database handler
3074
	 * @param int $origin_id Old thirdparty id
3075
	 * @param int $dest_id New thirdparty id
3076
	 * @return bool
3077
	 */
3078
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
3079
	{
3080
		$tables = array(
3081
			'user',
3082
		);
3083
3084
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
3085
	}
3086
3087
3088
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3089
	/**
3090
	 *      Charge indicateurs this->nb pour le tableau de bord
3091
	 *
3092
	 *      @return     int         <0 if KO, >0 if OK
3093
	 */
3094
	function load_state_board()
3095
	{
3096
        // phpcs:enable
3097
		global $conf;
3098
3099
		$this->nb=array();
3100
3101
		$sql = "SELECT count(u.rowid) as nb";
3102
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
3103
		$sql.= " WHERE u.statut > 0";
3104
		//$sql.= " AND employee != 0";
3105
		$sql.= " AND u.entity IN (".getEntity('user').")";
3106
3107
		$resql=$this->db->query($sql);
3108
		if ($resql)
3109
		{
3110
			while ($obj=$this->db->fetch_object($resql))
3111
			{
3112
				$this->nb["users"]=$obj->nb;
3113
			}
3114
			$this->db->free($resql);
3115
			return 1;
3116
		}
3117
		else
3118
		{
3119
			dol_print_error($this->db);
3120
			$this->error=$this->db->error();
3121
			return -1;
3122
		}
3123
	}
3124
3125
	/**
3126
	 *  Create a document onto disk according to template module.
3127
	 *
3128
	 * 	@param	    string		$modele			Force model to use ('' to not force)
3129
	 * 	@param		Translate	$outputlangs	Object langs to use for output
3130
	 *  @param      int			$hidedetails    Hide details of lines
3131
	 *  @param      int			$hidedesc       Hide description
3132
	 *  @param      int			$hideref        Hide ref
3133
         *  @param   null|array  $moreparams     Array to provide more information
3134
	 * 	@return     int         				0 if KO, 1 if OK
3135
	 */
3136
	public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
3137
	{
3138
		global $conf, $user, $langs;
3139
3140
		$langs->load("user");
3141
3142
		// Positionne le modele sur le nom du modele a utiliser
3143
		if (! dol_strlen($modele))
3144
		{
3145
			if (! empty($conf->global->USER_ADDON_PDF))
3146
			{
3147
				$modele = $conf->global->USER_ADDON_PDF;
3148
			}
3149
			else
3150
			{
3151
				$modele = 'bluesky';
3152
			}
3153
		}
3154
3155
		$modelpath = "core/modules/user/doc/";
3156
3157
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
3158
	}
3159
3160
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3161
	/**
3162
	 *  Return property of user from its id
3163
	 *
3164
	 *  @param	int		$rowid      id of contact
3165
	 *  @param  string	$mode       'email' or 'mobile'
3166
	 *  @return string  			Email of user with format: "Full name <email>"
3167
	 */
3168
	function user_get_property($rowid,$mode)
3169
	{
3170
        // phpcs:enable
3171
		$user_property='';
3172
3173
		if (empty($rowid)) return '';
3174
3175
		$sql = "SELECT rowid, email, user_mobile, civility, lastname, firstname";
3176
		$sql.= " FROM ".MAIN_DB_PREFIX."user";
3177
		$sql.= " WHERE rowid = '".$rowid."'";
3178
3179
		$resql=$this->db->query($sql);
3180
		if ($resql)
3181
		{
3182
			$nump = $this->db->num_rows($resql);
3183
3184
			if ($nump)
3185
			{
3186
				$obj = $this->db->fetch_object($resql);
3187
3188
				if ($mode == 'email') $user_property = dolGetFirstLastname($obj->firstname, $obj->lastname)." <".$obj->email.">";
3189
				else if ($mode == 'mobile') $user_property = $obj->user_mobile;
3190
			}
3191
			return $user_property;
3192
		}
3193
		else
3194
		{
3195
			dol_print_error($this->db);
3196
		}
3197
	}
3198
3199
	/**
3200
	 *	Load all objects into $this->users
3201
	 *
3202
	 *  @param	string		$sortorder		sort order
3203
	 *  @param	string		$sortfield		sort field
3204
	 *  @param	int			$limit			limit page
3205
	 *  @param	int			$offset			page
3206
	 *  @param	array		$filter			Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
3207
	 *  @param  string      $filtermode		Filter mode (AND or OR)
3208
	 *  @return int							<0 if KO, >0 if OK
3209
	 */
3210
	function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter=array(), $filtermode='AND')
3211
	{
3212
		global $conf;
3213
3214
		$sql="SELECT t.rowid";
3215
		$sql.= ' FROM '.MAIN_DB_PREFIX .$this->table_element.' as t ';
3216
		$sql.= " WHERE 1";
3217
3218
		// Manage filter
3219
		$sqlwhere = array();
3220
		if (!empty($filter)){
3221
			foreach($filter as $key => $value) {
3222
				if ($key=='t.rowid') {
3223
					$sqlwhere[] = $key . '='. $value;
3224
				}
3225
				elseif (strpos($key,'date') !== false) {
3226
					$sqlwhere[] = $key.' = \''.$this->db->idate($value).'\'';
3227
				}
3228
				elseif ($key=='customsql') {
3229
					$sqlwhere[] = $value;
3230
				}
3231
				else {
3232
					$sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
3233
				}
3234
			}
3235
		}
3236
		if (count($sqlwhere) > 0) {
3237
			$sql .= ' AND (' . implode(' '.$filtermode.' ', $sqlwhere).')';
3238
		}
3239
		$sql.= $this->db->order($sortfield,$sortorder);
3240
		if ($limit) $sql.= $this->db->plimit($limit+1,$offset);
3241
3242
		dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG);
3243
3244
		$resql=$this->db->query($sql);
3245
		if ($resql)
3246
		{
3247
			$this->users=array();
3248
			$num = $this->db->num_rows($resql);
3249
			if ($num)
3250
			{
3251
				while ($obj = $this->db->fetch_object($resql))
3252
				{
3253
					$line = new self($this->db);
3254
					$result = $line->fetch($obj->rowid);
3255
					if ($result>0 && !empty($line->id)) {
3256
						$this->users[$obj->rowid] = clone $line;
3257
					}
3258
				}
3259
				$this->db->free($resql);
3260
			}
3261
			return $num;
3262
		}
3263
		else
3264
		{
3265
			$this->errors[] = $this->db->lasterror();
3266
			return -1;
3267
		}
3268
	}
3269
}
3270