Passed
Push — develop ( b317ce...4281e4 )
by Портнов
05:07
created

ExtensionsOutWorkTimeConf::getWeekDayInterval()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 12
rs 9.6111
cc 5
nc 5
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 === $year_to && $Year === $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_to = (empty($time_to)) ? '23:59' : $time_to;
151
            $time_to = (strlen($time_to) === 4) ? "0{$time_to}" : $time_to;
152
153
            $time_from = (empty($time_from)) ? '00:00' : $time_from;
154
            $time_from = (strlen($time_from) === 4) ? "0{$time_from}" : $time_from;
155
156
            if(strtotime($time_from) > strtotime($time_to)){
157
                $intervals=[
158
                    "{$time_from}-23:59",
159
                    "00:00-{$time_to}"
160
                ];
161
            }else{
162
                $intervals=[
163
                    "{$time_from}-{$time_to}"
164
                ];
165
            }
166
        }
167
        return $intervals;
168
    }
169
170
    /**
171
     * Устанавливает тип и данные приложения.
172
     * @param        $ruleData
173
     * @param string $conf_out_set_var
174
     * @return string[]
175
     */
176
    private function initRuleAppData($ruleData, string &$conf_out_set_var): array{
177
        if ('extension' === $ruleData['action']) {
178
            $appName = 'GotoIfTime';
179
            $appdata = "internal,{$ruleData['extension']},1";
180
        } else {
181
            /** @var SoundFiles $res */
182
            $res = SoundFiles::findFirst($ruleData['audio_message_id']);
183
            $audio_message = ($res === null) ? '' : Util::trimExtensionForFile($res->path);
184
185
            $dialplanName = "work-time-set-var-{$ruleData}";
186
187
            if (strpos($conf_out_set_var, $dialplanName) === false) {
188
                $conf_out_set_var .= "[{$dialplanName}]\n" . 'exten => _.!,1,Set(filename=' . $audio_message . ')' . "\n\t" . 'same => n,Goto(playback-exit,${EXTEN},1)' . "\n\n";
189
            }
190
191
            $appName = 'ExecIfTime';
192
            $appdata = 'Goto(work-time-set-var-' . $ruleData . ',${EXTEN},1)';
193
        }
194
        return array($appName, $appdata);
195
    }
196
197
    /**
198
     * Возвращает диапазон дней недели.
199
     * @param array $out_data
200
     * @return string
201
     */
202
    private function getWeekDayInterval(array $out_data): string{
203
        $weekday_from = (string)$out_data['weekday_from'];
204
        $weekday_to = (string)$out_data['weekday_to'];
205
        $arr_weekday = [null, "mon", "tue", "wed", "thu", "fri", "sat", "sun"];
206
        if (empty($weekday_from) && empty($weekday_to)) {
207
            $weekdays = '*';
208
        } else {
209
            $weekday_from = (empty($weekday_from)) ? '1' : $weekday_from;
210
            $weekday_to = (empty($weekday_to)) ? '7' : $weekday_to;
211
            $weekdays = "{$arr_weekday[$weekday_from]}-{$arr_weekday[$weekday_to]}";
212
        }
213
        return $weekdays;
214
    }
215
216
    /**
217
     * Возвращает диапазон месяцев.
218
     * @param array $out_data
219
     * @return string[]
220
     */
221
    private function initDaysMonthsInterval(array $out_data): array{
222
        $date_from = $out_data['date_from'];
223
        $date_to = $out_data['date_to'];
224
        if (empty($date_from)) {
225
            $mDays = '*';
226
            $months = '*';
227
        } else {
228
            $mDays = strtolower(date("j", (int)$date_from));
229
            $months = strtolower(date("M", (int)$date_from));
230
            if (!empty($date_to)) {
231
                $mDays .= "-" . strtolower(date("j", (int)$date_to));
232
                $months .= "-" . strtolower(date("M", (int)$date_to));
233
            }
234
        }
235
        return array($mDays, $months);
236
    }
237
238
239
}