| Total Complexity | 57 |
| Total Lines | 310 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
Complex classes like IncomingContexts 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 IncomingContexts, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | class IncomingContexts extends ConfigClass{ |
||
| 15 | /** |
||
| 16 | * Генератор входящих контекстов. |
||
| 17 | * |
||
| 18 | * @param string | array $provider |
||
| 19 | * @param string | array $login |
||
| 20 | * @param string $uniqid |
||
| 21 | * |
||
| 22 | * @return string |
||
| 23 | */ |
||
| 24 | public static function generate($provider, $login = '', $uniqid = ''): string |
||
| 25 | { |
||
| 26 | $conf = ''; |
||
| 27 | $dialplan = []; |
||
| 28 | $di = Di::getDefault(); |
||
| 29 | if ($di === null) { |
||
| 30 | return ''; |
||
| 31 | } |
||
| 32 | $additionalModules = $di->getShared(PBXConfModulesProvider::SERVICE_NAME); |
||
| 33 | $confExtensions = ConferenceConf::getConferenceExtensions(); |
||
| 34 | |||
| 35 | $filter = self::getRoutesFilter($provider); |
||
| 36 | |||
| 37 | /** @var IncomingRoutingTable $default_action */ |
||
| 38 | $default_action = IncomingRoutingTable::findFirst('priority = 9999'); |
||
| 39 | /** @var IncomingRoutingTable $m_data */ |
||
| 40 | $m_data = IncomingRoutingTable::find($filter); |
||
| 41 | $data = $m_data->toArray(); |
||
| 42 | uasort($data, __CLASS__ . '::sortArrayByPriority'); |
||
| 43 | |||
| 44 | $need_def_rout = self::checkNeedDefRout($provider, $data); |
||
| 45 | $config = new MikoPBXConfig(); |
||
| 46 | $lang = str_replace('_', '-', $config->getGeneralSettings('PBXLanguage')); |
||
| 47 | |||
| 48 | $rout_data_dial = []; |
||
| 49 | foreach ($data as $rout) { |
||
| 50 | $number = trim($rout['number']); |
||
| 51 | $timeout = trim($rout['timeout']); |
||
| 52 | $rout_number = ($number === '') ? 'X!' : $number; |
||
| 53 | $rout_data = &$dialplan[$rout_number]; |
||
| 54 | if (empty($rout_data)) { |
||
| 55 | self::generateRouteDialplan($rout_data, $provider, $rout, $lang, $additionalModules); |
||
| 56 | } |
||
| 57 | self::generateDialActions($rout_data_dial, $rout, $rout_number, $confExtensions, $timeout, $provider, $number); |
||
| 58 | } |
||
| 59 | |||
| 60 | self::multiplyExtensionsInDialplan($dialplan, $rout_data_dial, $login, $data, $need_def_rout, $provider); |
||
| 61 | self::trimDialplans($dialplan, $rout_data_dial); |
||
| 62 | self::createSummaryDialplan($conf, $provider, $uniqid, $dialplan, $default_action, $confExtensions, $additionalModules); |
||
| 63 | |||
| 64 | return $conf; |
||
| 65 | } |
||
| 66 | |||
| 67 | /** |
||
| 68 | * @param array|string $provider |
||
| 69 | * @return array|string[] |
||
| 70 | */ |
||
| 71 | private static function getRoutesFilter($provider): array{ |
||
| 82 | } |
||
| 83 | |||
| 84 | /** |
||
| 85 | * Проверка нужен ли дефолтный маршрут для провайдера. |
||
| 86 | * @param $provider |
||
| 87 | * @param array $data |
||
| 88 | * @return bool |
||
| 89 | */ |
||
| 90 | private static function checkNeedDefRout($provider, array &$data): bool{ |
||
| 103 | } |
||
| 104 | |||
| 105 | /** |
||
| 106 | * @param $rout_data |
||
| 107 | * @param $provider |
||
| 108 | * @param array $rout |
||
| 109 | * @param string $lang |
||
| 110 | * @param $additionalModules |
||
| 111 | */ |
||
| 112 | private static function generateRouteDialplan(?string &$rout_data, $provider, array $rout, string $lang, $additionalModules): void{ |
||
| 113 | |||
| 114 | $number = trim($rout['number']); |
||
| 115 | $rout_number = ($number === '') ? 'X!' : $number; |
||
| 116 | |||
| 117 | $ext_prefix = ('none' === $provider) ? '' : '_'; |
||
| 118 | $rout_data .= "exten => {$ext_prefix}{$rout_number},1,NoOp(--- Incoming call ---)\n\t"; |
||
| 119 | $rout_data .= 'same => n,Set(CHANNEL(language)=' . $lang . ')' . "\n\t"; |
||
| 120 | $rout_data .= 'same => n,Set(CHANNEL(hangup_handler_wipe)=hangup_handler,s,1)' . "\n\t"; |
||
| 121 | $rout_data .= 'same => n,Set(__FROM_DID=${EXTEN})' . "\n\t"; |
||
| 122 | $rout_data .= 'same => n,Set(__FROM_CHAN=${CHANNEL})' . "\n\t"; |
||
| 123 | // Установка имени пира. |
||
| 124 | $rout_data .= 'same => n,ExecIf($["${CHANNEL(channeltype)}" != "Local"]?Gosub(set_from_peer,s,1))' . "\n\t"; |
||
| 125 | $rout_data .= 'same => n,ExecIf($["${CHANNEL(channeltype)}" == "Local"]?Set(__FROM_PEER=${CALLERID(num)}))' . "\n\t"; |
||
| 126 | $rout_data .= 'same => n,Gosub(add-trim-prefix-clid,${EXTEN},1)' . "\n\t"; |
||
| 127 | |||
| 128 | foreach ($additionalModules as $appClass) { |
||
| 129 | $addition = $appClass->generateIncomingRoutBeforeDial($rout_number); |
||
| 130 | if (!empty($addition)) { |
||
| 131 | $rout_data .= $appClass->confBlockWithComments($addition); |
||
| 132 | } |
||
| 133 | } |
||
| 134 | // Описываем возможность прыжка в пользовательский sub контекст. |
||
| 135 | $rout_data .= " \n\t" . 'same => n,GosubIf($["${DIALPLAN_EXISTS(${CONTEXT}-custom,${EXTEN},1)}" == "1"]?${CONTEXT}-custom,${EXTEN},1)'; |
||
| 136 | |||
| 137 | if (!empty($rout['extension'])) { |
||
| 138 | $rout_data = rtrim($rout_data); |
||
| 139 | } |
||
| 140 | } |
||
| 141 | |||
| 142 | /** |
||
| 143 | * @param array $rout_data_dial |
||
| 144 | * @param $rout |
||
| 145 | * @param string $rout_number |
||
| 146 | * @param array $confExtensions |
||
| 147 | * @param string $timeout |
||
| 148 | * @param $provider |
||
| 149 | * @param string $number |
||
| 150 | * @return void |
||
| 151 | */ |
||
| 152 | private static function generateDialActions(array &$rout_data_dial, $rout, string $rout_number, array $confExtensions, string $timeout, $provider, string $number): void{ |
||
| 153 | if (empty($rout['extension'])) { |
||
| 154 | return; |
||
| 155 | } |
||
| 156 | // Обязательно проверяем "DIALSTATUS", в случае с парковой через AMI вызова это необходимо. |
||
| 157 | // При ответе может отработать следующий приоритет. |
||
| 158 | if (!isset($rout_data_dial[$rout_number])) { |
||
| 159 | $rout_data_dial[$rout_number] = ''; |
||
| 160 | } |
||
| 161 | |||
| 162 | if (in_array($rout['extension'], $confExtensions, true)) { |
||
| 163 | // Это конференция. Тут не требуется обработка таймаута ответа. |
||
| 164 | // Вызов будет отвечен сразу конференцией. |
||
| 165 | $dial_command = " \n\t" . 'same => n,' . 'ExecIf($["${M_DIALSTATUS}" != "ANSWER"]?' . "Goto(internal,{$rout['extension']},1));"; |
||
| 166 | $rout_data_dial[$rout_number] .= ""; |
||
| 167 | } else { |
||
| 168 | $dial_command = " \n\t" . 'same => n,' . 'ExecIf($["${M_DIALSTATUS}" != "ANSWER"]?' . "Dial(Local/{$rout['extension']}@internal-incoming/n,{$timeout},TKg));"; |
||
| 169 | $rout_data_dial[$rout_number] .= " \n\t" . "same => n,Set(M_TIMEOUT={$timeout})"; |
||
| 170 | } |
||
| 171 | $rout_data_dial[$rout_number] .= $dial_command; |
||
| 172 | |||
| 173 | if (!is_array($provider)) { |
||
| 174 | return; |
||
| 175 | } |
||
| 176 | |||
| 177 | $key = $provider[$rout['provider']] ?? ''; |
||
| 178 | if (!isset($rout_data_dial[$key])) { |
||
| 179 | $rout_data_dial[$key] = ''; |
||
| 180 | } |
||
| 181 | if (empty($number)) { |
||
| 182 | $rout_data_dial[$key] .= $dial_command; |
||
| 183 | } |
||
| 184 | } |
||
| 185 | |||
| 186 | /** |
||
| 187 | * @param array $dialplans |
||
| 188 | * @param array $rout_data_dial |
||
| 189 | */ |
||
| 190 | private static function trimDialplans(array $dialplans, array $rout_data_dial):void{ |
||
| 191 | foreach ($dialplans as $key => &$dialplan) { |
||
| 192 | if (!array_key_exists($key, $rout_data_dial)) { |
||
| 193 | continue; |
||
| 194 | } |
||
| 195 | $dialplan = rtrim($dialplan); |
||
| 196 | $dialplan .= $rout_data_dial[$key]; |
||
| 197 | } |
||
| 198 | } |
||
| 199 | |||
| 200 | |||
| 201 | /** |
||
| 202 | * Добавление дополнительных exten в Dialplan |
||
| 203 | * @param array $dialplan |
||
| 204 | * @param array $rout_data_dial |
||
| 205 | * @param $login |
||
| 206 | * @param array $data |
||
| 207 | * @param bool $need_def_rout |
||
| 208 | * @param $provider |
||
| 209 | */ |
||
| 210 | private static function multiplyExtensionsInDialplan(array &$dialplan, array &$rout_data_dial, $login, array $data, bool $need_def_rout, $provider): void{ |
||
| 211 | if (is_string($login)) { |
||
| 212 | self::multiplyExtensionsInDialplanStringLogin($login, $data, $rout_data_dial, $dialplan, $need_def_rout); |
||
| 213 | } |
||
| 214 | if (is_array($provider)) { |
||
| 215 | foreach (array_values($provider) as $_login) { |
||
| 216 | $dialplan[$_login] = str_replace('_X!,1', "{$_login},1", $dialplan['X!']); |
||
| 217 | } |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * @param string $login |
||
| 223 | * @param array $data |
||
| 224 | * @param array $rout_data_dial |
||
| 225 | * @param array $dialplan |
||
| 226 | * @param bool $need_def_rout |
||
| 227 | */ |
||
| 228 | private static function multiplyExtensionsInDialplanStringLogin(string $login, array $data, array &$rout_data_dial, array &$dialplan, bool $need_def_rout): void{ |
||
| 229 | $add_login_pattern = self::needAddLoginExtension($login, $data); |
||
| 230 | if ($add_login_pattern && array_key_exists('X!', $rout_data_dial) && isset($dialplan['X!'])) { |
||
| 231 | $dialplan[$login] = str_replace('_X!,1', "{$login},1", $dialplan['X!']); |
||
| 232 | $rout_data_dial[$login] = $rout_data_dial['X!']; |
||
| 233 | } elseif ($add_login_pattern === true && $need_def_rout === true && count($data) === 1) { |
||
| 234 | // Только маршрут "По умолчанию". |
||
| 235 | $dialplan[$login] = str_replace('_X!,1', "{$login},1", $dialplan['X!']); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | /** |
||
| 240 | * Если логин не числовой, то нужно добавить такой Exten. |
||
| 241 | * @param string $login |
||
| 242 | * @param array $data |
||
| 243 | * @return bool |
||
| 244 | */ |
||
| 245 | private static function needAddLoginExtension(string $login, array $data): bool{ |
||
| 266 | } |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Формирование итогового dialplan. |
||
| 270 | * @param string $conf |
||
| 271 | * @param $provider |
||
| 272 | * @param string $uniqId |
||
| 273 | * @param array $dialplan |
||
| 274 | * @param IncomingRoutingTable $default_action |
||
| 275 | * @param array $confExtensions |
||
| 276 | * @param $additionalModules |
||
| 277 | * @return string |
||
| 278 | */ |
||
| 279 | private static function createSummaryDialplan(string & $conf, $provider, string $uniqId, array $dialplan, IncomingRoutingTable $default_action, array $confExtensions, $additionalModules): string{ |
||
| 280 | $uniqId = is_string($provider) ? $provider : $uniqId; |
||
| 281 | $conf .= "\n" . "[{$uniqId}-incoming]\n"; |
||
| 282 | foreach ($dialplan as $dpln) { |
||
| 283 | $conf .= $dpln . "\n"; |
||
| 284 | if (null === $default_action && 'none' !== $provider) { |
||
| 285 | continue; |
||
| 286 | } |
||
| 287 | if ('extension' === $default_action->action) { |
||
| 288 | $conf = self::createSummaryDialplanGoto($conf, $default_action, $confExtensions, $additionalModules, $uniqId); |
||
| 289 | $conf .= " \t" . 'same => n,GosubIf($["${DIALPLAN_EXISTS(${CONTEXT}-after-dial-custom,${EXTEN},1)}" == "1"]?${CONTEXT}-after-dial-custom,${EXTEN},1)' . "\n"; |
||
| 290 | } elseif ('busy' === $default_action->action) { |
||
| 291 | $conf .= "\t" . "same => n,Busy()" . "\n"; |
||
| 292 | } |
||
| 293 | $conf .= "\t" . "same => n,Hangup()" . "\n"; |
||
| 294 | } |
||
| 295 | return $conf; |
||
| 296 | } |
||
| 297 | |||
| 298 | /** |
||
| 299 | * @param string $conf |
||
| 300 | * @param IncomingRoutingTable $default_action |
||
| 301 | * @param array $confExtensions |
||
| 302 | * @param $additionalModules |
||
| 303 | * @param string $uniqId |
||
| 304 | * @return string |
||
| 305 | */ |
||
| 306 | private static function createSummaryDialplanGoto(string $conf, IncomingRoutingTable $default_action, array $confExtensions, $additionalModules, string $uniqId): string{ |
||
| 324 | } |
||
| 325 | |||
| 326 | } |