Completed
Branch develop (c2c696)
by
unknown
28:47
created

User::_load_ldap_dn()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 8
nop 2
dl 0
loc 9
rs 9.2
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-2016 Regis Houssin        <[email protected]>
8
 * Copyright (C) 2005      Lionel Cousteix      <[email protected]>
9
 * Copyright (C) 2011      Herve Prot           <[email protected]>
10
 * Copyright (C) 2013-2014 Philippe Grand       <[email protected]>
11
 * Copyright (C) 2013-2015 Alexandre Spangaro   <[email protected]>
12
 * Copyright (C) 2015      Marcos García        <[email protected]>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 3 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26
 */
27
28
/**
29
 *  \file       htdocs/user/class/user.class.php
30
 *	\brief      File of class to manage users
31
 *  \ingroup	core
32
 */
33
34
require_once DOL_DOCUMENT_ROOT .'/core/class/commonobject.class.php';
35
36
/**
37
 *	Class to manage Dolibarr users
38
 */
39
class User extends CommonObject
40
{
41
	public $element='user';
42
	public $table_element='user';
43
	protected $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
44
45
	public $id=0;
46
	public $ldap_sid;
47
	public $search_sid;
48
	public $employee;
49
	public $gender;
50
	public $email;
51
	public $skype;
52
	public $job;
53
	public $signature;
54
	public $address;
55
    	public $zip;
56
    	public $town;
57
    	public $state_id;
58
    	public $state_code;
59
    	public $state;
60
	public $office_phone;
61
	public $office_fax;
62
	public $user_mobile;
63
	public $admin;
64
	public $login;
65
    	public $api_key;
66
	public $entity;
67
68
	//! Clear password in memory
69
	public $pass;
70
	//! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
71
	public $pass_indatabase;
72
	//! Encrypted password in database (always defined)
73
	public $pass_indatabase_crypted;
74
75
	public $datec;
76
	public $datem;
77
78
	//! If this is defined, it is an external user
79
	/**
80
	 * @deprecated
81
	 * @see socid
82
	 */
83
	public $societe_id;
84
	/**
85
	 * @deprecated
86
	 * @see contactid
87
	 */
88
	public $contact_id;
89
	public $socid;
90
	public $contactid;
91
92
	public $fk_member;
93
	public $fk_user;
94
95
	public $clicktodial_url;
96
	public $clicktodial_login;
97
	public $clicktodial_password;
98
	public $clicktodial_poste;
99
100
	public $datelastlogin;
101
	public $datepreviouslogin;
102
	public $statut;
103
	public $photo;
104
	public $lang;
105
106
	public $rights;                        // Array of permissions user->rights->permx
107
	public $all_permissions_are_loaded;	/**< \private all_permissions_are_loaded */
108
	private $_tab_loaded=array();		// Array of cache of already loaded permissions
109
	public $nb_rights;			// Number of rights granted to the user
110
111
	public $conf;           		// To store personal config
112
	var $oldcopy;                	// To contains a clone of this when we need to save old properties of object
113
114
	public $users;					// To store all tree of users hierarchy
115
	public $parentof;				// To store an array of all parents for all ids.
116
117
	public $accountancy_code;			// Accountancy code in prevision of the complete accountancy module
118
	
119
	public $thm;					// Average cost of employee - Used for valuation of time spent
120
	public $tjm;					// Average cost of employee
121
	
122
	public $salary;					// Monthly salary       - Denormalized value from llx_user_employment  
123
	public $salaryextra;				// Monthly salary extra - Denormalized value from llx_user_employment
124
	public $weeklyhours;				// Weekly hours         - Denormalized value from llx_user_employment
125
126
	public $color;						// Define background color for user in agenda
127
	
128
	public $dateemployment;			// Define date of employment by company
129
130
	private $cache_childids;
131
	
132
	
133
	/**
134
	 *    Constructor de la classe
135
	 *
136
	 *    @param   DoliDb  $db     Database handler
137
	 */
138
	function __construct($db)
139
	{
140
		$this->db = $db;
141
142
		// User preference
143
		$this->liste_limit = 0;
144
		$this->clicktodial_loaded = 0;
145
146
		// For cache usage
147
		$this->all_permissions_are_loaded = 0;
148
		$this->nb_rights = 0;
149
150
		// Force some default values
151
		$this->admin = 0;
152
		$this->employee = 1;
153
154
		$this->conf				    = new stdClass();
155
		$this->rights				= new stdClass();
156
		$this->rights->user			= new stdClass();
157
		$this->rights->user->user	= new stdClass();
158
		$this->rights->user->self	= new stdClass();
159
	}
160
161
	/**
162
	 *	Load a user from database with its id or ref (login)
163
	 *
164
	 *	@param	int		$id		       		If defined, id to used for search
165
	 * 	@param  string	$login       		If defined, login to used for search
166
	 *	@param  string	$sid				If defined, sid to used for search
167
	 * 	@param	int		$loadpersonalconf	1=also load personal conf of user (in $user->conf->xxx)
168
	 *  @param  int     $entity             If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup.
169
	 * 	@return	int							<0 if KO, 0 not found, >0 if OK
170
	 */
171
	function fetch($id='', $login='',$sid='',$loadpersonalconf=1, $entity=-1)
172
	{
173
		global $conf, $user;
174
175
		// Clean parameters
176
		$login=trim($login);
177
178
		// Get user
179
		$sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.email, u.job, u.skype, u.signature, u.office_phone, u.office_fax, u.user_mobile,";
180
		$sql.= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
181
		$sql.= " u.admin, u.login, u.note,";
182
		$sql.= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,";
183
		$sql.= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid,";
184
		$sql.= " u.statut, u.lang, u.entity,";
185
		$sql.= " u.datec as datec,";
186
		$sql.= " u.tms as datem,";
187
		$sql.= " u.datelastlogin as datel,";
188
		$sql.= " u.datepreviouslogin as datep,";
189
		$sql.= " u.photo as photo,";
190
		$sql.= " u.openid as openid,";
191
		$sql.= " u.accountancy_code,";
192
		$sql.= " u.thm,";
193
		$sql.= " u.tjm,";
194
		$sql.= " u.salary,";
195
		$sql.= " u.salaryextra,";
196
		$sql.= " u.weeklyhours,";
197
		$sql.= " u.color,";
198
		$sql.= " u.dateemployment,";
199
		$sql.= " u.ref_int, u.ref_ext,";
200
        $sql.= " c.code as country_code, c.label as country,";
201
        $sql.= " d.code_departement as state_code, d.nom as state";
202
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
203
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON u.fk_country = c.rowid";
204
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON u.fk_state = d.rowid";
205
206
		if ($entity < 0)
207
		{
208
    		if ((empty($conf->multicompany->enabled) || empty($conf->multicompany->transverse_mode)) && (! empty($user->entity)))
209
    		{
210
    			$sql.= " WHERE u.entity IN (0,".$conf->entity.")";
211
    		}
212
    		else
213
    		{
214
    			$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
215
    		}
216
		}
217
		else  // The fetch was forced on an entity
218
		{
219
			if (!empty($conf->multicompany->enabled) && !empty($conf->multicompany->transverse_mode))
220
				$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
221
			else
222
				$sql.= " WHERE u.entity IN (0, ".$conf->entity.")";
223
		}
224
225
		if ($sid)    // permet une recherche du user par son SID ActiveDirectory ou Samba
226
		{
227
			$sql.= " AND (u.ldap_sid = '".$this->db->escape($sid)."' OR u.login = '".$this->db->escape($login)."') LIMIT 1";
228
		}
229
		else if ($login)
230
		{
231
			$sql.= " AND u.login = '".$this->db->escape($login)."'";
232
		}
233
		else
234
		{
235
			$sql.= " AND u.rowid = ".$id;
236
		}
237
238
		$result = $this->db->query($sql);
239
		if ($result)
240
		{
241
			$obj = $this->db->fetch_object($result);
242
			if ($obj)
243
			{
244
				$this->id 			= $obj->rowid;
245
				$this->ref 			= $obj->rowid;
246
247
				$this->ref_int 		= $obj->ref_int;
248
				$this->ref_ext 		= $obj->ref_ext;
249
250
				$this->ldap_sid 	= $obj->ldap_sid;
251
				$this->lastname		= $obj->lastname;
252
				$this->firstname 	= $obj->firstname;
253
254
				$this->employee		= $obj->employee;
255
256
				$this->login		= $obj->login;
257
				$this->gender       = $obj->gender;
258
				$this->pass_indatabase = $obj->pass;
259
				$this->pass_indatabase_crypted = $obj->pass_crypted;
260
				$this->pass			= $obj->pass;
261
				$this->pass_temp	= $obj->pass_temp;
262
                $this->api_key		= $obj->api_key;
263
264
                $this->address 		= $obj->address;
265
                $this->zip 			= $obj->zip;
266
                $this->town 		= $obj->town;
267
268
                $this->country_id   = $obj->country_id;
269
                $this->country_code = $obj->country_id?$obj->country_code:'';
270
                //$this->country 		= $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
271
272
                $this->state_id     = $obj->state_id;
273
                $this->state_code   = $obj->state_code;
274
                $this->state        = ($obj->state!='-'?$obj->state:'');
275
276
				$this->office_phone	= $obj->office_phone;
277
				$this->office_fax   = $obj->office_fax;
278
				$this->user_mobile  = $obj->user_mobile;
279
				$this->email		= $obj->email;
280
				$this->skype		= $obj->skype;
281
				$this->job			= $obj->job;
282
				$this->signature	= $obj->signature;
283
				$this->admin		= $obj->admin;
284
				$this->note			= $obj->note;
285
				$this->statut		= $obj->statut;
286
				$this->photo		= $obj->photo;
287
				$this->openid		= $obj->openid;
288
				$this->lang			= $obj->lang;
289
				$this->entity		= $obj->entity;
290
				$this->accountancy_code		= $obj->accountancy_code;
291
				$this->thm			= $obj->thm;
292
				$this->tjm			= $obj->tjm;
293
				$this->salary		= $obj->salary;
294
				$this->salaryextra	= $obj->salaryextra;
295
				$this->weeklyhours	= $obj->weeklyhours;
296
				$this->color		= $obj->color;
297
				$this->dateemployment	= $this->db->jdate($obj->dateemployment);
298
299
				$this->datec				= $this->db->jdate($obj->datec);
300
				$this->datem				= $this->db->jdate($obj->datem);
301
				$this->datelastlogin		= $this->db->jdate($obj->datel);
302
				$this->datepreviouslogin	= $this->db->jdate($obj->datep);
303
304
				$this->societe_id           = $obj->fk_soc;		// deprecated
305
				$this->contact_id           = $obj->fk_socpeople;	// deprecated
306
				$this->socid                = $obj->fk_soc;
307
				$this->contactid            = $obj->fk_socpeople;
308
				$this->fk_member            = $obj->fk_member;
309
				$this->fk_user        		= $obj->fk_user;
310
311
				// Protection when module multicompany was set, admin was set to first entity and the module disabled,
312
				// then this admin user must be admin for all entities.
313
				if (empty($conf->multicompany->enabled) && $this->admin && $this->entity == 1) $this->entity = 0;
314
315
				// Retreive all extrafield for thirdparty
316
				// fetch optionals attributes and labels
317
				require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
318
				$extrafields=new ExtraFields($this->db);
319
				$extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true);
320
				$this->fetch_optionals($this->id,$extralabels);
321
322
				$this->db->free($result);
323
			}
324
			else
325
			{
326
				$this->error="USERNOTFOUND";
327
				dol_syslog(get_class($this)."::fetch user not found", LOG_DEBUG);
328
329
				$this->db->free($result);
330
				return 0;
331
			}
332
		}
333
		else
334
		{
335
			$this->error=$this->db->lasterror();
336
			return -1;
337
		}
338
339
		// To get back the global configuration unique to the user
340
		if ($loadpersonalconf)
341
		{
342
			$sql = "SELECT param, value FROM ".MAIN_DB_PREFIX."user_param";
343
			$sql.= " WHERE fk_user = ".$this->id;
344
			$sql.= " AND entity = ".$conf->entity;
345
			//dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
346
			$resql=$this->db->query($sql);
347
			if ($resql)
348
			{
349
				$num = $this->db->num_rows($resql);
350
				$i = 0;
351
				while ($i < $num)
352
				{
353
					$obj = $this->db->fetch_object($resql);
354
					$p=(! empty($obj->param)?$obj->param:'');
355
					if (! empty($p)) $this->conf->$p = $obj->value;
356
					$i++;
357
				}
358
				$this->db->free($resql);
359
			}
360
			else
361
			{
362
				$this->error=$this->db->error();
363
				return -2;
364
			}
365
		}
366
367
		return 1;
368
	}
369
370
	/**
371
	 *  Add a right to the user
372
	 *
373
	 * 	@param	int		$rid			id du droit a ajouter
374
	 *  @param  string	$allmodule		Ajouter tous les droits du module allmodule
375
	 *  @param  string	$allperms		Ajouter tous les droits du module allmodule, perms allperms
376
	 *  @param	int		$entity			Entity to use
377
	 *  @return int						> 0 if OK, < 0 if KO
378
	 */
379
	function addrights($rid, $allmodule='', $allperms='', $entity='')
380
	{
381
		global $conf, $user, $langs;
382
383
		$entity = (! empty($entity)?$entity:$conf->entity);
384
385
		dol_syslog(get_class($this)."::addrights $rid, $allmodule, $allperms, $entity");
386
		$error=0;
387
		$whereforadd='';
388
389
		$this->db->begin();
390
391
		if (! empty($rid))
392
		{
393
			// Si on a demande ajout d'un droit en particulier, on recupere
394
			// les caracteristiques (module, perms et subperms) de ce droit.
395
			$sql = "SELECT module, perms, subperms";
396
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
397
			$sql.= " WHERE id = '".$this->db->escape($rid)."'";
398
			$sql.= " AND entity = ".$entity;
399
400
			$result=$this->db->query($sql);
401
			if ($result) {
402
				$obj = $this->db->fetch_object($result);
403
				$module=$obj->module;
404
				$perms=$obj->perms;
405
				$subperms=$obj->subperms;
406
			}
407
			else {
408
				$error++;
409
				dol_print_error($this->db);
410
			}
411
412
			// Where pour la liste des droits a ajouter
413
			$whereforadd="id=".$this->db->escape($rid);
414
			// Ajout des droits induits
415
			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...
416
			else if (! empty($perms)) $whereforadd.=" OR (module='$module' AND (perms='lire' OR perms='read') AND subperms IS NULL)";
417
		}
418
		else {
419
			// On a pas demande un droit en particulier mais une liste de droits
420
			// sur la base d'un nom de module de de perms
421
			// Where pour la liste des droits a ajouter
422
			if (! empty($allmodule)) $whereforadd="module='".$this->db->escape($allmodule)."'";
423
			if (! empty($allperms))  $whereforadd=" AND perms='".$this->db->escape($allperms)."'";
424
		}
425
426
		// Ajout des droits trouves grace au critere whereforadd
427
		if (! empty($whereforadd))
428
		{
429
			//print "$module-$perms-$subperms";
430
			$sql = "SELECT id";
431
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
432
			$sql.= " WHERE ".$whereforadd;
433
			$sql.= " AND entity = ".$entity;
434
435
			$result=$this->db->query($sql);
436
			if ($result)
437
			{
438
				$num = $this->db->num_rows($result);
439
				$i = 0;
440
				while ($i < $num)
441
				{
442
					$obj = $this->db->fetch_object($result);
443
					$nid = $obj->id;
444
445
					$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = ".$this->id." AND fk_id=".$nid;
446
					if (! $this->db->query($sql)) $error++;
447
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_rights (fk_user, fk_id) VALUES (".$this->id.", ".$nid.")";
448
					if (! $this->db->query($sql)) $error++;
449
450
					$i++;
451
				}
452
			}
453
			else
454
			{
455
				$error++;
456
				dol_print_error($this->db);
457
			}
458
		}
459
460
		if (! $error)
461
		{
462
		    $this->context = array('audit'=>$langs->trans("PermissionsAdd"));
0 ignored issues
show
Documentation Bug introduced by
It seems like array('audit' => $langs->trans('PermissionsAdd')) of type array<string,?,{"audit":"?"}> is incompatible with the declared type array<integer,string> of property $context.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
463
		    
464
		    // Call trigger
465
		    $result=$this->call_trigger('USER_MODIFY',$user);
466
		    if ($result < 0) { $error++; }
467
		    // End call triggers
468
		}
469
		
470
		if ($error) {
471
			$this->db->rollback();
472
			return -$error;
473
		}
474
		else {
475
			$this->db->commit();
476
			return 1;
477
		}
478
479
	}
480
481
482
	/**
483
	 *  Remove a right to the user
484
	 *
485
	 *  @param	int		$rid        Id du droit a retirer
486
	 *  @param  string	$allmodule  Retirer tous les droits du module allmodule
487
	 *  @param  string	$allperms   Retirer tous les droits du module allmodule, perms allperms
488
	 *  @param	int		$entity			Entity to use
489
	 *  @return int         		> 0 if OK, < 0 if OK
490
	 */
491
	function delrights($rid, $allmodule='', $allperms='', $entity='')
492
	{
493
		global $conf, $user, $langs;
494
495
		$error=0;
496
		$wherefordel='';
497
		$entity = (! empty($entity)?$entity:$conf->entity);
498
499
		$this->db->begin();
500
501
		if (! empty($rid))
502
		{
503
			// Si on a demande supression d'un droit en particulier, on recupere
504
			// les caracteristiques module, perms et subperms de ce droit.
505
			$sql = "SELECT module, perms, subperms";
506
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
507
			$sql.= " WHERE id = '".$this->db->escape($rid)."'";
508
			$sql.= " AND entity = ".$entity;
509
510
			$result=$this->db->query($sql);
511
			if ($result) {
512
				$obj = $this->db->fetch_object($result);
513
				$module=$obj->module;
514
				$perms=$obj->perms;
515
				$subperms=$obj->subperms;
516
			}
517
			else {
518
				$error++;
519
				dol_print_error($this->db);
520
			}
521
522
			// Where pour la liste des droits a supprimer
523
			$wherefordel="id=".$this->db->escape($rid);
524
			// Suppression des droits induits
525
			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...
526
			if ($perms=='lire' || $perms=='read')       $wherefordel.=" OR (module='$module')";
527
		}
528
		else {
529
			// On a demande suppression d'un droit sur la base d'un nom de module ou perms
530
			// Where pour la liste des droits a supprimer
531
			if (! empty($allmodule)) $wherefordel="module='".$this->db->escape($allmodule)."'";
532
			if (! empty($allperms))  $wherefordel=" AND perms='".$this->db->escape($allperms)."'";
533
		}
534
535
		// Suppression des droits selon critere defini dans wherefordel
536
		if (! empty($wherefordel))
537
		{
538
			//print "$module-$perms-$subperms";
539
			$sql = "SELECT id";
540
			$sql.= " FROM ".MAIN_DB_PREFIX."rights_def";
541
			$sql.= " WHERE $wherefordel";
542
			$sql.= " AND entity = ".$entity;
543
544
			$result=$this->db->query($sql);
545
			if ($result)
546
			{
547
				$num = $this->db->num_rows($result);
548
				$i = 0;
549
				while ($i < $num)
550
				{
551
					$obj = $this->db->fetch_object($result);
552
					$nid = $obj->id;
553
554
					$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights";
555
					$sql.= " WHERE fk_user = ".$this->id." AND fk_id=".$nid;
556
					if (! $this->db->query($sql)) $error++;
557
558
					$i++;
559
				}
560
			}
561
			else
562
			{
563
				$error++;
564
				dol_print_error($this->db);
565
			}
566
		}
567
568
		if (! $error)
569
		{
570
		    $this->context = array('audit'=>$langs->trans("PermissionsDelete"));
0 ignored issues
show
Documentation Bug introduced by
It seems like array('audit' => $langs-...s('PermissionsDelete')) of type array<string,?,{"audit":"?"}> is incompatible with the declared type array<integer,string> of property $context.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
571
		    
572
		    // Call trigger
573
		    $result=$this->call_trigger('USER_MODIFY',$user);
574
		    if ($result < 0) { $error++; }
575
		    // End call triggers
576
		}
577
		
578
		if ($error) {
579
			$this->db->rollback();
580
			return -$error;
581
		}
582
		else {
583
			$this->db->commit();
584
			return 1;
585
		}
586
587
	}
588
589
590
	/**
591
	 *  Clear all permissions array of user
592
	 *
593
	 *  @return	void
594
	 *  @see	getrights
595
	 */
596
	function clearrights()
597
	{
598
		dol_syslog(get_class($this)."::clearrights reset user->rights");
599
		$this->rights='';
600
		$this->all_permissions_are_loaded=false;
601
		$this->_tab_loaded=array();
602
	}
603
604
605
	/**
606
	 *	Load permissions granted to user into object user
607
	 *
608
	 *	@param  string	$moduletag    Limit permission for a particular module ('' by default means load all permissions)
609
	 *	@return	void
610
	 *  @see	clearrights
611
	 */
612
	function getrights($moduletag='')
613
	{
614
		global $conf;
615
616
		if ($moduletag && isset($this->_tab_loaded[$moduletag]) && $this->_tab_loaded[$moduletag])
617
		{
618
			// Le fichier de ce module est deja charge
619
			return;
620
		}
621
622
		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...
623
		{
624
			// Si les permissions ont deja ete charge pour ce user, on quitte
625
			return;
626
		}
627
628
		// Recuperation des droits utilisateurs + recuperation des droits groupes
629
630
		// D'abord les droits utilisateurs
631
		$sql = "SELECT r.module, r.perms, r.subperms";
632
		$sql.= " FROM ".MAIN_DB_PREFIX."user_rights as ur";
633
		$sql.= ", ".MAIN_DB_PREFIX."rights_def as r";
634
		$sql.= " WHERE r.id = ur.fk_id";
635
		$sql.= " AND r.entity IN (0,".(! empty($conf->multicompany->enabled) && ! empty($conf->multicompany->transverse_mode)?"1,":"").$conf->entity.")";
636
		$sql.= " AND ur.fk_user= ".$this->id;
637
		$sql.= " AND r.perms IS NOT NULL";
638
		if ($moduletag) $sql.= " AND r.module = '".$this->db->escape($moduletag)."'";
639
640
		$resql = $this->db->query($sql);
641
		if ($resql)
642
		{
643
			$num = $this->db->num_rows($resql);
644
			$i = 0;
645
			while ($i < $num)
646
			{
647
				$obj = $this->db->fetch_object($resql);
648
649
				$module=$obj->module;
650
				$perms=$obj->perms;
651
				$subperms=$obj->subperms;
652
653
				if ($perms)
654
				{
655
					if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error
656
					if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass();
657
					if ($subperms)
658
					{
659
						if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass();
660
						if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++;
661
						$this->rights->$module->$perms->$subperms = 1;
662
					}
663
					else
664
					{
665
						if(empty($this->rights->$module->$perms)) $this->nb_rights++;
666
						$this->rights->$module->$perms = 1;
667
					}
668
669
				}
670
				$i++;
671
			}
672
			$this->db->free($resql);
673
		}
674
675
		// Maintenant les droits groupes
676
		$sql = "SELECT r.module, r.perms, r.subperms";
677
		$sql.= " FROM ".MAIN_DB_PREFIX."usergroup_rights as gr,";
678
		$sql.= " ".MAIN_DB_PREFIX."usergroup_user as gu,";
679
		$sql.= " ".MAIN_DB_PREFIX."rights_def as r";
680
		$sql.= " WHERE r.id = gr.fk_id";
681
		if (! empty($conf->multicompany->enabled) && ! empty($conf->multicompany->transverse_mode)) {
682
			$sql.= " AND gu.entity IN (0,".$conf->entity.")";
683
		} else {
684
			$sql.= " AND r.entity = ".$conf->entity;
685
		}
686
		$sql.= " AND gr.fk_usergroup = gu.fk_usergroup";
687
		$sql.= " AND gu.fk_user = ".$this->id;
688
		$sql.= " AND r.perms IS NOT NULL";
689
		if ($moduletag) $sql.= " AND r.module = '".$this->db->escape($moduletag)."'";
690
691
		$resql = $this->db->query($sql);
692
		if ($resql)
693
		{
694
			$num = $this->db->num_rows($resql);
695
			$i = 0;
696
			while ($i < $num)
697
			{
698
				$obj = $this->db->fetch_object($resql);
699
700
				$module=$obj->module;
701
				$perms=$obj->perms;
702
				$subperms=$obj->subperms;
703
704
				if ($perms)
705
				{
706
					if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error
707
					if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass();
708
					if ($subperms)
709
					{
710
						if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass();
711
						if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++;
712
						$this->rights->$module->$perms->$subperms = 1;
713
					}
714
					else
715
					{
716
						if(empty($this->rights->$module->$perms)) $this->nb_rights++;
717
						$this->rights->$module->$perms = 1;
718
					}
719
720
				}
721
				$i++;
722
			}
723
			$this->db->free($resql);
724
		}
725
726
		// For backward compatibility
727
		if (isset($this->rights->propale) && ! isset($this->rights->propal)) $this->rights->propal = $this->rights->propale;
728
		if (isset($this->rights->propal) && ! isset($this->rights->propale)) $this->rights->propale = $this->rights->propal;
729
730
		if (! $moduletag)
731
		{
732
			// Si module etait non defini, alors on a tout charge, on peut donc considerer
733
			// que les droits sont en cache (car tous charges) pour cet instance de user
734
			$this->all_permissions_are_loaded=1;
735
		}
736
		else
737
		{
738
			// Si module defini, on le marque comme charge en cache
739
			$this->_tab_loaded[$moduletag]=1;
740
		}
741
	}
742
743
	/**
744
	 *  Change status of a user
745
	 *
746
	 *	@param	int		$statut		Status to set
747
	 *  @return int     			<0 if KO, 0 if nothing is done, >0 if OK
748
	 */
749
	function setstatus($statut)
750
	{
751
		global $conf,$langs,$user;
752
753
		$error=0;
754
755
		// Check parameters
756
		if ($this->statut == $statut) return 0;
757
		else $this->statut = $statut;
758
759
		$this->db->begin();
760
761
		// Deactivate user
762
		$sql = "UPDATE ".MAIN_DB_PREFIX."user";
763
		$sql.= " SET statut = ".$this->statut;
764
		$sql.= " WHERE rowid = ".$this->id;
765
		$result = $this->db->query($sql);
766
767
		dol_syslog(get_class($this)."::setstatus", LOG_DEBUG);
768
		if ($result)
769
		{
770
            // Call trigger
771
            $result=$this->call_trigger('USER_ENABLEDISABLE',$user);
772
            if ($result < 0) { $error++; }
773
            // End call triggers
774
		}
775
776
		if ($error)
777
		{
778
			$this->db->rollback();
779
			return -$error;
780
		}
781
		else
782
		{
783
			$this->db->commit();
784
			return 1;
785
		}
786
	}
787
788
	/**
789
	 * Sets object to supplied categories.
790
	 *
791
	 * Deletes object from existing categories not supplied.
792
	 * Adds it to non existing supplied categories.
793
	 * Existing categories are left untouch.
794
	 *
795
	 * @param int[]|int $categories Category or categories IDs
796
	 */
797
	public function setCategories($categories)
798
	{
799
		// Handle single category
800
		if (!is_array($categories)) {
801
			$categories = array($categories);
802
		}
803
804
		// Get current categories
805
		require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
806
		$c = new Categorie($this->db);
807
		$existing = $c->containing($this->id, Categorie::TYPE_USER, 'id');
808
809
		// Diff
810
		if (is_array($existing)) {
811
			$to_del = array_diff($existing, $categories);
812
			$to_add = array_diff($categories, $existing);
813
		} else {
814
			$to_del = array(); // Nothing to delete
815
			$to_add = $categories;
816
		}
817
818
		// Process
819
		foreach ($to_del as $del) {
820
			if ($c->fetch($del) > 0) {
821
				$c->del_type($this, 'user');
822
			}
823
		}
824
		foreach ($to_add as $add) {
825
			if ($c->fetch($add) > 0) {
826
				$c->add_type($this, 'user');
827
			}
828
		}
829
830
		return;
831
	}
832
833
	/**
834
	 *    	Delete the user
835
	 *
836
	 * 		@return		int		<0 if KO, >0 if OK
837
	 */
838
	function delete()
839
	{
840
		global $user,$conf,$langs;
841
842
		$error=0;
843
844
		$this->db->begin();
845
846
		$this->fetch($this->id);
847
848
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
849
850
		// Remove rights
851
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_rights WHERE fk_user = ".$this->id;
852
853
		if (! $error && ! $this->db->query($sql))
854
		{
855
			$error++;
856
        	$this->error = $this->db->lasterror();
857
		}
858
859
		// Remove group
860
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user WHERE fk_user  = ".$this->id;
861
		if (! $error && ! $this->db->query($sql))
862
		{
863
			$error++;
864
        	$this->error = $this->db->lasterror();
865
		}
866
867
		// If contact, remove link
868
		if ($this->contact_id)
869
		{
870
			$sql = "UPDATE ".MAIN_DB_PREFIX."socpeople SET fk_user_creat = null WHERE rowid = ".$this->contact_id;
871
			if (! $error && ! $this->db->query($sql))
872
			{
873
				$error++;
874
	        	$this->error = $this->db->lasterror();
875
			}
876
		}
877
878
		// Remove extrafields
879
		if ((! $error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) // For avoid conflicts if trigger used
880
        {
881
			$result=$this->deleteExtraFields();
882
			if ($result < 0)
883
			{
884
           		$error++;
885
           		dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
886
           	}
887
        }
888
889
		// Remove user
890
        if (! $error)
891
        {
892
	        $sql = "DELETE FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".$this->id;
893
	       	dol_syslog(get_class($this)."::delete", LOG_DEBUG);
894
	       	if (! $this->db->query($sql))
895
	       	{
896
	       		$error++;
897
	       		$this->error = $this->db->lasterror();
898
	       	}
899
        }
900
901
		if (! $error)
902
		{
903
            // Call trigger
904
            $result=$this->call_trigger('USER_DELETE',$user);
905
	        if ($result < 0)
906
	        {
907
	            $error++;
908
	            $this->db->rollback();
909
			    return -1;
910
	        }
911
            // End call triggers
912
913
			$this->db->commit();
914
			return 1;
915
		}
916
		else
917
		{
918
			$this->db->rollback();
919
			return -1;
920
		}
921
	}
922
923
	/**
924
	 *  Create a user into database
925
	 *
926
	 *  @param	User	$user        	Objet user doing creation
927
	 *  @param  int		$notrigger		1=do not execute triggers, 0 otherwise
928
	 *  @return int			         	<0 if KO, id of created user if OK
929
	 */
930
	function create($user,$notrigger=0)
931
	{
932
		global $conf,$langs;
933
		global $mysoc;
934
935
		// Clean parameters
936
		$this->login = trim($this->login);
937
		if (! isset($this->entity)) $this->entity=$conf->entity;	// If not defined, we use default value
938
939
		dol_syslog(get_class($this)."::create login=".$this->login.", user=".(is_object($user)?$user->id:''), LOG_DEBUG);
940
941
		// Check parameters
942
		if (! empty($conf->global->USER_MAIL_REQUIRED) && ! isValidEMail($this->email))
943
		{
944
			$langs->load("errors");
945
			$this->error = $langs->trans("ErrorBadEMail",$this->email);
946
			return -1;
947
		}
948
		if (empty($this->login))
949
		{
950
			$langs->load("errors");
951
			$this->error = $langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Login"));
952
			return -1;
953
		}
954
955
		$this->datec = dol_now();
956
957
		$error=0;
958
		$this->db->begin();
959
960
		$sql = "SELECT login FROM ".MAIN_DB_PREFIX."user";
961
		$sql.= " WHERE login ='".$this->db->escape($this->login)."'";
962
		$sql.= " AND entity IN (0,".$this->db->escape($conf->entity).")";
963
		
964
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
965
		$resql=$this->db->query($sql);
966
		if ($resql)
967
		{
968
			$num = $this->db->num_rows($resql);
969
			$this->db->free($resql);
970
971
			if ($num)
972
			{
973
				$this->error = 'ErrorLoginAlreadyExists';
974
				dol_syslog(get_class($this)."::create ".$this->error, LOG_WARNING);
975
				$this->db->rollback();
976
				return -6;
977
			}
978
			else
979
			{
980
				$sql = "INSERT INTO ".MAIN_DB_PREFIX."user (datec,login,ldap_sid,entity)";
981
				$sql.= " VALUES('".$this->db->idate($this->datec)."','".$this->db->escape($this->login)."','".$this->db->escape($this->ldap_sid)."',".$this->db->escape($this->entity).")";
982
				$result=$this->db->query($sql);
983
984
				dol_syslog(get_class($this)."::create", LOG_DEBUG);
985
				if ($result)
986
				{
987
					$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."user");
988
989
					// Set default rights
990
					if ($this->set_default_rights() < 0)
991
					{
992
						$this->error='ErrorFailedToSetDefaultRightOfUser';
993
						$this->db->rollback();
994
						return -5;
995
					}
996
					
997
					// Update minor fields
998
					$result = $this->update($user,1,1);
999
					if ($result < 0)
1000
					{
1001
						$this->db->rollback();
1002
						return -4;
1003
					}
1004
1005
					if (! empty($conf->global->STOCK_USERSTOCK_AUTOCREATE))
1006
					{
1007
						require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1008
						$langs->load("stocks");
1009
						$entrepot = new Entrepot($this->db);
1010
						$entrepot->libelle = $langs->trans("PersonalStock",$this->getFullName($langs));
1011
						$entrepot->description = $langs->trans("ThisWarehouseIsPersonalStock",$this->getFullName($langs));
1012
						$entrepot->statut = 1;
1013
						$entrepot->country_id = $mysoc->country_id;
1014
						$entrepot->create($user);
1015
					}
1016
					
1017
					if (! $notrigger)
1018
					{
1019
                        // Call trigger
1020
                        $result=$this->call_trigger('USER_CREATE',$user);
1021
                        if ($result < 0) { $error++; }
1022
                        // End call triggers
1023
					}
1024
1025
					if (! $error)
1026
					{
1027
						$this->db->commit();
1028
						return $this->id;
1029
					}
1030
					else
1031
					{
1032
						//$this->error=$interface->error;
1033
						dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
1034
						$this->db->rollback();
1035
						return -3;
1036
					}
1037
				}
1038
				else
1039
				{
1040
					$this->error=$this->db->lasterror();
1041
					$this->db->rollback();
1042
					return -2;
1043
				}
1044
			}
1045
		}
1046
		else
1047
		{
1048
			$this->error=$this->db->lasterror();
1049
			$this->db->rollback();
1050
			return -1;
1051
		}
1052
	}
1053
1054
1055
	/**
1056
	 *  Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
1057
	 *
1058
	 *  @param	Contact	$contact    Object for source contact
1059
	 * 	@param  string	$login      Login to force
1060
	 *  @param  string	$password   Password to force
1061
	 *  @return int 				<0 if error, if OK returns id of created user
1062
	 */
1063
	function create_from_contact($contact,$login='',$password='')
1064
	{
1065
		global $conf,$user,$langs;
1066
1067
		$error=0;
1068
1069
		// Define parameters
1070
		$this->admin		= 0;
1071
		$this->lastname		= $contact->lastname;
1072
		$this->firstname	= $contact->firstname;
1073
		$this->gender		= $contact->gender;
1074
		$this->email		= $contact->email;
1075
    	$this->skype 		= $contact->skype;
1076
		$this->office_phone	= $contact->phone_pro;
1077
		$this->office_fax	= $contact->fax;
1078
		$this->user_mobile	= $contact->phone_mobile;
1079
		$this->address      = $contact->address;
1080
		$this->zip          = $contact->zip;
1081
		$this->town         = $contact->town;
1082
		$this->state_id     = $contact->state_id;
1083
		$this->country_id   = $contact->country_id;
1084
        $this->employee     = 0;
1085
        
1086
		if (empty($login)) $login=strtolower(substr($contact->firstname, 0, 4)) . strtolower(substr($contact->lastname, 0, 4));
1087
		$this->login = $login;
1088
1089
		$this->db->begin();
1090
1091
		// Cree et positionne $this->id
1092
		$result=$this->create($user);
1093
		if ($result > 0)
1094
		{
1095
			$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1096
			$sql.= " SET fk_socpeople=".$contact->id;
1097
			if ($contact->socid) $sql.=", fk_soc=".$contact->socid;
1098
			$sql.= " WHERE rowid=".$this->id;
1099
			$resql=$this->db->query($sql);
1100
1101
			dol_syslog(get_class($this)."::create_from_contact", LOG_DEBUG);
1102
			if ($resql)
1103
			{
1104
				$this->context['createfromcontact']='createfromcontact';
1105
1106
                // Call trigger
1107
                $result=$this->call_trigger('USER_CREATE',$user);
1108
                if ($result < 0) { $error++; $this->db->rollback(); return -1; }
1109
                // End call triggers
1110
1111
				$this->db->commit();
1112
				return $this->id;
1113
			}
1114
			else
1115
			{
1116
				$this->error=$this->db->error();
1117
1118
				$this->db->rollback();
1119
				return -1;
1120
			}
1121
		}
1122
		else
1123
		{
1124
			// $this->error deja positionne
1125
			dol_syslog(get_class($this)."::create_from_contact - 0");
1126
1127
			$this->db->rollback();
1128
			return $result;
1129
		}
1130
1131
	}
1132
1133
	/**
1134
	 *  Create a user into database from a member object
1135
	 *
1136
	 *  @param	Adherent	$member		Object member source
1137
	 * 	@param	string		$login		Login to force
1138
	 *  @return int						<0 if KO, if OK, return id of created account
1139
	 */
1140
	function create_from_member($member,$login='')
1141
	{
1142
		global $conf,$user,$langs;
1143
1144
		// Positionne parametres
1145
		$this->admin = 0;
1146
		$this->lastname     = $member->lastname;
1147
		$this->firstname    = $member->firstname;
1148
		$this->gender		= $member->gender;
1149
		$this->email        = $member->email;
1150
		$this->fk_member    = $member->id;
1151
		$this->pass         = $member->pass;
1152
		$this->address      = $member->address;
1153
		$this->zip          = $member->zip;
1154
		$this->town         = $member->town;
1155
		$this->state_id     = $member->state_id;
1156
		$this->country_id   = $member->country_id;
1157
1158
		if (empty($login)) $login=strtolower(substr($member->firstname, 0, 4)) . strtolower(substr($member->lastname, 0, 4));
1159
		$this->login = $login;
1160
1161
		$this->db->begin();
1162
1163
		// Create and set $this->id
1164
		$result=$this->create($user);
1165
		if ($result > 0)
1166
		{
1167
			$newpass=$this->setPassword($user,$this->pass);
1168
			if (is_numeric($newpass) && $newpass < 0) $result=-2;
1169
1170
			if ($result > 0 && $member->fk_soc)	// If member is linked to a thirdparty
1171
			{
1172
				$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1173
				$sql.= " SET fk_soc=".$member->fk_soc;
1174
				$sql.= " WHERE rowid=".$this->id;
1175
1176
				dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG);
1177
				$resql=$this->db->query($sql);
1178
				if ($resql)
1179
				{
1180
					$this->db->commit();
1181
					return $this->id;
1182
				}
1183
				else
1184
				{
1185
					$this->error=$this->db->lasterror();
1186
1187
					$this->db->rollback();
1188
					return -1;
1189
				}
1190
			}
1191
		}
1192
1193
		if ($result > 0)
1194
		{
1195
			$this->db->commit();
1196
			return $this->id;
1197
		}
1198
		else
1199
		{
1200
			// $this->error deja positionne
1201
			$this->db->rollback();
1202
			return -2;
1203
		}
1204
	}
1205
1206
	/**
1207
	 *    Assign rights by default
1208
	 *
1209
	 *    @return     integer erreur <0, si ok renvoi le nbre de droits par defaut positionnes
1210
	 */
1211
	function set_default_rights()
1212
	{
1213
		global $conf;
1214
1215
		$sql = "SELECT id FROM ".MAIN_DB_PREFIX."rights_def";
1216
		$sql.= " WHERE bydefault = 1";
1217
		$sql.= " AND entity = ".$conf->entity;
1218
1219
		$resql=$this->db->query($sql);
1220
		if ($resql)
1221
		{
1222
			$num = $this->db->num_rows($resql);
1223
			$i = 0;
1224
			$rd = array();
1225
			while ($i < $num)
1226
			{
1227
				$row = $this->db->fetch_row($resql);
1228
				$rd[$i] = $row[0];
1229
				$i++;
1230
			}
1231
			$this->db->free($resql);
1232
		}
1233
		$i = 0;
1234
		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...
1235
		{
1236
1237
			$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...
1238
			$result=$this->db->query($sql);
1239
1240
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_rights (fk_user, fk_id) VALUES ($this->id, $rd[$i])";
1241
			$result=$this->db->query($sql);
1242
			if (! $result) return -1;
1243
			$i++;
1244
		}
1245
1246
		return $i;
1247
	}
1248
1249
	/**
1250
	 *  	Update a user into database (and also password if this->pass is defined)
1251
	 *
1252
	 *		@param	User	$user				User qui fait la mise a jour
1253
	 *    	@param  int		$notrigger			1 ne declenche pas les triggers, 0 sinon
1254
	 *		@param	int		$nosyncmember		0=Synchronize linked member (standard info), 1=Do not synchronize linked member
1255
	 *		@param	int		$nosyncmemberpass	0=Synchronize linked member (password), 1=Do not synchronize linked member
1256
	 *    	@return int 		        		<0 si KO, >=0 si OK
1257
	 */
1258
	function update($user,$notrigger=0,$nosyncmember=0,$nosyncmemberpass=0)
1259
	{
1260
		global $conf, $langs;
1261
1262
		$nbrowsaffected=0;
1263
		$error=0;
1264
1265
		dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncmember=".$nosyncmember.", nosyncmemberpass=".$nosyncmemberpass);
1266
1267
		// Clean parameters
1268
		$this->lastname     = trim($this->lastname);
1269
		$this->firstname    = trim($this->firstname);
1270
		$this->employee    	= $this->employee?$this->employee:0;
1271
		$this->login        = trim($this->login);
1272
		$this->gender       = trim($this->gender);
1273
		$this->pass         = trim($this->pass);
1274
        $this->api_key      = trim($this->api_key);
1275
		$this->address		= $this->address?trim($this->address):trim($this->address);
1276
        $this->zip			= $this->zip?trim($this->zip):trim($this->zip);
1277
        $this->town			= $this->town?trim($this->town):trim($this->town);
1278
        $this->state_id		= trim($this->state_id);
1279
        $this->country_id	= ($this->country_id > 0)?$this->country_id:0;
1280
		$this->office_phone = trim($this->office_phone);
1281
		$this->office_fax   = trim($this->office_fax);
1282
		$this->user_mobile  = trim($this->user_mobile);
1283
		$this->email        = trim($this->email);
1284
		$this->skype        = trim($this->skype);
1285
		$this->job    		= trim($this->job);
1286
		$this->signature    = trim($this->signature);
1287
		$this->note         = trim($this->note);
1288
		$this->openid       = trim(empty($this->openid)?'':$this->openid);    // Avoid warning
1289
		$this->admin        = $this->admin?$this->admin:0;
1290
		$this->address		= empty($this->address)?'':$this->address;
1291
		$this->zip			= empty($this->zip)?'':$this->zip;
1292
		$this->town			= empty($this->town)?'':$this->town;
1293
		$this->accountancy_code = trim($this->accountancy_code);
1294
		$this->color 		= empty($this->color)?'':$this->color;
1295
		$this->dateemployment 	= empty($this->dateemployment)?'':$this->dateemployment;
1296
1297
		// Check parameters
1298
		if (! empty($conf->global->USER_MAIL_REQUIRED) && ! isValidEMail($this->email))
1299
		{
1300
			$langs->load("errors");
1301
			$this->error = $langs->trans("ErrorBadEMail",$this->email);
1302
			return -1;
1303
		}
1304
		if (empty($this->login))
1305
		{
1306
			$langs->load("errors");
1307
			$this->error = $langs->trans("ErrorFieldRequired",$this->login);
1308
			return -1;
1309
		}
1310
1311
		$this->db->begin();
1312
1313
		// Update datas
1314
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
1315
		$sql.= " lastname = '".$this->db->escape($this->lastname)."'";
1316
		$sql.= ", firstname = '".$this->db->escape($this->firstname)."'";
1317
		$sql.= ", employee = ".$this->employee;
1318
		$sql.= ", login = '".$this->db->escape($this->login)."'";
1319
        $sql.= ", api_key = ".($this->api_key ? "'".$this->db->escape($this->api_key)."'" : "null");
1320
		$sql.= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null");	// 'man' or 'woman'
1321
		if (! empty($user->admin)) $sql.= ", admin = ".$this->admin;	// admin flag can be set/unset only by an admin user
1322
		$sql.= ", address = '".$this->db->escape($this->address)."'";
1323
		$sql.= ", zip = '".$this->db->escape($this->zip)."'";
1324
		$sql.= ", town = '".$this->db->escape($this->town)."'";
1325
		$sql.= ", fk_state = ".((! empty($this->state_id) && $this->state_id > 0)?"'".$this->db->escape($this->state_id)."'":"null");
1326
		$sql.= ", fk_country = ".((! empty($this->country_id) && $this->country_id > 0)?"'".$this->db->escape($this->country_id)."'":"null");
1327
		$sql.= ", office_phone = '".$this->db->escape($this->office_phone)."'";
1328
		$sql.= ", office_fax = '".$this->db->escape($this->office_fax)."'";
1329
		$sql.= ", user_mobile = '".$this->db->escape($this->user_mobile)."'";
1330
		$sql.= ", email = '".$this->db->escape($this->email)."'";
1331
		$sql.= ", skype = '".$this->db->escape($this->skype)."'";
1332
		$sql.= ", job = '".$this->db->escape($this->job)."'";
1333
		$sql.= ", signature = '".$this->db->escape($this->signature)."'";
1334
		$sql.= ", accountancy_code = '".$this->db->escape($this->accountancy_code)."'";
1335
		$sql.= ", color = '".$this->db->escape($this->color)."'";
1336
		$sql.= ", dateemployment=".(strval($this->dateemployment)!='' ? "'".$this->db->idate($this->dateemployment)."'" : 'null');
1337
		$sql.= ", note = '".$this->db->escape($this->note)."'";
1338
		$sql.= ", photo = ".($this->photo?"'".$this->db->escape($this->photo)."'":"null");
1339
		$sql.= ", openid = ".($this->openid?"'".$this->db->escape($this->openid)."'":"null");
1340
		$sql.= ", fk_user = ".($this->fk_user > 0?"'".$this->db->escape($this->fk_user)."'":"null");
1341
		if (isset($this->thm) || $this->thm != '')                 $sql.= ", thm= ".($this->thm != ''?"'".$this->db->escape($this->thm)."'":"null");
1342
		if (isset($this->tjm) || $this->tjm != '')                 $sql.= ", tjm= ".($this->tjm != ''?"'".$this->db->escape($this->tjm)."'":"null");
1343
		if (isset($this->salary) || $this->salary != '')           $sql.= ", salary= ".($this->salary != ''?"'".$this->db->escape($this->salary)."'":"null");
1344
		if (isset($this->salaryextra) || $this->salaryextra != '') $sql.= ", salaryextra= ".($this->salaryextra != ''?"'".$this->db->escape($this->salaryextra)."'":"null");
1345
		$sql.= ", weeklyhours= ".($this->weeklyhours != ''?"'".$this->db->escape($this->weeklyhours)."'":"null");
1346
		$sql.= ", entity = '".$this->db->escape($this->entity)."'";
1347
		$sql.= " WHERE rowid = ".$this->id;
1348
		
1349
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1350
		$resql = $this->db->query($sql);
1351
		if ($resql)
1352
		{
1353
			$nbrowsaffected+=$this->db->affected_rows($resql);
1354
1355
			// Update password
1356
			if (!empty($this->pass))
1357
			{
1358
				if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted)
1359
				{
1360
					// Si mot de passe saisi et different de celui en base
1361
					$result=$this->setPassword($user,$this->pass,0,$notrigger,$nosyncmemberpass);
1362
					if (! $nbrowsaffected) $nbrowsaffected++;
1363
				}
1364
			}
1365
1366
			// If user is linked to a member, remove old link to this member
1367
			if ($this->fk_member > 0)
1368
			{
1369
				dol_syslog(get_class($this)."::update remove link with member. We will recreate it later", LOG_DEBUG);
1370
			    $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL where fk_member = ".$this->fk_member;
1371
				$resql = $this->db->query($sql);
1372
				if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
1373
			}
1374
			// Set link to user
1375
			dol_syslog(get_class($this)."::update set link with member", LOG_DEBUG);
1376
			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member =".($this->fk_member>0?$this->fk_member:'null')." where rowid = ".$this->id;
1377
			$resql = $this->db->query($sql);
1378
			if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
1379
1380
			if ($nbrowsaffected)	// If something has changed in data
1381
			{
1382
				if ($this->fk_member > 0 && ! $nosyncmember)
1383
				{
1384
				    dol_syslog(get_class($this)."::update user is linked with a member. We try to update member too.", LOG_DEBUG);
1385
				    
1386
					require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1387
1388
					// This user is linked with a member, so we also update members informations
1389
					// if this is an update.
1390
					$adh=new Adherent($this->db);
1391
					$result=$adh->fetch($this->fk_member);
1392
1393
					if ($result >= 0)
1394
					{
1395
						$adh->firstname=$this->firstname;
1396
						$adh->lastname=$this->lastname;
1397
						$adh->login=$this->login;
1398
						$adh->gender=$this->gender;
1399
						
1400
						$adh->pass=$this->pass;
1401
						
1402
						$adh->societe=(empty($adh->societe) && $this->societe_id ? $this->societe_id : $adh->societe);
1403
1404
						$adh->email=$this->email;
1405
						$adh->skype=$this->skype;
1406
						$adh->phone=$this->office_phone;
1407
						$adh->phone_mobile=$this->user_mobile;
1408
1409
						$adh->note=$this->note;
1410
1411
						$adh->user_id=$this->id;
1412
						$adh->user_login=$this->login;
1413
1414
						$result=$adh->update($user,0,1,0);
1415
                        if ($result < 0)
1416
						{
1417
						    $this->error=$adh->error;
1418
						    $this->errors=$adh->errors;
1419
							dol_syslog(get_class($this)."::update error after calling adh->update to sync it with user: ".$this->error, LOG_ERR);
1420
							$error++;
1421
						}
1422
					}
1423
					else
1424
					{
1425
						$this->error=$adh->error;
1426
						$this->errors=$adh->errors;
1427
						$error++;
1428
					}
1429
				}
1430
			}
1431
1432
			$action='update';
1433
1434
			// Actions on extra fields (by external module or standard code)
1435
			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
1436
			{
1437
				$result=$this->insertExtraFields();
1438
				if ($result < 0)
1439
				{
1440
					$error++;
1441
				}
1442
			}
1443
1444
			if (! $error && ! $notrigger)
1445
			{
1446
                // Call trigger
1447
                $result=$this->call_trigger('USER_MODIFY',$user);
1448
                if ($result < 0) { $error++; }
1449
                // End call triggers
1450
			}
1451
1452
			if (! $error)
1453
			{
1454
				$this->db->commit();
1455
				return $nbrowsaffected;
1456
			}
1457
			else
1458
			{
1459
				dol_syslog(get_class($this)."::update error=".$this->error,LOG_ERR);
1460
				$this->db->rollback();
1461
				return -1;
1462
			}
1463
		}
1464
		else
1465
		{
1466
			$this->error=$this->db->lasterror();
1467
			$this->db->rollback();
1468
			return -2;
1469
		}
1470
1471
	}
1472
1473
	/**
1474
	 *    Mise a jour en base de la date de derniere connexion d'un utilisateur
1475
	 *	  Fonction appelee lors d'une nouvelle connexion
1476
	 *
1477
	 *    @return     <0 si echec, >=0 si ok
1478
	 */
1479
	function update_last_login_date()
1480
	{
1481
		$now=dol_now();
1482
1483
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
1484
		$sql.= " datepreviouslogin = datelastlogin,";
1485
		$sql.= " datelastlogin = '".$this->db->idate($now)."',";
1486
		$sql.= " tms = tms";    // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion
1487
		$sql.= " WHERE rowid = ".$this->id;
1488
1489
		dol_syslog(get_class($this)."::update_last_login_date user->id=".$this->id." ".$sql, LOG_DEBUG);
1490
		$resql = $this->db->query($sql);
1491
		if ($resql)
1492
		{
1493
			$this->datepreviouslogin=$this->datelastlogin;
1494
			$this->datelastlogin=$now;
1495
			return 1;
1496
		}
1497
		else
1498
		{
1499
			$this->error=$this->db->lasterror().' sql='.$sql;
1500
			return -1;
1501
		}
1502
	}
1503
1504
1505
	/**
1506
	 *  Change password of a user
1507
	 *
1508
	 *  @param	User	$user             		Object user of user making change
1509
	 *  @param  string	$password         		New password in clear text (to generate if not provided)
1510
	 *	@param	int		$changelater			1=Change password only after clicking on confirm email
1511
	 *	@param	int		$notrigger				1=Does not launch triggers
1512
	 *	@param	int		$nosyncmember	        Do not synchronize linked member
1513
	 *  @return string 			          		If OK return clear password, 0 if no change, < 0 if error
1514
	 */
1515
	function setPassword($user, $password='', $changelater=0, $notrigger=0, $nosyncmember=0)
1516
	{
1517
		global $conf, $langs;
1518
		require_once DOL_DOCUMENT_ROOT .'/core/lib/security2.lib.php';
1519
1520
		$error=0;
1521
1522
		dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i','*',$password)." changelater=".$changelater." notrigger=".$notrigger." nosyncmember=".$nosyncmember, LOG_DEBUG);
1523
1524
		// If new password not provided, we generate one
1525
		if (! $password)
1526
		{
1527
			$password=getRandomPassword(false);
1528
		}
1529
1530
		// Crypt password
1531
		$password_crypted = dol_hash($password);
1532
1533
		// Mise a jour
1534
		if (! $changelater)
1535
		{
1536
		    if (! is_object($this->oldcopy)) $this->oldcopy = clone $this;
1537
1538
		    $this->db->begin();
1539
1540
		    $sql = "UPDATE ".MAIN_DB_PREFIX."user";
1541
			$sql.= " SET pass_crypted = '".$this->db->escape($password_crypted)."',";
1542
			$sql.= " pass_temp = null";
1543
			if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
1544
			{
1545
				$sql.= ", pass = null";
1546
			}
1547
			else
1548
			{
1549
				$sql.= ", pass = '".$this->db->escape($password)."'";
1550
			}
1551
			$sql.= " WHERE rowid = ".$this->id;
1552
1553
			dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1554
			$result = $this->db->query($sql);
1555
			if ($result)
1556
			{
1557
				if ($this->db->affected_rows($result))
1558
				{
1559
					$this->pass=$password;
1560
					$this->pass_indatabase=$password;
1561
					$this->pass_indatabase_crypted=$password_crypted;
1562
1563
					if ($this->fk_member && ! $nosyncmember)
1564
					{
1565
						require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1566
1567
						// This user is linked with a member, so we also update members informations
1568
						// if this is an update.
1569
						$adh=new Adherent($this->db);
1570
						$result=$adh->fetch($this->fk_member);
1571
1572
						if ($result >= 0)
1573
						{
1574
							$result=$adh->setPassword($user,$this->pass,(empty($conf->global->DATABASE_PWD_ENCRYPTED)?0:1),1);	// Cryptage non gere dans module adherent
1575
							if ($result < 0)
1576
							{
1577
								$this->error=$adh->error;
1578
								dol_syslog(get_class($this)."::setPassword ".$this->error,LOG_ERR);
1579
								$error++;
1580
							}
1581
						}
1582
						else
1583
						{
1584
							$this->error=$adh->error;
1585
							$error++;
1586
						}
1587
					}
1588
1589
					dol_syslog(get_class($this)."::setPassword notrigger=".$notrigger." error=".$error,LOG_DEBUG);
1590
1591
					if (! $error && ! $notrigger)
1592
					{
1593
                        // Call trigger
1594
                        $result=$this->call_trigger('USER_NEW_PASSWORD',$user);
1595
                        if ($result < 0) { $error++; $this->db->rollback(); return -1; }
1596
                        // End call triggers
1597
					}
1598
1599
					$this->db->commit();
1600
					return $this->pass;
1601
				}
1602
				else
1603
				{
1604
				    $this->db->rollback();
1605
					return 0;
1606
				}
1607
			}
1608
			else
1609
			{
1610
			    $this->db->rollback();
1611
				dol_print_error($this->db);
1612
				return -1;
1613
			}
1614
		}
1615
		else
1616
		{
1617
			// We store clear password in password temporary field.
1618
			// After receiving confirmation link, we will crypt it and store it in pass_crypted
1619
			$sql = "UPDATE ".MAIN_DB_PREFIX."user";
1620
			$sql.= " SET pass_temp = '".$this->db->escape($password)."'";
1621
			$sql.= " WHERE rowid = ".$this->id;
1622
1623
			dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);	// No log
1624
			$result = $this->db->query($sql);
1625
			if ($result)
1626
			{
1627
				return $password;
1628
			}
1629
			else
1630
			{
1631
				dol_print_error($this->db);
1632
				return -3;
1633
			}
1634
		}
1635
	}
1636
1637
1638
	/**
1639
	 *  Send new password by email
1640
	 *
1641
	 *  @param	User	$user           Object user that send email
1642
	 *  @param	string	$password       New password
1643
	 *	@param	int		$changelater	1=Change password only after clicking on confirm email
1644
	 *  @return int 		            < 0 si erreur, > 0 si ok
1645
	 */
1646
	function send_password($user, $password='', $changelater=0)
1647
	{
1648
		global $conf,$langs;
1649
		global $dolibarr_main_url_root;
1650
1651
		require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
1652
1653
		$msgishtml=0;
1654
1655
		// Define $msg
1656
		$mesg = '';
1657
1658
		$outputlangs=new Translate("",$conf);
1659
		if (isset($this->conf->MAIN_LANG_DEFAULT)
1660
		&& $this->conf->MAIN_LANG_DEFAULT != 'auto')
1661
		{	// If user has defined its own language (rare because in most cases, auto is used)
1662
			$outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT);
1663
		}
1664
		else
1665
		{	// If user has not defined its own language, we used current language
1666
			$outputlangs=$langs;
1667
		}
1668
1669
		$outputlangs->load("main");
1670
		$outputlangs->load("errors");
1671
		$outputlangs->load("users");
1672
		$outputlangs->load("other");
1673
1674
		$appli=constant('DOL_APPLICATION_TITLE');
1675
		if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE;
1676
		
1677
		$subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli);
1678
1679
		// Define $urlwithroot
1680
		$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
1681
		$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT;		// This is to use external domain name found into config file
1682
1683
		if (! $changelater)
1684
		{
1685
			$url = $urlwithroot.'/';
1686
		    
1687
			$mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived").".\n";
1688
			$mesg.= $outputlangs->transnoentitiesnoconv("NewKeyIs")." :\n\n";
1689
			$mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n";
1690
			$mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n";
1691
			$mesg.= "\n";
1692
			
1693
			$mesg.= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli).': '.$url."\n\n";
1694
			$mesg.= "--\n";
1695
			$mesg.= $user->getFullName($outputlangs);	// Username that make then sending
1696
		
1697
			dol_syslog(get_class($this)."::send_password changelater is off, url=".$url);
1698
		}
1699
		else
1700
		{
1701
			$url = $urlwithroot.'/user/passwordforgotten.php?action=validatenewpassword&username='.$this->login."&passwordhash=".dol_hash($password);
1702
		    
1703
			$mesg.= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived")."\n";
1704
			$mesg.= $outputlangs->transnoentitiesnoconv("NewKeyWillBe")." :\n\n";
1705
			$mesg.= $outputlangs->transnoentitiesnoconv("Login")." = ".$this->login."\n";
1706
			$mesg.= $outputlangs->transnoentitiesnoconv("Password")." = ".$password."\n\n";
1707
			$mesg.= "\n";
1708
			$mesg.= $outputlangs->transnoentitiesnoconv("YouMustClickToChange")." :\n";
1709
			$mesg.= $url."\n\n";
1710
			$mesg.= $outputlangs->transnoentitiesnoconv("ForgetIfNothing")."\n\n";
1711
			
1712
			dol_syslog(get_class($this)."::send_password changelater is on, url=".$url);
1713
		}
1714
1715
        $mailfile = new CMailFile(
1716
            $subject,
1717
            $this->email,
1718
            $conf->notification->email_from,
1719
            $mesg,
1720
            array(),
1721
            array(),
1722
            array(),
1723
            '',
1724
            '',
1725
            0,
1726
            $msgishtml
1727
        );
1728
1729
		if ($mailfile->sendfile())
1730
		{
1731
			return 1;
1732
		}
1733
		else
1734
		{
1735
			$langs->trans("errors");
1736
			$this->error=$langs->trans("ErrorFailedToSendPassword").' '.$mailfile->error;
1737
			return -1;
1738
		}
1739
	}
1740
1741
	/**
1742
	 * 		Renvoie la derniere erreur fonctionnelle de manipulation de l'objet
1743
	 *
1744
	 * 		@return    string      chaine erreur
1745
	 */
1746
	function error()
1747
	{
1748
		return $this->error;
1749
	}
1750
1751
1752
	/**
1753
	 *    	Read clicktodial information for user
1754
	 *
1755
	 * 		@return		<0 if KO, >0 if OK
1756
	 */
1757
	function fetch_clicktodial()
1758
	{
1759
		$sql = "SELECT url, login, pass, poste ";
1760
		$sql.= " FROM ".MAIN_DB_PREFIX."user_clicktodial as u";
1761
		$sql.= " WHERE u.fk_user = ".$this->id;
1762
1763
		$resql = $this->db->query($sql);
1764
		if ($resql)
1765
		{
1766
			if ($this->db->num_rows($resql))
1767
			{
1768
				$obj = $this->db->fetch_object($resql);
1769
1770
				$this->clicktodial_url = $obj->url;
1771
				$this->clicktodial_login = $obj->login;
1772
				$this->clicktodial_password = $obj->pass;
1773
				$this->clicktodial_poste = $obj->poste;
1774
			}
1775
1776
			$this->clicktodial_loaded = 1;	// Data loaded (found or not)
1777
1778
			$this->db->free($resql);
1779
			return 1;
1780
		}
1781
		else
1782
		{
1783
			$this->error=$this->db->error();
1784
			return -1;
1785
		}
1786
	}
1787
1788
	/**
1789
	 *  Update clicktodial info
1790
	 *
1791
	 *  @return	integer
1792
	 */
1793
	function update_clicktodial()
1794
	{
1795
		$this->db->begin();
1796
1797
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."user_clicktodial";
1798
		$sql .= " WHERE fk_user = ".$this->id;
1799
1800
		dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
1801
		$result = $this->db->query($sql);
1802
1803
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."user_clicktodial";
1804
		$sql .= " (fk_user,url,login,pass,poste)";
1805
		$sql .= " VALUES (".$this->id;
1806
		$sql .= ", '". $this->db->escape($this->clicktodial_url) ."'";
1807
		$sql .= ", '". $this->db->escape($this->clicktodial_login) ."'";
1808
		$sql .= ", '". $this->db->escape($this->clicktodial_password) ."'";
1809
		$sql .= ", '". $this->db->escape($this->clicktodial_poste) ."')";
1810
1811
		dol_syslog(get_class($this).'::update_clicktodial', LOG_DEBUG);
1812
		$result = $this->db->query($sql);
1813
		if ($result)
1814
		{
1815
			$this->db->commit();
1816
			return 1;
1817
		}
1818
		else
1819
		{
1820
			$this->db->rollback();
1821
			$this->error=$this->db->lasterror();
1822
			return -1;
1823
		}
1824
	}
1825
1826
1827
	/**
1828
	 *  Add user into a group
1829
	 *
1830
	 *  @param	int	$group      Id of group
1831
	 *  @param  int		$entity     Entity
1832
	 *  @param  int		$notrigger  Disable triggers
1833
	 *  @return int  				<0 if KO, >0 if OK
1834
	 */
1835
	function SetInGroup($group, $entity, $notrigger=0)
1836
	{
1837
		global $conf, $langs, $user;
1838
1839
		$error=0;
1840
1841
		$this->db->begin();
1842
1843
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user";
1844
		$sql.= " WHERE fk_user  = ".$this->id;
1845
		$sql.= " AND fk_usergroup = ".$group;
1846
		$sql.= " AND entity = ".$entity;
1847
1848
		$result = $this->db->query($sql);
1849
1850
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."usergroup_user (entity, fk_user, fk_usergroup)";
1851
		$sql.= " VALUES (".$entity.",".$this->id.",".$group.")";
1852
1853
		$result = $this->db->query($sql);
1854
		if ($result)
1855
		{
1856
			if (! $error && ! $notrigger)
1857
			{
1858
			    $this->newgroupid=$group;    // deprecated. Remove this.
1859
			    $this->context = array('audit'=>$langs->trans("UserSetInGroup"), 'newgroupid'=>$group);
0 ignored issues
show
Documentation Bug introduced by
It seems like array('audit' => $langs-...'newgroupid' => $group) of type array<string,?,{"audit":...newgroupid":"integer"}> is incompatible with the declared type array<integer,string> of property $context.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1860
			     
1861
			    // Call trigger
1862
                $result=$this->call_trigger('USER_MODIFY',$user);
1863
	            if ($result < 0) { $error++; }
1864
                // End call triggers
1865
			}
1866
1867
			if (! $error)
1868
			{
1869
				$this->db->commit();
1870
				return 1;
1871
			}
1872
			else
1873
			{
1874
				dol_syslog(get_class($this)."::SetInGroup ".$this->error, LOG_ERR);
1875
				$this->db->rollback();
1876
				return -2;
1877
			}
1878
		}
1879
		else
1880
		{
1881
			$this->error=$this->db->lasterror();
1882
			$this->db->rollback();
1883
			return -1;
1884
		}
1885
	}
1886
1887
	/**
1888
	 *  Remove a user from a group
1889
	 *
1890
	 *  @param	int   $group       Id of group
1891
	 *  @param  int		$entity      Entity
1892
	 *  @param  int		$notrigger   Disable triggers
1893
	 *  @return int  			     <0 if KO, >0 if OK
1894
	 */
1895
	function RemoveFromGroup($group, $entity, $notrigger=0)
1896
	{
1897
		global $conf,$langs,$user;
1898
1899
		$error=0;
1900
1901
		$this->db->begin();
1902
1903
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user";
1904
		$sql.= " WHERE fk_user  = ".$this->id;
1905
		$sql.= " AND fk_usergroup = ".$group;
1906
		$sql.= " AND entity = ".$entity;
1907
1908
		$result = $this->db->query($sql);
1909
		if ($result)
1910
		{
1911
			if (! $error && ! $notrigger)
1912
			{
1913
			    $this->oldgroupid=$group;    // deprecated. Remove this.
1914
			    $this->context = array('audit'=>$langs->trans("UserRemovedFromGroup"), 'oldgroupid'=>$group);
0 ignored issues
show
Documentation Bug introduced by
It seems like array('audit' => $langs-...'oldgroupid' => $group) of type array<string,?,{"audit":...oldgroupid":"integer"}> is incompatible with the declared type array<integer,string> of property $context.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1915
			    
1916
			    // Call trigger
1917
                $result=$this->call_trigger('USER_MODIFY',$user);
1918
                if ($result < 0) { $error++; }
1919
                // End call triggers
1920
			}
1921
1922
			if (! $error)
1923
			{
1924
				$this->db->commit();
1925
				return 1;
1926
			}
1927
			else
1928
			{
1929
				$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...
1930
				dol_syslog(get_class($this)."::RemoveFromGroup ".$this->error, LOG_ERR);
1931
				$this->db->rollback();
1932
				return -2;
1933
			}
1934
		}
1935
		else
1936
		{
1937
			$this->error=$this->db->lasterror();
1938
			$this->db->rollback();
1939
			return -1;
1940
		}
1941
	}
1942
1943
1944
	/**
1945
	 *  Return a link with photo
1946
	 * 	Use this->id,this->photo
1947
	 *
1948
	 *	@param	int		$width			Width of image
1949
	 *	@param	int		$height			Height of image
1950
	 *  @param	string	$cssclass		Force a css class
1951
     * 	@param	string	$imagesize		'mini', 'small' or '' (original)
1952
	 *	@return	string					String with URL link
1953
	 */
1954
	function getPhotoUrl($width, $height, $cssclass='', $imagesize='')
1955
	{
1956
		$result='';
1957
1958
		$result.='<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
1959
	    $result.=Form::showphoto('userphoto', $this, $width, $height, 0, $cssclass, $imagesize);
1960
	    $result.='</a>';
1961
1962
	    return $result;
1963
	}
1964
1965
	/**
1966
	 *  Return a link to the user card (with optionaly the picto)
1967
	 * 	Use this->id,this->lastname, this->firstname
1968
	 *
1969
	 *	@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)
1970
	 *	@param	string	$option				On what the link point to
1971
     *  @param  integer $infologin      	Add complete info tooltip
1972
     *  @param	integer	$notooltip			1=Disable tooltip on picto and name
1973
     *  @param	int		$maxlen				Max length of visible user name
1974
     *  @param	int		$hidethirdpartylogo	Hide logo of thirdparty if user is external user
1975
     *  @param  string  $mode               ''=Show firstname and lastname, 'firstname'=Show only firstname, 'login'=Show login
1976
     *  @param  string  $morecss            Add more css on link
1977
	 *	@return	string						String with URL
1978
	 */
1979
	function getNomUrl($withpictoimg=0, $option='', $infologin=0, $notooltip=0, $maxlen=24, $hidethirdpartylogo=0, $mode='',$morecss='')
1980
	{
1981
		global $langs, $conf, $db, $hookmanager;
1982
        	global $dolibarr_main_authentication, $dolibarr_main_demo;
1983
        	global $menumanager;
1984
1985
		if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) $withpictoimg=0;
1986
1987
	        $result = '';
1988
	        $companylink = '';
1989
	        $link = '';
1990
	
1991
	        $label = '<u>' . $langs->trans("User") . '</u>';
1992
	        $label.= '<div width="100%">';
1993
	        $label.= '<b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs,'','');
1994
	        if (! empty($this->login))
1995
	        $label.= '<br><b>' . $langs->trans('Login') . ':</b> ' . $this->login;
1996
	        $label.= '<br><b>' . $langs->trans("EMail").':</b> '.$this->email;
1997
	        if (! empty($this->admin))
1998
	        $label.= '<br><b>' . $langs->trans("Administrator").'</b>: '.yn($this->admin);
1999
	        if (! empty($this->societe_id) )	// Add thirdparty for external users
2000
	        {
2001
	            $thirdpartystatic = new Societe($db);
2002
	            $thirdpartystatic->fetch($this->societe_id);
2003
	            if (empty($hidethirdpartylogo)) $companylink = ' '.$thirdpartystatic->getNomUrl(2);	// picto only of company
2004
	            $company=' ('.$langs->trans("Company").': '.$thirdpartystatic->name.')';
2005
	        }
2006
	        $type=($this->societe_id?$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...
2007
	        $label.= '<br><b>' . $langs->trans("Type") . ':</b> ' . $type;
2008
	        $label.='</div>';
2009
	        if (! empty($this->photo))
2010
	        {
2011
	        	$label.= '<div class="photointooltip">';
2012
			$label.= Form::showphoto('userphoto', $this, 80, 0, 0, 'photowithmargin photologintooltip', 'small', 0, 1);
2013
	        	$label.= '</div><div style="clear: both;"></div>';
2014
	        }
2015
2016
	        // Info Login
2017
	        if ($infologin)
2018
	        {
2019
	            $label.= '<br>';
2020
	            $label.= '<br><u>'.$langs->trans("Connection").'</u>';
2021
	            $label.= '<br><b>'.$langs->trans("IPAddress").'</b>: '.$_SERVER["REMOTE_ADDR"];
2022
	            if (! empty($conf->global->MAIN_MODULE_MULTICOMPANY)) $label.= '<br><b>'.$langs->trans("ConnectedOnMultiCompany").':</b> '.$conf->entity.' (user entity '.$this->entity.')';
2023
	            $label.= '<br><b>'.$langs->trans("AuthenticationMode").':</b> '.$_SESSION["dol_authmode"].(empty($dolibarr_main_demo)?'':' (demo)');
2024
	            $label.= '<br><b>'.$langs->trans("ConnectedSince").':</b> '.dol_print_date($this->datelastlogin,"dayhour",'tzuser');
2025
	            $label.= '<br><b>'.$langs->trans("PreviousConnexion").':</b> '.dol_print_date($this->datepreviouslogin,"dayhour",'tzuser');
2026
	            $label.= '<br><b>'.$langs->trans("CurrentTheme").':</b> '.$conf->theme;
2027
	            $label.= '<br><b>'.$langs->trans("CurrentMenuManager").':</b> '.$menumanager->name;
2028
	            $s=picto_from_langcode($langs->getDefaultLang());
2029
	            $label.= '<br><b>'.$langs->trans("CurrentUserLanguage").':</b> '.($s?$s.' ':'').$langs->getDefaultLang();
2030
	            $label.= '<br><b>'.$langs->trans("Browser").':</b> '.$conf->browser->name.($conf->browser->version?' '.$conf->browser->version:'').' ('.$_SERVER['HTTP_USER_AGENT'].')';
2031
	            $label.= '<br><b>'.$langs->trans("Layout").':</b> '.$conf->browser->layout;
2032
	            $label.= '<br><b>'.$langs->trans("Screen").':</b> '.$_SESSION['dol_screenwidth'].' x '.$_SESSION['dol_screenheight'];
2033
	            if (! empty($conf->browser->phone)) $label.= '<br><b>'.$langs->trans("Phone").':</b> '.$conf->browser->phone;
2034
	            if (! empty($_SESSION["disablemodules"])) $label.= '<br><b>'.$langs->trans("DisabledModules").':</b> <br>'.join(', ',explode(',',$_SESSION["disablemodules"]));
2035
	        }
2036
2037
        
2038
	        if ($option == 'leave') $link.= '<a href="'.DOL_URL_ROOT.'/holiday/list.php?id='.$this->id.'"';
2039
	        else $link.= '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'"';
2040
	        
2041
	        $linkclose="";
2042
	        if (empty($notooltip))
2043
	        {
2044
	            if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2045
	            {
2046
	                $langs->load("users");
2047
	                $label=$langs->trans("ShowUser");
2048
	                $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
2049
	            }
2050
	            $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
2051
	            $linkclose.= ' class="classfortooltip'.($morecss?' '.$morecss:'').'"';
2052
	        }
2053
		if (! is_object($hookmanager))
2054
		{
2055
			include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
2056
			$hookmanager=new HookManager($this->db);
2057
		}
2058
		$hookmanager->initHooks(array('userdao'));
2059
		$parameters=array('id'=>$this->id);
2060
		$reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
0 ignored issues
show
Bug introduced by
The variable $action 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...
2061
		if ($reshook > 0) $linkclose = $hookmanager->resPrint;
2062
2063
        $link.=$linkclose.'>';
2064
		$linkend='</a>';
2065
2066
        //if ($withpictoimg == -1) $result.='<div class="nowrap">';
2067
		$result.=$link;
2068
	    if ($withpictoimg)
2069
	    {
2070
	      	$paddafterimage='';
2071
			if (abs($withpictoimg) == 1) $paddafterimage='style="margin-right: 3px;"';
2072
        		if ($withpictoimg > 0) $picto='<div class="inline-block nopadding valignmiddle'.($morecss?' userimg'.$morecss:'').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).'</div>';
2073
        		else $picto='<div class="inline-block nopadding valignmiddle'.($morecss?' userimg'.$morecss:'').'"'.($paddafterimage?' '.$paddafterimage:'').'>'.Form::showphoto('userphoto', $this, 0, 0, 0, 'loginphoto', 'mini', 0, 1).'</div>';
2074
            		$result.=$picto;
2075
		}
2076
		if (abs($withpictoimg) != 2)
2077
		{
2078
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='<div class="inline-block nopadding valignmiddle'.((! isset($this->statut) || $this->statut)?'':' strikefordisabled').($morecss?' usertext'.$morecss:'').'">';
2079
			if ($mode == 'login') $result.=dol_trunc($this->login, $maxlen);
2080
			else $result.=$this->getFullName($langs,'',($mode == 'firstname' ? 2 : -1),$maxlen);
2081
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='</div>';
2082
		}
2083
		$result.=$linkend;
2084
		//if ($withpictoimg == -1) $result.='</div>';
2085
		$result.=$companylink;
2086
		return $result;
2087
	}
2088
2089
	/**
2090
	 *  Renvoie login clicable (avec eventuellement le picto)
2091
	 *
2092
	 *	@param	int		$withpicto		Include picto into link
2093
	 *	@param	string	$option			Sur quoi pointe le lien
2094
	 *	@return	string					Chaine avec URL
2095
	 */
2096
	function getLoginUrl($withpicto=0,$option='')
2097
	{
2098
		global $langs;
2099
2100
		$result='';
2101
2102
		$link = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2103
		$linkend='</a>';
2104
2105
		if ($option == 'xxx')
2106
		{
2107
			$link = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2108
			$linkend='</a>';
2109
		}
2110
2111
		if ($withpicto) $result.=($link.img_object($langs->trans("ShowUser"),'user').$linkend.' ');
2112
		$result.=$link.$this->login.$linkend;
2113
		return $result;
2114
	}
2115
2116
	/**
2117
	 *  Retourne le libelle du statut d'un user (actif, inactif)
2118
	 *
2119
	 *  @param	int		$mode          0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2120
	 *  @return	string 			       Label of status
2121
	 */
2122
	function getLibStatut($mode=0)
2123
	{
2124
		return $this->LibStatut($this->statut,$mode);
2125
	}
2126
2127
	/**
2128
	 *  Renvoi le libelle d'un statut donne
2129
	 *
2130
	 *  @param	int		$statut        	Id statut
2131
	 *  @param  int		$mode          	0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2132
	 *  @return string 			       	Label of status
2133
	 */
2134
	function LibStatut($statut,$mode=0)
2135
	{
2136
		global $langs;
2137
		$langs->load('users');
2138
2139
		if ($mode == 0)
2140
		{
2141
			$prefix='';
2142
			if ($statut == 1) return $langs->trans('Enabled');
2143
			if ($statut == 0) return $langs->trans('Disabled');
2144
		}
2145
		if ($mode == 1)
2146
		{
2147
			if ($statut == 1) return $langs->trans('Enabled');
2148
			if ($statut == 0) return $langs->trans('Disabled');
2149
		}
2150
		if ($mode == 2)
2151
		{
2152
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"').' '.$langs->trans('Enabled');
2153
			if ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"').' '.$langs->trans('Disabled');
2154
		}
2155
		if ($mode == 3)
2156
		{
2157
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"');
2158
			if ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"');
2159
		}
2160
		if ($mode == 4)
2161
		{
2162
			if ($statut == 1) return img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"').' '.$langs->trans('Enabled');
2163
			if ($statut == 0) return img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"').' '.$langs->trans('Disabled');
2164
		}
2165
		if ($mode == 5)
2166
		{
2167
			if ($statut == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4','class="pictostatus"');
2168
			if ($statut == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5','class="pictostatus"');
2169
		}
2170
	}
2171
2172
2173
	/**
2174
	 *	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2175
	 *
2176
	 *	@param	array	$info		Info array loaded by _load_ldap_info
2177
	 *	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2178
	 *								1=
2179
	 *								2=Return key only (uid=qqq)
2180
	 *	@return	string				DN
2181
	 */
2182
	function _load_ldap_dn($info,$mode=0)
2183
	{
2184
		global $conf;
2185
		$dn='';
2186
		if ($mode==0) $dn=$conf->global->LDAP_KEY_USERS."=".$info[$conf->global->LDAP_KEY_USERS].",".$conf->global->LDAP_USER_DN;
2187
		if ($mode==1) $dn=$conf->global->LDAP_USER_DN;
2188
		if ($mode==2) $dn=$conf->global->LDAP_KEY_USERS."=".$info[$conf->global->LDAP_KEY_USERS];
2189
		return $dn;
2190
	}
2191
2192
	/**
2193
	 *	Initialize the info array (array of LDAP values) that will be used to call LDAP functions
2194
	 *
2195
	 *	@return		array		Tableau info des attributs
2196
	 */
2197
	function _load_ldap_info()
2198
	{
2199
		global $conf,$langs;
2200
2201
		$info=array();
2202
2203
		// Object classes
2204
		$info["objectclass"]=explode(',',$conf->global->LDAP_USER_OBJECT_CLASS);
2205
2206
		$this->fullname=$this->getFullName($langs);
2207
2208
		// Champs
2209
		if ($this->fullname && ! empty($conf->global->LDAP_FIELD_FULLNAME))   $info[$conf->global->LDAP_FIELD_FULLNAME] = $this->fullname;
2210
		if ($this->lastname && ! empty($conf->global->LDAP_FIELD_NAME))       $info[$conf->global->LDAP_FIELD_NAME] = $this->lastname;
2211
		if ($this->firstname && ! empty($conf->global->LDAP_FIELD_FIRSTNAME)) $info[$conf->global->LDAP_FIELD_FIRSTNAME] = $this->firstname;
2212
		if ($this->login && ! empty($conf->global->LDAP_FIELD_LOGIN))         $info[$conf->global->LDAP_FIELD_LOGIN] = $this->login;
2213
		if ($this->login && ! empty($conf->global->LDAP_FIELD_LOGIN_SAMBA))   $info[$conf->global->LDAP_FIELD_LOGIN_SAMBA] = $this->login;
2214
		if ($this->pass && ! empty($conf->global->LDAP_FIELD_PASSWORD))       $info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass;	// this->pass = mot de passe non crypte
2215
		if ($this->ldap_sid && ! empty($conf->global->LDAP_FIELD_SID))        $info[$conf->global->LDAP_FIELD_SID] = $this->ldap_sid;
2216
		if ($this->societe_id > 0)
2217
		{
2218
			$soc = new Societe($this->db);
2219
			$soc->fetch($this->societe_id);
2220
2221
			$info["o"] = $soc->lastname;
2222
			if ($soc->client == 1)      $info["businessCategory"] = "Customers";
2223
			if ($soc->client == 2)      $info["businessCategory"] = "Prospects";
2224
			if ($soc->fournisseur == 1) $info["businessCategory"] = "Suppliers";
2225
		}
2226
		if ($this->address && ! empty($conf->global->LDAP_FIELD_ADDRESS))     $info[$conf->global->LDAP_FIELD_ADDRESS] = $this->address;
2227
		if ($this->zip && ! empty($conf->global->LDAP_FIELD_ZIP))             $info[$conf->global->LDAP_FIELD_ZIP] = $this->zip;
2228
		if ($this->town && ! empty($conf->global->LDAP_FIELD_TOWN))           $info[$conf->global->LDAP_FIELD_TOWN] = $this->town;
2229
		if ($this->office_phone && ! empty($conf->global->LDAP_FIELD_PHONE))  $info[$conf->global->LDAP_FIELD_PHONE] = $this->office_phone;
2230
		if ($this->user_mobile && ! empty($conf->global->LDAP_FIELD_MOBILE))  $info[$conf->global->LDAP_FIELD_MOBILE] = $this->user_mobile;
2231
		if ($this->office_fax && ! empty($conf->global->LDAP_FIELD_FAX))	     $info[$conf->global->LDAP_FIELD_FAX] = $this->office_fax;
2232
		if ($this->note && ! empty($conf->global->LDAP_FIELD_DESCRIPTION))    $info[$conf->global->LDAP_FIELD_DESCRIPTION] = $this->note;
2233
		if ($this->email && ! empty($conf->global->LDAP_FIELD_MAIL))          $info[$conf->global->LDAP_FIELD_MAIL] = $this->email;
2234
    	if ($this->skype && ! empty($conf->global->LDAP_FIELD_SKYPE))          $info[$conf->global->LDAP_FIELD_SKYPE] = $this->skype;
2235
2236
		if ($conf->global->LDAP_SERVER_TYPE == 'egroupware')
2237
		{
2238
			$info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
2239
2240
			$info['uidnumber'] = $this->id;
2241
2242
			$info['phpgwTz']      = 0;
2243
			$info['phpgwMailType'] = 'INTERNET';
2244
			$info['phpgwMailHomeType'] = 'INTERNET';
2245
2246
			$info["phpgwContactTypeId"] = 'n';
2247
			$info["phpgwContactCatId"] = 0;
2248
			$info["phpgwContactAccess"] = "public";
2249
2250
			if (dol_strlen($this->egroupware_id) == 0)
2251
			{
2252
				$this->egroupware_id = 1;
2253
			}
2254
2255
			$info["phpgwContactOwner"] = $this->egroupware_id;
2256
2257
			if ($this->email) $info["rfc822Mailbox"] = $this->email;
2258
			if ($this->phone_mobile) $info["phpgwCellTelephoneNumber"] = $this->phone_mobile;
2259
		}
2260
2261
		return $info;
2262
	}
2263
2264
2265
	/**
2266
	 *  Initialise an instance with random values.
2267
	 *  Used to build previews or test instances.
2268
	 *	id must be 0 if object instance is a specimen.
2269
	 *
2270
	 *  @return	void
2271
	 */
2272
	function initAsSpecimen()
2273
	{
2274
		global $user,$langs;
2275
2276
		$now=dol_now();
2277
2278
		// Initialise parametres
2279
		$this->id=0;
2280
		$this->ref = 'SPECIMEN';
2281
		$this->specimen=1;
2282
2283
		$this->lastname='DOLIBARR';
2284
		$this->firstname='SPECIMEN';
2285
		$this->gender='man';
2286
		$this->note='This is a note';
2287
		$this->email='[email protected]';
2288
    	$this->skype='tom.hanson';
2289
		$this->office_phone='0999999999';
2290
		$this->office_fax='0999999998';
2291
		$this->user_mobile='0999999997';
2292
		$this->admin=0;
2293
		$this->login='dolibspec';
2294
		$this->pass='dolibspec';
2295
		//$this->pass_indatabase='dolibspec';									Set after a fetch
2296
		//$this->pass_indatabase_crypted='e80ca5a88c892b0aaaf7e154853bccab';	Set after a fetch
2297
		$this->datec=$now;
2298
		$this->datem=$now;
2299
2300
		$this->datelastlogin=$now;
2301
		$this->datepreviouslogin=$now;
2302
		$this->statut=1;
2303
2304
		//$this->societe_id = 1;	For external users
2305
		//$this->contact_id = 1;	For external users
2306
		$this->entity = 1;
2307
	}
2308
2309
	/**
2310
	 *  Load info of user object
2311
	 *
2312
	 *  @param  int		$id     Id of user to load
2313
	 *  @return	void
2314
	 */
2315
	function info($id)
2316
	{
2317
		$sql = "SELECT u.rowid, u.login as ref, u.datec,";
2318
		$sql.= " u.tms as date_modification, u.entity";
2319
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
2320
		$sql.= " WHERE u.rowid = ".$id;
2321
2322
		$result=$this->db->query($sql);
2323
		if ($result)
2324
		{
2325
			if ($this->db->num_rows($result))
2326
			{
2327
				$obj = $this->db->fetch_object($result);
2328
2329
				$this->id = $obj->rowid;
2330
2331
				$this->ref			     = (! $obj->ref) ? $obj->rowid : $obj->ref;
2332
				$this->date_creation     = $this->db->jdate($obj->datec);
2333
				$this->date_modification = $this->db->jdate($obj->date_modification);
2334
				$this->entity            = $obj->entity;
2335
			}
2336
2337
			$this->db->free($result);
2338
2339
		}
2340
		else
2341
		{
2342
			dol_print_error($this->db);
2343
		}
2344
	}
2345
2346
2347
	/**
2348
	 *    Return number of mass Emailing received by this contacts with its email
2349
	 *
2350
	 *    @return       int     Number of EMailings
2351
	 */
2352
	function getNbOfEMailings()
2353
	{
2354
		$sql = "SELECT count(mc.email) as nb";
2355
		$sql.= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2356
		$sql.= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2357
		$sql.= " AND mc.statut=1";      // -1 erreur, 0 non envoye, 1 envoye avec succes
2358
		$resql=$this->db->query($sql);
2359
		if ($resql)
2360
		{
2361
			$obj = $this->db->fetch_object($resql);
2362
			$nb=$obj->nb;
2363
2364
			$this->db->free($resql);
2365
			return $nb;
2366
		}
2367
		else
2368
		{
2369
			$this->error=$this->db->error();
2370
			return -1;
2371
		}
2372
	}
2373
2374
	/**
2375
	 *  Return number of existing users
2376
	 *
2377
	 *  @param	string	$limitTo	Limit to '' or 'active'
2378
	 *  @param	string	$option		'superadmin' = return for entity 0 only
2379
	 *  @param	int		$admin		Filter on admin tag
2380
	 *  @return int  				Number of users
2381
	 */
2382
	function getNbOfUsers($limitTo, $option='', $admin=-1)
2383
	{
2384
		global $conf;
2385
2386
		$sql = "SELECT count(rowid) as nb";
2387
		$sql.= " FROM ".MAIN_DB_PREFIX."user";
2388
		if ($option == 'superadmin')
2389
		{
2390
			$sql.= " WHERE entity = 0";
2391
			if ($admin >= 0) $sql.= " AND admin = ".$admin;
2392
		}
2393
		else
2394
		{
2395
			$sql.=" WHERE entity IN (".getEntity('user',0).")";
2396
			if ($limitTo == 'active') $sql.= " AND statut = 1";
2397
			if ($admin >= 0) $sql.= " AND admin = ".$admin;
2398
		}
2399
2400
		$resql=$this->db->query($sql);
2401
		if ($resql)
2402
		{
2403
			$obj = $this->db->fetch_object($resql);
2404
			$nb=$obj->nb;
2405
2406
			$this->db->free($resql);
2407
			return $nb;
2408
		}
2409
		else
2410
		{
2411
			$this->error=$this->db->lasterror();
2412
			return -1;
2413
		}
2414
	}
2415
2416
	/**
2417
	 *  Update user using data from the LDAP
2418
	 *
2419
	 *  @param	ldapuser	$ldapuser	Ladp User
2420
	 *
2421
	 *  @return int  				<0 if KO, >0 if OK
2422
	 */
2423
	function update_ldap2dolibarr(&$ldapuser)
2424
	{
2425
		// TODO: Voir pourquoi le update met à jour avec toutes les valeurs vide (global $user écrase ?)
2426
		global $user, $conf;
2427
2428
		$this->firstname=$ldapuser->{$conf->global->LDAP_FIELD_FIRSTNAME};
2429
		$this->lastname=$ldapuser->{$conf->global->LDAP_FIELD_NAME};
2430
		$this->login=$ldapuser->{$conf->global->LDAP_FIELD_LOGIN};
2431
		$this->pass=$ldapuser->{$conf->global->LDAP_FIELD_PASSWORD};
2432
		$this->pass_indatabase_crypted=$ldapuser->{$conf->global->LDAP_FIELD_PASSWORD_CRYPTED};
2433
2434
		$this->office_phone=$ldapuser->{$conf->global->LDAP_FIELD_PHONE};
2435
		$this->user_mobile=$ldapuser->{$conf->global->LDAP_FIELD_MOBILE};
2436
		$this->office_fax=$ldapuser->{$conf->global->LDAP_FIELD_FAX};
2437
		$this->email=$ldapuser->{$conf->global->LDAP_FIELD_MAIL};
2438
		$this->skype=$ldapuser->{$conf->global->LDAP_FIELD_SKYPE};
2439
		$this->ldap_sid=$ldapuser->{$conf->global->LDAP_FIELD_SID};
2440
2441
		$this->job=$ldapuser->{$conf->global->LDAP_FIELD_TITLE};
2442
		$this->note=$ldapuser->{$conf->global->LDAP_FIELD_DESCRIPTION};
2443
2444
		$result = $this->update($user);
2445
2446
		dol_syslog(get_class($this)."::update_ldap2dolibarr result=".$result, LOG_DEBUG);
2447
2448
		return $result;
2449
	}
2450
2451
2452
	/**
2453
	 * Return and array with all instanciated first level children users of current user
2454
	 *
2455
	 * @return	void
2456
	 * @see getAllChildIds 
2457
	 */
2458
	function get_children()
2459
	{
2460
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."user";
2461
		$sql.= " WHERE fk_user = ".$this->id;
2462
2463
		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...
2464
		$res  = $this->db->query($sql);
2465
		if ($res)
2466
		{
2467
			$users = array ();
2468
			while ($rec = $this->db->fetch_array($res))
2469
			{
2470
				$user = new User($this->db);
2471
				$user->fetch($rec['rowid']);
2472
				$users[] = $user;
2473
			}
2474
			return $users;
2475
		}
2476
		else
2477
		{
2478
			dol_print_error($this->db);
2479
			return -1;
2480
		}
2481
	}
2482
2483
2484
	/**
2485
	 * 	Load this->parentof that is array(id_son=>id_parent, ...)
2486
	 *
2487
	 *	@return		int		<0 if KO, >0 if OK
2488
	 */
2489
	private function load_parentof()
2490
	{
2491
		global $conf;
2492
2493
		$this->parentof=array();
2494
2495
		// Load array[child]=parent
2496
		$sql = "SELECT fk_user as id_parent, rowid as id_son";
2497
		$sql.= " FROM ".MAIN_DB_PREFIX."user";
2498
		$sql.= " WHERE fk_user <> 0";
2499
		$sql.= " AND entity IN (".getEntity('user',1).")";
2500
2501
		dol_syslog(get_class($this)."::load_parentof", LOG_DEBUG);
2502
		$resql = $this->db->query($sql);
2503
		if ($resql)
2504
		{
2505
			while ($obj= $this->db->fetch_object($resql))
2506
			{
2507
				$this->parentof[$obj->id_son]=$obj->id_parent;
2508
			}
2509
			return 1;
2510
		}
2511
		else
2512
		{
2513
			dol_print_error($this->db);
2514
			return -1;
2515
		}
2516
	}
2517
2518
	/**
2519
	 * 	Reconstruit l'arborescence hierarchique des users sous la forme d'un tableau
2520
	 *	Set and return this->users that is an array sorted according to tree with arrays of:
2521
	 *				id = id user
2522
	 *				lastname
2523
	 *				firstname
2524
	 *				fullname = nom avec chemin complet du user
2525
	 *				fullpath = chemin complet compose des id: "_grandparentid_parentid_id"
2526
	 *
2527
	 *  @param      int		$deleteafterid      Removed all users including the leaf $deleteafterid (and all its child) in user tree.
2528
	 *  @param		string	$filter				SQL filter on users
2529
	 *	@return		array		      		  	Array of users $this->users. Note: $this->parentof is also set.
2530
	 */
2531
	function get_full_tree($deleteafterid=0, $filter='')
2532
	{
2533
		global $conf,$user;
2534
2535
		$this->users = array();
2536
2537
		// Init this->parentof that is array(id_son=>id_parent, ...)
2538
		$this->load_parentof();
2539
2540
		// Init $this->users array
2541
		$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
2542
		$sql.= " FROM ".MAIN_DB_PREFIX."user as u";
2543
		if(! empty($conf->multicompany->enabled) && $conf->entity == 1 && (! empty($conf->multicompany->transverse_mode) || (! empty($user->admin) && empty($user->entity))))
2544
		{
2545
			$sql.= " WHERE u.entity IS NOT NULL";
2546
		}
2547
		else
2548
		{
2549
			$sql.= " WHERE u.entity IN (".getEntity('user',1).")";
2550
		}
2551
		if ($filter) $sql.=" AND ".$filter;
2552
2553
		dol_syslog(get_class($this)."::get_full_tree get user list", LOG_DEBUG);
2554
		$resql = $this->db->query($sql);
2555
		if ($resql)
2556
		{
2557
			$i=0;
2558
			while ($obj = $this->db->fetch_object($resql))
2559
			{
2560
				$this->users[$obj->rowid]['rowid'] = $obj->rowid;
2561
				$this->users[$obj->rowid]['id'] = $obj->rowid;
2562
				$this->users[$obj->rowid]['fk_user'] = $obj->fk_user;
2563
				$this->users[$obj->rowid]['fk_soc'] = $obj->fk_soc;
2564
				$this->users[$obj->rowid]['firstname'] = $obj->firstname;
2565
				$this->users[$obj->rowid]['lastname'] = $obj->lastname;
2566
				$this->users[$obj->rowid]['login'] = $obj->login;
2567
				$this->users[$obj->rowid]['statut'] = $obj->statut;
2568
				$this->users[$obj->rowid]['entity'] = $obj->entity;
2569
				$this->users[$obj->rowid]['email'] = $obj->email;
2570
				$this->users[$obj->rowid]['gender'] = $obj->gender;
2571
				$this->users[$obj->rowid]['admin'] = $obj->admin;
2572
				$this->users[$obj->rowid]['photo'] = $obj->photo;
2573
				$i++;
2574
			}
2575
		}
2576
		else
2577
		{
2578
			dol_print_error($this->db);
2579
			return -1;
2580
		}
2581
2582
		// We add the fullpath property to each elements of first level (no parent exists)
2583
		dol_syslog(get_class($this)."::get_full_tree call to build_path_from_id_user", LOG_DEBUG);
2584
		foreach($this->users as $key => $val)
2585
		{
2586
			$result = $this->build_path_from_id_user($key,0);	// Process a branch from the root user key (this user has no parent)
2587
			if ($result < 0) 
2588
			{
2589
			    $this->error='ErrorLoopInHierarchy';
2590
			    return -1;
2591
			}
2592
		}
2593
2594
		// Exclude leaf including $deleteafterid from tree
2595
		if ($deleteafterid)
2596
		{
2597
			//print "Look to discard user ".$deleteafterid."\n";
2598
			$keyfilter1='^'.$deleteafterid.'$';
2599
			$keyfilter2='_'.$deleteafterid.'$';
2600
			$keyfilter3='^'.$deleteafterid.'_';
2601
			$keyfilter4='_'.$deleteafterid.'_';
2602
			foreach($this->users as $key => $val)
2603
			{
2604
				if (preg_match('/'.$keyfilter1.'/',$val['fullpath']) || preg_match('/'.$keyfilter2.'/',$val['fullpath'])
2605
					|| preg_match('/'.$keyfilter3.'/',$val['fullpath']) || preg_match('/'.$keyfilter4.'/',$val['fullpath']))
2606
				{
2607
					unset($this->users[$key]);
2608
				}
2609
			}
2610
		}
2611
2612
		dol_syslog(get_class($this)."::get_full_tree dol_sort_array", LOG_DEBUG);
2613
		$this->users=dol_sort_array($this->users, 'fullname', 'asc', true, false);
2614
2615
		//var_dump($this->users);
2616
2617
		return $this->users;
2618
	}
2619
2620
	/**
2621
	 * 	Return list of all child users id in herarchy (all sublevels).
2622
	 *  Note: Calling this function also reset full list of users into $this->users.
2623
	 *
2624
	 *  @param      int      $addcurrentuser    1=Add also current user id to the list.
2625
	 *	@return		array		      		  	Array of user id lower than user (all levels under user). This overwrite this->users.
2626
	 *  @see get_children
2627
	 */
2628
	function getAllChildIds($addcurrentuser=0)
2629
	{
2630
    	$childids=array();
2631
	    
2632
	    if (isset($this->cache_childids[$this->id]))
2633
	    {
2634
	        $childids = $this->cache_childids[$this->id];
2635
	    }
2636
	    else
2637
	    {
2638
    		// Init this->users
2639
    		$this->get_full_tree();
2640
    
2641
    		$idtoscan=$this->id;
2642
    
2643
    		dol_syslog("Build childid for id = ".$idtoscan);
2644
    		foreach($this->users as $id => $val)
2645
    		{
2646
    			//var_dump($val['fullpath']);
2647
    			if (preg_match('/_'.$idtoscan.'_/', $val['fullpath'])) $childids[$val['id']]=$val['id'];
2648
    		}
2649
	    }    
2650
		$this->cache_childids[$this->id] = $childids;
2651
		
2652
		if ($addcurrentuser) $childids[$this->id]=$this->id;
2653
		
2654
		return $childids;
2655
	}
2656
2657
	/**
2658
	 *	For user id_user and its childs available in this->users, define property fullpath and fullname.
2659
	 *  Function called by get_full_tree().
2660
	 *
2661
	 * 	@param		int		$id_user		id_user entry to update
2662
	 * 	@param		int		$protection		Deep counter to avoid infinite loop (no more required, a protection is added with array useridfound)
2663
	 *	@return		int                     < 0 if KO (infinit loop), >= 0 if OK
2664
	 */
2665
	function build_path_from_id_user($id_user,$protection=0)
2666
	{
2667
		dol_syslog(get_class($this)."::build_path_from_id_user id_user=".$id_user." protection=".$protection, LOG_DEBUG);
2668
2669
		if (! empty($this->users[$id_user]['fullpath']))
2670
		{
2671
			// Already defined
2672
			dol_syslog(get_class($this)."::build_path_from_id_user fullpath and fullname already defined", LOG_WARNING);
2673
			return 0;
2674
		}
2675
2676
		// Define fullpath and fullname
2677
		$this->users[$id_user]['fullpath'] = '_'.$id_user;
2678
		$this->users[$id_user]['fullname'] = $this->users[$id_user]['lastname'];
2679
		$i=0; $cursor_user=$id_user;
2680
2681
		$useridfound=array($id_user);
2682
		while (! empty($this->parentof[$cursor_user]))
2683
		{
2684
			if (in_array($this->parentof[$cursor_user], $useridfound)) 
2685
			{
2686
				dol_syslog("The hierarchy of user has a recursive loop", LOG_WARNING);
2687
				return -1;     // Should not happen. Protection against looping hierarchy
2688
			}
2689
			$useridfound[]=$this->parentof[$cursor_user];
2690
		    $this->users[$id_user]['fullpath'] = '_'.$this->parentof[$cursor_user].$this->users[$id_user]['fullpath'];
2691
			$this->users[$id_user]['fullname'] = $this->users[$this->parentof[$cursor_user]]['lastname'].' >> '.$this->users[$id_user]['fullname'];
2692
			$i++; $cursor_user=$this->parentof[$cursor_user];
2693
		}
2694
2695
		// We count number of _ to have level
2696
		$this->users[$id_user]['level']=dol_strlen(preg_replace('/[^_]/i','',$this->users[$id_user]['fullpath']));
2697
2698
		return 1;
2699
	}
2700
2701
	/**
2702
	 * Function used to replace a thirdparty id with another one.
2703
	 *
2704
	 * @param DoliDB $db Database handler
2705
	 * @param int $origin_id Old thirdparty id
2706
	 * @param int $dest_id New thirdparty id
2707
	 * @return bool
2708
	 */
2709
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2710
	{
2711
		$tables = array(
2712
			'user'
2713
		);
2714
2715
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2716
	}
2717
2718
2719
	/**
2720
     *      Charge indicateurs this->nb pour le tableau de bord
2721
     *
2722
     *      @return     int         <0 if KO, >0 if OK
2723
     */
2724
    function load_state_board()
2725
    {
2726
        global $conf;
2727
2728
        $this->nb=array();
2729
2730
        $sql = "SELECT count(u.rowid) as nb";
2731
        $sql.= " FROM ".MAIN_DB_PREFIX."user as u";
2732
        $sql.= " WHERE u.statut > 0";
2733
        //$sql.= " AND employee != 0";
2734
        $sql.= " AND u.entity IN (".getEntity('user', 1).")";
2735
2736
        $resql=$this->db->query($sql);
2737
        if ($resql)
2738
        {
2739
            while ($obj=$this->db->fetch_object($resql))
2740
            {
2741
                $this->nb["users"]=$obj->nb;
2742
            }
2743
            $this->db->free($resql);
2744
            return 1;
2745
        }
2746
        else
2747
        {
2748
            dol_print_error($this->db);
2749
            $this->error=$this->db->error();
2750
            return -1;
2751
        }
2752
    }
2753
2754
}
2755
2756