NetworkController::deleteAction()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 10
rs 10
c 0
b 0
f 0
cc 3
nc 2
nop 1
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\NetworkEditForm;
24
use MikoPBX\Common\Models\LanInterfaces;
25
use MikoPBX\Common\Models\PbxSettings;
26
use MikoPBX\Core\System\Util;
27
28
class NetworkController extends BaseController
29
{
30
    /**
31
     * Lan cards settings form
32
     */
33
    public function modifyAction(): void
34
    {
35
        $networkInterfaces = LanInterfaces::find();
36
        foreach ($networkInterfaces as $record) {
37
            if ($record->disabled !== '1') {
38
                $arrEth[] = $record;
39
            }
40
        }
41
42
        $template = new LanInterfaces();
43
        $template->id = 0;
44
        $template->dhcp = '1';
45
        $template->vlanid = '4095';
46
47
        $arrEth[] = $template;
48
49
        $internetInterface = LanInterfaces::findFirstByInternet('1');
50
        if ($internetInterface === null) {
51
            $internetInterface = new LanInterfaces();
52
            $internetInterface->id = 1;
53
        }
54
55
        // We will find additional interfaces which we can delete
56
        $deletableInterfaces = [];
57
        $countInterfaces = LanInterfaces::count(['group' => 'interface']);
58
        foreach ($countInterfaces as $record) {
59
            if ($record->rowcount > 1) {
60
                $deletableInterfaces[] = $record->interface;
61
            }
62
        }
63
        $form = new NetworkEditForm($internetInterface, ['eths' => $arrEth]);
64
65
        $this->view->setVars(
66
            [
67
                'SIP_PORT' => PbxSettings::getValueByKey(PbxSettings::SIP_PORT),
68
                'EXTERNAL_SIP_PORT' => PbxSettings::getValueByKey(PbxSettings::EXTERNAL_SIP_PORT),
69
                'TLS_PORT' => PbxSettings::getValueByKey(PbxSettings::TLS_PORT),
70
                'EXTERNAL_TLS_PORT' => PbxSettings::getValueByKey(PbxSettings::EXTERNAL_TLS_PORT),
71
                'RTP_PORT_FROM' => PbxSettings::getValueByKey(PbxSettings::RTP_PORT_FROM),
72
                'RTP_PORT_TO' => PbxSettings::getValueByKey(PbxSettings::RTP_PORT_TO),
73
                'form' => $form,
74
                'eths' => $arrEth,
75
                'deletableEths' => $deletableInterfaces,
76
                'isDocker' => Util::isDocker(),
77
                'submitMode' => null,
78
            ]
79
        );
80
    }
81
82
    /**
83
     * Saves the lan cards settings
84
     */
85
    public function saveAction(): void
86
    {
87
        if (!$this->request->isPost()) {
88
            return;
89
        }
90
91
        $data = $this->request->getPost();
92
        $this->db->begin();
93
94
95
        list($result, $messages) = $this->saveLanInterfaces($data);
96
        if (!$result) {
97
            $this->flash->warning(implode('<br>', $messages));
98
            $this->view->success = false;
99
            $this->db->rollback();
100
            return;
101
        }
102
103
        list($result, $messages) = $this->saveNatSettings($data);
104
        if (!$result) {
105
            $this->flash->warning(implode('<br>', $messages));
106
            $this->view->success = false;
107
            $this->db->rollback();
108
            return;
109
        }
110
111
        $this->view->reload = 'network/modify';
112
        $this->flash->success($this->translation->_('ms_SuccessfulSaved'));
113
        $this->view->success = true;
114
        $this->db->commit();
115
    }
116
117
    /**
118
     * Saves the LAN interface configurations.
119
     *
120
     * This method iterates through each existing LAN interface, updates its configuration based on the provided data,
121
     * and saves the changes. If a new interface needs to be added (specified by 'interface_0'), it creates and saves this
122
     * new interface as well. If any save operation fails, the method returns an array containing `false` and the error messages.
123
     *
124
     * @param array $data Array containing the interface configurations.
125
     *                    Expected to contain interface settings such as IP, mask, etc., and a special key 'interface_0' for new interfaces.
126
     * @return array Returns an array with a boolean success flag and an array of error messages if applicable.
127
     */
128
    private function saveLanInterfaces(array $data): array
129
    {
130
        $networkInterfaces = LanInterfaces::find();
131
132
        // Update interface settings
133
        foreach ($networkInterfaces as $eth) {
134
            $this->fillEthStructure($eth, $data);
135
            if ($eth->save() === false) {
136
                $errors = $eth->getMessages();
137
                return [false, $errors];
138
            }
139
        }
140
141
        // Save additional interface settings if it exists
142
        if ($data['interface_0'] !== '') {
143
            $eth = new LanInterfaces();
144
            $eth->id = 0;
145
            $this->fillEthStructure($eth, $data);
146
            $eth->id = null;
147
            $eth->disabled = '0';
148
            if ($eth->create() === false) {
149
                $errors = $eth->getMessages();
150
                return [false, $errors];
151
            }
152
        }
153
154
        return [true, []];
155
    }
156
157
    /**
158
     * Fills network interface settings
159
     *
160
     * @param LanInterfaces $eth
161
     * @param array $data post data
162
     */
163
    private function fillEthStructure(LanInterfaces $eth, array $data): void
164
    {
165
        $isDocker = Util::isDocker();
166
        foreach ($eth as $name => $value) {
167
            $itIsInternetInterfce = intval($eth->id) === intval($data['internet_interface']);
168
            switch ($name) {
169
                case 'topology':
170
                    if ($itIsInternetInterfce) {
171
                        $eth->$name = ($data['usenat'] === 'on') ? LanInterfaces::TOPOLOGY_PRIVATE : LanInterfaces::TOPOLOGY_PUBLIC;
172
                    } else {
173
                        $eth->$name = '';
174
                    }
175
                    break;
176
                case 'extipaddr':
177
                    if ($itIsInternetInterfce) {
178
                        if (array_key_exists($name, $data)) {
179
                            $eth->$name = ($data['usenat'] === 'on') ? $data[$name] : $data['ipaddr_' . $eth->id];
180
                        } else {
181
                            $eth->$name = $data['ipaddr_' . $eth->id];
182
                        }
183
                    } else {
184
                        $eth->$name = '';
185
                    }
186
187
                    break;
188
                case 'exthostname':
189
                    if ($itIsInternetInterfce) {
190
                        if (array_key_exists($name, $data)) {
191
                            $eth->$name = ($data['usenat'] === 'on') ? $data[$name] : $data['hostname'];
192
                        } else {
193
                            $eth->$name = $data['hostname'];
194
                        }
195
                    } else {
196
                        $eth->$name = '';
197
                    }
198
                    break;
199
                case 'dhcp':
200
                    if (array_key_exists($name . '_' . $eth->id, $data)) {
201
                        $eth->$name = ($data['dhcp_' . $eth->id]) === 'on' ? '1' : '0';
202
                    }
203
                    if ($isDocker) {
204
                        $eth->dhcp = '1';
205
                    }
206
                    break;
207
                case 'internet':
208
                    $eth->$name = $itIsInternetInterfce ? '1' : '0';
209
                    break;
210
                case 'ipaddr':
211
                case 'subnet':
212
                    $eth->$name = '';
213
                    if (array_key_exists($name . '_' . $eth->id, $data)) {
214
                        $eth->$name = ($data['dhcp_' . $eth->id]) === 'on' ? '' : $data[$name . '_' . $eth->id];
215
                    }
216
                    break;
217
                case 'interface':
218
                    if ($eth->id === 0) {
219
                        $eth->$name = LanInterfaces::findFirstById($data[$name . '_' . $eth->id])->interface;
220
                    }
221
                    break;
222
                case 'domain':
223
                case 'hostname':
224
                case 'gateway':
225
                case 'primarydns':
226
                case 'secondarydns':
227
                    if (array_key_exists($name, $data) && $itIsInternetInterfce) {
228
                        $eth->$name = $data[$name];
229
                    } else {
230
                        $eth->$name = '';
231
                    }
232
                    break;
233
                default:
234
                    if (array_key_exists($name . '_' . $eth->id, $data)) {
235
                        $eth->$name = $data[$name . '_' . $eth->id];
236
                    }
237
            }
238
        }
239
    }
240
241
    /**
242
     * Saves the NAT-related settings for external access.
243
     *
244
     * Iterates through a list of predefined setting keys related to NAT configuration (like external SIP and TLS ports),
245
     * and updates these settings with new values from the provided data. If a setting fails to save, the method returns
246
     * immediately with an error.
247
     *
248
     * @param array $data Associative array where keys are setting names and values are the new settings to be saved.
249
     * @return array Returns an array with a boolean success flag and, if unsuccessful, an array of error messages.
250
     */
251
    private function saveNatSettings(array $data): array
252
    {
253
        $messages = [];
254
        foreach ($data as $key => $value) {
255
            switch ($key) {
256
                case PbxSettings::AUTO_UPDATE_EXTERNAL_IP:
257
                    PbxSettings::setValueByKey($key, $value === 'on' ? '1' : '0', $messages);
258
                    break;
259
                case PbxSettings::EXTERNAL_SIP_PORT:
260
                    if (empty($value)) {
261
                        $value = PbxSettings::getValueByKey(PbxSettings::SIP_PORT);
262
                    }
263
                    PbxSettings::setValueByKey($key, trim($value), $messages);
264
                    break;
265
                case PbxSettings::EXTERNAL_TLS_PORT:
266
                    if (empty($value)) {
267
                        $value = PbxSettings::getValueByKey(PbxSettings::TLS_PORT);
268
                    }
269
                    PbxSettings::setValueByKey($key, trim($value), $messages);
270
                    break;
271
                default:
272
            }
273
        }
274
        $result = count($messages) === 0;
275
        return [$result, ['error' => $messages]];
276
    }
277
278
    /**
279
     * Delete a lan interface by ID
280
     *
281
     * @param string $ethId interface id
282
     */
283
    public function deleteAction(string $ethId = ''): void
284
    {
285
        $eth = LanInterfaces::findFirstById($ethId);
286
        if ($eth !== null && $eth->delete() === false) {
287
            $errors = $eth->getMessages();
288
            $this->flash->warning(implode('<br>', $errors));
289
            $this->view->success = false;
290
            return;
291
        }
292
        $this->view->success = true;
293
    }
294
}
295