Passed
Push — develop ( a56058...ddfce4 )
by Nikolay
04:39
created

SaveRecordAction::deleteMobileNumber()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 15
rs 9.9666
cc 2
nc 2
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\PBXCoreREST\Lib\Extensions;
21
22
use MikoPBX\Common\Handlers\CriticalErrorsHandler;
23
use MikoPBX\Common\Models\ExtensionForwardingRights;
24
use MikoPBX\Common\Models\Extensions;
25
use MikoPBX\Common\Models\ExternalPhones;
26
use MikoPBX\Common\Models\PbxSettings;
27
use MikoPBX\Common\Models\PbxSettingsConstants;
28
use MikoPBX\Common\Models\Sip;
29
use MikoPBX\Common\Models\Users;
30
use MikoPBX\Common\Providers\MainDatabaseProvider;
31
use MikoPBX\Common\Providers\ModelsMetadataProvider;
32
use MikoPBX\PBXCoreREST\Lib\PBXApiResult;
33
use Phalcon\Di;
34
use Phalcon\Di\Injectable;
35
use Phalcon\Security\Random;
36
37
/**
38
 * Class SaveRecord
39
 * Provides methods to save extension records with associated entities.
40
 *
41
 * @package MikoPBX\PBXCoreREST\Lib\Extensions
42
 */
43
class SaveRecordAction extends Injectable
44
{
45
    /**
46
     * Saves a record with associated entities.
47
     *
48
     * @param array $data Data to be saved.
49
     * @return PBXApiResult Result of the save operation.
50
     */
51
    public static function main(array $data): PBXApiResult
52
    {
53
        // Initialize the result object
54
        $res = new PBXApiResult();
55
        $res->processor = __METHOD__;
56
        $res->success = true;
57
58
        $di = Di::getDefault();
59
        $db = $di->get(MainDatabaseProvider::SERVICE_NAME);
60
        $db->begin();
61
62
        $dataStructure = new DataStructure($data);
63
64
        // Save user entity
65
        list($userEntity, $res->success) = self::saveUser($dataStructure);
66
        if (!$res->success) {
67
            // Handle errors and rollback
68
            $res->messages['error'][] = $userEntity->getMessages();
69
            $db->rollback();
70
            return $res;
71
        } else {
72
            $dataStructure->user_id = $userEntity->id;
73
        }
74
75
        // Save extension entity
76
        list($extension, $res->success) = self::saveExtension($dataStructure, false);
77
        if (!$res->success) {
78
            // Handle errors and rollback
79
            $res->messages['error'][] = implode($extension->getMessages());
80
            $db->rollback();
81
            return $res;
82
        }
83
84
        // Save SIP entity
85
        list($sipEntity, $res->success) = self::saveSip($dataStructure);
86
        if (!$res->success) {
87
            // Handle errors and rollback
88
            $res->messages['error'][] = implode($sipEntity->getMessages());
89
            $db->rollback();
90
            return $res;
91
        }
92
93
        // Save forwarding rights entity
94
        list($fwdEntity, $res->success) = self::saveForwardingRights($dataStructure);
95
        if (!$res->success) {
96
            // Handle errors and rollback
97
            $res->messages['error'][] = implode($fwdEntity->getMessages());
98
            $db->rollback();
99
            return $res;
100
        }
101
102
        // Check mobile number presence and save related entities
103
        if (!empty($dataStructure->mobile_number)) {
104
105
            // Save mobile extension
106
            list($mobileExtension, $res->success) = self::saveExtension($dataStructure, true);
107
            if (!$res->success) {
108
                // Handle errors and rollback
109
                $res->messages['error'][] = implode($mobileExtension->getMessages());
110
                $db->rollback();
111
                return $res;
112
            }
113
114
            // Save ExternalPhones for mobile number
115
            list($externalPhone, $res->success) = self::saveExternalPhones($dataStructure);
116
            if (!$res->success) {
117
                // Handle errors and rollback
118
                $res->messages['error'][] = implode($externalPhone->getMessages());
119
                $db->rollback();
120
                return $res;
121
            }
122
        } else {
123
            // Delete mobile number if it was associated with the user
124
            list($deletedMobileNumber, $res->success) = self::deleteMobileNumber($userEntity);
125
            if (!$res->success) {
126
                $res->messages['error'][] = implode($deletedMobileNumber->getMessages());
127
                $db->rollback();
128
                return $res;
129
            }
130
        }
131
        $db->commit();
132
133
        $res = GetRecordAction::main($extension->id);
134
        $res->processor = __METHOD__;
135
        return $res;
136
    }
137
138
    /**
139
     * Save parameters to the Users table
140
     *
141
     * @param DataStructure $dataStructure The data structure containing the input data.
142
     * @return array An array containing the saved Users entity and the save result.
143
     */
144
    private static function saveUser(DataStructure $dataStructure): array
145
    {
146
        $userEntity = Users::findFirstById($dataStructure->user_id);
147
        if ($userEntity === null) {
148
            $userEntity = new Users();
149
        }
150
151
        // Fill in user parameters
152
        $metaData = Di::getDefault()->get(ModelsMetadataProvider::SERVICE_NAME);
153
        foreach ($metaData->getAttributes($userEntity) as $name) {
154
            switch ($name) {
155
                case 'language':
156
                    $userEntity->$name = PbxSettings::getValueByKey(PbxSettingsConstants::PBX_LANGUAGE);
157
                    break;
158
                default:
159
                    $propertyKey = 'user_' . $name;
160
                    if (property_exists($dataStructure, $propertyKey)) {
161
                        $userEntity->$name = $dataStructure->$propertyKey;
162
                    }
163
            }
164
        }
165
166
        $result = $userEntity->save();
167
        return [$userEntity, $result];
168
    }
169
170
    /**
171
     * Save the extension for a user.
172
     * @param DataStructure $dataStructure The data structure containing the input data.
173
     * @param bool $isMobile Flag indicating if it's a mobile extension.
174
     *
175
     * @return array An array containing the saved Extensions entity and the save result.
176
     */
177
    private static function saveExtension(DataStructure $dataStructure, bool $isMobile = false): array
178
    {
179
        $parameters = [];
180
        $parameters['conditions'] = 'type=:type: AND is_general_user_number = "1" AND userid=:userid:';
181
        $parameters['bind']['type'] = $isMobile ? Extensions::TYPE_EXTERNAL : Extensions::TYPE_SIP;
182
        $parameters['bind']['userid'] = $dataStructure->user_id ;
183
184
        $extension = Extensions::findFirst($parameters);
185
        if ($extension === null) {
186
            $extension = new Extensions();
187
        }
188
        $metaData = Di::getDefault()->get(ModelsMetadataProvider::SERVICE_NAME);
189
        foreach ($metaData->getAttributes($extension) as $name) {
190
            switch ($name) {
191
                case 'id':
192
                    // Skip saving the 'id' field
193
                    break;
194
                case 'type':
195
                    // Set the 'type' based on the value of $isMobile
196
                    $extension->$name = $isMobile ? Extensions::TYPE_EXTERNAL : Extensions::TYPE_SIP;
197
                    break;
198
                case 'callerid':
199
                    // Sanitize the caller ID based on 'user_username' on model before save function
200
                    $extension->$name = $dataStructure->user_username;
201
                    break;
202
                case 'userid':
203
                    // Set 'userid' to the ID of the user entity
204
                    $extension->$name = $dataStructure->user_id;
205
                    break;
206
                case 'number':
207
                    // Set 'number' based on the value of mobile_number or number
208
                    $extension->$name = $isMobile ? $dataStructure->mobile_number : $dataStructure->number;
209
                    break;
210
                default:
211
                    if (property_exists($dataStructure, $name)) {
212
                        // Set other fields based on the values in $data
213
                        $extension->$name = $dataStructure->$name;
214
                    }
215
            }
216
        }
217
        $result = $extension->save();
218
        return [$extension, $result];
219
    }
220
221
    /**
222
     * Save the SIP entity with the provided data.
223
     *
224
     * @param DataStructure $dataStructure The data structure containing the input data.
225
     * @return array An array containing the saved SIP entity and the save result.
226
     */
227
    private static function saveSip(DataStructure $dataStructure): array
228
    {
229
        $sipEntity = SIP::findFirstByUniqid($dataStructure->sip_uniqid);
230
        if ($sipEntity === null) {
231
            $sipEntity = new SIP();
232
        }
233
234
        $metaData = Di::getDefault()->get(ModelsMetadataProvider::SERVICE_NAME);
235
        foreach ($metaData->getAttributes($sipEntity) as $name) {
236
            switch ($name) {
237
                case 'weakSecret':
238
                    $sipEntity->$name = '0';
239
                    break;
240
                case 'networkfilterid':
241
                    if ($dataStructure->sip_networkfilterid === 'none') {
242
                        $sipEntity->$name = null;
243
                    } else {
244
                        $sipEntity->$name = $dataStructure->sip_networkfilterid;
245
                    }
246
                    break;
247
                case 'extension':
248
                    // Set 'extension' based on the value of number
249
                    $sipEntity->$name = $dataStructure->number;
250
                    break;
251
                case 'description':
252
                    // Set 'description' based on the value of user_username
253
                    $sipEntity->$name = $dataStructure->user_username;
254
                    break;
255
                case 'manualattributes':
256
                    // Set 'manualattributes' using the value of sip_manualattributes
257
                    $sipEntity->setManualAttributes($dataStructure->sip_manualattributes);
258
                    break;
259
                default:
260
                    $propertyKey = 'sip_' . $name;
261
                    if (property_exists($dataStructure, $propertyKey)) {
262
                        // Set other fields based on the other fields in $dataStructure
263
                        $sipEntity->$name = $dataStructure->$propertyKey;
264
                    }
265
            }
266
        }
267
268
        $result = $sipEntity->save();
269
        return [$sipEntity, $result];
270
    }
271
272
    /**
273
     * Save the ExtensionForwardingRights entity with the provided data.
274
     *
275
     * @param DataStructure $dataStructure The data structure containing the input data.
276
     * @return array An array containing the saved ExtensionForwardingRights entity and the save result.
277
     */
278
    private static function saveForwardingRights(DataStructure $dataStructure): array
279
    {
280
        $forwardingRight = ExtensionForwardingRights::findFirstByExtension($dataStructure->number);
281
        if ($forwardingRight === null) {
282
            $forwardingRight = new ExtensionForwardingRights();
283
        }
284
        $metaData = Di::getDefault()->get(ModelsMetadataProvider::SERVICE_NAME);
285
        foreach ($metaData->getAttributes($forwardingRight) as $name) {
286
            switch ($name) {
287
                case 'extension':
288
                    // Set 'extension' based on the value of number
289
                    $forwardingRight->$name = $dataStructure->number;
290
                    break;
291
                case 'ringlength':
292
                    $forwardingRight->ringlength = 0;
293
                    if (!empty($dataStructure->fwd_ringlength)) {
294
                        $forwardingRight->ringlength = $dataStructure->fwd_ringlength;
295
                    } elseif (!empty($dataStructure->fwd_forwarding)) {
296
                        $forwardingRight->ringlength = 45;
297
                    }
298
                    break;
299
                default:
300
                    $propertyKey = 'fwd_' . $name;
301
                    if (property_exists($dataStructure, $propertyKey)) {
302
                        // Set other fields based on the other fields in $dataStructure
303
                        $forwardingRight->$name = $dataStructure->$propertyKey === -1 ? '' : $dataStructure->$propertyKey;
304
                    }
305
            }
306
        }
307
        $result = $forwardingRight->save();
308
        return [$forwardingRight, $result];
309
    }
310
311
    /**
312
     * Save parameters to the ExternalPhones table for a mobile number.
313
     *
314
     * @param DataStructure $dataStructure The data structure containing the input data.
315
     * @return array An array containing the saved ExternalPhones entity and the save result.
316
     */
317
    private static function saveExternalPhones(DataStructure $dataStructure): array
318
    {
319
        $externalPhone = ExternalPhones::findFirstByUniqid($dataStructure->mobile_uniqid);
320
        if ($externalPhone === null) {
321
            $externalPhone = new ExternalPhones();
322
        }
323
        $metaData = Di::getDefault()->get(ModelsMetadataProvider::SERVICE_NAME);
324
        foreach ($metaData->getAttributes($externalPhone) as $name) {
325
            switch ($name) {
326
                case 'extension':
327
                    $externalPhone->$name = $dataStructure->mobile_number;
328
                    break;
329
                case 'description':
330
                    $externalPhone->$name = $dataStructure->user_username;
331
                    break;
332
                default:
333
                    $propertyKey = 'mobile_' . $name;
334
                    if (property_exists($dataStructure, $propertyKey)) {
335
                        // Set other fields based on the other fields in $dataStructure
336
                        $externalPhone->$name = $dataStructure->$propertyKey;
337
                    }
338
            }
339
        }
340
341
        $result = $externalPhone->save();
342
        return [$externalPhone, $result];
343
    }
344
345
    /**
346
     * Delete a mobile number associated with a user.
347
     *
348
     * @param Users $userEntity The user entity.
349
     * @return array An array containing the deleted mobile number entity and the deletion result.
350
     */
351
    private static function deleteMobileNumber(Users $userEntity): array
352
    {
353
        $parameters = [
354
            'conditions' => 'type="' . Extensions::TYPE_EXTERNAL . '" AND is_general_user_number = "1" AND userid=:userid:',
355
            'bind' => [
356
                'userid' => $userEntity->id,
357
            ],
358
        ];
359
        $deletedMobileNumber = Extensions::findFirst($parameters);
360
        $result = true;
361
        if ($deletedMobileNumber !== null) {
362
            // Delete the mobile number entity if found
363
            $result = $deletedMobileNumber->delete();
364
        }
365
        return [$deletedMobileNumber, $result];
366
    }
367
}