Issues (2380)

Base/User.php (27 issues)

1
<?php
2
/* Copyright (C) 2018       Alxarafe            <[email protected]>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
namespace Alixar\Base;
18
19
use Alixar\Helpers\AlDolUtils;
20
use Alxarafe\Helpers\Config;
21
use Alixar\Base\AlCommonObject;
22
use Alixar\Helpers\Globals;
23
24
class User extends AlCommonObject
25
{
26
27
    /**
28
     * @var string ID to identify managed object
29
     */
30
    public $element = 'user';
31
32
    /**
33
     * @var string Name of table without prefix where object is stored
34
     */
35
    public $table_element = 'user';
36
37
    /**
38
     * @var int Field with ID of parent key if this field has a parent
39
     */
40
    public $fk_element = 'fk_user';
41
42
    /**
43
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
44
     * @var int
45
     */
46
    public $ismultientitymanaged = 1;
47
    public $id = 0;
48
    public $statut;
49
    public $ldap_sid;
50
    public $search_sid;
51
    public $employee;
52
    public $gender;
53
    public $birth;
54
    public $email;
55
    public $skype;
56
    public $twitter;
57
    public $facebook;
58
    public $job;   // job position
59
    public $signature;
60
61
    /**
62
     * @var string Address
63
     */
64
    public $address;
65
    public $zip;
66
    public $town;
67
    public $state_id;  // The state/department
68
    public $state_code;
69
    public $state;
70
    public $office_phone;
71
    public $office_fax;
72
    public $user_mobile;
73
    public $admin;
74
    public $login;
75
    public $api_key;
76
77
    /**
78
     * @var int Entity
79
     */
80
    public $entity;
81
//! Clear password in memory
82
    public $pass;
83
//! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
84
    public $pass_indatabase;
85
//! Encrypted password in database (always defined)
86
    public $pass_indatabase_crypted;
87
    public $datec;
88
    public $datem;
89
//! If this is defined, it is an external user
90
    /**
91
     * @deprecated
92
     * @see socid
93
     */
94
    public $societe_id;
95
96
    /**
97
     * @deprecated
98
     * @see contactid
99
     */
100
    public $contact_id;
101
    public $socid;
102
    public $contactid;
103
104
    /**
105
     * @var int ID
106
     */
107
    public $fk_member;
108
109
    /**
110
     * @var int User ID
111
     */
112
    public $fk_user;
113
    public $clicktodial_url;
114
    public $clicktodial_login;
115
    public $clicktodial_password;
116
    public $clicktodial_poste;
117
    public $datelastlogin;
118
    public $datepreviouslogin;
119
    public $photo;
120
    public $lang;
121
    public $rights;                        // Array of permissions user->rights->permx
122
    public $all_permissions_are_loaded;    // All permission are loaded
123
    public $nb_rights;              // Number of rights granted to the user
124
    private $_tab_loaded = array();     // Cache array of already loaded permissions
125
    public $conf;             // To store personal config
126
    public $default_values;         // To store default values for user
127
    public $lastsearch_values_tmp;  // To store current search criterias for user
128
    public $lastsearch_values;      // To store last saved search criterias for user
129
    public $users = array();  // To store all tree of users hierarchy
130
    public $parentof;    // To store an array of all parents for all ids.
131
    private $cache_childids;
132
    public $accountancy_code;   // Accountancy code in prevision of the complete accountancy module
133
    public $thm;     // Average cost of employee - Used for valuation of time spent
134
    public $tjm;     // Average cost of employee
135
    public $salary;     // Monthly salary       - Denormalized value from llx_user_employment
136
    public $salaryextra;    // Monthly salary extra - Denormalized value from llx_user_employment
137
    public $weeklyhours;    // Weekly hours         - Denormalized value from llx_user_employment
138
    public $color;      // Define background color for user in agenda
139
    public $dateemployment;   // Define date of employment by company
140
    public $dateemploymentend;  // Define date of employment end by company
141
    public $default_c_exp_tax_cat;
142
    public $default_range;
143
    public $fields = array(
144
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
145
        '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'),
146
        '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'),
147
    );
148
149
    /**
150
     *    Constructor of the class
151
     *
152
     *    @param   DoliDb  $db     Database handler
0 ignored issues
show
The type Alixar\Base\DoliDb was not found. Did you mean DoliDb? If so, make sure to prefix the type with \.
Loading history...
153
     */
154
    function __construct()
155
    {
156
// User preference
157
        $this->liste_limit = 0;
158
        $this->clicktodial_loaded = 0;
159
160
// For cache usage
161
        $this->all_permissions_are_loaded = 0;
162
        $this->nb_rights = 0;
163
164
// Force some default values
165
        $this->admin = 0;
166
        $this->employee = 1;
167
168
        $this->conf = new \stdClass();
169
        $this->rights = new \stdClass();
170
        $this->rights->user = new \stdClass();
171
        $this->rights->user->user = new \stdClass();
172
        $this->rights->user->self = new \stdClass();
173
    }
174
175
    /**
176
     * 	Load a user from database with its id or ref (login).
177
     *  This function does not load permissions, only user properties. Use getrights() for this just after the fetch.
178
     *
179
     * 	@param	int		$id		       		If defined, id to used for search
180
     * 	@param  string	$login       		If defined, login to used for search
181
     * 	@param  string	$sid				If defined, sid to used for search
182
     * 	@param	int		$loadpersonalconf	1=also load personal conf of user (in Globals::$user->conf->xxx), 0=do not load personal conf.
183
     *  @param  int     $entity             If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup.
184
     * 	@return	int							<0 if KO, 0 not found, >0 if OK
185
     */
186
    function fetch($id = '', $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1)
187
    {
188
// global $conf, Globals::$user;
189
// Clean parameters
190
        $login = trim($login);
191
192
// Get user
193
        $sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.birth, u.email, u.job, u.skype, u.twitter, u.facebook,";
194
        $sql .= " u.signature, u.office_phone, u.office_fax, u.user_mobile,";
195
        $sql .= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
196
        $sql .= " u.admin, u.login, u.note,";
197
        $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,";
198
        $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid,";
199
        $sql .= " u.statut, u.lang, u.entity,";
200
        $sql .= " u.datec as datec,";
201
        $sql .= " u.tms as datem,";
202
        $sql .= " u.datelastlogin as datel,";
203
        $sql .= " u.datepreviouslogin as datep,";
204
        $sql .= " u.photo as photo,";
205
        $sql .= " u.openid as openid,";
206
        $sql .= " u.accountancy_code,";
207
        $sql .= " u.thm,";
208
        $sql .= " u.tjm,";
209
        $sql .= " u.salary,";
210
        $sql .= " u.salaryextra,";
211
        $sql .= " u.weeklyhours,";
212
        $sql .= " u.color,";
213
        $sql .= " u.dateemployment, u.dateemploymentend,";
214
        $sql .= " u.ref_int, u.ref_ext,";
215
        $sql .= " u.default_range, u.default_c_exp_tax_cat,";   // Expense report default mode
216
        $sql .= " c.code as country_code, c.label as country,";
217
        $sql .= " d.code_departement as state_code, d.nom as state";
218
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
219
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid";
220
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_departements as d ON u.fk_state = d.rowid";
221
222
        if ($entity < 0) {
223
            if ((empty(Globals::$conf->multicompany->enabled) || empty(Globals::$conf->global->MULTICOMPANY_TRANSVERSE_MODE)) && (!empty(Globals::$user->entity))) {
224
                $sql .= " WHERE u.entity IN (0," . Globals::$conf->entity . ")";
225
            } else {
226
                $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
227
            }
228
        } else {  // The fetch was forced on an entity
229
            if (!empty(Globals::$conf->multicompany->enabled) && !empty(Globals::$conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
230
                $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
231
            } else {
232
                $sql .= " WHERE u.entity IN (0, " . (($entity != '' && $entity >= 0) ? $entity : Globals::$conf->entity) . ")";   // search in entity provided in parameter
233
            }
234
        }
235
236
        if ($sid) {    // permet une recherche du user par son SID ActiveDirectory ou Samba
237
//$sql .= " AND (u.ldap_sid = '" . Config::$dbEngine->escape($sid) . "' OR u.login = '" . Config::$dbEngine->escape($login) . "') LIMIT 1";
238
            $sql .= " AND (u.ldap_sid = '" . $sid . "' OR u.login = '" . Config::$dbEngine->escape($login) . "') LIMIT 1";
239
        } else if ($login) {
240
// $sql .= " AND u.login = '" . Config::$dbEngine->escape($login) . "'";
241
            $sql .= " AND u.login = '" . $login . "'";
242
        } else {
243
            $sql .= " AND u.rowid = " . $id;
244
        }
245
        $sql .= " ORDER BY u.entity ASC";    // Avoid random result when there is 2 login in 2 different entities
246
247
        $result = Config::$dbEngine->select($sql);
248
// echo "<p>SQL in 2477 of User: '$sql'</p>";
249
        if ($result) {
250
            if (count($result) > 0) {
251
252
// Convert array to stdclass
253
                $obj = json_decode(json_encode($result[0]));
254
255
                $this->id = $obj->rowid;
256
                $this->ref = $obj->rowid;
257
258
                $this->ref_int = $obj->ref_int;
259
                $this->ref_ext = $obj->ref_ext;
260
261
                $this->ldap_sid = $obj->ldap_sid;
262
                $this->lastname = $obj->lastname;
263
                $this->firstname = $obj->firstname;
264
265
                $this->employee = $obj->employee;
266
267
                $this->login = $obj->login;
268
                $this->gender = $obj->gender;
269
// $this->birth = Config::$dbEngine->jdate($obj->birth);
270
                $this->birth = $obj->birth;
271
272
                $this->pass_indatabase = $obj->pass;
273
                $this->pass_indatabase_crypted = $obj->pass_crypted;
274
                $this->pass = $obj->pass;
275
                $this->pass_temp = $obj->pass_temp;
276
                $this->api_key = $obj->api_key;
277
278
                $this->address = $obj->address;
279
                $this->zip = $obj->zip;
280
                $this->town = $obj->town;
281
282
                $this->country_id = $obj->country_id;
283
                $this->country_code = $obj->country_id ? $obj->country_code : '';
284
//$this->country 		= $obj->country_id?(Globals::$langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?Globals::$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
285
286
                $this->state_id = $obj->state_id;
287
                $this->state_code = $obj->state_code;
288
                $this->state = ($obj->state != '-' ? $obj->state : '');
289
290
                $this->office_phone = $obj->office_phone;
291
                $this->office_fax = $obj->office_fax;
292
                $this->user_mobile = $obj->user_mobile;
293
                $this->email = $obj->email;
294
                $this->skype = $obj->skype;
295
                $this->twitter = $obj->twitter;
296
                $this->facebook = $obj->facebook;
297
                $this->job = $obj->job;
298
                $this->signature = $obj->signature;
299
                $this->admin = $obj->admin;
300
                $this->note = $obj->note;
301
                $this->statut = $obj->statut;
302
                $this->photo = $obj->photo;
303
                $this->openid = $obj->openid;
304
                $this->lang = $obj->lang;
305
                $this->entity = $obj->entity;
306
                $this->accountancy_code = $obj->accountancy_code;
307
                $this->thm = $obj->thm;
308
                $this->tjm = $obj->tjm;
309
                $this->salary = $obj->salary;
310
                $this->salaryextra = $obj->salaryextra;
311
                $this->weeklyhours = $obj->weeklyhours;
312
                $this->color = $obj->color;
313
314
                /*
315
                  $this->dateemployment = Config::$dbEngine->jdate($obj->dateemployment);
316
                  $this->dateemploymentend = Config::$dbEngine->jdate($obj->dateemploymentend);
317
318
                  $this->datec = Config::$dbEngine->jdate($obj->datec);
319
                  $this->datem = Config::$dbEngine->jdate($obj->datem);
320
                  $this->datelastlogin = Config::$dbEngine->jdate($obj->datel);
321
                  $this->datepreviouslogin = Config::$dbEngine->jdate($obj->datep);
322
                 */
323
                $this->dateemployment = $obj->dateemployment;
324
                $this->dateemploymentend = $obj->dateemploymentend;
325
326
                $this->datec = $obj->datec;
327
                $this->datem = $obj->datem;
328
                $this->datelastlogin = $obj->datel;
329
                $this->datepreviouslogin = $obj->datep;
330
331
                $this->societe_id = $obj->fk_soc;  // deprecated
332
                $this->contact_id = $obj->fk_socpeople; // deprecated
333
                $this->socid = $obj->fk_soc;
334
                $this->contactid = $obj->fk_socpeople;
335
                $this->fk_member = $obj->fk_member;
336
                $this->fk_user = $obj->fk_user;
337
338
                $this->default_range = $obj->default_range;
339
                $this->default_c_exp_tax_cat = $obj->default_c_exp_tax_cat;
340
341
// Protection when module multicompany was set, admin was set to first entity and then, the module was disabled,
342
// in such case, this admin user must be admin for ALL entities.
343
                if (empty(Globals::$conf->multicompany->enabled) && $this->admin && $this->entity == 1) {
344
                    $this->entity = 0;
345
                }
346
347
// Retreive all extrafield
348
// fetch optionals attributes and labels
349
                $this->fetch_optionals();
350
            } else {
351
                $this->error = "USERNOTFOUND";
352
                AlDolUtils::dol_syslog(get_class($this) . "::fetch user not found", LOG_DEBUG);
353
                return 0;
354
            }
355
        } else {
356
            $this->error = Config::$dbEngine->lasterror();
357
            return -1;
358
        }
359
360
// To get back the global configuration unique to the user
361
        if ($loadpersonalconf) {
362
// Load user->conf for user
363
            $sql = "SELECT param, value FROM " . MAIN_DB_PREFIX . "user_param";
364
            $sql .= " WHERE fk_user = " . $this->id;
365
            $sql .= " AND entity = " . Globals::$conf->entity;
366
//DolUtils::dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
367
            $resql = Config::$dbEngine->select($sql);
368
            if (is_array($resql)) {
369
                foreach ($resql as $array) {
370
                    $obj = json_decode(json_encode($array));
371
372
                    $p = (!empty($obj->param) ? $obj->param : '');
373
                    if (!empty($p)) {
374
                        $this->conf->$p = $obj->value;
375
                    }
376
                }
377
            } else {
378
// $this->error = Config::$dbEngine->lasterror();
379
                return -2;
380
            }
381
382
            $result = $this->loadDefaultValues();
383
384
            if ($result < 0) {
385
// $this->error = Config::$dbEngine->lasterror();
386
                return -3;
387
            }
388
        }
389
390
        return 1;
391
    }
392
393
    /**
394
     *  Load default value in property ->default_values
395
     *
396
     *  @return int						> 0 if OK, < 0 if KO
397
     */
398
    function loadDefaultValues()
399
    {
400
// global $conf;
401
// Load user->default_values for user. TODO Save this in memcached ?
402
        $sql = "SELECT rowid, entity, type, page, param, value";
403
        $sql .= " FROM " . MAIN_DB_PREFIX . "default_values";
404
        $sql .= " WHERE entity IN (" . ($this->entity > 0 ? $this->entity . ", " : "") . Globals::$conf->entity . ")"; // Entity of user (if defined) + current entity
405
        $sql .= " AND user_id IN (0" . ($this->id > 0 ? ", " . $this->id : "") . ")";       // User 0 (all) + me (if defined)
406
        $resql = Config::$dbEngine->select($sql);
407
        if (is_array($resql)) {
408
            foreach ($resql as $array) {
409
                $obj = json_decode(json_encode($array));
410
411
                $pagewithoutquerystring = $obj->page;
412
                $pagequeries = '';
413
                if (preg_match('/^([^\?]+)\?(.*)$/', $pagewithoutquerystring, $reg)) { // There is query param
414
                    $pagewithoutquerystring = $reg[1];
415
                    $pagequeries = $reg[2];
416
                }
417
                $this->default_values[$pagewithoutquerystring][$obj->type][$pagequeries ? $pagequeries : '_noquery_'][$obj->param] = $obj->value;
418
//if ($pagequeries) $this->default_values[$pagewithoutquerystring][$obj->type.'_queries']=$pagequeries;
419
            }
420
// Sort by key, so _noquery_ is last
421
            if (!empty($this->default_values)) {
422
                foreach ($this->default_values as $a => $b) {
423
                    foreach ($b as $c => $d) {
424
                        krsort($this->default_values[$a][$c]);
425
                    }
426
                }
427
            }
428
// Config::$dbEngine->free($resql);
429
430
            return 1;
431
        }
432
        AlDolUtils::dol_print_error(Config::$dbEngine);
0 ignored issues
show
The method dol_print_error() does not exist on Alixar\Helpers\AlDolUtils. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

432
        AlDolUtils::/** @scrutinizer ignore-call */ dol_print_error(Config::$dbEngine);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
433
        return -1;
434
    }
435
436
    /**
437
     *  Add a right to the user
438
     *
439
     * 	@param	int		$rid			Id of permission to add or 0 to add several permissions
440
     *  @param  string	$allmodule		Add all permissions of module $allmodule
441
     *  @param  string	$allperms		Add all permissions of module $allmodule, subperms $allperms only
442
     *  @param	int		$entity			Entity to use
443
     *  @param  int	    $notrigger		1=Does not execute triggers, 0=Execute triggers
444
     *  @return int						> 0 if OK, < 0 if KO
445
     *  @see	clearrights, delrights, getrights
446
     */
447
    function addrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
448
    {
449
//global $conf, Globals::$user, Globals::$langs;
450
451
        $entity = (!empty($entity) ? $entity : Globals::$conf->entity);
452
453
        AlDolUtils::dol_syslog(get_class($this) . "::addrights $rid, $allmodule, $allperms, $entity");
454
        $error = 0;
455
        $whereforadd = '';
456
457
        Config::$dbEngine->begin();
458
459
        if (!empty($rid)) {
460
// Si on a demande ajout d'un droit en particulier, on recupere
461
// les caracteristiques (module, perms et subperms) de ce droit.
462
            $sql = "SELECT module, perms, subperms";
463
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
464
            $sql .= " WHERE id = '" . Config::$dbEngine->escape($rid) . "'";
465
            $sql .= " AND entity = " . $entity;
466
467
            $result = Config::$dbEngine->query($sql);
468
            if ($result) {
469
                $obj = Config::$dbEngine->fetch_object($result);
470
                $module = $obj->module;
471
                $perms = $obj->perms;
472
                $subperms = $obj->subperms;
473
            } else {
474
                $error++;
475
                dol_print_error(Config::$dbEngine);
476
            }
477
478
// Where pour la liste des droits a ajouter
479
            $whereforadd = "id=" . Config::$dbEngine->escape($rid);
480
// Ajout des droits induits
481
            if (!empty($subperms)) {
482
                $whereforadd .= " OR (module='$module' AND perms='$perms' AND (subperms='lire' OR subperms='read'))";
483
            } else {
484
                if (!empty($perms)) {
485
                    $whereforadd .= " OR (module='$module' AND (perms='lire' OR perms='read') AND subperms IS NULL)";
486
                }
487
            }
488
        } else {
489
// On a pas demande un droit en particulier mais une liste de droits
490
// sur la base d'un nom de module de de perms
491
// Where pour la liste des droits a ajouter
492
            if (!empty($allmodule)) {
493
                if ($allmodule == 'allmodules') {
494
                    $whereforadd = 'allmodules';
495
                } else {
496
                    $whereforadd = "module='" . Config::$dbEngine->escape($allmodule) . "'";
497
                    if (!empty($allperms)) {
498
                        $whereforadd .= " AND perms='" . Config::$dbEngine->escape($allperms) . "'";
499
                    }
500
                }
501
            }
502
        }
503
504
// Ajout des droits trouves grace au critere whereforadd
505
        if (!empty($whereforadd)) {
506
//print "$module-$perms-$subperms";
507
            $sql = "SELECT id";
508
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
509
            $sql .= " WHERE entity = " . $entity;
510
            if (!empty($whereforadd) && $whereforadd != 'allmodules') {
511
                $sql .= " AND " . $whereforadd;
512
            }
513
514
            $result = Config::$dbEngine->query($sql);
515
            if ($result) {
516
                $num = Config::$dbEngine->num_rows($result);
517
                $i = 0;
518
                while ($i < $num) {
519
                    $obj = Config::$dbEngine->fetch_object($result);
520
                    $nid = $obj->id;
521
522
                    $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = " . $this->id . " AND fk_id=" . $nid . " AND entity = " . $entity;
523
                    if (!Config::$dbEngine->query($sql))
524
                        $error++;
525
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_rights (entity, fk_user, fk_id) VALUES (" . $entity . ", " . $this->id . ", " . $nid . ")";
526
                    if (!Config::$dbEngine->query($sql))
527
                        $error++;
528
529
                    $i++;
530
                }
531
            }
532
            else {
533
                $error++;
534
                dol_print_error(Config::$dbEngine);
535
            }
536
        }
537
538
        if (!$error && !$notrigger) {
539
            Globals::$langs->load("other");
540
            $this->context = array('audit' => Globals::$langs->trans("PermissionsAdd") . ($rid ? ' (id=' . $rid . ')' : ''));
541
542
// Call trigger
543
            $result = $this->call_trigger('USER_MODIFY', Globals::$user);
544
            if ($result < 0) {
545
                $error++;
546
            }
547
// End call triggers
548
        }
549
550
        if ($error) {
551
            Config::$dbEngine->rollback();
552
            return -$error;
553
        } else {
554
            Config::$dbEngine->commit();
555
            return 1;
556
        }
557
    }
558
559
    /**
560
     *  Remove a right to the user
561
     *
562
     *  @param	int		$rid        Id du droit a retirer
563
     *  @param  string	$allmodule  Retirer tous les droits du module allmodule
564
     *  @param  string	$allperms   Retirer tous les droits du module allmodule, perms allperms
565
     *  @param	int		$entity		Entity to use
566
     *  @param  int	    $notrigger	1=Does not execute triggers, 0=Execute triggers
567
     *  @return int         		> 0 if OK, < 0 if OK
568
     *  @see	clearrights, addrights, getrights
569
     */
570
    function delrights($rid, $allmodule = '', $allperms = '', $entity = 0, $notrigger = 0)
571
    {
572
//global $conf, Globals::$user, Globals::$langs;
573
574
        $error = 0;
575
        $wherefordel = '';
576
        $entity = (!empty($entity) ? $entity : Globals::$conf->entity);
577
578
        Config::$dbEngine->begin();
579
580
        if (!empty($rid)) {
581
// Si on a demande supression d'un droit en particulier, on recupere
582
// les caracteristiques module, perms et subperms de ce droit.
583
            $sql = "SELECT module, perms, subperms";
584
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
585
            $sql .= " WHERE id = '" . Config::$dbEngine->escape($rid) . "'";
586
            $sql .= " AND entity = " . $entity;
587
588
            $result = Config::$dbEngine->query($sql);
589
            if ($result) {
590
                $obj = Config::$dbEngine->fetch_object($result);
591
                $module = $obj->module;
592
                $perms = $obj->perms;
593
                $subperms = $obj->subperms;
594
            } else {
595
                $error++;
596
                dol_print_error(Config::$dbEngine);
597
            }
598
599
// Where pour la liste des droits a supprimer
600
            $wherefordel = "id=" . Config::$dbEngine->escape($rid);
601
// Suppression des droits induits
602
            if ($subperms == 'lire' || $subperms == 'read') {
603
                $wherefordel .= " OR (module='$module' AND perms='$perms' AND subperms IS NOT NULL)";
604
            }
605
            if ($perms == 'lire' || $perms == 'read') {
606
                $wherefordel .= " OR (module='$module')";
607
            }
608
        } else {
609
// On a demande suppression d'un droit sur la base d'un nom de module ou perms
610
// Where pour la liste des droits a supprimer
611
            if (!empty($allmodule)) {
612
                if ($allmodule == 'allmodules') {
613
                    $wherefordel = 'allmodules';
614
                } else {
615
                    $wherefordel = "module='" . Config::$dbEngine->escape($allmodule) . "'";
616
                    if (!empty($allperms)) {
617
                        $whereforadd .= " AND perms='" . Config::$dbEngine->escape($allperms) . "'";
0 ignored issues
show
Comprehensibility Best Practice introduced by alxarafe
The variable $whereforadd does not exist. Did you maybe mean $wherefordel?
Loading history...
618
                    }
619
                }
620
            }
621
        }
622
623
// Suppression des droits selon critere defini dans wherefordel
624
        if (!empty($wherefordel)) {
625
//print "$module-$perms-$subperms";
626
            $sql = "SELECT id";
627
            $sql .= " FROM " . MAIN_DB_PREFIX . "rights_def";
628
            $sql .= " WHERE entity = " . $entity;
629
            if (!empty($wherefordel) && $wherefordel != 'allmodules') {
630
                $sql .= " AND " . $wherefordel;
631
            }
632
633
            $result = Config::$dbEngine->query($sql);
634
            if ($result) {
635
                $num = Config::$dbEngine->num_rows($result);
636
                $i = 0;
637
                while ($i < $num) {
638
                    $obj = Config::$dbEngine->fetch_object($result);
639
                    $nid = $obj->id;
640
641
                    $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights";
642
                    $sql .= " WHERE fk_user = " . $this->id . " AND fk_id=" . $nid;
643
                    $sql .= " AND entity = " . $entity;
644
                    if (!Config::$dbEngine->query($sql)) {
645
                        $error++;
646
                    }
647
648
                    $i++;
649
                }
650
            } else {
651
                $error++;
652
                dol_print_error(Config::$dbEngine);
653
            }
654
        }
655
656
        if (!$error && !$notrigger) {
657
            Globals::$langs->load("other");
658
            $this->context = array('audit' => Globals::$langs->trans("PermissionsDelete") . ($rid ? ' (id=' . $rid . ')' : ''));
659
660
// Call trigger
661
            $result = $this->call_trigger('USER_MODIFY', Globals::$user);
662
            if ($result < 0) {
663
                $error++;
664
            }
665
// End call triggers
666
        }
667
668
        if ($error) {
669
            Config::$dbEngine->rollback();
670
            return -$error;
671
        } else {
672
            Config::$dbEngine->commit();
673
            return 1;
674
        }
675
    }
676
677
    /**
678
     *  Clear all permissions array of user
679
     *
680
     *  @return	void
681
     *  @see	getrights
682
     */
683
    function clearrights()
684
    {
685
        AlDolUtils::dol_syslog(get_class($this) . "::clearrights reset user->rights");
686
        $this->rights = '';
687
        $this->all_permissions_are_loaded = false;
688
        $this->_tab_loaded = array();
689
    }
690
691
    /**
692
     * 	Load permissions granted to user into object user
693
     *
694
     * 	@param  string	$moduletag		Limit permission for a particular module ('' by default means load all permissions)
695
     *  @param	int		$forcereload	Force reload of permissions even if they were already loaded (ignore cache)
696
     * 	@return	void
697
     *  @see	clearrights, delrights, addrights
698
     */
699
    function getrights($moduletag = '', $forcereload = 0)
700
    {
701
        global $conf;
702
703
        if (empty($forcereload)) {
704
            if ($moduletag && isset($this->_tab_loaded[$moduletag]) && $this->_tab_loaded[$moduletag]) {
705
// Rights for this module are already loaded, so we leave
706
                return;
707
            }
708
709
            if ($this->all_permissions_are_loaded) {
710
// We already loaded all rights for this user, so we leave
711
                return;
712
            }
713
        }
714
715
// Recuperation des droits utilisateurs + recuperation des droits groupes
716
// D'abord les droits utilisateurs
717
        $sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
718
        $sql .= " FROM " . MAIN_DB_PREFIX . "user_rights as ur";
719
        $sql .= ", " . MAIN_DB_PREFIX . "rights_def as r";
720
        $sql .= " WHERE r.id = ur.fk_id";
721
        if (!empty(Globals::$conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
722
            $sql .= " AND r.entity IN (0," . (!empty(Globals::$conf->multicompany->enabled) && !empty(Globals::$conf->global->MULTICOMPANY_TRANSVERSE_MODE) ? "1," : "") . Globals::$conf->entity . ")";
723
        } else {
724
            $sql .= " AND ur.entity = " . Globals::$conf->entity;
725
        }
726
        $sql .= " AND ur.fk_user= " . $this->id;
727
        $sql .= " AND r.perms IS NOT NULL";
728
        if ($moduletag) {
729
// $sql .= " AND r.module = '" . Config::$dbEngine->escape($moduletag) . "'";
730
            $sql .= " AND r.module = '" . $moduletag . "'";
731
        }
732
733
        $resql = Config::$dbEngine->select($sql);
734
        if (is_array($resql)) {
735
            foreach ($resql as $array) {
736
                $obj = json_decode(json_encode($array));
737
738
                $module = $obj->module;
739
                $perms = $obj->perms;
740
                $subperms = $obj->subperms;
741
742
                if ($perms) {
743
                    if (!isset($this->rights) || !is_object($this->rights)) {
744
                        $this->rights = new \stdClass(); // For avoid error
745
                    }
746
                    if ($module) {
747
                        if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
748
                            $this->rights->$module = new \stdClass();
749
                        }
750
                        if ($subperms) {
751
                            if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms)) {
752
                                $this->rights->$module->$perms = new \stdClass();
753
                            }
754
                            if (empty($this->rights->$module->$perms->$subperms)) {
755
                                $this->nb_rights++;
756
                            }
757
                            $this->rights->$module->$perms->$subperms = 1;
758
                        } else {
759
                            if (empty($this->rights->$module->$perms)) {
760
                                $this->nb_rights++;
761
                            }
762
                            $this->rights->$module->$perms = 1;
763
                        }
764
                    }
765
                }
766
            }
767
        }
768
769
// Maintenant les droits groupes
770
        $sql = "SELECT DISTINCT r.module, r.perms, r.subperms";
771
        $sql .= " FROM " . MAIN_DB_PREFIX . "usergroup_rights as gr,";
772
        $sql .= " " . MAIN_DB_PREFIX . "usergroup_user as gu,";
773
        $sql .= " " . MAIN_DB_PREFIX . "rights_def as r";
774
        $sql .= " WHERE r.id = gr.fk_id";
775
        if (!empty(Globals::$conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
776
            if (!empty(Globals::$conf->multicompany->enabled) && !empty(Globals::$conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
777
                $sql .= " AND gu.entity IN (0," . Globals::$conf->entity . ")";
778
            } else {
779
                $sql .= " AND r.entity = " . Globals::$conf->entity;
780
            }
781
        } else {
782
            $sql .= " AND gr.entity = " . Globals::$conf->entity;
783
            $sql .= " AND r.entity = " . Globals::$conf->entity;
784
        }
785
        $sql .= " AND gr.fk_usergroup = gu.fk_usergroup";
786
        $sql .= " AND gu.fk_user = " . $this->id;
787
        $sql .= " AND r.perms IS NOT NULL";
788
        if ($moduletag) {
789
            $sql .= " AND r.module = '" . $moduletag . "'";
790
        }
791
792
        $resql = Config::$dbEngine->select($sql);
793
        if (is_array($resql)) {
794
            foreach ($resql as $array) {
795
                $obj = json_decode(json_encode($array));
796
797
                $module = $obj->module;
798
                $perms = $obj->perms;
799
                $subperms = $obj->subperms;
800
801
                if ($perms) {
802
                    if (!isset($this->rights) || !is_object($this->rights)) {
803
                        $this->rights = new \stdClass(); // For avoid error
804
                    }
805
                    if (!isset($this->rights->$module) || !is_object($this->rights->$module)) {
806
                        $this->rights->$module = new \stdClass();
807
                    }
808
                    if ($subperms) {
809
                        if (!isset($this->rights->$module->$perms) || !is_object($this->rights->$module->$perms)) {
810
                            $this->rights->$module->$perms = new \stdClass();
811
                        }
812
                        if (empty($this->rights->$module->$perms->$subperms)) {
813
                            $this->nb_rights++;
814
                        }
815
                        $this->rights->$module->$perms->$subperms = 1;
816
                    } else {
817
                        if (empty($this->rights->$module->$perms)) {
818
                            $this->nb_rights++;
819
                        }
820
// 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
821
                        if (!is_object($this->rights->$module->$perms)) {
822
                            $this->rights->$module->$perms = 1;
823
                        }
824
                    }
825
                }
826
            }
827
        }
828
829
// For backward compatibility
830
        if (isset($this->rights->propale) && !isset($this->rights->propal)) {
831
            $this->rights->propal = $this->rights->propale;
832
        }
833
        if (isset($this->rights->propal) && !isset($this->rights->propale)) {
834
            $this->rights->propale = $this->rights->propal;
835
        }
836
837
        if (!$moduletag) {
838
// Si module etait non defini, alors on a tout charge, on peut donc considerer
839
// que les droits sont en cache (car tous charges) pour cet instance de user
840
            $this->all_permissions_are_loaded = 1;
841
        } else {
842
// Si module defini, on le marque comme charge en cache
843
            $this->_tab_loaded[$moduletag] = 1;
844
        }
845
    }
846
847
    /**
848
     *  Change status of a user
849
     *
850
     * 	@param	int		$statut		Status to set
851
     *  @return int     			<0 if KO, 0 if nothing is done, >0 if OK
852
     */
853
    function setstatus($statut)
854
    {
855
// global $conf, Globals::$langs, Globals::$user;
856
857
        $error = 0;
858
859
// Check parameters
860
        if ($this->statut == $statut) {
861
            return 0;
862
        } else {
863
            $this->statut = $statut;
864
        }
865
866
        Config::$dbEngine->begin();
867
868
// Deactivate user
869
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
870
        $sql .= " SET statut = " . $this->statut;
871
        $sql .= " WHERE rowid = " . $this->id;
872
        $result = Config::$dbEngine->query($sql);
873
874
        AlDolUtils::dol_syslog(get_class($this) . "::setstatus", LOG_DEBUG);
875
        if ($result) {
876
// Call trigger
877
            $result = $this->call_trigger('USER_ENABLEDISABLE', Globals::$user);
878
            if ($result < 0) {
879
                $error++;
880
            }
881
// End call triggers
882
        }
883
884
        if ($error) {
885
            Config::$dbEngine->rollback();
886
            return -$error;
887
        } else {
888
            Config::$dbEngine->commit();
889
            return 1;
890
        }
891
    }
892
893
    /**
894
     * Sets object to supplied categories.
895
     *
896
     * Deletes object from existing categories not supplied.
897
     * Adds it to non existing supplied categories.
898
     * Existing categories are left untouch.
899
     *
900
     * @param int[]|int $categories Category or categories IDs
901
     * @return void
902
     */
903
    public function setCategories($categories)
904
    {
905
// Handle single category
906
        if (!is_array($categories)) {
907
            $categories = array($categories);
908
        }
909
910
// Get current categories
911
        require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
912
        $c = new Categorie(Config::$dbEngine);
0 ignored issues
show
The type Alixar\Base\Categorie was not found. Did you mean Categorie? If so, make sure to prefix the type with \.
Loading history...
913
        $existing = $c->containing($this->id, Categorie::TYPE_USER, 'id');
914
915
// Diff
916
        if (is_array($existing)) {
917
            $to_del = array_diff($existing, $categories);
918
            $to_add = array_diff($categories, $existing);
919
        } else {
920
            $to_del = array(); // Nothing to delete
921
            $to_add = $categories;
922
        }
923
924
// Process
925
        foreach ($to_del as $del) {
926
            if ($c->fetch($del) > 0) {
927
                $c->del_type($this, 'user');
928
            }
929
        }
930
        foreach ($to_add as $add) {
931
            if ($c->fetch($add) > 0) {
932
                $c->add_type($this, 'user');
933
            }
934
        }
935
936
        return;
937
    }
938
939
    /**
940
     *    	Delete the user
941
     *
942
     * 		@return		int		<0 if KO, >0 if OK
943
     */
944
    function delete()
945
    {
946
//global Globals::$user, $conf, Globals::$langs;
947
948
        $error = 0;
949
950
        Config::$dbEngine->begin();
951
952
        $this->fetch($this->id);
953
954
        AlDolUtils::dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
955
956
// Remove rights
957
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = " . $this->id;
958
959
        if (!$error && !Config::$dbEngine->query($sql)) {
960
            $error++;
961
            $this->error = Config::$dbEngine->lasterror();
962
        }
963
964
// Remove group
965
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user WHERE fk_user  = " . $this->id;
966
        if (!$error && !Config::$dbEngine->query($sql)) {
967
            $error++;
968
            $this->error = Config::$dbEngine->lasterror();
969
        }
970
971
// If contact, remove link
972
        if ($this->contact_id) {
973
            $sql = "UPDATE " . MAIN_DB_PREFIX . "socpeople SET fk_user_creat = null WHERE rowid = " . $this->contact_id;
974
            if (!$error && !Config::$dbEngine->query($sql)) {
975
                $error++;
976
                $this->error = Config::$dbEngine->lasterror();
977
            }
978
        }
979
980
// Remove extrafields
981
        if ((!$error) && (empty(Globals::$conf->global->MAIN_EXTRAFIELDS_DISABLED))) { // For avoid conflicts if trigger used
982
            $result = $this->deleteExtraFields();
983
            if ($result < 0) {
984
                $error++;
985
                AlDolUtils::dol_syslog(get_class($this) . "::delete error -4 " . $this->error, LOG_ERR);
986
            }
987
        }
988
989
// Remove user
990
        if (!$error) {
991
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user WHERE rowid = " . $this->id;
992
            AlDolUtils::dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
993
            if (!Config::$dbEngine->query($sql)) {
994
                $error++;
995
                $this->error = Config::$dbEngine->lasterror();
996
            }
997
        }
998
999
        if (!$error) {
1000
// Call trigger
1001
            $result = $this->call_trigger('USER_DELETE', Globals::$user);
1002
            if ($result < 0) {
1003
                $error++;
1004
                Config::$dbEngine->rollback();
1005
                return -1;
1006
            }
1007
// End call triggers
1008
1009
            Config::$dbEngine->commit();
1010
            return 1;
1011
        } else {
1012
            Config::$dbEngine->rollback();
1013
            return -1;
1014
        }
1015
    }
1016
1017
    /**
1018
     *  Create a user into database
1019
     *
1020
     *  @param	User	Globals::$user        	Objet user doing creation
1021
     *  @param  int		$notrigger		1=do not execute triggers, 0 otherwise
1022
     *  @return int			         	<0 if KO, id of created user if OK
1023
     */
1024
    function create($user, $notrigger = 0)
1025
    {
1026
//global $conf, Globals::$langs;
1027
//global $mysoc;
1028
// Clean parameters
1029
        $this->login = trim($this->login);
1030
        if (!isset($this->entity)) {
1031
            $this->entity = Globals::$conf->entity; // If not defined, we use default value
1032
        }
1033
        AlDolUtils::dol_syslog(get_class($this) . "::create login=" . $this->login . ", user=" . (is_object(Globals::$user) ? Globals::$user->id : ''), LOG_DEBUG);
1034
1035
// Check parameters
1036
        if (!empty(Globals::$conf->global->USER_MAIL_REQUIRED) && !isValidEMail($this->email)) {
1037
            Globals::$langs->load("errors");
1038
            $this->error = Globals::$langs->trans("ErrorBadEMail", $this->email);
1039
            return -1;
1040
        }
1041
        if (empty($this->login)) {
1042
            Globals::$langs->load("errors");
1043
            $this->error = Globals::$langs->trans("ErrorFieldRequired", Globals::$langs->transnoentitiesnoconv("Login"));
1044
            return -1;
1045
        }
1046
1047
        $this->datec = dol_now();
1048
1049
        $error = 0;
1050
        Config::$dbEngine->begin();
1051
1052
        $sql = "SELECT login FROM " . MAIN_DB_PREFIX . "user";
1053
        $sql .= " WHERE login ='" . Config::$dbEngine->escape($this->login) . "'";
1054
        $sql .= " AND entity IN (0," . Config::$dbEngine->escape(Globals::$conf->entity) . ")";
1055
1056
        AlDolUtils::dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1057
        $resql = Config::$dbEngine->query($sql);
1058
        if ($resql) {
1059
            $num = Config::$dbEngine->num_rows($resql);
1060
            Config::$dbEngine->free($resql);
1061
1062
            if ($num) {
1063
                $this->error = 'ErrorLoginAlreadyExists';
1064
                AlDolUtils::dol_syslog(get_class($this) . "::create " . $this->error, LOG_WARNING);
1065
                Config::$dbEngine->rollback();
1066
                return -6;
1067
            } else {
1068
                $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user (datec,login,ldap_sid,entity)";
1069
                $sql .= " VALUES('" . Config::$dbEngine->idate($this->datec) . "','" . Config::$dbEngine->escape($this->login) . "','" . Config::$dbEngine->escape($this->ldap_sid) . "'," . Config::$dbEngine->escape($this->entity) . ")";
1070
                $result = Config::$dbEngine->query($sql);
1071
1072
                AlDolUtils::dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1073
                if ($result) {
1074
                    $this->id = Config::$dbEngine->last_insert_id(MAIN_DB_PREFIX . "user");
1075
1076
// Set default rights
1077
                    if ($this->set_default_rights() < 0) {
1078
                        $this->error = 'ErrorFailedToSetDefaultRightOfUser';
1079
                        Config::$dbEngine->rollback();
1080
                        return -5;
1081
                    }
1082
1083
// Update minor fields
1084
                    $result = $this->update(Globals::$user, 1, 1);
1085
                    if ($result < 0) {
1086
                        Config::$dbEngine->rollback();
1087
                        return -4;
1088
                    }
1089
1090
                    if (!empty(Globals::$conf->global->STOCK_USERSTOCK_AUTOCREATE)) {
1091
                        require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1092
                        Globals::$langs->load("stocks");
1093
                        $entrepot = new Entrepot(Config::$dbEngine);
0 ignored issues
show
The type Alixar\Base\Entrepot was not found. Did you mean Entrepot? If so, make sure to prefix the type with \.
Loading history...
1094
                        $entrepot->libelle = Globals::$langs->trans("PersonalStock", $this->getFullName(Globals::$langs));
1095
                        $entrepot->description = Globals::$langs->trans("ThisWarehouseIsPersonalStock", $this->getFullName(Globals::$langs));
1096
                        $entrepot->statut = 1;
1097
                        $entrepot->country_id = $mysoc->country_id;
0 ignored issues
show
Comprehensibility Best Practice introduced by alxarafe
The variable $mysoc seems to be never defined.
Loading history...
1098
                        $entrepot->create(Globals::$user);
1099
                    }
1100
1101
                    if (!$notrigger) {
1102
// Call trigger
1103
                        $result = $this->call_trigger('USER_CREATE', Globals::$user);
1104
                        if ($result < 0) {
1105
                            $error++;
1106
                        }
1107
// End call triggers
1108
                    }
1109
1110
                    if (!$error) {
1111
                        Config::$dbEngine->commit();
1112
                        return $this->id;
1113
                    } else {
1114
//$this->error=$interface->error;
1115
                        AlDolUtils::dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
1116
                        Config::$dbEngine->rollback();
1117
                        return -3;
1118
                    }
1119
                } else {
1120
                    $this->error = Config::$dbEngine->lasterror();
1121
                    Config::$dbEngine->rollback();
1122
                    return -2;
1123
                }
1124
            }
1125
        } else {
1126
            $this->error = Config::$dbEngine->lasterror();
1127
            Config::$dbEngine->rollback();
1128
            return -1;
1129
        }
1130
    }
1131
1132
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1133
    /**
1134
     *  Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
1135
     *
1136
     *  @param	Contact	$contact    Object for source contact
0 ignored issues
show
Bug introduced by alxarafe