Passed
Push — develop ( e6c77a...f886db )
by Портнов
04:53
created

generateIncomingRoutBeforeDial()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
nop 1
1
<?php
2
//
3
4
5
namespace MikoPBX\Core\Asterisk\Configs;
6
7
8
use MikoPBX\Common\Models\OutWorkTimes;
9
use MikoPBX\Common\Models\SoundFiles;
10
use MikoPBX\Core\System\Util;
11
use MikoPBX\Modules\Config\ConfigClass;
12
13
class ExtensionsOutWorkTimeConf extends ConfigClass
14
{
15
    public const OUT_WORK_TIME_CONTEXT = 'check-out-work-time';
16
17
    /**
18
     * Генератор extensions, дополнительные контексты.
19
     * @return string
20
     */
21
    public function extensionGenContexts(): string
22
    {
23
        return $this->generateOutWorkTimes();
24
    }
25
26
    /**
27
     * Кастомизация входящего контекста для конкретного маршрута.
28
     *
29
     * @param $rout_number
30
     *
31
     * @return string
32
     */
33
    public function generateIncomingRoutBeforeDial($rout_number): string
34
    {
35
        // Проверим распискние для входящих внешних звонков.
36
        return 'same => n,Gosub('.self::OUT_WORK_TIME_CONTEXT.',${EXTEN},1)';
37
    }
38
39
    /**
40
     * Описываем нерабочее время.
41
     *
42
     * @return string
43
     */
44
    private function generateOutWorkTimes(): string
45
    {
46
        $conf = "\n\n[playback-exit]\n";
47
        $conf .= 'exten => _.!,1,NoOp(check time)' . "\n\t";
48
        $conf .= 'same => n,Gosub(dial_outworktimes,${EXTEN},1)' . "\n\t";
49
        $conf .= 'same => n,Playback(${filename})' . "\n\t";
50
        $conf .= 'same => n,Hangup()' . "\n\n";
51
52
        $checkContext = self::OUT_WORK_TIME_CONTEXT;
53
        $conf .= "[".$checkContext."]\n";
54
        $conf .= "exten => _.!,1,NoOp(check time)\n\t";
55
        $conf .= 'same => n,Set(currentYear=${STRFTIME(,,%Y)})'."\n\t";
56
        $conf .= 'same => n,GosubIf($["${DIALPLAN_EXISTS('.$checkContext.'-${currentYear},${EXTEN},1)}" == "1"]?'.$checkContext.'-${currentYear},${EXTEN},1)'."\n\t";
57
58
        $data = OutWorkTimes::find(['order' => 'date_from']);
59
        $conf_out_set_var = '';
60
61
        $checkContextsYear = [];
62
        foreach ($data as $out_data) {
63
            $intervals = $this->getOutWorkIntervals($out_data->date_from,$out_data->date_to);
64
            foreach ($intervals as $interval){
65
                $ruleData = $out_data->toArray();
66
                $ruleData['date_to']    = $interval['date_to'];
67
                $ruleData['date_from']  = $interval['date_from'];
68
                $this->generateOutWorkRule($ruleData, $conf_out_set_var, $conf, $checkContextsYear);
69
            }
70
        }
71
        $conf .= "same => n,return\n\n";
72
        $conf .= $conf_out_set_var;
73
74
        foreach ($checkContextsYear as $year => $rule){
75
            $conf .= "[".$checkContext."-{$year}]\n";
76
            $conf .= "exten => _.!,1,NoOp(check time {$year} year)\n\t";
77
            $conf .= implode("", $rule);
78
            $conf .= "same => n,return\n";
79
        }
80
81
        return $conf;
82
    }
83
84
    /**
85
     * Получает массив интервалов для разных "Годов"
86
     * @param $date_from
87
     * @param $date_to
88
     * @return array
89
     */
90
    private function getOutWorkIntervals($date_from, $date_to):array{
91
        $year_from  = 1*date('Y', (int)$date_from);
92
        $year_to    = 1*date('Y', (int)$date_to);
93
94
        $intervals = [];
95
        $Year = $year_from;
96
        if($year_to === $year_from){
97
            $intervals[] = [
98
                'date_from' => $date_from,
99
                'date_to'   => $date_to
100
            ];
101
            return $intervals;
102
        }
103
        while ($Year <= $year_to){
104
            if($Year === $year_from){
105
                $intervals[] = [
106
                    'date_from' => $date_from,
107
                    'date_to'   => (string)strtotime('31-12-'.$Year)
108
                ];
109
            }elseif ($Year === $year_to){
110
                $intervals[] = [
111
                    'date_from' => (string)strtotime('01-01-'.$Year),
112
                    'date_to'   => $date_to
113
                ];
114
            }else{
115
                $intervals[] = [
116
                    'date_from' => (string)strtotime('01-01-'.$Year),
117
                    'date_to'   => (string)strtotime('31-12-'.$Year)
118
                ];
119
            }
120
            $Year++ ;
121
        }
122
        return $intervals;
123
    }
124
125
    /**
126
     * Формирование правила переключателя по времени.
127
     * @param array  $out_data
128
     * @param string $conf_out_set_var
129
     * @param string $conf
130
     * @param array  $checkContextsYear
131
     */
132
    private function generateOutWorkRule(array $out_data, string & $conf_out_set_var, string & $conf, array & $checkContextsYear):void{
133
        $year_from = '';
134
        if ( !empty($out_data['date_from']) && !empty($out_data['date_to'])) {
135
            $year_from = date('Y', (int)$out_data['date_to']);
136
        }
137
138
        $timesArray = $this->getTimesInterval($out_data);
139
        $weekdays   = $this->getWeekDayInterval($out_data);
140
141
        [$mDays,    $months]  = $this->initDaysMonthsInterval($out_data);
142
        [$appName,  $appdata] = $this->initRuleAppData($out_data, $conf_out_set_var);
143
144
        foreach ($timesArray as $times){
145
            $rule = "same => n,{$appName}($times,$weekdays,$mDays,$months?{$appdata})\n\t";
146
            if(empty($year_from)){
147
                $conf .= $rule;
148
            }else{
149
                $checkContextsYear[$year_from][] = $rule;
150
            }
151
        }
152
    }
153
154
    /**
155
     * Получает интервалы времени.
156
     * @param array $out_data
157
     * @return array
158
     */
159
    private function getTimesInterval(array $out_data): array{
160
        $time_from  = $out_data['time_from'];
161
        $time_to    = $out_data['time_to'];
162
        if (empty($time_from) && empty($time_to)) {
163
            $intervals = ['*'];
164
        } else {
165
            $time_from  = $this->normaliseTime($time_from);
166
            $time_to    = $this->normaliseTime($time_to, '23:59');
167
            if(strtotime($time_from) > strtotime($time_to)){
168
                $intervals=[
169
                    "{$time_from}-23:59",
170
                    "00:00-{$time_to}"
171
                ];
172
            }else{
173
                $intervals=[
174
                    "{$time_from}-{$time_to}"
175
                ];
176
            }
177
        }
178
        return $intervals;
179
    }
180
181
    /**
182
     * Нормализация времени в приемлемый формат.
183
     * @param        $srcTime
184
     * @param string $defVal
185
     * @return string
186
     */
187
    private function normaliseTime($srcTime, $defVal = '00:00'):string{
188
        $time = (empty($srcTime)) ? $defVal : $srcTime;
189
        return (strlen($time) === 4) ? "0{$time}" : $time;
190
    }
191
192
    /**
193
     * Устанавливает тип и данные приложения.
194
     * @param        $ruleData
195
     * @param string $conf_out_set_var
196
     * @return string[]
197
     */
198
    private function initRuleAppData($ruleData, string &$conf_out_set_var): array{
199
        if ('extension' === $ruleData['action']) {
200
            $appName = 'GotoIfTime';
201
            $appdata = "internal,{$ruleData['extension']},1";
202
        } else {
203
            /** @var SoundFiles $res */
204
            $res = SoundFiles::findFirst($ruleData['audio_message_id']);
205
            $audio_message = ($res === null) ? '' : Util::trimExtensionForFile($res->path);
206
207
            $dialplanName = "work-time-set-var-{$ruleData}";
208
209
            if (strpos($conf_out_set_var, $dialplanName) === false) {
210
                $conf_out_set_var .= "[{$dialplanName}]\n" . 'exten => _.!,1,Set(filename=' . $audio_message . ')' . "\n\t" . 'same => n,Goto(playback-exit,${EXTEN},1)' . "\n\n";
211
            }
212
213
            $appName = 'ExecIfTime';
214
            $appdata = 'Goto(work-time-set-var-' . $ruleData . ',${EXTEN},1)';
215
        }
216
        return array($appName, $appdata);
217
    }
218
219
    /**
220
     * Возвращает диапазон дней недели.
221
     * @param array $out_data
222
     * @return string
223
     */
224
    private function getWeekDayInterval(array $out_data): string{
225
        $weekday_from = (string)$out_data['weekday_from'];
226
        $weekday_to = (string)$out_data['weekday_to'];
227
        $arr_weekday = [null, "mon", "tue", "wed", "thu", "fri", "sat", "sun"];
228
        if (empty($weekday_from) && empty($weekday_to)) {
229
            $weekdays = '*';
230
        } else {
231
            $weekday_from = (empty($weekday_from)) ? '1' : $weekday_from;
232
            $weekday_to = (empty($weekday_to)) ? '7' : $weekday_to;
233
            $weekdays = "{$arr_weekday[$weekday_from]}-{$arr_weekday[$weekday_to]}";
234
        }
235
        return $weekdays;
236
    }
237
238
    /**
239
     * Возвращает диапазон месяцев.
240
     * @param array $out_data
241
     * @return string[]
242
     */
243
    private function initDaysMonthsInterval(array $out_data): array{
244
        $date_from = $out_data['date_from'];
245
        $date_to = $out_data['date_to'];
246
        if (empty($date_from)) {
247
            $mDays = '*';
248
            $months = '*';
249
        } else {
250
            $mDays = strtolower(date("j", (int)$date_from));
251
            $months = strtolower(date("M", (int)$date_from));
252
            if (!empty($date_to)) {
253
                $mDays .= "-" . strtolower(date("j", (int)$date_to));
254
                $months .= "-" . strtolower(date("M", (int)$date_to));
255
            }
256
        }
257
        return array($mDays, $months);
258
    }
259
260
261
}