Passed
Push — develop ( 47399f...282944 )
by Nikolay
05:15
created

RestoreDefaultSettings::createParkingSlots()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 22
c 1
b 0
f 0
dl 0
loc 31
rs 9.2568
cc 5
nc 9
nop 0
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\System;
21
22
use MikoPBX\Common\Models\AsteriskManagerUsers;
23
use MikoPBX\Common\Models\CallQueueMembers;
24
use MikoPBX\Common\Models\CallQueues;
25
use MikoPBX\Common\Models\CustomFiles;
26
use MikoPBX\Common\Models\ExtensionForwardingRights;
27
use MikoPBX\Common\Models\Extensions;
28
use MikoPBX\Common\Models\FirewallRules;
29
use MikoPBX\Common\Models\Iax;
30
use MikoPBX\Common\Models\IncomingRoutingTable;
31
use MikoPBX\Common\Models\IvrMenu;
32
use MikoPBX\Common\Models\IvrMenuActions;
33
use MikoPBX\Common\Models\NetworkFilters;
34
use MikoPBX\Common\Models\OutgoingRoutingTable;
35
use MikoPBX\Common\Models\OutWorkTimes;
36
use MikoPBX\Common\Models\PbxExtensionModules;
37
use MikoPBX\Common\Models\PbxSettings;
38
use MikoPBX\Common\Models\PbxSettingsConstants;
39
use MikoPBX\Common\Models\Sip;
40
use MikoPBX\Common\Models\SoundFiles;
41
use MikoPBX\Common\Models\Users;
42
use MikoPBX\Core\Asterisk\CdrDb;
43
use MikoPBX\Core\System\PBX;
44
use MikoPBX\Core\System\Processes;
45
use MikoPBX\Core\System\Upgrade\UpdateDatabase;
46
use MikoPBX\Core\System\Util;
47
use MikoPBX\Modules\PbxExtensionUtils;
48
use MikoPBX\PBXCoreREST\Lib\PBXApiResult;
49
use Phalcon\Di;
50
51
/**
52
 * Returns MikoPBX into default settings stage without any extensions, providers, cdr and sound files
53
 *
54
 * @package MikoPBX\PBXCoreREST\Lib\System
55
 */
56
class RestoreDefaultSettings extends \Phalcon\Di\Injectable
57
{
58
    /**
59
     * Restore default system settings.
60
     *
61
     * @return PBXApiResult An object containing the result of the API call.
62
     */
63
    public static function main(): PBXApiResult
64
    {
65
        $res            = new PBXApiResult();
66
        $res->processor = __METHOD__;
67
        $di             = DI::getDefault();
68
        if ($di === null) {
69
            $res->messages[] = 'Error on DI initialize';
70
            return $res;
71
        }
72
        $rm     = Util::which('rm');
73
        $res->success = true;
74
75
        // Change incoming rule to default action
76
        IncomingRoutingTable::resetDefaultRoute();
77
        self::preCleaning($res);
78
79
        self::cleaningMainTables($res);
80
        self::cleaningOtherExtensions($res);
81
        self::cleaningSoundFiles($res);
82
        self::cleaningBackups();
83
84
        // Delete PbxExtensions modules
85
        $records = PbxExtensionModules::find();
86
        foreach ($records as $record) {
87
            $moduleDir = PbxExtensionUtils::getModuleDir($record->uniqid);
88
            Processes::mwExec("{$rm} -rf {$moduleDir}");
89
            if ( ! $record->delete()) {
90
                $res->messages[] = $record->getMessages();
91
                $res->success    = false;
92
            }
93
        }
94
95
        // Reset PBXSettings
96
        $defaultValues = PbxSettings::getDefaultArrayValues();
97
        $fixedKeys = [
98
            'Name',
99
            'Description',
100
            PbxSettingsConstants::SSH_PASSWORD,
101
            'SSHRsaKey',
102
            'SSHDssKey',
103
            PbxSettingsConstants::SSH_AUTHORIZED_KEYS,
104
            'SSHecdsaKey',
105
            'SSHLanguage',
106
            'WEBHTTPSPublicKey',
107
            'WEBHTTPSPrivateKey',
108
            'RedirectToHttps',
109
            'PBXLanguage',
110
            'PBXVersion',
111
            'WebAdminLogin',
112
            'WebAdminPassword',
113
            'WebAdminLanguage',
114
        ];
115
        foreach ($defaultValues as $key=>$defaultValue){
116
            if (in_array($key, $fixedKeys, true)){
117
                continue;
118
            }
119
            $record = PbxSettings::findFirstByKey($key);
120
            if ($record===null){
121
                $record = new PbxSettings();
122
                $record->key = $key;
123
            }
124
            $record->value = $defaultValue;
125
        }
126
127
        // Delete CallRecords from database
128
        $cdr = CdrDb::getPathToDB();
129
        Processes::mwExec("{$rm} -rf {$cdr}*");
130
        $dbUpdater = new UpdateDatabase();
131
        $dbUpdater->updateDatabaseStructure();
132
133
        // Delete CallRecords sound files
134
        $callRecordsPath = $di->getShared('config')->path('asterisk.monitordir');
135
        if (stripos($callRecordsPath, '/storage/usbdisk1/mikopbx') !== false) {
136
            Processes::mwExec("{$rm} -rf {$callRecordsPath}/*");
137
        }
138
139
        // Recreate parking slots
140
        self::createParkingSlots();
141
142
        // Restart PBX
143
        $pbxConsole = Util::which('pbx-console');
144
        shell_exec("$pbxConsole services restart-all");
145
        PBX::coreRestart();
146
147
        return $res;
148
    }
149
150
    /**
151
     * Perform pre-cleaning operations on specific columns of certain models.
152
     *
153
     * @param PBXApiResult $res The result object to store any error messages.
154
     *
155
     * @return void
156
     */
157
    public static function preCleaning(PBXApiResult &$res):void
158
    {
159
        $preCleaning = [
160
            CallQueues::class => [
161
                'redirect_to_extension_if_empty',
162
                'redirect_to_extension_if_unanswered',
163
                'redirect_to_extension_if_repeat_exceeded'
164
            ],
165
            IvrMenu::class => [
166
                'timeout_extension'
167
            ]
168
        ];
169
        foreach ($preCleaning as $class => $columns) {
170
            $records = call_user_func([$class, 'find']);
171
            foreach ($records as $record){
172
                foreach ($columns as $column){
173
                    $record->$column = '';
174
                }
175
                if ( ! $record->save()) {
176
                    $res->messages[] = $record->getMessages();
177
                    $res->success    = false;
178
                }
179
            }
180
        }
181
    }
182
183
    /**
184
     * Perform cleaning operations on main tables.
185
     *
186
     * @param PBXApiResult $res The result object to store any error messages.
187
     *
188
     * @return void
189
     */
190
    public static function cleaningMainTables(&$res):void
191
    {
192
        // Define the models and conditions for cleaning
193
        $clearThisModels = [
194
            [ExtensionForwardingRights::class => ''],
195
            [OutWorkTimes::class => ''],
196
            [IvrMenuActions::class => ''],
197
            [CallQueueMembers::class => ''],
198
            [OutgoingRoutingTable::class => ''],
199
            [IncomingRoutingTable::class => 'id>1'],
200
            [Sip::class => ''], // All SIP providers
201
            [Iax::class => ''], // All IAX providers
202
            [AsteriskManagerUsers::class => ''],
203
            [Extensions::class => 'type="' . Extensions::TYPE_IVR_MENU . '"'],  // IVR Menu
204
            [Extensions::class => 'type="' . Extensions::TYPE_CONFERENCE . '"'],  // CONFERENCE
205
            [Extensions::class => 'type="' . Extensions::TYPE_QUEUE . '"'],  // QUEUE
206
            [Users::class => 'id>"1"'], // All except root with their extensions
207
            [CustomFiles::class => ''],
208
            [NetworkFilters::class=>'permit!="0.0.0.0/0" AND deny!="0.0.0.0/0"'] //Delete all other rules
209
        ];
210
211
        // Iterate over each model and perform deletion based on conditions
212
        foreach ($clearThisModels as $modelParams) {
213
            foreach ($modelParams as $key => $value) {
214
                $records = call_user_func([$key, 'find'], $value);
215
                if (!$records->delete()) {
216
                    // If deletion fails, add error messages to the result object
217
                    $res->messages[] = $records->getMessages();
218
                    $res->success    = false;
219
                }
220
            }
221
        }
222
        // Allow all connections for 0.0.0.0/0 in firewall rules
223
        $firewallRules = FirewallRules::find();
224
        foreach ($firewallRules as $firewallRule){
225
            $firewallRule->action = 'allow';
226
            $firewallRule->save();
227
        }
228
    }
229
230
    /**
231
     * Perform cleaning operations on other extensions.
232
     *
233
     * @param PBXApiResult $res The result object to store any error messages.
234
     *
235
     * @return void
236
     */
237
    public static function cleaningOtherExtensions(&$res):void
238
    {
239
        // Define the parameters for querying the extensions to delete
240
        $parameters     = [
241
            'conditions' => 'not number IN ({ids:array})',
242
            'bind'       => [
243
                'ids' => [
244
                    '000063',   // Reads back the extension
245
                    '000064',   // 0000MILLI
246
                    '10003246', // Echo test
247
                    'hangup',   // System Extension
248
                    'busy',     // System Extension
249
                    'did2user', // System Extension
250
                    'voicemail',// System Extension
251
                ],
252
            ],
253
        ];
254
        $stopDeleting   = false;
255
        $countRecords   = Extensions::count($parameters);
256
        $deleteAttempts = 0;
257
        while ($stopDeleting === false) {
258
            $record = Extensions::findFirst($parameters);
259
            if ($record === null) {
260
                $stopDeleting = true;
261
                continue;
262
            }
263
            if ( ! $record->delete()) {
264
                $deleteAttempts += 1;
265
            }
266
            if ($deleteAttempts > $countRecords * 10) {
267
                $stopDeleting    = true; // Prevent loop
268
                $res->messages[] = $record->getMessages();
269
            }
270
        }
271
    }
272
273
    /**
274
     * Clean up custom sound files.
275
     *
276
     * @param PBXApiResult $res The result object to store any error messages.
277
     *
278
     * @return void
279
     */
280
    public static function cleaningSoundFiles(&$res):void
281
    {
282
        $rm     = Util::which('rm');
283
        $parameters = [
284
            'conditions' => 'category = :custom:',
285
            'bind'       => [
286
                'custom' => SoundFiles::CATEGORY_CUSTOM,
287
            ],
288
        ];
289
        $records    = SoundFiles::find($parameters);
290
        foreach ($records as $record) {
291
            if (stripos($record->path, '/storage/usbdisk1/mikopbx') !== false) {
292
                Processes::mwExec("{$rm} -rf {$record->path}");
293
                if ( ! $record->delete()) {
294
                    $res->messages[] = $record->getMessages();
295
                    $res->success    = false;
296
                }
297
            }
298
        }
299
    }
300
301
    /**
302
     * Deletes main database (CF) backups
303
     * @return void
304
     */
305
    public static function cleaningBackups():void
306
    {
307
        $di = Di::getDefault();
308
        $dir = $di->getShared('config')->path('core.mediaMountPoint').'/mikopbx/backup';
309
        if(file_exists($dir)){
310
            $chAttr     = Util::which('chattr');
311
            Processes::mwExec("$chAttr -i -R $dir");
312
            $rm     = Util::which('rm');
313
            Processes::mwExec("$rm -rf $dir/*");
314
        }
315
    }
316
317
    /**
318
     * Create parking extensions.
319
     *
320
     * @return void
321
     */
322
    public static function createParkingSlots()
323
    {
324
        // Delete all parking slots
325
        $currentSlots = Extensions::findByType(Extensions::TYPE_PARKING);
326
        foreach ($currentSlots as $currentSlot) {
327
            if (!$currentSlot->delete()) {
328
                Util::sysLogMsg(
329
                    __CLASS__,
330
                    'Can not delete extenison ' . $currentSlot->number . ' from \MikoPBX\Common\Models\Extensions ' . implode($currentSlot->getMessages()),
331
                    LOG_ERR
332
                );
333
            }
334
        }
335
336
        $startSlot = intval(PbxSettings::getValueByKey(PbxSettingsConstants::PBX_CALL_PARKING_START_SLOT));
337
        $endSlot = intval(PbxSettings::getValueByKey(PbxSettingsConstants::PBX_CALL_PARKING_END_SLOT));
338
        $reservedSlot = intval(PbxSettings::getValueByKey(PbxSettingsConstants::PBX_CALL_PARKING_EXT));
339
340
        // Create an array of new numbers
341
        $numbers = range($startSlot, $endSlot);
342
        $numbers[] = $reservedSlot;
343
        foreach ($numbers as $number) {
344
            $record = new Extensions();
345
            $record->type = Extensions::TYPE_PARKING;
346
            $record->number = $number;
347
            $record->show_in_phonebook = '0';
348
            if (!$record->create()) {
349
                Util::sysLogMsg(
350
                    __CLASS__,
351
                    'Can not create extenison ' . $record->number . ' from \MikoPBX\Common\Models\Extensions ' . implode($record->getMessages()),
352
                    LOG_ERR
353
                );
354
            }
355
        }
356
    }
357
358
}