src/Library/Utils/Other/Other.php line 389

Open in your IDE?
  1. <?php
  2. namespace App\Library\Utils\Other;
  3. use App\Library\Utils\Dev\ReflectionUtils\ReflectionUtils;
  4. use App\Library\Utils\StringUtils;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Symfony\Component\Console\Input\InputInterface;
  7. use Symfony\Component\Console\Output\OutputInterface;
  8. use Symfony\Component\Console\Question\Question;
  9. use Symfony\Component\HttpFoundation\Request;
  10. class Other
  11. {
  12.     public function __construct(EntityManagerInterface $em)
  13.     {
  14.         $this->em $em;
  15.     }
  16.     /**
  17.      * @param InputInterface $input
  18.      * @param OutputInterface $output
  19.      * @param string $defaultAnswerMsg
  20.      * @return array|mixed|string|string[]|null
  21.      */
  22.     public static function askUser(InputInterface $inputOutputInterface $output$helper$questionTxt, &$replaceAll null,
  23.                                                   $defaultAnswerMsg null$noMsg null$stopMsg null,
  24.                                    array $answers null$defaultAnswer "yes"$useYesNoAllAnswers true$allowAnyInput false,
  25.                                                   $stopInputOnEmptyAnswer false, array $generateMenu null)
  26.     {
  27.         $answer null;
  28.         $yesNoAllAnswers = ['y''n''a''s''yes''no''all'];
  29.         if ($answers === null$answers = [];
  30.         $answers array_merge(
  31.             ($useYesNoAllAnswers $yesNoAllAnswers : []),
  32.             ($answers $answers : []),
  33.             ($stopInputOnEmptyAnswer ? ["stop"] : [])
  34.         );
  35.         if ($stopInputOnEmptyAnswer$defaultAnswer "stop";
  36.         if (!in_array($defaultAnswer$answers)) {
  37.             $defaultAnswer null;
  38.         }
  39.         $answerShortcuts = ['s''y''n''a'];
  40.         $answerShortcutReplacements = ['stop''yes''no''all'];
  41.         if ($generateMenu) {
  42.             $menuItemNumber 0;
  43.             foreach ($generateMenu as $menuItemData) {
  44.                 $menuCaption = ($menuItemData[1] ? $menuItemData[1] : $menuItemData[2]);
  45.                 $answerReplacement $menuItemData[2];
  46.                 if (!$answerReplacement) continue;
  47.                 $menuItemNumber++;
  48.                 $answerStr = ($menuItemData[0] ? $menuItemData[0] : strval($menuItemNumber));
  49.                 $questionTxt .= "\n" $answerStr ". " $menuCaption " ";
  50.                 $answers array_merge($answers, [$answerStr$answerReplacement]);
  51.                 if (strlen($answerStr) == 1) {
  52.                     $answerShortcuts array_merge($answerShortcuts, [$answerStr]);
  53.                     $answerShortcutReplacements array_merge($answerShortcutReplacements, [$answerReplacement]);
  54.                 }
  55.             }
  56.         }
  57.         if ($defaultAnswer$questionTxt .= "\nPress Enter - " . ($defaultAnswerMsg $defaultAnswerMsg $defaultAnswer) . ' ';
  58.         while (!$replaceAll && (!$answer || (!$allowAnyInput && !in_array($answer$answers)))) {
  59.             $question = new Question($questionTxt'[DEFAULT]');
  60.             $answer $helper->ask($input$output$question);
  61.             if ($answer == '[DEFAULT]'$answer $defaultAnswer;
  62.             if (strlen($answer) == '1') {
  63.                 $answer str_replace($answerShortcuts$answerShortcutReplacements$answer);
  64.             }
  65.         }
  66.         if ($answer == 'no') {
  67.             if ($noMsg) echo $noMsg;
  68.         } else if ($answer == 'yes' || $answer == 'all') {
  69.             if ($answer == 'all'$replaceAll true;
  70.         } else if ($answer == 'stop') {
  71.             if ($stopMsg) echo $stopMsg;
  72.             return null;
  73.         }
  74.         return $answer;
  75.     }
  76.     public static function findParentPathWithDir($path$childDirNames)
  77.     {
  78.         if (!is_array($childDirNames)) {
  79.             $childDirNames = [$childDirNames];
  80.         }
  81.         while (true) {
  82.             $path realpath($path "/..");
  83.             $continueSearch false;
  84.             foreach ($childDirNames as $childDirName) {
  85.                 if (($continueSearch = !is_dir($path "/" $childDirName))) break;
  86.             }
  87.             if (!$continueSearch) break;
  88.         }
  89.         return $path;
  90.     }
  91.     static public function getPathStructure($path)
  92.     {
  93.         $result = [
  94.             'segments' => explode("/"$path),
  95.         ];
  96.         $result['fileNameWithExtension'] = $result['segments'][array_key_last($result['segments'])];
  97.         $fileNameWithExtensionArr explode("."$result['fileNameWithExtension']);
  98.         $result['extension'] = $fileNameWithExtensionArr[array_key_last($fileNameWithExtensionArr)];
  99.         unset($fileNameWithExtensionArr[array_key_last($fileNameWithExtensionArr)]);
  100.         $result['fileNameWithoutExtension'] = implode("."$fileNameWithExtensionArr);
  101.         $result['lastSegment'] = $result['segments'][array_key_last($result['segments'])];
  102.         $pathWithoutLastSegment $result['segments'];
  103.         unset($pathWithoutLastSegment[array_key_last($pathWithoutLastSegment)]);
  104.         $pathWithoutLastSegment implode("/"$pathWithoutLastSegment);
  105.         $result['pathWithoutLastSegment'] = $pathWithoutLastSegment;
  106.         return $result;
  107.     }
  108.     public static function getAllSubdirs($path$asString falsebool $addFilesString$_dirLevel ""$recursively true)
  109.     {
  110.         $dirStructure = [];
  111.         $strDirStructure "";
  112.         foreach (scandir($path) as $objName) {
  113.             if ($objName != "." && $objName != ".." is_dir($path DIRECTORY_SEPARATOR $objName)) {
  114.                 if ($asString) {
  115.                     $filesString "";
  116.                     if ($addFilesString) {
  117.                         $addFilesCount 3;
  118.                         foreach (glob("$path/$objName/*") as $filePath) {
  119.                             if (is_dir($filePath)) {
  120.                                 continue;
  121.                             }
  122.                             if ($addFilesCount == 0) {
  123.                                 $filesString .= ($filesString ", " "") . "...";
  124.                                 break;
  125.                             }
  126.                             $filesString .= ($filesString ", " "") . self::getPathStructure($filePath)['lastSegment'];
  127.                             $addFilesCount--;
  128.                         }
  129.                         if (strlen($filesString) > 150) {
  130.                             $filesString substr($filesString0150) . "...";
  131.                         }
  132.                         if ($filesString) {
  133.                             $filesString "     ($filesString)";
  134.                         }
  135.                     }
  136.                     $strDirStructure .= $_dirLevel '- ' $objName $filesString "\r\n" .
  137.                         self::getAllSubdirs($path DIRECTORY_SEPARATOR $objNametrue$addFilesString$_dirLevel "     "true);
  138.                 } else {
  139.                     $dirStructure[$objName] = ($recursively self::getAllSubdirs($path DIRECTORY_SEPARATOR $objNamefalse$addFilesString""true) :
  140.                         $path DIRECTORY_SEPARATOR $objName);
  141.                 }
  142.             }
  143.         }
  144.         if ($asString) {
  145.             return $strDirStructure;
  146.         } else {
  147.             return $dirStructure;
  148.         }
  149.     }
  150.     public static function createGuid(int $length 16)
  151.     {
  152.         $guid bin2hex(openssl_random_pseudo_bytes($length));
  153.         return $guid;
  154.     }
  155.     public static function createToken(): string
  156.     {
  157.         return self::createGuid(32);
  158.     }
  159.     /**
  160.      * @param array|string $addDataBefore
  161.      * @param array|string|mixed $data
  162.      * @param $fileNameWithoutExtension
  163.      */
  164.     public static function appendLog($data$fileNameWithoutExtension 'tests'$addDataBefore null$toOneLine true)
  165.     {
  166.         try {
  167.             $path null;
  168.             if (is_file($fileNameWithoutExtension)) {
  169.                 $path $fileNameWithoutExtension;
  170.             } else {
  171.                 $path self::findParentPathWithDir(__DIR__, ['src''var']) . '/var/log/' $fileNameWithoutExtension ".log";
  172.             }
  173.             if (is_array($data)) {
  174. //            $data = json_encode($data);
  175.                 $data = ($toOneLine StringUtils::arrayToOneLineString($data) : var_export($datatrue));
  176.             }
  177.             if ($addDataBefore) {
  178.                 if (is_array($addDataBefore)) {
  179.                     $addDataBeforeArr $addDataBefore;
  180.                     $addDataBefore "";
  181.                     foreach ($addDataBeforeArr as $dataLable => $dataTmp) {
  182.                         if (is_object($dataTmp) && (ReflectionUtils::hasParentClass($dataTmp, [\Exception::class, \Error::class]))) {
  183.                             if (is_numeric($dataLable)) {
  184.                                 $dataLable get_class($dataTmp);
  185.                             }
  186.                             $dataTmp $dataTmp->getMessage() . ". (File: " $dataTmp->getFile() . ":" $dataTmp->getLine() .
  187.                                 ". Trace: " var_export(self::getBacktrace($dataTmp->getTrace()), true) . ")";
  188.                         }
  189.                         if (!is_numeric($dataLable)) {
  190.                             $dataLable ucfirst($dataLable);
  191.                         }
  192.                         $addNext "";
  193.                         if (is_numeric($dataLable) && is_string($dataTmp)) {
  194.                             $addNext ucfirst($dataTmp);
  195.                         } else {
  196.                             if (is_bool($dataTmp) || is_null($dataTmp)) {
  197.                                 $dataTmp json_encode($dataTmp);
  198.                             }
  199.                             $addNext "{$dataLable}: " $dataTmp;
  200.                         }
  201.                         $addDataBefore .= ($addDataBefore ". " "") . $addNext;
  202.                     }
  203.                 }
  204.                 $data $addDataBefore $data "\r\n";
  205.             }
  206.             self::writeTxtToFile($data$pathnullfalsenullnull,
  207.                 falsetruetrue);
  208.         } catch (\Exception $exception) {
  209.             try {
  210.                 self::writeTxtToFile("Cant append log. Exception: {$exception->getMessage()}{$exception->getFile()}:{$exception->getLine()}$path,
  211.                     nullfalsenullnull,
  212.                     falsetruetrue);
  213.             } catch (\Exception $exception) {
  214.             }
  215.         }
  216.     }
  217.     public static function canAddDebugLog(): bool
  218.     {
  219.         return isset($_ENV["DEBUG_LOG"]) && $_ENV["DEBUG_LOG"] == 1;
  220.     }
  221.     public static function appendTestLog($data$addDataBefore null$toOneLine true)
  222.     {
  223.         self::appendLog($data'tests'$addDataBefore$toOneLine);
  224.     }
  225.     public static function appendQueryLog($data$addDataBefore null$toOneLine true)
  226.     {
  227.         self::appendLog($data'queryLog'$addDataBefore$toOneLine);
  228.     }
  229.     public static function appendTgBotLog($data$addDataBefore null$toOneLine true)
  230.     {
  231.         self::appendLog($data'tgBotLog'$addDataBefore$toOneLine);
  232.     }
  233.     public static function appendPyTgStderrLog($data$addDataBefore null$toOneLine true)
  234.     {
  235.         self::appendLog($data'pyTgStderrLog'$addDataBefore$toOneLine);
  236.     }
  237.     public static function appendSuccessRoomAccessLog($data$addDataBefore null$toOneLine true)
  238.     {
  239.         self::appendLog($data'successRoomAccess'$addDataBefore$toOneLine);
  240.     }
  241.     public static function appendUserStartedStreamLog($data$addDataBefore null$toOneLine true)
  242.     {
  243.         self::appendLog($data'userStartedStream'$addDataBefore$toOneLine);
  244.     }
  245.     public static function appendAuthLog($data$addDataBefore null$toOneLine true)
  246.     {
  247.         self::appendLog($data'authLog'$addDataBefore$toOneLine);
  248.     }
  249.     /**
  250.      * {@inheritdoc}
  251.      * @return null
  252.      */
  253.     static function writeTxtToFile($data$fileName 'logs.txt'string $findRootDirName nullbool $jsonEncode false,
  254.                                    $caption null$do_var_export false$is_all_defined_vars false$addDate false,
  255.                                    bool $append false)
  256.     {
  257.         if ($findRootDirName) {
  258.             $logDirPath "./";
  259.             $logDirRealPath null;
  260.             $dirLevel 0;
  261.             while (!str_ends_with(($logDirRealPath realpath($logDirPath)), "/" $findRootDirName)) {
  262.                 $logDirPath .= "../";
  263.                 $dirLevel++;
  264.                 if ($dirLevel == 500) {
  265.                     throw new \Exception('Cant\'t find root dir.');
  266.                 }
  267.             }
  268.             $fileName $logDirRealPath "/" $fileName;
  269.         }
  270.         try {
  271.             if ($is_all_defined_vars) {
  272.                 if ($caption == null) {
  273.                     $caption "all_defined_vars";
  274.                 }
  275.                 $allVars = [];
  276.                 foreach ($data as $varName => $varData) {
  277.                     $isClassObj = !is_bool($varData) && !is_int($varData) && !is_float($varData) && !is_string($varData) && !is_array($varData);
  278.                     if ($isClassObj) {
  279.                         $allVars[$varName] = get_class($varData);
  280.                     } else {
  281.                         $allVars[$varName] = $varData;
  282.                     }
  283.                     if (is_array($varData)) {
  284.                         $allVars[$varName] = array_keys($varData);
  285.                     }
  286.                 }
  287.                 $data $allVars;
  288.             }
  289.         } catch (\Exception $ex) {
  290.             $data "error: " $ex->getMessage();
  291.         }
  292.         if ($do_var_export) {
  293.             $data var_export($datatrue);
  294.         }
  295.         if ($caption) {
  296. //            $data = $caption . "-->\n" . $data . "\n<--" . $caption;
  297.             $data $caption ": " $data;
  298.         }
  299.         if ($addDate) {
  300.             $data = (new \DateTime())->format('d.m.Y H:i:s') . ": " $data;
  301.         }
  302.         $flags 0;
  303.         if ($append) {
  304.             $flags FILE_APPEND LOCK_EX;
  305.         }
  306.         if ($jsonEncode) {
  307.             $data json_encode($dataJSON_PRETTY_PRINT);
  308.         }
  309.         $myfile file_put_contents($fileName$data PHP_EOL$flags);
  310.     }
  311.     public static function getHostUrl($slashAtEnd true): string
  312.     {
  313.         $url $_SERVER["REQUEST_SCHEME"] . "://" $_SERVER['SERVER_NAME'] .
  314.             (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] ? ":" $_SERVER['SERVER_PORT'] : "") .
  315.             ($slashAtEnd "/" "");
  316.         return $url;
  317.     }
  318.     public static function filterArray($array$callback null$childElementMethodName null$childElementMethodResult null): array
  319.     {
  320.         $array array_filter($array, function ($curElement) use ($callback$childElementMethodName$childElementMethodResult) {
  321.             $result = (!$callback || ($callback($curElement)) &&
  322.                 (!$childElementMethodName || call_user_func([$curElement$childElementMethodName]) == $childElementMethodResult));
  323.             return $result;
  324.         });
  325.         return $array;
  326.     }
  327.     public static function getBacktrace(array $backtrace null): ?array
  328.     {
  329.         if (!$backtrace) {
  330.             $backtrace debug_backtrace();
  331.         }
  332.         foreach ($backtrace as &$trace) {
  333.             if (isset($trace['file']) && isset($trace["line"]) && isset($trace["function"])) {
  334.                 $trace "{$trace['file']}:{$trace["line"]} (->{$trace["function"]})";
  335.             } else {
  336.                 $trace "...";
  337.             }
  338.         }
  339.         return $backtrace;
  340.     }
  341.     public static function removeKey(array $arraystring $key): array
  342.     {
  343.         unset($array[$key]);
  344.         return $array;
  345.     }
  346.     /**
  347.      * @param null|array|mixed $object
  348.      * @param array|mixed $data
  349.      * @param \Closure|null $createObjectCallback
  350.      */
  351.     public function setObjectDataFromArray($object null$data$includedDataKeys null,
  352.                                            \Closure $createObjectCallback null,
  353.         $beforeObjectPersistCallback null)
  354.     {
  355.         if ($object && !is_array($object)) {
  356.             $object = [$object];
  357.         }
  358.         if (!is_array($data)) {
  359.             $data = [$data];
  360.         }
  361.         $objectIndex = -1;
  362.         foreach ($data as $currentData) {
  363.             $objectIndex++;
  364.             $currentObject null;
  365.             if (!$object) {
  366.                 $currentObject $createObjectCallback();
  367.             } else {
  368.                 $currentObject $object[$objectIndex];
  369.             }
  370.             foreach ($currentData as $setMethod => $dataElement) {
  371.                 if ($includedDataKeys && !in_array($setMethod$includedDataKeys)) {
  372.                     continue;
  373.                 }
  374.                 $setMethod 'set' ucfirst($setMethod);
  375.                 if (method_exists($currentObject$setMethod)) {
  376.                     $currentObject->{$setMethod}($dataElement);
  377.                 }
  378.             }
  379.             if (!$object) {
  380.                 if (!$beforeObjectPersistCallback || $beforeObjectPersistCallback($currentObject$currentData)) {
  381.                     $this->em->persist($currentObject);
  382.                     $this->em->flush();
  383.                 }
  384.             }
  385.         }
  386.     }
  387.     /**
  388.      * @param mixed|array $object
  389.      */
  390.     public static function objectToArray($object$includedDataKeys$onDataCreateCallback null,
  391.                                          array $overrideKeyNames null): array
  392.     {
  393.         $objects $object;
  394.         if (!is_array($objects)) {
  395.             $objects = [$object];
  396.         }
  397.         $objectsData = [];
  398.         $objectsDataIndex = -1;
  399.         foreach ($objects as $currentObject) {
  400.             $objectsDataIndex++;
  401.             $currentObjectData = [];
  402.             foreach ($includedDataKeys as $dataKey) {
  403.                 $getMethod 'get' ucfirst($dataKey);
  404.                 if ($overrideKeyNames) {
  405.                     if (in_array($dataKeyarray_keys($overrideKeyNames))) {
  406.                         $dataKey $overrideKeyNames[$dataKey];
  407.                     }
  408.                 }
  409.                 $currentObjectData[$dataKey] = $currentObject->{$getMethod}();
  410.             }
  411.             if ($onDataCreateCallback) {
  412.                 $currentObjectData $onDataCreateCallback($currentObject$currentObjectData);
  413.             }
  414.             if ($currentObjectData) {
  415.                 $objectsData[$objectsDataIndex] = $currentObjectData;
  416.             }
  417.         }
  418.         if (is_array($object)) {
  419.             return $objectsData;
  420.         } else {
  421.             return $objectsData[0];
  422.         }
  423.     }
  424.     /**
  425.      * @param mixed|array $object
  426.      */
  427.     public static function objectToId($object)
  428.     {
  429.         $objects $object;
  430.         $isArray is_array($objects);
  431.         if (!$isArray) {
  432.             $objects = [$object];
  433.         }
  434.         $result = [];
  435.         foreach ($objects as $object) {
  436.             $result[] = $object->getId();
  437.         }
  438.         if ($isArray) {
  439.             return $result;
  440.         } else {
  441.             return $result[0];
  442.         }
  443.     }
  444.     public static function objectToStringId($object): string
  445.     {
  446.         return implode(","self::objectToId($object));
  447.     }
  448.     public static function sumObjectField($object$field)
  449.     {
  450.         $objects $object;
  451.         $isArray is_array($objects);
  452.         if (!$isArray) {
  453.             $objects = [$object];
  454.         }
  455.         $result 0;
  456.         $field "get" ucfirst($field);
  457.         foreach ($objects as $object) {
  458.             $result += $object->$field();
  459.         }
  460.         return $result;
  461.     }
  462.     /**
  463.      *
  464.      * $callback = function($curElement, $elementIndex, $key) {};
  465.      *
  466.      * @param $array
  467.      * @param null $callback
  468.      * @param null $childElementName
  469.      * @param null $childElementValue
  470.      * @param null $element
  471.      * @param null $skipElement
  472.      * @param null $childArraysElementValueRegex
  473.      * @param bool $returnDetailedResult
  474.      * @return array|int
  475.      */
  476.     static public function findIndexInArray($array$callback null$childElementName null$childElementValue null$element null,
  477.                                             $skipElement null$childArraysElementValueRegex nullbool $returnDetailedResult false,
  478.                                             $childElementMethodName null$childElementMethodResult null$childArraysElementValue null)
  479.     {
  480.         $elementIndex 0;
  481.         $foundIndex = -1;
  482.         $foundKey null;
  483.         $detailedResult = [];
  484.         foreach ($array as $key => $curElement) {
  485.             $found = (!$skipElement || $skipElement != $curElement) &&
  486.                 ((!$callback || $callback($curElement$elementIndex$key)) &&
  487.                     (!$childElementName || (isset($curElement[$childElementName]) && (!$childElementValue || $curElement[$childElementName] == $childElementValue))) &&
  488.                     (!$element || $element == $curElement) &&
  489.                     (!$childElementMethodName || call_user_func([$curElement$childElementMethodName]) == $childElementMethodResult));
  490.             if ($found && ($childArraysElementValueRegex || $childArraysElementValue)) {
  491.                 $found false;
  492.                 $detailedResult['foundChildElementValue'] = null;
  493.                 $tmpArray = ($childElementName $curElement[$childElementName] : $curElement);
  494.                 foreach ($tmpArray as $childKey => $curChildElement) {
  495.                     if ((!$childArraysElementValueRegex || preg_match($childArraysElementValueRegex$curChildElement)) &&
  496.                         (!$childArraysElementValue || $curChildElement == $childArraysElementValue))
  497.                     {
  498.                         $detailedResult['foundChildElementValue'] = $curChildElement;
  499.                         $found true;
  500.                         break;
  501.                     }
  502.                 }
  503.             }
  504.             if ($found) {
  505.                 $foundIndex $elementIndex;
  506.                 $foundKey $key;
  507.                 break;
  508.             }
  509.             $elementIndex++;
  510.         }
  511.         if ($returnDetailedResult) {
  512.             $detailedResult['index'] = $foundIndex;
  513.             $detailedResult['key'] = $foundKey;
  514.             return $detailedResult;
  515.         } else {
  516.             return $foundIndex;
  517.         }
  518.     }
  519.     /**
  520.      * @return array|int
  521.      */
  522.     static public function findIndexInArrayByElement($array$element null)
  523.     {
  524.         return self::findIndexInArray($arraynullnullnull$element);
  525.     }
  526.     public static function findInArrayByChildArrayElementValue($array$childArrayElementValue$childElementName null,
  527.                                                                bool $returnDetailedResult false)
  528.     {
  529.         return self::findInArray($arraynull$childElementNamenullnullnull,
  530.             nullnull$returnDetailedResultnull,
  531.             null$childArrayElementValue);
  532.     }
  533.     static public function findInArray($array$callback null$childElementName null$childElementValue null$element null,
  534.                                        $skipElement null$getResultElementValueWithName null,
  535.                                        $childArraysElementValueRegex null,
  536.                                        bool $returnDetailedResult false$childElementMethodName null$childElementMethodResult null,
  537.         $childArraysElementValue null)
  538.     {
  539.         $result self::findIndexInArray($array$callback$childElementName$childElementValue$element$skipElement$childArraysElementValueRegex,
  540.             $returnDetailedResult$childElementMethodName$childElementMethodResult$childArraysElementValue);
  541.         $index = ($returnDetailedResult $result['index'] : $result);
  542.         $subResult $index;
  543.         if ($index > -|| is_string($index)) {
  544.             $foundKey array_keys($array)[$index];
  545.             if ($getResultElementValueWithName) {
  546.                 $subResult $array[$foundKey][$getResultElementValueWithName];
  547.             } else {
  548.                 $subResult $array[$foundKey];
  549.             }
  550.         } else {
  551.             $subResult null;
  552.         }
  553.         if ($returnDetailedResult) {
  554.             $result['result'] = $subResult;
  555.         } else {
  556.             $result $subResult;
  557.         }
  558.         return $result;
  559.     }
  560.     public static function findInArrayByElementMethodResult($array$childElementMethodName$childElementMethodResult)
  561.     {
  562.         return self::findInArray($arraynullnullnullnullnull,
  563.             nullnullfalse$childElementMethodName,
  564.             $childElementMethodResult);
  565.     }
  566.     public static function convertArray(array $array$elementMethodName null)
  567.     {
  568.         foreach ($array as $key => $value) {
  569.             if ($elementMethodName) {
  570.                 $array[$key] = call_user_func([$value$elementMethodName]);
  571.             }
  572.         }
  573.         return $array;
  574.     }
  575.     public static function sumArray($array$elementMethodName null, array $keys null): float
  576.     {
  577.         if ($keys) {
  578.             return Other::sumArray(array_intersect_key($arrayarray_flip($keys)));
  579.         }
  580.         /** @var float $sum */
  581.         $sum 0.0;
  582.         foreach ($array as $key => $value) {
  583.             if ($elementMethodName) {
  584.                 $sum += (float)call_user_func([$value$elementMethodName]);
  585.             } else {
  586.                 $sum += (float)$value;
  587.             }
  588.         }
  589.         return $sum;
  590.     }
  591.     public static function getVarPath(?string $subPath null): string
  592.     {
  593.         $path self::getRootPath'/var/' . ($subPath ?: "")) ;
  594.         return $path;
  595.     }
  596.     public static function getRootPath(?string $subPath null): string
  597.     {
  598.         $path self::findParentPathWithDir(__DIR__, ['src''var']) . ($subPath ?: "");
  599.         return $path;
  600.     }
  601.     public static function setSettings(array $settings nullstring $settingName null$settingValue null$fileName "settings.json"$isAbsolutePath false)
  602.     {
  603.         if (!$isAbsolutePath) {
  604.             $fileName self::getVarPath($fileName);
  605.         }
  606.         if ($settingName) {
  607.             $settings = [$settingName => $settingValue];
  608.         }
  609.         $currentSettings = [];
  610.         if (is_file($fileName)) {
  611.             $currentSettings json_decode(file_get_contents($fileName), true);
  612.         }
  613.         foreach ($settings as $key => $value) {
  614.             $currentSettings[$key] = $value;
  615.         }
  616.         self::writeTxtToFile($currentSettings$fileNamenulltrue);
  617.     }
  618.     /**
  619.      * @param string|null $settingName
  620.      * @param bool $nullIfNotExists
  621.      * @param $fileName
  622.      * @return array|mixed|null
  623.      * @throws \Exception
  624.      */
  625.     public static function getSettings(string $settingName nullbool $nullIfNotExists false$fileName "settings.json"$isAbsolutePath false)
  626.     {
  627.         if (!$isAbsolutePath) {
  628.             $fileName self::getVarPath($fileName);
  629.         }
  630.         $settings = [];
  631.         if (is_file($fileName)) {
  632.             $settings json_decode(file_get_contents($fileName), true);
  633.         }
  634.         if ($settingName) {
  635.             if (!isset($settings[$settingName])) {
  636.                 if ($nullIfNotExists) {
  637.                     return null;
  638.                 } else {
  639.                     throw new \Exception((is_file($fileName) ? "Setting not exists: $settingName"Settings file not exists: $fileName"));
  640.                 }
  641.             }
  642.             return $settings[$settingName];
  643.         } else {
  644.             return $settings;
  645.         }
  646.     }
  647.     public static function findInChildArray($array$childArrayKey$childArrayValue): ?array
  648.     {
  649.         foreach ($array as $key => $element) {
  650.             if (isset($element[$childArrayKey]) && $element[$childArrayKey] == $childArrayValue) {
  651.                 return ["key" => $key"childKey" => $childArrayKey"value" => $childArrayValue"childArray" => $element];
  652.             }
  653.         }
  654.         return null;
  655.     }
  656.     public static function getIdIndexedEntityArray(array $entities): array
  657.     {
  658.         $arr = [];
  659.         foreach ($entities as $item) {
  660.             $arr[$item->getId()] = $item;
  661.         }
  662.         return $arr;
  663.     }
  664.     public static function removeFilesByRegex($directory$regex) {
  665.         $files glob($directory '/*');
  666.         $removeFiles = [];
  667.         if ($files !== false) {
  668.             foreach ($files as $file) {
  669.                 if (preg_match($regexbasename($file))) {
  670.                     $removeFiles[] = $file;
  671.                 }
  672.             }
  673.             foreach ($removeFiles as $file) {
  674.                 unlink($file);
  675.             }
  676.         }
  677.     }
  678.     public static function getRequestAttributes(Request $request)
  679.     {
  680.         return array_intersect_key($request->attributes->all(),
  681.             array_flip(array_filter(array_keys($request->attributes->all()),
  682.                 function ($key) {return !str_starts_with($key"_");})));
  683.     }
  684.     public static function sleepMs($milliseconds) {
  685.         $microseconds $milliseconds 1000;
  686.         usleep($microseconds);
  687.     }
  688.     public static function filterArrayNotNull(array $arr): array
  689.     {
  690.         return array_filter($arr, function ($value) {
  691.             return $value !== null;
  692.         });
  693.     }
  694.     public static function assertObjectHydrated($objectbool $hydrateFlag null)
  695.     {
  696.         if (!$object && !$hydrateFlag) {
  697.             throw new \Exception("Object not hydrated");
  698.         }
  699.     }
  700.     /**
  701.      * @param array|mixed $value
  702.      * @param $callback
  703.      * @return void
  704.      */
  705.     public static function forEach($value$callback): void
  706.     {
  707.         if (is_array($value)) {
  708.             foreach ($value as $element) {
  709.                 $callback($element);
  710.             }
  711.         } else {
  712.             $callback($value);
  713.         }
  714.     }
  715.     public static function runProcess(string $namestring $args$throwOnNonZeroExitCode falsebool $async false): array
  716.     {
  717. //        $command = "$name " . escapeshellarg($args);
  718.         $command = ($async "nohup " "") . "$name $args. ($async " > " $_ENV['PYTHON_TELEGRAM_PATH'] . "/var/log/aaa 2>&1 & echo $!" "");
  719. //        if (strpos($command, "python3")) {
  720. //            throw new \Exception("$command");
  721. //        }
  722.         if ($async) {
  723.             exec($command$output);
  724.             $pid = (int)$output[0];
  725.             return [
  726.                 'pid' => $pid,
  727.             ];
  728.         }
  729.         // Open a process for the Python script
  730.         $descriptorspec = [
  731.             => ['pipe''r'], // stdin is a pipe that the child will read from
  732.             => ['pipe''w'], // stdout is a pipe that the child will write to
  733.             => ['pipe''w']  // stderr is a pipe that the child will write to
  734.         ];
  735.         $process proc_open($command$descriptorspec$pipes);
  736.         if (is_resource($process)) {
  737.             $status proc_get_status($process);
  738.             $pid $status['pid'] ?? null;
  739.             fclose($pipes[0]);
  740.             $stdout stream_get_contents($pipes[1]);
  741.             fclose($pipes[1]);
  742.             $stderr stream_get_contents($pipes[2]);
  743.             fclose($pipes[2]);
  744.             $exitCode proc_close($process);
  745.             // Output any errors
  746. //            if (!empty($stderr)) {
  747. //                throw new \Exception("Errors:\n" . $stderr) ;
  748. //            }
  749.             $result = [
  750.                 'stdout' => trim($stdout),
  751.                 'stderr' => $stderr,
  752.                 'exitCode' => $exitCode,
  753.                 "pid" => $pid,
  754.             ];
  755.             if ($throwOnNonZeroExitCode && $exitCode !== 0) {
  756.                 throw new \Exception("Exit code is not 0: " $stderr);
  757.             }
  758.             return $result;
  759.         } else {
  760.             throw new \Exception("Failed to open process.") ;
  761.         }
  762.     }
  763.     public static function hasArrayCurlFile(array $arr): bool
  764.     {
  765.         foreach ($arr as $value) {
  766.             if ($value instanceof \CURLFile) {
  767.                 return true;
  768.             }
  769.             if (is_array($value) && self::hasArrayCurlFile($value)) {
  770.                 return true;
  771.             }
  772.         }
  773.         return false;
  774.     }
  775. }