Passed
Push — develop ( 8b34e3...3e2019 )
by Nikolay
12:53
created

IvrMenuController::sortArrayByDigits()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
/**
3
 * Copyright (C) MIKO LLC - All Rights Reserved
4
 * Unauthorized copying of this file, via any medium is strictly prohibited
5
 * Proprietary and confidential
6
 * Written by Nikolay Beketov, 5 2018
7
 *
8
 */
9
10
namespace MikoPBX\AdminCabinet\Controllers;
11
12
use MikoPBX\AdminCabinet\Forms\IvrMenuEditForm;
13
use MikoPBX\Common\Models\{Extensions, IvrMenu, IvrMenuActions, SoundFiles};
14
15
class IvrMenuController extends BaseController
16
{
17
18
19
    /**
20
     * Builds IVR menu representation
21
     */
22
    public function indexAction(): void
23
    {
24
        $records = IvrMenuActions::find();
25
        $ivrMenuActions=[];
26
        foreach ($records as $record) {
27
            $ivrMenuActions[$record->ivr_menu_id][$record->id]=[
28
                'digits'=>$record->digits,
29
                'represent'=>$record->Extensions===null?'ERROR':$record->Extensions->getRepresent()
30
            ];
31
        }
32
33
        $records = IvrMenu::find();
34
        $ivrMenuList=[];
35
        foreach ($records as $record) {
36
            usort($ivrMenuActions[$record->uniqid], [__CLASS__, 'sortArrayByDigits']);
37
            $ivrMenuList[]=[
38
                'uniqid'=>$record->uniqid,
39
                'name'=>$record->name,
40
                'extension'=>$record->extension,
41
                'actions'=>$ivrMenuActions[$record->uniqid],
42
                'description'=>$record->description,
43
                'timeoutExtension'=>$record->TimeoutExtensions===null?'ERROR':$record->TimeoutExtensions->getRepresent()
44
            ];
45
        }
46
        $this->view->ivrmenu = $ivrMenuList;
47
    }
48
49
    /**
50
     * Карточка редактирования IVR меню
51
     *
52
     * @param string $ivrmenuid идентификатор меню
53
     */
54
    public function modifyAction($ivrmenuid = ''): void
55
    {
56
        $ivrmenu                = IvrMenu::findFirstByUniqid($ivrmenuid);
57
        $ivrActionsList         = [];
58
        $soundfilesList         = [];
59
        $extensionList          = [];
60
        $soundfilesList[""]     = $this->translation->_("sf_SelectAudioFile");
61
        $extensionList[""]      = $this->translation->_("ex_SelectNumber");
62
        $extensionListForFilter = [];
63
        if ($ivrmenu === null) {
64
            $ivrmenu                   = new IvrMenu();
65
            $ivrmenu->uniqid           = strtoupper('IVR-' . md5($ivrmenu->id . time()));
66
            $ivrmenu->number_of_repeat = 3;
67
            $ivrmenu->extension
68
                                       = Extensions::getNextFreeApplicationNumber();
69
            $ivrmenu->timeout          = 7;
70
        } else {
71
            $extensionListForFilter[] = $ivrmenu->timeout_extension;
72
            // Списк экстеншенов очереди
73
            $parameters = [
74
                'conditions' => 'ivr_menu_id=:menu:',
75
                'bind'       => [
76
                    'menu' => $ivrmenu->uniqid,
77
                ],
78
            ];
79
            $actions    = IvrMenuActions::find($parameters);
80
            foreach ($actions as $action) {
81
                $ivrActionsList[]         = [
82
                    'id'                 => $action->id,
83
                    'extension'          => $action->extension,
84
                    'extensionRepresent' => str_replace(
85
                        '"',
86
                        '\\"',
87
                        $action->Extensions->getRepresent()
88
                    ),
89
                    'digits'             => $action->digits,
90
                ];
91
                $extensionListForFilter[] = $action->extension;
92
            }
93
        }
94
        usort($ivrActionsList, [__CLASS__, 'sortArrayByDigits']);
95
96
        // Список всех эктеншенов выбранных ранее для правил адресации
97
        if (count($extensionListForFilter) > 0) {
98
            $parameters = [
99
                'conditions' => 'number IN ({ids:array})',
100
                'bind'       => [
101
                    'ids' => $extensionListForFilter,
102
                ],
103
            ];
104
            $extensions = Extensions::find($parameters);
105
            foreach ($extensions as $record) {
106
                $extensionList[$record->number] = $record->getRepresent();
107
            }
108
        }
109
110
        // Список звуковых файлов для IVR
111
        $soundFiles = SoundFiles::find('category="custom"');
112
        foreach ($soundFiles as $soundFile) {
113
            $soundfilesList[$soundFile->id] = $soundFile->getRepresent();
114
        }
115
116
        $form                   = new IvrMenuEditForm(
117
            $ivrmenu, [
118
            'extensions' => $extensionList,
119
            'soundfiles' => $soundfilesList,
120
        ]
121
        );
122
        $this->view->form       = $form;
123
        $this->view->ivractions = $ivrActionsList;
124
        $this->view->represent  = $ivrmenu->getRepresent();
125
        $this->view->extension  = $ivrmenu->extension;
126
127
    }
128
129
    /**
130
     * Sorts array by digits field
131
     *
132
     * @param $a
133
     * @param $b
134
     *
135
     * @return int|null
136
     */
137
    public function sortArrayByDigits($a, $b): ?int
138
    {
139
        $a = (int)$a['digits'];
140
        $b = (int)$b['digits'];
141
        if ($a === $b) {
142
            return 0;
143
        } else {
144
            return ($a < $b) ? -1 : 1;
145
        }
146
    }
147
148
    /**
149
     * Сохранение ivr меню
150
     */
151
    public function saveAction(): void
152
    {
153
        if ( ! $this->request->isPost()) {
154
            return;
155
        }
156
157
        $this->db->begin();
158
159
        $data          = $this->request->getPost();
160
        $ivrMenuRecord = IvrMenu::findFirstByUniqid($data['uniqid']);
161
        if ($ivrMenuRecord === null) {
162
            $ivrMenuRecord = new IvrMenu();
163
164
            $extension                    = new Extensions();
165
            $extension->type              = Extensions::TYPE_IVR_MENU;
166
            $extension->number            = $data["extension"];
167
            $extension->callerid          = $this->sanitizeCallerId($data["name"]);
168
            $extension->userid            = null;
169
            $extension->show_in_phonebook = 1;
170
            $extension->public_access     = 1;
171
        } else {
172
            $extension = $ivrMenuRecord->Extensions;
173
        }
174
175
        // Заполним параметры внутреннего номера
176
        if ( ! $this->updateExtension($extension, $data)) {
177
            $this->view->success = false;
178
            $this->db->rollback();
179
180
            return;
181
        }
182
183
        // Заполним параметры IVR меню
184
        if ( ! $this->updateIVRMenu($ivrMenuRecord, $data)) {
185
            $this->view->success = false;
186
            $this->db->rollback();
187
188
            return;
189
        }
190
191
        // Заполним параметры участников IVR Меню
192
        if ( ! $this->updateIVRMenuActions($data)) {
193
            $this->view->success = false;
194
            $this->db->rollback();
195
196
            return;
197
        }
198
199
        $this->view->success = true;
200
        $this->db->commit();
201
202
        // Если это было создание карточки то надо перегрузить страницу с указанием ID
203
        if (empty($data['id'])) {
204
            $this->view->reload = "ivr-menu/modify/{$data['uniqid']}";
205
        }
206
    }
207
208
    /**
209
     * Обновление параметров внутреннего номера
210
     *
211
     * @param \MikoPBX\Common\Models\Extensions $extension
212
     * @param array                             $data массив полей из POST запроса
213
     *
214
     * @return bool update result
215
     */
216
    private function updateExtension(Extensions $extension, array $data): bool
217
    {
218
        $extension->number   = $data['extension'];
219
        $extension->callerid = $this->sanitizeCallerId($data['name']);
220
        if ($extension->save() === false) {
221
            $errors = $extension->getMessages();
222
            $this->flash->error(implode('<br>', $errors));
223
224
            return false;
225
        }
226
227
        return true;
228
    }
229
230
    /**
231
     * Обновление параметров IVR меню
232
     *
233
     * @param \MikoPBX\Common\Models\IvrMenu $ivrMenu
234
     * @param array                          $data массив полей из POST запроса
235
     *
236
     * @return bool update result
237
     */
238
    private function updateIVRMenu(IvrMenu $ivrMenu, array $data): bool
239
    {
240
        // Заполним параметры записи Ivr Menu
241
        foreach ($ivrMenu as $name => $value) {
242
            switch ($name) {
243
                case "extension":
244
                case "name":
245
                    $ivrMenu->$name = $data[$name];
246
                    break;
247
                case "allow_enter_any_internal_extension":
248
                    if (array_key_exists($name, $data) && $data[$name] == "on") {
249
                        $ivrMenu->$name = "1";
250
                    } else {
251
                        $ivrMenu->$name = "0";
252
                    }
253
                    break;
254
                default:
255
                    if ( ! array_key_exists($name, $data)) {
256
                        continue 2;
257
                    }
258
                    $ivrMenu->$name = $data[$name];
259
            }
260
        }
261
        if ($ivrMenu->save() === false) {
262
            $errors = $ivrMenu->getMessages();
263
            $this->flash->error(implode('<br>', $errors));
264
265
            return false;
266
        }
267
268
        return true;
269
    }
270
271
    /**
272
     * Обновление действий в IVR меню
273
     *
274
     * @param array $data массив полей из POST запроса
275
     *
276
     * @return bool update result
277
     */
278
    private function updateIVRMenuActions(array $data): bool
279
    {
280
        $existDigits = [];
281
282
        // Заполним параметры IvrMenuActions
283
        $arrActions = json_decode($data['actions']);
284
        foreach ($arrActions as $value) {
285
            $parameters = [
286
                'conditions' => 'ivr_menu_id = :uniqid: AND digits=:digits:',
287
                'bind'       => [
288
                    'digits' => $value->digits,
289
                    'uniqid' => $data['uniqid'],
290
                ],
291
            ];
292
            $newRule    = IvrMenuActions::findFirst($parameters);
293
            if ($newRule === null) {
294
                $newRule              = new IvrMenuActions();
295
                $newRule->digits      = $value->digits;
296
                $newRule->ivr_menu_id = $data['uniqid'];
297
            }
298
            $newRule->extension = $value->extension;
299
            if ($newRule->save() === false) {
300
                $errors = $newRule->getMessages();
301
                $this->flash->warning(implode('<br>', $errors));
302
                $this->view->success = false;
303
304
                return false;
305
            }
306
            $existDigits[] = $value->digits;
307
        }
308
309
        // Удалим лишние элементы меню
310
        $parameters = [
311
            'conditions' => 'digits NOT IN ({numbers:array}) AND ivr_menu_id=:uniqid:',
312
            'bind'       => [
313
                'numbers' => $existDigits,
314
                'uniqid'  => $data['uniqid'],
315
            ],
316
        ];
317
318
        $deletedActions = IvrMenuActions::find($parameters);
319
        if ($deletedActions && $deletedActions->delete() === false) {
320
            $errors = $deletedActions->getMessages();
321
            $this->flash->error(implode('<br>', $errors));
322
323
            return false;
324
        }
325
326
        return true;
327
    }
328
329
    /**
330
     * Удаление ivr меню
331
     *
332
     * @param string $uniqid
333
     */
334
    public function deleteAction($uniqid = '')
335
    {
336
        if ($uniqid === '') {
337
            return;
338
        }
339
340
        $ivrMenu = IvrMenu::findFirstByUniqid($uniqid);
341
        if ($ivrMenu === null) {
342
            return;
343
        }
344
345
        $this->db->begin();
346
        $errors = false;
347
        $extension = $ivrMenu->Extensions;
348
        if ( ! $extension->delete()) {
349
            $errors = $extension->getMessages();
350
        }
351
352
        if ($errors) {
353
            $this->flash->warning(implode('<br>', $errors));
354
            $this->db->rollback();
355
        } else {
356
            $this->db->commit();
357
        }
358
359
        $this->forward('ivr-menu/index');
360
    }
361
362
363
}