Passed
Push — develop ( 558982...38f712 )
by Nikolay
06:07
created

CallQueuesController::deleteAction()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 31
rs 9.4222
c 0
b 0
f 0
cc 5
nc 6
nop 1
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
namespace MikoPBX\AdminCabinet\Controllers;
21
22
use MikoPBX\AdminCabinet\Forms\CallQueueEditForm;
23
use MikoPBX\Common\Models\{CallQueueMembers, CallQueues, Extensions, SoundFiles};
24
25
class CallQueuesController extends BaseController
26
{
27
28
    /**
29
     *  Builds call queues representation
30
     */
31
    public function indexAction(): void
32
    {
33
        $records = CallQueueMembers::find();
34
        $callQueueMembers=[];
35
        foreach ($records as $record) {
36
            $callQueueMembers[$record->queue][$record->id]=[
37
                'priority'=>$record->priority,
38
                'represent'=>$record->Extensions===null?'ERROR':$record->Extensions->getRepresent()
39
            ];
40
        }
41
42
        $records = CallQueues::find();
43
        $callQueuesList=[];
44
        foreach ($records as $record) {
45
            $members = $callQueueMembers[$record->uniqid];
46
            if (is_array($members)){
47
                usort($members, [__CLASS__, 'sortArrayByPriority']);
48
            } else {
49
                $members = [];
50
            }
51
            $callQueuesList[]=[
52
                'uniqid'=>$record->uniqid,
53
                'name'=>$record->name,
54
                'extension'=>$record->extension,
55
                'members'=>$members,
56
                'description'=>$record->description,
57
            ];
58
        }
59
        $this->view->callQueuesList = $callQueuesList;
60
61
    }
62
63
    /**
64
     * Modify the call queue action.
65
     *
66
     * @param string $uniqid (optional) The identifier of the queue being modified.
67
     * @return void
68
     */
69
    public function modifyAction(string $uniqid = ''): void
70
    {
71
        $queue            = CallQueues::findFirstByUniqid($uniqid);
72
        $queueMembersList = [];
73
        $soundfilesList   = [];
74
        $extensionList    = [];
75
        if ($queue === null) {
76
            $queue                              = new CallQueues();
77
            $queue->uniqid                      = Extensions::TYPE_QUEUE . strtoupper('-' . md5($queue->id . time()));
78
            $queue->caller_hear                 = 'moh';
79
            $queue->seconds_to_ring_each_member = 60;
80
            $queue->seconds_for_wrapup          = 1;
81
            $queue->announce_position           = 0;
82
            $queue->announce_hold_time          = 0;
83
            $queue->periodic_announce_frequency = 30;
84
            $queue->extension                   = Extensions::getNextFreeApplicationNumber();
85
        } else {
86
            // Queue extension list
87
            $parameters = [
88
                'conditions' => 'queue=:queue:',
89
                'bind'       => [
90
                    'queue' => $queue->uniqid,
91
                ],
92
            ];
93
            $members    = CallQueueMembers::find($parameters);
94
            foreach ($members as $member) {
95
                $queueMembersList[] = [
96
                    'id'       => $member->id,
97
                    'number'   => $member->extension,
98
                    'priority'  => $member->priority,
99
                    'callerid' => $member->Extensions===null?'ERROR':$member->Extensions->getRepresent(),
100
                ];
101
            }
102
            usort($queueMembersList, [__CLASS__, 'sortArrayByPriority']);
103
        }
104
105
        $extensionList[""] = $this->translation->_("ex_SelectNumber");
106
        // List of all used extensions
107
        $parameters = [
108
            'conditions' => 'number IN ({ids:array})',
109
            'bind'       => [
110
                'ids' => [
111
                    $queue->timeout_extension,
112
                    $queue->redirect_to_extension_if_empty,
113
                    $queue->redirect_to_extension_if_unanswered,
114
                    $queue->redirect_to_extension_if_repeat_exceeded,
115
                ],
116
            ],
117
        ];
118
        $extensions = Extensions::find($parameters);
119
        foreach ($extensions as $record) {
120
            $extensionList[$record->number] = $record->getRepresent();
121
        }
122
123
        // List of sound files for queues
124
        $soundfilesList[""] = $this->translation->_("sf_SelectAudioFile");
125
        $soundfilesList[-1] = '-';
126
        $mohSoundFilesList  = $soundfilesList;
127
128
        $soundFiles         = SoundFiles::find(['columns' => 'id,name,category']);
129
        foreach ($soundFiles as $soundFile) {
130
            if(SoundFiles::CATEGORY_CUSTOM === $soundFile->category){
131
                $soundfilesList[$soundFile->id] = $soundFile->name;
132
            }else{
133
                $mohSoundFilesList[$soundFile->id] = $soundFile->name;
134
            }
135
        }
136
137
        $form                        = new CallQueueEditForm(
138
            $queue, [
139
                      'extensions' => $extensionList,
140
                      'soundfiles' => $soundfilesList,
141
                      'mohSoundFiles' => $mohSoundFilesList,
142
                  ]
143
        );
144
        $this->view->form            = $form;
145
        $this->view->extensionsTable = $queueMembersList;
146
        $this->view->represent       = $queue->getRepresent();
147
        $this->view->extension       = $queue->extension;
148
    }
149
150
151
    /**
152
     * Save the queue via AJAX request from the form.
153
     *
154
     * This method saves the queue by processing an AJAX request from the form.
155
     *
156
     * @return void
157
     */
158
    public function saveAction(): void
159
    {
160
        if ( ! $this->request->isPost()) {
161
            return;
162
        }
163
        $this->db->begin();
164
165
        $data  = $this->request->getPost();
166
        $queue = CallQueues::findFirstByUniqid($data['uniqid']);
167
        if ($queue === null) {
168
            $queue                        = new CallQueues();
169
            $extension                    = new Extensions();
170
            $extension->type              = Extensions::TYPE_QUEUE;
171
            $extension->number            = $data["extension"];
172
            $extension->callerid          = $this->sanitizeCallerId($data["name"]);
173
            $extension->userid            = null;
174
            $extension->show_in_phonebook = 1;
175
            $extension->public_access     = 1;
176
        } else {
177
            $extension = $queue->Extensions;
178
        }
179
180
        // Update the extension parameters
181
        if ( ! $this->updateExtension($extension, $data)) {
182
            $this->view->success = false;
183
            $this->db->rollback();
184
185
            return;
186
        }
187
188
        // Update the queue parameters
189
        if ( ! $this->updateQueue($queue, $data)) {
190
            $this->view->success = false;
191
            $this->db->rollback();
192
193
            return;
194
        }
195
196
        // Update the queue members
197
        if ( ! $this->updateQueueMembers($data)) {
198
            $this->view->success = false;
199
            $this->db->rollback();
200
201
            return;
202
        }
203
204
        $this->flash->success($this->translation->_('ms_SuccessfulSaved'));
205
        $this->view->success = true;
206
        $this->db->commit();
207
208
        // If it was a new queue card, reload the page with the specified ID
209
        if (empty($data['id'])) {
210
            $this->view->reload = "call-queues/modify/{$data['uniqid']}";
211
        }
212
    }
213
214
    /**
215
     * Update the extension parameters.
216
     *
217
     * This method updates the parameters of the internal extension.
218
     *
219
     * @param \MikoPBX\Common\Models\Extensions $extension The extension object to update.
220
     * @param array                             $data      The array of fields from the POST request.
221
     *
222
     * @return bool The update result. Returns true if the update is successful, false otherwise.
223
     */
224
    private function updateExtension(Extensions $extension, array $data): bool
225
    {
226
        $extension->number   = $data['extension'];
227
        $extension->callerid = $this->sanitizeCallerId($data['name']);
228
        if ($extension->save() === false) {
229
            $errors = $extension->getMessages();
230
            $this->flash->error(implode('<br>', $errors));
231
232
            return false;
233
        }
234
235
        return true;
236
    }
237
238
    /**
239
     * Update queue parameters.
240
     *
241
     * This method updates the parameters of a queue.
242
     *
243
     * @param \MikoPBX\Common\Models\CallQueues $queue The queue object to update.
244
     * @param array                             $data  The array of fields from the POST request.
245
     *
246
     * @return bool The update result. Returns true if the update is successful, false otherwise.
247
     */
248
    private function updateQueue(CallQueues $queue, array $data): bool
249
    {
250
        foreach ($queue as $name => $value) {
251
            switch ($name) {
252
                case "extension":
253
                case "name":
254
                    $queue->$name = $data[$name];
255
                    break;
256
                case "recive_calls_while_on_a_call":
257
                case "announce_position":
258
                case "announce_hold_time":
259
                    if (array_key_exists($name, $data)) {
260
                        $queue->$name = ($data[$name] == 'on') ? "1" : "0";
261
                    } else {
262
                        $queue->$name = "0";
263
                    }
264
                    break;
265
266
                case "periodic_announce_sound_id":
267
                case "moh_sound_id":
268
                case "redirect_to_extension_if_repeat_exceeded":
269
                case "redirect_to_extension_if_empty":
270
                    if ( ! array_key_exists($name, $data) || empty($data[$name])) {
271
                        $queue->$name = null;
272
                        continue 2;
273
                    }
274
                    $queue->$name = $data[$name];
275
276
                    break;
277
                case "timeout_to_redirect_to_extension":
278
                case "number_unanswered_calls_to_redirect":
279
                    if ( ! array_key_exists($name, $data)) {
280
                        continue 2;
281
                    }
282
                    if (empty($data[$name])) {
283
                        $queue->$name = null;
284
                    } else {
285
                        $queue->$name = $data[$name];
286
                    }
287
                    break;
288
                case "timeout_extension":
289
                    if ( ! array_key_exists($name, $data)
290
                        || empty($data[$name])
291
                        || (array_key_exists('timeout_to_redirect_to_extension', $data)
292
                            && intval($data['timeout_to_redirect_to_extension']) === 0)) {
293
                        $queue->$name = null;
294
                        continue 2;
295
                    }
296
                    $queue->$name = $data[$name];
297
298
                    break;
299
                case "redirect_to_extension_if_unanswered":
300
                    if ( ! array_key_exists($name, $data)
301
                        || empty($data[$name])
302
                        || (array_key_exists('number_unanswered_calls_to_redirect', $data)
303
                            && intval($data['number_unanswered_calls_to_redirect']) === 0)) {
304
                        $queue->$name = null;
305
                        continue 2;
306
                    }
307
                    $queue->$name = $data[$name];
308
309
                    break;
310
                default:
311
                    if ( ! array_key_exists($name, $data)) {
312
                        continue 2;
313
                    }
314
                    $queue->$name = $data[$name];
315
            }
316
        }
317
318
        if ($queue->save() === false) {
319
            $errors = $queue->getMessages();
320
            $this->flash->error(implode('<br>', $errors));
321
322
            return false;
323
        }
324
325
        return true;
326
    }
327
328
    /**
329
     * Update the queue members with the provided data.
330
     *
331
     * @param array $data The data containing the queue members information.
332
     * @return bool True if the update is successful, false otherwise.
333
     */
334
    private function updateQueueMembers(array $data): bool
335
    {
336
        $realMembers = [];
337
        // Update settings for existing queue members
338
        $membersTable = json_decode($data['members']);
339
        foreach ($membersTable as $member) {
340
            $parameters   = [
341
                'conditions' => 'extension = :number: AND queue=:uniqid:',
342
                'bind'       => [
343
                    'number' => $member->number,
344
                    'uniqid' => $data['uniqid'],
345
                ],
346
            ];
347
            $queueMembers = CallQueueMembers::find($parameters);
348
            if (is_countable($queueMembers) && count($queueMembers) > 1) {
349
                // Remove extra members and create a new one
350
                if ($queueMembers->delete() === false) {
351
                    $errors = $queueMembers->getMessages();
352
                    $this->flash->error(implode('<br>', $errors));
353
354
                    return false;
355
                }
356
                $queueMember = new CallQueueMembers();
357
            } elseif (is_countable($queueMembers) && count($queueMembers) === 1) {
358
                $queueMember = $queueMembers->getFirst();
359
            } else {
360
                $queueMember = new CallQueueMembers();
361
            }
362
363
            $queueMember->priority  = $member->priority;
364
            $queueMember->extension = $member->number;
365
            $queueMember->queue     = $data['uniqid'];
366
            $realMembers[]          = $member->number;
367
            if ($queueMember->save() === false) {
368
                $errors = $queueMember->getMessages();
369
                $this->flash->error(implode('<br>', $errors));
370
371
                return false;
372
            }
373
        }
374
375
        // Remove queue members not present in the list
376
        $parameters = [
377
            'conditions' => 'extension NOT IN  ({numbers:array}) AND queue=:uniqid:',
378
            'bind'       => [
379
                'numbers' => $realMembers,
380
                'uniqid'  => $data['uniqid'],
381
            ],
382
        ];
383
384
        $deletedMembers = CallQueueMembers::find($parameters);
385
        if ($deletedMembers && $deletedMembers->delete() === false) {
386
            $errors = $deletedMembers->getMessages();
387
            $this->flash->error(implode('<br>', $errors));
388
389
            return false;
390
        }
391
392
        return true;
393
    }
394
395
}