Passed
Push — CHECK_API ( 78ffdd...fa4f39 )
by Rafael
41:29
created

Contacts::index()   F

Complexity

Conditions 24
Paths 16257

Size

Total Lines 95
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 24
eloc 59
nc 16257
nop 10
dl 0
loc 95
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2015       Jean-François Ferry         <[email protected]>
4
 * Copyright (C) 2019       Frédéric France             <[email protected]>
5
 * Copyright (C) 2024		MDW							<[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Dolibarr\Code\Societe\Api;
23
24
use Dolibarr\Code\Contact\Classes\Contact;
25
use Dolibarr\Core\Base\DolibarrApi;
26
use Luracast\Restler\RestException;
27
28
/**
29
 * API class for contacts
30
 *
31
 * @access protected
32
 * @class  DolibarrApiAccess {@requires user,external}
33
 */
34
class Contacts extends DolibarrApi
35
{
36
    /**
37
     *
38
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
39
     */
40
    public static $FIELDS = array(
41
        'lastname',
42
    );
43
44
    /**
45
     * @var Contact $contact {@type Contact}
46
     */
47
    public $contact;
48
49
    /**
50
     * Constructor
51
     */
52
    public function __construct()
53
    {
54
        global $db, $conf;
55
        $this->db = $db;
56
57
        $this->contact = new Contact($this->db);
58
    }
59
60
    /**
61
     * Get properties of a contact object
62
     *
63
     * Return an array with contact information
64
     *
65
     * @param   int    $id                  ID of contact
66
     * @param   int    $includecount        Count and return also number of elements the contact is used as a link for
67
     * @param   int    $includeroles        Includes roles of the contact
68
     * @return  object                      data without useless information
69
     *
70
     * @throws  RestException
71
     */
72
    public function get($id, $includecount = 0, $includeroles = 0)
73
    {
74
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
75
            throw new RestException(403, 'No permission to read contacts');
76
        }
77
78
        if ($id === 0) {
79
            $result = $this->contact->initAsSpecimen();
80
        } else {
81
            $result = $this->contact->fetch($id);
82
        }
83
84
        if (!$result) {
85
            throw new RestException(404, 'Contact not found');
86
        }
87
88
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
89
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
90
        }
91
92
        if ($includecount) {
93
            $this->contact->load_ref_elements();
94
        }
95
96
        if ($includeroles) {
97
            $this->contact->fetchRoles();
98
        }
99
100
        if (isModEnabled('mailing')) {
101
            $this->contact->getNoEmail();
102
        }
103
104
        return $this->_cleanObjectDatas($this->contact);
105
    }
106
107
    /**
108
     * Get properties of a contact object by Email
109
     *
110
     * @param   string  $email                  Email of contact
111
     * @param   int    $includecount        Count and return also number of elements the contact is used as a link for
112
     * @param   int    $includeroles        Includes roles of the contact
113
     * @return  array|mixed data without useless information
114
     *
115
     * @url GET email/{email}
116
     *
117
     * @throws RestException 401     Insufficient rights
118
     * @throws RestException 404     User or group not found
119
     */
120
    public function getByEmail($email, $includecount = 0, $includeroles = 0)
121
    {
122
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
123
            throw new RestException(403, 'No permission to read contacts');
124
        }
125
126
        if (empty($email)) {
127
            $result = $this->contact->initAsSpecimen();
128
        } else {
129
            $result = $this->contact->fetch('', '', '', $email);
130
        }
131
132
        if (!$result) {
133
            throw new RestException(404, 'Contact not found');
134
        }
135
136
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
137
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
138
        }
139
140
        if ($includecount) {
141
            $this->contact->load_ref_elements();
142
        }
143
144
        if ($includeroles) {
145
            $this->contact->fetchRoles();
146
        }
147
148
        if (isModEnabled('mailing')) {
149
            $this->contact->getNoEmail();
150
        }
151
152
        return $this->_cleanObjectDatas($this->contact);
153
    }
154
155
    /**
156
     * List contacts
157
     *
158
     * Get a list of contacts
159
     *
160
     * @param string    $sortfield          Sort field
161
     * @param string    $sortorder          Sort order
162
     * @param int       $limit              Limit for list
163
     * @param int       $page               Page number
164
     * @param string    $thirdparty_ids     Thirdparty ids to filter contacts of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
165
     * @param int       $category   Use this param to filter list by category
166
     * @param string    $sqlfilters         Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
167
     * @param int       $includecount       Count and return also number of elements the contact is used as a link for
168
     * @param int       $includeroles        Includes roles of the contact
169
     * @param string    $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
170
     * @return Contact[]                        Array of contact objects
171
     *
172
     * @throws RestException
173
     */
174
    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includecount = 0, $includeroles = 0, $properties = '')
175
    {
176
        global $db, $conf;
177
178
        $obj_ret = array();
179
180
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
181
            throw new RestException(403, 'No permission to read contacts');
182
        }
183
184
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
185
        $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
186
187
        // If the internal user must only see his customers, force searching by him
188
        $search_sale = 0;
189
        if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
190
            $search_sale = DolibarrApiAccess::$user->id;
191
        }
192
193
        $sql = "SELECT t.rowid";
194
        $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as t";
195
        if ($category > 0) {
196
            $sql .= ", " . MAIN_DB_PREFIX . "categorie_contact as c";
197
        }
198
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "socpeople_extrafields as te ON te.fk_object = t.rowid";
199
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON t.fk_soc = s.rowid";
200
        $sql .= ' WHERE t.entity IN (' . getEntity('contact') . ')';
201
        if ($socids) {
202
            $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socids) . ")";
203
        }
204
        // Search on sale representative
205
        if ($search_sale && $search_sale != '-1') {
206
            if ($search_sale == -2) {
207
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
208
            } elseif ($search_sale > 0) {
209
                $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = " . ((int) $search_sale) . ")";
210
            }
211
        }
212
        // Select contacts of given category
213
        if ($category > 0) {
214
            $sql .= " AND c.fk_categorie = " . ((int) $category);
215
            $sql .= " AND c.fk_socpeople = t.rowid ";
216
        }
217
218
        // Add sql filters
219
        if ($sqlfilters) {
220
            $errormessage = '';
221
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
222
            if ($errormessage) {
223
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
224
            }
225
        }
226
227
        $sql .= $this->db->order($sortfield, $sortorder);
228
229
        if ($limit) {
230
            if ($page < 0) {
231
                $page = 0;
232
            }
233
            $offset = $limit * $page;
234
235
            $sql .= $this->db->plimit($limit + 1, $offset);
236
        }
237
        $result = $this->db->query($sql);
238
        if ($result) {
239
            $num = $this->db->num_rows($result);
240
            $min = min($num, ($limit <= 0 ? $num : $limit));
241
            $i = 0;
242
            while ($i < $min) {
243
                $obj = $this->db->fetch_object($result);
244
                $contact_static = new Contact($this->db);
245
                if ($contact_static->fetch($obj->rowid)) {
246
                    $contact_static->fetchRoles();
247
                    if ($includecount) {
248
                        $contact_static->load_ref_elements();
249
                    }
250
                    if ($includeroles) {
251
                        $contact_static->fetchRoles();
252
                    }
253
                    if (isModEnabled('mailing')) {
254
                        $contact_static->getNoEmail();
255
                    }
256
257
                    $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($contact_static), $properties);
258
                }
259
260
                $i++;
261
            }
262
        } else {
263
            throw new RestException(503, 'Error when retrieve contacts : ' . $sql);
264
        }
265
        if (!count($obj_ret)) {
266
            throw new RestException(404, 'Contacts not found');
267
        }
268
        return $obj_ret;
269
    }
270
271
    /**
272
     * Create contact object
273
     *
274
     * @param   array   $request_data   Request datas
275
     * @return  int     ID of contact
276
     *
277
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
278
     */
279
    public function post($request_data = null)
280
    {
281
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
282
            throw new RestException(403, 'No permission to create/update contacts');
283
        }
284
        // Check mandatory fields
285
        $result = $this->_validate($request_data);
286
287
        foreach ($request_data as $field => $value) {
288
            if ($field === 'caller') {
289
                // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
290
                $this->contact->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
291
                continue;
292
            }
293
            if ($field == 'array_options' && is_array($value)) {
294
                foreach ($value as $index => $val) {
295
                    $this->contact->array_options[$index] = $this->_checkValForAPI('extrafields', $val, $this->contact);
296
                }
297
                continue;
298
            }
299
300
            $this->contact->$field = $this->_checkValForAPI($field, $value, $this->contact);
301
        }
302
        if ($this->contact->create(DolibarrApiAccess::$user) < 0) {
303
            throw new RestException(500, "Error creating contact", array_merge(array($this->contact->error), $this->contact->errors));
304
        }
305
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset($this->contact->no_email)) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Contact\Classes\Contact::$no_email has been deprecated: Has been replaced by a search into llx_mailing_unsubscribe ( Ignorable by Annotation )

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

305
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset(/** @scrutinizer ignore-deprecated */ $this->contact->no_email)) {

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...
306
            $this->contact->setNoEmail($this->contact->no_email);
307
        }
308
        return $this->contact->id;
309
    }
310
311
    /**
312
     * Update contact
313
     *
314
     * @param   int     $id                 Id of contact to update
315
     * @param   array   $request_data       Datas
316
     * @return  Object|false                Updated object, false when issue toupdate
317
     *
318
     * @throws RestException 401
319
     * @throws RestException 404
320
     * @throws RestException 500
321
     */
322
    public function put($id, $request_data = null)
323
    {
324
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
325
            throw new RestException(403, 'No permission to create/update contacts');
326
        }
327
328
        $result = $this->contact->fetch($id);
329
        if (!$result) {
330
            throw new RestException(404, 'Contact not found');
331
        }
332
333
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
334
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
335
        }
336
337
        foreach ($request_data as $field => $value) {
338
            if ($field == 'id') {
339
                continue;
340
            }
341
            if ($field === 'caller') {
342
                // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
343
                $this->contact->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
344
                continue;
345
            }
346
            if ($field == 'array_options' && is_array($value)) {
347
                foreach ($value as $index => $val) {
348
                    $this->contact->array_options[$index] = $this->_checkValForAPI('extrafields', $val, $this->contact);
349
                }
350
                continue;
351
            }
352
353
            $this->contact->$field = $this->_checkValForAPI($field, $value, $this->contact);
354
        }
355
356
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset($this->contact->no_email)) {
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Contact\Classes\Contact::$no_email has been deprecated: Has been replaced by a search into llx_mailing_unsubscribe ( Ignorable by Annotation )

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

356
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset(/** @scrutinizer ignore-deprecated */ $this->contact->no_email)) {

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...
357
            $this->contact->setNoEmail($this->contact->no_email);
358
        }
359
360
        if ($this->contact->update($id, DolibarrApiAccess::$user, 0, 'update') > 0) {
361
            return $this->get($id);
362
        } else {
363
            throw new RestException(500, $this->contact->error);
364
        }
365
    }
366
367
    /**
368
     * Delete contact
369
     *
370
     * @param   int     $id Contact ID
371
     * @return  integer
372
     */
373
    public function delete($id)
374
    {
375
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'supprimer')) {
376
            throw new RestException(403, 'No permission to delete contacts');
377
        }
378
        $result = $this->contact->fetch($id);
379
        if (!$result) {
380
            throw new RestException(404, 'Contact not found');
381
        }
382
383
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
384
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
385
        }
386
        $this->contact->oldcopy = clone $this->contact;
387
        return $this->contact->delete(DolibarrApiAccess::$user);
388
    }
389
390
    /**
391
     * Create an user account object from contact (external user)
392
     *
393
     * @param   int     $id   Id of contact
394
     * @param   array   $request_data   Request datas
395
     * @return  int     ID of user
396
     *
397
     * @url POST {id}/createUser
398
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
399
     */
400
    public function createUser($id, $request_data = null)
401
    {
402
        //if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'creer')) {
403
        //throw new RestException(403);
404
        //}
405
406
        if (!isset($request_data["login"])) {
407
            throw new RestException(400, "login field missing");
408
        }
409
        if (!isset($request_data["password"])) {
410
            throw new RestException(400, "password field missing");
411
        }
412
413
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
414
            throw new RestException(403, 'No permission to read contacts');
415
        }
416
        if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'creer')) {
417
            throw new RestException(403, 'No permission to create user');
418
        }
419
420
        $contact = new Contact($this->db);
421
        $contact->fetch($id);
422
        if ($contact->id <= 0) {
423
            throw new RestException(404, 'Contact not found');
424
        }
425
426
        if (!DolibarrApi::_checkAccessToResource('contact', $contact->id, 'socpeople&societe')) {
427
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
428
        }
429
430
        // Check mandatory fields
431
        $login = $request_data["login"];
432
        $password = $request_data["password"];
433
        $useraccount = new User($this->db);
434
        $result = $useraccount->create_from_contact($contact, $login, $password);
435
        if ($result <= 0) {
436
            throw new RestException(500, "User not created");
437
        }
438
        // password parameter not used in create_from_contact
439
        $useraccount->setPassword($useraccount, $password);
440
441
        return $result;
442
    }
443
444
    /**
445
     * Get categories for a contact
446
     *
447
     * @param int       $id         ID of contact
448
     * @param string    $sortfield  Sort field
449
     * @param string    $sortorder  Sort order
450
     * @param int       $limit      Limit for list
451
     * @param int       $page       Page number
452
     *
453
     * @return mixed
454
     *
455
     * @url GET {id}/categories
456
     */
457
    public function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
458
    {
459
        if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
460
            throw new RestException(403);
461
        }
462
463
        $categories = new Categorie($this->db);
464
465
        $result = $categories->getListForItem($id, 'contact', $sortfield, $sortorder, $limit, $page);
466
467
        if ($result < 0) {
468
            throw new RestException(503, 'Error when retrieve category list : ' . $categories->error);
469
        }
470
471
        return $result;
472
    }
473
474
    /**
475
     * Add a category to a contact
476
     *
477
     * @url PUT {id}/categories/{category_id}
478
     *
479
     * @param   int     $id             Id of contact
480
     * @param   int     $category_id    Id of category
481
     *
482
     * @return  mixed
483
     *
484
     * @throws RestException 401 Insufficient rights
485
     * @throws RestException 404 Category or contact not found
486
     */
487
    public function addCategory($id, $category_id)
488
    {
489
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
490
            throw new RestException(403, 'Insufficient rights');
491
        }
492
493
        $result = $this->contact->fetch($id);
494
        if (!$result) {
495
            throw new RestException(404, 'Contact not found');
496
        }
497
        $category = new Categorie($this->db);
498
        $result = $category->fetch($category_id);
499
        if (!$result) {
500
            throw new RestException(404, 'category not found');
501
        }
502
503
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id)) {
504
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
505
        }
506
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
507
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
508
        }
509
510
        $category->add_type($this->contact, 'contact');
511
512
        return $this->_cleanObjectDatas($this->contact);
513
    }
514
515
    /**
516
     * Remove the link between a category and a contact
517
     *
518
     * @url DELETE {id}/categories/{category_id}
519
     *
520
     * @param   int     $id             Id of contact
521
     * @param   int     $category_id    Id of category
522
     * @return  mixed
523
     *
524
     * @throws  RestException 401     Insufficient rights
525
     * @throws  RestException 404     Category or contact not found
526
     */
527
    public function deleteCategory($id, $category_id)
528
    {
529
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
530
            throw new RestException(403, 'Insufficient rights');
531
        }
532
533
        $result = $this->contact->fetch($id);
534
        if (!$result) {
535
            throw new RestException(404, 'Contact not found');
536
        }
537
        $category = new Categorie($this->db);
538
        $result = $category->fetch($category_id);
539
        if (!$result) {
540
            throw new RestException(404, 'category not found');
541
        }
542
543
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id)) {
544
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
545
        }
546
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
547
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
548
        }
549
550
        $category->del_type($this->contact, 'contact');
551
552
        return $this->_cleanObjectDatas($this->contact);
553
    }
554
555
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
556
    /**
557
     * Clean sensible object datas
558
     *
559
     * @param   Object  $object     Object to clean
560
     * @return  Object              Object with cleaned properties
561
     */
562
    protected function _cleanObjectDatas($object)
563
    {
564
		// phpcs:enable
565
        $object = parent::_cleanObjectDatas($object);
566
567
        unset($object->total_ht);
568
        unset($object->total_tva);
569
        unset($object->total_localtax1);
570
        unset($object->total_localtax2);
571
        unset($object->total_ttc);
572
573
        unset($object->note);
574
        unset($object->lines);
575
        unset($object->thirdparty);
576
577
        return $object;
578
    }
579
580
    /**
581
     * Validate fields before create or update object
582
     *
583
     * @param   string[]|null     $data   Data to validate
584
     * @return  string[]
585
     * @throws  RestException
586
     */
587
    private function _validate($data)
588
    {
589
        $contact = array();
590
        foreach (Contacts::$FIELDS as $field) {
591
            if (!isset($data[$field])) {
592
                throw new RestException(400, "$field field missing");
593
            }
594
            $contact[$field] = $data[$field];
595
        }
596
597
        return $contact;
598
    }
599
}
600