Passed
Pull Request — master (#16)
by Nikolay
13:10 queued 02:12
created

ExtensionsController::saveSip()   C

Complexity

Conditions 17
Paths 36

Size

Total Lines 52
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 40
dl 0
loc 52
rs 5.2166
c 0
b 0
f 0
cc 17
nc 36
nop 2

How to fix   Long Method    Complexity   

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:

1
<?php
2
/*
3
 * Copyright © MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Alexey Portnov, 8 2020
7
 */
8
9
namespace MikoPBX\AdminCabinet\Controllers;
10
11
use MikoPBX\AdminCabinet\Forms\ExtensionEditForm;
12
use MikoPBX\Common\Models\{
13
    ExtensionForwardingRights,
14
    Extensions,
15
    ExternalPhones,
16
    NetworkFilters,
17
    PbxExtensionModules,
18
    PbxSettings,
19
    Sip,
20
    Users
21
};
22
use Phalcon\Text;
23
24
use function MikoPBX\Common\Config\appPath;
25
26
class ExtensionsController extends BaseController
27
{
28
29
    /**
30
     * Построение списка внутренних номеров и сотрудников
31
     */
32
    public function indexAction(): void
33
    {
34
        $extensionTable = [];
35
36
        $parameters = [
37
            'models'     => [
38
                'Extensions' => Extensions::class,
39
            ],
40
            'conditions' => 'Extensions.is_general_user_number = "1"',
41
            'columns'    => [
42
                'id'       => 'Extensions.id',
43
                'username' => 'Users.username',
44
                'number'   => 'Extensions.number',
45
                'userid'   => 'Extensions.userid',
46
                'disabled' => 'Sip.disabled',
47
                'secret'   => 'Sip.secret',
48
                'email'    => 'Users.email',
49
                'type'     => 'Extensions.type',
50
                'avatar'   => 'Users.avatar',
51
52
            ],
53
            'order'      => 'number',
54
            'joins'      => [
55
                'Sip'   => [
56
                    0 => Sip::class,
57
                    1 => 'Sip.extension=Extensions.number',
58
                    2 => 'Sip',
59
                    3 => 'LEFT',
60
                ],
61
                'Users' => [
62
                    0 => Users::class,
63
                    1 => 'Users.id = Extensions.userid',
64
                    2 => 'Users',
65
                    3 => 'INNER',
66
                ],
67
            ],
68
        ];
69
        $query      = $this->di->get('modelsManager')->createBuilder($parameters)->getQuery();
70
        $extensions = $query->execute();
71
72
        foreach ($extensions as $extension) {
73
            switch ($extension->type) {
74
                case Extensions::TYPE_SIP:
75
                    $extensionTable[$extension->userid]['userid']   = $extension->userid;
76
                    $extensionTable[$extension->userid]['number']   = $extension->number;
77
                    $extensionTable[$extension->userid]['status']   = ($extension->disabled === '1') ? 'disabled' : '';
78
                    $extensionTable[$extension->userid]['id']       = $extension->id;
79
                    $extensionTable[$extension->userid]['username'] = $extension->username;
80
                    $extensionTable[$extension->userid]['email']    = $extension->email;
81
                    $extensionTable[$extension->userid]['secret']   = $extension->secret;
82
83
                    if ( ! array_key_exists('mobile', $extensionTable[$extension->userid])) {
84
                        $extensionTable[$extension->userid]['mobile'] = '';
85
                    }
86
                    if ($extension->avatar) {
87
                        $filename    = md5($extension->avatar);
88
                        $imgCacheDir = appPath('sites/admin-cabinet/assets/img/cache');
89
                        $imgFile     = "{$imgCacheDir}/$filename.jpg";
90
                        if ( ! file_exists($imgFile)) {
91
                            $this->base64ToJpeg($extension->avatar, $imgFile);
92
                        }
93
94
                        $extensionTable[$extension->userid]['avatar'] = "{$this->url->get()}assets/img/cache/{$filename}.jpg";
95
                    } else {
96
                        $extensionTable[$extension->userid]['avatar'] = "{$this->url->get()}assets/img/unknownPerson.jpg";
97
                    }
98
99
                    break;
100
                case Extensions::TYPE_EXTERNAL:
101
                    $extensionTable[$extension->userid]['mobile'] = $extension->number;
102
                    break;
103
                default:
104
            }
105
        }
106
        $this->view->extensions = $extensionTable;
107
    }
108
109
    /**
110
     * Создает файл jpeg из переданной картинки
111
     *
112
     * @param $base64_string
113
     * @param $output_file
114
     *
115
     * @return void
116
     */
117
    private function base64ToJpeg($base64_string, $output_file): void
118
    {
119
        // open the output file for writing
120
        $ifp = fopen($output_file, 'wb');
121
122
        if ($ifp === false) {
123
            return;
124
        }
125
        // split the string on commas
126
        // $data[ 0 ] == "data:image/png;base64"
127
        // $data[ 1 ] == <actual base64 string>
128
        $data = explode(',', $base64_string);
129
130
        // we could add validation here with ensuring count( $data ) > 1
131
        fwrite($ifp, base64_decode($data[1]));
132
133
        // clean up the file resource
134
        fclose($ifp);
135
    }
136
137
    /**
138
     * Change extension settings
139
     *
140
     * @param ?string $id modified extension id
141
     */
142
    public function modifyAction($id = null): void
143
    {
144
        $extension = Extensions::findFirstById($id);
145
146
        if ($extension === null) {
147
            $extension                         = new Extensions();
148
            $extension->show_in_phonebook      = '1';
149
            $extension->public_access          = '0';
150
            $extension->is_general_user_number = '1';
151
            $extension->type                   = Extensions::TYPE_SIP;
152
            $extension->Sip                    = new Sip();
153
            $extension->Sip->disabled          = 0;
154
            $extension->Sip->type              = 'peer';
155
            $extension->Sip->uniqid            = Extensions::TYPE_SIP.strtoupper('-PHONE-' . md5(time()));
156
            $extension->Sip->busylevel         = 1;
157
            $extension->Sip->qualify           = '1';
158
            $extension->Sip->qualifyfreq       = 60;
159
            $extension->number                 = $this->getNextInternalNumber();
160
161
            $extension->Users       = new Users();
162
            $extension->Users->role = 'user';
163
164
            $extension->ExtensionForwardingRights = new ExtensionForwardingRights();
165
166
            $this->view->avatar = '';
167
        } else {
168
            $this->view->avatar = $extension->Users->avatar;
169
        }
170
        $arrNetworkFilters         = [];
171
        $networkFilters            = NetworkFilters::getAllowedFiltersForType(['SIP']);
172
        $arrNetworkFilters['none'] = $this->translation->_('ex_NoNetworkFilter');
173
        foreach ($networkFilters as $filter) {
174
            $arrNetworkFilters[$filter->id] = $filter->getRepresent();
175
        }
176
177
        $parameters        = [
178
            'conditions' => 'type = "'.Extensions::TYPE_EXTERNAL.'" AND is_general_user_number = "1" AND userid=:userid:',
179
            'bind'       => [
180
                'userid' => $extension->userid,
181
            ],
182
        ];
183
        $externalExtension = Extensions::findFirst($parameters);
184
        if ($externalExtension === null) {
185
            $externalExtension                           = new Extensions();
186
            $externalExtension->userid                   = $extension->userid;
187
            $externalExtension->type                     = Extensions::TYPE_EXTERNAL;
188
            $externalExtension->is_general_user_number   = '1';
189
            $externalExtension->ExternalPhones           = new ExternalPhones();
190
            $externalExtension->ExternalPhones->uniqid   = Extensions::TYPE_EXTERNAL.strtoupper('-' . md5(time()));
191
            $externalExtension->ExternalPhones->disabled = '0';
192
        }
193
194
        $forwardingExtensions  = [];
195
        $forwardingExtensions[''] = $this->translation->_('ex_SelectNumber');
196
197
        $parameters = [
198
            'conditions' => 'number IN ({ids:array})',
199
            'bind'       => [
200
                'ids' => [
201
                    $extension->ExtensionForwardingRights->forwarding,
202
                    $extension->ExtensionForwardingRights->forwardingonbusy,
203
                    $extension->ExtensionForwardingRights->forwardingonunavailable,
204
                ],
205
            ],
206
        ];
207
        $extensions = Extensions::find($parameters);
208
        foreach ($extensions as $record) {
209
            $forwardingExtensions[$record->number] = $record->getRepresent();
210
        }
211
212
        // Ограничим длинну внутреннего номера согласно настройкам
213
        $extensionsLength      = PbxSettings::getValueByKey('PBXInternalExtensionLength');
214
        $internalExtensionMask = "9{3,{$extensionsLength}}";
215
216
        $form = new ExtensionEditForm(
217
            $extension, [
218
                          'network_filters'        => $arrNetworkFilters,
219
                          'external_extension'     => $externalExtension,
220
                          'forwarding_extensions'  => $forwardingExtensions,
221
                          'internalextension_mask' => $internalExtensionMask,
222
                      ]
223
        );
224
225
        $this->view->form      = $form;
226
        $this->view->represent = $extension->getRepresent();
227
    }
228
229
    /**
230
     * Получает из базы следующий за последним введенным внутренним номером
231
     */
232
    private function getNextInternalNumber()
233
    {
234
        $parameters = [
235
            'conditions' => 'type = "'.Extensions::TYPE_SIP.'"',
236
            'column'     => 'number',
237
        ];
238
        $query      = Extensions::maximum($parameters);
239
        if ($query === null) {
240
            $query = 200;
241
        }
242
        $result       = (int)$query + 1;
243
        $extensionsLength = PbxSettings::getValueByKey('PBXInternalExtensionLength');
244
        $maxExtension = (10 ** $extensionsLength) - 1;
245
246
        return ($result <= $maxExtension) ? $result : '';
247
    }
248
249
    /**
250
     * Сохранение карточки пользователя с его номерами
251
     *
252
     * @return void параметры помещаются в view и обрабатваются через ControllerBase::afterExecuteRoute()
253
     */
254
    public function saveAction(): void
255
    {
256
        if ( ! $this->request->isPost()) {
257
            return;
258
        }
259
260
        $this->db->begin();
261
262
        $data = $this->request->getPost();
263
264
        $sipEntity = null;
265
266
        if (array_key_exists('sip_uniqid', $data)) {
267
            $sipEntity = SIP::findFirstByUniqid($data['sip_uniqid']);
268
        }
269
270
        if ($sipEntity === null) {
271
            $sipEntity             = new SIP();
272
            $extension             = new Extensions();
273
            $userEntity            = new Users();
274
            $fwdEntity             = new ExtensionForwardingRights();
275
            $fwdEntity->ringlength = 45;
276
        } else {
277
            $extension = $sipEntity->Extensions;
278
            if ( ! $extension) {
279
                $extension = new Extensions();
280
            }
281
            $userEntity = $extension->Users;
282
            if ( ! $userEntity) {
283
                $userEntity = new Users();
284
            }
285
            $fwdEntity = $extension->ExtensionForwardingRights;
286
            if ( ! $fwdEntity) {
287
                $fwdEntity = new ExtensionForwardingRights();
288
            }
289
        }
290
291
        // Заполним параметры пользователя
292
        if ( ! $this->saveUser($userEntity, $data)) {
293
            $this->view->success = false;
294
            $this->db->rollback();
295
296
            return;
297
        }
298
299
        // Заполним параметры внутреннего номера
300
        if ( ! $this->saveExtension($extension, $userEntity, $data, false)) {
301
            $this->view->success = false;
302
            $this->db->rollback();
303
304
            return;
305
        }
306
307
        // Заполним параметры SIP учетки
308
        if ( ! $this->saveSip($sipEntity, $data)) {
309
            $this->view->success = false;
310
            $this->db->rollback();
311
312
            return;
313
        }
314
315
316
        // Заполним параметры маршрутизации
317
        if ( ! $this->saveForwardingRights($fwdEntity, $data)) {
318
            $this->view->success = false;
319
            $this->db->rollback();
320
321
            return;
322
        }
323
324
        // Если мобильный не указан, то не будем его добавлять в базу
325
        if ( ! empty($data['mobile_number'])) {
326
            $externalPhone = ExternalPhones::findFirstByUniqid($data['mobile_uniqid']);
327
            if ($externalPhone === null) {
328
                $externalPhone   = new ExternalPhones();
329
                $mobileExtension = new Extensions();
330
            } else {
331
                $mobileExtension = $externalPhone->Extensions;
332
            }
333
334
            // Заполним параметры Extension для мобильного
335
            if ( ! $this->saveExtension($mobileExtension, $userEntity, $data, true)) {
336
                $this->view->success = false;
337
                $this->db->rollback();
338
339
                return;
340
            }
341
342
            // Заполним параметры ExternalPhones для мобильного
343
            if ( ! $this->saveExternalPhones($externalPhone, $data)) {
344
                $this->view->success = false;
345
                $this->db->rollback();
346
347
                return;
348
            }
349
        } else {
350
            // Удалить номер мобильного если он был привязан к пользователю
351
            $parameters          = [
352
                'conditions' => 'type="'.Extensions::TYPE_EXTERNAL.'" AND is_general_user_number = "1" AND userid=:userid:',
353
                'bind'       => [
354
                    'userid' => $userEntity->id,
355
                ],
356
            ];
357
            $deletedMobileNumber = Extensions::findFirst($parameters);
358
            if ($deletedMobileNumber !== null
359
                && $deletedMobileNumber->delete() === false) {
360
                $errors = $deletedMobileNumber->getMessages();
361
                $this->flash->error(implode('<br>', $errors));
362
                $this->view->success = false;
363
                $this->db->rollback();
364
365
                return;
366
            }
367
        }
368
369
        $this->flash->success($this->translation->_('ms_SuccessfulSaved'));
370
        $this->view->success = true;
371
        $this->db->commit();
372
373
        // Если это было создание карточки то надо перегрузить страницу с указанием ID
374
        if (empty($data['id'])) {
375
            $this->view->reload = "extensions/modify/{$extension->id}";
376
        }
377
    }
378
379
    /**
380
     * Сохранение параметров в таблицу Users
381
     *
382
     * @param Users $userEntity
383
     * @param array $data - POST дата
384
     *
385
     * @return bool результат сохранения
386
     */
387
    private function saveUser(Users $userEntity, array $data)
388
    {
389
        // Заполним параметры пользователя
390
        foreach ($userEntity as $name => $value) {
391
            switch ($name) {
392
                case 'role':
393
                    if (array_key_exists('user_' . $name, $data)) {
394
                        $userEntity->$name = ($userEntity->$name === 'user') ? 'user' : $data['user_' . $name]; // не повышаем роль
395
                    }
396
                    break;
397
                default:
398
                    if (array_key_exists('user_' . $name, $data)) {
399
                        $userEntity->$name = $data['user_' . $name];
400
                    }
401
            }
402
        }
403
404
        if ($userEntity->save() === false) {
405
            $errors = $userEntity->getMessages();
406
            $this->flash->error(implode('<br>', $errors));
407
408
            return false;
409
        }
410
411
        return true;
412
    }
413
414
    /**
415
     * Сохранение параметров в таблицу Extensions
416
     *
417
     * @param Extensions $extension
418
     * @param Users      $userEntity
419
     * @param array      $data - POST дата
420
     * @param bool isMobile - это мобильный телефон
421
     *
422
     * @return bool результат сохранения
423
     */
424
    private function saveExtension(Extensions $extension, Users $userEntity, array $data, $isMobile = false): bool
425
    {
426
        foreach ($extension as $name => $value) {
427
            switch ($name) {
428
                case 'id':
429
                    break;
430
                case 'show_in_phonebook':
431
                case 'is_general_user_number':
432
                    $extension->$name = '1';
433
                    break;
434
                case 'type':
435
                    $extension->$name = $isMobile ? Extensions::TYPE_EXTERNAL : Extensions::TYPE_SIP;
436
                    break;
437
                case 'public_access':
438
                    if (array_key_exists($name, $data)) {
439
                        $extension->$name = ($data[$name] === 'on') ? '1' : '0';
440
                    } else {
441
                        $extension->$name = '0';
442
                    }
443
                    break;
444
                case 'callerid':
445
                    $extension->$name = $this->sanitizeCallerId($data['user_username']);
446
                    break;
447
                case 'userid':
448
                    $extension->$name = $userEntity->id;
449
                    break;
450
                case 'number':
451
                    $extension->$name = $isMobile ? $data['mobile_number'] : $data['number'];
452
                    break;
453
                default:
454
                    if (array_key_exists($name, $data)) {
455
                        $extension->$name = $data[$name];
456
                    }
457
            }
458
        }
459
460
        if ($extension->save() === false) {
461
            $errors = $extension->getMessages();
462
            $this->flash->error(implode('<br>', $errors));
463
464
            return false;
465
        }
466
467
        return true;
468
    }
469
470
    /**
471
     * Сохранение параметров в таблицу SIP
472
     *
473
     * @param Sip   $sipEntity
474
     * @param array $data - POST дата
475
     *
476
     * @return bool результат сохранения
477
     */
478
    private function saveSip(Sip $sipEntity, array $data): bool
479
    {
480
        foreach ($sipEntity as $name => $value) {
481
            switch ($name) {
482
                case 'qualify':
483
                    if (array_key_exists($name, $data)) {
484
                        $sipEntity->$name = ($data[$name] === 'on') ? '1' : '0';
485
                    } else {
486
                        $sipEntity->$name = "0";
487
                    }
488
                    break;
489
                case 'disabled':
490
                case 'disablefromuser':
491
                    if (array_key_exists('sip_' . $name, $data)) {
492
                        $sipEntity->$name = ($data['sip_' . $name] === 'on') ? '1' : '0';
493
                    } else {
494
                        $sipEntity->$name = "0";
495
                    }
496
                    break;
497
                case 'networkfilterid':
498
                    if ( ! array_key_exists('sip_' . $name, $data)) {
499
                        continue 2;
500
                    }
501
                    if ($data['sip_' . $name] === 'none') {
502
                        $sipEntity->$name = null;
503
                    } else {
504
                        $sipEntity->$name = $data['sip_' . $name];
505
                    }
506
                    break;
507
                case 'extension':
508
                    $sipEntity->$name = $data['number'];
509
                    break;
510
                case 'description':
511
                    $sipEntity->$name = $data['user_username'];
512
                    break;
513
                case 'manualattributes':
514
                    $sipEntity->setManualAttributes($data['sip_manualattributes']);
515
                    break;
516
                default:
517
                    if (array_key_exists('sip_' . $name, $data)) {
518
                        $sipEntity->$name = $data['sip_' . $name];
519
                    }
520
            }
521
        }
522
        if ($sipEntity->save() === false) {
523
            $errors = $sipEntity->getMessages();
524
            $this->flash->error(implode('<br>', $errors));
525
526
            return false;
527
        }
528
529
        return true;
530
    }
531
532
    /**
533
     * Заполним параметры переадресации
534
     *
535
     * @param \MikoPBX\Common\Models\ExtensionForwardingRights $forwardingRight
536
     * @param                                                  $data
537
     *
538
     * @return bool
539
     */
540
    private function saveForwardingRights(ExtensionForwardingRights $forwardingRight, $data): bool
541
    {
542
        foreach ($forwardingRight as $name => $value) {
543
            switch ($name) {
544
                case 'extension':
545
                    $forwardingRight->$name = $data['number'];
546
                    break;
547
                default:
548
                    if (array_key_exists('fwd_' . $name, $data)) {
549
                        $forwardingRight->$name = ($data['fwd_' . $name] === -1) ? '' : $data['fwd_' . $name];
550
                    }
551
            }
552
        }
553
        if (empty($forwardingRight->forwarding)) {
554
            $forwardingRight->ringlength = null;
555
        }
556
557
        if ($forwardingRight->save() === false) {
558
            $errors = $forwardingRight->getMessages();
559
            $this->flash->error(implode('<br>', $errors));
560
561
            return false;
562
        }
563
564
        return true;
565
    }
566
567
    /**
568
     * Заполним параметры ExternalPhones для мобильного номера
569
     *
570
     * @param ExternalPhones $externalPhone
571
     * @param array          $data - POST дата
572
     *
573
     * @return bool результат сохранения
574
     */
575
    private function saveExternalPhones(ExternalPhones $externalPhone, array $data): bool
576
    {
577
        foreach ($externalPhone as $name => $value) {
578
            switch ($name) {
579
                case 'extension':
580
                    $externalPhone->$name = $data['mobile_number'];
581
                    break;
582
                case 'description':
583
                    $externalPhone->$name = $data['user_username'];
584
                    break;
585
                case 'disabled':
586
                    if (array_key_exists('mobile_' . $name, $data)) {
587
                        $externalPhone->$name = ($data['mobile_' . $name] === 'on') ? '1' : '0';
588
                    } else {
589
                        $externalPhone->$name = '0';
590
                    }
591
                    break;
592
                default:
593
                    if (array_key_exists('mobile_' . $name, $data)) {
594
                        $externalPhone->$name = $data['mobile_' . $name];
595
                    }
596
            }
597
        }
598
        if ($externalPhone->save() === false) {
599
            $errors = $externalPhone->getMessages();
600
            $this->flash->error(implode('<br>', $errors));
601
602
            return false;
603
        }
604
605
        return true;
606
    }
607
608
    /**
609
     * Удаление внутреннего номера и всех зависимых от него записей в том числе мобильного и переадресаций
610
     *
611
     * @param string $id - записи внутренненго номера
612
     */
613
    public function deleteAction($id = '')
614
    {
615
        $this->db->begin();
616
        $extension = Extensions::findFirstById($id);
617
618
        // Чтобы не было зацикливания при удалении сначала удалим
619
        // настройки переадресации у этой же учетной записи, т.к. она может ссылаться на себя
620
621
        $errors = null;
622
        if ($extension !== null && $extension->ExtensionForwardingRights
623
            && ! $extension->ExtensionForwardingRights->delete()) {
624
            $errors = $extension->ExtensionForwardingRights->getMessages();
625
        }
626
627
        if ( ! $errors && $extension) {
628
            $user = $extension->Users;
629
            if ( ! $user->delete()) {
630
                $errors = $user->getMessages();
631
            }
632
        }
633
634
        if ($errors) {
635
            $this->flash->error(implode('<br>', $errors));
636
            $this->db->rollback();
637
        } else {
638
            $this->db->commit();
639
        }
640
641
        $this->forward('extensions/index');
642
    }
643
644
    /**
645
     * Проверка на доступность номера JS скрипта extensions.js
646
     *
647
     * @param string $number - внутренний номер пользователя
648
     *
649
     * @return void параметры помещаются в view и обрабатваются через ControllerBase::afterExecuteRoute()
650
     */
651
    public function availableAction($number = ''): void
652
    {
653
        $result = true;
654
        // Проверим пересечение с внутренним номерным планом
655
        $extension = Extensions::findFirstByNumber($number);
656
        if ($extension !== null) {
657
            $result             = false;
658
            $this->view->userId = $extension->userid;
659
        }
660
        // Проверим пересечение с парковочными слотами
661
        if ($result) {
662
            $parkExt       = PbxSettings::getValueByKey('PBXCallParkingExt');
663
            $parkStartSlot = PbxSettings::getValueByKey('PBXCallParkingStartSlot');
664
            $parkEndSlot   = PbxSettings::getValueByKey('PBXCallParkingEndSlot');
665
            if ($number === $parkExt || ($number >= $parkStartSlot && $number <= $parkEndSlot)) {
666
                $result             = false;
667
                $this->view->userId = 0;
668
            }
669
        }
670
671
        $this->view->numberAvailable = $result;
672
    }
673
674
    /**
675
     * Отключение всех номеров пользователя
676
     *
677
     * @param string $number - внутренний номер пользователя
678
     *
679
     * @return void
680
     */
681
    public function disableAction($number = ''): void
682
    {
683
        $extension = Extensions::findFirstByNumber($number);
684
        if ($extension !== null) {
685
            $extensions = Extensions::findByUserid($extension->userid);
686
            foreach ($extensions as $extension) {
687
                switch ($extension->type) {
688
                    case Extensions::TYPE_SIP:
689
                        $extension->Sip->disabled = '1';
690
                        break;
691
                    case Extensions::TYPE_EXTERNAL:
692
                        $extension->ExternalPhones->disabled = '1';
693
                        break;
694
                }
695
                if ($extension->save() === true) {
696
                    $this->view->success = true;
697
                } else {
698
                    $this->view->success = false;
699
                    $errors              = $extension->getMessages();
700
                    $this->flash->error(implode('<br>', $errors));
701
702
                    return;
703
                }
704
            }
705
        }
706
    }
707
708
    /**
709
     * Включение всех номеров пользователя
710
     *
711
     * @param string $number - внутренний номер пользователя
712
     *
713
     * @return void
714
     */
715
    public function enableAction($number = ''): void
716
    {
717
        $extension = Extensions::findFirstByNumber($number);
718
        if ($extension !== null) {
719
            $extensions = Extensions::findByUserid($extension->userid);
720
            foreach ($extensions as $extension) {
721
                switch ($extension->type) {
722
                    case Extensions::TYPE_SIP:
723
                        $extension->Sip->disabled = '0';
724
                        break;
725
                    case Extensions::TYPE_EXTERNAL:
726
                        $extension->ExternalPhones->disabled = '1';
727
                        break;
728
                }
729
                if ($extension->save() === true) {
730
                    $this->view->success = true;
731
                } else {
732
                    $this->view->success = false;
733
                    $errors              = $extension->getMessages();
734
                    $this->flash->error(implode('<br>', $errors));
735
736
                    return;
737
                }
738
            }
739
        }
740
    }
741
742
    /**
743
     * Возвращает представление для списка нормеров телефонов по AJAX запросу
744
     *
745
     * @return void
746
     */
747
    public function GetPhonesRepresentAction(): void
748
    {
749
        if ( ! $this->request->isPost()) {
750
            return;
751
        }
752
        $numbers = $this->request->getPost('numbers');
753
        $result  = [];
754
        foreach ($numbers as $number) {
755
            $result[$number] = [
756
                'number'    => $number,
757
                'represent' => $this->GetPhoneRepresentAction($number),
758
            ];
759
        }
760
        $this->view->success = true;
761
        $this->view->message = $result;
762
    }
763
764
    /**
765
     * Возвращает представление нормера телефона по AJAX запросу
766
     *
767
     * @param $phoneNumber
768
     *
769
     * @return string
770
     */
771
    public function GetPhoneRepresentAction($phoneNumber): string
772
    {
773
        $response = $phoneNumber;
774
775
        if (strlen($phoneNumber) > 10) {
776
            $seekNumber = substr($phoneNumber, -9);
777
            $parameters = [
778
                'conditions' => 'number LIKE :SearchPhrase1:',
779
                'bind'       => [
780
                    'SearchPhrase1' => "%{$seekNumber}",
781
                ],
782
            ];
783
        } else {
784
            $parameters = [
785
                'conditions' => 'number = :SearchPhrase1:',
786
                'bind'       => [
787
                    'SearchPhrase1' => $phoneNumber,
788
                ],
789
            ];
790
        }
791
        $result = Extensions::findFirst($parameters);
792
        if ($result !== null) {
793
            $response = $result->getRepresent();
794
        }
795
796
        return $response;
797
    }
798
799
    /**
800
     * Используется для генерации списка выбора пользователей из JS скрипта extensions.js
801
     *
802
     * @param string $type {all, phones, internal} - отображать только телефоны или все возможные номера
803
     *
804
     * @return void параметры помещаются в view и обрабатваются через ControllerBase::afterExecuteRoute()
805
     */
806
    public function getForSelectAction($type = 'all'): void
807
    {
808
        $results = [];
809
810
        switch ($type) {
811
            case 'all':
812
            {
813
                $parameters = [
814
                    'conditions' => 'show_in_phonebook="1"',
815
                ];
816
                break;
817
            }
818
            case 'phones':
819
            {
820
                // Список телефоонных эктеншенов
821
                $parameters = [
822
                    'conditions' => 'type IN ({ids:array}) AND show_in_phonebook="1"',
823
                    'bind'       => [
824
                        'ids' => [Extensions::TYPE_SIP, Extensions::TYPE_EXTERNAL],
825
                    ],
826
                ];
827
                break;
828
            }
829
            case 'internal':
830
            {
831
                // Только внутренние
832
                $parameters = [
833
                    'conditions' => 'type IN ({ids:array}) AND show_in_phonebook="1"',
834
                    'bind'       => [
835
                        'ids' => [Extensions::TYPE_SIP],
836
                    ],
837
                ];
838
                break;
839
            }
840
            default:
841
            {
842
                $parameters = [
843
                    'conditions' => 'show_in_phonebook="1"',
844
                ];
845
            }
846
        }
847
        $extensions = Extensions::find($parameters);
848
        foreach ($extensions as $record) {
849
            $type = ($record->userid > 0) ? ' USER'
850
                : $record->type; // Пользователи будут самыми первыми в списке
851
            $type = Text::underscore(strtoupper($type));
852
853
854
            // Необходимо проверить к какому модулю относится эта запись
855
            // и включен ли этот модуль в данный момент
856
            if ($type === Extensions::TYPE_MODULES) {
857
                $module = $this->findModuleByExtensionNumber($record->number);
858
                if ($module === null || $module->disabled === '1') {
859
                    continue; // исключаем отключенные модули
860
                }
861
            }
862
            $represent        = $record->getRepresent();
863
            $clearedRepresent = strip_tags($represent);
864
            $results[]        = [
865
                'name'          => $represent,
866
                'value'         => $record->number,
867
                'type'          => $type,
868
                'typeLocalized' => $this->translation->_("ex_dropdownCategory_{$type}"),
869
                'sorter'        => ($record->userid > 0) ? "{$type}{$clearedRepresent}{$record->number}" : "{$type}{$clearedRepresent}"
870
                // 'avatar' => ( $record->userid > 0 )
871
                // 	? $record->Users->avatar : '',
872
            ];
873
        }
874
875
        usort(
876
            $results,
877
            [__CLASS__, 'sortExtensionsArray']
878
        );
879
880
        $this->view->success = true;
881
        $this->view->results = $results;
882
    }
883
884
    /**
885
     * Try to find module by extension number
886
     *
887
     * @param string $number
888
     *
889
     * @return mixed|null
890
     */
891
    private function findModuleByExtensionNumber(string $number)
892
    {
893
        $result         = null;
894
        $extension      = Extensions::findFirst("number ='{$number}'");
895
        $relatedLinks   = $extension->getRelatedLinks();
896
        $moduleUniqueID = false;
897
        foreach ($relatedLinks as $relation) {
898
            $obj = $relation['object'];
899
            if (strpos(get_class($obj), 'Modules\\') === 0) {
900
                $moduleUniqueID = explode('Models\\', get_class($obj))[1];
901
            }
902
        }
903
        if ($moduleUniqueID) {
904
            $result = PbxExtensionModules::findFirstByUniqid($moduleUniqueID);
905
        }
906
907
        return $result;
908
    }
909
910
    /**
911
     * Сортировка массива extensions
912
     *
913
     * @param $a
914
     * @param $b
915
     *
916
     * @return int
917
     */
918
    private function sortExtensionsArray($a, $b): int
919
    {
920
        return strcmp($a['sorter'], $b['sorter']);
921
    }
922
923
924
}