Passed
Push — main ( f1540e...02d90d )
by Rafael
45:15
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
use DoliCore\Api\DolibarrApi;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, DolibarrApi. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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