Passed
Pull Request — master (#2)
by
unknown
26:19
created

User::getNomUrl()   F

Complexity

Conditions 50
Paths > 20000

Size

Total Lines 159
Code Lines 106

Duplication

Lines 0
Ratio 0 %

Importance

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