| Total Complexity | 52 |
| Total Lines | 398 |
| Duplicated Lines | 0 % |
| Changes | 3 | ||
| Bugs | 0 | Features | 0 |
Complex classes like ExtensionsOutWorkTimeConf often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ExtensionsOutWorkTimeConf, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 40 | class ExtensionsOutWorkTimeConf extends AsteriskConfigClass |
||
| 41 | { |
||
| 42 | // The module hook applying priority |
||
| 43 | public int $priority = 510; |
||
| 44 | public const OUT_WORK_TIME_CONTEXT = 'check-out-work-time'; |
||
| 45 | private string $conf = ''; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * Generates core modules config files |
||
| 49 | */ |
||
| 50 | protected function generateConfigProtected(): void |
||
| 76 | } |
||
| 77 | |||
| 78 | } |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Generates the extension contexts for out of work time configurations. |
||
| 82 | * |
||
| 83 | * @return string The generated configuration. |
||
| 84 | */ |
||
| 85 | public function extensionGenContexts(): string |
||
| 90 | } |
||
| 91 | |||
| 92 | |||
| 93 | /** |
||
| 94 | * |
||
| 95 | * @return string Set global vars. |
||
| 96 | */ |
||
| 97 | public function extensionGlobals(): string |
||
| 98 | { |
||
| 99 | $configs = ''; |
||
| 100 | $dbData = Sip::find("type = 'friend' AND ( disabled <> '1')"); |
||
| 101 | foreach ($dbData as $sipPeer) { |
||
| 102 | $context_id = SIPConf::getContextId($sipPeer->host, $sipPeer->port); |
||
| 103 | $configs .= "CONTEXT_ID_$sipPeer->uniqid=$context_id".PHP_EOL; |
||
| 104 | } |
||
| 105 | return $configs; |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * Generates the customized incoming context for a specific route before dialing system. |
||
| 110 | * |
||
| 111 | * @param string $rout_number The route number. |
||
| 112 | * |
||
| 113 | * @return string The generated configuration. |
||
| 114 | */ |
||
| 115 | public function generateIncomingRoutBeforeDialSystem(string $rout_number): string |
||
| 116 | { |
||
| 117 | // Check the schedule for incoming external calls. |
||
| 118 | return 'same => n,NoOp(contextID: ${contextID})' . PHP_EOL . "\t" . |
||
| 119 | 'same => n,ExecIf($["${CONTEXT}" == "public-direct-dial"]?Set(contextID=none-incoming))' . PHP_EOL . "\t" . |
||
| 120 | 'same => n,ExecIf($["${contextID}x" == "x"]?Set(contextID=${CONTEXT_ID_${providerID}}))' . PHP_EOL . "\t" . |
||
| 121 | 'same => n,ExecIf($["${contextID}x" == "x"]?Set(contextID=${CONTEXT}))' . PHP_EOL . "\t" . |
||
| 122 | 'same => n,GosubIf($["${IGNORE_TIME}" != "1"]?' . self::OUT_WORK_TIME_CONTEXT . ',${EXTEN},1)' . PHP_EOL . "\t"; |
||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Generates the out of work time configurations. |
||
| 127 | * |
||
| 128 | * @return void |
||
| 129 | */ |
||
| 130 | private function generateOutWorkTimes(): void |
||
| 131 | { |
||
| 132 | $this->conf = PHP_EOL."[playback-exit]".PHP_EOL. |
||
| 133 | 'exten => ' . ExtensionsConf::ALL_EXTENSION . ',1,Gosub(dial_outworktimes,${EXTEN},1)' . PHP_EOL."\t". |
||
| 134 | 'same => n,Playback(${filename})' . PHP_EOL. "\t". |
||
| 135 | 'same => n,Hangup()'.PHP_EOL. |
||
| 136 | 'exten => _[hit],1,Hangup()'.PHP_EOL.PHP_EOL; |
||
| 137 | $this->conf .= '[calendar-event]'.PHP_EOL. |
||
| 138 | 'exten => s,1,NoOp( calendar: ${CALENDAR_EVENT(calendar)}, summary: ${CALENDAR_EVENT(summary)} )'.PHP_EOL."\t". |
||
| 139 | 'same => n,NoOp( description: ${CALENDAR_EVENT(description)} )'.PHP_EOL."\t". |
||
| 140 | 'same => n,NoOp( start: ${CALENDAR_EVENT(start)}, end: ${CALENDAR_EVENT(end)})'.PHP_EOL."\t". |
||
| 141 | 'same => n,NoOp( busystate: ${CALENDAR_EVENT(busystate)} )'.PHP_EOL."\t". |
||
| 142 | 'same => n,answer()'.PHP_EOL."\t". |
||
| 143 | 'same => n,Wait(2)' . PHP_EOL . |
||
| 144 | 'same => n,hangup' . PHP_EOL . PHP_EOL; |
||
| 145 | |||
| 146 | $routesData = $this->getRoutesData(); |
||
| 147 | $additionalContexts = ''; |
||
| 148 | $conf_out_set_var = ''; |
||
| 149 | $data = OutWorkTimes::find(['order'=>'priority, date_from'])->toArray(); |
||
| 150 | $this->conf .= "[" . self::OUT_WORK_TIME_CONTEXT . "]".PHP_EOL; |
||
| 151 | $this->conf .= 'exten => ' . ExtensionsConf::ALL_EXTENSION . ',1,Set(currentYear=${STRFTIME(,,%Y)})' . "\n\t"; |
||
| 152 | foreach ($data as $ruleData) { |
||
| 153 | $contextId = 'check-out-work-time-'.$ruleData['id']; |
||
| 154 | $this->conf .= 'same => n,Gosub('.$contextId.',${EXTEN},1)'.PHP_EOL."\t"; |
||
| 155 | [, $years] = $this->getOutWorkIntervals($ruleData['date_from'], $ruleData['date_to']); |
||
| 156 | $additionalContexts.= '['.$contextId.']'.PHP_EOL; |
||
| 157 | $additionalContexts.= 'exten => _[0-9*#+a-zA-Z]!,1,NoOp()'.PHP_EOL."\t"; |
||
| 158 | if(!empty($years)){ |
||
| 159 | $additionalContexts.= 'same => n,Set(TMP_YEARS='.implode('-',$years).'-)'.PHP_EOL."\t"; |
||
| 160 | $additionalContexts.= 'same => n,ExecIf($["STRREPLACE(TMP_YEARS,currentYear)" == "${TMP_YEARS}"]?return)'.PHP_EOL."\t"; |
||
| 161 | } |
||
| 162 | // Restrictions for the route are not allowed for this rule. |
||
| 163 | if ($ruleData['allowRestriction'] === '1') { |
||
| 164 | $additionalContexts.= 'same => n,ExecIf($["${DIALPLAN_EXISTS('.$contextId.'-${contextID},${EXTEN},1)}" == "0"]?return)'.PHP_EOL."\t"; |
||
| 165 | } |
||
| 166 | if(empty($ruleData['calType'])){ |
||
| 167 | $this->generateOutWorkRule($ruleData, $conf_out_set_var, $additionalContexts); |
||
| 168 | }else{ |
||
| 169 | $appdata = $this->initRuleAppData($ruleData, $conf_out_set_var); |
||
| 170 | $additionalContexts.= 'same => n,GotoIf(${CALENDAR_BUSY(calendar-'.$ruleData['id'].')}?'.$appdata.')'.PHP_EOL."\t"; |
||
| 171 | } |
||
| 172 | $additionalContexts.= 'same => n,return'.PHP_EOL; |
||
| 173 | $additionalContexts.= 'exten => _[hit],1,Hangup()'.PHP_EOL; |
||
| 174 | $contextData = $routesData[$ruleData['id']]??[]; |
||
| 175 | foreach ($contextData as $subContext => $arrayDid){ |
||
| 176 | $additionalContexts.= "[$contextId-$subContext]".PHP_EOL; |
||
| 177 | foreach (array_unique($arrayDid) as $did){ |
||
| 178 | $additionalContexts .= "exten => $did,1,NoOp(-)" . PHP_EOL; |
||
| 179 | } |
||
| 180 | } |
||
| 181 | $additionalContexts.= PHP_EOL; |
||
| 182 | |||
| 183 | } |
||
| 184 | $this->conf .= "same => n,return".PHP_EOL; |
||
| 185 | $this->conf .= 'exten => _[hit],1,Hangup()' . PHP_EOL.PHP_EOL; |
||
| 186 | $this->conf .= $additionalContexts.PHP_EOL; |
||
| 187 | $this->conf .= PHP_EOL.$conf_out_set_var.PHP_EOL; |
||
| 188 | } |
||
| 189 | |||
| 190 | /** |
||
| 191 | * Retrieves the data for the routes. |
||
| 192 | * |
||
| 193 | * @return array |
||
| 194 | */ |
||
| 195 | private function getRoutesData(): array |
||
| 232 | } |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Get the out-of-work intervals based on the provided date range. |
||
| 236 | * |
||
| 237 | * @param int $date_from The starting date. |
||
| 238 | * @param int $date_to The ending date. |
||
| 239 | * |
||
| 240 | * @return array An array of intervals. |
||
| 241 | */ |
||
| 242 | private function getOutWorkIntervals($date_from, $date_to): array |
||
| 243 | { |
||
| 244 | $years = []; |
||
| 245 | $year_from = 1 * date('Y', (int)$date_from); |
||
| 246 | $year_to = 1 * date('Y', (int)$date_to); |
||
| 247 | |||
| 248 | $intervals = []; |
||
| 249 | $Year = $year_from; |
||
| 250 | if ($year_to === $year_from) { |
||
| 251 | if(!empty($date_from)){ |
||
| 252 | $years[] = $Year; |
||
| 253 | } |
||
| 254 | $intervals[] = [ |
||
| 255 | 'date_from' => $date_from, |
||
| 256 | 'date_to' => $date_to |
||
| 257 | ]; |
||
| 258 | return [$intervals, $years]; |
||
| 259 | } |
||
| 260 | while ($Year <= $year_to) { |
||
| 261 | |||
| 262 | $years[] = $Year; |
||
| 263 | if ($Year === $year_from) { |
||
| 264 | $intervals[] = [ |
||
| 265 | 'date_from' => $date_from, |
||
| 266 | 'date_to' => (string)strtotime('31-12-' . $Year) |
||
| 267 | ]; |
||
| 268 | } elseif ($Year === $year_to) { |
||
| 269 | $intervals[] = [ |
||
| 270 | 'date_from' => (string)strtotime('01-01-' . $Year), |
||
| 271 | 'date_to' => $date_to |
||
| 272 | ]; |
||
| 273 | } else { |
||
| 274 | $intervals[] = [ |
||
| 275 | 'date_from' => (string)strtotime('01-01-' . $Year), |
||
| 276 | 'date_to' => (string)strtotime('31-12-' . $Year) |
||
| 277 | ]; |
||
| 278 | } |
||
| 279 | $Year++; |
||
| 280 | } |
||
| 281 | return [$intervals, $years]; |
||
| 282 | } |
||
| 283 | |||
| 284 | /** |
||
| 285 | * Generate the out-of-work rule based on the provided data. |
||
| 286 | * |
||
| 287 | * @param array $out_data The data for the out-of-work rule. |
||
| 288 | * @param string &$conf_out_set_var The output string for the SET variables. |
||
| 289 | * @param string &$conf The output string for the configuration. |
||
| 290 | * |
||
| 291 | * @return void |
||
| 292 | */ |
||
| 293 | private function generateOutWorkRule(array $out_data, string &$conf_out_set_var, string &$conf): void |
||
| 294 | { |
||
| 295 | $timesArray = $this->getTimesInterval($out_data); |
||
| 296 | $weekdays = $this->getWeekDayInterval($out_data); |
||
| 297 | |||
| 298 | [$mDays, $months] = $this->initDaysMonthsInterval($out_data); |
||
| 299 | $appdata = $this->initRuleAppData($out_data, $conf_out_set_var); |
||
| 300 | |||
| 301 | foreach ($timesArray as $times) { |
||
| 302 | $conf .= "same => n,GotoIfTime($times,$weekdays,$mDays,$months?{$appdata})\n\t"; |
||
| 303 | } |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * Get the time intervals based on the provided out-of-work data. |
||
| 308 | * |
||
| 309 | * @param array $out_data The out-of-work data. |
||
| 310 | * |
||
| 311 | * @return array The time intervals. |
||
| 312 | */ |
||
| 313 | private function getTimesInterval(array $out_data): array |
||
| 314 | { |
||
| 315 | $time_from = $out_data['time_from']; |
||
| 316 | $time_to = $out_data['time_to']; |
||
| 317 | if (empty($time_from) && empty($time_to)) { |
||
| 318 | $intervals = ['*']; |
||
| 319 | } else { |
||
| 320 | $time_from = $this->normaliseTime($time_from); |
||
| 321 | $time_to = $this->normaliseTime($time_to, '23:59'); |
||
| 322 | if (strtotime($time_from) > strtotime($time_to)) { |
||
| 323 | $intervals = [ |
||
| 324 | "{$time_from}-23:59", |
||
| 325 | "00:00-{$time_to}" |
||
| 326 | ]; |
||
| 327 | } else { |
||
| 328 | $intervals = [ |
||
| 329 | "{$time_from}-{$time_to}" |
||
| 330 | ]; |
||
| 331 | } |
||
| 332 | } |
||
| 333 | return $intervals; |
||
| 334 | } |
||
| 335 | |||
| 336 | /** |
||
| 337 | * Normalize the time to an acceptable format. |
||
| 338 | * |
||
| 339 | * @param string $srcTime The source time to be normalized. |
||
| 340 | * @param string $defVal The default value to be used if the source time is empty. |
||
| 341 | * @return string The normalized time. |
||
| 342 | */ |
||
| 343 | private function normaliseTime($srcTime, $defVal = '00:00'): string |
||
| 344 | { |
||
| 345 | $time = (empty($srcTime)) ? $defVal : $srcTime; |
||
| 346 | return (strlen($time) === 4) ? "0{$time}" : $time; |
||
| 347 | } |
||
| 348 | |||
| 349 | /** |
||
| 350 | * Initialize the rule application data based on the rule type. |
||
| 351 | * |
||
| 352 | * @param array $ruleData The rule data. |
||
| 353 | * @param string $conf_out_set_var The reference to the configuration variable for output. |
||
| 354 | * |
||
| 355 | * @return string An array containing the data. |
||
| 356 | */ |
||
| 357 | private function initRuleAppData($ruleData, string &$conf_out_set_var): string |
||
| 376 | } |
||
| 377 | |||
| 378 | /** |
||
| 379 | * Returns a string representing the weekday interval. |
||
| 380 | * |
||
| 381 | * @param array $out_data An array containing the weekday_from and weekday_to values. |
||
| 382 | * |
||
| 383 | * @return string The weekday interval string. |
||
| 384 | */ |
||
| 385 | private function getWeekDayInterval(array $out_data): string |
||
| 402 | } |
||
| 403 | |||
| 404 | /** |
||
| 405 | * Initializes the days and months interval based on the provided data. |
||
| 406 | * |
||
| 407 | * @param array $out_data An array containing the date_from and date_to values. |
||
| 408 | * |
||
| 409 | * @return array An array containing the days and months interval. |
||
| 410 | */ |
||
| 411 | private function initDaysMonthsInterval(array $out_data): array |
||
| 412 | { |
||
| 413 | // Extract date_from and date_to values |
||
| 414 | $date_from = $out_data['date_from']; |
||
| 415 | $date_to = $out_data['date_to']; |
||
| 416 | if (empty($date_from)) { |
||
| 417 | // If date_from is empty, set mDays and months to '*' |
||
| 418 | $mDays = '*'; |
||
| 419 | $months = '*'; |
||
| 420 | } else { |
||
| 421 | // Convert date_from to lowercase day and month abbreviations |
||
| 422 | $mDays = strtolower(date("j", (int)$date_from)); |
||
| 423 | $months = strtolower(date("M", (int)$date_from)); |
||
| 424 | if (!empty($date_to)) { |
||
| 425 | $mDays .= "-" . strtolower(date("j", (int)$date_to)); |
||
| 426 | $months .= "-" . strtolower(date("M", (int)$date_to)); |
||
| 427 | } |
||
| 428 | } |
||
| 429 | return array($mDays, $months); |
||
| 430 | } |
||
| 431 | |||
| 432 | public function generateModulesConf(): string |
||
| 438 | } |
||
| 439 | } |