Passed
Push — develop ( d5179e...bede24 )
by Портнов
05:56 queued 11s
created

ActionHangupChan   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 26
eloc 85
c 1
b 0
f 0
dl 0
loc 144
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
C hangupChanCheckSipTrtansfer() 0 55 14
B hangupChanEndCalls() 0 50 9
A execute() 0 16 3
1
<?php
2
3
4
namespace MikoPBX\Core\Workers\Libs\WorkerCallEvents;
5
6
7
use MikoPBX\Common\Models\CallDetailRecordsTmp;
8
use MikoPBX\Core\System\Util;
9
use MikoPBX\Core\Workers\WorkerCallEvents;
10
11
class ActionHangupChan {
12
13
    public static function execute(WorkerCallEvents $worker, $data):void
14
    {
15
        $channels       = [];
16
        $transfer_calls = [];
17
18
        self::hangupChanEndCalls($worker, $data, $transfer_calls, $channels);
19
        // Проверим, возможно это обычный трансфер.
20
        CreateRowTransfer::execute($worker, 'hangup_chan', $data, $transfer_calls);
21
        self::hangupChanCheckSipTrtansfer($worker, $data, $channels);
22
23
        // Очистим память.
24
        if(isset($worker->checkChanHangupTransfer[$data['agi_channel']])){
25
            unset($worker->checkChanHangupTransfer[$data['agi_channel']]);
26
        }
27
        if(isset($worker->mixMonitorChannels[$data['agi_channel']])){
28
            unset($worker->mixMonitorChannels[$data['agi_channel']]);
29
        }
30
31
    }
32
33
    /**
34
     * Обработка события уничтожения канала.
35
     * @param       $worker
36
     * @param array $data
37
     * @param array $transfer_calls
38
     * @param array $channels
39
     */
40
    private static function hangupChanEndCalls($worker, array $data, array &$transfer_calls, array &$channels):void{
41
        $filter         = [
42
            'linkedid=:linkedid: AND endtime = "" AND (src_chan=:src_chan: OR dst_chan=:dst_chan:)',
43
            'bind' => [
44
                'linkedid' => $data['linkedid'],
45
                'src_chan' => $data['agi_channel'],
46
                'dst_chan' => $data['agi_channel'],
47
            ],
48
        ];
49
        /** @var CallDetailRecordsTmp $m_data */
50
        /** @var CallDetailRecordsTmp $row */
51
        $m_data = CallDetailRecordsTmp::find($filter);
52
        foreach ($m_data as $row) {
53
            if ($row->transfer == 1) {
54
                $transfer_calls[] = $row->toArray();
55
            }
56
            if ($row->dialstatus === 'ORIGINATE') {
57
                $row->writeAttribute('dialstatus', '');
58
                if($row->answer === ''){
59
                    $newId = $row->linkedid.'_'.$row->src_num.'_'.substr($row->src_chan, strpos($row->src_chan,'-') +1);
60
                    $row->writeAttribute('UNIQUEID', $newId);
61
                }
62
            }
63
            $row->writeAttribute('endtime', $data['end']);
64
            $row->writeAttribute('transfer', 0);
65
            if ($data['dialstatus'] !== '') {
66
                if ($data['dialstatus'] === 'ORIGINATE') {
67
                    $row->writeAttribute('dst_chan', '');
68
                }
69
                $row->writeAttribute('dialstatus', $data['dialstatus']);
70
            }
71
            $res = $row->update();
72
            if ( ! $res) {
73
                Util::sysLogMsg('Action_hangup_chan', implode(' ', $row->getMessages()), LOG_DEBUG);
74
            }
75
76
            if ($row->src_chan !== $data['agi_channel']) {
77
                $channels[] = [
78
                    'chan' => $row->src_chan,
79
                    'did'  => $row->did,
80
                    'num'  => $row->src_num,
81
                    'out'  => true,
82
                ];
83
            } else {
84
                $worker->StopMixMonitor($row->dst_chan);
85
                $channels[] = [
86
                    'chan' => $row->dst_chan,
87
                    'did'  => $row->did,
88
                    'num'  => $row->dst_num,
89
                    'out'  => false,
90
                ];
91
            }
92
        }
93
    }
94
95
    /**
96
     * Проверяем на SIP трансфер.
97
     * @param $data
98
     * @param $channels
99
     */
100
    private static function hangupChanCheckSipTrtansfer($worker, $data, $channels):void{
101
        $not_local = (stripos($data['agi_channel'], 'local/') === false);
102
        if($not_local === false || $data['OLD_LINKEDID'] !== $data['linkedid']) {
103
            return;
104
        }
105
        $am = Util::getAstManager('off');
106
        $active_chans = $am->GetChannels(false);
107
        // Намек на SIP трансфер.
108
        foreach ($channels as $data_chan) {
109
            if ( ! in_array($data_chan['chan'], $active_chans, true)) {
110
                // Вызов уже завершен. Не интересно.
111
                continue;
112
            }
113
            $BRIDGEPEER = $am->GetVar($data_chan['chan'], 'BRIDGEPEER', null, false);
114
            if ( !is_string($BRIDGEPEER) || ! in_array($BRIDGEPEER, $active_chans, true)) {
115
                // Вызов уже завершен. Не интересно.
116
                continue;
117
            }
118
119
            $linkedid = $am->GetVar($data_chan['chan'], 'CHANNEL(linkedid)', null, false);
120
            if ( empty($linkedid) || $linkedid === $data['linkedid']) {
121
                continue;
122
            }
123
124
            $CALLERID = $am->GetVar($BRIDGEPEER, 'CALLERID(num)', null, false);
125
            $n_data['action']        = 'sip_transfer';
126
            $n_data['src_chan']      = $data_chan['out'] ? $data_chan['chan'] : $BRIDGEPEER;
127
            $n_data['src_num']       = $data_chan['out'] ? $data_chan['num'] : $CALLERID;
128
            $n_data['dst_chan']      = $data_chan['out'] ? $BRIDGEPEER : $data_chan['chan'];
129
            $n_data['dst_num']       = $data_chan['out'] ? $CALLERID : $data_chan['num'];
130
            $n_data['start']         = date('Y-m-d H:i:s');
131
            $n_data['answer']        = date('Y-m-d H:i:s');
132
            $n_data['linkedid']      = $linkedid;
133
            $n_data['UNIQUEID']      = $data['linkedid'] . Util::generateRandomString();
134
            $n_data['transfer']      = '0';
135
            $n_data['recordingfile'] = $worker->MixMonitor($n_data['dst_chan'], $n_data['UNIQUEID']);
136
            $n_data['did']           = $data_chan['did'];
137
138
            Util::logMsgDb('call_events', json_encode($n_data));
139
            InsertDataToDB::execute($n_data);
140
            $filter = [
141
                'linkedid=:linkedid:',
142
                'bind' => ['linkedid' => $data['linkedid']],
143
            ];
144
            $m_data = CallDetailRecordsTmp::find($filter);
145
            foreach ($m_data as $row) {
146
                $row->writeAttribute('linkedid', $linkedid);
147
                $row->save();
148
            }
149
150
            /**
151
             * Отправка UserEvent
152
             */
153
            $AgiData = base64_encode(json_encode($n_data));
154
            $am->UserEvent('CdrConnector', ['AgiData' => $AgiData]);
155
        } // Обход текущих каналов.
156
    }
157
}