Passed
Push — develop ( c1eaed...deed70 )
by Портнов
11:55 queued 13s
created

ActionHangupChan::hangupChanEndCalls()   C

Complexity

Conditions 12
Paths 74

Size

Total Lines 63
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 42
c 4
b 0
f 0
dl 0
loc 63
rs 6.9666
cc 12
nc 74
nop 4

How to fix   Long Method    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
namespace MikoPBX\Core\Workers\Libs\WorkerCallEvents;
5
6
7
use MikoPBX\Common\Models\CallDetailRecordsTmp;
8
use MikoPBX\Core\Asterisk\Configs\VoiceMailConf;
9
use MikoPBX\Core\System\Util;
10
use MikoPBX\Core\Workers\WorkerCallEvents;
11
12
class ActionHangupChan {
13
14
    public static function execute(WorkerCallEvents $worker, $data):void
15
    {
16
        $channels       = [];
17
        $transfer_calls = [];
18
19
        self::hangupChanEndCalls($worker, $data, $transfer_calls, $channels);
20
        // Проверим, возможно это обычный трансфер.
21
        CreateRowTransfer::execute($worker, 'hangup_chan', $data, $transfer_calls);
22
        self::hangupChanCheckSipTrtansfer($worker, $data, $channels);
23
24
        // Очистим память.
25
        if(isset($worker->checkChanHangupTransfer[$data['agi_channel']])){
26
            unset($worker->checkChanHangupTransfer[$data['agi_channel']]);
27
        }
28
        if(isset($worker->mixMonitorChannels[$data['agi_channel']])){
29
            unset($worker->mixMonitorChannels[$data['agi_channel']]);
30
        }
31
32
    }
33
34
    /**
35
     * Обработка события уничтожения канала.
36
     * @param       $worker
37
     * @param array $data
38
     * @param array $transfer_calls
39
     * @param array $channels
40
     */
41
    private static function hangupChanEndCalls($worker, array $data, array &$transfer_calls, array &$channels):void{
42
        $filter         = [
43
            'linkedid=:linkedid: AND endtime = "" AND (src_chan=:src_chan: OR dst_chan=:dst_chan:)',
44
            'bind' => [
45
                'linkedid' => $data['linkedid'],
46
                'src_chan' => $data['agi_channel'],
47
                'dst_chan' => $data['agi_channel'],
48
            ],
49
        ];
50
        /** @var CallDetailRecordsTmp $m_data */
51
        /** @var CallDetailRecordsTmp $row */
52
        $m_data = CallDetailRecordsTmp::find($filter);
53
        $countRows = count($m_data->toArray());
54
        foreach ($m_data as $row) {
55
            $vmState = $data['VMSTATUS']??'';
56
            if($row->dst_num === VoiceMailConf::VOICE_MAIL_EXT && $vmState !== 'FAILED'){
57
                // Этот вызов будет заверщен событием voicemail_end
58
                continue;
59
            }
60
            if ($row->transfer === '1' && !empty($row->dst_chan)) {
61
                // Обязательно канал назначения не должен быть пустым.
62
                // Иначе это не переадресация.
63
                $transfer_calls[] = $row->toArray();
64
            }
65
            if ($row->dialstatus === 'ORIGINATE') {
66
                $row->writeAttribute('dialstatus', '');
67
                if($row->answer === ''){
68
                    $newId = $row->linkedid.'_'.$row->src_num.'_'.substr($row->src_chan, strpos($row->src_chan,'-') +1);
69
                    $row->writeAttribute('UNIQUEID', $newId);
70
                }
71
            }
72
            $row->writeAttribute('endtime', $data['end']);
73
            $row->writeAttribute('transfer', 0);
74
            if ($data['dialstatus'] !== '') {
75
                if ($data['dialstatus'] === 'ORIGINATE') {
76
                    $row->writeAttribute('dst_chan', '');
77
                }
78
                $row->writeAttribute('dialstatus', $data['dialstatus']);
79
            }
80
            $res = $row->update();
81
            if ( ! $res) {
82
                Util::sysLogMsg('Action_hangup_chan', implode(' ', $row->getMessages()), LOG_DEBUG);
83
            }
84
85
            if ($row->src_chan !== $data['agi_channel']) {
86
                $channels[] = [
87
                    'chan' => $row->src_chan,
88
                    'did'  => $row->did,
89
                    'num'  => $row->src_num,
90
                    'out'  => true,
91
                ];
92
            } else {
93
                $worker->StopMixMonitor($row->dst_chan);
94
                $channels[] = [
95
                    'chan' => $row->dst_chan,
96
                    'did'  => $row->did,
97
                    'num'  => $row->dst_num,
98
                    'out'  => false,
99
                ];
100
            }
101
        }
102
103
        self::regMissedCall($data, $countRows);
104
    }
105
106
    /**
107
     * Если hangup_chan единственный event.
108
     * @param array $data
109
     * @param int   $tmpCdrCount
110
     */
111
    private static function regMissedCall(array $data, int $tmpCdrCount):void
112
    {
113
        if($tmpCdrCount > 0 || $data['did'] === ''){
114
            return;
115
        }
116
        if(stripos($data['agi_channel'], 'local/') !== false){
117
            // Локальные каналы не логируем как пропущенные.
118
            return;
119
        }
120
        $filter         = [
121
            'linkedid=:linkedid: AND (src_chan=:src_chan: OR dst_chan=:dst_chan:)',
122
            'bind' => [
123
                'linkedid' => $data['linkedid'],
124
                'src_chan' => $data['agi_channel'],
125
                'dst_chan' => $data['agi_channel'],
126
            ],
127
        ];
128
        $m_data = CallDetailRecordsTmp::findFirst($filter);
129
        if($m_data !== null){
130
            return;
131
        }
132
        if(empty($data['UNIQUEID'])){
133
            $data['UNIQUEID'] = $data['agi_threadid'];
134
        }
135
        $time = (float)str_replace('mikopbx-', '', $data['linkedid']);
136
        $data['start']   = date("Y-m-d H:i:s.v", $time);
0 ignored issues
show
Bug introduced by
$time of type double is incompatible with the type integer|null expected by parameter $timestamp of date(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        $data['start']   = date("Y-m-d H:i:s.v", /** @scrutinizer ignore-type */ $time);
Loading history...
137
        $data['endtime'] = $data['end'];
138
139
        InsertDataToDB::execute($data);
140
    }
141
142
    /**
143
     * Проверяем на SIP трансфер.
144
     * @param $worker
145
     * @param $data
146
     * @param $channels
147
     */
148
    private static function hangupChanCheckSipTrtansfer($worker, $data, $channels):void{
149
        $not_local = (stripos($data['agi_channel'], 'local/') === false);
150
        if($not_local === false || $data['OLD_LINKEDID'] !== $data['linkedid']) {
151
            return;
152
        }
153
        $am = Util::getAstManager('off');
154
        $active_chans = $am->GetChannels(false);
155
        // Намек на SIP трансфер.
156
        foreach ($channels as $data_chan) {
157
            if ( ! in_array($data_chan['chan'], $active_chans, true)) {
158
                // Вызов уже завершен. Не интересно.
159
                continue;
160
            }
161
            $BRIDGEPEER = $am->GetVar($data_chan['chan'], 'BRIDGEPEER', null, false);
162
            if ( !is_string($BRIDGEPEER) || ! in_array($BRIDGEPEER, $active_chans, true)) {
163
                // Вызов уже завершен. Не интересно.
164
                continue;
165
            }
166
167
            $linkedid = $am->GetVar($data_chan['chan'], 'CHANNEL(linkedid)', null, false);
168
            if ( empty($linkedid) || $linkedid === $data['linkedid']) {
169
                continue;
170
            }
171
172
            $CALLERID = $am->GetVar($BRIDGEPEER, 'CALLERID(num)', null, false);
173
            $n_data['action']        = 'sip_transfer';
174
            $n_data['src_chan']      = $data_chan['out'] ? $data_chan['chan'] : $BRIDGEPEER;
175
            $n_data['src_num']       = $data_chan['out'] ? $data_chan['num'] : $CALLERID;
176
            $n_data['dst_chan']      = $data_chan['out'] ? $BRIDGEPEER : $data_chan['chan'];
177
            $n_data['dst_num']       = $data_chan['out'] ? $CALLERID : $data_chan['num'];
178
            $n_data['start']         = date('Y-m-d H:i:s');
179
            $n_data['answer']        = date('Y-m-d H:i:s');
180
            $n_data['linkedid']      = $linkedid;
181
            $n_data['UNIQUEID']      = $data['linkedid'] . Util::generateRandomString();
182
            $n_data['transfer']      = '0';
183
            $n_data['recordingfile'] = $worker->MixMonitor($n_data['dst_chan'], $n_data['UNIQUEID']);
184
            $n_data['did']           = $data_chan['did'];
185
186
            InsertDataToDB::execute($n_data);
187
            $filter = [
188
                'linkedid=:linkedid:',
189
                'bind' => ['linkedid' => $data['linkedid']],
190
            ];
191
            $m_data = CallDetailRecordsTmp::find($filter);
192
            foreach ($m_data as $row) {
193
                $row->writeAttribute('linkedid', $linkedid);
194
                $row->save();
195
            }
196
197
            /**
198
             * Отправка UserEvent
199
             */
200
            $AgiData = base64_encode(json_encode($n_data));
201
            $am->UserEvent('CdrConnector', ['AgiData' => $AgiData]);
202
        } // Обход текущих каналов.
203
    }
204
}