Passed
Push — master ( 1a792f...fc4753 )
by Alxarafe
28:08
created

User::getNomUrl()   F

Complexity

Conditions 50
Paths > 20000

Size

Total Lines 150
Code Lines 106

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 50
eloc 106
nc 54212608
nop 9
dl 0
loc 150
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (c) 2002-2007 Rodolphe Quiedeville <[email protected]>
3
 * Copyright (c) 2002-2003 Jean-Louis Bergamo   <[email protected]>
4
 * Copyright (c) 2004-2012 Laurent Destailleur  <[email protected]>
5
 * Copyright (C) 2004      Sebastien Di Cintio  <[email protected]>
6
 * Copyright (C) 2004      Benoit Mortier       <[email protected]>
7
 * Copyright (C) 2005-2017 Regis Houssin        <[email protected]>
8
 * Copyright (C) 2005      Lionel Cousteix      <[email protected]>
9
 * Copyright (C) 2011      Herve Prot           <[email protected]>
10
 * Copyright (C) 2013-2018 Philippe Grand       <[email protected]>
11
 * Copyright (C) 2013-2015 Alexandre Spangaro   <[email protected]>
12
 * Copyright (C) 2015      Marcos García        <[email protected]>
13
 * Copyright (C) 2018      charlene Benke       <[email protected]>
14
 * Copyright (C) 2018      Nicolas ZABOURI      <[email protected]>
15
 * Copyright (C) 2019       Alxarafe            <[email protected]>
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 3 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29
 */
30
defined('BASE_PATH') or die('Single entry point through the index.php of the main folder');
31
32
/**
33
 *  \file       htdocs/user/class/user.class.php
34
 * 	\brief      File of class to manage users
35
 *  \ingroup	core
36
 */
37
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
38
39
/**
40
 * 	Class to manage Dolibarr users
41
 */
42
class User extends CommonObject
43
{
44
45
    /**
46
     * @var string ID to identify managed object
47
     */
48
    public $element = 'user';
49
50
    /**
51
     * @var string Name of table without prefix where object is stored
52
     */
53
    public $table_element = 'user';
54
55
    /**
56
     * @var int Field with ID of parent key if this field has a parent
57
     */
58
    public $fk_element = 'fk_user';
59
60
    /**
61
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
62
     * @var int
63
     */
64
    public $ismultientitymanaged = 1;
65
    public $id = 0;
66
    public $statut;
67
    public $ldap_sid;
68
    public $search_sid;
69
    public $employee;
70
    public $gender;
71
    public $birth;
72
    public $email;
73
    public $skype;
74
    public $twitter;
75
    public $facebook;
76
    public $job;   // job position
77
    public $signature;
78
79
    /**
80
     * @var string Address
81
     */
82
    public $address;
83
    public $zip;
84
    public $town;
85
    public $state_id;  // The state/department
86
    public $state_code;
87
    public $state;
88
    public $office_phone;
89
    public $office_fax;
90
    public $user_mobile;
91
    public $admin;
92
    public $login;
93
    public $api_key;
94
95
    /**
96
     * @var int Entity
97
     */
98
    public $entity;
99
    //! Clear password in memory
100
    public $pass;
101
    //! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
102
    public $pass_indatabase;
103
    //! Encrypted password in database (always defined)
104
    public $pass_indatabase_crypted;
105
    public $datec;
106
    public $datem;
107
    //! If this is defined, it is an external user
108
    /**
109
     * @deprecated
110
     * @see socid
111
     */
112
    public $societe_id;
113
114
    /**
115
     * @deprecated
116
     * @see contactid
117
     */
118
    public $contact_id;
119
    public $socid;
120
    public $contactid;
121
122
    /**
123
     * @var int ID
124
     */
125
    public $fk_member;
126
127
    /**
128
     * @var int User ID
129
     */
130
    public $fk_user;
131
    public $clicktodial_url;
132
    public $clicktodial_login;
133
    public $clicktodial_password;
134
    public $clicktodial_poste;
135
    public $datelastlogin;
136
    public $datepreviouslogin;
137
    public $photo;
138
    public $lang;
139
    public $rights;                        // Array of permissions user->rights->permx
140
    public $all_permissions_are_loaded;    // All permission are loaded
141
    public $nb_rights;              // Number of rights granted to the user
142
    private $_tab_loaded = array();     // Cache array of already loaded permissions
143
    public $conf;             // To store personal config
144
    public $default_values;         // To store default values for user
145
    public $lastsearch_values_tmp;  // To store current search criterias for user
146
    public $lastsearch_values;      // To store last saved search criterias for user
147
    public $users = array();  // To store all tree of users hierarchy
148
    public $parentof;    // To store an array of all parents for all ids.
149
    private $cache_childids;
150
    public $accountancy_code;   // Accountancy code in prevision of the complete accountancy module
151
    public $thm;     // Average cost of employee - Used for valuation of time spent
152
    public $tjm;     // Average cost of employee
153
    public $salary;     // Monthly salary       - Denormalized value from llx_user_employment
154
    public $salaryextra;    // Monthly salary extra - Denormalized value from llx_user_employment
155
    public $weeklyhours;    // Weekly hours         - Denormalized value from llx_user_employment
156
    public $color;      // Define background color for user in agenda
157
    public $dateemployment;   // Define date of employment by company
158
    public $dateemploymentend;  // Define date of employment end by company
159
    public $default_c_exp_tax_cat;
160
    public $default_range;
161
    public $fields = array(
162
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
163
        'lastname' => array('type' => 'varchar(50)', 'label' => 'Name', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 20, 'searchall' => 1, 'comment' => 'Reference of object'),
164
        'firstname' => array('type' => 'varchar(50)', 'label' => 'Name', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 10, 'searchall' => 1, 'comment' => 'Reference of object'),
165
    );
166
167
    /**
168
     *    Constructor of the class
169
     *
170
     *    @param   DoliDb  $db     Database handler
171
     */
172
    function __construct($db)
173
    {
174
        $this->db = $db;
175
176
        // User preference
177
        $this->liste_limit = 0;
178
        $this->clicktodial_loaded = 0;
179
180
        // For cache usage
181
        $this->all_permissions_are_loaded = 0;
182
        $this->nb_rights = 0;
183
184
        // Force some default values
185
        $this->admin = 0;
186
        $this->employee = 1;
187
188
        $this->conf = new stdClass();
189
        $this->rights = new stdClass();
190
        $this->rights->user = new stdClass();
191
        $this->rights->user->user = new stdClass();
192
        $this->rights->user->self = new stdClass();
193
    }
194
195
    /**
196
     * 	Load a user from database with its id or ref (login).
197
     *  This function does not load permissions, only user properties. Use getrights() for this just after the fetch.
198
     *
199
     * 	@param	int		$id		       		If defined, id to used for search
200
     * 	@param  string	$login       		If defined, login to used for search
201
     * 	@param  string	$sid				If defined, sid to used for search
202
     * 	@param	int		$loadpersonalconf	1=also load personal conf of user (in $user->conf->xxx), 0=do not load personal conf.
203
     *  @param  int     $entity             If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup.
204
     * 	@return	int							<0 if KO, 0 not found, >0 if OK
205
     */
206
    function fetch($id = '', $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1)
207
    {
208
        global $conf, $user;
209
210
        // Clean parameters
211
        $login = trim($login);
212
213
        // Get user
214
        $sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.birth, u.email, u.job, u.skype, u.twitter, u.facebook,";
215
        $sql .= " u.signature, u.office_phone, u.office_fax, u.user_mobile,";
216
        $sql .= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
217
        $sql .= " u.admin, u.login, u.note,";
218
        $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,";
219
        $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid,";
220
        $sql .= " u.statut, u.lang, u.entity,";
221
        $sql .= " u.datec as datec,";
222
        $sql .= " u.tms as datem,";
223
        $sql .= " u.datelastlogin as datel,";
224
        $sql .= " u.datepreviouslogin as datep,";
225
        $sql .= " u.photo as photo,";
226
        $sql .= " u.openid as openid,";
227
        $sql .= " u.accountancy_code,";
228
        $sql .= " u.thm,";
229
        $sql .= " u.tjm,";
230
        $sql .= " u.salary,";
231
        $sql .= " u.salaryextra,";
232
        $sql .= " u.weeklyhours,";
233
        $sql .= " u.color,";
234
        $sql .= " u.dateemployment, u.dateemploymentend,";
235
        $sql .= " u.ref_int, u.ref_ext,";
236
        $sql .= " u.default_range, u.default_c_exp_tax_cat,";   // Expense report default mode
237
        $sql .= " c.code as country_code, c.label as country,";
238
        $sql .= " d.code_departement as state_code, d.nom as state";
239
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
240
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid";
241
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_departements as d ON u.fk_state = d.rowid";
242
243
        if ($entity < 0) {
244
            if ((empty($conf->multicompany->enabled) || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) && (!empty($user->entity))) {
245
                $sql .= " WHERE u.entity IN (0," . $conf->entity . ")";
246
            } else {
247
                $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
248
            }
249
        } else {  // The fetch was forced on an entity
250
            if (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))
251
                $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
252
            else
253
                $sql .= " WHERE u.entity IN (0, " . (($entity != '' && $entity >= 0) ? $entity : $conf->entity) . ")";   // search in entity provided in parameter
254
        }
255
256
        if ($sid) {    // permet une recherche du user par son SID ActiveDirectory ou Samba
257
            $sql .= " AND (u.ldap_sid = '" . $this->db->escape($sid) . "' OR u.login = '" . $this->db->escape($login) . "') LIMIT 1";
258
        } else if ($login) {
259
            $sql .= " AND u.login = '" . $this->db->escape($login) . "'";
260
        } else {
261
            $sql .= " AND u.rowid = " . $id;
262
        }
263
        $sql .= " ORDER BY u.entity ASC";    // Avoid random result when there is 2 login in 2 different entities
264
265
        $result = $this->db->query($sql);
266
        if ($result) {
267
            $obj = $this->db->fetch_object($result);
268
            if ($obj) {
269
                $this->id = $obj->rowid;
270
                $this->ref = $obj->rowid;
271
272
                $this->ref_int = $obj->ref_int;
273
                $this->ref_ext = $obj->ref_ext;
274
275
                $this->ldap_sid = $obj->ldap_sid;
276
                $this->lastname = $obj->lastname;
277
                $this->firstname = $obj->firstname;
278
279
                $this->employee = $obj->employee;
280
281
                $this->login = $obj->login;
282
                $this->gender = $obj->gender;
283
                $this->birth = $this->db->jdate($obj->birth);
284
                $this->pass_indatabase = $obj->pass;
285
                $this->pass_indatabase_crypted = $obj->pass_crypted;
286
                $this->pass = $obj->pass;
287
                $this->pass_temp = $obj->pass_temp;
288
                $this->api_key = $obj->api_key;
289
290
                $this->address = $obj->address;
291
                $this->zip = $obj->zip;
292
                $this->town = $obj->town;
293
294
                $this->country_id = $obj->country_id;
295
                $this->country_code = $obj->country_id ? $obj->country_code : '';
296
                //$this->country 		= $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
297
298
                $this->state_id = $obj->state_id;
299
                $this->state_code = $obj->state_code;
300
                $this->state = ($obj->state != '-' ? $obj->state : '');
301
302
                $this->office_phone = $obj->office_phone;
303
                $this->office_fax = $obj->office_fax;
304
                $this->user_mobile = $obj->user_mobile;
305
                $this->email = $obj->email;
306
                $this->skype = $obj->skype;
307
                $this->twitter = $obj->twitter;
308
                $this->facebook = $obj->facebook;
309
                $this->job = $obj->job;
310
                $this->signature = $obj->signature;
311
                $this->admin = $obj->admin;
312
                $this->note = $obj->note;
313
                $this->statut = $obj->statut;
314
                $this->photo = $obj->photo;
315
                $this->openid = $obj->openid;
316
                $this->lang = $obj->lang;
317
                $this->entity = $obj->entity;
318
                $this->accountancy_code = $obj->accountancy_code;
319
                $this->thm = $obj->thm;
320
                $this->tjm = $obj->tjm;
321
                $this->salary = $obj->salary;
322
                $this->salaryextra = $obj->salaryextra;
323
                $this->weeklyhours = $obj->weeklyhours;
324
                $this->color = $obj->color;
325
                $this->dateemployment = $this->db->jdate($obj->dateemployment);
326
                $this->dateemploymentend = $this->db->jdate($obj->dateemploymentend);
327
328
                $this->datec = $this->db->jdate($obj->datec);
329
                $this->datem = $this->db->jdate($obj->datem);
330
                $this->datelastlogin = $this->db->jdate($obj->datel);
331
                $this->datepreviouslogin = $this->db->jdate($obj->datep);
332
333
                $this->societe_id = $obj->fk_soc;  // deprecated
334
                $this->contact_id = $obj->fk_socpeople; // deprecated
335
                $this->socid = $obj->fk_soc;
336
                $this->contactid = $obj->fk_socpeople;
337
                $this->fk_member = $obj->fk_member;
338
                $this->fk_user = $obj->fk_user;
339
340
                $this->default_range = $obj->default_range;
341
                $this->default_c_exp_tax_cat = $obj->default_c_exp_tax_cat;
342
343
                // Protection when module multicompany was set, admin was set to first entity and then, the module was disabled,
344
                // in such case, this admin user must be admin for ALL entities.
345
                if (empty($conf->multicompany->enabled) && $this->admin && $this->entity == 1)
346
                    $this->entity = 0;
347
348
                // Retreive all extrafield
349
                // fetch optionals attributes and labels
350
                $this->fetch_optionals();
351
352
                $this->db->free($result);
353
            }
354
            else {
355
                $this->error = "USERNOTFOUND";
356
                dol_syslog(get_class($this) . "::fetch user not found", LOG_DEBUG);
357
358
                $this->db->free($result);
359
                return 0;
360
            }
361
        } else {
362
            $this->error = $this->db->lasterror();
363
            return -1;
364
        }
365
366
        // To get back the global configuration unique to the user
367
        if ($loadpersonalconf) {
368
            // Load user->conf for user
369
            $sql = "SELECT param, value FROM " . MAIN_DB_PREFIX . "user_param";
370
            $sql .= " WHERE fk_user = " . $this->id;
371
            $sql .= " AND entity = " . $conf->entity;
372
            //dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
373
            $resql = $this->db->query($sql);
374
            if ($resql) {
375
                $num = $this->db->num_rows($resql);
376
                $i = 0;
377
                while ($i < $num) {
378
                    $obj = $this->db->fetch_object($resql);
379
                    $p = (!empty($obj->param) ? $obj->param : '');
380
                    if (!empty($p))
381
                        $this->conf->$p = $obj->value;
382
                    $i++;
383
                }
384
                $this->db->free($resql);
385
            }
386
            else {
387
                $this->error = $this->db->lasterror();
388
                return -2;
389
            }
390
391
            $result = $this->loadDefaultValues();
392
393
            if ($result < 0) {
394
                $this->error = $this->db->lasterror();
395
                return -3;
396
            }
397
        }
398
399
        return 1;
400
    }
401
402
    /**
403
     *  Load default value in property ->default_values
404
     *
405
     *  @return int						> 0 if OK, < 0 if KO
406
     */
407
    function loadDefaultValues()
408
    {
409
        global $conf;
410
411
        // Load user->default_values for user. TODO Save this in memcached ?
412
        $sql = "SELECT rowid, entity, type, page, param, value";
413
        $sql .= " FROM " . MAIN_DB_PREFIX . "default_values";
414
        $sql .= " WHERE entity IN (" . ($this->entity > 0 ? $this->entity . ", " : "") . $conf->entity . ")"; // Entity of user (if defined) + current entity
415
        $sql .= " AND user_id IN (0" . ($this->id > 0 ? ", " . $this->id : "") . ")";       // User 0 (all) + me (if defined)
416
        $resql = $this->db->query($sql);
417
        if ($resql) {
418
            while ($obj = $this->db->fetch_object($resql)) {
419
                if (!empty($obj->page) && !empty($obj->type) && !empty($obj->param)) {
420
                    // $obj->page is relative URL with or without params
421
                    // $obj->type can be 'filters', 'sortorder', 'createform', ...
422
                    // $obj->param is key or param
423
                    $pagewithoutquerystring = $obj->page;
424
                    $pagequeries = '';
425
                    if (preg_match('/^([^\?]+)\?(.*)$/', $pagewithoutquerystring, $reg)) { // There is query param
426
                        $pagewithoutquerystring = $reg[1];
427
                        $pagequeries = $reg[2];
428
                    }
429
                    $this->default_values[$pagewithoutquerystring][$obj->type][$pagequeries ? $pagequeries : '_noquery_'][$obj->param] = $obj->value;
430
                    //if ($pagequeries) $this->default_values[$pagewithoutquerystring][$obj->type.'_queries']=$pagequeries;
431
                }
432
            }
433
            // Sort by key, so _noquery_ is last
434
            if (!empty($this->default_values)) {
435
                foreach ($this->default_values as $a => $b) {
436
                    foreach ($b as $c => $d) {
437
                        krsort($this->default_values[$a][$c]);
438
                    }
439
                }
440
            }
441
            $this->db->free($resql);
442
443
            return 1;
444
        } else {
445
            dol_print_error($this->db);
446
            return -1;
447
        }
448
    }
449
450
    /**
451
     *  Add a right to the user
452
     *
453
     * 	@param	int		$rid			Id of permission to add or 0 to add several permissions
454
     *  @param  string	$allmodule		Add all permissions of module $allmodule
455
     *  @param  string	$allperms		Add all permissions of module $allmodule, subperms $allperms only
456
     *  @param	int		$entity			Entity to use
457
     *  @param  int	    $notrigger		1=Does not execute triggers, 0=Execute triggers
458
     *  @return int						> 0 if OK, < 0 if KO
459
     *  @see	clearrights, delrights, getrights
460
     */
461
    function addrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
462
    {
463
        global $conf, $user, $langs;
464
465
        $entity = (!empty($entity) ? $entity : $conf->entity);
466
467
        dol_syslog(get_class($this) . "::addrights $rid, $allmodule, $allperms, $entity");
468
        $error = 0;
469
        $whereforadd = '';
470
471
        $this->db->begin();
472
473
        if (!empty($rid)) {
474
            // Si on a demande ajout d'un droit en particulier, on recupere
475
            // les caracteristiques (module, perms et subperms) de ce droit.
476
            $sql = "SELECT module, perms, subperms";
477
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
478
            $sql .= " WHERE id = '" . $this->db->escape($rid) . "'";
479
            $sql .= " AND entity = " . $entity;
480
481
            $result = $this->db->query($sql);
482
            if ($result) {
483
                $obj = $this->db->fetch_object($result);
484
                $module = $obj->module;
485
                $perms = $obj->perms;
486
                $subperms = $obj->subperms;
487
            } else {
488
                $error++;
489
                dol_print_error($this->db);
490
            }
491
492
            // Where pour la liste des droits a ajouter
493
            $whereforadd = "id=" . $this->db->escape($rid);
494
            // Ajout des droits induits
495
            if (!empty($subperms))
496
                $whereforadd .= " OR (module='$module' AND perms='$perms' AND (subperms='lire' OR subperms='read'))";
497
            else if (!empty($perms))
498
                $whereforadd .= " OR (module='$module' AND (perms='lire' OR perms='read') AND subperms IS NULL)";
499
        }
500
        else {
501
            // On a pas demande un droit en particulier mais une liste de droits
502
            // sur la base d'un nom de module de de perms
503
            // Where pour la liste des droits a ajouter
504
            if (!empty($allmodule)) {
505
                if ($allmodule == 'allmodules') {
506
                    $whereforadd = 'allmodules';
507
                } else {
508
                    $whereforadd = "module='" . $this->db->escape($allmodule) . "'";
509
                    if (!empty($allperms))
510
                        $whereforadd .= " AND perms='" . $this->db->escape($allperms) . "'";
511
                }
512
            }
513
        }
514
515
        // Ajout des droits trouves grace au critere whereforadd
516
        if (!empty($whereforadd)) {
517
            //print "$module-$perms-$subperms";
518
            $sql = "SELECT id";
519
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
520
            $sql .= " WHERE entity = " . $entity;
521
            if (!empty($whereforadd) && $whereforadd != 'allmodules') {
522
                $sql .= " AND " . $whereforadd;
523
            }
524
525
            $result = $this->db->query($sql);
526
            if ($result) {
527
                $num = $this->db->num_rows($result);
528
                $i = 0;
529
                while ($i < $num) {
530
                    $obj = $this->db->fetch_object($result);
531
                    $nid = $obj->id;
532
533
                    $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = " . $this->id . " AND fk_id=" . $nid . " AND entity = " . $entity;
534
                    if (!$this->db->query($sql))
535
                        $error++;
536
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_rights (entity, fk_user, fk_id) VALUES (" . $entity . ", " . $this->id . ", " . $nid . ")";
537
                    if (!$this->db->query($sql))
538
                        $error++;
539
540
                    $i++;
541
                }
542
            }
543
            else {
544
                $error++;
545
                dol_print_error($this->db);
546
            }
547
        }
548
549
        if (!$error && !$notrigger) {
550
            $langs->load("other");
551
            $this->context = array('audit' => $langs->trans("PermissionsAdd") . ($rid ? ' (id=' . $rid . ')' : ''));
552
553
            // Call trigger
554
            $result = $this->call_trigger('USER_MODIFY', $user);
555
            if ($result < 0) {
556
                $error++;
557
            }
558
            // End call triggers
559
        }
560
561
        if ($error) {
562
            $this->db->rollback();
563
            return -$error;
564
        } else {
565
            $this->db->commit();
566
            return 1;
567
        }
568
    }
569
570
    /**
571
     *  Remove a right to the user
572
     *
573
     *  @param	int		$rid        Id du droit a retirer
574
     *  @param  string	$allmodule  Retirer tous les droits du module allmodule
575
     *  @param  string	$allperms   Retirer tous les droits du module allmodule, perms allperms
576
     *  @param	int		$entity		Entity to use
577
     *  @param  int	    $notrigger	1=Does not execute triggers, 0=Execute triggers
578
     *  @return int         		> 0 if OK, < 0 if OK
579
     *  @see	clearrights, addrights, getrights
580
     */
581
    function delrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
582
    {
583
        global $conf, $user, $langs;
584
585
        $error = 0;
586
        $wherefordel = '';
587
        $entity = (!empty($entity) ? $entity : $conf->entity);
588
589
        $this->db->begin();
590
591
        if (!empty($rid)) {
592
            // Si on a demande supression d'un droit en particulier, on recupere
593
            // les caracteristiques module, perms et subperms de ce droit.
594
            $sql = "SELECT module, perms, subperms";
595
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
596
            $sql .= " WHERE id = '" . $this->db->escape($rid) . "'";
597
            $sql .= " AND entity = " . $entity;
598
599
            $result = $this->db->query($sql);
600
            if ($result) {
601
                $obj = $this->db->fetch_object($result);
602
                $module = $obj->module;
603
                $perms = $obj->perms;
604
                $subperms = $obj->subperms;
605
            } else {
606
                $error++;
607
                dol_print_error($this->db);
608
            }
609
610
            // Where pour la liste des droits a supprimer
611
            $wherefordel = "id=" . $this->db->escape($rid);
612
            // Suppression des droits induits
613
            if ($subperms == 'lire' || $subperms == 'read')
614
                $wherefordel .= " OR (module='$module' AND perms='$perms' AND subperms IS NOT NULL)";
615
            if ($perms == 'lire' || $perms == 'read')
616
                $wherefordel .= " OR (module='$module')";
617
        }
618
        else {
619
            // On a demande suppression d'un droit sur la base d'un nom de module ou perms
620
            // Where pour la liste des droits a supprimer
621
            if (!empty($allmodule)) {
622
                if ($allmodule == 'allmodules') {
623
                    $wherefordel = 'allmodules';
624
                } else {
625
                    $wherefordel = "module='" . $this->db->escape($allmodule) . "'";
626
                    if (!empty($allperms))
627
                        $whereforadd .= " AND perms='" . $this->db->escape($allperms) . "'";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $whereforadd does not exist. Did you maybe mean $wherefordel?
Loading history...
628
                }
629
            }
630
        }
631
632
        // Suppression des droits selon critere defini dans wherefordel
633
        if (!empty($wherefordel)) {
634
            //print "$module-$perms-$subperms";
635
            $sql = "SELECT id";
636
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
637
            $sql .= " WHERE entity = " . $entity;
638
            if (!empty($wherefordel) && $wherefordel != 'allmodules') {
639
                $sql .= " AND " . $wherefordel;
640
            }
641
642
            $result = $this->db->query($sql);
643
            if ($result) {
644
                $num = $this->db->num_rows($result);
645
                $i = 0;
646
                while ($i < $num) {
647
                    $obj = $this->db->fetch_object($result);
648
                    $nid = $obj->id;
649
650
                    $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights";
651
                    $sql .= " WHERE fk_user = " . $this->id . " AND fk_id=" . $nid;
652
                    $sql .= " AND entity = " . $entity;
653
                    if (!$this->db->query($sql))
654
                        $error++;
655
656
                    $i++;
657
                }
658
            }
659
            else {
660
                $error++;
661
                dol_print_error($this->db);
662
            }
663
        }
664
665
        if (!$error && !$notrigger) {
666
            $langs->load("other");
667
            $this->context = array('audit' => $langs->trans("PermissionsDelete") . ($rid ? ' (id=' . $rid . ')' : ''));
668
669
            // Call trigger
670
            $result = $this->call_trigger('USER_MODIFY', $user);
671
            if ($result < 0) {
672
                $error++;
673
            }
674
            // End call triggers
675
        }
676
677
        if ($error) {
678
            $this->db->rollback();
679
            return -$error;
680
        } else {
681
            $this->db->commit();
682
            return 1;
683
        }
684
    }
685
686
    /**
687
     *  Clear all permissions array of user
688
     *
689
     *  @return	void
690
     *  @see	getrights
691
     */
692
    function clearrights()
693
    {
694
        dol_syslog(get_class($this) . "::clearrights reset user->rights");
695
        $this->rights = '';
696
        $this->all_permissions_are_loaded = false;
697
        $this->_tab_loaded = array();
698
    }
699
700
    /**
701
     * 	Load permissions granted to user into object user
702
     *
703
     * 	@param  string	$moduletag		Limit permission for a particular module ('' by default means load all permissions)
704
     *  @param	int		$forcereload	Force reload of permissions even if they were already loaded (ignore cache)
705
     * 	@return	void
706
     *  @see	clearrights, delrights, addrights
707
     */
708
    function getrights($moduletag = '', $forcereload = 0)
709
    {
710
        global $conf;
711
712
        if (empty($forcereload)) {
713
            if ($moduletag && isset($this->_tab_loaded[$moduletag]) && $this->_tab_loaded[$moduletag]) {
714
                // Rights for this module are already loaded, so we leave
715
                return;
716
            }
717
718
            if ($this->all_permissions_are_loaded) {
719
                // We already loaded all rights for this user, so we leave
720
                return;
721
            }
722
        }
723
724
        // Recuperation des droits utilisateurs + recuperation des droits groupes
725
        // D'abord les droits utilisateurs
726
        $sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
727
        $sql .= " FROM " . MAIN_DB_PREFIX . "user_rights as ur";
728
        $sql .= ", " . MAIN_DB_PREFIX . "rights_def as r";
729
        $sql .= " WHERE r.id = ur.fk_id";
730
        if (!empty($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
731
            $sql .= " AND r.entity IN (0," . (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) ? "1," : "") . $conf->entity . ")";
732
        } else {
733
            $sql .= " AND ur.entity = " . $conf->entity;
734
        }
735
        $sql .= " AND ur.fk_user= " . $this->id;
736
        $sql .= " AND r.perms IS NOT NULL";
737
        if ($moduletag)
738
            $sql .= " AND r.module = '" . $this->db->escape($moduletag) . "'";
739
740
        $resql = $this->db->query($sql);
741
        if ($resql) {
742
            $num = $this->db->num_rows($resql);
743
            $i = 0;
744
            while ($i < $num) {
745
                $obj = $this->db->fetch_object($resql);
746
747
                $module = $obj->module;
748
                $perms = $obj->perms;
749
                $subperms = $obj->subperms;
750
751
                if ($perms) {
752
                    if (!isset($this->rights) || !is_object($this->rights))
753
                        $this->rights = new stdClass(); // For avoid error
754
                    if ($module) {
755
                        if (!isset($this->rights->$module) || !is_object($this->rights->$module))
756
                            $this->rights->$module = new stdClass();
757
                        if ($subperms) {
758
                            if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms))
759
                                $this->rights->$module->$perms = new stdClass();
760
                            if (empty($this->rights->$module->$perms->$subperms))
761
                                $this->nb_rights++;
762
                            $this->rights->$module->$perms->$subperms = 1;
763
                        }
764
                        else {
765
                            if (empty($this->rights->$module->$perms))
766
                                $this->nb_rights++;
767
                            $this->rights->$module->$perms = 1;
768
                        }
769
                    }
770
                }
771
                $i++;
772
            }
773
            $this->db->free($resql);
774
        }
775
776
        // Maintenant les droits groupes
777
        $sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
778
        $sql .= " FROM " . MAIN_DB_PREFIX . "usergroup_rights as gr,";
779
        $sql .= " " . MAIN_DB_PREFIX . "usergroup_user as gu,";
780
        $sql .= " " . MAIN_DB_PREFIX . "rights_def as r";
781
        $sql .= " WHERE r.id = gr.fk_id";
782
        if (!empty($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
783
            if (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
784
                $sql .= " AND gu.entity IN (0," . $conf->entity . ")";
785
            } else {
786
                $sql .= " AND r.entity = " . $conf->entity;
787
            }
788
        } else {
789
            $sql .= " AND gr.entity = " . $conf->entity;
790
            $sql .= " AND r.entity = " . $conf->entity;
791
        }
792
        $sql .= " AND gr.fk_usergroup = gu.fk_usergroup";
793
        $sql .= " AND gu.fk_user = " . $this->id;
794
        $sql .= " AND r.perms IS NOT NULL";
795
        if ($moduletag)
796
            $sql .= " AND r.module = '" . $this->db->escape($moduletag) . "'";
797
798
        $resql = $this->db->query($sql);
799
        if ($resql) {
800
            $num = $this->db->num_rows($resql);
801
            $i = 0;
802
            while ($i < $num) {
803
                $obj = $this->db->fetch_object($resql);
804
805
                $module = $obj->module;
806
                $perms = $obj->perms;
807
                $subperms = $obj->subperms;
808
809
                if ($perms) {
810
                    if (!isset($this->rights) || !is_object($this->rights))
811
                        $this->rights = new stdClass(); // For avoid error
812
                    if (!isset($this->rights->$module) || !is_object($this->rights->$module))
813
                        $this->rights->$module = new stdClass();
814
                    if ($subperms) {
815
                        if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms))
816
                            $this->rights->$module->$perms = new stdClass();
817
                        if (empty($this->rights->$module->$perms->$subperms))
818
                            $this->nb_rights++;
819
                        $this->rights->$module->$perms->$subperms = 1;
820
                    }
821
                    else {
822
                        if (empty($this->rights->$module->$perms))
823
                            $this->nb_rights++;
824
                        // if we have already define a subperm like this $this->rights->$module->level1->level2 with llx_user_rights, we don't want override level1 because the level2 can be not define on user group
825
                        if (!is_object($this->rights->$module->$perms))
826
                            $this->rights->$module->$perms = 1;
827
                    }
828
                }
829
                $i++;
830
            }
831
            $this->db->free($resql);
832
        }
833
834
        // For backward compatibility
835
        if (isset($this->rights->propale) && !isset($this->rights->propal))
836
            $this->rights->propal = $this->rights->propale;
837
        if (isset($this->rights->propal) && !isset($this->rights->propale))
838
            $this->rights->propale = $this->rights->propal;
839
840
        if (!$moduletag) {
841
            // Si module etait non defini, alors on a tout charge, on peut donc considerer
842
            // que les droits sont en cache (car tous charges) pour cet instance de user
843
            $this->all_permissions_are_loaded = 1;
844
        } else {
845
            // Si module defini, on le marque comme charge en cache
846
            $this->_tab_loaded[$moduletag] = 1;
847
        }
848
    }
849
850
    /**
851
     *  Change status of a user
852
     *
853
     * 	@param	int		$statut		Status to set
854
     *  @return int     			<0 if KO, 0 if nothing is done, >0 if OK
855
     */
856
    function setstatus($statut)
857
    {
858
        global $conf, $langs, $user;
859
860
        $error = 0;
861
862
        // Check parameters
863
        if ($this->statut == $statut)
864
            return 0;
865
        else
866
            $this->statut = $statut;
867
868
        $this->db->begin();
869
870
        // Deactivate user
871
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
872
        $sql .= " SET statut = " . $this->statut;
873
        $sql .= " WHERE rowid = " . $this->id;
874
        $result = $this->db->query($sql);
875
876
        dol_syslog(get_class($this) . "::setstatus", LOG_DEBUG);
877
        if ($result) {
878
            // Call trigger
879
            $result = $this->call_trigger('USER_ENABLEDISABLE', $user);
880
            if ($result < 0) {
881
                $error++;
882
            }
883
            // End call triggers
884
        }
885
886
        if ($error) {
887
            $this->db->rollback();
888
            return -$error;
889
        } else {
890
            $this->db->commit();
891
            return 1;
892
        }
893
    }
894
895
    /**
896
     * Sets object to supplied categories.
897
     *
898
     * Deletes object from existing categories not supplied.
899
     * Adds it to non existing supplied categories.
900
     * Existing categories are left untouch.
901
     *
902
     * @param int[]|int $categories Category or categories IDs
903
     * @return void
904
     */
905
    public function setCategories($categories)
906
    {
907
        // Handle single category
908
        if (!is_array($categories)) {
909
            $categories = array($categories);
910
        }
911
912
        // Get current categories
913
        require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
914
        $c = new Categorie($this->db);
915
        $existing = $c->containing($this->id, Categorie::TYPE_USER, 'id');
916
917
        // Diff
918
        if (is_array($existing)) {
919
            $to_del = array_diff($existing, $categories);
920
            $to_add = array_diff($categories, $existing);
921
        } else {
922
            $to_del = array(); // Nothing to delete
923
            $to_add = $categories;
924
        }
925
926
        // Process
927
        foreach ($to_del as $del) {
928
            if ($c->fetch($del) > 0) {
929
                $c->del_type($this, 'user');
930
            }
931
        }
932
        foreach ($to_add as $add) {
933
            if ($c->fetch($add) > 0) {
934
                $c->add_type($this, 'user');
935
            }
936
        }
937
938
        return;
939
    }
940
941
    /**
942
     *    	Delete the user
943
     *
944
     * 		@return		int		<0 if KO, >0 if OK
945
     */
946
    function delete()
947
    {
948
        global $user, $conf, $langs;
949
950
        $error = 0;
951
952
        $this->db->begin();
953
954
        $this->fetch($this->id);
955
956
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
957
958
        // Remove rights
959
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = " . $this->id;
960
961
        if (!$error && !$this->db->query($sql)) {
962
            $error++;
963
            $this->error = $this->db->lasterror();
964
        }
965
966
        // Remove group
967
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user WHERE fk_user  = " . $this->id;
968
        if (!$error && !$this->db->query($sql)) {
969
            $error++;
970
            $this->error = $this->db->lasterror();
971
        }
972
973
        // If contact, remove link
974
        if ($this->contact_id) {
975
            $sql = "UPDATE " . MAIN_DB_PREFIX . "socpeople SET fk_user_creat = null WHERE rowid = " . $this->contact_id;
976
            if (!$error && !$this->db->query($sql)) {
977
                $error++;
978
                $this->error = $this->db->lasterror();
979
            }
980
        }
981
982
        // Remove extrafields
983
        if ((!$error) && (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))) { // For avoid conflicts if trigger used
984
            $result = $this->deleteExtraFields();
985
            if ($result < 0) {
986
                $error++;
987
                dol_syslog(get_class($this) . "::delete error -4 " . $this->error, LOG_ERR);
988
            }
989
        }
990
991
        // Remove user
992
        if (!$error) {
993
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user WHERE rowid = " . $this->id;
994
            dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
995
            if (!$this->db->query($sql)) {
996
                $error++;
997
                $this->error = $this->db->lasterror();
998
            }
999
        }
1000
1001
        if (!$error) {
1002
            // Call trigger
1003
            $result = $this->call_trigger('USER_DELETE', $user);
1004
            if ($result < 0) {
1005
                $error++;
1006
                $this->db->rollback();
1007
                return -1;
1008
            }
1009
            // End call triggers
1010
1011
            $this->db->commit();
1012
            return 1;
1013
        } else {
1014
            $this->db->rollback();
1015
            return -1;
1016
        }
1017
    }
1018
1019
    /**
1020
     *  Create a user into database
1021
     *
1022
     *  @param	User	$user        	Objet user doing creation
1023
     *  @param  int		$notrigger		1=do not execute triggers, 0 otherwise
1024
     *  @return int			         	<0 if KO, id of created user if OK
1025
     */
1026
    function create($user, $notrigger = 0)
1027
    {
1028
        global $conf, $langs;
1029
        global $mysoc;
1030
1031
        // Clean parameters
1032
        $this->login = trim($this->login);
1033
        if (!isset($this->entity))
1034
            $this->entity = $conf->entity; // If not defined, we use default value
1035
1036
        dol_syslog(get_class($this) . "::create login=" . $this->login . ", user=" . (is_object($user) ? $user->id : ''), LOG_DEBUG);
1037
1038
        // Check parameters
1039
        if (!empty($conf->global->USER_MAIL_REQUIRED) && !isValidEMail($this->email)) {
1040
            $langs->load("errors");
1041
            $this->error = $langs->trans("ErrorBadEMail", $this->email);
1042
            return -1;
1043
        }
1044
        if (empty($this->login)) {
1045
            $langs->load("errors");
1046
            $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Login"));
1047
            return -1;
1048
        }
1049
1050
        $this->datec = dol_now();
1051
1052
        $error = 0;
1053
        $this->db->begin();
1054
1055
        $sql = "SELECT login FROM " . MAIN_DB_PREFIX . "user";
1056
        $sql .= " WHERE login ='" . $this->db->escape($this->login) . "'";
1057
        $sql .= " AND entity IN (0," . $this->db->escape($conf->entity) . ")";
1058
1059
        dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1060
        $resql = $this->db->query($sql);
1061
        if ($resql) {
1062
            $num = $this->db->num_rows($resql);
1063
            $this->db->free($resql);
1064
1065
            if ($num) {
1066
                $this->error = 'ErrorLoginAlreadyExists';
1067
                dol_syslog(get_class($this) . "::create " . $this->error, LOG_WARNING);
1068
                $this->db->rollback();
1069
                return -6;
1070
            } else {
1071
                $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user (datec,login,ldap_sid,entity)";
1072
                $sql .= " VALUES('" . $this->db->idate($this->datec) . "','" . $this->db->escape($this->login) . "','" . $this->db->escape($this->ldap_sid) . "'," . $this->db->escape($this->entity) . ")";
1073
                $result = $this->db->query($sql);
1074
1075
                dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1076
                if ($result) {
1077
                    $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "user");
1078
1079
                    // Set default rights
1080
                    if ($this->set_default_rights() < 0) {
1081
                        $this->error = 'ErrorFailedToSetDefaultRightOfUser';
1082
                        $this->db->rollback();
1083
                        return -5;
1084
                    }
1085
1086
                    // Update minor fields
1087
                    $result = $this->update($user, 1, 1);
1088
                    if ($result < 0) {
1089
                        $this->db->rollback();
1090
                        return -4;
1091
                    }
1092
1093
                    if (!empty($conf->global->STOCK_USERSTOCK_AUTOCREATE)) {
1094
                        require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1095
                        $langs->load("stocks");
1096
                        $entrepot = new Entrepot($this->db);
1097
                        $entrepot->libelle = $langs->trans("PersonalStock", $this->getFullName($langs));
1098
                        $entrepot->description = $langs->trans("ThisWarehouseIsPersonalStock", $this->getFullName($langs));
1099
                        $entrepot->statut = 1;
1100
                        $entrepot->country_id = $mysoc->country_id;
1101
                        $entrepot->create($user);
1102
                    }
1103
1104
                    if (!$notrigger) {
1105
                        // Call trigger
1106
                        $result = $this->call_trigger('USER_CREATE', $user);
1107
                        if ($result < 0) {
1108
                            $error++;
1109
                        }
1110
                        // End call triggers
1111
                    }
1112
1113
                    if (!$error) {
1114
                        $this->db->commit();
1115
                        return $this->id;
1116
                    } else {
1117
                        //$this->error=$interface->error;
1118
                        dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
1119
                        $this->db->rollback();
1120
                        return -3;
1121
                    }
1122
                } else {
1123
                    $this->error = $this->db->lasterror();
1124
                    $this->db->rollback();
1125
                    return -2;
1126
                }
1127
            }
1128
        } else {
1129
            $this->error = $this->db->lasterror();
1130
            $this->db->rollback();
1131
            return -1;
1132
        }
1133
    }
1134
1135
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1136
    /**
1137
     *  Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
1138
     *
1139
     *  @param	Contact	$contact    Object for source contact
1140
     * 	@param  string	$login      Login to force
1141
     *  @param  string	$password   Password to force
1142
     *  @return int 				<0 if error, if OK returns id of created user
1143
     */
1144
    function create_from_contact($contact, $login = '', $password = '')
1145
    {
1146
        // phpcs:enable
1147
        global $conf, $user, $langs;
1148
1149
        $error = 0;
1150
1151
        // Define parameters
1152
        $this->admin = 0;
1153
        $this->lastname = $contact->lastname;
1154
        $this->firstname = $contact->firstname;
1155
        $this->gender = $contact->gender;
1156
        $this->email = $contact->email;
1157
        $this->skype = $contact->skype;
1158
        $this->twitter = $contact->twitter;
1159
        $this->facebook = $contact->facebook;
1160
        $this->office_phone = $contact->phone_pro;
1161
        $this->office_fax = $contact->fax;
1162
        $this->user_mobile = $contact->phone_mobile;
1163
        $this->address = $contact->address;
1164
        $this->zip = $contact->zip;
1165
        $this->town = $contact->town;
1166
        $this->state_id = $contact->state_id;
1167
        $this->country_id = $contact->country_id;
1168
        $this->employee = 0;
1169
1170
        if (empty($login))
1171
            $login = strtolower(substr($contact->firstname, 0, 4)) . strtolower(substr($contact->lastname, 0, 4));
1172
        $this->login = $login;
1173
1174
        $this->db->begin();
1175
1176
        // Cree et positionne $this->id
1177
        $result = $this->create($user);
1178
        if ($result > 0) {
1179
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1180
            $sql .= " SET fk_socpeople=" . $contact->id;
1181
            if ($contact->socid)
1182
                $sql .= ", fk_soc=" . $contact->socid;
1183
            $sql .= " WHERE rowid=" . $this->id;
1184
            $resql = $this->db->query($sql);
1185
1186
            dol_syslog(get_class($this) . "::create_from_contact", LOG_DEBUG);
1187
            if ($resql) {
1188
                $this->context['createfromcontact'] = 'createfromcontact';
1189
1190
                // Call trigger
1191
                $result = $this->call_trigger('USER_CREATE', $user);
1192
                if ($result < 0) {
1193
                    $error++;
1194
                    $this->db->rollback();
1195
                    return -1;
1196
                }
1197
                // End call triggers
1198
1199
                $this->db->commit();
1200
                return $this->id;
1201
            } else {
1202
                $this->error = $this->db->error();
1203
1204
                $this->db->rollback();
1205
                return -1;
1206
            }
1207
        } else {
1208
            // $this->error deja positionne
1209
            dol_syslog(get_class($this) . "::create_from_contact - 0");
1210
1211
            $this->db->rollback();
1212
            return $result;
1213
        }
1214
    }
1215
1216
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1217
    /**
1218
     *  Create a user into database from a member object
1219
     *
1220
     *  @param	Adherent	$member		Object member source
1221
     * 	@param	string		$login		Login to force
1222
     *  @return int						<0 if KO, if OK, return id of created account
1223
     */
1224
    function create_from_member($member, $login = '')
1225
    {
1226
        // phpcs:enable
1227
        global $conf, $user, $langs;
1228
1229
        // Positionne parametres
1230
        $this->admin = 0;
1231
        $this->lastname = $member->lastname;
1232
        $this->firstname = $member->firstname;
1233
        $this->gender = $member->gender;
1234
        $this->email = $member->email;
1235
        $this->fk_member = $member->id;
1236
        $this->pass = $member->pass;
1237
        $this->address = $member->address;
1238
        $this->zip = $member->zip;
1239
        $this->town = $member->town;
1240
        $this->state_id = $member->state_id;
1241
        $this->country_id = $member->country_id;
1242
1243
        if (empty($login))
1244
            $login = strtolower(substr($member->firstname, 0, 4)) . strtolower(substr($member->lastname, 0, 4));
1245
        $this->login = $login;
1246
1247
        $this->db->begin();
1248
1249
        // Create and set $this->id
1250
        $result = $this->create($user);
1251
        if ($result > 0) {
1252
            $newpass = $this->setPassword($user, $this->pass);
1253
            if (is_numeric($newpass) && $newpass < 0)
1254
                $result = -2;
1255
1256
            if ($result > 0 && $member->fk_soc) { // If member is linked to a thirdparty
1257
                $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1258
                $sql .= " SET fk_soc=" . $member->fk_soc;
1259
                $sql .= " WHERE rowid=" . $this->id;
1260
1261
                dol_syslog(get_class($this) . "::create_from_member", LOG_DEBUG);
1262
                $resql = $this->db->query($sql);
1263
                if ($resql) {
1264
                    $this->db->commit();
1265
                    return $this->id;
1266
                } else {
1267
                    $this->error = $this->db->lasterror();
1268
1269
                    $this->db->rollback();
1270
                    return -1;
1271
                }
1272
            }
1273
        }
1274
1275
        if ($result > 0) {
1276
            $this->db->commit();
1277
            return $this->id;
1278
        } else {
1279
            // $this->error deja positionne
1280
            $this->db->rollback();
1281
            return -2;
1282
        }
1283
    }
1284
1285
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1286
    /**
1287
     *    Assign rights by default
1288
     *
1289
     *    @return     integer erreur <0, si ok renvoi le nbre de droits par defaut positionnes
1290
     */
1291
    function set_default_rights()
1292
    {
1293
        // phpcs:enable
1294
        global $conf;
1295
1296
        $sql = "SELECT id FROM " . MAIN_DB_PREFIX . "rights_def";
1297
        $sql .= " WHERE bydefault = 1";
1298
        $sql .= " AND entity = " . $conf->entity;
1299
1300
        $resql = $this->db->query($sql);
1301
        if ($resql) {
1302
            $num = $this->db->num_rows($resql);
1303
            $i = 0;
1304
            $rd = array();
1305
            while ($i < $num) {
1306
                $row = $this->db->fetch_row($resql);
1307
                $rd[$i] = $row[0];
1308
                $i++;
1309
            }
1310
            $this->db->free($resql);
1311
        }
1312
        $i = 0;
1313
        while ($i < $num) {
1314
1315
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = $this->id AND fk_id=$rd[$i]";
1316
            $result = $this->db->query($sql);
1317
1318
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_rights (fk_user, fk_id) VALUES ($this->id, $rd[$i])";
1319
            $result = $this->db->query($sql);
1320
            if (!$result)
1321
                return -1;
1322
            $i++;
1323
        }
1324
1325
        return $i;
1326
    }
1327
1328
    /**
1329
     *  	Update a user into database (and also password if this->pass is defined)
1330
     *
1331
     * 		@param	User	$user				User qui fait la mise a jour
1332
     *    	@param  int		$notrigger			1 ne declenche pas les triggers, 0 sinon
1333
     * 		@param	int		$nosyncmember		0=Synchronize linked member (standard info), 1=Do not synchronize linked member
1334
     * 		@param	int		$nosyncmemberpass	0=Synchronize linked member (password), 1=Do not synchronize linked member
1335
     * 		@param	int		$nosynccontact		0=Synchronize linked contact, 1=Do not synchronize linked contact
1336
     *    	@return int 		        		<0 si KO, >=0 si OK
1337
     */
1338
    function update($user, $notrigger = 0, $nosyncmember = 0, $nosyncmemberpass = 0, $nosynccontact = 0)
1339
    {
1340
        global $conf, $langs;
1341
1342
        $nbrowsaffected = 0;
1343
        $error = 0;
1344
1345
        dol_syslog(get_class($this) . "::update notrigger=" . $notrigger . ", nosyncmember=" . $nosyncmember . ", nosyncmemberpass=" . $nosyncmemberpass);
1346
1347
        // Clean parameters
1348
        $this->lastname = trim($this->lastname);
1349
        $this->firstname = trim($this->firstname);
1350
        $this->employee = $this->employee ? $this->employee : 0;
1351
        $this->login = trim($this->login);
1352
        $this->gender = trim($this->gender);
1353
        $this->birth = trim($this->birth);
1354
        $this->pass = trim($this->pass);
1355
        $this->api_key = trim($this->api_key);
1356
        $this->address = $this->address ? trim($this->address) : trim($this->address);
1357
        $this->zip = $this->zip ? trim($this->zip) : trim($this->zip);
1358
        $this->town = $this->town ? trim($this->town) : trim($this->town);
1359
        $this->state_id = trim($this->state_id);
1360
        $this->country_id = ($this->country_id > 0) ? $this->country_id : 0;
1361
        $this->office_phone = trim($this->office_phone);
1362
        $this->office_fax = trim($this->office_fax);
1363
        $this->user_mobile = trim($this->user_mobile);
1364
        $this->email = trim($this->email);
1365
1366
        $this->skype = trim($this->skype);
1367
        $this->twitter = trim($this->twitter);
1368
        $this->facebook = trim($this->facebook);
1369
1370
        $this->job = trim($this->job);
1371
        $this->signature = trim($this->signature);
1372
        $this->note = trim($this->note);
1373
        $this->openid = trim(empty($this->openid) ? '' : $this->openid);    // Avoid warning
1374
        $this->admin = $this->admin ? $this->admin : 0;
1375
        $this->address = empty($this->address) ? '' : $this->address;
1376
        $this->zip = empty($this->zip) ? '' : $this->zip;
1377
        $this->town = empty($this->town) ? '' : $this->town;
1378
        $this->accountancy_code = trim($this->accountancy_code);
1379
        $this->color = empty($this->color) ? '' : $this->color;
1380
        $this->dateemployment = empty($this->dateemployment) ? '' : $this->dateemployment;
1381
        $this->dateemploymentend = empty($this->dateemploymentend) ? '' : $this->dateemploymentend;
1382
1383
        // Check parameters
1384
        if (!empty($conf->global->USER_MAIL_REQUIRED) && !isValidEMail($this->email)) {
1385
            $langs->load("errors");
1386
            $this->error = $langs->trans("ErrorBadEMail", $this->email);
1387
            return -1;
1388
        }
1389
        if (empty($this->login)) {
1390
            $langs->load("errors");
1391
            $this->error = $langs->trans("ErrorFieldRequired", $this->login);
1392
            return -1;
1393
        }
1394
1395
        $this->db->begin();
1396
1397
        // Update datas
1398
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET";
1399
        $sql .= " lastname = '" . $this->db->escape($this->lastname) . "'";
1400
        $sql .= ", firstname = '" . $this->db->escape($this->firstname) . "'";
1401
        $sql .= ", employee = " . $this->employee;
1402
        $sql .= ", login = '" . $this->db->escape($this->login) . "'";
1403
        $sql .= ", api_key = " . ($this->api_key ? "'" . $this->db->escape($this->api_key) . "'" : "null");
1404
        $sql .= ", gender = " . ($this->gender != -1 ? "'" . $this->db->escape($this->gender) . "'" : "null"); // 'man' or 'woman'
1405
        $sql .= ", birth=" . (strval($this->birth) != '' ? "'" . $this->db->idate($this->birth) . "'" : 'null');
1406
        if (!empty($user->admin))
1407
            $sql .= ", admin = " . $this->admin; // admin flag can be set/unset only by an admin user
1408
        $sql .= ", address = '" . $this->db->escape($this->address) . "'";
1409
        $sql .= ", zip = '" . $this->db->escape($this->zip) . "'";
1410
        $sql .= ", town = '" . $this->db->escape($this->town) . "'";
1411
        $sql .= ", fk_state = " . ((!empty($this->state_id) && $this->state_id > 0) ? "'" . $this->db->escape($this->state_id) . "'" : "null");
1412
        $sql .= ", fk_country = " . ((!empty($this->country_id) && $this->country_id > 0) ? "'" . $this->db->escape($this->country_id) . "'" : "null");
1413
        $sql .= ", office_phone = '" . $this->db->escape($this->office_phone) . "'";
1414
        $sql .= ", office_fax = '" . $this->db->escape($this->office_fax) . "'";
1415
        $sql .= ", user_mobile = '" . $this->db->escape($this->user_mobile) . "'";
1416
        $sql .= ", email = '" . $this->db->escape($this->email) . "'";
1417
        $sql .= ", skype = '" . $this->db->escape($this->skype) . "'";
1418
        $sql .= ", twitter = '" . $this->db->escape($this->twitter) . "'";
1419
        $sql .= ", facebook = '" . $this->db->escape($this->facebook) . "'";
1420
        $sql .= ", job = '" . $this->db->escape($this->job) . "'";
1421
        $sql .= ", signature = '" . $this->db->escape($this->signature) . "'";
1422
        $sql .= ", accountancy_code = '" . $this->db->escape($this->accountancy_code) . "'";
1423
        $sql .= ", color = '" . $this->db->escape($this->color) . "'";
1424
        $sql .= ", dateemployment=" . (strval($this->dateemployment) != '' ? "'" . $this->db->idate($this->dateemployment) . "'" : 'null');
1425
        $sql .= ", dateemploymentend=" . (strval($this->dateemploymentend) != '' ? "'" . $this->db->idate($this->dateemploymentend) . "'" : 'null');
1426
        $sql .= ", note = '" . $this->db->escape($this->note) . "'";
1427
        $sql .= ", photo = " . ($this->photo ? "'" . $this->db->escape($this->photo) . "'" : "null");
1428
        $sql .= ", openid = " . ($this->openid ? "'" . $this->db->escape($this->openid) . "'" : "null");
1429
        $sql .= ", fk_user = " . ($this->fk_user > 0 ? "'" . $this->db->escape($this->fk_user) . "'" : "null");
1430
        if (isset($this->thm) || $this->thm != '')
1431
            $sql .= ", thm= " . ($this->thm != '' ? "'" . $this->db->escape($this->thm) . "'" : "null");
1432
        if (isset($this->tjm) || $this->tjm != '')
1433
            $sql .= ", tjm= " . ($this->tjm != '' ? "'" . $this->db->escape($this->tjm) . "'" : "null");
1434
        if (isset($this->salary) || $this->salary != '')
1435
            $sql .= ", salary= " . ($this->salary != '' ? "'" . $this->db->escape($this->salary) . "'" : "null");
1436
        if (isset($this->salaryextra) || $this->salaryextra != '')
1437
            $sql .= ", salaryextra= " . ($this->salaryextra != '' ? "'" . $this->db->escape($this->salaryextra) . "'" : "null");
1438
        $sql .= ", weeklyhours= " . ($this->weeklyhours != '' ? "'" . $this->db->escape($this->weeklyhours) . "'" : "null");
1439
        $sql .= ", entity = '" . $this->db->escape($this->entity) . "'";
1440
        $sql .= ", default_range = " . ($this->default_range > 0 ? $this->default_range : 'null');
1441
        $sql .= ", default_c_exp_tax_cat = " . ($this->default_c_exp_tax_cat > 0 ? $this->default_c_exp_tax_cat : 'null');
1442
1443
        $sql .= " WHERE rowid = " . $this->id;
1444
1445
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
1446
        $resql = $this->db->query($sql);
1447
        if ($resql) {
1448
            $nbrowsaffected += $this->db->affected_rows($resql);
1449
1450
            // Update password
1451
            if (!empty($this->pass)) {
1452
                if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
1453
                    // Si mot de passe saisi et different de celui en base
1454
                    $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass);
1455
                    if (!$nbrowsaffected)
1456
                        $nbrowsaffected++;
1457
                }
1458
            }
1459
1460
            // If user is linked to a member, remove old link to this member
1461
            if ($this->fk_member > 0) {
1462
                dol_syslog(get_class($this) . "::update remove link with member. We will recreate it later", LOG_DEBUG);
1463
                $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET fk_member = NULL where fk_member = " . $this->fk_member;
1464
                $resql = $this->db->query($sql);
1465
                if (!$resql) {
1466
                    $this->error = $this->db->error();
1467
                    $this->db->rollback();
1468
                    return -5;
1469
                }
1470
            }
1471
            // Set link to user
1472
            dol_syslog(get_class($this) . "::update set link with member", LOG_DEBUG);
1473
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET fk_member =" . ($this->fk_member > 0 ? $this->fk_member : 'null') . " where rowid = " . $this->id;
1474
            $resql = $this->db->query($sql);
1475
            if (!$resql) {
1476
                $this->error = $this->db->error();
1477
                $this->db->rollback();
1478
                return -5;
1479
            }
1480
1481
            if ($nbrowsaffected) { // If something has changed in data
1482
                if ($this->fk_member > 0 && !$nosyncmember) {
1483
                    dol_syslog(get_class($this) . "::update user is linked with a member. We try to update member too.", LOG_DEBUG);
1484
1485
                    require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
1486
1487
                    // This user is linked with a member, so we also update member information
1488
                    // if this is an update.
1489
                    $adh = new Adherent($this->db);
1490
                    $result = $adh->fetch($this->fk_member);
1491
1492
                    if ($result >= 0) {
1493
                        $adh->firstname = $this->firstname;
1494
                        $adh->lastname = $this->lastname;
1495
                        $adh->login = $this->login;
1496
                        $adh->gender = $this->gender;
1497
                        $adh->birth = $this->birth;
1498
1499
                        $adh->pass = $this->pass;
1500
1501
                        $adh->societe = (empty($adh->societe) && $this->societe_id ? $this->societe_id : $adh->societe);
1502
1503
                        $adh->address = $this->address;
1504
                        $adh->town = $this->town;
1505
                        $adh->zip = $this->zip;
1506
                        $adh->state_id = $this->state_id;
1507
                        $adh->country_id = $this->country_id;
1508
1509
                        $adh->email = $this->email;
1510
1511
                        $adh->skype = $this->skype;
1512
                        $adh->twitter = $this->twitter;
1513
                        $adh->facebook = $this->facebook;
1514
1515
                        $adh->phone = $this->office_phone;
1516
                        $adh->phone_mobile = $this->user_mobile;
1517
1518
                        $adh->user_id = $this->id;
1519
                        $adh->user_login = $this->login;
1520
1521
                        $result = $adh->update($user, 0, 1, 0);
1522
                        if ($result < 0) {
1523
                            $this->error = $adh->error;
1524
                            $this->errors = $adh->errors;
1525
                            dol_syslog(get_class($this) . "::update error after calling adh->update to sync it with user: " . $this->error, LOG_ERR);
1526
                            $error++;
1527
                        }
1528
                    } else {
1529
                        $this->error = $adh->error;
1530
                        $this->errors = $adh->errors;
1531
                        $error++;
1532
                    }
1533
                }
1534
1535
                if ($this->contact_id > 0 && !$nosynccontact) {
1536
                    dol_syslog(get_class($this) . "::update user is linked with a contact. We try to update contact too.", LOG_DEBUG);
1537
1538
                    require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1539
1540
                    // This user is linked with a contact, so we also update contact information
1541
                    // if this is an update.
1542
                    $tmpobj = new Contact($this->db);
1543
                    $result = $tmpobj->fetch($this->contact_id);
1544
1545
                    if ($result >= 0) {
1546
                        $tmpobj->firstname = $this->firstname;
1547
                        $tmpobj->lastname = $this->lastname;
1548
                        $tmpobj->login = $this->login;
1549
                        $tmpobj->gender = $this->gender;
1550
                        $tmpobj->birth = $this->birth;
1551
1552
                        //$tmpobj->pass=$this->pass;
1553
                        //$tmpobj->societe=(empty($tmpobj->societe) && $this->societe_id ? $this->societe_id : $tmpobj->societe);
1554
1555
                        $tmpobj->email = $this->email;
1556
1557
                        $tmpobj->skype = $this->skype;
1558
                        $tmpobj->twitter = $this->twitter;
1559
                        $tmpobj->facebook = $this->facebook;
1560
1561
                        $tmpobj->phone_pro = $this->office_phone;
1562
                        $tmpobj->phone_mobile = $this->user_mobile;
1563
                        $tmpobj->fax = $this->office_fax;
1564
1565
                        $tmpobj->address = $this->address;
1566
                        $tmpobj->town = $this->town;
1567
                        $tmpobj->zip = $this->zip;
1568
                        $tmpobj->state_id = $this->state_id;
1569
                        $tmpobj->country_id = $this->country_id;
1570
1571
                        $tmpobj->user_id = $this->id;
1572
                        $tmpobj->user_login = $this->login;
1573
1574
                        $result = $tmpobj->update($tmpobj->id, $user, 0, 'update', 1);
1575
                        if ($result < 0) {
1576
                            $this->error = $tmpobj->error;
1577
                            $this->errors = $tmpobj->errors;
1578
                            dol_syslog(get_class($this) . "::update error after calling adh->update to sync it with user: " . $this->error, LOG_ERR);
1579
                            $error++;
1580
                        }
1581
                    } else {
1582
                        $this->error = $tmpobj->error;
1583
                        $this->errors = $tmpobj->errors;
1584
                        $error++;
1585
                    }
1586
                }
1587
            }
1588
1589
            $action = 'update';
1590
1591
            // Actions on extra fields
1592
            if (!$error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
1593
                $result = $this->insertExtraFields();
1594
                if ($result < 0) {
1595
                    $error++;
1596
                }
1597
            }
1598
1599
            if (!$error && !$notrigger) {
1600
                // Call trigger
1601
                $result = $this->call_trigger('USER_MODIFY', $user);
1602
                if ($result < 0) {
1603
                    $error++;
1604
                }
1605
                // End call triggers
1606
            }
1607
1608
            if (!$error) {
1609
                $this->db->commit();
1610
                return $nbrowsaffected;
1611
            } else {
1612
                dol_syslog(get_class($this) . "::update error=" . $this->error, LOG_ERR);
1613
                $this->db->rollback();
1614
                return -1;
1615
            }
1616
        } else {
1617
            $this->error = $this->db->lasterror();
1618
            $this->db->rollback();
1619
            return -2;
1620
        }
1621
    }
1622
1623
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1624
    /**
1625
     *    Mise a jour en base de la date de derniere connexion d'un utilisateur
1626
     * 	  Fonction appelee lors d'une nouvelle connexion
1627
     *
1628
     *    @return     <0 si echec, >=0 si ok
0 ignored issues
show
Documentation Bug introduced by
The doc comment <0 at position 0 could not be parsed: Unknown type name '<' at position 0 in <0.
Loading history...
1629
     */
1630
    function update_last_login_date()
1631
    {
1632
        // phpcs:enable
1633
        $now = dol_now();
1634
1635
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET";
1636
        $sql .= " datepreviouslogin = datelastlogin,";
1637
        $sql .= " datelastlogin = '" . $this->db->idate($now) . "',";
1638
        $sql .= " tms = tms";    // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion
1639
        $sql .= " WHERE rowid = " . $this->id;
1640
1641
        dol_syslog(get_class($this) . "::update_last_login_date user->id=" . $this->id . " " . $sql, LOG_DEBUG);
1642
        $resql = $this->db->query($sql);
1643
        if ($resql) {
1644
            $this->datepreviouslogin = $this->datelastlogin;
1645
            $this->datelastlogin = $now;
1646
            return 1;
1647
        } else {
1648
            $this->error = $this->db->lasterror() . ' sql=' . $sql;
1649
            return -1;
1650
        }
1651
    }
1652
1653
    /**
1654
     *  Change password of a user
1655
     *
1656
     *  @param	User	$user             		Object user of user making change
1657
     *  @param  string	$password         		New password in clear text (to generate if not provided)
1658
     * 	@param	int		$changelater			1=Change password only after clicking on confirm email
1659
     * 	@param	int		$notrigger				1=Does not launch triggers
1660
     * 	@param	int		$nosyncmember	        Do not synchronize linked member
1661
     *  @return string 			          		If OK return clear password, 0 if no change, < 0 if error
1662
     */
1663
    function setPassword($user, $password = '', $changelater = 0, $notrigger = 0, $nosyncmember = 0)
1664
    {
1665
        global $conf, $langs;
1666
        require_once DOL_DOCUMENT_ROOT . '/core/lib/security2.lib.php';
1667
1668
        $error = 0;
1669
1670
        dol_syslog(get_class($this) . "::setPassword user=" . $user->id . " password=" . preg_replace('/./i', '*', $password) . " changelater=" . $changelater . " notrigger=" . $notrigger . " nosyncmember=" . $nosyncmember, LOG_DEBUG);
1671
1672
        // If new password not provided, we generate one
1673
        if (!$password) {
1674
            $password = getRandomPassword(false);
1675
        }
1676
1677
        // Crypt password
1678
        $password_crypted = dol_hash($password);
1679
1680
        // Mise a jour
1681
        if (!$changelater) {
1682
            if (!is_object($this->oldcopy))
1683
                $this->oldcopy = clone $this;
1684
1685
            $this->db->begin();
1686
1687
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1688
            $sql .= " SET pass_crypted = '" . $this->db->escape($password_crypted) . "',";
1689
            $sql .= " pass_temp = null";
1690
            if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
1691
                $sql .= ", pass = null";
1692
            } else {
1693
                $sql .= ", pass = '" . $this->db->escape($password) . "'";
1694
            }
1695
            $sql .= " WHERE rowid = " . $this->id;
1696
1697
            dol_syslog(get_class($this) . "::setPassword", LOG_DEBUG);
1698
            $result = $this->db->query($sql);
1699
            if ($result) {
1700
                if ($this->db->affected_rows($result)) {
1701
                    $this->pass = $password;
1702
                    $this->pass_indatabase = $password;
1703
                    $this->pass_indatabase_crypted = $password_crypted;
1704
1705
                    if ($this->fk_member && !$nosyncmember) {
1706
                        require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
1707
1708
                        // This user is linked with a member, so we also update members informations
1709
                        // if this is an update.
1710
                        $adh = new Adherent($this->db);
1711
                        $result = $adh->fetch($this->fk_member);
1712
1713
                        if ($result >= 0) {
1714
                            $result = $adh->setPassword($user, $this->pass, (empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1), 1); // Cryptage non gere dans module adherent
1715
                            if ($result < 0) {
1716
                                $this->error = $adh->error;
1717
                                dol_syslog(get_class($this) . "::setPassword " . $this->error, LOG_ERR);
1718
                                $error++;
1719
                            }
1720
                        } else {
1721
                            $this->error = $adh->error;
1722
                            $error++;
1723
                        }
1724
                    }
1725
1726
                    dol_syslog(get_class($this) . "::setPassword notrigger=" . $notrigger . " error=" . $error, LOG_DEBUG);
1727
1728
                    if (!$error && !$notrigger) {
1729
                        // Call trigger
1730
                        $result = $this->call_trigger('USER_NEW_PASSWORD', $user);
1731
                        if ($result < 0) {
1732
                            $error++;
1733
                            $this->db->rollback();
1734
                            return -1;
1735
                        }
1736
                        // End call triggers
1737
                    }
1738
1739
                    $this->db->commit();
1740
                    return $this->pass;
1741
                } else {
1742
                    $this->db->rollback();
1743
                    return 0;
1744
                }
1745
            } else {
1746
                $this->db->rollback();
1747
                dol_print_error($this->db);
1748
                return -1;
1749
            }
1750
        } else {
1751
            // We store clear password in password temporary field.
1752
            // After receiving confirmation link, we will crypt it and store it in pass_crypted
1753
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1754
            $sql .= " SET pass_temp = '" . $this->db->escape($password) . "'";
1755
            $sql .= " WHERE rowid = " . $this->id;
1756
1757
            dol_syslog(get_class($this) . "::setPassword", LOG_DEBUG); // No log
1758
            $result = $this->db->query($sql);
1759
            if ($result) {
1760
                return $password;
1761
            } else {
1762
                dol_print_error($this->db);
1763
                return -3;
1764
            }
1765
        }
1766
    }
1767
1768
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1769
    /**
1770
     *  Send new password by email
1771
     *
1772
     *  @param	User	$user           Object user that send email
1773
     *  @param	string	$password       New password
1774
     * 	@param	int		$changelater	0=Send clear passwod into email, 1=Change password only after clicking on confirm email. @TODO Add method 2 = Send link to reset password
1775
     *  @return int 		            < 0 si erreur, > 0 si ok
1776
     */
1777
    function send_password($user, $password = '', $changelater = 0)
1778
    {
1779
        // phpcs:enable
1780
        global $conf, $langs;
1781
        global $dolibarr_main_url_root;
1782
1783
        require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
1784
1785
        $msgishtml = 0;
1786
1787
        // Define $msg
1788
        $mesg = '';
1789
1790
        $outputlangs = new Translate("", $conf);
1791
        if (isset($this->conf->MAIN_LANG_DEFAULT) && $this->conf->MAIN_LANG_DEFAULT != 'auto') { // If user has defined its own language (rare because in most cases, auto is used)
1792
            $outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT);
1793
        } else { // If user has not defined its own language, we used current language
1794
            $outputlangs = $langs;
1795
        }
1796
1797
        // Load translation files required by the page
1798
        $outputlangs->loadLangs(array("main", "errors", "users", "other"));
1799
1800
        $appli = constant('DOL_APPLICATION_TITLE');
1801
        if (!empty($conf->global->MAIN_APPLICATION_TITLE))
1802
            $appli = $conf->global->MAIN_APPLICATION_TITLE;
1803
1804
        $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli);
1805
1806
        // Define $urlwithroot
1807
        $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
1808
        $urlwithroot = $urlwithouturlroot . DOL_URL_ROOT;  // This is to use external domain name found into config file
1809
1810
        if (!$changelater) {
1811
            $url = $urlwithroot . '/';
1812
1813
            $mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived") . ".\n";
1814
            $mesg .= $outputlangs->transnoentitiesnoconv("NewKeyIs") . " :\n\n";
1815
            $mesg .= $outputlangs->transnoentitiesnoconv("Login") . " = " . $this->login . "\n";
1816
            $mesg .= $outputlangs->transnoentitiesnoconv("Password") . " = " . $password . "\n\n";
1817
            $mesg .= "\n";
1818
1819
            $mesg .= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli) . ': ' . $url . "\n\n";
1820
            $mesg .= "--\n";
1821
            $mesg .= $user->getFullName($outputlangs); // Username that make then sending
1822
1823
            dol_syslog(get_class($this) . "::send_password changelater is off, url=" . $url);
1824
        } else {
1825
            $url = $urlwithroot . '/user/passwordforgotten.php?action=validatenewpassword&username=' . $this->login . "&passwordhash=" . dol_hash($password);
1826
1827
            $mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived") . "\n";
1828
            $mesg .= $outputlangs->transnoentitiesnoconv("NewKeyWillBe") . " :\n\n";
1829
            $mesg .= $outputlangs->transnoentitiesnoconv("Login") . " = " . $this->login . "\n";
1830
            $mesg .= $outputlangs->transnoentitiesnoconv("Password") . " = " . $password . "\n\n";
1831
            $mesg .= "\n";
1832
            $mesg .= $outputlangs->transnoentitiesnoconv("YouMustClickToChange") . " :\n";
1833
            $mesg .= $url . "\n\n";
1834
            $mesg .= $outputlangs->transnoentitiesnoconv("ForgetIfNothing") . "\n\n";
1835
1836
            dol_syslog(get_class($this) . "::send_password changelater is on, url=" . $url);
1837
        }
1838
1839
        $mailfile = new CMailFile(
1840
            $subject, $this->email, $conf->global->MAIN_MAIL_EMAIL_FROM, $mesg, array(), array(), array(), '', '', 0, $msgishtml
1841
        );
1842
1843
        if ($mailfile->sendfile()) {
1844
            return 1;
1845
        } else {
1846
            $langs->trans("errors");
1847
            $this->error = $langs->trans("ErrorFailedToSendPassword") . ' ' . $mailfile->error;
1848
            return -1;
1849
        }
1850
    }
1851
1852
    /**
1853
     * 		Renvoie la derniere erreur fonctionnelle de manipulation de l'objet
1854
     *
1855
     * 		@return    string      chaine erreur
1856
     */
1857
    function error()
1858
    {
1859
        return $this->error;
1860
    }
1861
1862
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1863
    /**
1864
     *    	Read clicktodial information for user
1865
     *
1866
     * 		@return		<0 if KO, >0 if OK
0 ignored issues
show
Documentation Bug introduced by
The doc comment <0 at position 0 could not be parsed: Unknown type name '<' at position 0 in <0.
Loading history...
1867
     */
1868
    function fetch_clicktodial()
1869
    {
1870
        // phpcs:enable
1871
        $sql = "SELECT url, login, pass, poste ";
1872
        $sql .= " FROM " . MAIN_DB_PREFIX . "user_clicktodial as u";
1873
        $sql .= " WHERE u.fk_user = " . $this->id;
1874
1875
        $resql = $this->db->query($sql);
1876
        if ($resql) {
1877
            if ($this->db->num_rows($resql)) {
1878
                $obj = $this->db->fetch_object($resql);
1879
1880
                $this->clicktodial_url = $obj->url;
1881
                $this->clicktodial_login = $obj->login;
1882
                $this->clicktodial_password = $obj->pass;
1883
                $this->clicktodial_poste = $obj->poste;
1884
            }
1885
1886
            $this->clicktodial_loaded = 1; // Data loaded (found or not)
1887
1888
            $this->db->free($resql);
1889
            return 1;
1890
        } else {
1891
            $this->error = $this->db->error();
1892
            return -1;
1893
        }
1894
    }
1895
1896
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1897
    /**
1898
     *  Update clicktodial info
1899
     *
1900
     *  @return	integer
1901
     */
1902
    function update_clicktodial()
1903
    {
1904
        // phpcs:enable
1905
        $this->db->begin();
1906
1907
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_clicktodial";
1908
        $sql .= " WHERE fk_user = " . $this->id;
1909
1910
        dol_syslog(get_class($this) . '::update_clicktodial', LOG_DEBUG);
1911
        $result = $this->db->query($sql);
1912
1913
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_clicktodial";
1914
        $sql .= " (fk_user,url,login,pass,poste)";
1915
        $sql .= " VALUES (" . $this->id;
1916
        $sql .= ", '" . $this->db->escape($this->clicktodial_url) . "'";
1917
        $sql .= ", '" . $this->db->escape($this->clicktodial_login) . "'";
1918
        $sql .= ", '" . $this->db->escape($this->clicktodial_password) . "'";
1919
        $sql .= ", '" . $this->db->escape($this->clicktodial_poste) . "')";
1920
1921
        dol_syslog(get_class($this) . '::update_clicktodial', LOG_DEBUG);
1922
        $result = $this->db->query($sql);
1923
        if ($result) {
1924
            $this->db->commit();
1925
            return 1;
1926
        } else {
1927
            $this->db->rollback();
1928
            $this->error = $this->db->lasterror();
1929
            return -1;
1930
        }
1931
    }
1932
1933
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1934
    /**
1935
     *  Add user into a group
1936
     *
1937
     *  @param	int	$group      Id of group
1938
     *  @param  int		$entity     Entity
1939
     *  @param  int		$notrigger  Disable triggers
1940
     *  @return int  				<0 if KO, >0 if OK
1941
     */
1942
    function SetInGroup($group, $entity, $notrigger = 0)
1943
    {
1944
        // phpcs:enable
1945
        global $conf, $langs, $user;
1946
1947
        $error = 0;
1948
1949
        $this->db->begin();
1950
1951
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user";
1952
        $sql .= " WHERE fk_user  = " . $this->id;
1953
        $sql .= " AND fk_usergroup = " . $group;
1954
        $sql .= " AND entity = " . $entity;
1955
1956
        $result = $this->db->query($sql);
1957
1958
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "usergroup_user (entity, fk_user, fk_usergroup)";
1959
        $sql .= " VALUES (" . $entity . "," . $this->id . "," . $group . ")";
1960
1961
        $result = $this->db->query($sql);
1962
        if ($result) {
1963
            if (!$error && !$notrigger) {
1964
                $this->newgroupid = $group;    // deprecated. Remove this.
1965
                $this->context = array('audit' => $langs->trans("UserSetInGroup"), 'newgroupid' => $group);
1966
1967
                // Call trigger
1968
                $result = $this->call_trigger('USER_MODIFY', $user);
1969
                if ($result < 0) {
1970
                    $error++;
1971
                }
1972
                // End call triggers
1973
            }
1974
1975
            if (!$error) {
1976
                $this->db->commit();
1977
                return 1;
1978
            } else {
1979
                dol_syslog(get_class($this) . "::SetInGroup " . $this->error, LOG_ERR);
1980
                $this->db->rollback();
1981
                return -2;
1982
            }
1983
        } else {
1984
            $this->error = $this->db->lasterror();
1985
            $this->db->rollback();
1986
            return -1;
1987
        }
1988
    }
1989
1990
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1991
    /**
1992
     *  Remove a user from a group
1993
     *
1994
     *  @param	int   $group       Id of group
1995
     *  @param  int		$entity      Entity
1996
     *  @param  int		$notrigger   Disable triggers
1997
     *  @return int  			     <0 if KO, >0 if OK
1998
     */
1999
    function RemoveFromGroup($group, $entity, $notrigger = 0)
2000
    {
2001
        // phpcs:enable
2002
        global $conf, $langs, $user;
2003
2004
        $error = 0;
2005
2006
        $this->db->begin();
2007
2008
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user";
2009
        $sql .= " WHERE fk_user  = " . $this->id;
2010
        $sql .= " AND fk_usergroup = " . $group;
2011
        $sql .= " AND entity = " . $entity;
2012
2013
        $result = $this->db->query($sql);
2014
        if ($result) {
2015
            if (!$error && !$notrigger) {
2016
                $this->oldgroupid = $group;    // deprecated. Remove this.
2017
                $this->context = array('audit' => $langs->trans("UserRemovedFromGroup"), 'oldgroupid' => $group);
2018
2019
                // Call trigger
2020
                $result = $this->call_trigger('USER_MODIFY', $user);
2021
                if ($result < 0) {
2022
                    $error++;
2023
                }
2024
                // End call triggers
2025
            }
2026
2027
            if (!$error) {
2028
                $this->db->commit();
2029
                return 1;
2030
            } else {
2031
                $this->error = $interface->error;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $interface seems to be never defined.
Loading history...
2032
                dol_syslog(get_class($this) . "::RemoveFromGroup " . $this->error, LOG_ERR);
2033
                $this->db->rollback();
2034
                return -2;
2035
            }
2036
        } else {
2037
            $this->error = $this->db->lasterror();
2038
            $this->db->rollback();
2039
            return -1;
2040
        }
2041
    }
2042
2043
    /**
2044
     *  Return a link with photo
2045
     * 	Use this->id,this->photo
2046
     *
2047
     * 	@param	int		$width			Width of image
2048
     * 	@param	int		$height			Height of image
2049
     *  @param	string	$cssclass		Force a css class
2050
     * 	@param	string	$imagesize		'mini', 'small' or '' (original)
2051
     * 	@return	string					String with URL link
2052
     */
2053
    function getPhotoUrl($width, $height, $cssclass = '', $imagesize = '')
2054
    {
2055
        $result = '<a href="' . DOL_URL_ROOT . '/user/card.php?id=' . $this->id . '">';
2056
        $result .= Form::showphoto('userphoto', $this, $width, $height, 0, $cssclass, $imagesize);
2057
        $result .= '</a>';
2058
2059
        return $result;
2060
    }
2061
2062
    /**
2063
     *  Return a link to the user card (with optionaly the picto)
2064
     * 	Use this->id,this->lastname, this->firstname
2065
     *
2066
     * 	@param	int		$withpictoimg				Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small)
2067
     * 	@param	string	$option						On what the link point to ('leave', 'nolink', )
2068
     *  @param  integer $infologin      			0=Add default info tooltip, 1=Add complete info tooltip, -1=No info tooltip
2069
     *  @param	integer	$notooltip					1=Disable tooltip on picto and name
2070
     *  @param	int		$maxlen						Max length of visible user name
2071
     *  @param	int		$hidethirdpartylogo			Hide logo of thirdparty if user is external user
2072
     *  @param  string  $mode               		''=Show firstname and lastname, 'firstname'=Show only firstname, 'login'=Show login
2073
     *  @param  string  $morecss            		Add more css on link
2074
     *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2075
     * 	@return	string								String with URL
2076
     */
2077
    function getNomUrl($withpictoimg = 0, $option = '', $infologin = 0, $notooltip = 0, $maxlen = 24, $hidethirdpartylogo = 0, $mode = '', $morecss = '', $save_lastsearch_value = -1)
2078
    {
2079
        global $langs, $conf, $db, $hookmanager, $user;
2080
        global $dolibarr_main_authentication, $dolibarr_main_demo;
2081
        global $menumanager;
2082
2083
        if (!$user->rights->user->user->lire && $user->id != $this->id) {
2084
            $option = 'nolink';
2085
        }
2086
2087
        if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) {
2088
            $withpictoimg = 0;
2089
        }
2090
2091
        $result = '';
2092
        $label = '';
2093
        $link = '';
2094
        $linkstart = '';
2095
        $linkend = '';
2096
2097
        if (!empty($this->photo)) {
2098
            $label .= '<div class="photointooltip">';
2099
            $label .= Form::showphoto('userphoto', $this, 0, 60, 0, 'photowithmargin photologintooltip', 'small', 0, 1); // Force height to 60 so we total height of tooltip can be calculated and collision can be managed
2100
            $label .= '</div><div style="clear: both;"></div>';
2101
        }
2102
2103
        // Info Login
2104
        $label .= '<div class="centpercent">';
2105
        $label .= '<u>' . $langs->trans("User") . '</u><br>';
2106
        $label .= '<b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs, '');
2107
        if (!empty($this->login)) {
2108
            $label .= '<br><b>' . $langs->trans('Login') . ':</b> ' . $this->login;
2109
        }
2110
        $label .= '<br><b>' . $langs->trans("EMail") . ':</b> ' . $this->email;
2111
        if (!empty($this->admin)) {
2112
            $label .= '<br><b>' . $langs->trans("Administrator") . '</b>: ' . yn($this->admin);
2113
        }
2114
        if (!empty($this->socid)) { // Add thirdparty for external users
2115
            $thirdpartystatic = new Societe($db);
2116
            $thirdpartystatic->fetch($this->socid);
2117
            if (empty($hidethirdpartylogo)) {
2118
                $companylink = ' ' . $thirdpartystatic->getNomUrl(2, (($option == 'nolink') ? 'nolink' : '')); // picto only of company
2119
            }
2120
            $company = ' (' . $langs->trans("Company") . ': ' . $thirdpartystatic->name . ')';
2121
        }
2122
        $type = ($this->socid ? $langs->trans("External") . $company : $langs->trans("Internal"));
2123
        $label .= '<br><b>' . $langs->trans("Type") . ':</b> ' . $type;
2124
        $label .= '<br><b>' . $langs->trans("Status") . '</b>: ' . $this->getLibStatut(0);
2125
        $label .= '</div>';
2126
        if ($infologin > 0) {
2127
            $label .= '<br>';
2128
            $label .= '<br><u>' . $langs->trans("Connection") . '</u>';
2129
            $label .= '<br><b>' . $langs->trans("IPAddress") . '</b>: ' . $_SERVER["REMOTE_ADDR"];
2130
            if (!empty($conf->global->MAIN_MODULE_MULTICOMPANY))
2131
                $label .= '<br><b>' . $langs->trans("ConnectedOnMultiCompany") . ':</b> ' . $conf->entity . ' (user entity ' . $this->entity . ')';
2132
            $label .= '<br><b>' . $langs->trans("AuthenticationMode") . ':</b> ' . $_SESSION["dol_authmode"] . (empty($dolibarr_main_demo) ? '' : ' (demo)');
2133
            $label .= '<br><b>' . $langs->trans("ConnectedSince") . ':</b> ' . dol_print_date($this->datelastlogin, "dayhour", 'tzuser');
2134
            $label .= '<br><b>' . $langs->trans("PreviousConnexion") . ':</b> ' . dol_print_date($this->datepreviouslogin, "dayhour", 'tzuser');
2135
            $label .= '<br><b>' . $langs->trans("CurrentTheme") . ':</b> ' . $conf->theme;
2136
            $label .= '<br><b>' . $langs->trans("CurrentMenuManager") . ':</b> ' . $menumanager->name;
2137
            $s = picto_from_langcode($langs->getDefaultLang());
2138
            $label .= '<br><b>' . $langs->trans("CurrentUserLanguage") . ':</b> ' . ($s ? $s . ' ' : '') . $langs->getDefaultLang();
2139
            $label .= '<br><b>' . $langs->trans("Browser") . ':</b> ' . $conf->browser->name . ($conf->browser->version ? ' ' . $conf->browser->version : '') . ' (' . $_SERVER['HTTP_USER_AGENT'] . ')';
2140
            $label .= '<br><b>' . $langs->trans("Layout") . ':</b> ' . $conf->browser->layout;
2141
            $label .= '<br><b>' . $langs->trans("Screen") . ':</b> ' . $_SESSION['dol_screenwidth'] . ' x ' . $_SESSION['dol_screenheight'];
2142
            if ($conf->browser->layout == 'phone')
2143
                $label .= '<br><b>' . $langs->trans("Phone") . ':</b> ' . $langs->trans("Yes");
2144
            if (!empty($_SESSION["disablemodules"]))
2145
                $label .= '<br><b>' . $langs->trans("DisabledModules") . ':</b> <br>' . join(', ', explode(',', $_SESSION["disablemodules"]));
2146
        }
2147
        if ($infologin < 0)
2148
            $label = '';
2149
2150
        // $url = DOL_URL_ROOT . '/user/card.php?id=' . $this->id;
2151
        $url = BASE_URI . '?controller=user&method=card&id=' . $this->id;
2152
        if ($option == 'leave') {
2153
            //$url = DOL_URL_ROOT . '/holiday/list.php?id=' . $this->id;
2154
            $url = BASE_URI . '?controller=holiday&method=list&id=' . $this->id;
2155
        }
2156
        if ($option != 'nolink') {
2157
            // Add param to save lastsearch_values or not
2158
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2159
            if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"]))
2160
                $add_save_lastsearch_values = 1;
2161
            if ($add_save_lastsearch_values)
2162
                $url .= '&save_lastsearch_values=1';
2163
        }
2164
2165
        $linkstart = '<a href="' . $url . '"';
2166
        $linkclose = "";
2167
        if (empty($notooltip)) {
2168
            if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2169
                $langs->load("users");
2170
                $label = $langs->trans("ShowUser");
2171
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
2172
            }
2173
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
2174
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
2175
2176
            /*
2177
              $hookmanager->initHooks(array('userdao'));
2178
              $parameters=array('id'=>$this->id);
2179
              $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
2180
              if ($reshook > 0) $linkclose = $hookmanager->resPrint;
2181
             */
2182
        }
2183
2184
        $linkstart .= $linkclose . '>';
2185
        $linkend = '</a>';
2186
2187
        //if ($withpictoimg == -1) $result.='<div class="nowrap">';
2188
        $result .= (($option == 'nolink') ? '' : $linkstart);
2189
        if ($withpictoimg) {
2190
            $paddafterimage = '';
2191
            if (abs($withpictoimg) == 1)
2192
                $paddafterimage = 'style="margin-right: 3px;"';
2193
            // Only picto
2194
            if ($withpictoimg > 0)
2195
                $picto = '<!-- picto user --><div class="inline-block nopadding userimg' . ($morecss ? ' ' . $morecss : '') . '">' . img_object('', 'user', $paddafterimage . ' ' . ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1) . '</div>';
2196
            // Picto must be a photo
2197
            else
2198
                $picto = '<!-- picto photo user --><div class="inline-block nopadding userimg' . ($morecss ? ' ' . $morecss : '') . '"' . ($paddafterimage ? ' ' . $paddafterimage : '') . '>' . Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto' . ($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1) . '</div>';
2199
            $result .= $picto;
2200
        }
2201
        if ($withpictoimg > -2 && $withpictoimg != 2) {
2202
            if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2203
                $result .= '<div class="inline-block nopadding valignmiddle usertext' . ((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled') . ($morecss ? ' ' . $morecss : '') . '">';
2204
            if ($mode == 'login')
2205
                $result .= dol_trunc($this->login, $maxlen);
2206
            else
2207
                $result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : -1), $maxlen);
2208
            if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2209
                $result .= '</div>';
2210
        }
2211
        $result .= (($option == 'nolink') ? '' : $linkend);
2212
        //if ($withpictoimg == -1) $result.='</div>';
2213
2214
        $result .= $companylink;
2215
2216
        global $action;
2217
        $hookmanager->initHooks(array('userdao'));
2218
        $parameters = array('id' => $this->id, 'getnomurl' => $result);
2219
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action);    // Note that $action and $object may have been modified by some hooks
2220
        if ($reshook > 0) {
2221
            $result = $hookmanager->resPrint;
2222
        } else {
2223
            $result .= $hookmanager->resPrint;
2224
        }
2225
2226
        return $result;
2227
    }
2228
2229
    /**
2230
     *  Return clickable link of login (eventualy with picto)
2231
     *
2232
     * 	@param	int		$withpicto		Include picto into link
2233
     * 	@param	string	$option			Sur quoi pointe le lien
2234
     * 	@return	string					Chaine avec URL
2235
     */
2236
    function getLoginUrl($withpicto = 0, $option = '')
2237
    {
2238
        global $langs, $user;
2239
2240
        $result = '';
2241
2242
        // $linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2243
        $linkstart = '<a href="' . BASE_URI . '?controller=user&method=card&id=' . $this->id . '">';
2244
        $linkend = '</a>';
2245
2246
        //Check user's rights to see an other user
2247
        if ((!$user->rights->user->user->lire && $this->id != $user->id))
2248
            $option = 'nolink';
2249
2250
        if ($option == 'xxx') {
2251
            //$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2252
            $linkstart = '<a href="' . BASE_URI . '?controller=user&method=card.php&id=' . $this->id . '">';
2253
            $linkend = '</a>';
2254
        }
2255
2256
        if ($option == 'nolink') {
2257
            $linkstart = '';
2258
            $linkend = '';
2259
        }
2260
2261
        $result .= $linkstart;
2262
        if ($withpicto)
2263
            $result .= img_object($langs->trans("ShowUser"), 'user', 'class="paddingright"');
2264
        $result .= $this->login;
2265
        $result .= $linkend;
2266
        return $result;
2267
    }
2268
2269
    /**
2270
     *  Return label of status of user (active, inactive)
2271
     *
2272
     *  @param	int		$mode          0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2273
     *  @return	string 			       Label of status
2274
     */
2275
    function getLibStatut($mode = 0)
2276
    {
2277
        return $this->LibStatut($this->statut, $mode);
2278
    }
2279
2280
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2281
    /**
2282
     *  Renvoi le libelle d'un statut donne
2283
     *
2284
     *  @param	int		$statut        	Id statut
2285
     *  @param  int		$mode          	0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2286
     *  @return string 			       	Label of status
2287
     */
2288
    function LibStatut($statut, $mode = 0)
2289
    {
2290
        // phpcs:enable
2291
        global $langs;
2292
        $langs->load('users');
2293
2294
        if ($mode == 0) {
2295
            if ($statut == 1)
2296
                return $langs->trans('Enabled');
2297
            elseif ($statut == 0)
2298
                return $langs->trans('Disabled');
2299
        }
2300
        elseif ($mode == 1) {
2301
            if ($statut == 1)
2302
                return $langs->trans('Enabled');
2303
            elseif ($statut == 0)
2304
                return $langs->trans('Disabled');
2305
        }
2306
        elseif ($mode == 2) {
2307
            if ($statut == 1)
2308
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"') . ' ' . $langs->trans('Enabled');
2309
            elseif ($statut == 0)
2310
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"') . ' ' . $langs->trans('Disabled');
2311
        }
2312
        elseif ($mode == 3) {
2313
            if ($statut == 1)
2314
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"');
2315
            elseif ($statut == 0)
2316
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"');
2317
        }
2318
        elseif ($mode == 4) {
2319
            if ($statut == 1)
2320
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"') . ' ' . $langs->trans('Enabled');
2321
            elseif ($statut == 0)
2322
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"') . ' ' . $langs->trans('Disabled');
2323
        }
2324
        elseif ($mode == 5) {
2325
            if ($statut == 1)
2326
                return $langs->trans('Enabled') . ' ' . img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"');
2327
            elseif ($statut == 0)
2328
                return $langs->trans('Disabled') . ' ' . img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"');
2329
        }
2330
    }
2331
2332
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2333
    /**
2334
     * 	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2335
     *
2336
     * 	@param	array	$info		Info array loaded by _load_ldap_info
2337
     * 	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2338
     * 								1=Return parent (ou=xxx,dc=aaa,dc=bbb)
2339
     * 								2=Return key only (RDN) (uid=qqq)
2340
     * 	@return	string				DN
2341
     */
2342
    function _load_ldap_dn($info, $mode = 0)
2343
    {
2344
        // phpcs:enable
2345
        global $conf;
2346
        $dn = '';
2347
        if ($mode == 0)
2348
            $dn = $conf->global->LDAP_KEY_USERS . "=" . $info[$conf->global->LDAP_KEY_USERS] . "," . $conf->global->LDAP_USER_DN;
2349
        elseif ($mode == 1)
2350
            $dn = $conf->global->LDAP_USER_DN;
2351
        elseif ($mode == 2)
2352
            $dn = $conf->global->LDAP_KEY_USERS . "=" . $info[$conf->global->LDAP_KEY_USERS];
2353
        return $dn;
2354
    }
2355
2356
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2357
    /**
2358
     * 	Initialize the info array (array of LDAP values) that will be used to call LDAP functions
2359
     *
2360
     * 	@return		array		Tableau info des attributs
2361
     */
2362
    function _load_ldap_info()
2363
    {
2364
        // phpcs:enable
2365
        global $conf, $langs;
2366
2367
        $info = array();
2368
        $keymodified = false;
2369
2370
        // Object classes
2371
        $info["objectclass"] = explode(',', $conf->global->LDAP_USER_OBJECT_CLASS);
2372
2373
        $this->fullname = $this->getFullName($langs);
2374
2375
        // Possible LDAP KEY (constname => varname)
2376
        $ldapkey = array(
2377
            'LDAP_FIELD_FULLNAME' => 'fullname',
2378
            'LDAP_FIELD_NAME' => 'lastname',
2379
            'LDAP_FIELD_FIRSTNAME' => 'firstname',
2380
            'LDAP_FIELD_LOGIN' => 'login',
2381
            'LDAP_FIELD_LOGIN_SAMBA' => 'login',
2382
            'LDAP_FIELD_PHONE' => 'office_phone',
2383
            'LDAP_FIELD_MOBILE' => 'user_mobile',
2384
            'LDAP_FIELD_FAX' => 'office_fax',
2385
            'LDAP_FIELD_MAIL' => 'email',
2386
            'LDAP_FIELD_SID' => 'ldap_sid',
2387
            'LDAP_FIELD_SKYPE' => 'skype',
2388
            'LDAP_FIELD_TWITTER' => 'twitter',
2389
            'LDAP_FIELD_FACEBOOK' => 'facebook'
2390
        );
2391
2392
        // Champs
2393
        foreach ($ldapkey as $constname => $varname) {
2394
            if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2395
                $info[$conf->global->$constname] = $this->$varname;
2396
2397
                // Check if it is the LDAP key and if its value has been changed
2398
                if (!empty($conf->global->LDAP_KEY_USERS) && $conf->global->LDAP_KEY_USERS == $conf->global->$constname) {
2399
                    if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname)
2400
                        $keymodified = true; // For check if LDAP key has been modified
2401
                }
2402
            }
2403
        }
2404
        if ($this->address && !empty($conf->global->LDAP_FIELD_ADDRESS))
2405
            $info[$conf->global->LDAP_FIELD_ADDRESS] = $this->address;
2406
        if ($this->zip && !empty($conf->global->LDAP_FIELD_ZIP))
2407
            $info[$conf->global->LDAP_FIELD_ZIP] = $this->zip;
2408
        if ($this->town && !empty($conf->global->LDAP_FIELD_TOWN))
2409
            $info[$conf->global->LDAP_FIELD_TOWN] = $this->town;
2410
        if ($this->note_public && !empty($conf->global->LDAP_FIELD_DESCRIPTION))
2411
            $info[$conf->global->LDAP_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_public, 2);
2412
        if ($this->socid > 0) {
2413
            $soc = new Societe($this->db);
2414
            $soc->fetch($this->socid);
2415
2416
            $info[$conf->global->LDAP_FIELD_COMPANY] = $soc->name;
2417
            if ($soc->client == 1)
2418
                $info["businessCategory"] = "Customers";
2419
            if ($soc->client == 2)
2420
                $info["businessCategory"] = "Prospects";
2421
            if ($soc->fournisseur == 1)
2422
                $info["businessCategory"] = "Suppliers";
2423
        }
2424
2425
        // When password is modified
2426
        if (!empty($this->pass)) {
2427
            if (!empty($conf->global->LDAP_FIELD_PASSWORD))
2428
                $info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2429
            if (!empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED))
2430
                $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
2431
        }
2432
        // Set LDAP password if possible
2433
        elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') { // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2434
            if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2435
                // Just for the default MD5 !
2436
                if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2437
                    if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED)) {
2438
                        $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase_crypted, 5); // Create OpenLDAP MD5 password from Dolibarr MD5 password
2439
                    }
2440
                }
2441
            }
2442
            // Use $this->pass_indatabase value if exists
2443
            elseif (!empty($this->pass_indatabase)) {
2444
                if (!empty($conf->global->LDAP_FIELD_PASSWORD))
2445
                    $info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2446
                if (!empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED))
2447
                    $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
2448
            }
2449
        }
2450
2451
        if ($conf->global->LDAP_SERVER_TYPE == 'egroupware') {
2452
            $info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
2453
2454
            $info['uidnumber'] = $this->id;
2455
2456
            $info['phpgwTz'] = 0;
2457
            $info['phpgwMailType'] = 'INTERNET';
2458
            $info['phpgwMailHomeType'] = 'INTERNET';
2459
2460
            $info["phpgwContactTypeId"] = 'n';
2461
            $info["phpgwContactCatId"] = 0;
2462
            $info["phpgwContactAccess"] = "public";
2463
2464
            if (dol_strlen($this->egroupware_id) == 0) {
2465
                $this->egroupware_id = 1;
2466
            }
2467
2468
            $info["phpgwContactOwner"] = $this->egroupware_id;
2469
2470
            if ($this->email)
2471
                $info["rfc822Mailbox"] = $this->email;
2472
            if ($this->phone_mobile)
2473
                $info["phpgwCellTelephoneNumber"] = $this->phone_mobile;
2474
        }
2475
2476
        return $info;
2477
    }
2478
2479
    /**
2480
     *  Initialise an instance with random values.
2481
     *  Used to build previews or test instances.
2482
     * 	id must be 0 if object instance is a specimen.
2483
     *
2484
     *  @return	void
2485
     */
2486
    function initAsSpecimen()
2487
    {
2488
        global $user, $langs;
2489
2490
        $now = dol_now();
2491
2492
        // Initialise parametres
2493
        $this->id = 0;
2494
        $this->ref = 'SPECIMEN';
2495
        $this->specimen = 1;
2496
2497
        $this->lastname = 'DOLIBARR';
2498
        $this->firstname = 'SPECIMEN';
2499
        $this->gender = 'man';
2500
        $this->note = 'This is a note';
2501
        $this->email = '[email protected]';
2502
        $this->skype = 'skypepseudo';
2503
        $this->twitter = 'twitterpseudo';
2504
        $this->facebook = 'facebookpseudo';
2505
        $this->office_phone = '0999999999';
2506
        $this->office_fax = '0999999998';
2507
        $this->user_mobile = '0999999997';
2508
        $this->admin = 0;
2509
        $this->login = 'dolibspec';
2510
        $this->pass = 'dolibspec';
2511
        //$this->pass_indatabase='dolibspec';									Set after a fetch
2512
        //$this->pass_indatabase_crypted='e80ca5a88c892b0aaaf7e154853bccab';	Set after a fetch
2513
        $this->datec = $now;
2514
        $this->datem = $now;
2515
2516
        $this->datelastlogin = $now;
2517
        $this->datepreviouslogin = $now;
2518
        $this->statut = 1;
2519
2520
        //$this->societe_id = 1;	For external users
2521
        //$this->contact_id = 1;	For external users
2522
        $this->entity = 1;
2523
    }
2524
2525
    /**
2526
     *  Load info of user object
2527
     *
2528
     *  @param  int		$id     Id of user to load
2529
     *  @return	void
2530
     */
2531
    function info($id)
2532
    {
2533
        $sql = "SELECT u.rowid, u.login as ref, u.datec,";
2534
        $sql .= " u.tms as date_modification, u.entity";
2535
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2536
        $sql .= " WHERE u.rowid = " . $id;
2537
2538
        $result = $this->db->query($sql);
2539
        if ($result) {
2540
            if ($this->db->num_rows($result)) {
2541
                $obj = $this->db->fetch_object($result);
2542
2543
                $this->id = $obj->rowid;
2544
2545
                $this->ref = (!$obj->ref) ? $obj->rowid : $obj->ref;
2546
                $this->date_creation = $this->db->jdate($obj->datec);
2547
                $this->date_modification = $this->db->jdate($obj->date_modification);
2548
                $this->entity = $obj->entity;
2549
            }
2550
2551
            $this->db->free($result);
2552
        } else {
2553
            dol_print_error($this->db);
2554
        }
2555
    }
2556
2557
    /**
2558
     *    Return number of mass Emailing received by this contacts with its email
2559
     *
2560
     *    @return       int     Number of EMailings
2561
     */
2562
    function getNbOfEMailings()
2563
    {
2564
        $sql = "SELECT count(mc.email) as nb";
2565
        $sql .= " FROM " . MAIN_DB_PREFIX . "mailing_cibles as mc";
2566
        $sql .= " WHERE mc.email = '" . $this->db->escape($this->email) . "'";
2567
        $sql .= " AND mc.statut NOT IN (-1,0)";      // -1 erreur, 0 non envoye, 1 envoye avec succes
2568
2569
        $resql = $this->db->query($sql);
2570
        if ($resql) {
2571
            $obj = $this->db->fetch_object($resql);
2572
            $nb = $obj->nb;
2573
2574
            $this->db->free($resql);
2575
            return $nb;
2576
        } else {
2577
            $this->error = $this->db->error();
2578
            return -1;
2579
        }
2580
    }
2581
2582
    /**
2583
     *  Return number of existing users
2584
     *
2585
     *  @param	string	$limitTo	Limit to '' or 'active'
2586
     *  @param	string	$option		'superadmin' = return for entity 0 only
2587
     *  @param	int		$admin		Filter on admin tag
2588
     *  @return int  				Number of users
2589
     */
2590
    function getNbOfUsers($limitTo, $option = '', $admin = -1)
2591
    {
2592
        global $conf;
2593
2594
        $sql = "SELECT count(rowid) as nb";
2595
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
2596
        if ($option == 'superadmin') {
2597
            $sql .= " WHERE entity = 0";
2598
            if ($admin >= 0)
2599
                $sql .= " AND admin = " . $admin;
2600
        }
2601
        else {
2602
            $sql .= " WHERE entity IN (" . getEntity('user', 0) . ")";
2603
            if ($limitTo == 'active')
2604
                $sql .= " AND statut = 1";
2605
            if ($admin >= 0)
2606
                $sql .= " AND admin = " . $admin;
2607
        }
2608
2609
        $resql = $this->db->query($sql);
2610
        if ($resql) {
2611
            $obj = $this->db->fetch_object($resql);
2612
            $nb = $obj->nb;
2613
2614
            $this->db->free($resql);
2615
            return $nb;
2616
        } else {
2617
            $this->error = $this->db->lasterror();
2618
            return -1;
2619
        }
2620
    }
2621
2622
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2623
    /**
2624
     *  Update user using data from the LDAP
2625
     *
2626
     *  @param	ldapuser	$ldapuser	Ladp User
2627
     *
2628
     *  @return int  				<0 if KO, >0 if OK
2629
     */
2630
    function update_ldap2dolibarr(&$ldapuser)
2631
    {
2632
        // phpcs:enable
2633
        // TODO: Voir pourquoi le update met à jour avec toutes les valeurs vide (global $user écrase ?)
2634
        global $user, $conf;
2635
2636
        $this->firstname = $ldapuser->{$conf->global->LDAP_FIELD_FIRSTNAME};
2637
        $this->lastname = $ldapuser->{$conf->global->LDAP_FIELD_NAME};
2638
        $this->login = $ldapuser->{$conf->global->LDAP_FIELD_LOGIN};
2639
        $this->pass = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD};
2640
        $this->pass_indatabase_crypted = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD_CRYPTED};
2641
2642
        $this->office_phone = $ldapuser->{$conf->global->LDAP_FIELD_PHONE};
2643
        $this->user_mobile = $ldapuser->{$conf->global->LDAP_FIELD_MOBILE};
2644
        $this->office_fax = $ldapuser->{$conf->global->LDAP_FIELD_FAX};
2645
        $this->email = $ldapuser->{$conf->global->LDAP_FIELD_MAIL};
2646
        $this->skype = $ldapuser->{$conf->global->LDAP_FIELD_SKYPE};
2647
        $this->twitter = $ldapuser->{$conf->global->LDAP_FIELD_TWITTER};
2648
        $this->facebook = $ldapuser->{$conf->global->LDAP_FIELD_FACEBOOK};
2649
        $this->ldap_sid = $ldapuser->{$conf->global->LDAP_FIELD_SID};
2650
2651
        $this->job = $ldapuser->{$conf->global->LDAP_FIELD_TITLE};
2652
        $this->note = $ldapuser->{$conf->global->LDAP_FIELD_DESCRIPTION};
2653
2654
        $result = $this->update($user);
2655
2656
        dol_syslog(get_class($this) . "::update_ldap2dolibarr result=" . $result, LOG_DEBUG);
2657
2658
        return $result;
2659
    }
2660
2661
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2662
    /**
2663
     * Return and array with all instanciated first level children users of current user
2664
     *
2665
     * @return	void
2666
     * @see getAllChildIds
2667
     */
2668
    function get_children()
2669
    {
2670
        // phpcs:enable
2671
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "user";
2672
        $sql .= " WHERE fk_user = " . $this->id;
2673
2674
        dol_syslog(get_class($this) . "::get_children result=" . $result, LOG_DEBUG);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result seems to be never defined.
Loading history...
2675
        $res = $this->db->query($sql);
2676
        if ($res) {
2677
            $users = array();
2678
            while ($rec = $this->db->fetch_array($res)) {
2679
                $user = new User($this->db);
2680
                $user->fetch($rec['rowid']);
2681
                $users[] = $user;
2682
            }
2683
            return $users;
2684
        } else {
2685
            dol_print_error($this->db);
2686
            return -1;
2687
        }
2688
    }
2689
2690
    /**
2691
     * 	Load this->parentof that is array(id_son=>id_parent, ...)
2692
     *
2693
     * 	@return		int		<0 if KO, >0 if OK
2694
     */
2695
    private function loadParentOf()
2696
    {
2697
        global $conf;
2698
2699
        $this->parentof = array();
2700
2701
        // Load array[child]=parent
2702
        $sql = "SELECT fk_user as id_parent, rowid as id_son";
2703
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
2704
        $sql .= " WHERE fk_user <> 0";
2705
        $sql .= " AND entity IN (" . getEntity('user') . ")";
2706
2707
        dol_syslog(get_class($this) . "::loadParentOf", LOG_DEBUG);
2708
        $resql = $this->db->query($sql);
2709
        if ($resql) {
2710
            while ($obj = $this->db->fetch_object($resql)) {
2711
                $this->parentof[$obj->id_son] = $obj->id_parent;
2712
            }
2713
            return 1;
2714
        } else {
2715
            dol_print_error($this->db);
2716
            return -1;
2717
        }
2718
    }
2719
2720
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2721
    /**
2722
     * 	Reconstruit l'arborescence hierarchique des users sous la forme d'un tableau
2723
     * 	Set and return this->users that is an array sorted according to tree with arrays of:
2724
     * 				id = id user
2725
     * 				lastname
2726
     * 				firstname
2727
     * 				fullname = nom avec chemin complet du user
2728
     * 				fullpath = chemin complet compose des id: "_grandparentid_parentid_id"
2729
     *
2730
     *  @param      int		$deleteafterid      Removed all users including the leaf $deleteafterid (and all its child) in user tree.
2731
     *  @param		string	$filter				SQL filter on users
2732
     * 	@return		array		      		  	Array of users $this->users. Note: $this->parentof is also set.
2733
     */
2734
    function get_full_tree($deleteafterid = 0, $filter = '')
2735
    {
2736
        // phpcs:enable
2737
        global $conf, $user;
2738
        global $hookmanager;
2739
2740
        // Actions hooked (by external module)
2741
        $hookmanager->initHooks(array('userdao'));
2742
2743
        $this->users = array();
2744
2745
        // Init this->parentof that is array(id_son=>id_parent, ...)
2746
        $this->loadParentOf();
2747
2748
        // Init $this->users array
2749
        $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
2750
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2751
        // Add fields from hooks
2752
        $parameters = array();
2753
        $reshook = $hookmanager->executeHooks('printUserListWhere', $parameters);    // Note that $action and $object may have been modified by hook
2754
        if ($reshook > 0) {
2755
            $sql .= $hookmanager->resPrint;
2756
        } else {
2757
            $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2758
        }
2759
        if ($filter)
2760
            $sql .= " AND " . $filter;
2761
2762
        dol_syslog(get_class($this) . "::get_full_tree get user list", LOG_DEBUG);
2763
        $resql = $this->db->query($sql);
2764
        if ($resql) {
2765
            $i = 0;
2766
            while ($obj = $this->db->fetch_object($resql)) {
2767
                $this->users[$obj->rowid]['rowid'] = $obj->rowid;
2768
                $this->users[$obj->rowid]['id'] = $obj->rowid;
2769
                $this->users[$obj->rowid]['fk_user'] = $obj->fk_user;
2770
                $this->users[$obj->rowid]['fk_soc'] = $obj->fk_soc;
2771
                $this->users[$obj->rowid]['firstname'] = $obj->firstname;
2772
                $this->users[$obj->rowid]['lastname'] = $obj->lastname;
2773
                $this->users[$obj->rowid]['login'] = $obj->login;
2774
                $this->users[$obj->rowid]['statut'] = $obj->statut;
2775
                $this->users[$obj->rowid]['entity'] = $obj->entity;
2776
                $this->users[$obj->rowid]['email'] = $obj->email;
2777
                $this->users[$obj->rowid]['gender'] = $obj->gender;
2778
                $this->users[$obj->rowid]['admin'] = $obj->admin;
2779
                $this->users[$obj->rowid]['photo'] = $obj->photo;
2780
                $i++;
2781
            }
2782
        } else {
2783
            dol_print_error($this->db);
2784
            return -1;
2785
        }
2786
2787
        // We add the fullpath property to each elements of first level (no parent exists)
2788
        dol_syslog(get_class($this) . "::get_full_tree call to build_path_from_id_user", LOG_DEBUG);
2789
        foreach ($this->users as $key => $val) {
2790
            $result = $this->build_path_from_id_user($key, 0); // Process a branch from the root user key (this user has no parent)
2791
            if ($result < 0) {
2792
                $this->error = 'ErrorLoopInHierarchy';
2793
                return -1;
2794
            }
2795
        }
2796
2797
        // Exclude leaf including $deleteafterid from tree
2798
        if ($deleteafterid) {
2799
            //print "Look to discard user ".$deleteafterid."\n";
2800
            $keyfilter1 = '^' . $deleteafterid . '$';
2801
            $keyfilter2 = '_' . $deleteafterid . '$';
2802
            $keyfilter3 = '^' . $deleteafterid . '_';
2803
            $keyfilter4 = '_' . $deleteafterid . '_';
2804
            foreach ($this->users as $key => $val) {
2805
                if (preg_match('/' . $keyfilter1 . '/', $val['fullpath']) || preg_match('/' . $keyfilter2 . '/', $val['fullpath']) || preg_match('/' . $keyfilter3 . '/', $val['fullpath']) || preg_match('/' . $keyfilter4 . '/', $val['fullpath'])) {
2806
                    unset($this->users[$key]);
2807
                }
2808
            }
2809
        }
2810
2811
        dol_syslog(get_class($this) . "::get_full_tree dol_sort_array", LOG_DEBUG);
2812
        $this->users = dol_sort_array($this->users, 'fullname', 'asc', true, false);
2813
2814
        //var_dump($this->users);
2815
2816
        return $this->users;
2817
    }
2818
2819
    /**
2820
     * 	Return list of all child users id in herarchy (all sublevels).
2821
     *  Note: Calling this function also reset full list of users into $this->users.
2822
     *
2823
     *  @param      int      $addcurrentuser    1=Add also current user id to the list.
2824
     * 	@return		array		      		  	Array of user id lower than user (all levels under user). This overwrite this->users.
2825
     *  @see get_children
2826
     */
2827
    function getAllChildIds($addcurrentuser = 0)
2828
    {
2829
        $childids = array();
2830
2831
        if (isset($this->cache_childids[$this->id])) {
2832
            $childids = $this->cache_childids[$this->id];
2833
        } else {
2834
            // Init this->users
2835
            $this->get_full_tree();
2836
2837
            $idtoscan = $this->id;
2838
2839
            dol_syslog("Build childid for id = " . $idtoscan);
2840
            foreach ($this->users as $id => $val) {
2841
                //var_dump($val['fullpath']);
2842
                if (preg_match('/_' . $idtoscan . '_/', $val['fullpath']))
2843
                    $childids[$val['id']] = $val['id'];
2844
            }
2845
        }
2846
        $this->cache_childids[$this->id] = $childids;
2847
2848
        if ($addcurrentuser)
2849
            $childids[$this->id] = $this->id;
2850
2851
        return $childids;
2852
    }
2853
2854
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2855
    /**
2856
     * 	For user id_user and its childs available in this->users, define property fullpath and fullname.
2857
     *  Function called by get_full_tree().
2858
     *
2859
     * 	@param		int		$id_user		id_user entry to update
2860
     * 	@param		int		$protection		Deep counter to avoid infinite loop (no more required, a protection is added with array useridfound)
2861
     * 	@return		int                     < 0 if KO (infinit loop), >= 0 if OK
2862
     */
2863
    function build_path_from_id_user($id_user, $protection = 0)
2864
    {
2865
        // phpcs:enable
2866
        dol_syslog(get_class($this) . "::build_path_from_id_user id_user=" . $id_user . " protection=" . $protection, LOG_DEBUG);
2867
2868
        if (!empty($this->users[$id_user]['fullpath'])) {
2869
            // Already defined
2870
            dol_syslog(get_class($this) . "::build_path_from_id_user fullpath and fullname already defined", LOG_WARNING);
2871
            return 0;
2872
        }
2873
2874
        // Define fullpath and fullname
2875
        $this->users[$id_user]['fullpath'] = '_' . $id_user;
2876
        $this->users[$id_user]['fullname'] = $this->users[$id_user]['lastname'];
2877
        $i = 0;
2878
        $cursor_user = $id_user;
2879
2880
        $useridfound = array($id_user);
2881
        while (!empty($this->parentof[$cursor_user])) {
2882
            if (in_array($this->parentof[$cursor_user], $useridfound)) {
2883
                dol_syslog("The hierarchy of user has a recursive loop", LOG_WARNING);
2884
                return -1;     // Should not happen. Protection against looping hierarchy
2885
            }
2886
            $useridfound[] = $this->parentof[$cursor_user];
2887
            $this->users[$id_user]['fullpath'] = '_' . $this->parentof[$cursor_user] . $this->users[$id_user]['fullpath'];
2888
            $this->users[$id_user]['fullname'] = $this->users[$this->parentof[$cursor_user]]['lastname'] . ' >> ' . $this->users[$id_user]['fullname'];
2889
            $i++;
2890
            $cursor_user = $this->parentof[$cursor_user];
2891
        }
2892
2893
        // We count number of _ to have level
2894
        $this->users[$id_user]['level'] = dol_strlen(preg_replace('/[^_]/i', '', $this->users[$id_user]['fullpath']));
2895
2896
        return 1;
2897
    }
2898
2899
    /**
2900
     * Function used to replace a thirdparty id with another one.
2901
     *
2902
     * @param DoliDB $db Database handler
2903
     * @param int $origin_id Old thirdparty id
2904
     * @param int $dest_id New thirdparty id
2905
     * @return bool
2906
     */
2907
    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2908
    {
2909
        $tables = array(
2910
            'user',
2911
        );
2912
2913
        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2914
    }
2915
2916
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2917
    /**
2918
     *      Charge indicateurs this->nb pour le tableau de bord
2919
     *
2920
     *      @return     int         <0 if KO, >0 if OK
2921
     */
2922
    function load_state_board()
2923
    {
2924
        // phpcs:enable
2925
        global $conf;
2926
2927
        $this->nb = array();
2928
2929
        $sql = "SELECT count(u.rowid) as nb";
2930
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2931
        $sql .= " WHERE u.statut > 0";
2932
        //$sql.= " AND employee != 0";
2933
        $sql .= " AND u.entity IN (" . getEntity('user') . ")";
2934
2935
        $resql = $this->db->query($sql);
2936
        if ($resql) {
2937
            while ($obj = $this->db->fetch_object($resql)) {
2938
                $this->nb["users"] = $obj->nb;
2939
            }
2940
            $this->db->free($resql);
2941
            return 1;
2942
        } else {
2943
            dol_print_error($this->db);
2944
            $this->error = $this->db->error();
2945
            return -1;
2946
        }
2947
    }
2948
2949
    /**
2950
     *  Create a document onto disk according to template module.
2951
     *
2952
     * 	@param	    string		$modele			Force model to use ('' to not force)
2953
     * 	@param		Translate	$outputlangs	Object langs to use for output
2954
     *  @param      int			$hidedetails    Hide details of lines
2955
     *  @param      int			$hidedesc       Hide description
2956
     *  @param      int			$hideref        Hide ref
2957
     *  @param   null|array  $moreparams     Array to provide more information
2958
     * 	@return     int         				0 if KO, 1 if OK
2959
     */
2960
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2961
    {
2962
        global $conf, $user, $langs;
2963
2964
        $langs->load("user");
2965
2966
        // Positionne le modele sur le nom du modele a utiliser
2967
        if (!dol_strlen($modele)) {
2968
            if (!empty($conf->global->USER_ADDON_PDF)) {
2969
                $modele = $conf->global->USER_ADDON_PDF;
2970
            } else {
2971
                $modele = 'bluesky';
2972
            }
2973
        }
2974
2975
        $modelpath = "core/modules/user/doc/";
2976
2977
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2978
    }
2979
2980
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2981
    /**
2982
     *  Return property of user from its id
2983
     *
2984
     *  @param	int		$rowid      id of contact
2985
     *  @param  string	$mode       'email' or 'mobile'
2986
     *  @return string  			Email of user with format: "Full name <email>"
2987
     */
2988
    function user_get_property($rowid, $mode)
2989
    {
2990
        // phpcs:enable
2991
        $user_property = '';
2992
2993
        if (empty($rowid))
2994
            return '';
2995
2996
        $sql = "SELECT rowid, email, user_mobile, civility, lastname, firstname";
2997
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
2998
        $sql .= " WHERE rowid = '" . $rowid . "'";
2999
3000
        $resql = $this->db->query($sql);
3001
        if ($resql) {
3002
            $nump = $this->db->num_rows($resql);
3003
3004
            if ($nump) {
3005
                $obj = $this->db->fetch_object($resql);
3006
3007
                if ($mode == 'email')
3008
                    $user_property = dolGetFirstLastname($obj->firstname, $obj->lastname) . " <" . $obj->email . ">";
3009
                else if ($mode == 'mobile')
3010
                    $user_property = $obj->user_mobile;
3011
            }
3012
            return $user_property;
3013
        }
3014
        else {
3015
            dol_print_error($this->db);
3016
        }
3017
    }
3018
3019
    /**
3020
     * 	Load all objects into $this->users
3021
     *
3022
     *  @param	string		$sortorder		sort order
3023
     *  @param	string		$sortfield		sort field
3024
     *  @param	int			$limit			limit page
3025
     *  @param	int			$offset			page
3026
     *  @param	array		$filter			Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
3027
     *  @param  string      $filtermode		Filter mode (AND or OR)
3028
     *  @return int							<0 if KO, >0 if OK
3029
     */
3030
    function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = array(), $filtermode = 'AND')
3031
    {
3032
        global $conf;
3033
3034
        $sql = "SELECT t.rowid";
3035
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t ';
3036
        $sql .= " WHERE 1";
3037
3038
        // Manage filter
3039
        $sqlwhere = array();
3040
        if (!empty($filter)) {
3041
            foreach ($filter as $key => $value) {
3042
                if ($key == 't.rowid') {
3043
                    $sqlwhere[] = $key . '=' . $value;
3044
                } elseif (strpos($key, 'date') !== false) {
3045
                    $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\'';
3046
                } elseif ($key == 'customsql') {
3047
                    $sqlwhere[] = $value;
3048
                } else {
3049
                    $sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\'';
3050
                }
3051
            }
3052
        }
3053
        if (count($sqlwhere) > 0) {
3054
            $sql .= ' AND (' . implode(' ' . $filtermode . ' ', $sqlwhere) . ')';
3055
        }
3056
        $sql .= $this->db->order($sortfield, $sortorder);
3057
        if ($limit)
3058
            $sql .= $this->db->plimit($limit + 1, $offset);
3059
3060
        dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
3061
3062
        $resql = $this->db->query($sql);
3063
        if ($resql) {
3064
            $this->users = array();
3065
            $num = $this->db->num_rows($resql);
3066
            if ($num) {
3067
                while ($obj = $this->db->fetch_object($resql)) {
3068
                    $line = new self($this->db);
3069
                    $result = $line->fetch($obj->rowid);
3070
                    if ($result > 0 && !empty($line->id)) {
3071
                        $this->users[$obj->rowid] = clone $line;
3072
                    }
3073
                }
3074
                $this->db->free($resql);
3075
            }
3076
            return $num;
3077
        } else {
3078
            $this->errors[] = $this->db->lasterror();
3079
            return -1;
3080
        }
3081
    }
3082
}
3083