| Total Complexity | 135 | 
| Total Lines | 909 | 
| Duplicated Lines | 0 % | 
| Changes | 4 | ||
| Bugs | 0 | Features | 0 | 
Complex classes like Util 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 Util, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 21 | class Util  | 
            ||
| 22 | { | 
            ||
| 23 | /**  | 
            ||
| 24 | * @param $options  | 
            ||
| 25 | * @param $manual_attributes  | 
            ||
| 26 | * @param $section  | 
            ||
| 27 | *  | 
            ||
| 28 | * @return string  | 
            ||
| 29 | */  | 
            ||
| 30 | public static function overrideConfigurationArray($options, $manual_attributes, $section): string  | 
            ||
| 31 |     { | 
            ||
| 32 | $result_config = '';  | 
            ||
| 33 |         if ($manual_attributes !== null && isset($manual_attributes[$section])) { | 
            ||
| 34 |             foreach ($manual_attributes[$section] as $key => $value) { | 
            ||
| 35 |                 if ($key === 'type') { | 
            ||
| 36 | continue;  | 
            ||
| 37 | }  | 
            ||
| 38 | $options[$key] = $value;  | 
            ||
| 39 | }  | 
            ||
| 40 | }  | 
            ||
| 41 |         foreach ($options as $key => $value) { | 
            ||
| 42 |             if (empty($value) || empty($key)) { | 
            ||
| 43 | continue;  | 
            ||
| 44 | }  | 
            ||
| 45 |             if (is_array($value)) { | 
            ||
| 46 | array_unshift($value, ' ');  | 
            ||
| 47 |                 $result_config .= trim(implode("\n{$key} = ", $value)) . "\n"; | 
            ||
| 48 |             } else { | 
            ||
| 49 |                 $result_config .= "{$key} = {$value}\n"; | 
            ||
| 50 | }  | 
            ||
| 51 | }  | 
            ||
| 52 | |||
| 53 | return "$result_config\n";  | 
            ||
| 54 | }  | 
            ||
| 55 | |||
| 56 | /**  | 
            ||
| 57 | * Kills process/daemon by name  | 
            ||
| 58 | *  | 
            ||
| 59 | * @param $procName  | 
            ||
| 60 | *  | 
            ||
| 61 | * @return int|null  | 
            ||
| 62 | */  | 
            ||
| 63 | public static function killByName($procName): ?int  | 
            ||
| 68 | }  | 
            ||
| 69 | |||
| 70 | /**  | 
            ||
| 71 | * Executes command exec().  | 
            ||
| 72 | *  | 
            ||
| 73 | * @param $command  | 
            ||
| 74 | * @param $outArr  | 
            ||
| 75 | * @param $retVal  | 
            ||
| 76 | *  | 
            ||
| 77 | * @return int  | 
            ||
| 78 | */  | 
            ||
| 79 | public static function mwExec($command, &$outArr = null, &$retVal = null): int  | 
            ||
| 80 |     { | 
            ||
| 81 | $retVal = 0;  | 
            ||
| 82 | $outArr = [];  | 
            ||
| 83 | $di = Di::getDefault();  | 
            ||
| 84 | |||
| 85 |         if ($di !== null && $di->getShared('config')->path('core.debugMode')) { | 
            ||
| 86 | echo "mwExec(): $command\n";  | 
            ||
| 87 |         } else { | 
            ||
| 88 |             exec("$command 2>&1", $outArr, $retVal); | 
            ||
| 89 | }  | 
            ||
| 90 | |||
| 91 | return $retVal;  | 
            ||
| 92 | }  | 
            ||
| 93 | |||
| 94 | /**  | 
            ||
| 95 | * Executes command exec() as background process.  | 
            ||
| 96 | *  | 
            ||
| 97 | * @param $command  | 
            ||
| 98 | * @param $out_file  | 
            ||
| 99 | * @param $sleep_time  | 
            ||
| 100 | */  | 
            ||
| 101 | public static function mwExecBg($command, $out_file = '/dev/null', $sleep_time = 0): void  | 
            ||
| 102 |     { | 
            ||
| 103 |         $nohupPath = self::which('nohup'); | 
            ||
| 104 |         $shPath    = self::which('sh'); | 
            ||
| 105 |         $rmPath    = self::which('rm'); | 
            ||
| 106 |         $sleepPath = self::which('sleep'); | 
            ||
| 107 |         if ($sleep_time > 0) { | 
            ||
| 108 | $filename = '/tmp/' . time() . '_noop.sh';  | 
            ||
| 109 |             file_put_contents($filename, "{$sleepPath} {$sleep_time}; {$command}; {$rmPath} -rf {$filename}"); | 
            ||
| 110 |             $noop_command = "{$nohupPath} {$shPath} {$filename} > {$out_file} 2>&1 &"; | 
            ||
| 111 |         } else { | 
            ||
| 112 |             $noop_command = "{$nohupPath} {$command} > {$out_file} 2>&1 &"; | 
            ||
| 113 | }  | 
            ||
| 114 | exec($noop_command);  | 
            ||
| 115 | }  | 
            ||
| 116 | |||
| 117 | /**  | 
            ||
| 118 | * Executes command exec() as background process with an execution timeout.  | 
            ||
| 119 | *  | 
            ||
| 120 | * @param $command  | 
            ||
| 121 | * @param int $timeout  | 
            ||
| 122 | * @param string $logname  | 
            ||
| 123 | */  | 
            ||
| 124 | public static function mwExecBgWithTimeout($command, $timeout = 4, $logname = '/dev/null'): void  | 
            ||
| 136 | }  | 
            ||
| 137 | |||
| 138 | /**  | 
            ||
| 139 | * Executes multiple commands.  | 
            ||
| 140 | *  | 
            ||
| 141 | * @param $arr_cmds  | 
            ||
| 142 | * @param array $out  | 
            ||
| 143 | * @param string $logname  | 
            ||
| 144 | */  | 
            ||
| 145 | public static function mwExecCommands($arr_cmds, &$out = [], $logname = ''): void  | 
            ||
| 158 | }  | 
            ||
| 159 | }  | 
            ||
| 160 | |||
| 161 | /**  | 
            ||
| 162 | * Create folder if it not exist.  | 
            ||
| 163 | *  | 
            ||
| 164 | * @param $parameters string one or multiple paths separated by space  | 
            ||
| 165 | *  | 
            ||
| 166 | * @param bool $addWWWRights  | 
            ||
| 167 | *  | 
            ||
| 168 | * @return bool  | 
            ||
| 169 | */  | 
            ||
| 170 | public static function mwMkdir(string $parameters, bool $addWWWRights=false): bool  | 
            ||
| 191 | }  | 
            ||
| 192 | |||
| 193 | /**  | 
            ||
| 194 | * Process PHP workers  | 
            ||
| 195 | *  | 
            ||
| 196 | * @param string $className  | 
            ||
| 197 | * @param string $param  | 
            ||
| 198 | * @param string $action  | 
            ||
| 199 | */  | 
            ||
| 200 | public static function processPHPWorker(string $className, string $param = 'start', string $action='restart'): void  | 
            ||
| 201 |     { | 
            ||
| 202 | $workerPath = self::getFilePathByClassName($className);  | 
            ||
| 203 |         if ( ! empty($workerPath)) { | 
            ||
| 204 |             $command = "php -f {$workerPath}"; | 
            ||
| 205 | self::processWorker($command, $param, $className, $action);  | 
            ||
| 206 | }  | 
            ||
| 207 | }  | 
            ||
| 208 | |||
| 209 | |||
| 210 | /**  | 
            ||
| 211 | * Try to find full path to php file by class name  | 
            ||
| 212 | *  | 
            ||
| 213 | * @param $className  | 
            ||
| 214 | *  | 
            ||
| 215 | * @return string|null  | 
            ||
| 216 | */  | 
            ||
| 217 | public static function getFilePathByClassName($className): ?string  | 
            ||
| 218 |     { | 
            ||
| 219 | $filename = null;  | 
            ||
| 220 |         try { | 
            ||
| 221 | $reflection = new ReflectionClass($className);  | 
            ||
| 222 | $filename = $reflection->getFileName();  | 
            ||
| 223 |         } catch (\ReflectionException $exception) { | 
            ||
| 224 |             self::sysLogMsg('Util', 'Error ' . $exception->getMessage()); | 
            ||
| 225 | }  | 
            ||
| 226 | |||
| 227 | return $filename;  | 
            ||
| 228 | }  | 
            ||
| 229 | |||
| 230 | /**  | 
            ||
| 231 | * Add message to Syslog.  | 
            ||
| 232 | *  | 
            ||
| 233 | * @param $log_name  | 
            ||
| 234 | * @param $text  | 
            ||
| 235 | * @param ?int $level  | 
            ||
| 236 | * @param ?int $facility  | 
            ||
| 237 | */  | 
            ||
| 238 | public static function sysLogMsg($log_name, $text, $level = null, $facility=LOG_AUTH): void  | 
            ||
| 239 |     { | 
            ||
| 240 | $level = ($level === null) ? LOG_WARNING : $level;  | 
            ||
| 241 |         openlog("$log_name", LOG_PID | LOG_PERROR, $facility); | 
            ||
| 242 | syslog($level, "$text");  | 
            ||
| 243 | closelog();  | 
            ||
| 244 | }  | 
            ||
| 245 | |||
| 246 | /**  | 
            ||
| 247 | * Manages a daemon/worker process  | 
            ||
| 248 | * Returns process statuses by name of it  | 
            ||
| 249 | *  | 
            ||
| 250 | * @param $cmd  | 
            ||
| 251 | * @param $param  | 
            ||
| 252 | * @param $proc_name  | 
            ||
| 253 | * @param $action  | 
            ||
| 254 | * @param $out_file  | 
            ||
| 255 | *  | 
            ||
| 256 | * @return array | bool  | 
            ||
| 257 | */  | 
            ||
| 258 | public static function processWorker($cmd, $param, $proc_name, $action, $out_file = '/dev/null')  | 
            ||
| 259 |     { | 
            ||
| 260 |         $path_kill  = self::which('kill'); | 
            ||
| 261 |         $path_nohup = self::which('nohup'); | 
            ||
| 262 | |||
| 263 | $WorkerPID = self::getPidOfProcess($proc_name);  | 
            ||
| 264 | |||
| 265 |          switch ($action) { | 
            ||
| 266 | case 'status':  | 
            ||
| 267 | $status = ($WorkerPID !== '') ? 'Started' : 'Stoped';  | 
            ||
| 268 | return ['status' => $status, 'app' => $proc_name, 'PID' => $WorkerPID];  | 
            ||
| 269 | case 'restart':  | 
            ||
| 270 | // Firstly start new process  | 
            ||
| 271 |                  self::mwExec("{$path_nohup} {$cmd} {$param}  > {$out_file} 2>&1 &"); | 
            ||
| 272 | // Then kill the old one  | 
            ||
| 273 |                  if ($WorkerPID !== '') { | 
            ||
| 274 |                      self::mwExec("{$path_kill} -9 {$WorkerPID}  > /dev/null 2>&1 &"); | 
            ||
| 275 | }  | 
            ||
| 276 | break;  | 
            ||
| 277 | case 'stop':  | 
            ||
| 278 |                  if ($WorkerPID !== '') { | 
            ||
| 279 |                      self::mwExec("{$path_kill} -9 {$WorkerPID}  > /dev/null 2>&1 &"); | 
            ||
| 280 | }  | 
            ||
| 281 | break;  | 
            ||
| 282 | case 'start':  | 
            ||
| 283 |                  if ($WorkerPID === '') { | 
            ||
| 284 |                      self::mwExec("{$path_nohup} {$cmd} {$param}  > {$out_file} 2>&1 &"); | 
            ||
| 285 | }  | 
            ||
| 286 | break;  | 
            ||
| 287 | case 'multiStart':  | 
            ||
| 288 |                  self::mwExec("{$path_nohup} {$cmd} {$param}  > {$out_file} 2>&1 &"); | 
            ||
| 289 | break;  | 
            ||
| 290 | default:  | 
            ||
| 291 | }  | 
            ||
| 292 | |||
| 293 | return true;  | 
            ||
| 294 | }  | 
            ||
| 295 | |||
| 296 | /**  | 
            ||
| 297 | * Return full path to executable binary  | 
            ||
| 298 | *  | 
            ||
| 299 | * @param string $cmd - name of file  | 
            ||
| 300 | *  | 
            ||
| 301 | * @return string  | 
            ||
| 302 | */  | 
            ||
| 303 | public static function which(string $cmd): string  | 
            ||
| 304 |     { | 
            ||
| 305 | global $_ENV;  | 
            ||
| 306 |         if (array_key_exists('PATH', $_ENV)) { | 
            ||
| 307 | $binaryFolders = $_ENV['PATH'];  | 
            ||
| 308 | |||
| 309 |             foreach (explode(':', $binaryFolders) as $path) { | 
            ||
| 310 |                 if (is_executable("{$path}/{$cmd}")) { | 
            ||
| 311 |                     return "{$path}/{$cmd}"; | 
            ||
| 312 | }  | 
            ||
| 313 | }  | 
            ||
| 314 | }  | 
            ||
| 315 | $binaryFolders =  | 
            ||
| 316 | [  | 
            ||
| 317 | '/bin',  | 
            ||
| 318 | '/sbin',  | 
            ||
| 319 | '/usr/bin',  | 
            ||
| 320 | '/usr/sbin',  | 
            ||
| 321 | '/usr/local/bin',  | 
            ||
| 322 | '/usr/local/sbin',  | 
            ||
| 323 | ];  | 
            ||
| 324 |         foreach ($binaryFolders as $path) { | 
            ||
| 325 |             if (is_executable("{$path}/{$cmd}")) { | 
            ||
| 326 |                 return "{$path}/{$cmd}"; | 
            ||
| 327 | }  | 
            ||
| 328 | }  | 
            ||
| 329 | |||
| 330 | return $cmd;  | 
            ||
| 331 | }  | 
            ||
| 332 | |||
| 333 | /**  | 
            ||
| 334 | * Возвращает PID процесса по его имени.  | 
            ||
| 335 | *  | 
            ||
| 336 | * @param $name  | 
            ||
| 337 | * @param string $exclude  | 
            ||
| 338 | *  | 
            ||
| 339 | * @return string  | 
            ||
| 340 | */  | 
            ||
| 341 | public static function getPidOfProcess($name, $exclude = ''): string  | 
            ||
| 342 |     { | 
            ||
| 343 |         $path_ps   = self::which('ps'); | 
            ||
| 344 |         $path_grep = self::which('grep'); | 
            ||
| 345 |         $path_awk  = self::which('awk'); | 
            ||
| 346 | |||
| 347 | $name = addslashes($name);  | 
            ||
| 348 | $filter_cmd = '';  | 
            ||
| 349 |         if ( ! empty($exclude)) { | 
            ||
| 350 | $filter_cmd = "| $path_grep -v " . escapeshellarg($exclude);  | 
            ||
| 351 | }  | 
            ||
| 352 | $out = [];  | 
            ||
| 353 | self::mwExec(  | 
            ||
| 354 |             "{$path_ps} -A -o 'pid,args' {$filter_cmd} | {$path_grep} '{$name}' | {$path_grep} -v grep | {$path_awk} ' {print $1} '", | 
            ||
| 355 | $out  | 
            ||
| 356 | );  | 
            ||
| 357 | |||
| 358 |         return trim(implode(' ', $out)); | 
            ||
| 359 | }  | 
            ||
| 360 | |||
| 361 | /**  | 
            ||
| 362 | * Инициация телефонного звонка.  | 
            ||
| 363 | * @param $peer_number  | 
            ||
| 364 | * @param $peer_mobile  | 
            ||
| 365 | * @param $dest_number  | 
            ||
| 366 | * @return array  | 
            ||
| 367 | * @throws Exception  | 
            ||
| 368 | */  | 
            ||
| 369 | public static function amiOriginate($peer_number, $peer_mobile, $dest_number): array  | 
            ||
| 370 |     { | 
            ||
| 371 |         $am       = self::getAstManager('off'); | 
            ||
| 372 | $channel = 'Local/' . $peer_number . '@internal-originate';  | 
            ||
| 373 | $context = 'all_peers';  | 
            ||
| 374 | $IS_ORGNT = self::generateRandomString();  | 
            ||
| 375 |         $variable = "_IS_ORGNT={$IS_ORGNT},pt1c_cid={$dest_number},_extenfrom1c={$peer_number},__peer_mobile={$peer_mobile},_FROM_PEER={$peer_number}"; | 
            ||
| 376 | |||
| 377 | return $am->Originate($channel,  | 
            ||
| 378 | $dest_number,  | 
            ||
| 379 | $context,  | 
            ||
| 380 | '1', null, null, null, null, $variable, null, true);  | 
            ||
| 381 | }  | 
            ||
| 382 | |||
| 383 | /**  | 
            ||
| 384 | * Получаем объект менеджер asterisk.  | 
            ||
| 385 | *  | 
            ||
| 386 | * @param string $events  | 
            ||
| 387 | *  | 
            ||
| 388 | * @return AsteriskManager  | 
            ||
| 389 | */  | 
            ||
| 390 | public static function getAstManager($events = 'on'): AsteriskManager  | 
            ||
| 391 |     { | 
            ||
| 392 |         if($events === 'on'){ | 
            ||
| 393 | $nameService = 'amiListner';  | 
            ||
| 394 |         }else{ | 
            ||
| 395 | $nameService = 'amiCommander';  | 
            ||
| 396 | }  | 
            ||
| 397 | |||
| 398 | $di = Di::getDefault();  | 
            ||
| 399 | $am = $di->getShared($nameService);  | 
            ||
| 400 |         if (is_resource($am->socket)) { | 
            ||
| 401 | return $am;  | 
            ||
| 402 | }  | 
            ||
| 403 | |||
| 404 | return $di->get($nameService);  | 
            ||
| 405 | }  | 
            ||
| 406 | |||
| 407 | /**  | 
            ||
| 408 | * Генератор произвольной строки.  | 
            ||
| 409 | * @param int $length  | 
            ||
| 410 | * @return string  | 
            ||
| 411 | */  | 
            ||
| 412 | public static function generateRandomString($length = 10): string  | 
            ||
| 413 |     { | 
            ||
| 414 | $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';  | 
            ||
| 415 | $charactersLength = strlen($characters);  | 
            ||
| 416 | $randomString = '';  | 
            ||
| 417 |         for ($i = 0; $i < $length; $i++) { | 
            ||
| 418 |             try { | 
            ||
| 419 | $randomString .= $characters[random_int(0, $charactersLength - 1)];  | 
            ||
| 420 |             }catch (\Exception $e ){ | 
            ||
| 421 | $randomString = '';  | 
            ||
| 422 | }  | 
            ||
| 423 | }  | 
            ||
| 424 | |||
| 425 | return $randomString;  | 
            ||
| 426 | }  | 
            ||
| 427 | |||
| 428 | /**  | 
            ||
| 429 | * Json validate  | 
            ||
| 430 | *  | 
            ||
| 431 | * @param $jsonString  | 
            ||
| 432 | *  | 
            ||
| 433 | * @return bool  | 
            ||
| 434 | */  | 
            ||
| 435 | public static function isJson($jsonString): bool  | 
            ||
| 436 |     { | 
            ||
| 437 | json_decode($jsonString, true);  | 
            ||
| 438 | |||
| 439 | return (json_last_error() === JSON_ERROR_NONE);  | 
            ||
| 440 | }  | 
            ||
| 441 | |||
| 442 | /**  | 
            ||
| 443 | * Возвращает размер файла в Мб.  | 
            ||
| 444 | *  | 
            ||
| 445 | * @param $filename  | 
            ||
| 446 | *  | 
            ||
| 447 | * @return float|int  | 
            ||
| 448 | */  | 
            ||
| 449 | public static function mFileSize($filename)  | 
            ||
| 450 |     { | 
            ||
| 451 | $size = 0;  | 
            ||
| 452 |         if (file_exists($filename)) { | 
            ||
| 453 | $tmp_size = filesize($filename);  | 
            ||
| 454 |             if ($tmp_size !== false) { | 
            ||
| 455 | // Получим размер в Мб.  | 
            ||
| 456 | $size = $tmp_size;  | 
            ||
| 457 | }  | 
            ||
| 458 | }  | 
            ||
| 459 | |||
| 460 | return $size;  | 
            ||
| 461 | }  | 
            ||
| 462 | |||
| 463 | /**  | 
            ||
| 464 | * Возвращает указанное количество X.  | 
            ||
| 465 | *  | 
            ||
| 466 | * @param $length  | 
            ||
| 467 | *  | 
            ||
| 468 | * @return string  | 
            ||
| 469 | */  | 
            ||
| 470 | public static function getExtensionX($length): string  | 
            ||
| 471 |     { | 
            ||
| 472 | $extension = '';  | 
            ||
| 473 |         for ($i = 0; $i < $length; $i++) { | 
            ||
| 474 | $extension .= 'X';  | 
            ||
| 475 | }  | 
            ||
| 476 | |||
| 477 | return $extension;  | 
            ||
| 478 | }  | 
            ||
| 479 | |||
| 480 | /**  | 
            ||
| 481 | * Проверяет существование файла.  | 
            ||
| 482 | *  | 
            ||
| 483 | * @param $filename  | 
            ||
| 484 | *  | 
            ||
| 485 | * @return bool  | 
            ||
| 486 | */  | 
            ||
| 487 | public static function recFileExists($filename): ?bool  | 
            ||
| 488 |     { | 
            ||
| 489 | return (file_exists($filename) && filesize($filename) > 0);  | 
            ||
| 490 | }  | 
            ||
| 491 | |||
| 492 | /**  | 
            ||
| 493 | * Если переданный параметр - число, то будет возвращена дата.  | 
            ||
| 494 | *  | 
            ||
| 495 | * @param $data  | 
            ||
| 496 | *  | 
            ||
| 497 | * @return string  | 
            ||
| 498 | */  | 
            ||
| 499 | public static function numberToDate($data): string  | 
            ||
| 500 |     { | 
            ||
| 501 | $re_number = '/^\d+.\d+$/';  | 
            ||
| 502 | preg_match_all($re_number, $data, $matches, PREG_SET_ORDER, 0);  | 
            ||
| 503 |         if (count($matches) > 0) { | 
            ||
| 504 |             $data = date('Y.m.d-H:i:s', $data); | 
            ||
| 505 | }  | 
            ||
| 506 | |||
| 507 | return $data;  | 
            ||
| 508 | }  | 
            ||
| 509 | |||
| 510 | /**  | 
            ||
| 511 | * Записывает данные в файл.  | 
            ||
| 512 | *  | 
            ||
| 513 | * @param $filename  | 
            ||
| 514 | * @param $data  | 
            ||
| 515 | */  | 
            ||
| 516 | public static function fileWriteContent($filename, $data): void  | 
            ||
| 517 |     { | 
            ||
| 518 | /** @var CustomFiles $res */  | 
            ||
| 519 |         $res = CustomFiles::findFirst("filepath = '{$filename}'"); | 
            ||
| 520 | |||
| 521 |         $filename_orgn = "{$filename}.orgn"; | 
            ||
| 522 |         if (($res === null || $res->mode === 'none') && file_exists($filename_orgn)) { | 
            ||
| 523 | unlink($filename_orgn);  | 
            ||
| 524 |         } elseif ($res !== null && $res->mode !== 'none') { | 
            ||
| 525 | // Запишем оригинальный файл.  | 
            ||
| 526 | file_put_contents($filename_orgn, $data);  | 
            ||
| 527 | }  | 
            ||
| 528 | |||
| 529 |         if ($res === null) { | 
            ||
| 530 | // Файл еще не зарегистрирован в базе. Сделаем это.  | 
            ||
| 531 | $res = new CustomFiles();  | 
            ||
| 532 |             $res->writeAttribute('filepath', $filename); | 
            ||
| 533 |             $res->writeAttribute('mode', 'none'); | 
            ||
| 534 | $res->save();  | 
            ||
| 535 |         } elseif ($res->mode === 'append') { | 
            ||
| 536 | // Добавить к файлу.  | 
            ||
| 537 | $data .= "\n\n";  | 
            ||
| 538 | $data .= base64_decode($res->content);  | 
            ||
| 539 |         } elseif ($res->mode === 'override') { | 
            ||
| 540 | // Переопределить файл.  | 
            ||
| 541 | $data = base64_decode($res->content);  | 
            ||
| 542 | }  | 
            ||
| 543 | file_put_contents($filename, $data);  | 
            ||
| 544 | }  | 
            ||
| 545 | |||
| 546 | |||
| 547 | |||
| 548 | /**  | 
            ||
| 549 | * Пишем лог в базу данных.  | 
            ||
| 550 | *  | 
            ||
| 551 | * @param $app  | 
            ||
| 552 | * @param $data_obj  | 
            ||
| 553 | */  | 
            ||
| 554 | public static function logMsgDb($app, $data_obj): void  | 
            ||
| 555 |     { | 
            ||
| 556 |         try { | 
            ||
| 557 | $data = new CallEventsLogs();  | 
            ||
| 558 |             $data->writeAttribute('eventtime', date("Y-m-d H:i:s")); | 
            ||
| 559 |             $data->writeAttribute('app', $app); | 
            ||
| 560 |             $data->writeAttribute('datajson', json_encode($data_obj, JSON_UNESCAPED_SLASHES)); | 
            ||
| 561 | |||
| 562 |             if (is_array($data_obj) && isset($data_obj['linkedid'])) { | 
            ||
| 563 |                 $data->writeAttribute('linkedid', $data_obj['linkedid']); | 
            ||
| 564 | }  | 
            ||
| 565 | $data->save();  | 
            ||
| 566 |         } catch (Exception $e) { | 
            ||
| 567 |             self::sysLogMsg('logMsgDb', $e->getMessage()); | 
            ||
| 568 | }  | 
            ||
| 569 | }  | 
            ||
| 570 | |||
| 571 | /**  | 
            ||
| 572 | * Возвращает текущую дату в виде строки с точностью до милисекунд.  | 
            ||
| 573 | *  | 
            ||
| 574 | * @return string  | 
            ||
| 575 | */  | 
            ||
| 576 | public static function getNowDate(): ?string  | 
            ||
| 587 | }  | 
            ||
| 588 | |||
| 589 | |||
| 590 | |||
| 591 | /**  | 
            ||
| 592 | * Получает расширение файла.  | 
            ||
| 593 | *  | 
            ||
| 594 | * @param $filename  | 
            ||
| 595 | * @return mixed  | 
            ||
| 596 | */  | 
            ||
| 597 | public static function getExtensionOfFile($filename)  | 
            ||
| 601 | }  | 
            ||
| 602 | |||
| 603 | /**  | 
            ||
| 604 | * Удаляет расширение файла.  | 
            ||
| 605 | *  | 
            ||
| 606 | * @param $filename  | 
            ||
| 607 | * @param string $delimiter  | 
            ||
| 608 | *  | 
            ||
| 609 | * @return string  | 
            ||
| 610 | */  | 
            ||
| 611 | public static function trimExtensionForFile($filename, $delimiter = '.'): string  | 
            ||
| 621 | }  | 
            ||
| 622 | |||
| 623 | |||
| 624 | |||
| 625 | /**  | 
            ||
| 626 | * Получаем размер файла / директории.  | 
            ||
| 627 | *  | 
            ||
| 628 | * @param $filename  | 
            ||
| 629 | *  | 
            ||
| 630 | * @return float  | 
            ||
| 631 | */  | 
            ||
| 632 | public static function getSizeOfFile($filename): float  | 
            ||
| 633 |     { | 
            ||
| 634 | $result = 0;  | 
            ||
| 635 |         if (file_exists($filename)) { | 
            ||
| 636 |             $duPath  = self::which('du'); | 
            ||
| 637 |             $awkPath = self::which('awk'); | 
            ||
| 638 |             self::mwExec("{$duPath} -d 0 -k '{$filename}' | {$awkPath}  '{ print $1}'", $out); | 
            ||
| 639 | $time_str = implode($out);  | 
            ||
| 640 |             preg_match_all('/^\d+$/', $time_str, $matches, PREG_SET_ORDER, 0); | 
            ||
| 641 |             if (count($matches) > 0) { | 
            ||
| 642 | $result = round(1 * $time_str / 1024, 2);  | 
            ||
| 643 | }  | 
            ||
| 644 | }  | 
            ||
| 645 | |||
| 646 | return $result;  | 
            ||
| 647 | }  | 
            ||
| 648 | |||
| 649 | /**  | 
            ||
| 650 | * Устанавливаем шрифт для консоли.  | 
            ||
| 651 | */  | 
            ||
| 652 | public static function setCyrillicFont(): void  | 
            ||
| 653 |     { | 
            ||
| 654 |         $setfontPath = self::which('setfont'); | 
            ||
| 655 |         self::mwExec("{$setfontPath} /usr/share/consolefonts/Cyr_a8x16.psfu.gz 2>/dev/null"); | 
            ||
| 656 | }  | 
            ||
| 657 | |||
| 658 | /**  | 
            ||
| 659 | * Получить перевод строки текста.  | 
            ||
| 660 | *  | 
            ||
| 661 | * @param $text  | 
            ||
| 662 | *  | 
            ||
| 663 | * @return mixed  | 
            ||
| 664 | */  | 
            ||
| 665 | public static function translate($text)  | 
            ||
| 666 |     { | 
            ||
| 667 | $di = Di::getDefault();  | 
            ||
| 668 |         if ($di !== null) { | 
            ||
| 669 |             return $di->getShared('translation')->_($text); | 
            ||
| 670 |         } else { | 
            ||
| 671 | return $text;  | 
            ||
| 672 | }  | 
            ||
| 673 | }  | 
            ||
| 674 | |||
| 675 | /**  | 
            ||
| 676 | *  | 
            ||
| 677 | * Delete a directory RECURSIVELY  | 
            ||
| 678 | *  | 
            ||
| 679 | * @param string $dir - directory path  | 
            ||
| 680 | *  | 
            ||
| 681 | * @link http://php.net/manual/en/function.rmdir.php  | 
            ||
| 682 | */  | 
            ||
| 683 | public static function rRmDir(string $dir): void  | 
            ||
| 684 |     { | 
            ||
| 685 |         if (is_dir($dir)) { | 
            ||
| 686 | $objects = scandir($dir);  | 
            ||
| 687 |             foreach ($objects as $object) { | 
            ||
| 688 |                 if ($object != "." && $object != "..") { | 
            ||
| 689 |                     if (filetype($dir . "/" . $object) == "dir") { | 
            ||
| 690 | self::rRmDir($dir . "/" . $object);  | 
            ||
| 691 |                     } else { | 
            ||
| 692 | unlink($dir . "/" . $object);  | 
            ||
| 693 | }  | 
            ||
| 694 | }  | 
            ||
| 695 | }  | 
            ||
| 696 |             if($objects !== false){ | 
            ||
| 697 | reset($objects);  | 
            ||
| 698 | }  | 
            ||
| 699 | rmdir($dir);  | 
            ||
| 700 | }  | 
            ||
| 701 | }  | 
            ||
| 702 | |||
| 703 | /**  | 
            ||
| 704 | * Генерация сертификата средствами openssl.  | 
            ||
| 705 | *  | 
            ||
| 706 | * @param ?array $options  | 
            ||
| 707 | * @param ?array $config_args_pkey  | 
            ||
| 708 | * @param ?array $config_args_csr  | 
            ||
| 709 | *  | 
            ||
| 710 | * @return array  | 
            ||
| 711 | */  | 
            ||
| 712 | public static function generateSslCert($options = null, $config_args_pkey = null, $config_args_csr = null): array  | 
            ||
| 713 |     { | 
            ||
| 714 | // Инициализация настроек.  | 
            ||
| 715 |         if ( ! $options) { | 
            ||
| 716 | $options = [  | 
            ||
| 717 | "countryName" => 'RU',  | 
            ||
| 718 | "stateOrProvinceName" => 'Moscow',  | 
            ||
| 719 | "localityName" => 'Zelenograd',  | 
            ||
| 720 | "organizationName" => 'MIKO LLC',  | 
            ||
| 721 | "organizationalUnitName" => 'Software development',  | 
            ||
| 722 | "commonName" => 'MIKO PBX',  | 
            ||
| 723 | "emailAddress" => '[email protected]',  | 
            ||
| 724 | ];  | 
            ||
| 725 | }  | 
            ||
| 726 | |||
| 727 |         if ( ! $config_args_csr) { | 
            ||
| 728 | $config_args_csr = ['digest_alg' => 'sha256'];  | 
            ||
| 729 | }  | 
            ||
| 730 | |||
| 731 |         if ( ! $config_args_pkey) { | 
            ||
| 732 | $config_args_pkey = [  | 
            ||
| 733 | "private_key_bits" => 2048,  | 
            ||
| 734 | "private_key_type" => OPENSSL_KEYTYPE_RSA,  | 
            ||
| 735 | ];  | 
            ||
| 736 | }  | 
            ||
| 737 | |||
| 738 | // Генерация ключей.  | 
            ||
| 739 | $private_key = openssl_pkey_new($config_args_pkey);  | 
            ||
| 740 | $csr = openssl_csr_new($options, $private_key, $config_args_csr);  | 
            ||
| 741 | $x509 = openssl_csr_sign($csr, null, $private_key, $days = 3650, $config_args_csr);  | 
            ||
| 742 | |||
| 743 | // Экспорт ключей.  | 
            ||
| 744 | openssl_x509_export($x509, $certout);  | 
            ||
| 745 | openssl_pkey_export($private_key, $pkeyout);  | 
            ||
| 746 | // echo $pkeyout; // -> WEBHTTPSPrivateKey  | 
            ||
| 747 | // echo $certout; // -> WEBHTTPSPublicKey  | 
            ||
| 748 | return ['PublicKey' => $certout, 'PrivateKey' => $pkeyout];  | 
            ||
| 749 | }  | 
            ||
| 750 | |||
| 751 | /**  | 
            ||
| 752 | * @return bool  | 
            ||
| 753 | */  | 
            ||
| 754 | public static function isSystemctl(): bool  | 
            ||
| 755 |     { | 
            ||
| 756 |         return (stripos(php_uname('v'), 'debian') !== false); | 
            ||
| 757 | }  | 
            ||
| 758 | |||
| 759 | /**  | 
            ||
| 760 | * Выводить текстовое сообщение "done" подсвечивает зеленым цветом.  | 
            ||
| 761 | */  | 
            ||
| 762 | public static function echoGreenDone(): void  | 
            ||
| 765 | }  | 
            ||
| 766 | |||
| 767 | /**  | 
            ||
| 768 | * Создание символической ссылки, если необходимо.  | 
            ||
| 769 | *  | 
            ||
| 770 | * @param $target  | 
            ||
| 771 | * @param $link  | 
            ||
| 772 | *  | 
            ||
| 773 | * @return bool  | 
            ||
| 774 | */  | 
            ||
| 775 | public static function createUpdateSymlink($target, $link): bool  | 
            ||
| 776 |     { | 
            ||
| 777 | $need_create_link = true;  | 
            ||
| 778 |         if (is_link($link)) { | 
            ||
| 779 | $old_target = readlink($link);  | 
            ||
| 780 | $need_create_link = ($old_target != $target);  | 
            ||
| 781 | // Если необходимо, удаляем старую ссылку.  | 
            ||
| 782 |             if ($need_create_link) { | 
            ||
| 783 |                 $cpPath = self::which('cp'); | 
            ||
| 784 |                 self::mwExec("{$cpPath} {$old_target}/* {$target}"); | 
            ||
| 785 | unlink($link);  | 
            ||
| 786 | }  | 
            ||
| 787 |         } elseif (is_dir($link)) { | 
            ||
| 788 | // Это должна быть именно ссылка. Файл удаляем.  | 
            ||
| 789 | rmdir($link);  | 
            ||
| 790 |         } elseif (file_exists($link)) { | 
            ||
| 791 | // Это должна быть именно ссылка. Файл удаляем.  | 
            ||
| 792 | unlink($link);  | 
            ||
| 793 | }  | 
            ||
| 794 | self::mwMkdir($target);  | 
            ||
| 795 |         if ($need_create_link) { | 
            ||
| 796 |             $lnPath = self::which('ln'); | 
            ||
| 797 |             self::mwExec("{$lnPath} -s {$target}  {$link}"); | 
            ||
| 798 | }  | 
            ||
| 799 | |||
| 800 | return $need_create_link;  | 
            ||
| 801 | }  | 
            ||
| 802 | |||
| 803 | /**  | 
            ||
| 804 | * Print message and write it to syslog  | 
            ||
| 805 | *  | 
            ||
| 806 | * @param $message  | 
            ||
| 807 | */  | 
            ||
| 808 | public static function echoWithSyslog($message): void  | 
            ||
| 812 | }  | 
            ||
| 813 | |||
| 814 | /**  | 
            ||
| 815 | * Добавляем задачу для уведомлений.  | 
            ||
| 816 | *  | 
            ||
| 817 | * @param string $tube  | 
            ||
| 818 | * @param $data  | 
            ||
| 819 | */  | 
            ||
| 820 | public function addJobToBeanstalk(string $tube, $data): void  | 
            ||
| 821 |     { | 
            ||
| 822 | $queue = new BeanstalkClient($tube);  | 
            ||
| 823 | $queue->publish(json_encode($data));  | 
            ||
| 824 | }  | 
            ||
| 825 | |||
| 826 | /**  | 
            ||
| 827 | * Apply regular rights for folders and files  | 
            ||
| 828 | *  | 
            ||
| 829 | * @param $folder  | 
            ||
| 830 | */  | 
            ||
| 831 | public static function addRegularWWWRights($folder): void  | 
            ||
| 832 |     { | 
            ||
| 833 |         if (posix_getuid() === 0) { | 
            ||
| 834 |             $findPath  = self::which('find'); | 
            ||
| 835 |             $chownPath = self::which('chown'); | 
            ||
| 836 |             $chmodPath = self::which('chmod'); | 
            ||
| 837 |             self::mwExec("{$findPath} {$folder} -type d -exec {$chmodPath} 755 {} \;"); | 
            ||
| 838 |             self::mwExec("{$findPath} {$folder} -type f -exec {$chmodPath} 644 {} \;"); | 
            ||
| 839 |             self::mwExec("{$chownPath} -R www:www {$folder}"); | 
            ||
| 840 | }  | 
            ||
| 841 | }  | 
            ||
| 842 | |||
| 843 | /**  | 
            ||
| 844 | * Apply executable rights for files  | 
            ||
| 845 | *  | 
            ||
| 846 | * @param $folder  | 
            ||
| 847 | */  | 
            ||
| 848 | public static function addExecutableRights($folder): void  | 
            ||
| 849 |     { | 
            ||
| 850 |         if (posix_getuid() === 0) { | 
            ||
| 851 |             $findPath  = self::which('find'); | 
            ||
| 852 |             $chmodPath = self::which('chmod'); | 
            ||
| 853 |             self::mwExec("{$findPath} {$folder} -type f -exec {$chmodPath} 755 {} \;"); | 
            ||
| 854 | }  | 
            ||
| 855 | }  | 
            ||
| 856 | |||
| 857 | /**  | 
            ||
| 858 | * Разбор INI конфига  | 
            ||
| 859 | *  | 
            ||
| 860 | * @param string $manual_attributes  | 
            ||
| 861 | *  | 
            ||
| 862 | * @return array  | 
            ||
| 863 | */  | 
            ||
| 864 | public static function parseIniSettings(string $manual_attributes): array  | 
            ||
| 865 |     { | 
            ||
| 866 | $tmp_data = base64_decode($manual_attributes);  | 
            ||
| 867 |         if (base64_encode($tmp_data) === $manual_attributes) { | 
            ||
| 868 | $manual_attributes = $tmp_data;  | 
            ||
| 869 | }  | 
            ||
| 870 | unset($tmp_data);  | 
            ||
| 871 | // TRIMMING  | 
            ||
| 872 |         $tmp_arr = explode("\n", $manual_attributes); | 
            ||
| 873 |         foreach ($tmp_arr as &$row) { | 
            ||
| 874 | $row = trim($row);  | 
            ||
| 875 | $pos = strpos($row, ']');  | 
            ||
| 876 |             if ($pos !== false && strpos($row, '[') === 0) { | 
            ||
| 877 | $row = "\n" . substr($row, 0, $pos);  | 
            ||
| 878 | }  | 
            ||
| 879 | }  | 
            ||
| 880 | unset($row);  | 
            ||
| 881 |         $manual_attributes = implode("\n", $tmp_arr); | 
            ||
| 882 | // TRIMMING END  | 
            ||
| 883 | |||
| 884 | $manual_data = [];  | 
            ||
| 885 |         $sections    = explode("\n[", str_replace(']', '', $manual_attributes)); | 
            ||
| 886 |         foreach ($sections as $section) { | 
            ||
| 887 |             $data_rows    = explode("\n", trim($section)); | 
            ||
| 888 | $section_name = trim($data_rows[0] ?? '');  | 
            ||
| 889 |             if ( ! empty($section_name)) { | 
            ||
| 890 | unset($data_rows[0]);  | 
            ||
| 891 | $manual_data[$section_name] = [];  | 
            ||
| 892 |                 foreach ($data_rows as $row) { | 
            ||
| 893 |                     if (strpos($row, '=') === false) { | 
            ||
| 894 | continue;  | 
            ||
| 895 | }  | 
            ||
| 896 | $key = '';  | 
            ||
| 897 |                     $arr_value = explode('=', $row); | 
            ||
| 898 |                     if (count($arr_value) > 1) { | 
            ||
| 899 | $key = trim($arr_value[0]);  | 
            ||
| 900 | unset($arr_value[0]);  | 
            ||
| 901 |                         $value = trim(implode('=', $arr_value)); | 
            ||
| 902 | }  | 
            ||
| 903 |                     if (empty($value) || empty($key)) { | 
            ||
| 904 | continue;  | 
            ||
| 905 | }  | 
            ||
| 906 | $manual_data[$section_name][$key] = $value;  | 
            ||
| 907 | }  | 
            ||
| 908 | }  | 
            ||
| 909 | }  | 
            ||
| 910 | |||
| 911 | return $manual_data;  | 
            ||
| 912 | }  | 
            ||
| 913 | |||
| 914 | /**  | 
            ||
| 915 | * Converts multidimensional array into single array  | 
            ||
| 916 | * @param $array  | 
            ||
| 917 | *  | 
            ||
| 918 | * @return array  | 
            ||
| 919 | */  | 
            ||
| 920 |     public static function flattenArray(array $array) { | 
            ||
| 930 | }  | 
            ||
| 931 | |||
| 932 | |||
| 933 | }  |