Passed
Push — develop ( 8ed3d9...e6c77a )
by Портнов
04:13
created

initDaysMonthsInterval()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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