Passed
Push — develop ( 8d717c...9d129a )
by Портнов
05:17 queued 10s
created

ExtensionsConf::generateInternal()   C

Complexity

Conditions 8
Paths 54

Size

Total Lines 140
Code Lines 96

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 96
c 2
b 0
f 0
dl 0
loc 140
rs 6.8428
cc 8
nc 54
nop 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
A ExtensionsConf::generateInternalTransfer() 0 19 5
A ExtensionsConf::generatePublicContext() 0 20 4
A ExtensionsConf::generateSipHints() 0 11 3

How to fix   Long Method   

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
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 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\Core\Asterisk\Configs;
21
22
use MikoPBX\Common\Models\{Iax, IncomingRoutingTable, OutgoingRoutingTable, OutWorkTimes, Providers, Sip, SoundFiles};
23
use MikoPBX\AdminCabinet\Forms\OutgoingRouteEditForm;
24
use MikoPBX\Common\Providers\PBXConfModulesProvider;
25
use MikoPBX\Core\Asterisk\Configs\Generators\Extensions\IncomingContexts;
26
use MikoPBX\Core\Asterisk\Configs\Generators\Extensions\InternalContexts;
27
use MikoPBX\Core\Asterisk\Configs\Generators\Extensions\OutgoingContext;
28
use MikoPBX\Modules\Config\ConfigClass;
29
use MikoPBX\Core\System\{MikoPBXConfig, Storage, Util};
30
use Phalcon\Di;
31
32
class ExtensionsConf extends ConfigClass
33
{
34
    protected string $description = 'extensions.conf';
35
36
    /**
37
     * Sorts array by priority field
38
     *
39
     * @param $a
40
     * @param $b
41
     *
42
     * @return int|null
43
     */
44
    public static function sortArrayByPriority(array $a, array $b): int
45
    {
46
        $aPriority = (int)($a['priority'] ?? 0);
47
        $bPriority = (int)($b['priority'] ?? 0);
48
        if ($aPriority === $bPriority) {
49
            return 0;
50
        }
51
52
        return ($aPriority < $bPriority) ? -1 : 1;
53
    }
54
55
    /**
56
     * Основной генератор extensions.conf
57
     */
58
    protected function generateConfigProtected(): void
59
    {
60
        /** @scrutinizer ignore-call */
61
        $additionalModules = $this->di->getShared(PBXConfModulesProvider::SERVICE_NAME);
62
        $conf              = "[globals] \n" .
63
            "TRANSFER_CONTEXT=internal-transfer; \n";
64
        if ($this->generalSettings['PBXRecordCalls'] === '1') {
65
            $conf .= "MONITOR_DIR=" . Storage::getMonitorDir() . " \n";
66
            $conf .= "MONITOR_STEREO=" . $this->generalSettings['PBXSplitAudioThread'] . " \n";
67
        }
68
        foreach ($additionalModules as $appClass) {
69
            $addition = $appClass->extensionGlobals();
70
            if ( ! empty($addition)) {
71
                $conf .= $appClass->confBlockWithComments($addition);
72
            }
73
        }
74
        $conf .= "\n";
75
        $conf .= "\n";
76
        $conf .= "[general] \n";
77
78
        // Контекст для внутренних вызовов.
79
        $conf .= InternalContexts::generate();
80
        // Создаем диалплан внутренних учеток.
81
        $this->generateOtherExten($conf);
82
        // Контекст для внутренних переадресаций.
83
        $this->generateInternalTransfer($conf);
84
        // Создаем контекст хинтов.
85
        $this->generateSipHints($conf);
86
        // Создаем контекст (исходящие звонки).
87
        $conf .= OutgoingContext::generate();
88
89
        // Описываем контекст для публичных входящих.
90
        $this->generatePublicContext($conf);
91
92
        Util::fileWriteContent($this->config->path('asterisk.astetcdir') . '/extensions.conf', $conf);
93
    }
94
95
    /**
96
     * Генератор прочих контекстов.
97
     *
98
     * @param $conf
99
     */
100
    private function generateOtherExten(&$conf): void
101
    {
102
        $extension = 'X!';
103
        // Контекст для AMI originate. Без него отображается не корректный CallerID.
104
        $conf .= '[sipregistrations]' . "\n\n";
105
106
        $conf .= '[messages]' . "\n" .
107
            'exten => _' . $extension . ',1,MessageSend(sip:${EXTEN},"${CALLERID(name)}"${MESSAGE(from)})' . "\n\n";
108
109
        $conf .= '[internal-originate]' . " \n";
110
        $conf .= 'exten => _' . $extension . ',1,NoOP(Hint ${HINT} exten ${EXTEN} )' . " \n";
111
        $conf .= '; Если это originate, то скроем один CDR.' . " \n\t";
112
        $conf .= 'same => n,ExecIf($["${pt1c_cid}x" != "x"]?Set(CALLERID(num)=${pt1c_cid}))' . " \n\t";
113
114
        $conf .= 'same => n,ExecIf($["${CUT(CHANNEL,\;,2)}" == "2"]?Set(__PT1C_SIP_HEADER=${SIPADDHEADER}))' . " \n\t";
115
        $conf .= 'same => n,ExecIf($["${peer_mobile}x" != "x"]?Set(ADDITIONAL_PEER=&Local/${peer_mobile}@outgoing/n))' . " \n\t";
116
117
        // Описываем возможность прыжка в пользовательский sub контекст.
118
        $conf .= 'same => n,GosubIf($["${DIALPLAN_EXISTS(${CONTEXT}-custom,${EXTEN},1)}" == "1"]?${CONTEXT}-custom,${EXTEN},1)' . "\n\t";
119
        $conf .= 'same => n,Dial(Local/${EXTEN}@internal-users/n${ADDITIONAL_PEER},60,TteKkHhb(originate_create_chan,s,1))' . " \n\n";
120
121
        $conf .= '[originate_create_chan]' . " \n";
122
        $conf .= 'exten => s,1,Set(CHANNEL(hangup_handler_wipe)=hangup_handler,s,1)' . "\n\t";
123
        $conf .= 'same => n,return' . " \n\n";
124
125
        $conf .= '[dial_create_chan]' . " \n";
126
        $conf .= 'exten => s,1,Gosub(lua_${ISTRANSFER}dial_create_chan,${EXTEN},1)' . "\n\t";
127
        $conf .= 'same => n,Set(pt1c_is_dst=1)' . " \n\t";
128
        $conf .= 'same => n,ExecIf($["${PT1C_SIP_HEADER}x" != "x"]?Set(PJSIP_HEADER(add,${CUT(PT1C_SIP_HEADER,:,1)})=${CUT(PT1C_SIP_HEADER,:,2)}))' . " \n\t";
129
        $conf .= 'same => n,Set(__PT1C_SIP_HEADER=${UNDEFINED})' . " \n\t";
130
        $conf .= 'same => n,Set(CHANNEL(hangup_handler_wipe)=hangup_handler,s,1)' . " \n\t";
131
        $conf .= 'same => n,return' . " \n\n";
132
133
        $conf .= '[hangup_handler]' . "\n";
134
        $conf .= 'exten => s,1,NoOp(--- hangup - ${CHANNEL} ---)' . "\n\t";
135
        $conf .= 'same => n,Gosub(hangup_chan,${EXTEN},1)' . "\n\t";
136
137
        $conf .= 'same => n,return' . "\n\n";
138
139
        $conf .= '[set_orign_chan]' . "\n";
140
        $conf .= 'exten => s,1,Wait(0.2)' . "\n\t";
141
        $conf .= 'same => n,Set(pl=${IF($["${CHANNEL:-1}" == "1"]?2:1)})' . "\n\t";
142
        $conf .= 'same => n,Set(orign_chan=${IMPORT(${CUT(CHANNEL,\;,1)}\;${pl},BRIDGEPEER)})' . "\n\t";
143
        $conf .= 'same => n,ExecIf($[ "${orign_chan}x" == "x" ]?Set(orign_chan=${IMPORT(${CUT(CHANNEL,\;,1)}\;${pl},FROM_CHAN)}))' . "\n\t";
144
        $conf .= 'same => n,ExecIf($[ "${QUEUE_SRC_CHAN}x" != "x" ]?Set(__QUEUE_SRC_CHAN=${orign_chan}))' . "\n\t";
145
        $conf .= 'same => n,ExecIf($[ "${QUEUE_SRC_CHAN:0:5}" == "Local" ]?Set(__QUEUE_SRC_CHAN=${FROM_CHAN}))' . "\n\t";
146
        $conf .= 'same => n,ExecIf($[ "${FROM_CHAN}x" == "x" ]?Set(__FROM_CHAN=${IMPORT(${CUT(CHANNEL,\;,1)}\;${pl},BRIDGEPEER)}))' . "\n\t";
147
        $conf .= 'same => n,return' . "\n\n";
148
149
        $conf .= '[playback]' . "\n";
150
        $conf .= 'exten => s,1,Playback(hello_demo,noanswer)' . "\n\t";
151
        $conf .= 'same => n,ExecIf($["${SRC_BRIDGE_CHAN}x" == "x"]?Wait(30))' . "\n\t";
152
        $conf .= 'same => n,Wait(0.3)' . "\n\t";
153
        $conf .= 'same => n,Bridge(${SRC_BRIDGE_CHAN},kKTthH)' . "\n\n";
154
155
        $conf .= 'exten => h,1,ExecIf($["${ISTRANSFER}x" != "x"]?Gosub(${ISTRANSFER}dial_hangup,${EXTEN},1))' . "\n\n";
156
157
        // TODO / Добавление / удаление префиксов на входящий callerid.
158
        $conf .= '[add-trim-prefix-clid]' . "\n";
159
        $conf .= 'exten => _.!,1,NoOp(--- Incoming call from ${CALLERID(num)} ---)' . "\n\t";
160
        $conf .= 'same => n,GosubIf($["${DIALPLAN_EXISTS(${CONTEXT}-custom,${EXTEN},1)}" == "1"]?${CONTEXT}-custom,${EXTEN},1)' . "\n\t";
161
        // Отсекаем "+".
162
        // $conf.= 'same => n,ExecIf( $["${CALLERID(num):0:1}" == "+"]?Set(CALLERID(num)=${CALLERID(num):1}))'."\n\t";
163
        // Отсекаем "7" и добавляем "8".
164
        // $conf.= 'same => n,ExecIf( $["${REGEX("^7[0-9]+" ${CALLERID(num)})}" == "1"]?Set(CALLERID(num)=8${CALLERID(num):1}))'."\n\t";
165
        $conf .= 'same => n,return' . "\n\n";
166
    }
167
168
    /**
169
     * Генератор контекста для переадресаций.
170
     *
171
     * @param $conf
172
     */
173
    private function generateInternalTransfer(&$conf): void
174
    {
175
        $additionalModules = $this->di->getShared(PBXConfModulesProvider::SERVICE_NAME);
176
        $conf              .= "[internal-transfer] \n";
177
178
        foreach ($additionalModules as $appClass) {
179
            $addition = $appClass->getIncludeInternalTransfer();
180
            if ( ! empty($addition)) {
181
                $conf .= $appClass->confBlockWithComments($addition);
182
            }
183
        }
184
185
        foreach ($additionalModules as $appClass) {
186
            $addition = $appClass->extensionGenInternalTransfer();
187
            if ( ! empty($addition)) {
188
                $conf .= $appClass->confBlockWithComments($addition);
189
            }
190
        }
191
        $conf .= 'exten => h,1,Gosub(transfer_dial_hangup,${EXTEN},1)' . "\n\n";
192
    }
193
194
    /**
195
     * Генератор хинтов SIP.
196
     *
197
     * @param $conf
198
     */
199
    private function generateSipHints(&$conf): void
200
    {
201
        $additionalModules = $this->di->getShared(PBXConfModulesProvider::SERVICE_NAME);
202
        $conf              .= "[internal-hints] \n";
203
        foreach ($additionalModules as $appClass) {
204
            $addition = $appClass->extensionGenHints();
205
            if ( ! empty($addition)) {
206
                $conf .= $appClass->confBlockWithComments($addition);
207
            }
208
        }
209
        $conf .= "\n\n";
210
    }
211
212
    /**
213
     * Контекст для входящих внешних звонков без авторизации.
214
     *
215
     * @param $conf
216
     */
217
    public function generatePublicContext(&$conf): void
218
    {
219
        $additionalModules = $this->di->getShared(PBXConfModulesProvider::SERVICE_NAME);
220
        $conf              .= "\n";
221
        $conf              .= IncomingContexts::generate('none');
222
        $conf              .= "[public-direct-dial] \n";
223
        foreach ($additionalModules as $appClass) {
224
            if ($appClass instanceof $this) {
225
                continue;
226
            }
227
            $appClass->generatePublicContext($conf);
228
        }
229
        $filter = ["provider IS NULL AND priority<>9999"];
230
231
        /**
232
         * @var array
233
         */
234
        $m_data = IncomingRoutingTable::find($filter);
235
        if (count($m_data->toArray()) > 0) {
236
            $conf .= 'include => none-incoming';
237
        }
238
    }
239
240
}