ProvidersController::deleteAction()   C
last analyzed

Complexity

Conditions 12
Paths 44

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 41
rs 6.9666
c 0
b 0
f 0
cc 12
nc 44
nop 1

How to fix   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
/*
4
 * MikoPBX - free phone system for small business
5
 * Copyright © 2017-2023 Alexey Portnov and Nikolay Beketov
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along with this program.
18
 * If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
namespace MikoPBX\AdminCabinet\Controllers;
22
23
use MikoPBX\AdminCabinet\Forms\{IaxProviderEditForm, SipProviderEditForm};
24
use MikoPBX\Common\Models\{Iax, Providers, Sip, SipHosts};
25
use Phalcon\Filter\Filter;
26
27
class ProvidersController extends BaseController
28
{
29
    /**
30
     * Retrieves and prepares a list of providers for display in the index view.
31
     */
32
    public function indexAction(): void
33
    {
34
        $providers = Providers::find();
35
        $providersList = [];
36
        foreach ($providers as $provider) {
37
            $modelType = ucfirst($provider->type);
38
            $provByType = $provider->$modelType;
39
            $providersList[] = [
40
                'uniqid' => $provByType->uniqid,
41
                'name' => $provByType->description,
42
                'username' => $provByType->username,
43
                'hostname' => $provByType->host,
44
                'type' => $provider->type,
45
                'status' => $provByType->disabled ? 'disabled' : '',
46
                'existLinks' => $provider->OutgoingRouting->count() > 0 ? 'true' : 'false',
47
48
            ];
49
        }
50
        $this->view->providerlist = $providersList;
51
    }
52
53
54
    /**
55
     * Opens the SIP provider card and fills in default values.
56
     *
57
     * @param string $uniqId Unique identifier of the provider (optional) when opening an existing one.
58
     */
59
    public function modifysipAction(string $uniqId = ''): void
60
    {
61
        $idIsEmpty = false;
62
        if (empty($uniqId)) {
63
            $idIsEmpty = true;
64
            $uniqId = $this->request->get('copy-source', Filter::FILTER_STRING, '');
65
        }
66
        /** @var Providers $provider */
67
        $provider = Providers::findFirstByUniqid($uniqId);
68
        if ($provider === null) {
69
            $uniqId = Sip::generateUniqueID('SIP-TRUNK-');
70
            $provider = new Providers();
71
            $provider->type = 'SIP';
72
            $provider->uniqid = $uniqId;
73
            $provider->sipuid = $uniqId;
74
            $provider->Sip = new Sip();
75
            $provider->Sip->uniqid = $uniqId;
76
            $provider->Sip->type = 'friend';
77
            $provider->Sip->port = 5060;
78
            $provider->Sip->disabled = '0';
79
            $provider->Sip->qualifyfreq = 60;
80
            $provider->Sip->qualify = '1';
81
            $provider->Sip->secret = SIP::generateSipPassword();
82
        } elseif ($idIsEmpty) {
83
            $uniqId = Sip::generateUniqueID('SIP-TRUNK-');
84
            $oldProvider = $provider;
85
            $provider = new Providers();
86
            foreach ($oldProvider->toArray() as $key => $value) {
87
                $provider->writeAttribute($key, $value);
88
            }
89
            $provider->Sip = new Sip();
90
            foreach ($oldProvider->Sip->toArray() as $key => $value) {
91
                $provider->Sip->writeAttribute($key, $value);
92
            }
93
            $provider->id     = '';
0 ignored issues
show
Documentation Bug introduced by
The property $id was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
94
            $provider->uniqid = $uniqId;
95
            $provider->sipuid = $uniqId;
96
            $provider->Sip->description = '';
97
            $provider->Sip->id     = '';
98
            $provider->Sip->uniqid = $uniqId;
99
            $provider->Sip->secret = md5(microtime());
100
        }
101
102
        $providerHost = $provider->Sip->host;
103
        $sipHosts = $provider->Sip->SipHosts;
104
        $hostsTable = [];
105
        foreach ($sipHosts as $host) {
106
            if ($providerHost !== $host->address) {
107
                $hostsTable[] = $host->address;
108
            }
109
        }
110
        $this->view->secret = $provider->Sip->secret;
111
        $this->view->hostsTable = $hostsTable;
112
        $options = ['note' => $provider->note];
113
        $this->view->form = new SipProviderEditForm($provider->Sip, $options);
114
        $this->view->represent = $provider->getRepresent();
115
    }
116
117
    /**
118
     * Opens the IAX provider card and fills in default values.
119
     *
120
     * @param string $uniqId
121
     */
122
    public function modifyiaxAction(string $uniqId = ''): void
123
    {
124
        $idIsEmpty = false;
125
        if (empty($uniqId)) {
126
            $idIsEmpty = true;
127
            $uniqId = $this->request->get('copy-source', Filter::FILTER_STRING, '');
128
        }
129
130
        $provider = Providers::findFirstByUniqid($uniqId);
131
132
        if ($provider === null) {
133
            $uniqId = Iax::generateUniqueID('IAX-TRUNK-');
134
            $provider = new Providers();
135
            $provider->type = 'IAX';
136
            $provider->uniqid = $uniqId;
137
            $provider->iaxuid = $uniqId;
138
            $provider->Iax = new Iax();
139
            $provider->Iax->uniqid = $uniqId;
140
            $provider->Iax->disabled = '0';
141
            $provider->Iax->qualify = '1';
142
        } elseif ($idIsEmpty) {
143
            $uniqId = Iax::generateUniqueID('IAX-TRUNK-');
144
            $oldProvider = $provider;
145
            $provider = new Providers();
146
            foreach ($oldProvider->toArray() as $key => $value) {
147
                $provider->writeAttribute($key, $value);
148
            }
149
            $provider->Iax = new Iax();
150
            foreach ($oldProvider->Iax->toArray() as $key => $value) {
151
                $provider->Iax->writeAttribute($key, $value);
152
            }
153
            $provider->id     = '';
0 ignored issues
show
Documentation Bug introduced by
The property $id was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
154
            $provider->uniqid = $uniqId;
155
            $provider->sipuid = $uniqId;
156
            $provider->Iax->description = '';
157
            $provider->Iax->id     = '';
0 ignored issues
show
Documentation Bug introduced by
The property $id was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
158
            $provider->Iax->uniqid = $uniqId;
159
            $provider->Iax->secret = md5(microtime());
160
        }
161
        $options = ['note' => $provider->note];
162
        $this->view->form = new IaxProviderEditForm($provider->Iax, $options);
163
        $this->view->represent = $provider->getRepresent();
164
    }
165
166
    /**
167
     * Enables a provider.
168
     *
169
     * @param string $type Provider type (SIP or IAX)
170
     * @param string $uniqid Unique identifier of the provider (optional) when opening an existing one.
171
     */
172
    public function enableAction(string $type, string $uniqid = ''): void
173
    {
174
        $this->view->success = false;
175
        switch ($type) {
176
            case 'iax':
177
            {
178
                $provider = Iax::findFirstByUniqid($uniqid);
179
                break;
180
            }
181
            case 'sip':
182
            {
183
                $provider = Sip::findFirstByUniqid($uniqid);
184
                break;
185
            }
186
            default:
187
                $provider = null;
188
        }
189
        if ($provider !== null) {
190
            $provider->disabled = '0';
191
            if ($provider->save() === true) {
192
                $this->view->success = true;
193
            }
194
        }
195
    }
196
197
    /**
198
     * Disables a provider.
199
     *
200
     * @param string $type Provider type (SIP or IAX)
201
     * @param string $uniqid Unique identifier of the provider (optional) when opening an existing one.
202
     */
203
    public function disableAction(string $type, string $uniqid = ''): void
204
    {
205
        $this->view->success = false;
206
        switch ($type) {
207
            case 'iax':
208
            {
209
                $provider = Iax::findFirstByUniqid($uniqid);
210
                break;
211
            }
212
            case 'sip':
213
            {
214
                $provider = Sip::findFirstByUniqid($uniqid);
215
                break;
216
            }
217
            default:
218
                $provider = null;
219
        }
220
        if ($provider !== null) {
221
            $provider->disabled = '1';
222
            if ($provider->save() === true) {
223
                $this->view->success = true;
224
            }
225
        }
226
    }
227
228
    /**
229
     * Saves a provider via AJAX request from a web form.
230
     *
231
     * @param string $type Provider type ('sip' or 'iax').
232
     */
233
    public function saveAction(string $type): void
234
    {
235
        if (!$this->request->isPost()) {
236
            $this->forward('network/index');
237
        }
238
        $this->db->begin();
239
        $data = $this->request->getPost();
240
241
        // Update SIP and IAX tables
242
        if (!$this->saveProvider($data, $type)) {
243
            $this->view->success = false;
244
            $this->db->rollback();
245
246
            return;
247
        }
248
249
        // Update additional hosts table for SIP providers
250
        if ($type === 'sip' && !$this->updateAdditionalHosts($data)) {
251
            $this->view->success = false;
252
            $this->db->rollback();
253
254
            return;
255
        }
256
257
        $this->flash->success($this->translation->_('ms_SuccessfulSaved'));
258
        $this->view->success = true;
259
        $this->db->commit();
260
261
        // If it was creating a new provider, reload the page with the specified ID
262
        if (empty($data['id'])) {
263
            $this->view->reload = "providers/modify$type/{$data['uniqid']}";
264
        }
265
    }
266
267
    /**
268
     * Save provider data table.
269
     *
270
     * @param array $data POST data.
271
     * @param string $type Provider type ('sip' or 'iax').
272
     *
273
     * @return bool Save result.
274
     */
275
    private function saveProvider(array $data, string $type): bool
276
    {
277
        // Check if it's a new or existing provider.
278
        $provider = Providers::findFirstByUniqid($data['uniqid']);
279
        if ($provider === null) {
280
            $provider = new Providers();
281
            $provider->uniqid = $data['uniqid'];
282
            switch ($type) {
283
                case 'iax':
284
                    $provider->iaxuid = $data['uniqid'];
285
                    $provider->type = 'IAX';
286
                    $provider->Iax = new Iax();
287
                    break;
288
                case 'sip':
289
                    $provider->sipuid = $data['uniqid'];
290
                    $provider->type = 'SIP';
291
                    $provider->Sip = new Sip();
292
                    break;
293
            }
294
        }
295
296
        if (isset($data['note'])) {
297
            $provider->note = $data['note'];
298
        }
299
        if ($provider->save() === false) {
300
            $errors = $provider->getMessages();
301
            $this->flash->warning(implode('<br>', $errors));
302
            return false;
303
        }
304
305
        switch ($type) {
306
            case 'iax':
307
                $providerByType = $provider->Iax;
308
                break;
309
            case 'sip':
310
                $providerByType = $provider->Sip;
311
                break;
312
            default:
313
                $providerByType = [];
314
        }
315
316
        foreach ($providerByType as $name => $value) {
317
            switch ($name) {
318
                case 'id':
319
                    break;
320
                case 'qualify':
321
                case 'disablefromuser':
322
                case 'noregister':
323
                case 'receive_calls_without_auth':
324
                    if (array_key_exists($name, $data)) {
325
                        $providerByType->$name = ($data[$name] === 'on') ? 1 : 0;
326
                    } else {
327
                        $providerByType->$name = 0;
328
                    }
329
                    break;
330
                case 'qualifyfreq':
331
                    $providerByType->$name = (int)$data[$name];
332
                    break;
333
                case 'manualattributes':
334
                    if (array_key_exists($name, $data)) {
335
                        $providerByType->setManualAttributes($data[$name]);
336
                    }
337
                    break;
338
                default:
339
                    if (array_key_exists($name, $data)) {
340
                        $providerByType->$name = $data[$name];
341
                    }
342
            }
343
        }
344
345
        if ($providerByType->save() === false) {
346
            $errors = $providerByType->getMessages();
347
            $this->flash->warning(implode('<br>', $errors));
348
349
            return false;
350
        }
351
352
        return true;
353
    }
354
355
    /**
356
     * Update additional hosts table.
357
     *
358
     * @param array $data Array of fields from the POST request.
359
     *
360
     * @return bool Update result.
361
     */
362
    private function updateAdditionalHosts(array $data): bool
363
    {
364
        $providerHost = $data['host'];
365
        $additionalHosts = json_decode($data['additionalHosts']);
366
        if ($data['registration_type'] !== Sip::REG_TYPE_INBOUND) {
367
            $hosts = array_merge([], array_column($additionalHosts, 'address'), [$providerHost]);
368
        } else {
369
            $hosts = array_column($additionalHosts, 'address');
370
        }
371
        $parameters = [
372
            'conditions' => 'provider_id = :providerId:',
373
            'bind' => [
374
                'providerId' => $data['uniqid']
375
            ]
376
        ];
377
        $currentRecords = SipHosts::find($parameters);
378
        foreach ($currentRecords as $record) {
379
            if (!in_array($record->address, $hosts, true)) {
380
                if ($record->delete() === false) {
381
                    $errors = $record->getMessages();
382
                    $this->flash->warning(implode('<br>', $errors));
383
                    return false;
384
                }
385
            } elseif (($key = array_search($record->address, $hosts, true)) !== false) {
386
                unset($hosts[$key]);
387
            }
388
        }
389
        foreach ($hosts as $record) {
390
            $currentRecord = new SipHosts();
391
            $currentRecord->provider_id = $data['uniqid'];
392
            $currentRecord->address = $record;
393
            if ($currentRecord->save() === false) {
394
                $errors = $currentRecord->getMessages();
395
                $this->flash->warning(implode('<br>', $errors));
396
                return false;
397
            }
398
        }
399
400
        return true;
401
    }
402
403
    /**
404
     * Deletes provider record by unique id
405
     *
406
     * @param string $uniqid
407
     */
408
    public function deleteAction(string $uniqid = ''): void
409
    {
410
        if ($uniqid === '') {
411
            return;
412
        }
413
414
        $provider = Providers::findFirstByUniqid($uniqid);
415
        if ($provider === null) {
416
            return;
417
        }
418
419
        $this->db->begin();
420
        $errors = false;
421
        if ($provider->Iax) {
422
            $iax = $provider->Iax;
423
            if (!$iax->delete()) {
424
                $errors = $iax->getMessages();
425
            }
426
        }
427
428
        if ($errors === false && $provider->Sip) {
429
            $sip = $provider->Sip;
430
            if ($sip->SipHosts) {
431
                $sipHosts = $sip->SipHosts;
432
                if (!$sipHosts->delete()) {
433
                    $errors = $sipHosts->getMessages();
434
                }
435
            }
436
            if ($errors === false && !$sip->delete()) {
437
                $errors = $sip->getMessages();
438
            }
439
        }
440
441
        if ($errors) {
442
            $this->flash->warning(implode('<br>', $errors));
443
            $this->db->rollback();
444
        } else {
445
            $this->db->commit();
446
        }
447
448
        $this->forward('providers/index');
449
    }
450
}
451