Passed
Push — master ( 65bdac...4e88da )
by Alxarafe
32:38
created

User   F

Complexity

Total Complexity 484

Size/Duplication

Total Lines 3103
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1709
dl 0
loc 3103
rs 0.8
c 0
b 0
f 0
wmc 484

45 Methods

Rating   Name   Duplication   Size   Complexity  
A update_clicktodial() 0 28 2
B SetInGroup() 0 45 6
A getNbOfEMailings() 0 17 2
D LibStatut() 0 41 19
A get_children() 0 19 3
B send_password() 0 73 6
A _load_ldap_dn() 0 13 4
C fetchAll() 0 51 13
A update_last_login_date() 0 20 2
A getAllChildIds() 0 27 5
F update() 0 288 72
B loadDefaultValues() 0 36 10
B RemoveFromGroup() 0 41 6
A getLoginUrl() 0 33 6
A getPhotoUrl() 0 8 1
A setstatus() 0 37 5
C create() 0 106 15
A set_default_rights() 0 36 5
A initAsSpecimen() 0 37 1
B create_from_contact() 0 71 6
F delrights() 0 104 22
A update_ldap2dolibarr() 0 29 1
A build_path_from_id_user() 0 34 4
A generateDocument() 0 18 3
A fetch_clicktodial() 0 25 3
A __construct() 0 19 1
C setPassword() 0 102 16
A clearrights() 0 6 1
A load_state_board() 0 24 3
A getLibStatut() 0 3 1
A info() 0 23 4
F fetch() 0 205 24
A replaceThirdparty() 0 7 1
A error() 0 3 1
F getrights() 0 145 45
F _load_ldap_info() 0 129 35
F delete() 0 70 15
C get_full_tree() 0 84 13
A user_get_property() 0 29 6
A loadParentOf() 0 22 3
F getNomUrl() 0 159 50
F addrights() 0 109 21
B setCategories() 0 34 7
B getNbOfUsers() 0 31 6
B create_from_member() 0 60 9

How to fix   Complexity   

Complex Class

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

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 Alxarafe\Helpers\Config;
20
use Alixar\Base\CommonObject;
21
use Alixar\Helpers\Globals;
22
23
class User extends CommonObject
24
{
25
26
    /**
27
     * @var string ID to identify managed object
28
     */
29
    public $element = 'user';
30
31
    /**
32
     * @var string Name of table without prefix where object is stored
33
     */
34
    public $table_element = 'user';
35
36
    /**
37
     * @var int Field with ID of parent key if this field has a parent
38
     */
39
    public $fk_element = 'fk_user';
40
41
    /**
42
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
43
     * @var int
44
     */
45
    public $ismultientitymanaged = 1;
46
    public $id = 0;
47
    public $statut;
48
    public $ldap_sid;
49
    public $search_sid;
50
    public $employee;
51
    public $gender;
52
    public $birth;
53
    public $email;
54
    public $skype;
55
    public $twitter;
56
    public $facebook;
57
    public $job;   // job position
58
    public $signature;
59
60
    /**
61
     * @var string Address
62
     */
63
    public $address;
64
    public $zip;
65
    public $town;
66
    public $state_id;  // The state/department
67
    public $state_code;
68
    public $state;
69
    public $office_phone;
70
    public $office_fax;
71
    public $user_mobile;
72
    public $admin;
73
    public $login;
74
    public $api_key;
75
76
    /**
77
     * @var int Entity
78
     */
79
    public $entity;
80
    //! Clear password in memory
81
    public $pass;
82
    //! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
83
    public $pass_indatabase;
84
    //! Encrypted password in database (always defined)
85
    public $pass_indatabase_crypted;
86
    public $datec;
87
    public $datem;
88
    //! If this is defined, it is an external user
89
    /**
90
     * @deprecated
91
     * @see socid
92
     */
93
    public $societe_id;
94
95
    /**
96
     * @deprecated
97
     * @see contactid
98
     */
99
    public $contact_id;
100
    public $socid;
101
    public $contactid;
102
103
    /**
104
     * @var int ID
105
     */
106
    public $fk_member;
107
108
    /**
109
     * @var int User ID
110
     */
111
    public $fk_user;
112
    public $clicktodial_url;
113
    public $clicktodial_login;
114
    public $clicktodial_password;
115
    public $clicktodial_poste;
116
    public $datelastlogin;
117
    public $datepreviouslogin;
118
    public $photo;
119
    public $lang;
120
    public $rights;                        // Array of permissions user->rights->permx
121
    public $all_permissions_are_loaded;    // All permission are loaded
122
    public $nb_rights;              // Number of rights granted to the user
123
    private $_tab_loaded = array();     // Cache array of already loaded permissions
124
    public $conf;             // To store personal config
125
    public $default_values;         // To store default values for user
126
    public $lastsearch_values_tmp;  // To store current search criterias for user
127
    public $lastsearch_values;      // To store last saved search criterias for user
128
    public $users = array();  // To store all tree of users hierarchy
129
    public $parentof;    // To store an array of all parents for all ids.
130
    private $cache_childids;
131
    public $accountancy_code;   // Accountancy code in prevision of the complete accountancy module
132
    public $thm;     // Average cost of employee - Used for valuation of time spent
133
    public $tjm;     // Average cost of employee
134
    public $salary;     // Monthly salary       - Denormalized value from llx_user_employment
135
    public $salaryextra;    // Monthly salary extra - Denormalized value from llx_user_employment
136
    public $weeklyhours;    // Weekly hours         - Denormalized value from llx_user_employment
137
    public $color;      // Define background color for user in agenda
138
    public $dateemployment;   // Define date of employment by company
139
    public $dateemploymentend;  // Define date of employment end by company
140
    public $default_c_exp_tax_cat;
141
    public $default_range;
142
    public $fields = array(
143
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
144
        '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'),
145
        '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'),
146
    );
147
148
    /**
149
     *    Constructor of the class
150
     *
151
     *    @param   DoliDb  $db     Database handler
0 ignored issues
show
Bug introduced by
The type Alixar\Base\DoliDb was not found. Did you mean DoliDb? If so, make sure to prefix the type with \.
Loading history...
152
     */
153
    function __construct()
154
    {
155
        // User preference
156
        $this->liste_limit = 0;
157
        $this->clicktodial_loaded = 0;
158
159
        // For cache usage
160
        $this->all_permissions_are_loaded = 0;
161
        $this->nb_rights = 0;
162
163
        // Force some default values
164
        $this->admin = 0;
165
        $this->employee = 1;
166
167
        $this->conf = new \stdClass();
168
        $this->rights = new \stdClass();
169
        $this->rights->user = new \stdClass();
170
        $this->rights->user->user = new \stdClass();
171
        $this->rights->user->self = new \stdClass();
172
    }
173
174
    /**
175
     * 	Load a user from database with its id or ref (login).
176
     *  This function does not load permissions, only user properties. Use getrights() for this just after the fetch.
177
     *
178
     * 	@param	int		$id		       		If defined, id to used for search
179
     * 	@param  string	$login       		If defined, login to used for search
180
     * 	@param  string	$sid				If defined, sid to used for search
181
     * 	@param	int		$loadpersonalconf	1=also load personal conf of user (in $user->conf->xxx), 0=do not load personal conf.
182
     *  @param  int     $entity             If a value is >= 0, we force the search on a specific entity. If -1, means search depens on default setup.
183
     * 	@return	int							<0 if KO, 0 not found, >0 if OK
184
     */
185
    function fetch($id = '', $login = '', $sid = '', $loadpersonalconf = 0, $entity = -1)
186
    {
187
        // global $conf, $user;
188
        // Clean parameters
189
        $login = trim($login);
190
191
        // Get user
192
        $sql = "SELECT u.rowid, u.lastname, u.firstname, u.employee, u.gender, u.birth, u.email, u.job, u.skype, u.twitter, u.facebook,";
193
        $sql .= " u.signature, u.office_phone, u.office_fax, u.user_mobile,";
194
        $sql .= " u.address, u.zip, u.town, u.fk_state as state_id, u.fk_country as country_id,";
195
        $sql .= " u.admin, u.login, u.note,";
196
        $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,";
197
        $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid,";
198
        $sql .= " u.statut, u.lang, u.entity,";
199
        $sql .= " u.datec as datec,";
200
        $sql .= " u.tms as datem,";
201
        $sql .= " u.datelastlogin as datel,";
202
        $sql .= " u.datepreviouslogin as datep,";
203
        $sql .= " u.photo as photo,";
204
        $sql .= " u.openid as openid,";
205
        $sql .= " u.accountancy_code,";
206
        $sql .= " u.thm,";
207
        $sql .= " u.tjm,";
208
        $sql .= " u.salary,";
209
        $sql .= " u.salaryextra,";
210
        $sql .= " u.weeklyhours,";
211
        $sql .= " u.color,";
212
        $sql .= " u.dateemployment, u.dateemploymentend,";
213
        $sql .= " u.ref_int, u.ref_ext,";
214
        $sql .= " u.default_range, u.default_c_exp_tax_cat,";   // Expense report default mode
215
        $sql .= " c.code as country_code, c.label as country,";
216
        $sql .= " d.code_departement as state_code, d.nom as state";
217
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
218
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid";
219
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_departements as d ON u.fk_state = d.rowid";
220
221
        if ($entity < 0) {
222
            if ((empty($conf->multicompany->enabled) || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) && (!empty($user->entity))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $conf seems to be never defined.
Loading history...
223
                $sql .= " WHERE u.entity IN (0," . Globals::$conf->entity . ")";
224
            } else {
225
                $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
226
            }
227
        } else {  // The fetch was forced on an entity
228
            if (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
229
                $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
230
            } else {
231
                $sql .= " WHERE u.entity IN (0, " . (($entity != '' && $entity >= 0) ? $entity : Globals::$conf->entity) . ")";   // search in entity provided in parameter
232
            }
233
        }
234
235
        if ($sid) {    // permet une recherche du user par son SID ActiveDirectory ou Samba
236
            //$sql .= " AND (u.ldap_sid = '" . Config::$dbEngine->escape($sid) . "' OR u.login = '" . Config::$dbEngine->escape($login) . "') LIMIT 1";
237
            $sql .= " AND (u.ldap_sid = '" . $sid . "' OR u.login = '" . Config::$dbEngine->escape($login) . "') LIMIT 1";
0 ignored issues
show
Bug introduced by
The method escape() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

237
            $sql .= " AND (u.ldap_sid = '" . $sid . "' OR u.login = '" . Config::$dbEngine->/** @scrutinizer ignore-call */ escape($login) . "') LIMIT 1";

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...
238
        } else if ($login) {
239
            // $sql .= " AND u.login = '" . Config::$dbEngine->escape($login) . "'";
240
            $sql .= " AND u.login = '" . $login . "'";
241
        } else {
242
            $sql .= " AND u.rowid = " . $id;
243
        }
244
        $sql .= " ORDER BY u.entity ASC";    // Avoid random result when there is 2 login in 2 different entities
245
246
        $result = Config::$dbEngine->select($sql);
247
        // echo "<p>SQL in 2477 of User: '$sql'</p>";
248
        if ($result) {
249
            if (count($result) > 0) {
250
251
                // Convert array to stdclass
252
                $obj = json_decode(json_encode($result[0]));
253
254
                $this->id = $obj->rowid;
255
                $this->ref = $obj->rowid;
256
257
                $this->ref_int = $obj->ref_int;
258
                $this->ref_ext = $obj->ref_ext;
259
260
                $this->ldap_sid = $obj->ldap_sid;
261
                $this->lastname = $obj->lastname;
262
                $this->firstname = $obj->firstname;
263
264
                $this->employee = $obj->employee;
265
266
                $this->login = $obj->login;
267
                $this->gender = $obj->gender;
268
                // $this->birth = Config::$dbEngine->jdate($obj->birth);
269
                $this->birth = $obj->birth;
270
271
                $this->pass_indatabase = $obj->pass;
272
                $this->pass_indatabase_crypted = $obj->pass_crypted;
273
                $this->pass = $obj->pass;
274
                $this->pass_temp = $obj->pass_temp;
275
                $this->api_key = $obj->api_key;
276
277
                $this->address = $obj->address;
278
                $this->zip = $obj->zip;
279
                $this->town = $obj->town;
280
281
                $this->country_id = $obj->country_id;
282
                $this->country_code = $obj->country_id ? $obj->country_code : '';
283
                //$this->country 		= $obj->country_id?($langs->trans('Country'.$obj->country_code)!='Country'.$obj->country_code?$langs->transnoentities('Country'.$obj->country_code):$obj->country):'';
284
285
                $this->state_id = $obj->state_id;
286
                $this->state_code = $obj->state_code;
287
                $this->state = ($obj->state != '-' ? $obj->state : '');
288
289
                $this->office_phone = $obj->office_phone;
290
                $this->office_fax = $obj->office_fax;
291
                $this->user_mobile = $obj->user_mobile;
292
                $this->email = $obj->email;
293
                $this->skype = $obj->skype;
294
                $this->twitter = $obj->twitter;
295
                $this->facebook = $obj->facebook;
296
                $this->job = $obj->job;
297
                $this->signature = $obj->signature;
298
                $this->admin = $obj->admin;
299
                $this->note = $obj->note;
300
                $this->statut = $obj->statut;
301
                $this->photo = $obj->photo;
302
                $this->openid = $obj->openid;
303
                $this->lang = $obj->lang;
304
                $this->entity = $obj->entity;
305
                $this->accountancy_code = $obj->accountancy_code;
306
                $this->thm = $obj->thm;
307
                $this->tjm = $obj->tjm;
308
                $this->salary = $obj->salary;
309
                $this->salaryextra = $obj->salaryextra;
310
                $this->weeklyhours = $obj->weeklyhours;
311
                $this->color = $obj->color;
312
313
                /*
314
                  $this->dateemployment = Config::$dbEngine->jdate($obj->dateemployment);
315
                  $this->dateemploymentend = Config::$dbEngine->jdate($obj->dateemploymentend);
316
317
                  $this->datec = Config::$dbEngine->jdate($obj->datec);
318
                  $this->datem = Config::$dbEngine->jdate($obj->datem);
319
                  $this->datelastlogin = Config::$dbEngine->jdate($obj->datel);
320
                  $this->datepreviouslogin = Config::$dbEngine->jdate($obj->datep);
321
                 */
322
                $this->dateemployment = $obj->dateemployment;
323
                $this->dateemploymentend = $obj->dateemploymentend;
324
325
                $this->datec = $obj->datec;
326
                $this->datem = $obj->datem;
327
                $this->datelastlogin = $obj->datel;
328
                $this->datepreviouslogin = $obj->datep;
329
330
                $this->societe_id = $obj->fk_soc;  // deprecated
331
                $this->contact_id = $obj->fk_socpeople; // deprecated
332
                $this->socid = $obj->fk_soc;
333
                $this->contactid = $obj->fk_socpeople;
334
                $this->fk_member = $obj->fk_member;
335
                $this->fk_user = $obj->fk_user;
336
337
                $this->default_range = $obj->default_range;
338
                $this->default_c_exp_tax_cat = $obj->default_c_exp_tax_cat;
339
340
                // Protection when module multicompany was set, admin was set to first entity and then, the module was disabled,
341
                // in such case, this admin user must be admin for ALL entities.
342
                if (empty($conf->multicompany->enabled) && $this->admin && $this->entity == 1) {
343
                    $this->entity = 0;
344
                }
345
346
                // Retreive all extrafield
347
                // fetch optionals attributes and labels
348
                $this->fetch_optionals();
349
            } else {
350
                $this->error = "USERNOTFOUND";
351
                DolUtils::dol_syslog(get_class($this) . "::fetch user not found", LOG_DEBUG);
352
                return 0;
353
            }
354
        } else {
355
            $this->error = Config::$dbEngine->lasterror();
0 ignored issues
show
Bug introduced by
The method lasterror() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

355
            /** @scrutinizer ignore-call */ $this->error = Config::$dbEngine->lasterror();

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...
356
            return -1;
357
        }
358
359
        // To get back the global configuration unique to the user
360
        if ($loadpersonalconf) {
361
            // Load user->conf for user
362
            $sql = "SELECT param, value FROM " . MAIN_DB_PREFIX . "user_param";
363
            $sql .= " WHERE fk_user = " . $this->id;
364
            $sql .= " AND entity = " . Globals::$conf->entity;
365
            //DolUtils::dol_syslog(get_class($this).'::fetch load personalized conf', LOG_DEBUG);
366
            $resql = Config::$dbEngine->select($sql);
367
            if (is_array($resql)) {
368
                foreach ($resql as $array) {
369
                    $obj = json_decode(json_encode($array));
370
371
                    $p = (!empty($obj->param) ? $obj->param : '');
372
                    if (!empty($p)) {
373
                        $this->conf->$p = $obj->value;
374
                    }
375
                }
376
            } else {
377
                // $this->error = Config::$dbEngine->lasterror();
378
                return -2;
379
            }
380
381
            $result = $this->loadDefaultValues();
382
383
            if ($result < 0) {
384
                // $this->error = Config::$dbEngine->lasterror();
385
                return -3;
386
            }
387
        }
388
389
        return 1;
390
    }
391
392
    /**
393
     *  Load default value in property ->default_values
394
     *
395
     *  @return int						> 0 if OK, < 0 if KO
396
     */
397
    function loadDefaultValues()
398
    {
399
        // global $conf;
400
        // Load user->default_values for user. TODO Save this in memcached ?
401
        $sql = "SELECT rowid, entity, type, page, param, value";
402
        $sql .= " FROM " . MAIN_DB_PREFIX . "default_values";
403
        $sql .= " WHERE entity IN (" . ($this->entity > 0 ? $this->entity . ", " : "") . Globals::$conf->entity . ")"; // Entity of user (if defined) + current entity
404
        $sql .= " AND user_id IN (0" . ($this->id > 0 ? ", " . $this->id : "") . ")";       // User 0 (all) + me (if defined)
405
        $resql = Config::$dbEngine->select($sql);
406
        if (is_array($resql)) {
407
            foreach ($resql as $array) {
408
                $obj = json_decode(json_encode($array));
409
410
                $pagewithoutquerystring = $obj->page;
411
                $pagequeries = '';
412
                if (preg_match('/^([^\?]+)\?(.*)$/', $pagewithoutquerystring, $reg)) { // There is query param
413
                    $pagewithoutquerystring = $reg[1];
414
                    $pagequeries = $reg[2];
415
                }
416
                $this->default_values[$pagewithoutquerystring][$obj->type][$pagequeries ? $pagequeries : '_noquery_'][$obj->param] = $obj->value;
417
                //if ($pagequeries) $this->default_values[$pagewithoutquerystring][$obj->type.'_queries']=$pagequeries;
418
            }
419
            // Sort by key, so _noquery_ is last
420
            if (!empty($this->default_values)) {
421
                foreach ($this->default_values as $a => $b) {
422
                    foreach ($b as $c => $d) {
423
                        krsort($this->default_values[$a][$c]);
424
                    }
425
                }
426
            }
427
            // Config::$dbEngine->free($resql);
428
429
            return 1;
430
        }
431
        DolUtils::dol_print_error(Config::$dbEngine);
432
            return -1;
433
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, $user, $langs;
450
451
        $entity = (!empty($entity) ? $entity : Globals::$conf->entity);
452
453
        DolUtils::dol_syslog(get_class($this) . "::addrights $rid, $allmodule, $allperms, $entity");
454
        $error = 0;
455
        $whereforadd = '';
456
457
        Config::$dbEngine->begin();
0 ignored issues
show
Bug introduced by
The method begin() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

457
        Config::$dbEngine->/** @scrutinizer ignore-call */ 
458
                           begin();

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...
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);
0 ignored issues
show
Bug introduced by
The method query() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

467
            /** @scrutinizer ignore-call */ $result = Config::$dbEngine->query($sql);

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...
468
            if ($result) {
469
                $obj = Config::$dbEngine->fetch_object($result);
0 ignored issues
show
Bug introduced by
The method fetch_object() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

469
                /** @scrutinizer ignore-call */ $obj = Config::$dbEngine->fetch_object($result);

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...
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);
0 ignored issues
show
Bug introduced by
The method num_rows() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

516
                /** @scrutinizer ignore-call */ $num = Config::$dbEngine->num_rows($result);

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...
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
            $langs->load("other");
540
            $this->context = array('audit' => $langs->trans("PermissionsAdd") . ($rid ? ' (id=' . $rid . ')' : ''));
541
542
            // Call trigger
543
            $result = $this->call_trigger('USER_MODIFY', $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, $user, $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
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
            $langs->load("other");
658
            $this->context = array('audit' => $langs->trans("PermissionsDelete") . ($rid ? ' (id=' . $rid . ')' : ''));
659
660
            // Call trigger
661
            $result = $this->call_trigger('USER_MODIFY', $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
        DolUtils::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($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
722
            $sql .= " AND r.entity IN (0," . (!empty($conf->multicompany->enabled) && !empty($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($conf->global->MULTICOMPANY_BACKWARD_COMPATIBILITY)) {
776
            if (!empty($conf->multicompany->enabled) && !empty($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, $langs, $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
        DolUtils::dol_syslog(get_class($this) . "::setstatus", LOG_DEBUG);
875
        if ($result) {
876
            // Call trigger
877
            $result = $this->call_trigger('USER_ENABLEDISABLE', $user);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
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);
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 $user, $conf, $langs;
947
948
        $error = 0;
949
950
        Config::$dbEngine->begin();
951
952
        $this->fetch($this->id);
953
954
        DolUtils::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($conf->global->MAIN_EXTRAFIELDS_DISABLED))) { // For avoid conflicts if trigger used
982
            $result = $this->deleteExtraFields();
983
            if ($result < 0) {
984
                $error++;
985
                DolUtils::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
            DolUtils::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', $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	$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, $langs;
1027
        global $mysoc;
1028
1029
        // Clean parameters
1030
        $this->login = trim($this->login);
1031
        if (!isset($this->entity)) {
1032
            $this->entity = Globals::$conf->entity; // If not defined, we use default value
1033
        }
1034
        DolUtils::dol_syslog(get_class($this) . "::create login=" . $this->login . ", user=" . (is_object($user) ? $user->id : ''), LOG_DEBUG);
1035
1036
        // Check parameters
1037
        if (!empty($conf->global->USER_MAIL_REQUIRED) && !isValidEMail($this->email)) {
1038
            $langs->load("errors");
1039
            $this->error = $langs->trans("ErrorBadEMail", $this->email);
1040
            return -1;
1041
        }
1042
        if (empty($this->login)) {
1043
            $langs->load("errors");
1044
            $this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Login"));
1045
            return -1;
1046
        }
1047
1048
        $this->datec = dol_now();
1049
1050
        $error = 0;
1051
        Config::$dbEngine->begin();
1052
1053
        $sql = "SELECT login FROM " . MAIN_DB_PREFIX . "user";
1054
        $sql .= " WHERE login ='" . Config::$dbEngine->escape($this->login) . "'";
1055
        $sql .= " AND entity IN (0," . Config::$dbEngine->escape($conf->entity) . ")";
1056
1057
        DolUtils::dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1058
        $resql = Config::$dbEngine->query($sql);
1059
        if ($resql) {
1060
            $num = Config::$dbEngine->num_rows($resql);
1061
            Config::$dbEngine->free($resql);
0 ignored issues
show
Bug introduced by
The method free() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1061
            Config::$dbEngine->/** @scrutinizer ignore-call */ 
1062
                               free($resql);

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...
1062
1063
            if ($num) {
1064
                $this->error = 'ErrorLoginAlreadyExists';
1065
                DolUtils::dol_syslog(get_class($this) . "::create " . $this->error, LOG_WARNING);
1066
                Config::$dbEngine->rollback();
1067
                return -6;
1068
            } else {
1069
                $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user (datec,login,ldap_sid,entity)";
1070
                $sql .= " VALUES('" . Config::$dbEngine->idate($this->datec) . "','" . Config::$dbEngine->escape($this->login) . "','" . Config::$dbEngine->escape($this->ldap_sid) . "'," . Config::$dbEngine->escape($this->entity) . ")";
0 ignored issues
show
Bug introduced by
The method idate() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1070
                $sql .= " VALUES('" . Config::$dbEngine->/** @scrutinizer ignore-call */ idate($this->datec) . "','" . Config::$dbEngine->escape($this->login) . "','" . Config::$dbEngine->escape($this->ldap_sid) . "'," . Config::$dbEngine->escape($this->entity) . ")";

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...
1071
                $result = Config::$dbEngine->query($sql);
1072
1073
                DolUtils::dol_syslog(get_class($this) . "::create", LOG_DEBUG);
1074
                if ($result) {
1075
                    $this->id = Config::$dbEngine->last_insert_id(MAIN_DB_PREFIX . "user");
0 ignored issues
show
Bug introduced by
The method last_insert_id() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1075
                    /** @scrutinizer ignore-call */ $this->id = Config::$dbEngine->last_insert_id(MAIN_DB_PREFIX . "user");

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...
1076
1077
                    // Set default rights
1078
                    if ($this->set_default_rights() < 0) {
1079
                        $this->error = 'ErrorFailedToSetDefaultRightOfUser';
1080
                        Config::$dbEngine->rollback();
1081
                        return -5;
1082
                    }
1083
1084
                    // Update minor fields
1085
                    $result = $this->update($user, 1, 1);
1086
                    if ($result < 0) {
1087
                        Config::$dbEngine->rollback();
1088
                        return -4;
1089
                    }
1090
1091
                    if (!empty($conf->global->STOCK_USERSTOCK_AUTOCREATE)) {
1092
                        require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1093
                        $langs->load("stocks");
1094
                        $entrepot = new Entrepot(Config::$dbEngine);
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Entrepot was not found. Did you mean Entrepot? If so, make sure to prefix the type with \.
Loading history...
1095
                        $entrepot->libelle = $langs->trans("PersonalStock", $this->getFullName($langs));
1096
                        $entrepot->description = $langs->trans("ThisWarehouseIsPersonalStock", $this->getFullName($langs));
1097
                        $entrepot->statut = 1;
1098
                        $entrepot->country_id = $mysoc->country_id;
1099
                        $entrepot->create($user);
1100
                    }
1101
1102
                    if (!$notrigger) {
1103
                        // Call trigger
1104
                        $result = $this->call_trigger('USER_CREATE', $user);
1105
                        if ($result < 0) {
1106
                            $error++;
1107
                        }
1108
                        // End call triggers
1109
                    }
1110
1111
                    if (!$error) {
1112
                        Config::$dbEngine->commit();
1113
                        return $this->id;
1114
                    } else {
1115
                        //$this->error=$interface->error;
1116
                        DolUtils::dol_syslog(get_class($this) . "::create " . $this->error, LOG_ERR);
1117
                        Config::$dbEngine->rollback();
1118
                        return -3;
1119
                    }
1120
                } else {
1121
                    $this->error = Config::$dbEngine->lasterror();
1122
                    Config::$dbEngine->rollback();
1123
                    return -2;
1124
                }
1125
            }
1126
        } else {
1127
            $this->error = Config::$dbEngine->lasterror();
1128
            Config::$dbEngine->rollback();
1129
            return -1;
1130
        }
1131
    }
1132
1133
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1134
    /**
1135
     *  Create a user from a contact object. User will be internal but if contact is linked to a third party, user will be external
1136
     *
1137
     *  @param	Contact	$contact    Object for source contact
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Contact was not found. Did you mean Contact? If so, make sure to prefix the type with \.
Loading history...
1138
     * 	@param  string	$login      Login to force
1139
     *  @param  string	$password   Password to force
1140
     *  @return int 				<0 if error, if OK returns id of created user
1141
     */
1142
    function create_from_contact($contact, $login = '', $password = '')
1143
    {
1144
        // phpcs:enable
1145
        global $conf, $user, $langs;
1146
1147
        $error = 0;
1148
1149
        // Define parameters
1150
        $this->admin = 0;
1151
        $this->lastname = $contact->lastname;
1152
        $this->firstname = $contact->firstname;
1153
        $this->gender = $contact->gender;
1154
        $this->email = $contact->email;
1155
        $this->skype = $contact->skype;
1156
        $this->twitter = $contact->twitter;
1157
        $this->facebook = $contact->facebook;
1158
        $this->office_phone = $contact->phone_pro;
1159
        $this->office_fax = $contact->fax;
1160
        $this->user_mobile = $contact->phone_mobile;
1161
        $this->address = $contact->address;
1162
        $this->zip = $contact->zip;
1163
        $this->town = $contact->town;
1164
        $this->state_id = $contact->state_id;
1165
        $this->country_id = $contact->country_id;
1166
        $this->employee = 0;
1167
1168
        if (empty($login)) {
1169
            $login = strtolower(substr($contact->firstname, 0, 4)) . strtolower(substr($contact->lastname, 0, 4));
1170
        }
1171
        $this->login = $login;
1172
1173
        Config::$dbEngine->begin();
1174
1175
        // Cree et positionne $this->id
1176
        $result = $this->create($user);
1177
        if ($result > 0) {
1178
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1179
            $sql .= " SET fk_socpeople=" . $contact->id;
1180
            if ($contact->socid) {
1181
                $sql .= ", fk_soc=" . $contact->socid;
1182
            }
1183
            $sql .= " WHERE rowid=" . $this->id;
1184
            $resql = Config::$dbEngine->query($sql);
1185
1186
            DolUtils::dol_syslog(get_class($this) . "::create_from_contact", LOG_DEBUG);
1187
            if ($resql) {
1188
                $this->context['createfromcontact'] = 'createfromcontact';
1189
1190
                // Call trigger
1191
                $result = $this->call_trigger('USER_CREATE', $user);
1192
                if ($result < 0) {
1193
                    $error++;
1194
                    Config::$dbEngine->rollback();
1195
                    return -1;
1196
                }
1197
                // End call triggers
1198
1199
                Config::$dbEngine->commit();
1200
                return $this->id;
1201
            } else {
1202
                $this->error = Config::$dbEngine->error();
0 ignored issues
show
Bug introduced by
The method error() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1202
                /** @scrutinizer ignore-call */ $this->error = Config::$dbEngine->error();

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...
1203
1204
                Config::$dbEngine->rollback();
1205
                return -1;
1206
            }
1207
        } else {
1208
            // $this->error deja positionne
1209
            DolUtils::dol_syslog(get_class($this) . "::create_from_contact - 0");
1210
1211
            Config::$dbEngine->rollback();
1212
            return $result;
1213
        }
1214
    }
1215
1216
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1217
    /**
1218
     *  Create a user into database from a member object
1219
     *
1220
     *  @param	Adherent	$member		Object member source
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Adherent was not found. Did you mean Adherent? If so, make sure to prefix the type with \.
Loading history...
1221
     * 	@param	string		$login		Login to force
1222
     *  @return int						<0 if KO, if OK, return id of created account
1223
     */
1224
    function create_from_member($member, $login = '')
1225
    {
1226
        // phpcs:enable
1227
        global $conf, $user, $langs;
1228
1229
        // Positionne parametres
1230
        $this->admin = 0;
1231
        $this->lastname = $member->lastname;
1232
        $this->firstname = $member->firstname;
1233
        $this->gender = $member->gender;
1234
        $this->email = $member->email;
1235
        $this->fk_member = $member->id;
1236
        $this->pass = $member->pass;
1237
        $this->address = $member->address;
1238
        $this->zip = $member->zip;
1239
        $this->town = $member->town;
1240
        $this->state_id = $member->state_id;
1241
        $this->country_id = $member->country_id;
1242
1243
        if (empty($login)) {
1244
            $login = strtolower(substr($member->firstname, 0, 4)) . strtolower(substr($member->lastname, 0, 4));
1245
        }
1246
        $this->login = $login;
1247
1248
        Config::$dbEngine->begin();
1249
1250
        // Create and set $this->id
1251
        $result = $this->create($user);
1252
        if ($result > 0) {
1253
            $newpass = $this->setPassword($user, $this->pass);
1254
            if (is_numeric($newpass) && $newpass < 0) {
1255
                $result = -2;
1256
            }
1257
1258
            if ($result > 0 && $member->fk_soc) { // If member is linked to a thirdparty
1259
                $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1260
                $sql .= " SET fk_soc=" . $member->fk_soc;
1261
                $sql .= " WHERE rowid=" . $this->id;
1262
1263
                DolUtils::dol_syslog(get_class($this) . "::create_from_member", LOG_DEBUG);
1264
                $resql = Config::$dbEngine->query($sql);
1265
                if ($resql) {
1266
                    Config::$dbEngine->commit();
1267
                    return $this->id;
1268
                } else {
1269
                    $this->error = Config::$dbEngine->lasterror();
1270
1271
                    Config::$dbEngine->rollback();
1272
                    return -1;
1273
                }
1274
            }
1275
        }
1276
1277
        if ($result > 0) {
1278
            Config::$dbEngine->commit();
1279
            return $this->id;
1280
        } else {
1281
            // $this->error deja positionne
1282
            Config::$dbEngine->rollback();
1283
            return -2;
1284
        }
1285
    }
1286
1287
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1288
    /**
1289
     *    Assign rights by default
1290
     *
1291
     *    @return     integer erreur <0, si ok renvoi le nbre de droits par defaut positionnes
1292
     */
1293
    function set_default_rights()
1294
    {
1295
        // phpcs:enable
1296
        global $conf;
1297
1298
        $sql = "SELECT id FROM " . MAIN_DB_PREFIX . "rights_def";
1299
        $sql .= " WHERE bydefault = 1";
1300
        $sql .= " AND entity = " . Globals::$conf->entity;
1301
1302
        $resql = Config::$dbEngine->query($sql);
1303
        if ($resql) {
1304
            $num = Config::$dbEngine->num_rows($resql);
1305
            $i = 0;
1306
            $rd = array();
1307
            while ($i < $num) {
1308
                $row = Config::$dbEngine->fetch_row($resql);
0 ignored issues
show
Bug introduced by
The method fetch_row() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1308
                /** @scrutinizer ignore-call */ $row = Config::$dbEngine->fetch_row($resql);

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...
1309
                $rd[$i] = $row[0];
1310
                $i++;
1311
            }
1312
            Config::$dbEngine->free($resql);
1313
        }
1314
        $i = 0;
1315
        while ($i < $num) {
1316
1317
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_rights WHERE fk_user = $this->id AND fk_id=$rd[$i]";
1318
            $result = Config::$dbEngine->query($sql);
1319
1320
            $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_rights (fk_user, fk_id) VALUES ($this->id, $rd[$i])";
1321
            $result = Config::$dbEngine->query($sql);
1322
            if (!$result) {
1323
                return -1;
1324
            }
1325
            $i++;
1326
        }
1327
1328
        return $i;
1329
    }
1330
1331
    /**
1332
     *  	Update a user into database (and also password if this->pass is defined)
1333
     *
1334
     * 		@param	User	$user				User qui fait la mise a jour
1335
     *    	@param  int		$notrigger			1 ne declenche pas les triggers, 0 sinon
1336
     * 		@param	int		$nosyncmember		0=Synchronize linked member (standard info), 1=Do not synchronize linked member
1337
     * 		@param	int		$nosyncmemberpass	0=Synchronize linked member (password), 1=Do not synchronize linked member
1338
     * 		@param	int		$nosynccontact		0=Synchronize linked contact, 1=Do not synchronize linked contact
1339
     *    	@return int 		        		<0 si KO, >=0 si OK
1340
     */
1341
    function update($user, $notrigger = 0, $nosyncmember = 0, $nosyncmemberpass = 0, $nosynccontact = 0)
1342
    {
1343
        global $conf, $langs;
1344
1345
        $nbrowsaffected = 0;
1346
        $error = 0;
1347
1348
        DolUtils::dol_syslog(get_class($this) . "::update notrigger=" . $notrigger . ", nosyncmember=" . $nosyncmember . ", nosyncmemberpass=" . $nosyncmemberpass);
1349
1350
        // Clean parameters
1351
        $this->lastname = trim($this->lastname);
1352
        $this->firstname = trim($this->firstname);
1353
        $this->employee = $this->employee ? $this->employee : 0;
1354
        $this->login = trim($this->login);
1355
        $this->gender = trim($this->gender);
1356
        $this->birth = trim($this->birth);
1357
        $this->pass = trim($this->pass);
1358
        $this->api_key = trim($this->api_key);
1359
        $this->address = $this->address ? trim($this->address) : trim($this->address);
1360
        $this->zip = $this->zip ? trim($this->zip) : trim($this->zip);
1361
        $this->town = $this->town ? trim($this->town) : trim($this->town);
1362
        $this->state_id = trim($this->state_id);
1363
        $this->country_id = ($this->country_id > 0) ? $this->country_id : 0;
1364
        $this->office_phone = trim($this->office_phone);
1365
        $this->office_fax = trim($this->office_fax);
1366
        $this->user_mobile = trim($this->user_mobile);
1367
        $this->email = trim($this->email);
1368
1369
        $this->skype = trim($this->skype);
1370
        $this->twitter = trim($this->twitter);
1371
        $this->facebook = trim($this->facebook);
1372
1373
        $this->job = trim($this->job);
1374
        $this->signature = trim($this->signature);
1375
        $this->note = trim($this->note);
1376
        $this->openid = trim(empty($this->openid) ? '' : $this->openid);    // Avoid warning
1377
        $this->admin = $this->admin ? $this->admin : 0;
1378
        $this->address = empty($this->address) ? '' : $this->address;
1379
        $this->zip = empty($this->zip) ? '' : $this->zip;
1380
        $this->town = empty($this->town) ? '' : $this->town;
1381
        $this->accountancy_code = trim($this->accountancy_code);
1382
        $this->color = empty($this->color) ? '' : $this->color;
1383
        $this->dateemployment = empty($this->dateemployment) ? '' : $this->dateemployment;
1384
        $this->dateemploymentend = empty($this->dateemploymentend) ? '' : $this->dateemploymentend;
1385
1386
        // Check parameters
1387
        if (!empty($conf->global->USER_MAIL_REQUIRED) && !isValidEMail($this->email)) {
1388
            $langs->load("errors");
1389
            $this->error = $langs->trans("ErrorBadEMail", $this->email);
1390
            return -1;
1391
        }
1392
        if (empty($this->login)) {
1393
            $langs->load("errors");
1394
            $this->error = $langs->trans("ErrorFieldRequired", $this->login);
1395
            return -1;
1396
        }
1397
1398
        Config::$dbEngine->begin();
1399
1400
        // Update datas
1401
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET";
1402
        $sql .= " lastname = '" . Config::$dbEngine->escape($this->lastname) . "'";
1403
        $sql .= ", firstname = '" . Config::$dbEngine->escape($this->firstname) . "'";
1404
        $sql .= ", employee = " . $this->employee;
1405
        $sql .= ", login = '" . Config::$dbEngine->escape($this->login) . "'";
1406
        $sql .= ", api_key = " . ($this->api_key ? "'" . Config::$dbEngine->escape($this->api_key) . "'" : "null");
1407
        $sql .= ", gender = " . ($this->gender != -1 ? "'" . Config::$dbEngine->escape($this->gender) . "'" : "null"); // 'man' or 'woman'
1408
        $sql .= ", birth=" . (strval($this->birth) != '' ? "'" . Config::$dbEngine->idate($this->birth) . "'" : 'null');
1409
        if (!empty($user->admin)) {
1410
            $sql .= ", admin = " . $this->admin; // admin flag can be set/unset only by an admin user
1411
        }
1412
        $sql .= ", address = '" . Config::$dbEngine->escape($this->address) . "'";
1413
        $sql .= ", zip = '" . Config::$dbEngine->escape($this->zip) . "'";
1414
        $sql .= ", town = '" . Config::$dbEngine->escape($this->town) . "'";
1415
        $sql .= ", fk_state = " . ((!empty($this->state_id) && $this->state_id > 0) ? "'" . Config::$dbEngine->escape($this->state_id) . "'" : "null");
1416
        $sql .= ", fk_country = " . ((!empty($this->country_id) && $this->country_id > 0) ? "'" . Config::$dbEngine->escape($this->country_id) . "'" : "null");
1417
        $sql .= ", office_phone = '" . Config::$dbEngine->escape($this->office_phone) . "'";
1418
        $sql .= ", office_fax = '" . Config::$dbEngine->escape($this->office_fax) . "'";
1419
        $sql .= ", user_mobile = '" . Config::$dbEngine->escape($this->user_mobile) . "'";
1420
        $sql .= ", email = '" . Config::$dbEngine->escape($this->email) . "'";
1421
        $sql .= ", skype = '" . Config::$dbEngine->escape($this->skype) . "'";
1422
        $sql .= ", twitter = '" . Config::$dbEngine->escape($this->twitter) . "'";
1423
        $sql .= ", facebook = '" . Config::$dbEngine->escape($this->facebook) . "'";
1424
        $sql .= ", job = '" . Config::$dbEngine->escape($this->job) . "'";
1425
        $sql .= ", signature = '" . Config::$dbEngine->escape($this->signature) . "'";
1426
        $sql .= ", accountancy_code = '" . Config::$dbEngine->escape($this->accountancy_code) . "'";
1427
        $sql .= ", color = '" . Config::$dbEngine->escape($this->color) . "'";
1428
        $sql .= ", dateemployment=" . (strval($this->dateemployment) != '' ? "'" . Config::$dbEngine->idate($this->dateemployment) . "'" : 'null');
1429
        $sql .= ", dateemploymentend=" . (strval($this->dateemploymentend) != '' ? "'" . Config::$dbEngine->idate($this->dateemploymentend) . "'" : 'null');
1430
        $sql .= ", note = '" . Config::$dbEngine->escape($this->note) . "'";
1431
        $sql .= ", photo = " . ($this->photo ? "'" . Config::$dbEngine->escape($this->photo) . "'" : "null");
1432
        $sql .= ", openid = " . ($this->openid ? "'" . Config::$dbEngine->escape($this->openid) . "'" : "null");
1433
        $sql .= ", fk_user = " . ($this->fk_user > 0 ? "'" . Config::$dbEngine->escape($this->fk_user) . "'" : "null");
1434
        if (isset($this->thm) || $this->thm != '') {
1435
            $sql .= ", thm= " . ($this->thm != '' ? "'" . Config::$dbEngine->escape($this->thm) . "'" : "null");
1436
        }
1437
        if (isset($this->tjm) || $this->tjm != '') {
1438
            $sql .= ", tjm= " . ($this->tjm != '' ? "'" . Config::$dbEngine->escape($this->tjm) . "'" : "null");
1439
        }
1440
        if (isset($this->salary) || $this->salary != '') {
1441
            $sql .= ", salary= " . ($this->salary != '' ? "'" . Config::$dbEngine->escape($this->salary) . "'" : "null");
1442
        }
1443
        if (isset($this->salaryextra) || $this->salaryextra != '') {
1444
            $sql .= ", salaryextra= " . ($this->salaryextra != '' ? "'" . Config::$dbEngine->escape($this->salaryextra) . "'" : "null");
1445
        }
1446
        $sql .= ", weeklyhours= " . ($this->weeklyhours != '' ? "'" . Config::$dbEngine->escape($this->weeklyhours) . "'" : "null");
1447
        $sql .= ", entity = '" . Config::$dbEngine->escape($this->entity) . "'";
1448
        $sql .= ", default_range = " . ($this->default_range > 0 ? $this->default_range : 'null');
1449
        $sql .= ", default_c_exp_tax_cat = " . ($this->default_c_exp_tax_cat > 0 ? $this->default_c_exp_tax_cat : 'null');
1450
1451
        $sql .= " WHERE rowid = " . $this->id;
1452
1453
        DolUtils::dol_syslog(get_class($this) . "::update", LOG_DEBUG);
1454
        $resql = Config::$dbEngine->query($sql);
1455
        if ($resql) {
1456
            $nbrowsaffected += Config::$dbEngine->affected_rows($resql);
0 ignored issues
show
Bug introduced by
The method affected_rows() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

1456
            $nbrowsaffected += Config::$dbEngine->/** @scrutinizer ignore-call */ affected_rows($resql);

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...
1457
1458
            // Update password
1459
            if (!empty($this->pass)) {
1460
                if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
1461
                    // Si mot de passe saisi et different de celui en base
1462
                    $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass);
1463
                    if (!$nbrowsaffected) {
1464
                        $nbrowsaffected++;
1465
                    }
1466
                }
1467
            }
1468
1469
            // If user is linked to a member, remove old link to this member
1470
            if ($this->fk_member > 0) {
1471
                DolUtils::dol_syslog(get_class($this) . "::update remove link with member. We will recreate it later", LOG_DEBUG);
1472
                $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET fk_member = NULL where fk_member = " . $this->fk_member;
1473
                $resql = Config::$dbEngine->query($sql);
1474
                if (!$resql) {
1475
                    $this->error = Config::$dbEngine->error();
1476
                    Config::$dbEngine->rollback();
1477
                    return -5;
1478
                }
1479
            }
1480
            // Set link to user
1481
            DolUtils::dol_syslog(get_class($this) . "::update set link with member", LOG_DEBUG);
1482
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET fk_member =" . ($this->fk_member > 0 ? $this->fk_member : 'null') . " where rowid = " . $this->id;
1483
            $resql = Config::$dbEngine->query($sql);
1484
            if (!$resql) {
1485
                $this->error = Config::$dbEngine->error();
1486
                Config::$dbEngine->rollback();
1487
                return -5;
1488
            }
1489
1490
            if ($nbrowsaffected) { // If something has changed in data
1491
                if ($this->fk_member > 0 && !$nosyncmember) {
1492
                    DolUtils::dol_syslog(get_class($this) . "::update user is linked with a member. We try to update member too.", LOG_DEBUG);
1493
1494
                    require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
1495
1496
                    // This user is linked with a member, so we also update member information
1497
                    // if this is an update.
1498
                    $adh = new Adherent(Config::$dbEngine);
1499
                    $result = $adh->fetch($this->fk_member);
1500
1501
                    if ($result >= 0) {
1502
                        $adh->firstname = $this->firstname;
1503
                        $adh->lastname = $this->lastname;
1504
                        $adh->login = $this->login;
1505
                        $adh->gender = $this->gender;
1506
                        $adh->birth = $this->birth;
1507
1508
                        $adh->pass = $this->pass;
1509
1510
                        $adh->societe = (empty($adh->societe) && $this->societe_id ? $this->societe_id : $adh->societe);
1511
1512
                        $adh->address = $this->address;
1513
                        $adh->town = $this->town;
1514
                        $adh->zip = $this->zip;
1515
                        $adh->state_id = $this->state_id;
1516
                        $adh->country_id = $this->country_id;
1517
1518
                        $adh->email = $this->email;
1519
1520
                        $adh->skype = $this->skype;
1521
                        $adh->twitter = $this->twitter;
1522
                        $adh->facebook = $this->facebook;
1523
1524
                        $adh->phone = $this->office_phone;
1525
                        $adh->phone_mobile = $this->user_mobile;
1526
1527
                        $adh->user_id = $this->id;
1528
                        $adh->user_login = $this->login;
1529
1530
                        $result = $adh->update($user, 0, 1, 0);
1531
                        if ($result < 0) {
1532
                            $this->error = $adh->error;
1533
                            $this->errors = $adh->errors;
1534
                            DolUtils::dol_syslog(get_class($this) . "::update error after calling adh->update to sync it with user: " . $this->error, LOG_ERR);
1535
                            $error++;
1536
                        }
1537
                    } else {
1538
                        $this->error = $adh->error;
1539
                        $this->errors = $adh->errors;
1540
                        $error++;
1541
                    }
1542
                }
1543
1544
                if ($this->contact_id > 0 && !$nosynccontact) {
1545
                    DolUtils::dol_syslog(get_class($this) . "::update user is linked with a contact. We try to update contact too.", LOG_DEBUG);
1546
1547
                    require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
1548
1549
                    // This user is linked with a contact, so we also update contact information
1550
                    // if this is an update.
1551
                    $tmpobj = new Contact(Config::$dbEngine);
1552
                    $result = $tmpobj->fetch($this->contact_id);
1553
1554
                    if ($result >= 0) {
1555
                        $tmpobj->firstname = $this->firstname;
1556
                        $tmpobj->lastname = $this->lastname;
1557
                        $tmpobj->login = $this->login;
1558
                        $tmpobj->gender = $this->gender;
1559
                        $tmpobj->birth = $this->birth;
1560
1561
                        //$tmpobj->pass=$this->pass;
1562
                        //$tmpobj->societe=(empty($tmpobj->societe) && $this->societe_id ? $this->societe_id : $tmpobj->societe);
1563
1564
                        $tmpobj->email = $this->email;
1565
1566
                        $tmpobj->skype = $this->skype;
1567
                        $tmpobj->twitter = $this->twitter;
1568
                        $tmpobj->facebook = $this->facebook;
1569
1570
                        $tmpobj->phone_pro = $this->office_phone;
1571
                        $tmpobj->phone_mobile = $this->user_mobile;
1572
                        $tmpobj->fax = $this->office_fax;
1573
1574
                        $tmpobj->address = $this->address;
1575
                        $tmpobj->town = $this->town;
1576
                        $tmpobj->zip = $this->zip;
1577
                        $tmpobj->state_id = $this->state_id;
1578
                        $tmpobj->country_id = $this->country_id;
1579
1580
                        $tmpobj->user_id = $this->id;
1581
                        $tmpobj->user_login = $this->login;
1582
1583
                        $result = $tmpobj->update($tmpobj->id, $user, 0, 'update', 1);
1584
                        if ($result < 0) {
1585
                            $this->error = $tmpobj->error;
1586
                            $this->errors = $tmpobj->errors;
1587
                            DolUtils::dol_syslog(get_class($this) . "::update error after calling adh->update to sync it with user: " . $this->error, LOG_ERR);
1588
                            $error++;
1589
                        }
1590
                    } else {
1591
                        $this->error = $tmpobj->error;
1592
                        $this->errors = $tmpobj->errors;
1593
                        $error++;
1594
                    }
1595
                }
1596
            }
1597
1598
            $action = 'update';
1599
1600
            // Actions on extra fields
1601
            if (!$error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) {
1602
                $result = $this->insertExtraFields();
1603
                if ($result < 0) {
1604
                    $error++;
1605
                }
1606
            }
1607
1608
            if (!$error && !$notrigger) {
1609
                // Call trigger
1610
                $result = $this->call_trigger('USER_MODIFY', $user);
1611
                if ($result < 0) {
1612
                    $error++;
1613
                }
1614
                // End call triggers
1615
            }
1616
1617
            if (!$error) {
1618
                Config::$dbEngine->commit();
1619
                return $nbrowsaffected;
1620
            } else {
1621
                DolUtils::dol_syslog(get_class($this) . "::update error=" . $this->error, LOG_ERR);
1622
                Config::$dbEngine->rollback();
1623
                return -1;
1624
            }
1625
        } else {
1626
            $this->error = Config::$dbEngine->lasterror();
1627
            Config::$dbEngine->rollback();
1628
            return -2;
1629
        }
1630
    }
1631
1632
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1633
    /**
1634
     *    Mise a jour en base de la date de derniere connexion d'un utilisateur
1635
     * 	  Fonction appelee lors d'une nouvelle connexion
1636
     *
1637
     *    @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...
1638
     */
1639
    function update_last_login_date()
1640
    {
1641
        // phpcs:enable
1642
        $now = dol_now();
1643
1644
        $sql = "UPDATE " . MAIN_DB_PREFIX . "user SET";
1645
        $sql .= " datepreviouslogin = datelastlogin,";
1646
        $sql .= " datelastlogin = '" . Config::$dbEngine->idate($now) . "',";
1647
        $sql .= " tms = tms";    // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion
1648
        $sql .= " WHERE rowid = " . $this->id;
1649
1650
        DolUtils::dol_syslog(get_class($this) . "::update_last_login_date user->id=" . $this->id . " " . $sql, LOG_DEBUG);
1651
        $resql = Config::$dbEngine->query($sql);
1652
        if ($resql) {
1653
            $this->datepreviouslogin = $this->datelastlogin;
1654
            $this->datelastlogin = $now;
1655
            return 1;
1656
        } else {
1657
            $this->error = Config::$dbEngine->lasterror() . ' sql=' . $sql;
1658
            return -1;
1659
        }
1660
    }
1661
1662
    /**
1663
     *  Change password of a user
1664
     *
1665
     *  @param	User	$user             		Object user of user making change
1666
     *  @param  string	$password         		New password in clear text (to generate if not provided)
1667
     * 	@param	int		$changelater			1=Change password only after clicking on confirm email
1668
     * 	@param	int		$notrigger				1=Does not launch triggers
1669
     * 	@param	int		$nosyncmember	        Do not synchronize linked member
1670
     *  @return string 			          		If OK return clear password, 0 if no change, < 0 if error
1671
     */
1672
    function setPassword($user, $password = '', $changelater = 0, $notrigger = 0, $nosyncmember = 0)
1673
    {
1674
        global $conf, $langs;
1675
        require_once DOL_DOCUMENT_ROOT . '/core/lib/security2.lib.php';
1676
1677
        $error = 0;
1678
1679
        DolUtils::dol_syslog(get_class($this) . "::setPassword user=" . $user->id . " password=" . preg_replace('/./i', '*', $password) . " changelater=" . $changelater . " notrigger=" . $notrigger . " nosyncmember=" . $nosyncmember, LOG_DEBUG);
1680
1681
        // If new password not provided, we generate one
1682
        if (!$password) {
1683
            $password = getRandomPassword(false);
1684
        }
1685
1686
        // Crypt password
1687
        $password_crypted = dol_hash($password);
1688
1689
        // Mise a jour
1690
        if (!$changelater) {
1691
            if (!is_object($this->oldcopy)) {
1692
                $this->oldcopy = clone $this;
1693
            }
1694
1695
            Config::$dbEngine->begin();
1696
1697
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1698
            $sql .= " SET pass_crypted = '" . Config::$dbEngine->escape($password_crypted) . "',";
1699
            $sql .= " pass_temp = null";
1700
            if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
1701
                $sql .= ", pass = null";
1702
            } else {
1703
                $sql .= ", pass = '" . Config::$dbEngine->escape($password) . "'";
1704
            }
1705
            $sql .= " WHERE rowid = " . $this->id;
1706
1707
            DolUtils::dol_syslog(get_class($this) . "::setPassword", LOG_DEBUG);
1708
            $result = Config::$dbEngine->query($sql);
1709
            if ($result) {
1710
                if (Config::$dbEngine->affected_rows($result)) {
1711
                    $this->pass = $password;
1712
                    $this->pass_indatabase = $password;
1713
                    $this->pass_indatabase_crypted = $password_crypted;
1714
1715
                    if ($this->fk_member && !$nosyncmember) {
1716
                        require_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php';
1717
1718
                        // This user is linked with a member, so we also update members informations
1719
                        // if this is an update.
1720
                        $adh = new Adherent(Config::$dbEngine);
1721
                        $result = $adh->fetch($this->fk_member);
1722
1723
                        if ($result >= 0) {
1724
                            $result = $adh->setPassword($user, $this->pass, (empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1), 1); // Cryptage non gere dans module adherent
1725
                            if ($result < 0) {
1726
                                $this->error = $adh->error;
1727
                                DolUtils::dol_syslog(get_class($this) . "::setPassword " . $this->error, LOG_ERR);
1728
                                $error++;
1729
                            }
1730
                        } else {
1731
                            $this->error = $adh->error;
1732
                            $error++;
1733
                        }
1734
                    }
1735
1736
                    DolUtils::dol_syslog(get_class($this) . "::setPassword notrigger=" . $notrigger . " error=" . $error, LOG_DEBUG);
1737
1738
                    if (!$error && !$notrigger) {
1739
                        // Call trigger
1740
                        $result = $this->call_trigger('USER_NEW_PASSWORD', $user);
1741
                        if ($result < 0) {
1742
                            $error++;
1743
                            Config::$dbEngine->rollback();
1744
                            return -1;
1745
                        }
1746
                        // End call triggers
1747
                    }
1748
1749
                    Config::$dbEngine->commit();
1750
                    return $this->pass;
1751
                } else {
1752
                    Config::$dbEngine->rollback();
1753
                    return 0;
1754
                }
1755
            } else {
1756
                Config::$dbEngine->rollback();
1757
                dol_print_error(Config::$dbEngine);
1758
                return -1;
1759
            }
1760
        } else {
1761
            // We store clear password in password temporary field.
1762
            // After receiving confirmation link, we will crypt it and store it in pass_crypted
1763
            $sql = "UPDATE " . MAIN_DB_PREFIX . "user";
1764
            $sql .= " SET pass_temp = '" . Config::$dbEngine->escape($password) . "'";
1765
            $sql .= " WHERE rowid = " . $this->id;
1766
1767
            DolUtils::dol_syslog(get_class($this) . "::setPassword", LOG_DEBUG); // No log
1768
            $result = Config::$dbEngine->query($sql);
1769
            if ($result) {
1770
                return $password;
1771
            } else {
1772
                dol_print_error(Config::$dbEngine);
1773
                return -3;
1774
            }
1775
        }
1776
    }
1777
1778
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1779
    /**
1780
     *  Send new password by email
1781
     *
1782
     *  @param	User	$user           Object user that send email
1783
     *  @param	string	$password       New password
1784
     * 	@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
1785
     *  @return int 		            < 0 si erreur, > 0 si ok
1786
     */
1787
    function send_password($user, $password = '', $changelater = 0)
1788
    {
1789
        // phpcs:enable
1790
        global $conf, $langs;
1791
        global $dolibarr_main_url_root;
1792
1793
        require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
1794
1795
        $msgishtml = 0;
1796
1797
        // Define $msg
1798
        $mesg = '';
1799
1800
        $outputlangs = new Translate("", $conf);
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Translate was not found. Did you mean Translate? If so, make sure to prefix the type with \.
Loading history...
1801
        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)
1802
            $outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT);
1803
        } else { // If user has not defined its own language, we used current language
1804
            $outputlangs = $langs;
1805
        }
1806
1807
        // Load translation files required by the page
1808
        $outputlangs->loadLangs(array("main", "errors", "users", "other"));
1809
1810
        $appli = constant('DOL_APPLICATION_TITLE');
1811
        if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
1812
            $appli = Globals::$conf->global->MAIN_APPLICATION_TITLE;
1813
        }
1814
1815
        $subject = $outputlangs->transnoentitiesnoconv("SubjectNewPassword", $appli);
1816
1817
        // Define $urlwithroot
1818
        $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
1819
        $urlwithroot = $urlwithouturlroot . DOL_URL_ROOT;  // This is to use external domain name found into config file
1820
1821
        if (!$changelater) {
1822
            $url = $urlwithroot . '/';
1823
1824
            $mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived") . ".\n";
1825
            $mesg .= $outputlangs->transnoentitiesnoconv("NewKeyIs") . " :\n\n";
1826
            $mesg .= $outputlangs->transnoentitiesnoconv("Login") . " = " . $this->login . "\n";
1827
            $mesg .= $outputlangs->transnoentitiesnoconv("Password") . " = " . $password . "\n\n";
1828
            $mesg .= "\n";
1829
1830
            $mesg .= $outputlangs->transnoentitiesnoconv("ClickHereToGoTo", $appli) . ': ' . $url . "\n\n";
1831
            $mesg .= "--\n";
1832
            $mesg .= $user->getFullName($outputlangs); // Username that make then sending
1833
1834
            DolUtils::dol_syslog(get_class($this) . "::send_password changelater is off, url=" . $url);
1835
        } else {
1836
            $url = $urlwithroot . '/user/passwordforgotten.php?action=validatenewpassword&username=' . $this->login . "&passwordhash=" . dol_hash($password);
1837
1838
            $mesg .= $outputlangs->transnoentitiesnoconv("RequestToResetPasswordReceived") . "\n";
1839
            $mesg .= $outputlangs->transnoentitiesnoconv("NewKeyWillBe") . " :\n\n";
1840
            $mesg .= $outputlangs->transnoentitiesnoconv("Login") . " = " . $this->login . "\n";
1841
            $mesg .= $outputlangs->transnoentitiesnoconv("Password") . " = " . $password . "\n\n";
1842
            $mesg .= "\n";
1843
            $mesg .= $outputlangs->transnoentitiesnoconv("YouMustClickToChange") . " :\n";
1844
            $mesg .= $url . "\n\n";
1845
            $mesg .= $outputlangs->transnoentitiesnoconv("ForgetIfNothing") . "\n\n";
1846
1847
            DolUtils::dol_syslog(get_class($this) . "::send_password changelater is on, url=" . $url);
1848
        }
1849
1850
        $mailfile = new CMailFile(
0 ignored issues
show
Bug introduced by
The type Alixar\Base\CMailFile was not found. Did you mean CMailFile? If so, make sure to prefix the type with \.
Loading history...
1851
            $subject, $this->email, Globals::$conf->global->MAIN_MAIL_EMAIL_FROM, $mesg, array(), array(), array(), '', '', 0, $msgishtml
1852
        );
1853
1854
        if ($mailfile->sendfile()) {
1855
            return 1;
1856
        } else {
1857
            $langs->trans("errors");
1858
            $this->error = $langs->trans("ErrorFailedToSendPassword") . ' ' . $mailfile->error;
1859
            return -1;
1860
        }
1861
    }
1862
1863
    /**
1864
     * 		Renvoie la derniere erreur fonctionnelle de manipulation de l'objet
1865
     *
1866
     * 		@return    string      chaine erreur
1867
     */
1868
    function error()
1869
    {
1870
        return $this->error;
1871
    }
1872
1873
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1874
    /**
1875
     *    	Read clicktodial information for user
1876
     *
1877
     * 		@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...
1878
     */
1879
    function fetch_clicktodial()
1880
    {
1881
        // phpcs:enable
1882
        $sql = "SELECT url, login, pass, poste ";
1883
        $sql .= " FROM " . MAIN_DB_PREFIX . "user_clicktodial as u";
1884
        $sql .= " WHERE u.fk_user = " . $this->id;
1885
1886
        $resql = Config::$dbEngine->query($sql);
1887
        if ($resql) {
1888
            if (Config::$dbEngine->num_rows($resql)) {
1889
                $obj = Config::$dbEngine->fetch_object($resql);
1890
1891
                $this->clicktodial_url = $obj->url;
1892
                $this->clicktodial_login = $obj->login;
1893
                $this->clicktodial_password = $obj->pass;
1894
                $this->clicktodial_poste = $obj->poste;
1895
            }
1896
1897
            $this->clicktodial_loaded = 1; // Data loaded (found or not)
1898
1899
            Config::$dbEngine->free($resql);
1900
            return 1;
1901
        } else {
1902
            $this->error = Config::$dbEngine->error();
1903
            return -1;
1904
        }
1905
    }
1906
1907
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1908
    /**
1909
     *  Update clicktodial info
1910
     *
1911
     *  @return	integer
1912
     */
1913
    function update_clicktodial()
1914
    {
1915
        // phpcs:enable
1916
        Config::$dbEngine->begin();
1917
1918
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_clicktodial";
1919
        $sql .= " WHERE fk_user = " . $this->id;
1920
1921
        DolUtils::dol_syslog(get_class($this) . '::update_clicktodial', LOG_DEBUG);
1922
        $result = Config::$dbEngine->query($sql);
1923
1924
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_clicktodial";
1925
        $sql .= " (fk_user,url,login,pass,poste)";
1926
        $sql .= " VALUES (" . $this->id;
1927
        $sql .= ", '" . Config::$dbEngine->escape($this->clicktodial_url) . "'";
1928
        $sql .= ", '" . Config::$dbEngine->escape($this->clicktodial_login) . "'";
1929
        $sql .= ", '" . Config::$dbEngine->escape($this->clicktodial_password) . "'";
1930
        $sql .= ", '" . Config::$dbEngine->escape($this->clicktodial_poste) . "')";
1931
1932
        DolUtils::dol_syslog(get_class($this) . '::update_clicktodial', LOG_DEBUG);
1933
        $result = Config::$dbEngine->query($sql);
1934
        if ($result) {
1935
            Config::$dbEngine->commit();
1936
            return 1;
1937
        } else {
1938
            Config::$dbEngine->rollback();
1939
            $this->error = Config::$dbEngine->lasterror();
1940
            return -1;
1941
        }
1942
    }
1943
1944
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1945
    /**
1946
     *  Add user into a group
1947
     *
1948
     *  @param	int	$group      Id of group
1949
     *  @param  int		$entity     Entity
1950
     *  @param  int		$notrigger  Disable triggers
1951
     *  @return int  				<0 if KO, >0 if OK
1952
     */
1953
    function SetInGroup($group, $entity, $notrigger = 0)
1954
    {
1955
        // phpcs:enable
1956
        global $conf, $langs, $user;
1957
1958
        $error = 0;
1959
1960
        Config::$dbEngine->begin();
1961
1962
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user";
1963
        $sql .= " WHERE fk_user  = " . $this->id;
1964
        $sql .= " AND fk_usergroup = " . $group;
1965
        $sql .= " AND entity = " . $entity;
1966
1967
        $result = Config::$dbEngine->query($sql);
1968
1969
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "usergroup_user (entity, fk_user, fk_usergroup)";
1970
        $sql .= " VALUES (" . $entity . "," . $this->id . "," . $group . ")";
1971
1972
        $result = Config::$dbEngine->query($sql);
1973
        if ($result) {
1974
            if (!$error && !$notrigger) {
1975
                $this->newgroupid = $group;    // deprecated. Remove this.
1976
                $this->context = array('audit' => $langs->trans("UserSetInGroup"), 'newgroupid' => $group);
1977
1978
                // Call trigger
1979
                $result = $this->call_trigger('USER_MODIFY', $user);
1980
                if ($result < 0) {
1981
                    $error++;
1982
                }
1983
                // End call triggers
1984
            }
1985
1986
            if (!$error) {
1987
                Config::$dbEngine->commit();
1988
                return 1;
1989
            } else {
1990
                DolUtils::dol_syslog(get_class($this) . "::SetInGroup " . $this->error, LOG_ERR);
1991
                Config::$dbEngine->rollback();
1992
                return -2;
1993
            }
1994
        } else {
1995
            $this->error = Config::$dbEngine->lasterror();
1996
            Config::$dbEngine->rollback();
1997
            return -1;
1998
        }
1999
    }
2000
2001
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2002
    /**
2003
     *  Remove a user from a group
2004
     *
2005
     *  @param	int   $group       Id of group
2006
     *  @param  int		$entity      Entity
2007
     *  @param  int		$notrigger   Disable triggers
2008
     *  @return int  			     <0 if KO, >0 if OK
2009
     */
2010
    function RemoveFromGroup($group, $entity, $notrigger = 0)
2011
    {
2012
        // phpcs:enable
2013
        global $conf, $langs, $user;
2014
2015
        $error = 0;
2016
2017
        Config::$dbEngine->begin();
2018
2019
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "usergroup_user";
2020
        $sql .= " WHERE fk_user  = " . $this->id;
2021
        $sql .= " AND fk_usergroup = " . $group;
2022
        $sql .= " AND entity = " . $entity;
2023
2024
        $result = Config::$dbEngine->query($sql);
2025
        if ($result) {
2026
            if (!$error && !$notrigger) {
2027
                $this->oldgroupid = $group;    // deprecated. Remove this.
2028
                $this->context = array('audit' => $langs->trans("UserRemovedFromGroup"), 'oldgroupid' => $group);
2029
2030
                // Call trigger
2031
                $result = $this->call_trigger('USER_MODIFY', $user);
2032
                if ($result < 0) {
2033
                    $error++;
2034
                }
2035
                // End call triggers
2036
            }
2037
2038
            if (!$error) {
2039
                Config::$dbEngine->commit();
2040
                return 1;
2041
            } else {
2042
                $this->error = $interface->error;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $interface seems to be never defined.
Loading history...
2043
                DolUtils::dol_syslog(get_class($this) . "::RemoveFromGroup " . $this->error, LOG_ERR);
2044
                Config::$dbEngine->rollback();
2045
                return -2;
2046
            }
2047
        } else {
2048
            $this->error = Config::$dbEngine->lasterror();
2049
            Config::$dbEngine->rollback();
2050
            return -1;
2051
        }
2052
    }
2053
2054
    /**
2055
     *  Return a link with photo
2056
     * 	Use this->id,this->photo
2057
     *
2058
     * 	@param	int		$width			Width of image
2059
     * 	@param	int		$height			Height of image
2060
     *  @param	string	$cssclass		Force a css class
2061
     * 	@param	string	$imagesize		'mini', 'small' or '' (original)
2062
     * 	@return	string					String with URL link
2063
     */
2064
    function getPhotoUrl($width, $height, $cssclass = '', $imagesize = '')
2065
    {
2066
        // $result = '<a href="' . DOL_URL_ROOT . '/user/card.php?id=' . $this->id . '">';
2067
        $result = '<a href="' . BASE_URI . '?controller=user&method=card&id=' . $this->id . '">';
2068
        $result .= Form::showphoto('userphoto', $this, $width, $height, 0, $cssclass, $imagesize);
2069
        $result .= '</a>';
2070
2071
        return $result;
2072
    }
2073
2074
    /**
2075
     *  Return a link to the user card (with optionaly the picto)
2076
     * 	Use this->id,this->lastname, this->firstname
2077
     *
2078
     * 	@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)
2079
     * 	@param	string	$option						On what the link point to ('leave', 'nolink', )
2080
     *  @param  integer $infologin      			0=Add default info tooltip, 1=Add complete info tooltip, -1=No info tooltip
2081
     *  @param	integer	$notooltip					1=Disable tooltip on picto and name
2082
     *  @param	int		$maxlen						Max length of visible user name
2083
     *  @param	int		$hidethirdpartylogo			Hide logo of thirdparty if user is external user
2084
     *  @param  string  $mode               		''=Show firstname and lastname, 'firstname'=Show only firstname, 'login'=Show login
2085
     *  @param  string  $morecss            		Add more css on link
2086
     *  @param  int     $save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2087
     * 	@return	string								String with URL
2088
     */
2089
    function getNomUrl($withpictoimg = 0, $option = '', $infologin = 0, $notooltip = 0, $maxlen = 24, $hidethirdpartylogo = 0, $mode = '', $morecss = '', $save_lastsearch_value = -1)
2090
    {
2091
        global $langs, $conf, $db, $hookmanager, $user;
2092
        global $dolibarr_main_authentication, $dolibarr_main_demo;
2093
        global $menumanager;
2094
2095
        if (!$user->rights->user->user->lire && $user->id != $this->id) {
2096
            $option = 'nolink';
2097
        }
2098
2099
        if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) {
2100
            $withpictoimg = 0;
2101
        }
2102
2103
        $result = '';
2104
        $label = '';
2105
        $link = '';
2106
        $linkstart = '';
2107
        $linkend = '';
2108
2109
        if (!empty($this->photo)) {
2110
            $label .= '<div class="photointooltip">';
2111
            $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
2112
            $label .= '</div><div style="clear: both;"></div>';
2113
        }
2114
2115
        // Info Login
2116
        $label .= '<div class="centpercent">';
2117
        $label .= '<u>' . $langs->trans("User") . '</u><br>';
2118
        $label .= '<b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs, '');
2119
        if (!empty($this->login)) {
2120
            $label .= '<br><b>' . $langs->trans('Login') . ':</b> ' . $this->login;
2121
        }
2122
        $label .= '<br><b>' . $langs->trans("EMail") . ':</b> ' . $this->email;
2123
        if (!empty($this->admin)) {
2124
            $label .= '<br><b>' . $langs->trans("Administrator") . '</b>: ' . yn($this->admin);
2125
        }
2126
        if (!empty($this->socid)) { // Add thirdparty for external users
2127
            $thirdpartystatic = new Societe($db);
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
2128
            $thirdpartystatic->fetch($this->socid);
2129
            if (empty($hidethirdpartylogo)) {
2130
                $companylink = ' ' . $thirdpartystatic->getNomUrl(2, (($option == 'nolink') ? 'nolink' : '')); // picto only of company
2131
            }
2132
            $company = ' (' . $langs->trans("Company") . ': ' . $thirdpartystatic->name . ')';
2133
        }
2134
        $type = ($this->socid ? $langs->trans("External") . $company : $langs->trans("Internal"));
2135
        $label .= '<br><b>' . $langs->trans("Type") . ':</b> ' . $type;
2136
        $label .= '<br><b>' . $langs->trans("Status") . '</b>: ' . $this->getLibStatut(0);
2137
        $label .= '</div>';
2138
        if ($infologin > 0) {
2139
            $label .= '<br>';
2140
            $label .= '<br><u>' . $langs->trans("Connection") . '</u>';
2141
            $label .= '<br><b>' . $langs->trans("IPAddress") . '</b>: ' . $_SERVER["REMOTE_ADDR"];
2142
            if (!empty($conf->global->MAIN_MODULE_MULTICOMPANY)) {
2143
                $label .= '<br><b>' . $langs->trans("ConnectedOnMultiCompany") . ':</b> ' . Globals::$conf->entity . ' (user entity ' . $this->entity . ')';
2144
            }
2145
            $label .= '<br><b>' . $langs->trans("AuthenticationMode") . ':</b> ' . $_SESSION["dol_authmode"] . (empty($dolibarr_main_demo) ? '' : ' (demo)');
2146
            $label .= '<br><b>' . $langs->trans("ConnectedSince") . ':</b> ' . dol_print_date($this->datelastlogin, "dayhour", 'tzuser');
2147
            $label .= '<br><b>' . $langs->trans("PreviousConnexion") . ':</b> ' . dol_print_date($this->datepreviouslogin, "dayhour", 'tzuser');
2148
            $label .= '<br><b>' . $langs->trans("CurrentTheme") . ':</b> ' . Globals::$conf->theme;
2149
            $label .= '<br><b>' . $langs->trans("CurrentMenuManager") . ':</b> ' . $menumanager->name;
2150
            $s = picto_from_langcode($langs->getDefaultLang());
2151
            $label .= '<br><b>' . $langs->trans("CurrentUserLanguage") . ':</b> ' . ($s ? $s . ' ' : '') . $langs->getDefaultLang();
2152
            $label .= '<br><b>' . $langs->trans("Browser") . ':</b> ' . Globals::$conf->browser->name . ($conf->browser->version ? ' ' . Globals::$conf->browser->version : '') . ' (' . $_SERVER['HTTP_USER_AGENT'] . ')';
2153
            $label .= '<br><b>' . $langs->trans("Layout") . ':</b> ' . Globals::$conf->browser->layout;
2154
            $label .= '<br><b>' . $langs->trans("Screen") . ':</b> ' . $_SESSION['dol_screenwidth'] . ' x ' . $_SESSION['dol_screenheight'];
2155
            if ($conf->browser->layout == 'phone') {
2156
                $label .= '<br><b>' . $langs->trans("Phone") . ':</b> ' . $langs->trans("Yes");
2157
            }
2158
            if (!empty($_SESSION["disablemodules"])) {
2159
                $label .= '<br><b>' . $langs->trans("DisabledModules") . ':</b> <br>' . join(', ', explode(',', $_SESSION["disablemodules"]));
2160
            }
2161
        }
2162
        if ($infologin < 0) {
2163
            $label = '';
2164
        }
2165
2166
        // $url = DOL_URL_ROOT . '/user/card.php?id=' . $this->id;
2167
        $url = BASE_URI . '?controller=user&method=card&id=' . $this->id;
2168
        if ($option == 'leave') {
2169
            //$url = DOL_URL_ROOT . '/holiday/list.php?id=' . $this->id;
2170
            $url = BASE_URI . '?controller=holiday&method=list&id=' . $this->id;
2171
        }
2172
        if ($option != 'nolink') {
2173
            // Add param to save lastsearch_values or not
2174
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2175
            if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2176
                $add_save_lastsearch_values = 1;
2177
            }
2178
            if ($add_save_lastsearch_values) {
2179
                $url .= '&save_lastsearch_values=1';
2180
            }
2181
        }
2182
2183
        $linkstart = '<a href="' . $url . '"';
2184
        $linkclose = "";
2185
        if (empty($notooltip)) {
2186
            if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2187
                $langs->load("users");
2188
                $label = $langs->trans("ShowUser");
2189
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
2190
            }
2191
            $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
2192
            $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"';
2193
2194
            /*
2195
              $hookmanager->initHooks(array('userdao'));
2196
              $parameters=array('id'=>$this->id);
2197
              $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
2198
              if ($reshook > 0) $linkclose = $hookmanager->resPrint;
2199
             */
2200
        }
2201
2202
        $linkstart .= $linkclose . '>';
2203
        $linkend = '</a>';
2204
2205
        //if ($withpictoimg == -1) $result.='<div class="nowrap">';
2206
        $result .= (($option == 'nolink') ? '' : $linkstart);
2207
        if ($withpictoimg) {
2208
            $paddafterimage = '';
2209
            if (abs($withpictoimg) == 1) {
2210
                $paddafterimage = 'style="margin-right: 3px;"';
2211
            }
2212
            // Only picto
2213
            if ($withpictoimg > 0) {
2214
                $picto = '<!-- picto user --><div class="inline-block nopadding userimg' . ($morecss ? ' ' . $morecss : '') . '">' . img_object('', 'user', $paddafterimage . ' ' . ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1) . '</div>';
2215
            } else { // Picto must be a photo
2216
                $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>';
2217
            }
2218
            $result .= $picto;
2219
        }
2220
        if ($withpictoimg > -2 && $withpictoimg != 2) {
2221
            if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2222
                $result .= '<div class="inline-block nopadding valignmiddle usertext' . ((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled') . ($morecss ? ' ' . $morecss : '') . '">';
2223
            }
2224
            if ($mode == 'login') {
2225
                $result .= dol_trunc($this->login, $maxlen);
2226
            } else {
2227
                $result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : -1), $maxlen);
2228
            }
2229
            if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
2230
                $result .= '</div>';
2231
        }
2232
        $result .= (($option == 'nolink') ? '' : $linkend);
2233
        //if ($withpictoimg == -1) $result.='</div>';
2234
2235
        $result .= $companylink;
2236
2237
        global $action;
2238
        $hookmanager->initHooks(array('userdao'));
2239
        $parameters = array('id' => $this->id, 'getnomurl' => $result);
2240
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action);    // Note that $action and $object may have been modified by some hooks
2241
        if ($reshook > 0) {
2242
            $result = $hookmanager->resPrint;
2243
        } else {
2244
            $result .= $hookmanager->resPrint;
2245
        }
2246
2247
        return $result;
2248
    }
2249
2250
    /**
2251
     *  Return clickable link of login (eventualy with picto)
2252
     *
2253
     * 	@param	int		$withpicto		Include picto into link
2254
     * 	@param	string	$option			Sur quoi pointe le lien
2255
     * 	@return	string					Chaine avec URL
2256
     */
2257
    function getLoginUrl($withpicto = 0, $option = '')
2258
    {
2259
        global $langs, $user;
2260
2261
        $result = '';
2262
2263
        // $linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2264
        $linkstart = '<a href="' . BASE_URI . '?controller=user&method=card&id=' . $this->id . '">';
2265
        $linkend = '</a>';
2266
2267
        //Check user's rights to see an other user
2268
        if ((!$user->rights->user->user->lire && $this->id != $user->id)) {
2269
            $option = 'nolink';
2270
        }
2271
2272
        if ($option == 'xxx') {
2273
            //$linkstart = '<a href="'.DOL_URL_ROOT.'/user/card.php?id='.$this->id.'">';
2274
            $linkstart = '<a href="' . BASE_URI . '?controller=user&method=card.php&id=' . $this->id . '">';
2275
            $linkend = '</a>';
2276
        }
2277
2278
        if ($option == 'nolink') {
2279
            $linkstart = '';
2280
            $linkend = '';
2281
        }
2282
2283
        $result .= $linkstart;
2284
        if ($withpicto) {
2285
            $result .= img_object($langs->trans("ShowUser"), 'user', 'class="paddingright"');
2286
        }
2287
        $result .= $this->login;
2288
        $result .= $linkend;
2289
        return $result;
2290
    }
2291
2292
    /**
2293
     *  Return label of status of user (active, inactive)
2294
     *
2295
     *  @param	int		$mode          0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2296
     *  @return	string 			       Label of status
2297
     */
2298
    function getLibStatut($mode = 0)
2299
    {
2300
        return $this->LibStatut($this->statut, $mode);
2301
    }
2302
2303
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2304
    /**
2305
     *  Renvoi le libelle d'un statut donne
2306
     *
2307
     *  @param	int		$statut        	Id statut
2308
     *  @param  int		$mode          	0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2309
     *  @return string 			       	Label of status
2310
     */
2311
    function LibStatut($statut, $mode = 0)
2312
    {
2313
        // phpcs:enable
2314
        global $langs;
2315
        $langs->load('users');
2316
2317
        if ($mode == 0) {
2318
            if ($statut == 1) {
2319
                return $langs->trans('Enabled');
2320
            } elseif ($statut == 0) {
2321
                return $langs->trans('Disabled');
2322
            }
2323
        } elseif ($mode == 1) {
2324
            if ($statut == 1) {
2325
                return $langs->trans('Enabled');
2326
            } elseif ($statut == 0) {
2327
                return $langs->trans('Disabled');
2328
            }
2329
        } elseif ($mode == 2) {
2330
            if ($statut == 1) {
2331
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"') . ' ' . $langs->trans('Enabled');
2332
            } elseif ($statut == 0) {
2333
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"') . ' ' . $langs->trans('Disabled');
2334
            }
2335
        } elseif ($mode == 3) {
2336
            if ($statut == 1) {
2337
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"');
2338
            } elseif ($statut == 0) {
2339
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"');
2340
            }
2341
        } elseif ($mode == 4) {
2342
            if ($statut == 1) {
2343
                return img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"') . ' ' . $langs->trans('Enabled');
2344
            } elseif ($statut == 0) {
2345
                return img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"') . ' ' . $langs->trans('Disabled');
2346
            }
2347
        } elseif ($mode == 5) {
2348
            if ($statut == 1) {
2349
                return $langs->trans('Enabled') . ' ' . img_picto($langs->trans('Enabled'), 'statut4', 'class="pictostatus"');
2350
            } elseif ($statut == 0) {
2351
                return $langs->trans('Disabled') . ' ' . img_picto($langs->trans('Disabled'), 'statut5', 'class="pictostatus"');
2352
            }
2353
        }
2354
    }
2355
2356
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2357
    /**
2358
     * 	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2359
     *
2360
     * 	@param	array	$info		Info array loaded by _load_ldap_info
2361
     * 	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2362
     * 								1=Return parent (ou=xxx,dc=aaa,dc=bbb)
2363
     * 								2=Return key only (RDN) (uid=qqq)
2364
     * 	@return	string				DN
2365
     */
2366
    function _load_ldap_dn($info, $mode = 0)
2367
    {
2368
        // phpcs:enable
2369
        global $conf;
2370
        $dn = '';
2371
        if ($mode == 0) {
2372
            $dn = Globals::$conf->global->LDAP_KEY_USERS . "=" . $info[$conf->global->LDAP_KEY_USERS] . "," . Globals::$conf->global->LDAP_USER_DN;
2373
        } elseif ($mode == 1) {
2374
            $dn = Globals::$conf->global->LDAP_USER_DN;
2375
        } elseif ($mode == 2) {
2376
            $dn = Globals::$conf->global->LDAP_KEY_USERS . "=" . $info[$conf->global->LDAP_KEY_USERS];
2377
        }
2378
        return $dn;
2379
    }
2380
2381
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2382
    /**
2383
     * 	Initialize the info array (array of LDAP values) that will be used to call LDAP functions
2384
     *
2385
     * 	@return		array		Tableau info des attributs
2386
     */
2387
    function _load_ldap_info()
2388
    {
2389
        // phpcs:enable
2390
        global $conf, $langs;
2391
2392
        $info = array();
2393
        $keymodified = false;
2394
2395
        // Object classes
2396
        $info["objectclass"] = explode(',', Globals::$conf->global->LDAP_USER_OBJECT_CLASS);
2397
2398
        $this->fullname = $this->getFullName($langs);
2399
2400
        // Possible LDAP KEY (constname => varname)
2401
        $ldapkey = array(
2402
            'LDAP_FIELD_FULLNAME' => 'fullname',
2403
            'LDAP_FIELD_NAME' => 'lastname',
2404
            'LDAP_FIELD_FIRSTNAME' => 'firstname',
2405
            'LDAP_FIELD_LOGIN' => 'login',
2406
            'LDAP_FIELD_LOGIN_SAMBA' => 'login',
2407
            'LDAP_FIELD_PHONE' => 'office_phone',
2408
            'LDAP_FIELD_MOBILE' => 'user_mobile',
2409
            'LDAP_FIELD_FAX' => 'office_fax',
2410
            'LDAP_FIELD_MAIL' => 'email',
2411
            'LDAP_FIELD_SID' => 'ldap_sid',
2412
            'LDAP_FIELD_SKYPE' => 'skype',
2413
            'LDAP_FIELD_TWITTER' => 'twitter',
2414
            'LDAP_FIELD_FACEBOOK' => 'facebook'
2415
        );
2416
2417
        // Champs
2418
        foreach ($ldapkey as $constname => $varname) {
2419
            if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2420
                $info[$conf->global->$constname] = $this->$varname;
2421
2422
                // Check if it is the LDAP key and if its value has been changed
2423
                if (!empty($conf->global->LDAP_KEY_USERS) && Globals::$conf->global->LDAP_KEY_USERS == Globals::$conf->global->$constname) {
2424
                    if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) {
2425
                        $keymodified = true; // For check if LDAP key has been modified
2426
                    }
2427
                }
2428
            }
2429
        }
2430
        if ($this->address && !empty($conf->global->LDAP_FIELD_ADDRESS)) {
2431
            $info[$conf->global->LDAP_FIELD_ADDRESS] = $this->address;
2432
        }
2433
        if ($this->zip && !empty($conf->global->LDAP_FIELD_ZIP)) {
2434
            $info[$conf->global->LDAP_FIELD_ZIP] = $this->zip;
2435
        }
2436
        if ($this->town && !empty($conf->global->LDAP_FIELD_TOWN)) {
2437
            $info[$conf->global->LDAP_FIELD_TOWN] = $this->town;
2438
        }
2439
        if ($this->note_public && !empty($conf->global->LDAP_FIELD_DESCRIPTION)) {
2440
            $info[$conf->global->LDAP_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_public, 2);
2441
        }
2442
        if ($this->socid > 0) {
2443
            $soc = new Societe(Config::$dbEngine);
2444
            $soc->fetch($this->socid);
2445
2446
            $info[$conf->global->LDAP_FIELD_COMPANY] = $soc->name;
2447
            if ($soc->client == 1) {
2448
                $info["businessCategory"] = "Customers";
2449
            }
2450
            if ($soc->client == 2) {
2451
                $info["businessCategory"] = "Prospects";
2452
            }
2453
            if ($soc->fournisseur == 1) {
2454
                $info["businessCategory"] = "Suppliers";
2455
            }
2456
        }
2457
2458
        // When password is modified
2459
        if (!empty($this->pass)) {
2460
            if (!empty($conf->global->LDAP_FIELD_PASSWORD)) {
2461
                $info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2462
            }
2463
            if (!empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED)) {
2464
                $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
2465
            }
2466
        }
2467
        // Set LDAP password if possible
2468
        elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') { // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2469
            if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2470
                // Just for the default MD5 !
2471
                if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2472
                    if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED)) {
2473
                        $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase_crypted, 5); // Create OpenLDAP MD5 password from Dolibarr MD5 password
2474
                    }
2475
                }
2476
            }
2477
            // Use $this->pass_indatabase value if exists
2478
            elseif (!empty($this->pass_indatabase)) {
2479
                if (!empty($conf->global->LDAP_FIELD_PASSWORD)) {
2480
                    $info[$conf->global->LDAP_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2481
                }
2482
                if (!empty($conf->global->LDAP_FIELD_PASSWORD_CRYPTED)) {
2483
                    $info[$conf->global->LDAP_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
2484
                }
2485
            }
2486
        }
2487
2488
        if ($conf->global->LDAP_SERVER_TYPE == 'egroupware') {
2489
            $info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
2490
2491
            $info['uidnumber'] = $this->id;
2492
2493
            $info['phpgwTz'] = 0;
2494
            $info['phpgwMailType'] = 'INTERNET';
2495
            $info['phpgwMailHomeType'] = 'INTERNET';
2496
2497
            $info["phpgwContactTypeId"] = 'n';
2498
            $info["phpgwContactCatId"] = 0;
2499
            $info["phpgwContactAccess"] = "public";
2500
2501
            if (dol_strlen($this->egroupware_id) == 0) {
2502
                $this->egroupware_id = 1;
2503
            }
2504
2505
            $info["phpgwContactOwner"] = $this->egroupware_id;
2506
2507
            if ($this->email) {
2508
                $info["rfc822Mailbox"] = $this->email;
2509
            }
2510
            if ($this->phone_mobile) {
2511
                $info["phpgwCellTelephoneNumber"] = $this->phone_mobile;
2512
            }
2513
        }
2514
2515
        return $info;
2516
    }
2517
2518
    /**
2519
     *  Initialise an instance with random values.
2520
     *  Used to build previews or test instances.
2521
     * 	id must be 0 if object instance is a specimen.
2522
     *
2523
     *  @return	void
2524
     */
2525
    function initAsSpecimen()
2526
    {
2527
        global $user, $langs;
2528
2529
        $now = dol_now();
2530
2531
        // Initialise parametres
2532
        $this->id = 0;
2533
        $this->ref = 'SPECIMEN';
2534
        $this->specimen = 1;
2535
2536
        $this->lastname = 'DOLIBARR';
2537
        $this->firstname = 'SPECIMEN';
2538
        $this->gender = 'man';
2539
        $this->note = 'This is a note';
2540
        $this->email = '[email protected]';
2541
        $this->skype = 'skypepseudo';
2542
        $this->twitter = 'twitterpseudo';
2543
        $this->facebook = 'facebookpseudo';
2544
        $this->office_phone = '0999999999';
2545
        $this->office_fax = '0999999998';
2546
        $this->user_mobile = '0999999997';
2547
        $this->admin = 0;
2548
        $this->login = 'dolibspec';
2549
        $this->pass = 'dolibspec';
2550
        //$this->pass_indatabase='dolibspec';									Set after a fetch
2551
        //$this->pass_indatabase_crypted='e80ca5a88c892b0aaaf7e154853bccab';	Set after a fetch
2552
        $this->datec = $now;
2553
        $this->datem = $now;
2554
2555
        $this->datelastlogin = $now;
2556
        $this->datepreviouslogin = $now;
2557
        $this->statut = 1;
2558
2559
        //$this->societe_id = 1;	For external users
2560
        //$this->contact_id = 1;	For external users
2561
        $this->entity = 1;
2562
    }
2563
2564
    /**
2565
     *  Load info of user object
2566
     *
2567
     *  @param  int		$id     Id of user to load
2568
     *  @return	void
2569
     */
2570
    function info($id)
2571
    {
2572
        $sql = "SELECT u.rowid, u.login as ref, u.datec,";
2573
        $sql .= " u.tms as date_modification, u.entity";
2574
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2575
        $sql .= " WHERE u.rowid = " . $id;
2576
2577
        $result = Config::$dbEngine->query($sql);
2578
        if ($result) {
2579
            if (Config::$dbEngine->num_rows($result)) {
2580
                $obj = Config::$dbEngine->fetch_object($result);
2581
2582
                $this->id = $obj->rowid;
2583
2584
                $this->ref = (!$obj->ref) ? $obj->rowid : $obj->ref;
2585
                $this->date_creation = Config::$dbEngine->jdate($obj->datec);
0 ignored issues
show
Bug introduced by
The method jdate() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

2585
                /** @scrutinizer ignore-call */ $this->date_creation = Config::$dbEngine->jdate($obj->datec);

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...
2586
                $this->date_modification = Config::$dbEngine->jdate($obj->date_modification);
2587
                $this->entity = $obj->entity;
2588
            }
2589
2590
            Config::$dbEngine->free($result);
2591
        } else {
2592
            dol_print_error(Config::$dbEngine);
2593
        }
2594
    }
2595
2596
    /**
2597
     *    Return number of mass Emailing received by this contacts with its email
2598
     *
2599
     *    @return       int     Number of EMailings
2600
     */
2601
    function getNbOfEMailings()
2602
    {
2603
        $sql = "SELECT count(mc.email) as nb";
2604
        $sql .= " FROM " . MAIN_DB_PREFIX . "mailing_cibles as mc";
2605
        $sql .= " WHERE mc.email = '" . Config::$dbEngine->escape($this->email) . "'";
2606
        $sql .= " AND mc.statut NOT IN (-1,0)";      // -1 erreur, 0 non envoye, 1 envoye avec succes
2607
2608
        $resql = Config::$dbEngine->query($sql);
2609
        if ($resql) {
2610
            $obj = Config::$dbEngine->fetch_object($resql);
2611
            $nb = $obj->nb;
2612
2613
            Config::$dbEngine->free($resql);
2614
            return $nb;
2615
        } else {
2616
            $this->error = Config::$dbEngine->error();
2617
            return -1;
2618
        }
2619
    }
2620
2621
    /**
2622
     *  Return number of existing users
2623
     *
2624
     *  @param	string	$limitTo	Limit to '' or 'active'
2625
     *  @param	string	$option		'superadmin' = return for entity 0 only
2626
     *  @param	int		$admin		Filter on admin tag
2627
     *  @return int  				Number of users
2628
     */
2629
    function getNbOfUsers($limitTo, $option = '', $admin = -1)
2630
    {
2631
        global $conf;
2632
2633
        $sql = "SELECT count(rowid) as nb";
2634
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
2635
        if ($option == 'superadmin') {
2636
            $sql .= " WHERE entity = 0";
2637
            if ($admin >= 0) {
2638
                $sql .= " AND admin = " . $admin;
2639
            }
2640
        } else {
2641
            $sql .= " WHERE entity IN (" . getEntity('user', 0) . ")";
2642
            if ($limitTo == 'active') {
2643
                $sql .= " AND statut = 1";
2644
            }
2645
            if ($admin >= 0) {
2646
                $sql .= " AND admin = " . $admin;
2647
            }
2648
        }
2649
2650
        $resql = Config::$dbEngine->query($sql);
2651
        if ($resql) {
2652
            $obj = Config::$dbEngine->fetch_object($resql);
2653
            $nb = $obj->nb;
2654
2655
            Config::$dbEngine->free($resql);
2656
            return $nb;
2657
        } else {
2658
            $this->error = Config::$dbEngine->lasterror();
2659
            return -1;
2660
        }
2661
    }
2662
2663
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2664
    /**
2665
     *  Update user using data from the LDAP
2666
     *
2667
     *  @param	ldapuser	$ldapuser	Ladp User
2668
     *
2669
     *  @return int  				<0 if KO, >0 if OK
2670
     */
2671
    function update_ldap2dolibarr(&$ldapuser)
2672
    {
2673
        // phpcs:enable
2674
        // TODO: Voir pourquoi le update met à jour avec toutes les valeurs vide (global $user écrase ?)
2675
        global $user, $conf;
2676
2677
        $this->firstname = $ldapuser->{$conf->global->LDAP_FIELD_FIRSTNAME};
2678
        $this->lastname = $ldapuser->{$conf->global->LDAP_FIELD_NAME};
2679
        $this->login = $ldapuser->{$conf->global->LDAP_FIELD_LOGIN};
2680
        $this->pass = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD};
2681
        $this->pass_indatabase_crypted = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD_CRYPTED};
2682
2683
        $this->office_phone = $ldapuser->{$conf->global->LDAP_FIELD_PHONE};
2684
        $this->user_mobile = $ldapuser->{$conf->global->LDAP_FIELD_MOBILE};
2685
        $this->office_fax = $ldapuser->{$conf->global->LDAP_FIELD_FAX};
2686
        $this->email = $ldapuser->{$conf->global->LDAP_FIELD_MAIL};
2687
        $this->skype = $ldapuser->{$conf->global->LDAP_FIELD_SKYPE};
2688
        $this->twitter = $ldapuser->{$conf->global->LDAP_FIELD_TWITTER};
2689
        $this->facebook = $ldapuser->{$conf->global->LDAP_FIELD_FACEBOOK};
2690
        $this->ldap_sid = $ldapuser->{$conf->global->LDAP_FIELD_SID};
2691
2692
        $this->job = $ldapuser->{$conf->global->LDAP_FIELD_TITLE};
2693
        $this->note = $ldapuser->{$conf->global->LDAP_FIELD_DESCRIPTION};
2694
2695
        $result = $this->update($user);
2696
2697
        DolUtils::dol_syslog(get_class($this) . "::update_ldap2dolibarr result=" . $result, LOG_DEBUG);
2698
2699
        return $result;
2700
    }
2701
2702
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2703
    /**
2704
     * Return and array with all instanciated first level children users of current user
2705
     *
2706
     * @return	void
2707
     * @see getAllChildIds
2708
     */
2709
    function get_children()
2710
    {
2711
        // phpcs:enable
2712
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "user";
2713
        $sql .= " WHERE fk_user = " . $this->id;
2714
2715
        DolUtils::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...
2716
        $res = Config::$dbEngine->query($sql);
2717
        if ($res) {
2718
            $users = array();
2719
            while ($rec = Config::$dbEngine->fetch_array($res)) {
0 ignored issues
show
Bug introduced by
The method fetch_array() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

2719
            while ($rec = Config::$dbEngine->/** @scrutinizer ignore-call */ fetch_array($res)) {

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...
2720
                $user = new User(Config::$dbEngine);
2721
                $user->fetch($rec['rowid']);
2722
                $users[] = $user;
2723
            }
2724
            return $users;
2725
        } else {
2726
            dol_print_error(Config::$dbEngine);
2727
            return -1;
2728
        }
2729
    }
2730
2731
    /**
2732
     * 	Load this->parentof that is array(id_son=>id_parent, ...)
2733
     *
2734
     * 	@return		int		<0 if KO, >0 if OK
2735
     */
2736
    private function loadParentOf()
2737
    {
2738
        global $conf;
2739
2740
        $this->parentof = array();
2741
2742
        // Load array[child]=parent
2743
        $sql = "SELECT fk_user as id_parent, rowid as id_son";
2744
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
2745
        $sql .= " WHERE fk_user <> 0";
2746
        $sql .= " AND entity IN (" . getEntity('user') . ")";
2747
2748
        DolUtils::dol_syslog(get_class($this) . "::loadParentOf", LOG_DEBUG);
2749
        $resql = Config::$dbEngine->query($sql);
2750
        if ($resql) {
2751
            while ($obj = Config::$dbEngine->fetch_object($resql)) {
2752
                $this->parentof[$obj->id_son] = $obj->id_parent;
2753
            }
2754
            return 1;
2755
        } else {
2756
            dol_print_error(Config::$dbEngine);
2757
            return -1;
2758
        }
2759
    }
2760
2761
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2762
    /**
2763
     * 	Reconstruit l'arborescence hierarchique des users sous la forme d'un tableau
2764
     * 	Set and return this->users that is an array sorted according to tree with arrays of:
2765
     * 				id = id user
2766
     * 				lastname
2767
     * 				firstname
2768
     * 				fullname = nom avec chemin complet du user
2769
     * 				fullpath = chemin complet compose des id: "_grandparentid_parentid_id"
2770
     *
2771
     *  @param      int		$deleteafterid      Removed all users including the leaf $deleteafterid (and all its child) in user tree.
2772
     *  @param		string	$filter				SQL filter on users
2773
     * 	@return		array		      		  	Array of users $this->users. Note: $this->parentof is also set.
2774
     */
2775
    function get_full_tree($deleteafterid = 0, $filter = '')
2776
    {
2777
        // phpcs:enable
2778
        global $conf, $user;
2779
        global $hookmanager;
2780
2781
        // Actions hooked (by external module)
2782
        $hookmanager->initHooks(array('userdao'));
2783
2784
        $this->users = array();
2785
2786
        // Init this->parentof that is array(id_son=>id_parent, ...)
2787
        $this->loadParentOf();
2788
2789
        // Init $this->users array
2790
        $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
2791
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2792
        // Add fields from hooks
2793
        $parameters = array();
2794
        $reshook = $hookmanager->executeHooks('printUserListWhere', $parameters);    // Note that $action and $object may have been modified by hook
2795
        if ($reshook > 0) {
2796
            $sql .= $hookmanager->resPrint;
2797
        } else {
2798
            $sql .= " WHERE u.entity IN (" . getEntity('user') . ")";
2799
        }
2800
        if ($filter) {
2801
            $sql .= " AND " . $filter;
2802
        }
2803
2804
        DolUtils::dol_syslog(get_class($this) . "::get_full_tree get user list", LOG_DEBUG);
2805
        $resql = Config::$dbEngine->query($sql);
2806
        if ($resql) {
2807
            $i = 0;
2808
            while ($obj = Config::$dbEngine->fetch_object($resql)) {
2809
                $this->users[$obj->rowid]['rowid'] = $obj->rowid;
2810
                $this->users[$obj->rowid]['id'] = $obj->rowid;
2811
                $this->users[$obj->rowid]['fk_user'] = $obj->fk_user;
2812
                $this->users[$obj->rowid]['fk_soc'] = $obj->fk_soc;
2813
                $this->users[$obj->rowid]['firstname'] = $obj->firstname;
2814
                $this->users[$obj->rowid]['lastname'] = $obj->lastname;
2815
                $this->users[$obj->rowid]['login'] = $obj->login;
2816
                $this->users[$obj->rowid]['statut'] = $obj->statut;
2817
                $this->users[$obj->rowid]['entity'] = $obj->entity;
2818
                $this->users[$obj->rowid]['email'] = $obj->email;
2819
                $this->users[$obj->rowid]['gender'] = $obj->gender;
2820
                $this->users[$obj->rowid]['admin'] = $obj->admin;
2821
                $this->users[$obj->rowid]['photo'] = $obj->photo;
2822
                $i++;
2823
            }
2824
        } else {
2825
            dol_print_error(Config::$dbEngine);
2826
            return -1;
2827
        }
2828
2829
        // We add the fullpath property to each elements of first level (no parent exists)
2830
        DolUtils::dol_syslog(get_class($this) . "::get_full_tree call to build_path_from_id_user", LOG_DEBUG);
2831
        foreach ($this->users as $key => $val) {
2832
            $result = $this->build_path_from_id_user($key, 0); // Process a branch from the root user key (this user has no parent)
2833
            if ($result < 0) {
2834
                $this->error = 'ErrorLoopInHierarchy';
2835
                return -1;
2836
            }
2837
        }
2838
2839
        // Exclude leaf including $deleteafterid from tree
2840
        if ($deleteafterid) {
2841
            //print "Look to discard user ".$deleteafterid."\n";
2842
            $keyfilter1 = '^' . $deleteafterid . '$';
2843
            $keyfilter2 = '_' . $deleteafterid . '$';
2844
            $keyfilter3 = '^' . $deleteafterid . '_';
2845
            $keyfilter4 = '_' . $deleteafterid . '_';
2846
            foreach ($this->users as $key => $val) {
2847
                if (preg_match('/' . $keyfilter1 . '/', $val['fullpath']) || preg_match('/' . $keyfilter2 . '/', $val['fullpath']) || preg_match('/' . $keyfilter3 . '/', $val['fullpath']) || preg_match('/' . $keyfilter4 . '/', $val['fullpath'])) {
2848
                    unset($this->users[$key]);
2849
                }
2850
            }
2851
        }
2852
2853
        DolUtils::dol_syslog(get_class($this) . "::get_full_tree dol_sort_array", LOG_DEBUG);
2854
        $this->users = dol_sort_array($this->users, 'fullname', 'asc', true, false);
2855
2856
        //var_dump($this->users);
2857
2858
        return $this->users;
2859
    }
2860
2861
    /**
2862
     * 	Return list of all child users id in herarchy (all sublevels).
2863
     *  Note: Calling this function also reset full list of users into $this->users.
2864
     *
2865
     *  @param      int      $addcurrentuser    1=Add also current user id to the list.
2866
     * 	@return		array		      		  	Array of user id lower than user (all levels under user). This overwrite this->users.
2867
     *  @see get_children
2868
     */
2869
    function getAllChildIds($addcurrentuser = 0)
2870
    {
2871
        $childids = array();
2872
2873
        if (isset($this->cache_childids[$this->id])) {
2874
            $childids = $this->cache_childids[$this->id];
2875
        } else {
2876
            // Init this->users
2877
            $this->get_full_tree();
2878
2879
            $idtoscan = $this->id;
2880
2881
            DolUtils::dol_syslog("Build childid for id = " . $idtoscan);
2882
            foreach ($this->users as $id => $val) {
2883
                //var_dump($val['fullpath']);
2884
                if (preg_match('/_' . $idtoscan . '_/', $val['fullpath'])) {
2885
                    $childids[$val['id']] = $val['id'];
2886
                }
2887
            }
2888
        }
2889
        $this->cache_childids[$this->id] = $childids;
2890
2891
        if ($addcurrentuser) {
2892
            $childids[$this->id] = $this->id;
2893
        }
2894
2895
        return $childids;
2896
    }
2897
2898
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2899
    /**
2900
     * 	For user id_user and its childs available in this->users, define property fullpath and fullname.
2901
     *  Function called by get_full_tree().
2902
     *
2903
     * 	@param		int		$id_user		id_user entry to update
2904
     * 	@param		int		$protection		Deep counter to avoid infinite loop (no more required, a protection is added with array useridfound)
2905
     * 	@return		int                     < 0 if KO (infinit loop), >= 0 if OK
2906
     */
2907
    function build_path_from_id_user($id_user, $protection = 0)
2908
    {
2909
        // phpcs:enable
2910
        DolUtils::dol_syslog(get_class($this) . "::build_path_from_id_user id_user=" . $id_user . " protection=" . $protection, LOG_DEBUG);
2911
2912
        if (!empty($this->users[$id_user]['fullpath'])) {
2913
            // Already defined
2914
            DolUtils::dol_syslog(get_class($this) . "::build_path_from_id_user fullpath and fullname already defined", LOG_WARNING);
2915
            return 0;
2916
        }
2917
2918
        // Define fullpath and fullname
2919
        $this->users[$id_user]['fullpath'] = '_' . $id_user;
2920
        $this->users[$id_user]['fullname'] = $this->users[$id_user]['lastname'];
2921
        $i = 0;
2922
        $cursor_user = $id_user;
2923
2924
        $useridfound = array($id_user);
2925
        while (!empty($this->parentof[$cursor_user])) {
2926
            if (in_array($this->parentof[$cursor_user], $useridfound)) {
2927
                DolUtils::dol_syslog("The hierarchy of user has a recursive loop", LOG_WARNING);
2928
                return -1;     // Should not happen. Protection against looping hierarchy
2929
            }
2930
            $useridfound[] = $this->parentof[$cursor_user];
2931
            $this->users[$id_user]['fullpath'] = '_' . $this->parentof[$cursor_user] . $this->users[$id_user]['fullpath'];
2932
            $this->users[$id_user]['fullname'] = $this->users[$this->parentof[$cursor_user]]['lastname'] . ' >> ' . $this->users[$id_user]['fullname'];
2933
            $i++;
2934
            $cursor_user = $this->parentof[$cursor_user];
2935
        }
2936
2937
        // We count number of _ to have level
2938
        $this->users[$id_user]['level'] = dol_strlen(preg_replace('/[^_]/i', '', $this->users[$id_user]['fullpath']));
2939
2940
        return 1;
2941
    }
2942
2943
    /**
2944
     * Function used to replace a thirdparty id with another one.
2945
     *
2946
     * @param DoliDB $db Database handler
2947
     * @param int $origin_id Old thirdparty id
2948
     * @param int $dest_id New thirdparty id
2949
     * @return bool
2950
     */
2951
    public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
0 ignored issues
show
Bug introduced by
The type Alixar\Base\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
2952
    {
2953
        $tables = array(
2954
            'user',
2955
        );
2956
2957
        return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2958
    }
2959
2960
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2961
    /**
2962
     *      Charge indicateurs this->nb pour le tableau de bord
2963
     *
2964
     *      @return     int         <0 if KO, >0 if OK
2965
     */
2966
    function load_state_board()
2967
    {
2968
        // phpcs:enable
2969
        global $conf;
2970
2971
        $this->nb = array();
2972
2973
        $sql = "SELECT count(u.rowid) as nb";
2974
        $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
2975
        $sql .= " WHERE u.statut > 0";
2976
        //$sql.= " AND employee != 0";
2977
        $sql .= " AND u.entity IN (" . getEntity('user') . ")";
2978
2979
        $resql = Config::$dbEngine->query($sql);
2980
        if ($resql) {
2981
            while ($obj = Config::$dbEngine->fetch_object($resql)) {
2982
                $this->nb["users"] = $obj->nb;
2983
            }
2984
            Config::$dbEngine->free($resql);
2985
            return 1;
2986
        } else {
2987
            dol_print_error(Config::$dbEngine);
2988
            $this->error = Config::$dbEngine->error();
2989
            return -1;
2990
        }
2991
    }
2992
2993
    /**
2994
     *  Create a document onto disk according to template module.
2995
     *
2996
     * 	@param	    string		$modele			Force model to use ('' to not force)
2997
     * 	@param		Translate	$outputlangs	Object langs to use for output
2998
     *  @param      int			$hidedetails    Hide details of lines
2999
     *  @param      int			$hidedesc       Hide description
3000
     *  @param      int			$hideref        Hide ref
3001
     *  @param   null|array  $moreparams     Array to provide more information
3002
     * 	@return     int         				0 if KO, 1 if OK
3003
     */
3004
    public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
3005
    {
3006
        global $conf, $user, $langs;
3007
3008
        $langs->load("user");
3009
3010
        // Positionne le modele sur le nom du modele a utiliser
3011
        if (!dol_strlen($modele)) {
3012
            if (!empty($conf->global->USER_ADDON_PDF)) {
3013
                $modele = Globals::$conf->global->USER_ADDON_PDF;
3014
            } else {
3015
                $modele = 'bluesky';
3016
            }
3017
        }
3018
3019
        $modelpath = "core/modules/user/doc/";
3020
3021
        return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
3022
    }
3023
3024
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3025
    /**
3026
     *  Return property of user from its id
3027
     *
3028
     *  @param	int		$rowid      id of contact
3029
     *  @param  string	$mode       'email' or 'mobile'
3030
     *  @return string  			Email of user with format: "Full name <email>"
3031
     */
3032
    function user_get_property($rowid, $mode)
3033
    {
3034
        // phpcs:enable
3035
        $user_property = '';
3036
3037
        if (empty($rowid)) {
3038
            return '';
3039
        }
3040
3041
        $sql = "SELECT rowid, email, user_mobile, civility, lastname, firstname";
3042
        $sql .= " FROM " . MAIN_DB_PREFIX . "user";
3043
        $sql .= " WHERE rowid = '" . $rowid . "'";
3044
3045
        $resql = Config::$dbEngine->query($sql);
3046
        if ($resql) {
3047
            $nump = Config::$dbEngine->num_rows($resql);
3048
3049
            if ($nump) {
3050
                $obj = Config::$dbEngine->fetch_object($resql);
3051
3052
                if ($mode == 'email') {
3053
                    $user_property = dolGetFirstLastname($obj->firstname, $obj->lastname) . " <" . $obj->email . ">";
3054
                } else if ($mode == 'mobile') {
3055
                    $user_property = $obj->user_mobile;
3056
                }
3057
            }
3058
            return $user_property;
3059
        } else {
3060
            dol_print_error(Config::$dbEngine);
3061
        }
3062
    }
3063
3064
    /**
3065
     * 	Load all objects into $this->users
3066
     *
3067
     *  @param	string		$sortorder		sort order
3068
     *  @param	string		$sortfield		sort field
3069
     *  @param	int			$limit			limit page
3070
     *  @param	int			$offset			page
3071
     *  @param	array		$filter			Filter array. Example array('field'=>'valueforlike', 'customurl'=>...)
3072
     *  @param  string      $filtermode		Filter mode (AND or OR)
3073
     *  @return int							<0 if KO, >0 if OK
3074
     */
3075
    function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = array(), $filtermode = 'AND')
3076
    {
3077
        global $conf;
3078
3079
        $sql = "SELECT t.rowid";
3080
        $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t ';
3081
        $sql .= " WHERE 1";
3082
3083
        // Manage filter
3084
        $sqlwhere = array();
3085
        if (!empty($filter)) {
3086
            foreach ($filter as $key => $value) {
3087
                if ($key == 't.rowid') {
3088
                    $sqlwhere[] = $key . '=' . $value;
3089
                } elseif (strpos($key, 'date') !== false) {
3090
                    $sqlwhere[] = $key . ' = \'' . Config::$dbEngine->idate($value) . '\'';
3091
                } elseif ($key == 'customsql') {
3092
                    $sqlwhere[] = $value;
3093
                } else {
3094
                    $sqlwhere[] = $key . ' LIKE \'%' . Config::$dbEngine->escape($value) . '%\'';
3095
                }
3096
            }
3097
        }
3098
        if (count($sqlwhere) > 0) {
3099
            $sql .= ' AND (' . implode(' ' . $filtermode . ' ', $sqlwhere) . ')';
3100
        }
3101
        $sql .= Config::$dbEngine->order($sortfield, $sortorder);
0 ignored issues
show
Bug introduced by
The method order() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

3101
        $sql .= Config::$dbEngine->/** @scrutinizer ignore-call */ 
3102
                                   order($sortfield, $sortorder);

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...
3102
        if ($limit) {
3103
            $sql .= Config::$dbEngine->plimit($limit + 1, $offset);
0 ignored issues
show
Bug introduced by
The method plimit() does not exist on Alxarafe\Database\Engine. ( Ignorable by Annotation )

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

3103
            $sql .= Config::$dbEngine->/** @scrutinizer ignore-call */ 
3104
                                       plimit($limit + 1, $offset);

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...
3104
        }
3105
3106
        DolUtils::dol_syslog(get_class($this) . "::" . __METHOD__, LOG_DEBUG);
3107
3108
        $resql = Config::$dbEngine->query($sql);
3109
        if ($resql) {
3110
            $this->users = array();
3111
            $num = Config::$dbEngine->num_rows($resql);
3112
            if ($num) {
3113
                while ($obj = Config::$dbEngine->fetch_object($resql)) {
3114
                    $line = new self(Config::$dbEngine);
3115
                    $result = $line->fetch($obj->rowid);
3116
                    if ($result > 0 && !empty($line->id)) {
3117
                        $this->users[$obj->rowid] = clone $line;
3118
                    }
3119
                }
3120
                Config::$dbEngine->free($resql);
3121
            }
3122
            return $num;
3123
        } else {
3124
            $this->errors[] = Config::$dbEngine->lasterror();
3125
            return -1;
3126
        }
3127
    }
3128
}
3129