AutoCompleteController.php 41.9 KB
Newer Older
Damien's avatar
Damien committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

/**
* Copyright Maarch since 2008 under licence GPLv3.
* See LICENCE.txt file at the root folder for more details.
* This file is part of Maarch software.
*
*/

/**
* @brief Auto Complete Controller
* @author dev@maarch.org
*/

namespace SrcCore\controllers;

Damien's avatar
Damien committed
17
use Contact\controllers\ContactController;
18
use Contact\models\ContactGroupModel;
Damien's avatar
Damien committed
19
use Contact\models\ContactModel;
20
use Contact\models\ContactParameterModel;
21
use Entity\models\EntityModel;
22
use Group\controllers\PrivilegeController;
23
24
25
use Group\models\GroupModel;
use Group\models\PrivilegeModel;
use Priority\models\PriorityModel;
Damien's avatar
Damien committed
26
use Respect\Validation\Validator;
Damien's avatar
Damien committed
27
28
use Slim\Http\Request;
use Slim\Http\Response;
29
use SrcCore\models\CoreConfigModel;
30
use SrcCore\models\CurlModel;
Damien's avatar
Damien committed
31
use SrcCore\models\DatabaseModel;
Damien's avatar
Damien committed
32
use SrcCore\models\TextFormatModel;
Damien's avatar
Damien committed
33
use SrcCore\models\ValidatorModel;
Damien's avatar
Damien committed
34
use Status\models\StatusModel;
35
use Tag\models\TagModel;
36
use User\controllers\UserController;
37
use User\models\UserGroupModel;
Damien's avatar
Damien committed
38
use User\models\UserModel;
39
40
use Folder\models\FolderModel;
use Folder\controllers\FolderController;
41
use MessageExchange\controllers\AnnuaryController;
Damien's avatar
Damien committed
42
43
44

class AutoCompleteController
{
Damien's avatar
Damien committed
45
    const LIMIT = 50;
Damien's avatar
Damien committed
46
    const TINY_LIMIT = 10;
Damien's avatar
Damien committed
47

Damien's avatar
Damien committed
48
49
    public static function getUsers(Request $request, Response $response)
    {
50
51
        $queryParams = $request->getQueryParams();
        $check = Validator::stringType()->notEmpty()->validate($queryParams['search']);
52
53
54
        if (!$check) {
            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
        }
Damien's avatar
Damien committed
55

56
        $fields = ['firstname', 'lastname'];
57
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
58

59
60
61
62
63
64
65
66
67
68
        $where = ['status not in (?)', 'mode not in (?)'];
        $data = [['DEL', 'SPD'], ['root_invisible', 'rest']];
        if (!empty($queryParams['inEntity'])) {
            if (is_numeric($queryParams['inEntity'])) {
                $entity = EntityModel::getById(['select' => ['entity_id'], 'id' => $queryParams['inEntity']]);
                $queryParams['inEntity'] = $entity['entity_id'];
            }
            $where[] = 'id in (SELECT user_id FROM users_entities WHERE entity_id = ?)';
            $data[] = $queryParams['inEntity'];
        }
Damien's avatar
Damien committed
69
        $requestData = AutoCompleteController::getDataForRequest([
70
            'search'        => $queryParams['search'],
71
            'fields'        => $fields,
72
73
            'where'         => $where,
            'data'          => $data,
Damien's avatar
Damien committed
74
75
            'fieldsNumber'  => 2,
        ]);
Damien's avatar
Damien committed
76

77
        $users = UserModel::get([
Damien's avatar
Damien committed
78
            'select'    => ['id', 'user_id', 'firstname', 'lastname'],
Damien's avatar
Damien committed
79
80
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
Damien's avatar
Damien committed
81
82
            'orderBy'   => ['lastname'],
            'limit'     => self::LIMIT
83
84
        ]);

Damien's avatar
Damien committed
85
        $data = [];
Florian Azizian's avatar
Florian Azizian committed
86
        foreach ($users as $value) {
87
            $primaryEntity = UserModel::getPrimaryEntityById(['id' => $value['id'], 'select' => ['entities.entity_label']]);
Damien's avatar
Damien committed
88
            $data[] = [
89
                'type'                  => 'user',
90
                'id'                    => empty($queryParams['serial']) ? $value['user_id'] : $value['id'],
91
92
93
94
                'serialId'              => $value['id'],
                'idToDisplay'           => "{$value['firstname']} {$value['lastname']}",
                'descriptionToDisplay'  => empty($primaryEntity) ? '' : $primaryEntity['entity_label'],
                'otherInfo'             => ''
Damien's avatar
Damien committed
95
96
97
98
99
100
            ];
        }

        return $response->withJson($data);
    }

101
102
103
104
105
    public static function getMaarchParapheurUsers(Request $request, Response $response)
    {
        $data = $request->getQueryParams();
        $check = Validator::stringType()->notEmpty()->validate($data['search']);
        if (!$check) {
106
            return $response->withStatus(400)->withJson(['errors' => 'search is empty']);
107
108
        }

Florian Azizian's avatar
Florian Azizian committed
109
110
111
112
113
        if (!empty($data['exludeAlreadyConnected'])) {
            $usersAlreadyConnected = UserModel::get([
                'select' => ['external_id->>\'maarchParapheur\' as external_id'],
                'where' => ['external_id->>\'maarchParapheur\' is not null']
            ]);
114
            $excludedUsers = array_column($usersAlreadyConnected, 'external_id');
Florian Azizian's avatar
Florian Azizian committed
115
116
        }

117
118
119
120
121
122
123
124
125
126
127
128
        $loadedXml = CoreConfigModel::getXmlLoaded(['path' => 'modules/visa/xml/remoteSignatoryBooks.xml']);

        if ($loadedXml->signatoryBookEnabled == 'maarchParapheur') {
            foreach ($loadedXml->signatoryBook as $value) {
                if ($value->id == "maarchParapheur") {
                    $url      = $value->url;
                    $userId   = $value->userId;
                    $password = $value->password;
                    break;
                }
            }

129
            $curlResponse = CurlModel::exec([
130
                'url'           => rtrim($url, '/') . '/rest/autocomplete/users?search='.urlencode($data['search']),
131
132
                'basicAuth'     => ['user' => $userId, 'password' => $password],
                'headers'       => ['content-type:application/json'],
133
                'method'        => 'GET'
134
135
136
137
138
139
140
141
142
143
144
145
146
            ]);

            if ($curlResponse['code'] != '200') {
                if (!empty($curlResponse['response']['errors'])) {
                    $errors =  $curlResponse['response']['errors'];
                } else {
                    $errors =  $curlResponse['errors'];
                }
                if (empty($errors)) {
                    $errors = 'An error occured. Please check your configuration file.';
                }
                return $response->withStatus(400)->withJson(['errors' => $errors]);
            }
147
148

            foreach ($curlResponse['response'] as $key => $value) {
149
150
151
152
                if (!empty($data['exludeAlreadyConnected']) && in_array($value['id'], $excludedUsers)) {
                    unset($curlResponse['response'][$key]);
                    continue;
                }
153
154
                $curlResponse['response'][$key]['idToDisplay'] = $value['firstname'] . ' ' . $value['lastname'];
                $curlResponse['response'][$key]['externalId']['maarchParapheur'] = $value['id'];
155
156
157
158
159
160

                // Remove external value in signatureModes
                $array = $curlResponse['response'][$key]['signatureModes'];
                unset($array[array_search('external', $array)]);
                $array = array_values($array);
                $curlResponse['response'][$key]['signatureModes'] = $array;
161
            }
162
163
164
165
166
167
            return $response->withJson($curlResponse['response']);
        } else {
            return $response->withStatus(403)->withJson(['errors' => 'maarchParapheur is not enabled']);
        }
    }

168
    public static function getCorrespondents(Request $request, Response $response)
169
    {
170
        $queryParams = $request->getQueryParams();
171

172
173
        if (!Validator::stringType()->notEmpty()->validate($queryParams['search'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Query params search is empty']);
174
175
        }

176
177
178
179
180
181
182
        $limit = self::TINY_LIMIT;
        if (!empty($queryParams['limit']) && is_numeric($queryParams['limit'])) {
            $limit = (int)$queryParams['limit'];
        } elseif (!empty($queryParams['limit']) && $queryParams['limit'] == 'none') {
            $limit = 0;
        }

183
184
        $searchOnEmails = !empty($queryParams['searchEmails']);

185
186
187
        //Contacts
        $autocompleteContacts = [];
        if (empty($queryParams['noContacts'])) {
188
189
190
191
192
            $searchableParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['searchable = ?'], 'data' => [true]]);

            $fields = [];
            foreach ($searchableParameters as $searchableParameter) {
                if (strpos($searchableParameter['identifier'], 'contactCustomField_') !== false) {
193
194
                    $customFieldId = explode('_', $searchableParameter['identifier'])[1];
                    $fields[] = "custom_fields->>'{$customFieldId}'";
195
                } else {
196
                    $fields[] = ContactController::MAPPING_FIELDS[$searchableParameter['identifier']];
197
198
199
                }
            }

200
            if ($searchOnEmails && !in_array('email', $fields)) {
201
                $fields[] = 'email';
202
203
            }

204
            $fieldsNumber = count($fields);
205
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
206

207
208
209
210
211
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $queryParams['search'],
                'fields'        => $fields,
                'where'         => ['enabled = ?'],
                'data'          => [true],
212
                'fieldsNumber'  => $fieldsNumber
213
            ]);
214

215
            $contacts = ContactModel::get([
216
                'select'    => ['id', 'email'],
217
218
                'where'     => $requestData['where'],
                'data'      => $requestData['data'],
219
                'orderBy'   => ['company', 'lastname NULLS FIRST'],
220
                'limit'     => $limit
221
            ]);
222

223
            foreach ($contacts as $contact) {
224
225
226
227
228
229
230
                $autoContact = ContactController::getAutocompleteFormat(['id' => $contact['id']]);

                if ($searchOnEmails && empty($autoContact['email'])) {
                    $autoContact['email'] = $contact['email'];
                }

                $autocompleteContacts[] = $autoContact;
231
232
233
            }
        }

234
235
236
237
        //Users
        $autocompleteUsers = [];
        if (empty($queryParams['noUsers'])) {
            $fields = ['firstname', 'lastname'];
238
239
240
241
242
243
244

            if ($searchOnEmails) {
                $fields[] = 'mail';
            }

            $nbFields = count($fields);

245
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
246
247
248
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $queryParams['search'],
                'fields'        => $fields,
249
                'where'         => ['status not in (?)', 'mode not in (?)'],
250
                'data'          => [['DEL', 'SPD'], ['root_invisible', 'rest']],
251
                'fieldsNumber'  => $nbFields,
252
            ]);
253

254
            $users = UserModel::get([
255
                'select'    => ['id', 'firstname', 'lastname', 'mail'],
256
257
258
                'where'     => $requestData['where'],
                'data'      => $requestData['data'],
                'orderBy'   => ['lastname'],
259
                'limit'     => $limit
260
            ]);
261

262
            foreach ($users as $user) {
263
                $autoUser = [
264
265
                    'type'          => 'user',
                    'id'            => $user['id'],
266
267
                    'firstname'     => $user['firstname'],
                    'lastname'      => $user['lastname']
268
                ];
269
270
271
272
273
274

                if ($searchOnEmails) {
                    $autoUser['email'] = $user['mail'];
                }

                $autocompleteUsers[] = $autoUser;
275
            }
276
277
        }

278
279
280
281
        //Entities
        $autocompleteEntities = [];
        if (empty($queryParams['noEntities'])) {
            $fields = ['entity_label'];
282
283
284
285
286
287
288

            if ($searchOnEmails) {
                $fields[] = 'email';
            }

            $nbFields = count($fields);

289
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
290
291
292
293
294
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $queryParams['search'],
                'fields'        => $fields,
                'where'         => ['enabled = ?'],
                'data'          => ['Y'],
295
                'fieldsNumber'  => $nbFields,
296
            ]);
297

298
            $entities = EntityModel::get([
299
300
301
302
                'select'    => [
                    'id', 'entity_id', 'entity_label', 'short_label', 'email', 'address_number', 'address_street', 'address_additional1',
                    'address_additional2', 'address_postcode', 'address_town', 'address_country'
                ],
303
304
305
                'where'     => $requestData['where'],
                'data'      => $requestData['data'],
                'orderBy'   => ['entity_label'],
306
                'limit'     => $limit
307
            ]);
308

309
            foreach ($entities as $value) {
310
                $entity = [
311
312
313
314
315
316
317
318
319
320
321
                    'type'                  => 'entity',
                    'id'                    => $value['id'],
                    'lastname'              => $value['entity_label'],
                    'firstname'             => '',
                    'addressNumber'         => $value['address_number'],
                    'addressStreet'         => $value['address_street'],
                    'addressAdditional1'    => $value['address_additional1'],
                    'addressAdditional2'    => $value['address_additional2'],
                    'addressPostcode'       => $value['address_postcode'],
                    'addressTown'           => $value['address_town'],
                    'addressCountry'        => $value['address_country']
322
                ];
323
324
325
326
327
328

                if ($searchOnEmails) {
                    $entity['email'] = $value['email'];
                }

                $autocompleteEntities[] = $entity;
329
330
            }
        }
331

332
333
334
335
        //Contacts Groups
        $autocompleteContactsGroups = [];
        if (empty($queryParams['noContactsGroups'])) {
            $fields = ['label'];
336
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
337
338
339
340
341
342
343
344
345
            $hasService = PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']]);

            $where = [];
            $data = [];
            if ($hasService) {
                $where[] = '1=1';
            } else {
                $userEntities = UserModel::getEntitiesById(['id' => $GLOBALS['id'], 'select' => ['entities.id']]);

346
                $entitiesId = array_column($userEntities, 'id');
347
348
349
350
351
                $where[] = '(owner = ? OR entities @> ?)';
                $data[] = $GLOBALS['id'];
                $data[] = json_encode($entitiesId);
            }

352
353
354
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $queryParams['search'],
                'fields'        => $fields,
355
356
                'where'         => $where,
                'data'          => $data,
357
358
                'fieldsNumber'  => 1,
            ]);
359

360
361
362
363
364
            $contactsGroups = ContactGroupModel::get([
                'select'    => ['id', 'label'],
                'where'     => $requestData['where'],
                'data'      => $requestData['data'],
                'orderBy'   => ['label'],
365
                'limit'     => $limit
366
367
368
369
370
371
            ]);

            foreach ($contactsGroups as $value) {
                $autocompleteContactsGroups[] = [
                    'type'          => 'contactGroup',
                    'id'            => $value['id'],
372
373
                    'lastname'      => $value['label'],
                    'firstname'     => ''
374
375
376
377
378
                ];
            }
        }

        $total = count($autocompleteContacts) + count($autocompleteUsers) + count($autocompleteEntities) + count($autocompleteContactsGroups);
379
380
        if ($total > $limit) {
            $divider = $total / $limit;
381
382
383
            $autocompleteContacts       = array_slice($autocompleteContacts, 0, round(count($autocompleteContacts) / $divider));
            $autocompleteUsers          = array_slice($autocompleteUsers, 0, round(count($autocompleteUsers) / $divider));
            $autocompleteEntities       = array_slice($autocompleteEntities, 0, round(count($autocompleteEntities) / $divider));
384
            $autocompleteContactsGroups = array_slice($autocompleteContactsGroups, 0, round(count($autocompleteContactsGroups) / $divider));
385
        }
386
        $autocompleteData = array_merge($autocompleteContacts, $autocompleteUsers, $autocompleteEntities, $autocompleteContactsGroups);
387
388
389
390

        return $response->withJson($autocompleteData);
    }

391
392
    public static function getUsersForAdministration(Request $request, Response $response)
    {
Damien's avatar
Damien committed
393
394
395
396
397
398
        $data = $request->getQueryParams();
        $check = Validator::stringType()->notEmpty()->validate($data['search']);
        if (!$check) {
            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
        }

399
400
        if (!UserController::isRoot(['id' => $GLOBALS['id']])) {
            $entities = EntityModel::getAllEntitiesByUserId(['userId' => $GLOBALS['id']]);
Damien's avatar
Damien committed
401

402
            $fields = ['users.firstname', 'users.lastname'];
403
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
404

Damien's avatar
Damien committed
405
406
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $data['search'],
407
                'fields'        => $fields,
Damien's avatar
Damien committed
408
                'where'         => [
409
                    'users.id = users_entities.user_id',
Damien's avatar
Damien committed
410
                    'users_entities.entity_id in (?)',
411
                    'users.status not in (?)'
Damien's avatar
Damien committed
412
                ],
413
                'data'          => [$entities, ['DEL', 'SPD']],
Damien's avatar
Damien committed
414
415
416
417
                'fieldsNumber'  => 2,
            ]);

            $users = DatabaseModel::select([
Damien's avatar
Damien committed
418
                'select'    => ['DISTINCT users.user_id', 'users.id', 'users.firstname', 'users.lastname'],
Damien's avatar
Damien committed
419
420
                'table'     => ['users, users_entities'],
                'where'     => $requestData['where'],
Damien's avatar
Damien committed
421
422
                'data'      => $requestData['data'],
                'limit'     => self::LIMIT
Damien's avatar
Damien committed
423
424
            ]);

425
            if (count($users) < self::LIMIT) {
426
                $fields = ['users.firstname', 'users.lastname'];
427
                $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
428

Damien's avatar
Damien committed
429
430
                $requestData = AutoCompleteController::getDataForRequest([
                    'search'        => $data['search'],
431
                    'fields'        => $fields,
Damien's avatar
Damien committed
432
433
                    'where'         => [
                        'users_entities IS NULL',
434
                        'users.mode not in (?)',
435
                        'users.status not in (?)'
Damien's avatar
Damien committed
436
                    ],
437
                    'data'          => [['root_invisible'], ['DEL', 'SPD']],
Damien's avatar
Damien committed
438
439
440
441
442
443
                    'fieldsNumber'  => 2,
                ]);

                $usersNoEntities = DatabaseModel::select([
                    'select'    => ['users.id', 'users.user_id', 'users.firstname', 'users.lastname'],
                    'table'     => ['users', 'users_entities'],
444
                    'left_join' => ['users.id = users_entities.user_id'],
Damien's avatar
Damien committed
445
                    'where'     => $requestData['where'],
446
447
                    'data'      => $requestData['data'],
                    'limit'     => (self::LIMIT - count($users))
Damien's avatar
Damien committed
448
449
450
451
                ]);

                $users = array_merge($users, $usersNoEntities);
            }
452
        } else {
Damien's avatar
Damien committed
453
454
455
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $data['search'],
                'fields'        => '(firstname ilike ? OR lastname ilike ?)',
Damien's avatar
Damien committed
456
457
                'where'         => ['status not in (?)', 'mode not in (?)'],
                'data'          => [['DEL', 'SPD'], ['root_invisible']],
Damien's avatar
Damien committed
458
459
                'fieldsNumber'  => 2,
            ]);
460
461

            $users = UserModel::get([
Damien's avatar
Damien committed
462
                'select'    => ['id', 'user_id', 'firstname', 'lastname'],
Damien's avatar
Damien committed
463
464
                'where'     => $requestData['where'],
                'data'      => $requestData['data'],
Damien's avatar
Damien committed
465
466
                'orderBy'   => ['lastname'],
                'limit'     => self::LIMIT
467
468
469
470
            ]);
        }

        $data = [];
Florian Azizian's avatar
Florian Azizian committed
471
        foreach ($users as $value) {
472
473
            $data[] = [
                'type'          => 'user',
474
475
476
                'id'            => $value['id'],
                'idToDisplay'   => "{$value['firstname']} {$value['lastname']}",
                'otherInfo'     => $value['user_id']
477
478
479
480
481
482
            ];
        }

        return $response->withJson($data);
    }

483
    public static function getUsersForCircuit(Request $request, Response $response)
Damien's avatar
Damien committed
484
    {
485
486
487
488
489
        $queryParams = $request->getQueryParams();

        $services = ['visa_documents', 'sign_document'];
        if (!empty($queryParams['circuit']) && $queryParams['circuit'] == 'opinion') {
            $services = ['avis_documents'];
Damien's avatar
Damien committed
490
491
        }

492
493
494
495
496
497
498
        $allowedGroups = [0];
        $groups = PrivilegeModel::get(['select' => ['DISTINCT group_id'], 'where' => ['service_id in (?)'], 'data' => [$services]]);
        if (!empty($groups)) {
            $groups = array_column($groups, 'group_id');
            $groups = GroupModel::get(['select' => ['id'], 'where' => ['group_id in (?)'], 'data' => [$groups]]);
            $allowedGroups = array_column($groups, 'id');
        }
499
        $requestData['where'] = [
500
            '(users.mode = ? OR (usergroup_content.user_id = users.id AND usergroup_content.group_id in (?)))',
501
            'users.mode not in (?)',
502
503
            'users.status not in (?)'
        ];
504
        $requestData['data'] = ['root_visible', $allowedGroups, ['root_invisible', 'rest'], ['DEL', 'SPD']];
Damien's avatar
Damien committed
505

506
507
        if (!empty($queryParams['search'])) {
            $fields = ['users.firstname', 'users.lastname'];
508
            $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
509

510
511
512
513
514
515
516
517
            $requestData = AutoCompleteController::getDataForRequest([
                'search'        => $queryParams['search'],
                'fields'        => $fields,
                'where'         => $requestData['where'],
                'data'          => $requestData['data'],
                'fieldsNumber'  => 2,
            ]);
        }
Damien's avatar
Damien committed
518
519

        $users = DatabaseModel::select([
520
            'select'    => ['DISTINCT users.id', 'users.firstname', 'users.lastname'],
521
            'table'     => ['users, usergroup_content'],
Damien's avatar
Damien committed
522
523
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
524
            'order_by'  => ['users.lastname']
Damien's avatar
Damien committed
525
526
527
        ]);

        $data = [];
528
        foreach ($users as $value) {
529
            $entity = UserModel::getPrimaryEntityById(['id' => $value['id'], 'select' => ['entities.short_label']]);
Damien's avatar
Damien committed
530
531
            $data[] = [
                'type'          => 'user',
532
                'id'            => $value['id'],
Damien's avatar
Damien committed
533
                'idToDisplay'   => "{$value['firstname']} {$value['lastname']}",
534
                'otherInfo'     => $entity['short_label']
Damien's avatar
Damien committed
535
            ];
Damien's avatar
Damien committed
536
537
538
539
540
541
542
        }

        return $response->withJson($data);
    }

    public static function getEntities(Request $request, Response $response)
    {
543
544
        $queryParams = $request->getQueryParams();
        if (!Validator::stringType()->notEmpty()->validate($queryParams['search'])) {
Damien's avatar
Damien committed
545
546
547
            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
        }

548
        $fields = ['entity_label'];
549
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
550

Damien's avatar
Damien committed
551
        $requestData = AutoCompleteController::getDataForRequest([
552
            'search'        => $queryParams['search'],
553
            'fields'        => $fields,
Damien's avatar
Damien committed
554
555
556
557
558
            'where'         => ['enabled = ?'],
            'data'          => ['Y'],
            'fieldsNumber'  => 1,
        ]);

Damien's avatar
Damien committed
559
        $entities = EntityModel::get([
560
            'select'    => ['id', 'entity_id', 'entity_label', 'short_label'],
Damien's avatar
Damien committed
561
562
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
Damien's avatar
Damien committed
563
564
            'orderBy'   => ['entity_label'],
            'limit'     => self::LIMIT
Damien's avatar
Damien committed
565
566
567
        ]);

        $data = [];
Florian Azizian's avatar
Florian Azizian committed
568
        foreach ($entities as $value) {
Damien's avatar
Damien committed
569
570
            $data[] = [
                'type'          => 'entity',
571
                'id'            => empty($queryParams['serial']) ? $value['entity_id'] : $value['id'],
572
                'serialId'      => $value['id'],
Damien's avatar
Damien committed
573
574
575
576
577
578
579
580
581
582
                'idToDisplay'   => $value['entity_label'],
                'otherInfo'     => $value['short_label']
            ];
        }

        return $response->withJson($data);
    }

    public static function getStatuses(Request $request, Response $response)
    {
Damien's avatar
Damien committed
583
        $statuses = StatusModel::get(['select' => ['id', 'label_status', 'img_filename']]);
Damien's avatar
Damien committed
584
585

        $data = [];
Florian Azizian's avatar
Florian Azizian committed
586
        foreach ($statuses as $value) {
Damien's avatar
Damien committed
587
588
589
590
            $data[] = [
                'type'          => 'status',
                'id'            => $value['id'],
                'idToDisplay'   => $value['label_status'],
591
                'otherInfo'     => $value['img_filename']
Damien's avatar
Damien committed
592
593
594
595
596
            ];
        }

        return $response->withJson($data);
    }
Damien's avatar
Damien committed
597

598
    public static function getContacts(Request $request, Response $response)
599
600
601
602
603
604
605
606
    {
        $data = $request->getQueryParams();

        $check = Validator::stringType()->notEmpty()->validate($data['search']);
        if (!$check) {
            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
        }

607
608
609
610
611
612
613
614
615
        $searchableParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['searchable = ?'], 'data' => [true]]);

        $fields = [];
        foreach ($searchableParameters as $searchableParameter) {
            if (strpos($searchableParameter['identifier'], 'contactCustomField_') !== false) {
                $customFieldId = explode('_', $searchableParameter['identifier'])[1];
                $fields[] = "custom_fields->>'{$customFieldId}'";
            } else {
                $fields[] = ContactController::MAPPING_FIELDS[$searchableParameter['identifier']];
616
617
618
            }
        }

619
        $fieldsNumber = count($fields);
620
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
621
622
623
624
625
626
627
628
629

        $requestData = AutoCompleteController::getDataForRequest([
            'search'        => $data['search'],
            'fields'        => $fields,
            'where'         => ['enabled = ?'],
            'data'          => [true],
            'fieldsNumber'  => $fieldsNumber
        ]);

630
        $contacts = ContactModel::get([
631
632
633
634
            'select'    => ['id', 'firstname', 'lastname', 'company', 'address_number', 'address_street', 'address_town', 'address_postcode'],
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
            'orderBy'   => ['company', 'lastname NULLS FIRST'],
635
636
637
638
639
            'limit'     => 1000
        ]);

        $data = [];
        foreach ($contacts as $contact) {
640
            $data[] = ContactController::getFormattedContactWithAddress(['contact' => $contact])['contact'];
641
642
643
644
645
        }

        return $response->withJson($data);
    }

646
647
648
649
650
651
652
653
    public static function getContactsCompany(Request $request, Response $response)
    {
        $queryParams = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($queryParams['search'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Query params search is empty']);
        }

654
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => ['company']]);
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
        $contacts = ContactModel::get([
            'select'    => [
                'id', 'company', 'address_number as "addressNumber"', 'address_street as "addressStreet"',
                'address_additional1 as "addressAdditional1"', 'address_additional2 as "addressAdditional2"', 'address_postcode as "addressPostcode"',
                'address_town as "addressTown"', 'address_country as "addressCountry"'
            ],
            'where'     => ['enabled = ?', $fields],
            'data'      => [true, $queryParams['search'] . '%'],
            'orderBy'   => ['company', 'lastname'],
            'limit'     => 1
        ]);

        return $response->withJson($contacts);
    }

Damien's avatar
Damien committed
670
671
672
673
674
    public static function getBanAddresses(Request $request, Response $response)
    {
        $data = $request->getQueryParams();

        $check = Validator::stringType()->notEmpty()->validate($data['address']);
Damien's avatar
Damien committed
675
        $check = $check && Validator::stringType()->notEmpty()->validate($data['department']);
Damien's avatar
Damien committed
676
677
678
        if (!$check) {
            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
        }
679
680
681
682
683
684
685
        $customId = CoreConfigModel::getCustomId();

        if (is_dir("custom/{$customId}/referential/ban/indexes/{$data['department']}")) {
            $path = "custom/{$customId}/referential/ban/indexes/{$data['department']}";
        } elseif (is_dir('referential/ban/indexes/' . $data['department'])) {
            $path = 'referential/ban/indexes/' . $data['department'];
        } else {
Damien's avatar
Damien committed
686
687
            return $response->withStatus(400)->withJson(['errors' => 'Department indexes do not exist']);
        }
Damien's avatar
Damien committed
688
689
690
691
692

        \Zend_Search_Lucene_Analysis_Analyzer::setDefault(new \Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive());
        \Zend_Search_Lucene_Search_QueryParser::setDefaultOperator(\Zend_Search_Lucene_Search_QueryParser::B_AND);
        \Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');

693
        $index = \Zend_Search_Lucene::open($path);
Damien's avatar
Damien committed
694
695
696
697
698
        \Zend_Search_Lucene::setResultSetLimit(100);

        $data['address'] = str_replace(['*', '~', '-', '\''], ' ', $data['address']);
        $aAddress = explode(' ', $data['address']);
        foreach ($aAddress as $key => $value) {
699
            if (mb_strlen($value) <= 2 && !is_numeric($value)) {
Damien's avatar
Damien committed
700
701
702
                unset($aAddress[$key]);
                continue;
            }
703
            if (mb_strlen($value) >= 3 && $value != 'rue' && $value != 'avenue' && $value != 'boulevard') {
Damien's avatar
Damien committed
704
705
706
707
                $aAddress[$key] .= '*';
            }
        }
        $data['address'] = implode(' ', $aAddress);
708
709
710
        if (empty($data['address'])) {
            return $response->withJson([]);
        }
Damien's avatar
Damien committed
711
712

        $hits = $index->find(TextFormatModel::normalize(['string' => $data['address']]));
Damien's avatar
Damien committed
713

Damien's avatar
Damien committed
714
        $addresses = [];
Florian Azizian's avatar
Florian Azizian committed
715
        foreach ($hits as $key => $hit) {
Damien's avatar
Damien committed
716
            $addresses[] = [
Damien's avatar
Damien committed
717
                'banId'         => $hit->banId,
718
719
                'lon'           => $hit->lon,
                'lat'           => $hit->lat,
Damien's avatar
Damien committed
720
721
722
                'number'        => $hit->streetNumber,
                'afnorName'     => $hit->afnorName,
                'postalCode'    => $hit->postalCode,
Damien's avatar
Damien committed
723
724
                'city'          => $hit->city,
                'address'       => "{$hit->streetNumber} {$hit->afnorName}, {$hit->city} ({$hit->postalCode})"
Damien's avatar
Damien committed
725
726
727
            ];
        }

Damien's avatar
Damien committed
728
        return $response->withJson($addresses);
Damien's avatar
Damien committed
729
    }
Damien's avatar
Damien committed
730

731
732
733
734
    public static function getOuM2MAnnuary(Request $request, Response $response)
    {
        $data = $request->getQueryParams();

735
        $check = Validator::stringType()->notEmpty()->validate($data['company']);
736
        if (!$check) {
737
            return $response->withStatus(400)->withJson(['errors' => 'Query company is empty']);
738
739
740
741
742
743
        }

        $control = AnnuaryController::getAnnuaries();
        if (!isset($control['annuaries'])) {
            if (isset($control['errors'])) {
                return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
744
            } elseif (isset($control['success'])) {
745
                return $response->withJson([]);
746
747
748
749
750
751
752
753
754
755
756
757
758
759
            }
        }

        $unitOrganizations = [];
        if (!empty($control['annuaries'])) {
            foreach ($control['annuaries'] as $annuary) {
                $ldap = @ldap_connect($annuary['uri']);
                if ($ldap === false) {
                    continue;
                }
                ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
                ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
                ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, 5);
    
760
                $search = @ldap_search($ldap, $annuary['baseDN'], "(ou=*{$data['company']}*)", ['ou', 'postOfficeBox', 'destinationIndicator', 'labeledURI']);
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
                if ($search === false) {
                    continue;
                }
                $entries = ldap_get_entries($ldap, $search);
    
                foreach ($entries as $key => $value) {
                    if (!is_numeric($key)) {
                        continue;
                    }
                    if (!empty($value['postofficebox'])) {
                        $unitOrganizations[] = [
                            'communicationValue' => $value['postofficebox'][0],
                            'businessIdValue'    => $value['destinationindicator'][0],
                            'unitOrganization'   => "{$value['ou'][0]} ({$value['postofficebox'][0]})"
                        ];
                    }
                    if (!empty($value['labeleduri'])) {
                        $unitOrganizations[] = [
                            'communicationValue' => $value['labeleduri'][0],
                            'businessIdValue'    => $value['destinationindicator'][0],
                            'unitOrganization'   => "{$value['ou'][0]} ({$value['labeleduri'][0]})"
                        ];
                    }
                }
    
                break;
            }
        }
        
        return $response->withJson($unitOrganizations);
    }

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
    public static function getAvailableContactsForM2M(Request $request, Response $response)
    {
        $queryParams = $request->getQueryParams();
        if (!Validator::stringType()->notEmpty()->validate($queryParams['search'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Query params search is empty']);
        }

        $autocompleteData = [];
        $searchableParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['searchable = ?'], 'data' => [true]]);

        $fields = [];
        foreach ($searchableParameters as $searchableParameter) {
            if (strpos($searchableParameter['identifier'], 'contactCustomField_') !== false) {
                $customFieldId = explode('_', $searchableParameter['identifier'])[1];
                $fields[] = "custom_fields->>'{$customFieldId}'";
            } else {
                $fields[] = ContactController::MAPPING_FIELDS[$searchableParameter['identifier']];
            }
        }

        $fieldsNumber = count($fields);
814
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
815
816
817
818

        $requestData = AutoCompleteController::getDataForRequest([
            'search'        => $queryParams['search'],
            'fields'        => $fields,
819
            'where'         => ['enabled = ?', "external_id->>'m2m' is not null", "external_id->>'m2m' != ''", "(communication_means->>'url' is not null OR communication_means->>'email' is not null)"],
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
            'data'          => [true],
            'fieldsNumber'  => $fieldsNumber
        ]);

        $contacts = ContactModel::get([
            'select'    => ['id', 'communication_means', 'external_id'],
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
            'orderBy'   => ['company', 'lastname NULLS FIRST'],
            'limit'     => self::TINY_LIMIT
        ]);

        foreach ($contacts as $contact) {
            $autoContact = ContactController::getAutocompleteFormat(['id' => $contact['id']]);

            $externalId = json_decode($contact['external_id'], true);
            $communicationMeans = json_decode($contact['communication_means'], true);
            $autoContact['m2m'] = $externalId['m2m'];
            $autoContact['communicationMeans'] = $communicationMeans['url'] ?? $communicationMeans['email'];
            $autocompleteData[] = $autoContact;
        }

        return $response->withJson($autocompleteData);
    }

845
846
847
848
849
850
851
852
853
854
855
856
857
    public static function getBusinessIdM2MAnnuary(Request $request, Response $response)
    {
        $data = $request->getQueryParams();

        $check = Validator::stringType()->notEmpty()->validate($data['communicationValue']);
        if (!$check) {
            return $response->withStatus(400)->withJson(['errors' => 'Query communicationValue is empty']);
        }

        $control = AnnuaryController::getAnnuaries();
        if (!isset($control['annuaries'])) {
            if (isset($control['errors'])) {
                return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
858
            } elseif (isset($control['success'])) {
859
                return $response->withJson([]);
860
861
862
            }
        }

863
        $unitOrganizations = [];
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
        foreach ($control['annuaries'] as $annuary) {
            $ldap = @ldap_connect($annuary['uri']);
            if ($ldap === false) {
                $error = 'Ldap connect failed : uri is maybe wrong';
                continue;
            }
            ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
            ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
            ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, 5);

            if (filter_var($data['communicationValue'], FILTER_VALIDATE_EMAIL)) {
                $search = @ldap_search($ldap, $annuary['baseDN'], "(postofficebox={$data['communicationValue']})", ['destinationIndicator']);
            } else {
                $search = @ldap_search($ldap, $annuary['baseDN'], "(labeleduri={$data['communicationValue']})", ['destinationIndicator']);
            }
            if ($search === false) {
                $error = 'Ldap search failed : baseDN is maybe wrong => ' . ldap_error($ldap);
                continue;
            }
            $entriesOu = ldap_get_entries($ldap, $search);
            foreach ($entriesOu as $keyOu => $valueOu) {
                if (!is_numeric($keyOu)) {
                    continue;
                }
                $siret   = $valueOu['destinationindicator'][0];
                $search  = @ldap_search($ldap, $valueOu['dn'], "(cn=*)", ['cn', 'initials', 'entryUUID']);
                $entries = ldap_get_entries($ldap, $search);

                foreach ($entries as $key => $value) {
                    if (!is_numeric($key)) {
                        continue;
                    }
                    $unitOrganizations[] = [
                        'entryuuid'        => $value['entryuuid'][0],
                        'businessIdValue'  => $siret . '/' . $value['initials'][0],
                        'unitOrganization' => "{$value['cn'][0]} - {$siret}/{$value['initials'][0]}"
                    ];
                }
            }

            return $response->withJson($unitOrganizations);
        }
    }

908
909
910
911
912
913
914
915
    public static function getFolders(Request $request, Response $response)
    {
        $data = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($data['search'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Query params search is empty']);
        }

916
        $scopedFolders = FolderController::getScopeFolders(['login' => $GLOBALS['login']]);
917
918
919
        if (empty($scopedFolders)) {
            return $response->withJson([]);
        }
920
921
922

        $arrScopedFoldersIds = array_column($scopedFolders, 'id');

923
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => ['label']]);
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952

        $selectedFolders = FolderModel::get([
            'where'    => ["{$fields} AND id in (?)"],
            'data'     => [ '%'.$data['search'].'%', $arrScopedFoldersIds],
            'orderBy'  => ['label']
        ]);

        $data = [];
        foreach ($selectedFolders as $value) {
            $data[] = [
                'id'            => $value['id'],
                'idToDisplay'   => $value['label'],
                'isPublic'      => $value['public'],
                'otherInfo'     => ''
            ];
        }

        return $response->withJson($data);
    }

    public static function getTags(Request $request, Response $response)
    {
        $data = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($data['search'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Query params search is empty']);
        }

        $fields = ['label'];
953
        $fields = AutoCompleteController::getInsensitiveFieldsForRequest(['fields' => $fields]);
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981

        $requestData = AutoCompleteController::getDataForRequest([
            'search'        => $data['search'],
            'fields'        => $fields,
            'where'         => ['1 = ?'],
            'data'          => ['1'],
            'fieldsNumber'  => 1,
        ]);

        $tags = TagModel::get([
            'select'    => ['id', 'label'],
            'where'     => $requestData['where'],
            'data'      => $requestData['data'],
            'orderBy'   => ['label'],
            'limit'     => self::LIMIT
        ]);

        $data = [];
        foreach ($tags as $value) {
            $data[] = [
                'id'            => $value['id'],
                'idToDisplay'   => $value['label']
            ];
        }

        return $response->withJson($data);
    }

982
    public static function getDataForRequest(array $args)
Damien's avatar
Damien committed
983
    {
984
985
986
987
        ValidatorModel::notEmpty($args, ['search', 'fields', 'fieldsNumber']);
        ValidatorModel::stringType($args, ['search', 'fields']);
        ValidatorModel::arrayType($args, ['where', 'data']);
        ValidatorModel::intType($args, ['fieldsNumber']);
Damien's avatar
Damien committed
988

989
        $searchItems = explode(' ', $args['search']);
Damien's avatar
Damien committed
990

991
        foreach ($searchItems as $keyItem => $item) {
Damien's avatar
Damien committed
992
            if (strlen($item) >= 2) {
993
                $args['where'][] = $args['fields'];
994
995
996
997
998
999
1000

                $isIncluded = false;
                foreach ($searchItems as $key => $value) {
                    if ($keyItem == $key) {
                        continue;
                    }
                    if (strpos($value, $item) === 0) {
For faster browsing, not all history is shown. View entire blame