Passed
Push — EXTRACT_CLASSES ( ae6b5c...83d77a )
by Rafael
60:14 queued 23:58
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\Core\Base\DolibarrApi;
25
use Luracast\Restler\RestException;
26
27
//require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
28
//require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
29
30
31
/**
32
 * API class for contacts
33
 *
34
 * @access protected
35
 * @class  DolibarrApiAccess {@requires user,external}
36
 */
37
class Contacts extends DolibarrApi
38
{
39
    /**
40
     *
41
     * @var array   $FIELDS     Mandatory fields, checked when create and update object
42
     */
43
    public static $FIELDS = array(
44
        'lastname',
45
    );
46
47
    /**
48
     * @var Contact $contact {@type Contact}
49
     */
50
    public $contact;
51
52
    /**
53
     * Constructor
54
     */
55
    public function __construct()
56
    {
57
        global $db, $conf;
58
        $this->db = $db;
59
60
        require_once constant('DOL_DOCUMENT_ROOT') . '/contact/class/contact.class.php';
61
        require_once constant('DOL_DOCUMENT_ROOT') . '/categories/class/categorie.class.php';
62
63
        $this->contact = new Contact($this->db);
64
    }
65
66
    /**
67
     * Get properties of a contact object
68
     *
69
     * Return an array with contact information
70
     *
71
     * @param   int    $id                  ID of contact
72
     * @param   int    $includecount        Count and return also number of elements the contact is used as a link for
73
     * @param   int    $includeroles        Includes roles of the contact
74
     * @return  object                      data without useless information
75
     *
76
     * @throws  RestException
77
     */
78
    public function get($id, $includecount = 0, $includeroles = 0)
79
    {
80
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
81
            throw new RestException(403, 'No permission to read contacts');
82
        }
83
84
        if ($id === 0) {
85
            $result = $this->contact->initAsSpecimen();
86
        } else {
87
            $result = $this->contact->fetch($id);
88
        }
89
90
        if (!$result) {
91
            throw new RestException(404, 'Contact not found');
92
        }
93
94
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
95
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
96
        }
97
98
        if ($includecount) {
99
            $this->contact->load_ref_elements();
100
        }
101
102
        if ($includeroles) {
103
            $this->contact->fetchRoles();
104
        }
105
106
        if (isModEnabled('mailing')) {
107
            $this->contact->getNoEmail();
108
        }
109
110
        return $this->_cleanObjectDatas($this->contact);
111
    }
112
113
    /**
114
     * Get properties of a contact object by Email
115
     *
116
     * @param   string  $email                  Email of contact
117
     * @param   int    $includecount        Count and return also number of elements the contact is used as a link for
118
     * @param   int    $includeroles        Includes roles of the contact
119
     * @return  array|mixed data without useless information
120
     *
121
     * @url GET email/{email}
122
     *
123
     * @throws RestException 401     Insufficient rights
124
     * @throws RestException 404     User or group not found
125
     */
126
    public function getByEmail($email, $includecount = 0, $includeroles = 0)
127
    {
128
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
129
            throw new RestException(403, 'No permission to read contacts');
130
        }
131
132
        if (empty($email)) {
133
            $result = $this->contact->initAsSpecimen();
134
        } else {
135
            $result = $this->contact->fetch('', '', '', $email);
136
        }
137
138
        if (!$result) {
139
            throw new RestException(404, 'Contact not found');
140
        }
141
142
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
143
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
144
        }
145
146
        if ($includecount) {
147
            $this->contact->load_ref_elements();
148
        }
149
150
        if ($includeroles) {
151
            $this->contact->fetchRoles();
152
        }
153
154
        if (isModEnabled('mailing')) {
155
            $this->contact->getNoEmail();
156
        }
157
158
        return $this->_cleanObjectDatas($this->contact);
159
    }
160
161
    /**
162
     * List contacts
163
     *
164
     * Get a list of contacts
165
     *
166
     * @param string    $sortfield          Sort field
167
     * @param string    $sortorder          Sort order
168
     * @param int       $limit              Limit for list
169
     * @param int       $page               Page number
170
     * @param string    $thirdparty_ids     Thirdparty ids to filter contacts of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
171
     * @param int       $category   Use this param to filter list by category
172
     * @param string    $sqlfilters         Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
173
     * @param int       $includecount       Count and return also number of elements the contact is used as a link for
174
     * @param int       $includeroles        Includes roles of the contact
175
     * @param string    $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
176
     * @return Contact[]                        Array of contact objects
177
     *
178
     * @throws RestException
179
     */
180
    public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includecount = 0, $includeroles = 0, $properties = '')
181
    {
182
        global $db, $conf;
183
184
        $obj_ret = array();
185
186
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
187
            throw new RestException(403, 'No permission to read contacts');
188
        }
189
190
        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
191
        $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
192
193
        // If the internal user must only see his customers, force searching by him
194
        $search_sale = 0;
195
        if (!DolibarrApiAccess::$user->hasRight('societe', 'client', 'voir') && !$socids) {
196
            $search_sale = DolibarrApiAccess::$user->id;
197
        }
198
199
        $sql = "SELECT t.rowid";
200
        $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as t";
201
        if ($category > 0) {
202
            $sql .= ", " . MAIN_DB_PREFIX . "categorie_contact as c";
203
        }
204
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "socpeople_extrafields as te ON te.fk_object = t.rowid";
205
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON t.fk_soc = s.rowid";
206
        $sql .= ' WHERE t.entity IN (' . getEntity('contact') . ')';
207
        if ($socids) {
208
            $sql .= " AND t.fk_soc IN (" . $this->db->sanitize($socids) . ")";
209
        }
210
        // Search on sale representative
211
        if ($search_sale && $search_sale != '-1') {
212
            if ($search_sale == -2) {
213
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
214
            } elseif ($search_sale > 0) {
215
                $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) . ")";
216
            }
217
        }
218
        // Select contacts of given category
219
        if ($category > 0) {
220
            $sql .= " AND c.fk_categorie = " . ((int) $category);
221
            $sql .= " AND c.fk_socpeople = t.rowid ";
222
        }
223
224
        // Add sql filters
225
        if ($sqlfilters) {
226
            $errormessage = '';
227
            $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
228
            if ($errormessage) {
229
                throw new RestException(400, 'Error when validating parameter sqlfilters -> ' . $errormessage);
230
            }
231
        }
232
233
        $sql .= $this->db->order($sortfield, $sortorder);
234
235
        if ($limit) {
236
            if ($page < 0) {
237
                $page = 0;
238
            }
239
            $offset = $limit * $page;
240
241
            $sql .= $this->db->plimit($limit + 1, $offset);
242
        }
243
        $result = $this->db->query($sql);
244
        if ($result) {
245
            $num = $this->db->num_rows($result);
246
            $min = min($num, ($limit <= 0 ? $num : $limit));
247
            $i = 0;
248
            while ($i < $min) {
249
                $obj = $this->db->fetch_object($result);
250
                $contact_static = new Contact($this->db);
251
                if ($contact_static->fetch($obj->rowid)) {
252
                    $contact_static->fetchRoles();
253
                    if ($includecount) {
254
                        $contact_static->load_ref_elements();
255
                    }
256
                    if ($includeroles) {
257
                        $contact_static->fetchRoles();
258
                    }
259
                    if (isModEnabled('mailing')) {
260
                        $contact_static->getNoEmail();
261
                    }
262
263
                    $obj_ret[] = $this->_filterObjectProperties($this->_cleanObjectDatas($contact_static), $properties);
264
                }
265
266
                $i++;
267
            }
268
        } else {
269
            throw new RestException(503, 'Error when retrieve contacts : ' . $sql);
270
        }
271
        if (!count($obj_ret)) {
272
            throw new RestException(404, 'Contacts not found');
273
        }
274
        return $obj_ret;
275
    }
276
277
    /**
278
     * Create contact object
279
     *
280
     * @param   array   $request_data   Request datas
281
     * @return  int     ID of contact
282
     *
283
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
284
     */
285
    public function post($request_data = null)
286
    {
287
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
288
            throw new RestException(403, 'No permission to create/update contacts');
289
        }
290
        // Check mandatory fields
291
        $result = $this->_validate($request_data);
292
293
        foreach ($request_data as $field => $value) {
294
            if ($field === 'caller') {
295
                // 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
296
                $this->contact->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
297
                continue;
298
            }
299
            if ($field == 'array_options' && is_array($value)) {
300
                foreach ($value as $index => $val) {
301
                    $this->contact->array_options[$index] = $this->_checkValForAPI('extrafields', $val, $this->contact);
302
                }
303
                continue;
304
            }
305
306
            $this->contact->$field = $this->_checkValForAPI($field, $value, $this->contact);
307
        }
308
        if ($this->contact->create(DolibarrApiAccess::$user) < 0) {
309
            throw new RestException(500, "Error creating contact", array_merge(array($this->contact->error), $this->contact->errors));
310
        }
311
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset($this->contact->no_email)) {
312
            $this->contact->setNoEmail($this->contact->no_email);
313
        }
314
        return $this->contact->id;
315
    }
316
317
    /**
318
     * Update contact
319
     *
320
     * @param   int     $id                 Id of contact to update
321
     * @param   array   $request_data       Datas
322
     * @return  Object|false                Updated object, false when issue toupdate
323
     *
324
     * @throws RestException 401
325
     * @throws RestException 404
326
     * @throws RestException 500
327
     */
328
    public function put($id, $request_data = null)
329
    {
330
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
331
            throw new RestException(403, 'No permission to create/update contacts');
332
        }
333
334
        $result = $this->contact->fetch($id);
335
        if (!$result) {
336
            throw new RestException(404, 'Contact not found');
337
        }
338
339
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
340
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
341
        }
342
343
        foreach ($request_data as $field => $value) {
344
            if ($field == 'id') {
345
                continue;
346
            }
347
            if ($field === 'caller') {
348
                // 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
349
                $this->contact->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
350
                continue;
351
            }
352
            if ($field == 'array_options' && is_array($value)) {
353
                foreach ($value as $index => $val) {
354
                    $this->contact->array_options[$index] = $this->_checkValForAPI('extrafields', $val, $this->contact);
355
                }
356
                continue;
357
            }
358
359
            $this->contact->$field = $this->_checkValForAPI($field, $value, $this->contact);
360
        }
361
362
        if (isModEnabled('mailing') && !empty($this->contact->email) && isset($this->contact->no_email)) {
363
            $this->contact->setNoEmail($this->contact->no_email);
364
        }
365
366
        if ($this->contact->update($id, DolibarrApiAccess::$user, 0, 'update') > 0) {
367
            return $this->get($id);
368
        } else {
369
            throw new RestException(500, $this->contact->error);
370
        }
371
    }
372
373
    /**
374
     * Delete contact
375
     *
376
     * @param   int     $id Contact ID
377
     * @return  integer
378
     */
379
    public function delete($id)
380
    {
381
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'supprimer')) {
382
            throw new RestException(403, 'No permission to delete contacts');
383
        }
384
        $result = $this->contact->fetch($id);
385
        if (!$result) {
386
            throw new RestException(404, 'Contact not found');
387
        }
388
389
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) {
390
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
391
        }
392
        $this->contact->oldcopy = clone $this->contact;
393
        return $this->contact->delete(DolibarrApiAccess::$user);
394
    }
395
396
    /**
397
     * Create an user account object from contact (external user)
398
     *
399
     * @param   int     $id   Id of contact
400
     * @param   array   $request_data   Request datas
401
     * @return  int     ID of user
402
     *
403
     * @url POST {id}/createUser
404
     * @suppress PhanPluginUnknownArrayMethodParamType  Luracast limitation
405
     */
406
    public function createUser($id, $request_data = null)
407
    {
408
        //if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'creer')) {
409
        //throw new RestException(403);
410
        //}
411
412
        if (!isset($request_data["login"])) {
413
            throw new RestException(400, "login field missing");
414
        }
415
        if (!isset($request_data["password"])) {
416
            throw new RestException(400, "password field missing");
417
        }
418
419
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'lire')) {
420
            throw new RestException(403, 'No permission to read contacts');
421
        }
422
        if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'creer')) {
423
            throw new RestException(403, 'No permission to create user');
424
        }
425
426
        $contact = new Contact($this->db);
427
        $contact->fetch($id);
428
        if ($contact->id <= 0) {
429
            throw new RestException(404, 'Contact not found');
430
        }
431
432
        if (!DolibarrApi::_checkAccessToResource('contact', $contact->id, 'socpeople&societe')) {
433
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
434
        }
435
436
        // Check mandatory fields
437
        $login = $request_data["login"];
438
        $password = $request_data["password"];
439
        $useraccount = new User($this->db);
440
        $result = $useraccount->create_from_contact($contact, $login, $password);
441
        if ($result <= 0) {
442
            throw new RestException(500, "User not created");
443
        }
444
        // password parameter not used in create_from_contact
445
        $useraccount->setPassword($useraccount, $password);
446
447
        return $result;
448
    }
449
450
    /**
451
     * Get categories for a contact
452
     *
453
     * @param int       $id         ID of contact
454
     * @param string    $sortfield  Sort field
455
     * @param string    $sortorder  Sort order
456
     * @param int       $limit      Limit for list
457
     * @param int       $page       Page number
458
     *
459
     * @return mixed
460
     *
461
     * @url GET {id}/categories
462
     */
463
    public function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0)
464
    {
465
        if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
466
            throw new RestException(403);
467
        }
468
469
        $categories = new Categorie($this->db);
470
471
        $result = $categories->getListForItem($id, 'contact', $sortfield, $sortorder, $limit, $page);
472
473
        if ($result < 0) {
474
            throw new RestException(503, 'Error when retrieve category list : ' . $categories->error);
475
        }
476
477
        return $result;
478
    }
479
480
    /**
481
     * Add a category to a contact
482
     *
483
     * @url PUT {id}/categories/{category_id}
484
     *
485
     * @param   int     $id             Id of contact
486
     * @param   int     $category_id    Id of category
487
     *
488
     * @return  mixed
489
     *
490
     * @throws RestException 401 Insufficient rights
491
     * @throws RestException 404 Category or contact not found
492
     */
493
    public function addCategory($id, $category_id)
494
    {
495
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
496
            throw new RestException(403, 'Insufficient rights');
497
        }
498
499
        $result = $this->contact->fetch($id);
500
        if (!$result) {
501
            throw new RestException(404, 'Contact not found');
502
        }
503
        $category = new Categorie($this->db);
504
        $result = $category->fetch($category_id);
505
        if (!$result) {
506
            throw new RestException(404, 'category not found');
507
        }
508
509
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id)) {
510
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
511
        }
512
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
513
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
514
        }
515
516
        $category->add_type($this->contact, 'contact');
517
518
        return $this->_cleanObjectDatas($this->contact);
519
    }
520
521
    /**
522
     * Remove the link between a category and a contact
523
     *
524
     * @url DELETE {id}/categories/{category_id}
525
     *
526
     * @param   int     $id             Id of contact
527
     * @param   int     $category_id    Id of category
528
     * @return  mixed
529
     *
530
     * @throws  RestException 401     Insufficient rights
531
     * @throws  RestException 404     Category or contact not found
532
     */
533
    public function deleteCategory($id, $category_id)
534
    {
535
        if (!DolibarrApiAccess::$user->hasRight('societe', 'contact', 'creer')) {
536
            throw new RestException(403, 'Insufficient rights');
537
        }
538
539
        $result = $this->contact->fetch($id);
540
        if (!$result) {
541
            throw new RestException(404, 'Contact not found');
542
        }
543
        $category = new Categorie($this->db);
544
        $result = $category->fetch($category_id);
545
        if (!$result) {
546
            throw new RestException(404, 'category not found');
547
        }
548
549
        if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id)) {
550
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
551
        }
552
        if (!DolibarrApi::_checkAccessToResource('category', $category->id)) {
553
            throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
554
        }
555
556
        $category->del_type($this->contact, 'contact');
557
558
        return $this->_cleanObjectDatas($this->contact);
559
    }
560
561
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
562
    /**
563
     * Clean sensible object datas
564
     *
565
     * @param   Object  $object     Object to clean
566
     * @return  Object              Object with cleaned properties
567
     */
568
    protected function _cleanObjectDatas($object)
569
    {
570
		// phpcs:enable
571
        $object = parent::_cleanObjectDatas($object);
572
573
        unset($object->total_ht);
574
        unset($object->total_tva);
575
        unset($object->total_localtax1);
576
        unset($object->total_localtax2);
577
        unset($object->total_ttc);
578
579
        unset($object->note);
580
        unset($object->lines);
581
        unset($object->thirdparty);
582
583
        return $object;
584
    }
585
586
    /**
587
     * Validate fields before create or update object
588
     *
589
     * @param   string[]|null     $data   Data to validate
590
     * @return  string[]
591
     * @throws  RestException
592
     */
593
    private function _validate($data)
594
    {
595
        $contact = array();
596
        foreach (Contacts::$FIELDS as $field) {
597
            if (!isset($data[$field])) {
598
                throw new RestException(400, "$field field missing");
599
            }
600
            $contact[$field] = $data[$field];
601
        }
602
603
        return $contact;
604
    }
605
}
606