Passed
Push — MODEL_LIB_240928 ( d6fbb6 )
by Rafael
48:22
created

Contact::getNoEmail()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 0
dl 0
loc 16
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2002-2004  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004       Benoit Mortier              <[email protected]>
5
 * Copyright (C) 2004-2013  Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
7
 * Copyright (C) 2007       Franky Van Liedekerke       <[email protected]>
8
 * Copyright (C) 2008       Raphael Bertrand (Resultic) <[email protected]>
9
 * Copyright (C) 2013       Florian Henry		  	    <[email protected]>
10
 * Copyright (C) 2013       Alexandre Spangaro 	        <[email protected]>
11
 * Copyright (C) 2013       Juanjo Menent	 	        <[email protected]>
12
 * Copyright (C) 2015       Marcos García               <[email protected]>
13
 * Copyright (C) 2019       Nicolas ZABOURI 	        <[email protected]>
14
 * Copyright (C) 2020       Open-Dsi  	                <[email protected]>
15
 * Copyright (C) 2024       Frédéric France             <[email protected]>
16
 * Copyright (C) 2024		MDW							<[email protected]>
17
 * Copyright (C) 2024       Rafael San José             <[email protected]>
18
 *
19
 * This program is free software; you can redistribute it and/or modify
20
 * it under the terms of the GNU General Public License as published by
21
 * the Free Software Foundation; either version 3 of the License, or
22
 * (at your option) any later version.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU General Public License
30
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
31
 */
32
33
namespace Dolibarr\Code\Contact\Classes;
34
35
use Dolibarr\Code\Categories\Classes\Categorie;
36
use Dolibarr\Code\Contact\Trait\Mailing;
37
use Dolibarr\Code\Core\Classes\Form;
38
use Dolibarr\Code\Core\Traits\CommonPeople;
39
use Dolibarr\Code\Core\Traits\CommonSocialNetworks;
40
use Dolibarr\Code\User\Classes\User;
41
use Dolibarr\Core\Base\CommonObject;
42
use DoliDB;
43
use Exception;
44
45
/**
46
 *  \file       htdocs/contact/class/contact.class.php
47
 *  \ingroup    societe
48
 *  \brief      File of contacts class
49
 */
50
51
/**
52
 *  Class to manage contact/addresses
53
 */
54
class Contact extends CommonObject
55
{
56
    use CommonSocialNetworks;
57
    use CommonPeople;
0 ignored issues
show
introduced by
The trait Dolibarr\Code\Core\Traits\CommonPeople requires some properties which are not provided by Dolibarr\Code\Contact\Classes\Contact: $MAIN_SHOW_REGION_IN_STATE_SELECT, $user_mobile, $attributes, $company, $global, $nom, $use_javascript_ajax, $societe, $phone
Loading history...
58
    use Mailing;
59
60
    /**
61
     * @var string ID to identify managed object
62
     */
63
    public $element = 'contact';
64
65
    /**
66
     * @var string Name of table without prefix where object is stored
67
     */
68
    public $table_element = 'socpeople';
69
70
    /**
71
     * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
72
     */
73
    public $picto = 'contact';
74
75
    /**
76
     *  'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
77
     *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
78
     *  'label' the translation key.
79
     *  'enabled' is a condition when the field must be managed.
80
     *  'position' is the sort order of field.
81
     *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
82
     *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
83
     *  'noteditable' says if field is not editable (1 or 0)
84
     *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
85
     *  'index' if we want an index in database.
86
     *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...).
87
     *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
88
     *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
89
     *  'css' is the CSS style to use on field. For example: 'maxwidth200'
90
     *  'help' is a string visible as a tooltip on field
91
     *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
92
     *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
93
     *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
94
     *  'comment' is not used. You can store here any text of your choice. It is not used by application.
95
     *
96
     *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
97
     */
98
99
    // BEGIN MODULEBUILDER PROPERTIES
100
    /**
101
     * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}>  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string,array{type:...ring>,comment?:string}> at position 16 could not be parsed: Expected '}' at position 16, but found 'int'.
Loading history...
102
     */
103
    public $fields = array(
104
        'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'noteditable' => 1, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id', 'css' => 'left'),
105
        'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 3, 'notnull' => 1, 'position' => 30, 'index' => 1),
106
        'ref_ext' => array('type' => 'varchar(255)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 3, 'position' => 35),
107
        'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => 3, 'position' => 40),
108
        'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => 1, 'position' => 45, 'showoncombobox' => 1, 'searchall' => 1),
109
        'name_alias' => array('type' => 'varchar(255)', 'label' => 'Name alias', 'enabled' => 1, 'visible' => -1, 'position' => 46, 'searchall' => 1),
110
        'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => 1, 'position' => 50, 'showoncombobox' => 1, 'searchall' => 1),
111
        'poste' => array('type' => 'varchar(80)', 'label' => 'PostOrFunction', 'enabled' => 1, 'visible' => -1, 'position' => 52),
112
        'address' => array('type' => 'varchar(255)', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 55),
113
        'zip' => array('type' => 'varchar(25)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 60),
114
        'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 65),
115
        'fk_departement' => array('type' => 'integer', 'label' => 'Fk departement', 'enabled' => 1, 'visible' => 3, 'position' => 70),
116
        'fk_pays' => array('type' => 'integer', 'label' => 'Fk pays', 'enabled' => 1, 'visible' => 3, 'position' => 75),
117
        'fk_soc' => array('type' => 'integer', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => 1, 'position' => 77, 'searchall' => 1),
118
        'birthday' => array('type' => 'date', 'label' => 'Birthday', 'enabled' => 1, 'visible' => -1, 'position' => 80),
119
        'phone' => array('type' => 'varchar(30)', 'label' => 'Phone', 'enabled' => 1, 'visible' => 1, 'position' => 90, 'searchall' => 1),
120
        'phone_perso' => array('type' => 'varchar(30)', 'label' => 'PhonePerso', 'enabled' => 1, 'visible' => -1, 'position' => 95, 'searchall' => 1),
121
        'phone_mobile' => array('type' => 'varchar(30)', 'label' => 'PhoneMobile', 'enabled' => 1, 'visible' => 1, 'position' => 100, 'searchall' => 1),
122
        'fax' => array('type' => 'varchar(30)', 'label' => 'Fax', 'enabled' => 1, 'visible' => -1, 'position' => 105, 'searchall' => 1),
123
        'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => 1, 'position' => 110, 'searchall' => 1),
124
        'socialnetworks' => array('type' => 'text', 'label' => 'SocialNetworks', 'enabled' => 1, 'visible' => 3, 'position' => 115),
125
        'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => 3, 'position' => 170),
126
        'priv' => array('type' => 'smallint(6)', 'label' => 'ContactVisibility', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 175),
127
        'fk_stcommcontact' => array('type' => 'integer', 'label' => 'ProspectStatus', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 220),
128
        'fk_prospectcontactlevel' => array('type' => 'varchar(12)', 'label' => 'ProspectLevel', 'enabled' => 1, 'visible' => -1, 'position' => 255),
129
        //no more used. Replace by a scan of email into mailing_unsubscribe. 'no_email' =>array('type'=>'smallint(6)', 'label'=>'No_Email', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>180),
130
        'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 3, 'position' => 195, 'searchall' => 1),
131
        'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 3, 'position' => 200, 'searchall' => 1),
132
        'default_lang' => array('type' => 'varchar(6)', 'label' => 'Default lang', 'enabled' => 1, 'visible' => 3, 'position' => 205),
133
        'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => 3, 'position' => 210),
134
        'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 300),
135
        'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 305),
136
        'fk_user_creat' => array('type' => 'integer', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => 3, 'position' => 310),
137
        'fk_user_modif' => array('type' => 'integer', 'label' => 'UserModif', 'enabled' => 1, 'visible' => 3, 'position' => 315),
138
        'statut' => array('type' => 'tinyint(4)', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 500),
139
        'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -1, 'position' => 1000),
140
    );
141
142
    public $civility_id; // In fact we store civility_code
143
    public $civility_code;
144
    public $civility;
145
146
    /**
147
     * @var string gender
148
     */
149
    public $gender;
150
151
    /**
152
     * @var int egroupware_id
153
     */
154
    //private $egroupware_id;
155
156
    /**
157
     * @var int birthday_alert
158
     */
159
    public $birthday_alert;
160
161
    /**
162
     * @var string The civilite code, not an integer
163
     * @deprecated
164
     * @see $civility_code
165
     */
166
    public $civilite;
167
168
    /**
169
     * @var string fullname
170
     */
171
    public $fullname;
172
173
    /**
174
     * @var string Name alias
175
     */
176
    public $name_alias;
177
178
    /**
179
     * @var string Address
180
     */
181
    public $address;
182
183
    /**
184
     * @var string zip code
185
     */
186
    public $zip;
187
188
    /**
189
     * @var string Town
190
     */
191
    public $town;
192
193
    /**
194
     * @var int  Id of department
195
     */
196
    public $state_id;
197
198
    /**
199
     * @var string  Code of department
200
     */
201
    public $state_code;
202
203
    /**
204
     * @var string  Label of department
205
     */
206
    public $state;
207
208
    /**
209
     * @var string  Job Position
210
     */
211
    public $poste;
212
213
    /**
214
     * @var int Thirdparty ID
215
     */
216
    public $socid;      // both socid and fk_soc are used
217
    public $fk_soc;     // both socid and fk_soc are used
218
219
    /**
220
     * @var string Thirdparty name
221
     */
222
    public $socname;
223
224
    /**
225
     * @var int  Status 0=inactive, 1=active
226
     */
227
    public $statut;
228
229
    public $code;
230
231
    /**
232
     * Email
233
     * @var string
234
     */
235
    public $email;
236
237
    /**
238
     * Email
239
     * @var string
240
     * @deprecated
241
     * @see $email
242
     */
243
    public $mail;
244
245
    /**
246
     * URL
247
     * @var string
248
     */
249
    public $url;
250
251
    /**
252
     * Unsubscribe all : 1 = contact has globally unsubscribed of all mass emailing
253
     * @var int
254
     * @deprecated Has been replaced by a search into llx_mailing_unsubscribe
255
     */
256
    public $no_email;
257
258
    /**
259
     * Array of social-networks
260
     * @var array
261
     */
262
    public $socialnetworks;
263
264
    /**
265
     * @var string filename for photo
266
     */
267
    public $photo;
268
269
    /**
270
     * @var string phone pro (professional/business)
271
     */
272
    public $phone_pro;
273
274
    /**
275
     * @var string phone perso (personal/private)
276
     */
277
    public $phone_perso;
278
279
    /**
280
     * @var string phone mobile
281
     */
282
    public $phone_mobile;
283
284
    /**
285
     * @var string fax
286
     */
287
    public $fax;
288
289
    /**
290
     * Private or public
291
     * @var int
292
     */
293
    public $priv;
294
295
    /**
296
     * @var int|string Date
297
     */
298
    public $birthday;
299
300
    /**
301
     * @var string language for contact communication  -- only with multilanguage enabled
302
     */
303
    public $default_lang;
304
305
    /**
306
     * @var int Number of invoices for which he is contact
307
     */
308
    public $ref_facturation;
309
310
    /**
311
     * @var int  Number of contracts for which he is contact
312
     */
313
    public $ref_contrat;
314
315
    /**
316
     * @var int Number of orders for which he is contact
317
     */
318
    public $ref_commande;
319
320
    /**
321
     * @var int Number of proposals for which he is contact
322
     */
323
    public $ref_propal;
324
325
    /**
326
     * @var int user ID
327
     */
328
    public $user_id;
329
330
    /**
331
     * @var string user login
332
     */
333
    public $user_login;
334
335
    // END MODULEBUILDER PROPERTIES
336
337
338
    /**
339
     * Old copy
340
     * @var static
341
     */
342
    public $oldcopy; // To contains a clone of this when we need to save old properties of object
343
344
    /**
345
     * @var array roles
346
     */
347
    public $roles;
348
349
    public $cacheprospectstatus = array();
350
351
    /**
352
     * @var string  Prospect level. ie: 'PL_LOW', 'PL...'
353
     */
354
    public $fk_prospectlevel;
355
356
    public $stcomm_id;
357
358
    public $statut_commercial;
359
360
    /**
361
     * @var string picto
362
     */
363
    public $stcomm_picto;
364
365
366
    /**
367
     *  Constructor
368
     *
369
     * @param DoliDB $db Database handler
370
     */
371
    public function __construct($db)
372
    {
373
        $this->db = $db;
374
        $this->statut = 1; // By default, status is enabled
375
        $this->ismultientitymanaged = 1;
376
        $this->isextrafieldmanaged = 1;
377
378
        if (!isModEnabled('mailing')) {
379
            $this->fields['no_email']['enabled'] = 0;
380
        }
381
        // typical ['s.nom'] is used for third-parties
382
        if (!getDolGlobalString('SOCIETE_DISABLE_CONTACTS')) {
383
            $this->fields['fk_soc']['enabled'] = 0;
384
            $this->fields['fk_soc']['searchall'] = 0;
385
        }
386
387
        // If THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES not set, there is no prospect level on contact level, only on thirdparty
388
        if (getDolGlobalString('SOCIETE_DISABLE_PROSPECTS') || !getDolGlobalString('THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES')) {  // Default behaviour
389
            $this->fields['fk_stcommcontact']['enabled'] = 0;
390
            $this->fields['fk_prospectcontactlevel']['enabled'] = 0;
391
        }
392
393
        // Unset fields that are disabled
394
        foreach ($this->fields as $key => $val) {
395
            if (isset($val['enabled']) && empty($val['enabled'])) {
396
                unset($this->fields[$key]);
397
            }
398
        }
399
400
        // Translate some data of arrayofkeyval
401
        /*if (is_object($langs))
402
        {
403
            foreach($this->fields as $key => $val)
404
            {
405
                if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval']))
406
                {
407
                    foreach($val['arrayofkeyval'] as $key2 => $val2)
408
                    {
409
                        $this->fields[$key]['arrayofkeyval'][$key2]=$langs->trans($val2);
410
                    }
411
                }
412
            }
413
        }*/
414
    }
415
416
    /**
417
     * Function used to replace a thirdparty id with another one.
418
     *
419
     * @param DoliDB $dbs Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
420
     * @param int $origin_id Old thirdparty id
421
     * @param int $dest_id New thirdparty id
422
     * @return  bool
423
     */
424
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
425
    {
426
        $tables = array(
427
            'socpeople', 'societe_contacts'
428
        );
429
430
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
431
    }
432
433
    /**
434
     *  Load indicators into this->nb for board
435
     *
436
     * @return     int         Return integer <0 if KO, >0 if OK
437
     */
438
    public function loadStateBoard()
439
    {
440
        global $user, $hookmanager;
441
442
        $this->nb = array();
443
        $clause = "WHERE";
444
445
        $sql = "SELECT count(sp.rowid) as nb";
446
        $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as sp";
447
        if (!$user->hasRight('societe', 'client', 'voir')) {
448
            $sql .= ", " . MAIN_DB_PREFIX . "societe as s";
449
            $sql .= ", " . MAIN_DB_PREFIX . "societe_commerciaux as sc";
450
            $sql .= " WHERE sp.fk_soc = s.rowid AND s.rowid = sc.fk_soc AND sc.fk_user = " . ((int)$user->id);
451
            $clause = "AND";
452
        }
453
        $sql .= " " . $clause . " sp.entity IN (" . getEntity($this->element) . ")";
454
        $sql .= " AND (sp.priv='0' OR (sp.priv='1' AND sp.fk_user_creat = " . ((int)$user->id) . "))";
455
        if ($user->socid > 0) {
456
            $sql .= " AND sp.fk_soc = " . ((int)$user->socid);
457
        }
458
        // Add where from hooks
459
        if (is_object($hookmanager)) {
460
            $parameters = array();
461
            $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $this); // Note that $action and $object may have been modified by hook
462
            $sql .= $hookmanager->resPrint;
463
        }
464
465
        $resql = $this->db->query($sql);
466
        if ($resql) {
467
            while ($obj = $this->db->fetch_object($resql)) {
468
                $this->nb["contacts"] = $obj->nb;
469
            }
470
            $this->db->free($resql);
471
            return 1;
472
        } else {
473
            dol_print_error($this->db);
474
            $this->error = $this->db->lasterror();
475
            return -1;
476
        }
477
    }
478
479
    /**
480
     *  Add a contact into database
481
     *
482
     * @param User $user Object user that create
483
     * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
484
     * @return     int                     Return integer <0 if KO, >0 if OK
485
     */
486
    public function create($user, $notrigger = 0)
487
    {
488
        global $conf;
489
490
        $error = 0;
491
        $now = dol_now();
492
493
        $this->db->begin();
494
495
        // Clean parameters
496
        $this->name_alias = trim($this->name_alias);
497
        $this->lastname = $this->lastname ? trim($this->lastname) : trim($this->name);
498
        $this->firstname = trim($this->firstname);
499
        $this->setUpperOrLowerCase();
500
        if (empty($this->socid)) {
501
            $this->socid = 0;
502
        }
503
        if (empty($this->priv)) {
504
            $this->priv = 0;
505
        }
506
        if (empty($this->statut)) {
507
            $this->statut = 0; // This is to convert '' into '0' to avoid bad sql request
508
        }
509
510
        $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity);
511
512
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "socpeople (";
513
        $sql .= " datec";
514
        $sql .= ", fk_soc";
515
        $sql .= ", name_alias";
516
        $sql .= ", lastname";
517
        $sql .= ", firstname";
518
        $sql .= ", fk_user_creat";
519
        $sql .= ", priv";
520
        $sql .= ", fk_stcommcontact";
521
        $sql .= ", statut";
522
        $sql .= ", canvas";
523
        $sql .= ", entity";
524
        $sql .= ", ref_ext";
525
        $sql .= ", import_key";
526
        $sql .= ") VALUES (";
527
        $sql .= "'" . $this->db->idate($now) . "',";
528
        if ($this->socid > 0) {
529
            $sql .= " " . ((int)$this->socid) . ",";
530
        } else {
531
            $sql .= "null,";
532
        }
533
        $sql .= "'" . $this->db->escape($this->name_alias) . "',";
534
        $sql .= "'" . $this->db->escape($this->lastname) . "',";
535
        $sql .= "'" . $this->db->escape($this->firstname) . "',";
536
        $sql .= " " . ($user->id > 0 ? ((int)$user->id) : "null") . ",";
537
        $sql .= " " . ((int)$this->priv) . ",";
538
        $sql .= " 0,";
539
        $sql .= " " . ((int)$this->statut) . ",";
540
        $sql .= " " . (!empty($this->canvas) ? "'" . $this->db->escape($this->canvas) . "'" : "null") . ",";
541
        $sql .= " " . ((int)$this->entity) . ",";
542
        $sql .= "'" . $this->db->escape($this->ref_ext) . "',";
543
        $sql .= " " . (!empty($this->import_key) ? "'" . $this->db->escape($this->import_key) . "'" : "null");
544
        $sql .= ")";
545
546
        dol_syslog(get_only_class($this) . "::create", LOG_DEBUG);
547
        $resql = $this->db->query($sql);
548
        if ($resql) {
549
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "socpeople");
550
551
            if (!$error) {
552
                $result = $this->update($this->id, $user, 1, 'add'); // This include updateRoles(), ...
553
                if ($result < 0) {
554
                    $error++;
555
                    $this->error = $this->db->lasterror();
556
                }
557
            }
558
559
            if (!$error) {
560
                $result = $this->update_perso($this->id, $user, 1); // TODO Remove function update_perso, should be same than update
561
                if ($result < 0) {
562
                    $error++;
563
                    $this->error = $this->db->lasterror();
564
                }
565
            }
566
567
            if (!$error && !$notrigger) {
568
                // Call trigger
569
                $result = $this->call_trigger('CONTACT_CREATE', $user);
570
                if ($result < 0) {
571
                    $error++;
572
                }
573
                // End call triggers
574
            }
575
576
            if (!$error) {
577
                $this->db->commit();
578
                return $this->id;
579
            } else {
580
                $this->db->rollback();
581
                dol_syslog(get_only_class($this) . "::create " . $this->error, LOG_ERR);
582
                return -2;
583
            }
584
        } else {
585
            $this->error = $this->db->lasterror();
586
587
            $this->db->rollback();
588
            dol_syslog(get_only_class($this) . "::create " . $this->error, LOG_ERR);
589
            return -1;
590
        }
591
    }
592
593
594
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
595
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
596
597
    /**
598
     *      Update information into database
599
     *
600
     * @param int $id Id of contact/address to update
601
     * @param User $user Object user making change
602
     * @param int $notrigger 0=no, 1=yes
603
     * @param string $action Current action for hookmanager
604
     * @param int $nosyncuser No sync linked user (external users and contacts are linked)
605
     * @return     int                     Return integer <0 if KO, >0 if OK
606
     */
607
    public function update($id, $user = null, $notrigger = 0, $action = 'update', $nosyncuser = 0)
608
    {
609
        global $conf;
610
611
        $error = 0;
612
613
        $this->id = $id;
614
615
        $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity);
616
617
        // Clean parameters
618
        $this->ref_ext = (empty($this->ref_ext) ? '' : trim($this->ref_ext));
619
        $this->name_alias = trim($this->name_alias);
620
        $this->lastname = trim($this->lastname) ? trim($this->lastname) : trim($this->lastname);
621
        $this->firstname = trim($this->firstname);
622
        $this->email = trim($this->email);
623
        $this->phone_pro = trim($this->phone_pro);
624
        $this->phone_perso = trim($this->phone_perso);
625
        $this->phone_mobile = trim($this->phone_mobile);
626
        $this->photo = trim($this->photo);
627
        $this->fax = trim($this->fax);
628
        $this->zip = (empty($this->zip) ? '' : trim($this->zip));
629
        $this->town = (empty($this->town) ? '' : trim($this->town));
630
        $this->country_id = (empty($this->country_id) || $this->country_id < 0) ? 0 : $this->country_id;
631
        if (empty($this->statut)) {
632
            $this->statut = 0;
633
        }
634
        if (empty($this->civility_code) && !is_numeric($this->civility_id)) {
635
            $this->civility_code = $this->civility_id; // For backward compatibility
636
        }
637
        $this->setUpperOrLowerCase();
638
639
        $this->db->begin();
640
641
        $sql = "UPDATE " . MAIN_DB_PREFIX . "socpeople SET";
642
        if ($this->socid > 0) {
643
            $sql .= " fk_soc = " . ((int)$this->socid) . ",";
644
        } elseif ($this->socid == -1) {
645
            $sql .= " fk_soc = NULL,";
646
        }
647
        $sql .= " civility='" . $this->db->escape($this->civility_code) . "'";
648
        $sql .= ", name_alias='" . $this->db->escape($this->name_alias) . "'";
649
        $sql .= ", lastname='" . $this->db->escape($this->lastname) . "'";
650
        $sql .= ", firstname='" . $this->db->escape($this->firstname) . "'";
651
        $sql .= ", address='" . $this->db->escape($this->address) . "'";
652
        $sql .= ", zip='" . $this->db->escape($this->zip) . "'";
653
        $sql .= ", town='" . $this->db->escape($this->town) . "'";
654
        $sql .= ", ref_ext = " . (!empty($this->ref_ext) ? "'" . $this->db->escape($this->ref_ext) . "'" : "NULL");
655
        $sql .= ", fk_pays=" . ($this->country_id > 0 ? $this->country_id : 'NULL');
656
        $sql .= ", fk_departement=" . ($this->state_id > 0 ? $this->state_id : 'NULL');
657
        $sql .= ", poste='" . $this->db->escape($this->poste) . "'";
658
        $sql .= ", fax='" . $this->db->escape($this->fax) . "'";
659
        $sql .= ", email='" . $this->db->escape($this->email) . "'";
660
        $sql .= ", socialnetworks = '" . $this->db->escape(json_encode($this->socialnetworks)) . "'";
661
        $sql .= ", photo='" . $this->db->escape($this->photo) . "'";
662
        $sql .= ", birthday=" . ($this->birthday ? "'" . $this->db->idate($this->birthday) . "'" : "null");
663
        $sql .= ", note_private = " . (isset($this->note_private) ? "'" . $this->db->escape($this->note_private) . "'" : "NULL");
664
        $sql .= ", note_public = " . (isset($this->note_public) ? "'" . $this->db->escape($this->note_public) . "'" : "NULL");
665
        $sql .= ", phone = " . (isset($this->phone_pro) ? "'" . $this->db->escape($this->phone_pro) . "'" : "NULL");
666
        $sql .= ", phone_perso = " . (isset($this->phone_perso) ? "'" . $this->db->escape($this->phone_perso) . "'" : "NULL");
667
        $sql .= ", phone_mobile = " . (isset($this->phone_mobile) ? "'" . $this->db->escape($this->phone_mobile) . "'" : "NULL");
668
        $sql .= ", priv = '" . $this->db->escape($this->priv) . "'";
669
        $sql .= ", fk_prospectlevel = '" . $this->db->escape($this->fk_prospectlevel) . "'";
670
        if (isset($this->stcomm_id)) {
671
            $sql .= ", fk_stcommcontact = " . ($this->stcomm_id > 0 || $this->stcomm_id == -1 ? $this->stcomm_id : "0");
672
        }
673
        $sql .= ", statut = " . ((int)$this->statut);
674
        $sql .= ", fk_user_modif=" . ($user->id > 0 ? "'" . $this->db->escape($user->id) . "'" : "NULL");
675
        $sql .= ", default_lang=" . ($this->default_lang ? "'" . $this->db->escape($this->default_lang) . "'" : "NULL");
676
        $sql .= ", entity = " . ((int)$this->entity);
677
        $sql .= " WHERE rowid = " . ((int)$id);
678
679
        dol_syslog(get_only_class($this) . "::update", LOG_DEBUG);
680
        $result = $this->db->query($sql);
681
        if ($result) {
682
            unset($this->country_code);
683
            unset($this->country);
684
            unset($this->state_code);
685
            unset($this->state);
686
687
            $action = 'update';
688
689
            // Actions on extra fields
690
            if (!$error) {
691
                $result = $this->insertExtraFields();
692
                if ($result < 0) {
693
                    $error++;
694
                }
695
            }
696
697
            if (!$error) {
698
                $result = $this->updateRoles();
699
                if ($result < 0) {
700
                    $error++;
701
                }
702
            }
703
704
            if (!$error && $this->user_id > 0) {
705
                // If contact is linked to a user
706
                $tmpobj = new User($this->db);
707
                $tmpobj->fetch($this->user_id);
708
                $usermustbemodified = 0;
709
                if ($tmpobj->office_phone != $this->phone_pro) {
710
                    $tmpobj->office_phone = $this->phone_pro;
711
                    $usermustbemodified++;
712
                }
713
                if ($tmpobj->office_fax != $this->fax) {
714
                    $tmpobj->office_fax = $this->fax;
715
                    $usermustbemodified++;
716
                }
717
                if ($tmpobj->address != $this->address) {
718
                    $tmpobj->address = $this->address;
719
                    $usermustbemodified++;
720
                }
721
                if ($tmpobj->town != $this->town) {
722
                    $tmpobj->town = $this->town;
723
                    $usermustbemodified++;
724
                }
725
                if ($tmpobj->zip != $this->zip) {
726
                    $tmpobj->zip = $this->zip;
727
                    $usermustbemodified++;
728
                }
729
                if ($tmpobj->zip != $this->zip) {
730
                    $tmpobj->state_id = $this->state_id;
731
                    $usermustbemodified++;
732
                }
733
                if ($tmpobj->country_id != $this->country_id) {
734
                    $tmpobj->country_id = $this->country_id;
735
                    $usermustbemodified++;
736
                }
737
                if ($tmpobj->email != $this->email) {
738
                    $tmpobj->email = $this->email;
739
                    $usermustbemodified++;
740
                }
741
                if (!empty(array_diff($tmpobj->socialnetworks, $this->socialnetworks))) {
742
                    $tmpobj->socialnetworks = $this->socialnetworks;
743
                    $usermustbemodified++;
744
                }
745
                if ($usermustbemodified) {
746
                    $result = $tmpobj->update($user, 0, 1, 1, 1);
747
                    if ($result < 0) {
748
                        $error++;
749
                    }
750
                }
751
            }
752
753
            if (!$error && !$notrigger) {
754
                // Call trigger
755
                $result = $this->call_trigger('CONTACT_MODIFY', $user);
756
                if ($result < 0) {
757
                    $error++;
758
                }
759
                // End call triggers
760
            }
761
762
            if (!$error) {
763
                $this->db->commit();
764
                return 1;
765
            } else {
766
                dol_syslog(get_only_class($this) . "::update Error " . $this->error, LOG_ERR);
767
                $this->db->rollback();
768
                return -$error;
769
            }
770
        } else {
771
            $this->error = $this->db->lasterror() . ' sql=' . $sql;
772
            $this->db->rollback();
773
            return -1;
774
        }
775
    }
776
777
778
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
779
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
780
781
    /**
782
     * Updates all roles (default contact for companies) according to values inside the ->roles array.
783
     * This is called by update of contact.
784
     *
785
     * @return int
786
     * @see fetchRoles()
787
     */
788
    public function updateRoles()
789
    {
790
        global $conf;
791
792
        $error = 0;
793
794
        if (!isset($this->roles)) {
795
            return 0;   // Avoid to loose roles when property not set
796
        }
797
798
        $this->db->begin();
799
800
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "societe_contacts WHERE fk_socpeople=" . ((int)$this->id) . " AND entity IN (" . getEntity("contact") . ")";
801
802
        $result = $this->db->query($sql);
803
        if (!$result) {
804
            $this->errors[] = $this->db->lasterror() . ' sql=' . $sql;
805
            $error++;
806
        } else {
807
            if (count($this->roles) > 0) {
808
                foreach ($this->roles as $keyRoles => $valRoles) {
809
                    $idrole = 0;
810
                    if (is_array($valRoles)) {
811
                        $idrole = $valRoles['id'];
812
                    } else {
813
                        $idrole = $valRoles;
814
                    }
815
816
                    $socid = 0;
817
                    if (is_array($valRoles)) {
818
                        $socid = $valRoles['socid'];
819
                    } else {
820
                        $socid = $this->socid;
821
                    }
822
823
                    if ($socid > 0) {
824
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_contacts";
825
                        $sql .= " (entity,";
826
                        $sql .= "date_creation,";
827
                        $sql .= "fk_soc,";
828
                        $sql .= "fk_c_type_contact,";
829
                        $sql .= "fk_socpeople) ";
830
                        $sql .= " VALUES (" . $conf->entity . ",";
831
                        $sql .= "'" . $this->db->idate(dol_now()) . "',";
832
                        $sql .= $socid . ", ";
833
                        $sql .= $idrole . " , ";
834
                        $sql .= $this->id;
835
                        $sql .= ")";
836
837
                        $result = $this->db->query($sql);
838
                        if (!$result) {
839
                            $this->errors[] = $this->db->lasterror() . ' sql=' . $sql;
840
                            $error++;
841
                        }
842
                    }
843
                }
844
            }
845
        }
846
        if (empty($error)) {
847
            $this->db->commit();
848
            return 1;
849
        } else {
850
            $this->error = implode(' ', $this->errors);
851
            $this->db->rollback();
852
            return $error * -1;
853
        }
854
    }
855
856
857
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
858
859
    /**
860
     *  Load object contact.
861
     *
862
     * @param int $id Id of contact
863
     * @param      ?User $user Load also alerts of this user (subscribing to alerts) that want alerts about this contact
864
     * @param string $ref_ext External reference, not given by Dolibarr
865
     * @param string $email Email
866
     * @param int $loadalsoroles Load also roles. Try to always 0 here and load roles with a separate call of fetchRoles().
867
     * @return     int                     >0 if OK, <0 if KO or if two records found for same ref or idprof, 0 if not found.
868
     */
869
    public function fetch($id, $user = null, $ref_ext = '', $email = '', $loadalsoroles = 0)
870
    {
871
        global $langs;
872
873
        dol_syslog(get_only_class($this) . "::fetch id=" . $id . " ref_ext=" . $ref_ext . " email=" . $email, LOG_DEBUG);
874
875
        if (empty($id) && empty($ref_ext) && empty($email)) {
876
            $this->error = 'BadParameter';
877
            return -1;
878
        }
879
880
        $langs->loadLangs(array("dict", "companies"));
881
882
        $sql = "SELECT c.rowid, c.entity, c.fk_soc, c.ref_ext, c.civility as civility_code, c.name_alias, c.lastname, c.firstname,";
883
        $sql .= " c.address, c.statut, c.zip, c.town,";
884
        $sql .= " c.fk_pays as country_id,";
885
        $sql .= " c.fk_departement as state_id,";
886
        $sql .= " c.birthday,";
887
        $sql .= " c.poste, c.phone, c.phone_perso, c.phone_mobile, c.fax, c.email,";
888
        $sql .= " c.socialnetworks,";
889
        $sql .= " c.photo,";
890
        $sql .= " c.priv, c.note_private, c.note_public, c.default_lang, c.canvas,";
891
        $sql .= " c.fk_prospectlevel, c.fk_stcommcontact, st.libelle as stcomm, st.picto as stcomm_picto,";
892
        $sql .= " c.import_key,";
893
        $sql .= " c.datec as date_creation, c.tms as date_modification,";
894
        $sql .= " co.label as country, co.code as country_code,";
895
        $sql .= " d.nom as state, d.code_departement as state_code,";
896
        $sql .= " u.rowid as user_id, u.login as user_login,";
897
        $sql .= " s.nom as socname, s.address as socaddress, s.zip as soccp, s.town as soccity, s.default_lang as socdefault_lang";
898
        $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as c";
899
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as co ON c.fk_pays = co.rowid";
900
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_departements as d ON c.fk_departement = d.rowid";
901
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as u ON c.rowid = u.fk_socpeople";
902
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON c.fk_soc = s.rowid";
903
        $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_stcommcontact as st ON c.fk_stcommcontact = st.id';
904
        if ($id) {
905
            $sql .= " WHERE c.rowid = " . ((int)$id);
906
        } else {
907
            $sql .= " WHERE c.entity IN (" . getEntity($this->element) . ")";
908
            if ($ref_ext) {
909
                $sql .= " AND c.ref_ext = '" . $this->db->escape($ref_ext) . "'";
910
            }
911
            if ($email) {
912
                $sql .= " AND c.email = '" . $this->db->escape($email) . "'";
913
            }
914
        }
915
916
        $resql = $this->db->query($sql);
917
        if ($resql) {
918
            $num = $this->db->num_rows($resql);
919
            if ($num > 1) {
920
                $this->error = 'Fetch found several records. Rename one of contact to avoid duplicate.';
921
                dol_syslog($this->error, LOG_ERR);
922
923
                return 2;
924
            } elseif ($num) {   // $num = 1
925
                $obj = $this->db->fetch_object($resql);
926
927
                $this->id = $obj->rowid;
928
                $this->entity = $obj->entity;
929
                $this->ref = $obj->rowid;
930
                $this->ref_ext = $obj->ref_ext;
931
932
                $this->civility_code = $obj->civility_code;
933
                $this->civility = $obj->civility_code ? ($langs->trans("Civility" . $obj->civility_code) != "Civility" . $obj->civility_code ? $langs->trans("Civility" . $obj->civility_code) : $obj->civility_code) : '';
934
935
                $this->name_alias = $obj->name_alias;
936
                $this->lastname = $obj->lastname;
937
                $this->firstname = $obj->firstname;
938
                $this->address = $obj->address;
939
                $this->zip = $obj->zip;
940
                $this->town = $obj->town;
941
942
                $this->date_creation = $this->db->jdate($obj->date_creation);
943
                $this->date_modification = $this->db->jdate($obj->date_modification);
944
945
                $this->state_id = $obj->state_id;
946
                $this->state_code = $obj->state_code;
947
                $this->state = $obj->state;
948
949
                $this->country_id = $obj->country_id;
950
                $this->country_code = $obj->country_id ? $obj->country_code : '';
951
                $this->country = $obj->country_id ? ($langs->trans('Country' . $obj->country_code) != 'Country' . $obj->country_code ? $langs->transnoentities('Country' . $obj->country_code) : $obj->country) : '';
952
953
                $this->fk_soc = $obj->fk_soc;     // Both fk_soc and socid are used
954
                $this->socid = $obj->fk_soc;     // Both fk_soc and socid are used
955
                $this->socname = $obj->socname;
956
                $this->poste = $obj->poste;
957
                $this->statut = $obj->statut;
958
959
                $this->fk_prospectlevel = $obj->fk_prospectlevel;
960
961
                $transcode = $langs->trans('StatusProspect' . $obj->fk_stcommcontact);
962
                $libelle = ($transcode != 'StatusProspect' . $obj->fk_stcommcontact ? $transcode : $obj->stcomm);
963
                $this->stcomm_id = $obj->fk_stcommcontact; // id statut commercial
964
                $this->statut_commercial = $libelle; // libelle statut commercial
965
                $this->stcomm_picto = $obj->stcomm_picto; // Picto statut commercial
966
967
                $this->phone_pro = trim($obj->phone);
968
                $this->fax = trim($obj->fax);
969
                $this->phone_perso = trim($obj->phone_perso);
970
                $this->phone_mobile = trim($obj->phone_mobile);
971
972
                $this->email = $obj->email;
973
                $this->socialnetworks = ($obj->socialnetworks ? (array)json_decode($obj->socialnetworks, true) : array());
974
                $this->photo = $obj->photo;
975
                $this->priv = $obj->priv;
976
                $this->mail = $obj->email;
977
978
                $this->birthday = $this->db->jdate($obj->birthday);
979
                $this->note = $obj->note_private; // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

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

979
                /** @scrutinizer ignore-deprecated */ $this->note = $obj->note_private; // deprecated

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
980
                $this->note_private = $obj->note_private;
981
                $this->note_public = $obj->note_public;
982
                $this->default_lang = $obj->default_lang;
983
                $this->user_id = $obj->user_id;
984
                $this->user_login = $obj->user_login;
985
                $this->canvas = $obj->canvas;
986
987
                $this->import_key = $obj->import_key;
988
989
                // Define gender according to civility
990
                $this->setGenderFromCivility();
991
992
                // Search Dolibarr user linked to this contact
993
                $sql = "SELECT u.rowid ";
994
                $sql .= " FROM " . MAIN_DB_PREFIX . "user as u";
995
                $sql .= " WHERE u.fk_socpeople = " . ((int)$this->id);
996
997
                $resql = $this->db->query($sql);
998
                if ($resql) {
999
                    if ($this->db->num_rows($resql)) {
1000
                        $uobj = $this->db->fetch_object($resql);
1001
1002
                        $this->user_id = $uobj->rowid;
1003
                    }
1004
                    $this->db->free($resql);
1005
                } else {
1006
                    $this->error = $this->db->error();
1007
                    return -1;
1008
                }
1009
1010
                // Retrieve all extrafield
1011
                // fetch optionals attributes and labels
1012
                $this->fetch_optionals();
1013
1014
                // Load also alerts of this user
1015
                if ($user) {
1016
                    $sql = "SELECT fk_user";
1017
                    $sql .= " FROM " . MAIN_DB_PREFIX . "user_alert";
1018
                    $sql .= " WHERE fk_user = " . ((int)$user->id) . " AND fk_contact = " . ((int)$id);
1019
1020
                    $resql = $this->db->query($sql);
1021
                    if ($resql) {
1022
                        if ($this->db->num_rows($resql)) {
1023
                            $obj = $this->db->fetch_object($resql);
1024
1025
                            $this->birthday_alert = 1;
1026
                        }
1027
                        $this->db->free($resql);
1028
                    } else {
1029
                        $this->error = $this->db->error();
1030
                        return -1;
1031
                    }
1032
                }
1033
1034
                // Load also roles of this address
1035
                if ($loadalsoroles) {
1036
                    $resultRole = $this->fetchRoles();
1037
                    if ($resultRole < 0) {
1038
                        return $resultRole;
1039
                    }
1040
                }
1041
1042
                return 1;
1043
            } else {
1044
                $this->error = $langs->trans("RecordNotFound");
1045
                return 0;
1046
            }
1047
        } else {
1048
            $this->error = $this->db->error();
1049
            return -1;
1050
        }
1051
    }
1052
1053
    /**
1054
     * Set the property "gender" of this class, based on the property "civility_id"
1055
     * or use property "civility_code" as fallback, when "civility_id" is not available.
1056
     *
1057
     * @return void
1058
     */
1059
    public function setGenderFromCivility()
1060
    {
1061
        unset($this->gender);
1062
1063
        if (in_array($this->civility_id, array('MR')) || in_array($this->civility_code, array('MR'))) {
1064
            $this->gender = 'man';
1065
        } elseif (in_array($this->civility_id, array('MME', 'MLE')) || in_array($this->civility_code, array('MME', 'MLE'))) {
1066
            $this->gender = 'woman';
1067
        }
1068
    }
1069
1070
    /**
1071
     * Fetch roles (default contact of some companies) for the current contact.
1072
     * This load the array ->roles.
1073
     *
1074
     * @return  int         Return integer <0 if KO, Nb of roles found if OK
1075
     * @see updateRoles()
1076
     */
1077
    public function fetchRoles()
1078
    {
1079
        global $langs;
1080
        $error = 0;
1081
        $num = 0;
1082
1083
        $sql = "SELECT tc.rowid, tc.element, tc.source, tc.code, tc.libelle as label, sc.rowid as contactroleid, sc.fk_soc as socid";
1084
        $sql .= " FROM " . MAIN_DB_PREFIX . "societe_contacts as sc, " . MAIN_DB_PREFIX . "c_type_contact as tc";
1085
        $sql .= " WHERE tc.rowid = sc.fk_c_type_contact";
1086
        $sql .= " AND tc.source = 'external' AND tc.active=1";
1087
        $sql .= " AND sc.fk_socpeople = " . ((int)$this->id);
1088
        $sql .= " AND sc.entity IN (" . getEntity('societe') . ')';
1089
1090
        $resql = $this->db->query($sql);
1091
        if ($resql) {
1092
            $this->roles = array();
1093
1094
            $num = $this->db->num_rows($resql);
1095
            if ($num > 0) {
1096
                while ($obj = $this->db->fetch_object($resql)) {
1097
                    $transkey = "TypeContact_" . $obj->element . "_" . $obj->source . "_" . $obj->code;
1098
                    $libelle_element = $langs->trans('ContactDefault_' . $obj->element);
1099
                    $this->roles[$obj->contactroleid] = array('id' => $obj->rowid, 'socid' => $obj->socid, 'element' => $obj->element, 'source' => $obj->source, 'code' => $obj->code, 'label' => $libelle_element . ' - ' . ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->label));
1100
                }
1101
            }
1102
        } else {
1103
            $error++;
1104
            $this->error = $this->db->lasterror();
1105
            $this->errors[] = $this->db->lasterror();
1106
        }
1107
1108
        if (empty($error)) {
1109
            return $num;
1110
        } else {
1111
            return $error * -1;
1112
        }
1113
    }
1114
1115
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1116
1117
    /**
1118
     *  Update field alert birthday
1119
     *
1120
     * @param int $id Id of contact
1121
     * @param User $user User asking to change alert or birthday
1122
     * @param int $notrigger 0=no, 1=yes
1123
     * @return     int                     Return integer <0 if KO, >=0 if OK
1124
     */
1125
    public function update_perso($id, $user = null, $notrigger = 0)
1126
    {
1127
        // phpcs:enable
1128
        $error = 0;
1129
        $result = false;
1130
1131
        $this->db->begin();
1132
1133
        // Update the contact
1134
        $sql = "UPDATE " . MAIN_DB_PREFIX . "socpeople SET";
1135
        $sql .= " birthday = " . ($this->birthday ? "'" . $this->db->idate($this->birthday) . "'" : "null");
1136
        $sql .= ", photo = " . ($this->photo ? "'" . $this->db->escape($this->photo) . "'" : "null");
1137
        if ($user) {
1138
            $sql .= ", fk_user_modif = " . ((int)$user->id);
1139
        }
1140
        $sql .= " WHERE rowid = " . ((int)$id);
1141
1142
        dol_syslog(get_only_class($this) . "::update_perso this->birthday=" . $this->birthday . " -", LOG_DEBUG);
1143
        $resql = $this->db->query($sql);
1144
        if (!$resql) {
1145
            $error++;
1146
            $this->error = $this->db->lasterror();
1147
        }
1148
1149
        if ($user) {
1150
            // Update birthday alert
1151
            if (!empty($this->birthday_alert)) {
1152
                //check existing
1153
                $sql_check = "SELECT rowid FROM " . MAIN_DB_PREFIX . "user_alert WHERE type = 1 AND fk_contact = " . ((int)$id) . " AND fk_user = " . ((int)$user->id);
1154
                $result_check = $this->db->query($sql_check);
1155
                if (!$result_check || ($this->db->num_rows($result_check) < 1)) {
1156
                    //insert
1157
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "user_alert(type, fk_contact, fk_user) ";
1158
                    $sql .= "VALUES (1," . ((int)$id) . "," . ((int)$user->id) . ")";
1159
                    $result = $this->db->query($sql);
1160
                    if (!$result) {
1161
                        $error++;
1162
                        $this->error = $this->db->lasterror();
1163
                    }
1164
                } else {
1165
                    $result = true;
1166
                }
1167
            } else {
1168
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "user_alert ";
1169
                $sql .= "WHERE type=1 AND fk_contact=" . ((int)$id) . " AND fk_user=" . ((int)$user->id);
1170
                $result = $this->db->query($sql);
1171
                if (!$result) {
1172
                    $error++;
1173
                    $this->error = $this->db->lasterror();
1174
                }
1175
            }
1176
        }
1177
1178
        if (!$error && !$notrigger) {
1179
            // Call trigger
1180
            $result = $this->call_trigger('CONTACT_MODIFY', $user);
1181
            if ($result < 0) {
1182
                $error++;
1183
            }
1184
            // End call triggers
1185
        }
1186
1187
        if (!$error) {
1188
            $this->db->commit();
1189
            return 1;
1190
        } else {
1191
            dol_syslog(get_only_class($this) . "::update Error " . $this->error, LOG_ERR);
1192
            $this->db->rollback();
1193
            return -$error;
1194
        }
1195
    }
1196
1197
    /**
1198
     *  Return DN string complete in the LDAP directory for the object
1199
     *
1200
     * @param array $info Info string loaded by _load_ldap_info
1201
     * @param int $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
1202
     *                                  1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
1203
     *                                  2=Return key only (uid=qqq)
1204
     * @return     string              DN
1205
     */
1206
    public function _load_ldap_dn($info, $mode = 0)
1207
    {
1208
        // phpcs:enable
1209
        global $conf;
1210
        $dn = '';
1211
        if ($mode == 0) {
1212
            $dn = getDolGlobalString('LDAP_KEY_CONTACTS') . "=" . $info[getDolGlobalString('LDAP_KEY_CONTACTS')] . "," . getDolGlobalString('LDAP_CONTACT_DN');
1213
        } elseif ($mode == 1) {
1214
            $dn = getDolGlobalString('LDAP_CONTACT_DN');
1215
        } elseif ($mode == 2) {
1216
            $dn = getDolGlobalString('LDAP_KEY_CONTACTS') . "=" . $info[getDolGlobalString('LDAP_KEY_CONTACTS')];
1217
        }
1218
        return $dn;
1219
    }
1220
1221
    /**
1222
     *  Initialize info table (LDAP attributes table)
1223
     *
1224
     * @return     array       Attributes info table
1225
     */
1226
    public function _load_ldap_info()
1227
    {
1228
        // phpcs:enable
1229
        global $conf, $langs;
1230
1231
        $info = array();
1232
1233
        // Object classes
1234
        $info["objectclass"] = explode(',', getDolGlobalString('LDAP_CONTACT_OBJECT_CLASS'));
1235
1236
        $this->fullname = $this->getFullName($langs);
1237
1238
        // Fields
1239
        if ($this->fullname && getDolGlobalString('LDAP_CONTACT_FIELD_FULLNAME')) {
1240
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_FULLNAME')] = $this->fullname;
1241
        }
1242
        if ($this->lastname && getDolGlobalString('LDAP_CONTACT_FIELD_NAME')) {
1243
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_NAME')] = $this->lastname;
1244
        }
1245
        if ($this->firstname && getDolGlobalString('LDAP_CONTACT_FIELD_FIRSTNAME')) {
1246
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_FIRSTNAME')] = $this->firstname;
1247
        }
1248
1249
        if ($this->poste) {
1250
            $info["title"] = $this->poste;
1251
        }
1252
        if ($this->socid > 0) {
1253
            $soc = new Societe($this->db);
1254
            $soc->fetch($this->socid);
1255
1256
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_COMPANY')] = $soc->name;
1257
            if ($soc->client == 1) {
1258
                $info["businessCategory"] = "Customers";
1259
            }
1260
            if ($soc->client == 2) {
1261
                $info["businessCategory"] = "Prospects";
1262
            }
1263
            if ($soc->fournisseur == 1) {
1264
                $info["businessCategory"] = "Suppliers";
1265
            }
1266
        }
1267
        if ($this->address && getDolGlobalString('LDAP_CONTACT_FIELD_ADDRESS')) {
1268
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_ADDRESS')] = $this->address;
1269
        }
1270
        if ($this->zip && getDolGlobalString('LDAP_CONTACT_FIELD_ZIP')) {
1271
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_ZIP')] = $this->zip;
1272
        }
1273
        if ($this->town && getDolGlobalString('LDAP_CONTACT_FIELD_TOWN')) {
1274
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_TOWN')] = $this->town;
1275
        }
1276
        if ($this->country_code && getDolGlobalString('LDAP_CONTACT_FIELD_COUNTRY')) {
1277
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_COUNTRY')] = $this->country_code;
1278
        }
1279
        if ($this->phone_pro && getDolGlobalString('LDAP_CONTACT_FIELD_PHONE')) {
1280
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_PHONE')] = $this->phone_pro;
1281
        }
1282
        if ($this->phone_perso && getDolGlobalString('LDAP_CONTACT_FIELD_HOMEPHONE')) {
1283
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_HOMEPHONE')] = $this->phone_perso;
1284
        }
1285
        if ($this->phone_mobile && getDolGlobalString('LDAP_CONTACT_FIELD_MOBILE')) {
1286
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_MOBILE')] = $this->phone_mobile;
1287
        }
1288
        if ($this->fax && getDolGlobalString('LDAP_CONTACT_FIELD_FAX')) {
1289
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_FAX')] = $this->fax;
1290
        }
1291
        if ($this->note_private && getDolGlobalString('LDAP_CONTACT_FIELD_DESCRIPTION')) {
1292
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_DESCRIPTION')] = dol_string_nohtmltag($this->note_private, 2);
1293
        }
1294
        if ($this->email && getDolGlobalString('LDAP_CONTACT_FIELD_MAIL')) {
1295
            $info[getDolGlobalString('LDAP_CONTACT_FIELD_MAIL')] = $this->email;
1296
        }
1297
1298
        if (getDolGlobalString('LDAP_SERVER_TYPE') == 'egroupware') {
1299
            $info["objectclass"][4] = "phpgwContact"; // compatibilite egroupware
1300
1301
            $info['uidnumber'] = $this->id;
1302
1303
            $info['phpgwTz'] = 0;
1304
            $info['phpgwMailType'] = 'INTERNET';
1305
            $info['phpgwMailHomeType'] = 'INTERNET';
1306
1307
            $info["phpgwContactTypeId"] = 'n';
1308
            $info["phpgwContactCatId"] = 0;
1309
            $info["phpgwContactAccess"] = "public";
1310
1311
            /*
1312
            if (dol_strlen($this->egroupware_id) == 0) {
1313
                $this->egroupware_id = 1;
1314
            }
1315
            $info["phpgwContactOwner"] = $this->egroupware_id;
1316
            */
1317
            $info["phpgwContactOwner"] = 1;
1318
1319
            if ($this->email) {
1320
                $info["rfc822Mailbox"] = $this->email;
1321
            }
1322
            if ($this->phone_mobile) {
1323
                $info["phpgwCellTelephoneNumber"] = $this->phone_mobile;
1324
            }
1325
        }
1326
1327
        return $info;
1328
    }
1329
1330
    /**
1331
     *  Load number of elements the contact is used as a link for
1332
     *  ref_facturation
1333
     *  ref_contrat
1334
     *  ref_commande (for order and/or shipments)
1335
     *  ref_propale
1336
     *
1337
     * @return     int                                 Return integer <0 if KO, >=0 if OK
1338
     */
1339
    public function load_ref_elements()
1340
    {
1341
        // phpcs:enable
1342
        // Count the elements for which it is contact
1343
        $sql = "SELECT tc.element, count(ec.rowid) as nb";
1344
        $sql .= " FROM " . MAIN_DB_PREFIX . "element_contact as ec, " . MAIN_DB_PREFIX . "c_type_contact as tc";
1345
        $sql .= " WHERE ec.fk_c_type_contact = tc.rowid";
1346
        $sql .= " AND fk_socpeople = " . ((int)$this->id);
1347
        $sql .= " AND tc.source = 'external'";
1348
        $sql .= " GROUP BY tc.element";
1349
1350
        dol_syslog(get_only_class($this) . "::load_ref_elements", LOG_DEBUG);
1351
1352
        $resql = $this->db->query($sql);
1353
        if ($resql) {
1354
            while ($obj = $this->db->fetch_object($resql)) {
1355
                if ($obj->nb) {
1356
                    if ($obj->element == 'facture') {
1357
                        $this->ref_facturation = $obj->nb;
1358
                    } elseif ($obj->element == 'contrat') {
1359
                        $this->ref_contrat = $obj->nb;
1360
                    } elseif ($obj->element == 'commande') {
1361
                        $this->ref_commande = $obj->nb;
1362
                    } elseif ($obj->element == 'propal') {
1363
                        $this->ref_propal = $obj->nb;
1364
                    }
1365
                }
1366
            }
1367
            $this->db->free($resql);
1368
            return 0;
1369
        } else {
1370
            $this->error = $this->db->lasterror();
1371
            return -1;
1372
        }
1373
    }
1374
1375
    /**
1376
     *  Delete a contact from database
1377
     *
1378
     * @param User $user User making the delete
1379
     * @param int $notrigger Disable all trigger
1380
     * @return     int                     Return integer <0 if KO, >0 if OK
1381
     */
1382
    public function delete($user, $notrigger = 0)
1383
    {
1384
        $error = 0;
1385
1386
        $this->db->begin();
1387
1388
        if (!$error && !$notrigger) {
1389
            // Call trigger
1390
            $result = $this->call_trigger('CONTACT_DELETE', $user);
1391
            if ($result < 0) {
1392
                $error++;
1393
            }
1394
            // End call triggers
1395
        }
1396
1397
        if (!$error) {
1398
            // Get all rowid of element_contact linked to a type that is link to llx_socpeople
1399
            $sql = "SELECT ec.rowid";
1400
            $sql .= " FROM " . MAIN_DB_PREFIX . "element_contact ec,";
1401
            $sql .= " " . MAIN_DB_PREFIX . "c_type_contact tc";
1402
            $sql .= " WHERE ec.fk_socpeople=" . ((int)$this->id);
1403
            $sql .= " AND ec.fk_c_type_contact=tc.rowid";
1404
            $sql .= " AND tc.source='external'";
1405
            dol_syslog(__METHOD__, LOG_DEBUG);
1406
            $resql = $this->db->query($sql);
1407
            if ($resql) {
1408
                $num = $this->db->num_rows($resql);
1409
1410
                $i = 0;
1411
                while ($i < $num && !$error) {
1412
                    $obj = $this->db->fetch_object($resql);
1413
1414
                    $sqldel = "DELETE FROM " . MAIN_DB_PREFIX . "element_contact";
1415
                    $sqldel .= " WHERE rowid = " . ((int)$obj->rowid);
1416
                    dol_syslog(__METHOD__, LOG_DEBUG);
1417
                    $result = $this->db->query($sqldel);
1418
                    if (!$result) {
1419
                        $error++;
1420
                        $this->error = $this->db->error() . ' sql=' . $sqldel;
1421
                    }
1422
1423
                    $i++;
1424
                }
1425
            } else {
1426
                $error++;
1427
                $this->error = $this->db->error() . ' sql=' . $sql;
1428
            }
1429
        }
1430
1431
        if (!$error) {
1432
            // Remove Roles
1433
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "societe_contacts WHERE fk_socpeople = " . ((int)$this->id);
1434
            dol_syslog(__METHOD__, LOG_DEBUG);
1435
            $resql = $this->db->query($sql);
1436
            if (!$resql) {
1437
                $error++;
1438
                $this->error .= $this->db->lasterror();
1439
                $errorflag = -1;
1440
            }
1441
        }
1442
1443
        if (!$error) {
1444
            // Remove Notifications
1445
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def WHERE fk_contact = " . ((int)$this->id);
1446
            dol_syslog(__METHOD__, LOG_DEBUG);
1447
            $resql = $this->db->query($sql);
1448
            if (!$resql) {
1449
                $error++;
1450
                $this->error .= $this->db->lasterror();
1451
                $errorflag = -1;
1452
            }
1453
        }
1454
1455
        if (!$error) {
1456
            // Remove category
1457
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "categorie_contact WHERE fk_socpeople = " . ((int)$this->id);
1458
            dol_syslog(__METHOD__, LOG_DEBUG);
1459
            $resql = $this->db->query($sql);
1460
            if (!$resql) {
1461
                $error++;
1462
                $this->error .= $this->db->lasterror();
1463
                $errorflag = -1;
1464
            }
1465
        }
1466
1467
        if (!$error) {
1468
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "socpeople";
1469
            $sql .= " WHERE rowid = " . ((int)$this->id);
1470
            dol_syslog(__METHOD__, LOG_DEBUG);
1471
            $result = $this->db->query($sql);
1472
            if (!$result) {
1473
                $error++;
1474
                $this->error = $this->db->error() . ' sql=' . $sql;
1475
            }
1476
        }
1477
1478
        // Remove extrafields
1479
        if (!$error) {
1480
            // For avoid conflicts if trigger used
1481
            $result = $this->deleteExtraFields();
1482
            if ($result < 0) {
1483
                $error++;
1484
            }
1485
        }
1486
1487
        if (!$error) {
1488
            $this->db->commit();
1489
            return 1;
1490
        } else {
1491
            $this->db->rollback();
1492
            dol_syslog("Error " . $this->error, LOG_ERR);
1493
            return -1;
1494
        }
1495
    }
1496
1497
    /**
1498
     *  Load contact information from the database
1499
     *
1500
     * @param int $id Id of the contact to load
1501
     * @return     void
1502
     */
1503
    public function info($id)
1504
    {
1505
        $sql = "SELECT c.rowid, c.datec as datec, c.fk_user_creat,";
1506
        $sql .= " c.tms as tms, c.fk_user_modif";
1507
        $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as c";
1508
        $sql .= " WHERE c.rowid = " . ((int)$id);
1509
1510
        $resql = $this->db->query($sql);
1511
        if ($resql) {
1512
            if ($this->db->num_rows($resql)) {
1513
                $obj = $this->db->fetch_object($resql);
1514
1515
                $this->id = $obj->rowid;
1516
1517
                $this->user_creation_id = $obj->fk_user_creat;
1518
                $this->user_modification_id = $obj->fk_user_modif;
1519
                $this->date_creation = $this->db->jdate($obj->datec);
1520
                $this->date_modification = $this->db->jdate($obj->tms);
1521
            }
1522
1523
            $this->db->free($resql);
1524
        } else {
1525
            print $this->db->error();
1526
        }
1527
    }
1528
1529
    /**
1530
     *  Return number of mass Emailing received by these contacts with its email
1531
     *
1532
     * @return       int     Number of EMailings
1533
     */
1534
    public function getNbOfEMailings()
1535
    {
1536
        $sql = "SELECT count(mc.email) as nb";
1537
        $sql .= " FROM " . MAIN_DB_PREFIX . "mailing_cibles as mc, " . MAIN_DB_PREFIX . "mailing as m";
1538
        $sql .= " WHERE mc.fk_mailing=m.rowid AND mc.email = '" . $this->db->escape($this->email) . "' ";
1539
        $sql .= " AND m.entity IN (" . getEntity($this->element) . ") AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with success
1540
1541
        $resql = $this->db->query($sql);
1542
        if ($resql) {
1543
            $obj = $this->db->fetch_object($resql);
1544
            $nb = $obj->nb;
1545
1546
            $this->db->free($resql);
1547
            return $nb;
1548
        } else {
1549
            $this->error = $this->db->error();
1550
            return -1;
1551
        }
1552
    }
1553
1554
    /**
1555
     *    Return civility label of contact
1556
     *
1557
     * @return   string                  Translated name of civility
1558
     */
1559
    public function getCivilityLabel()
1560
    {
1561
        global $langs;
1562
1563
        $code = ($this->civility_code ? $this->civility_code : (!empty($this->civility_id) ? $this->civility : (!empty($this->civilite) ? $this->civilite : '')));
1564
        if (empty($code)) {
1565
            return '';
1566
        }
1567
1568
        $langs->load("dict");
1569
        return $langs->getLabelFromKey($this->db, "Civility" . $code, "c_civility", "code", "label", $code);
1570
    }
1571
1572
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1573
1574
    /**
1575
     *  Return translated label of Public or Private
1576
     *
1577
     * @param int $status Type (0 = public, 1 = private)
1578
     * @return     string                  Label translated
1579
     */
1580
    public function LibPubPriv($status)
1581
    {
1582
        // phpcs:enable
1583
        global $langs;
1584
        if ($status == '1') {
1585
            return $langs->trans('ContactPrivate');
1586
        } else {
1587
            return $langs->trans('ContactPublic');
1588
        }
1589
    }
1590
1591
1592
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1593
1594
    /**
1595
     *  Initialise an instance with random values.
1596
     *  Used to build previews or test instances.
1597
     *  id must be 0 if object instance is a specimen.
1598
     *
1599
     * @return int >0 if ok
1600
     */
1601
    public function initAsSpecimen()
1602
    {
1603
        // Get first id of existing company and save it into $socid
1604
        $socid = 0;
1605
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "societe ORDER BY rowid LIMIT 1";
1606
        $resql = $this->db->query($sql);
1607
        if ($resql) {
1608
            $obj = $this->db->fetch_object($resql);
1609
            if ($obj) {
1610
                $socid = $obj->rowid;
1611
            }
1612
        }
1613
1614
        // Initialise parameters
1615
        $this->id = 0;
1616
        $this->entity = 1;
1617
        $this->specimen = 1;
1618
        $this->lastname = 'DOLIBARR';
1619
        $this->firstname = 'SPECIMEN';
1620
        $this->address = '21 jump street';
1621
        $this->zip = '99999';
1622
        $this->town = 'MyTown';
1623
        $this->country_id = 1;
1624
        $this->country_code = 'FR';
1625
        $this->country = 'France';
1626
        $this->email = '[email protected]';
1627
        $this->socialnetworks = array(
1628
            'skype' => 'tom.hanson',
1629
            'twitter' => 'tomhanson',
1630
            'linkedin' => 'tomhanson',
1631
        );
1632
        $this->phone_pro = '0909090901';
1633
        $this->phone_perso = '0909090902';
1634
        $this->phone_mobile = '0909090903';
1635
        $this->fax = '0909090909';
1636
1637
        $this->note_public = 'This is a comment (public)';
1638
        $this->note_private = 'This is a comment (private)';
1639
1640
        $this->socid = $socid;
1641
        $this->statut = 1;
1642
1643
        return 1;
1644
    }
1645
1646
    /**
1647
     *  Change status of a user
1648
     *
1649
     * @param int $status Status to set
1650
     * @return int                 Return integer <0 if KO, 0 if nothing is done, >0 if OK
1651
     */
1652
    public function setstatus($status)
1653
    {
1654
        global $conf, $langs, $user;
1655
1656
        $error = 0;
1657
1658
        // Check parameters
1659
        if ($this->statut == $status) {
1660
            return 0;
1661
        } else {
1662
            $this->statut = $status;
1663
        }
1664
1665
        $this->db->begin();
1666
1667
        // User disable
1668
        $sql = "UPDATE " . MAIN_DB_PREFIX . "socpeople";
1669
        $sql .= " SET statut = " . ((int)$this->statut);
1670
        $sql .= ", fk_user_modif = " . ((int)$user->id);
1671
        $sql .= " WHERE rowid = " . ((int)$this->id);
1672
        $result = $this->db->query($sql);
1673
1674
        dol_syslog(get_only_class($this) . "::setstatus", LOG_DEBUG);
1675
        if ($result) {
1676
            // Call trigger
1677
            $result = $this->call_trigger('CONTACT_ENABLEDISABLE', $user);
1678
            if ($result < 0) {
1679
                $error++;
1680
            }
1681
            // End call triggers
1682
        }
1683
1684
        if ($error) {
1685
            $this->db->rollback();
1686
            return -$error;
1687
        } else {
1688
            $this->db->commit();
1689
            return 1;
1690
        }
1691
    }
1692
1693
    /**
1694
     * Sets object to supplied categories.
1695
     *
1696
     * Deletes object from existing categories not supplied.
1697
     * Adds it to non existing supplied categories.
1698
     * Existing categories are left untouch.
1699
     *
1700
     * @param int[]|int $categories Category or categories IDs
1701
     * @return  int                         Return integer <0 if KO, >0 if OK
1702
     */
1703
    public function setCategories($categories)
1704
    {
1705
        return parent::setCategoriesCommon($categories, Categorie::TYPE_CONTACT);
1706
    }
1707
1708
    /**
1709
     * Get thirdparty contact roles of a given contact
1710
     *
1711
     * @param string $element Element type
1712
     * @return array|int            Array of contact roles or -1
1713
     * @throws Exception
1714
     */
1715
    public function getContactRoles($element = '')
1716
    {
1717
        $tab = array();
1718
1719
        if ($element == 'action') {
1720
            $element = 'agenda';
1721
        }
1722
1723
        $sql = "SELECT sc.fk_socpeople as id, sc.fk_c_type_contact";
1724
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_type_contact tc";
1725
        $sql .= ", " . MAIN_DB_PREFIX . "societe_contacts sc";
1726
        $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "socpeople sp";
1727
        $sql .= " ON sc.fk_socpeople = sp.rowid AND sp.statut = 1";
1728
        $sql .= " WHERE sc.fk_soc =" . ((int)$this->socid);
1729
        $sql .= " AND sc.fk_c_type_contact=tc.rowid";
1730
        $sql .= " AND tc.element = '" . $this->db->escape($element) . "'";
1731
        $sql .= " AND sp.entity IN (" . getEntity('contact') . ")";
1732
        $sql .= " AND tc.active = 1";
1733
1734
        dol_syslog(__METHOD__, LOG_DEBUG);
1735
        $resql = $this->db->query($sql);
1736
        if ($resql) {
1737
            $num = $this->db->num_rows($resql);
1738
            $i = 0;
1739
            while ($i < $num) {
1740
                $obj = $this->db->fetch_object($resql);
1741
                $tab[] = array('fk_socpeople' => $obj->id, 'type_contact' => $obj->fk_c_type_contact);
1742
1743
                $i++;
1744
            }
1745
1746
            return $tab;
1747
        } else {
1748
            $this->error = $this->db->error();
1749
            dol_print_error($this->db);
1750
            return -1;
1751
        }
1752
    }
1753
1754
    /**
1755
     *  Load array of prospect status
1756
     *
1757
     * @param int $active 1=Active only, 0=Not active only, -1=All
1758
     * @return int                 Return integer <0 if KO, >0 if OK
1759
     */
1760
    public function loadCacheOfProspStatus($active = 1)
1761
    {
1762
        global $langs;
1763
1764
        $sql = "SELECT id, code, libelle as label, picto FROM " . MAIN_DB_PREFIX . "c_stcommcontact";
1765
        if ($active >= 0) {
1766
            $sql .= " WHERE active = " . ((int)$active);
1767
        }
1768
        $resql = $this->db->query($sql);
1769
        $num = $this->db->num_rows($resql);
1770
        $i = 0;
1771
        while ($i < $num) {
1772
            $obj = $this->db->fetch_object($resql);
1773
            $this->cacheprospectstatus[$obj->id] = array('id' => $obj->id, 'code' => $obj->code, 'label' => ($langs->trans("ST_" . strtoupper($obj->code)) == "ST_" . strtoupper($obj->code)) ? $obj->label : $langs->trans("ST_" . strtoupper($obj->code)), 'picto' => $obj->picto);
1774
            $i++;
1775
        }
1776
        return 1;
1777
    }
1778
1779
    /**
1780
     *  Return prospect level
1781
     *
1782
     * @return     string        Label
1783
     */
1784
    public function getLibProspLevel()
1785
    {
1786
        return $this->libProspLevel($this->fk_prospectlevel);
1787
    }
1788
1789
    /**
1790
     *  Return label of prospect level
1791
     *
1792
     * @param string $fk_prospectlevel Prospect level
1793
     * @return string                          label of level
1794
     */
1795
    public function libProspLevel($fk_prospectlevel)
1796
    {
1797
        global $langs;
1798
1799
        $lib = $langs->trans("ProspectLevel" . $fk_prospectlevel);
1800
        // If lib not found in language file, we get label from cache/database
1801
        if ($lib == "ProspectLevel" . $fk_prospectlevel) {
1802
            $lib = $langs->getLabelFromKey($this->db, $fk_prospectlevel, 'c_prospectlevel', 'code', 'label');
1803
        }
1804
        return $lib;
1805
    }
1806
1807
    /**
1808
     *  Set prospect level
1809
     *
1810
     * @param User $user User who defines the discount
1811
     * @return int                 Return integer <0 if KO, >0 if OK
1812
     * @deprecated Use update function instead
1813
     */
1814
    public function setProspectLevel(User $user)
1815
    {
1816
        return $this->update($this->id, $user);
1817
    }
1818
1819
    /**
1820
     *  Return status of prospect
1821
     *
1822
     * @param int $mode 0=label long, 1=label short, 2=Picto + Label short, 3=Picto, 4=Picto + Label long
1823
     * @param string $label Label to use for status for added status
1824
     * @return string              Label
1825
     */
1826
    public function getLibProspCommStatut($mode = 0, $label = '')
1827
    {
1828
        return $this->libProspCommStatut($this->stcomm_id, $mode, $label, $this->stcomm_picto);
1829
    }
1830
1831
    /**
1832
     *  Return label of a given status
1833
     *
1834
     * @param int|string $statut Id or code for prospection status
1835
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
1836
     * @param string $label Label to use for status for added status
1837
     * @param string $picto Name of image file to show ('filenew', ...)
1838
     *                                      If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory.
1839
     *                                      Example: picto.png                  if picto.png is stored into htdocs/theme/mytheme/img
1840
     *                                      Example: picto.png@mymodule         if picto.png is stored into htdocs/mymodule/img
1841
     *                                      Example: /mydir/mysubdir/picto.png  if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1)
1842
     * @return string                      Label of status
1843
     */
1844
    public function libProspCommStatut($statut, $mode = 0, $label = '', $picto = '')
1845
    {
1846
        global $langs;
1847
        $langs->load('customers');
1848
1849
        if ($mode == 2) {
1850
            if ($statut == '-1' || $statut == 'ST_NO') {
1851
                return img_action($langs->trans("StatusProspect-1"), -1, $picto) . ' ' . $langs->trans("StatusProspect-1");
1852
            } elseif ($statut == '0' || $statut == 'ST_NEVER') {
1853
                return img_action($langs->trans("StatusProspect0"), 0, $picto) . ' ' . $langs->trans("StatusProspect0");
1854
            } elseif ($statut == '1' || $statut == 'ST_TODO') {
1855
                return img_action($langs->trans("StatusProspect1"), 1, $picto) . ' ' . $langs->trans("StatusProspect1");
1856
            } elseif ($statut == '2' || $statut == 'ST_PEND') {
1857
                return img_action($langs->trans("StatusProspect2"), 2, $picto) . ' ' . $langs->trans("StatusProspect2");
1858
            } elseif ($statut == '3' || $statut == 'ST_DONE') {
1859
                return img_action($langs->trans("StatusProspect3"), 3, $picto) . ' ' . $langs->trans("StatusProspect3");
1860
            } else {
1861
                return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto) . ' ' . (($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label);
1862
            }
1863
        }
1864
        if ($mode == 3) {
1865
            if ($statut == '-1' || $statut == 'ST_NO') {
1866
                return img_action($langs->trans("StatusProspect-1"), -1, $picto);
1867
            } elseif ($statut == '0' || $statut == 'ST_NEVER') {
1868
                return img_action($langs->trans("StatusProspect0"), 0, $picto);
1869
            } elseif ($statut == '1' || $statut == 'ST_TODO') {
1870
                return img_action($langs->trans("StatusProspect1"), 1, $picto);
1871
            } elseif ($statut == '2' || $statut == 'ST_PEND') {
1872
                return img_action($langs->trans("StatusProspect2"), 2, $picto);
1873
            } elseif ($statut == '3' || $statut == 'ST_DONE') {
1874
                return img_action($langs->trans("StatusProspect3"), 3, $picto);
1875
            } else {
1876
                return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto);
1877
            }
1878
        }
1879
        if ($mode == 4) {
1880
            if ($statut == '-1' || $statut == 'ST_NO') {
1881
                return img_action($langs->trans("StatusProspect-1"), -1, $picto) . ' ' . $langs->trans("StatusProspect-1");
1882
            } elseif ($statut == '0' || $statut == 'ST_NEVER') {
1883
                return img_action($langs->trans("StatusProspect0"), 0, $picto) . ' ' . $langs->trans("StatusProspect0");
1884
            } elseif ($statut == '1' || $statut == 'ST_TODO') {
1885
                return img_action($langs->trans("StatusProspect1"), 1, $picto) . ' ' . $langs->trans("StatusProspect1");
1886
            } elseif ($statut == '2' || $statut == 'ST_PEND') {
1887
                return img_action($langs->trans("StatusProspect2"), 2, $picto) . ' ' . $langs->trans("StatusProspect2");
1888
            } elseif ($statut == '3' || $statut == 'ST_DONE') {
1889
                return img_action($langs->trans("StatusProspect3"), 3, $picto) . ' ' . $langs->trans("StatusProspect3");
1890
            } else {
1891
                return img_action(($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label, 0, $picto) . ' ' . (($langs->trans("StatusProspect" . $statut) != "StatusProspect" . $statut) ? $langs->trans("StatusProspect" . $statut) : $label);
1892
            }
1893
        }
1894
1895
        return "Error, mode/status not found";
1896
    }
1897
1898
    /**
1899
     *  Return clickable link of object (with eventually picto)
1900
     *
1901
     * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
1902
     * @param array $arraydata Array of data
1903
     * @return     string                              HTML Code for Kanban thumb.
1904
     */
1905
    public function getKanbanView($option = '', $arraydata = null)
1906
    {
1907
        $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1908
1909
        $return = '<div class="box-flex-item box-flex-grow-zero">';
1910
        $return .= '<div class="info-box info-box-sm">';
1911
        $return .= '<span class="info-box-icon bg-infobox-action">';
1912
        //var_dump($this->photo);exit;
1913
        if (property_exists($this, 'photo') && !is_null($this->photo)) {
1914
            $return .= Form::showphoto('contact', $this, 0, 60, 0, 'photokanban photoref photowithmargin photologintooltip', 'small', 0, 1);
1915
        } else {
1916
            $return .= img_picto('', $this->picto);
1917
        }
1918
        $return .= '</span>';
1919
        $return .= '<div class="info-box-content">';
1920
        $return .= '<div class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(0) : $this->ref) . '</div>';
1921
        if ($selected >= 0) {
1922
            $return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>';
1923
        }
1924
        if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
1925
            $return .= '<div class="info-box-ref tdoverflowmax150">' . $this->thirdparty->getNomUrl(1) . '</div>';
1926
        }
1927
        /*if (property_exists($this, 'phone_pro') && !empty($this->phone_pro)) {
1928
            $return .= '<br>'.img_picto($langs->trans("Phone"), 'phone');
1929
            $return .= ' <span class="info-box-label">'.$this->phone_pro.'</span>';
1930
        }*/
1931
        /*if (method_exists($this, 'LibPubPriv')) {
1932
            $return .= '<br><span class="info-box-label opacitymedium">'.$langs->trans("Visibility").'</span>';
1933
            $return .= '<span> : '.$this->LibPubPriv($this->priv).'</span>';
1934
        }*/
1935
        if (method_exists($this, 'getLibStatut')) {
1936
            $return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>';
1937
        }
1938
        $return .= '</div>';
1939
        $return .= '</div>';
1940
        $return .= '</div>';
1941
        return $return;
1942
    }
1943
1944
    /**
1945
     *  Return name of contact with link (and eventually picto)
1946
     *  Use $this->id, $this->lastname, $this->firstname, this->civility_id
1947
     *
1948
     * @param int $withpicto Include picto with link (0=no picto, 1=picto + name, 2=picto only, -1=photo+name, -2=photo only)
1949
     * @param string $option Where the link point to
1950
     * @param int $maxlen Max length of
1951
     * @param string $moreparam Add more param into URL
1952
     * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
1953
     * @param int $notooltip 1=Disable tooltip
1954
     * @param string $morecss Add more css on link
1955
     * @return     string                                  String with URL
1956
     */
1957
    public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $moreparam = '', $save_lastsearch_value = -1, $notooltip = 0, $morecss = '')
1958
    {
1959
        global $conf, $langs, $hookmanager;
1960
1961
        if (!empty($conf->dol_no_mouse_hover)) {
1962
            $notooltip = 1; // Force disable tooltips
1963
        }
1964
1965
        $result = '';
1966
        $params = [
1967
            'id' => $this->id,
1968
            'objecttype' => $this->element,
1969
            'option' => $option,
1970
        ];
1971
        $classfortooltip = 'classfortooltip';
1972
        $dataparams = '';
1973
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1974
            $classfortooltip = 'classforajaxtooltip';
1975
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
1976
            $label = '';
1977
        } else {
1978
            $label = implode($this->getTooltipContentArray($params));
1979
        }
1980
1981
        $url = constant('BASE_URL') . '/contact/card.php?id=' . $this->id;
1982
1983
        if ($option !== 'nolink') {
1984
            // Add param to save lastsearch_values or not
1985
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1986
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1987
                $add_save_lastsearch_values = 1;
1988
            }
1989
            if ($url && $add_save_lastsearch_values) {
1990
                $url .= '&save_lastsearch_values=1';
1991
            }
1992
        }
1993
1994
        $url .= $moreparam;
1995
1996
        $linkclose = '';
1997
        if (empty($notooltip)) {
1998
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1999
                $label = $langs->trans("ShowContact");
2000
                $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
2001
            }
2002
            $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"');
2003
            $linkclose .= $dataparams . ' class="' . $classfortooltip . ($morecss ? ' ' . $morecss : '') . '"';
2004
        } else {
2005
            $linkclose = ($morecss ? ' class="' . $morecss . '"' : '');
2006
        }
2007
2008
        if ($option == 'nolink' || empty($url)) {
2009
            $linkstart = '<span';
2010
        } else {
2011
            $linkstart = '<a href="' . $url . '"';
2012
        }
2013
        $linkstart .= $linkclose . '>';
2014
        if ($option == 'nolink' || empty($url)) {
2015
            $linkend = '</span>';
2016
        } else {
2017
            $linkend = '</a>';
2018
        }
2019
2020
        $result .= $linkstart;
2021
2022
        if ($withpicto) {
2023
            if ($withpicto < 0) {
2024
                $result .= '<!-- picto photo contact --><span class="nopadding userimg' . ($morecss ? ' ' . $morecss : '') . '">' . Form::showphoto('contact', $this, 0, 0, 0, 'userphoto' . ($withpicto == -3 ? 'small' : ''), 'mini', 0, 1) . '</span>';
2025
                if ($withpicto != 2 && $withpicto != -2) {
2026
                    $result .= ' ';
2027
                }
2028
            } else {
2029
                $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="pictofixedwidth valignmiddle"' : '') : 'class="' . (($withpicto != 2) ? 'pictofixedwidth valignmiddle' : '') . '"'), 0, 0, $notooltip ? 0 : 1);
2030
            }
2031
        }
2032
        if ($withpicto != 2 && $withpicto != -2) {
2033
            $result .= '<span class="valigmiddle">' . ($maxlen ? dol_trunc($this->getFullName($langs), $maxlen) : $this->getFullName($langs)) . '</span>';
2034
        }
2035
2036
        $result .= $linkend;
2037
2038
        global $action;
2039
        $hookmanager->initHooks(array('contactdao'));
2040
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
2041
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2042
        if ($reshook > 0) {
2043
            $result = $hookmanager->resPrint;
2044
        } else {
2045
            $result .= $hookmanager->resPrint;
2046
        }
2047
2048
        return $result;
2049
    }
2050
2051
    /**
2052
     * getTooltipContentArray
2053
     * @param array $params params to construct tooltip data
2054
     * @return array
2055
     * @since v18
2056
     */
2057
    public function getTooltipContentArray($params)
2058
    {
2059
        global $conf, $langs, $user;
2060
2061
        $datas = [];
2062
2063
        if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2064
            return ['optimize' => $langs->trans("ShowContact")];
2065
        }
2066
        if (!empty($this->photo) && class_exists('Form')) {
2067
            $photo = '<div class="photointooltip floatright">';
2068
            $photo .= Form::showphoto('contact', $this, 0, 40, 0, 'photoref', 'mini', 0); // Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip.
2069
            $photo .= '</div>';
2070
            $datas['photo'] = $photo;
2071
        }
2072
2073
        $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("Contact") . '</u> ' . $this->getLibStatut(4);
2074
        $datas['name'] = '<br><b>' . $langs->trans("Name") . ':</b> ' . $this->getFullName($langs);
2075
        // if ($this->civility_id) $datas['civility'] = '<br><b>' . $langs->trans("Civility") . ':</b> '.$this->civility_id;        // TODO Translate civilty_id code
2076
        if (!empty($this->poste)) {
2077
            $datas['job'] = '<br><b>' . $langs->trans("Poste") . ':</b> ' . $this->poste;
2078
        }
2079
        $datas['email'] = '<br><b>' . $langs->trans("EMail") . ':</b> ' . $this->email;
2080
        $phonelist = array();
2081
        $country_code = empty($this->country_code) ? '' : $this->country_code;
2082
        if ($this->phone_pro) {
2083
            $phonelist[] = dol_print_phone($this->phone_pro, $country_code, $this->id, 0, '', '&nbsp;', 'phone');
2084
        }
2085
        if ($this->phone_mobile) {
2086
            $phonelist[] = dol_print_phone($this->phone_mobile, $country_code, $this->id, 0, '', '&nbsp;', 'mobile');
2087
        }
2088
        if ($this->phone_perso) {
2089
            $phonelist[] = dol_print_phone($this->phone_perso, $country_code, $this->id, 0, '', '&nbsp;', 'phone');
2090
        }
2091
        $datas['phonelist'] = '<br><b>' . $langs->trans("Phone") . ':</b> ' . implode('&nbsp;', $phonelist);
2092
        $datas['address'] = '<br><b>' . $langs->trans("Address") . ':</b> ' . dol_format_address($this, 1, ' ', $langs);
2093
2094
        return $datas;
2095
    }
2096
2097
    /**
2098
     *  Return the label of the status
2099
     *
2100
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2101
     * @return string                 Label of status
2102
     */
2103
    public function getLibStatut($mode)
2104
    {
2105
        return $this->LibStatut($this->statut, $mode);
2106
    }
2107
2108
    /**
2109
     *  Return the label of a given status
2110
     *
2111
     * @param int $status Id status
2112
     * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2113
     * @return string                 Label of status
2114
     */
2115
    public function LibStatut($status, $mode)
2116
    {
2117
        // phpcs:enable
2118
        global $langs;
2119
2120
        $labelStatus = array(
2121
            0 => 'ActivityCeased',
2122
            1 => 'InActivity',
2123
            4 => 'InActivity',
2124
            5 => 'ActivityCeased',
2125
        );
2126
        $labelStatusShort = array(
2127
            0 => 'ActivityCeased',
2128
            1 => 'InActivity',
2129
            4 => 'InActivity',
2130
            5 => 'ActivityCeased',
2131
        );
2132
2133
        $statusType = 'status4';
2134
        if ($status == 0 || $status == 5) {
2135
            $statusType = 'status5';
2136
        }
2137
2138
        $label = $langs->transnoentitiesnoconv($labelStatus[$status]);
2139
        $labelshort = $langs->transnoentitiesnoconv($labelStatusShort[$status]);
2140
2141
        return dolGetStatus($label, $labelshort, '', $statusType, $mode);
2142
    }
2143
2144
    /**
2145
     *  Set "blacklist" mailing status
2146
     *
2147
     * @param int $no_email 1=Do not send mailing, 0=Ok to receive mailing
2148
     * @return int                 Return integer <0 if KO, >0 if OK
2149
     */
2150
}
2151