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

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.     public static function getRemoteIp(): ?string
  347.     {
  348.         return $_SERVER['REMOTE_ADDR'] ?? null;
  349.     }
  350.     /**
  351.      * @param null|array|mixed $object
  352.      * @param array|mixed $data
  353.      * @param \Closure|null $createObjectCallback
  354.      */
  355.     public function setObjectDataFromArray($object null$data$includedDataKeys null,
  356.                                            \Closure $createObjectCallback null,
  357.         $beforeObjectPersistCallback null)
  358.     {
  359.         if ($object && !is_array($object)) {
  360.             $object = [$object];
  361.         }
  362.         if (!is_array($data)) {
  363.             $data = [$data];
  364.         }
  365.         $objectIndex = -1;
  366.         foreach ($data as $currentData) {
  367.             $objectIndex++;
  368.             $currentObject null;
  369.             if (!$object) {
  370.                 $currentObject $createObjectCallback();
  371.             } else {
  372.                 $currentObject $object[$objectIndex];
  373.             }
  374.             foreach ($currentData as $setMethod => $dataElement) {
  375.                 if ($includedDataKeys && !in_array($setMethod$includedDataKeys)) {
  376.                     continue;
  377.                 }
  378.                 $setMethod 'set' ucfirst($setMethod);
  379.                 if (method_exists($currentObject$setMethod)) {
  380.                     $currentObject->{$setMethod}($dataElement);
  381.                 }
  382.             }
  383.             if (!$object) {
  384.                 if (!$beforeObjectPersistCallback || $beforeObjectPersistCallback($currentObject$currentData)) {
  385.                     $this->em->persist($currentObject);
  386.                     $this->em->flush();
  387.                 }
  388.             }
  389.         }
  390.     }
  391.     /**
  392.      * @param mixed|array $object
  393.      */
  394.     public static function objectToArray($object$includedDataKeys$onDataCreateCallback null,
  395.                                          array $overrideKeyNames null): array
  396.     {
  397.         $objects $object;
  398.         if (!is_array($objects)) {
  399.             $objects = [$object];
  400.         }
  401.         $objectsData = [];
  402.         $objectsDataIndex = -1;
  403.         foreach ($objects as $currentObject) {
  404.             $objectsDataIndex++;
  405.             $currentObjectData = [];
  406.             foreach ($includedDataKeys as $dataKey) {
  407.                 $getMethod 'get' ucfirst($dataKey);
  408.                 if ($overrideKeyNames) {
  409.                     if (in_array($dataKeyarray_keys($overrideKeyNames))) {
  410.                         $dataKey $overrideKeyNames[$dataKey];
  411.                     }
  412.                 }
  413.                 $currentObjectData[$dataKey] = $currentObject->{$getMethod}();
  414.             }
  415.             if ($onDataCreateCallback) {
  416.                 $currentObjectData $onDataCreateCallback($currentObject$currentObjectData);
  417.             }
  418.             if ($currentObjectData) {
  419.                 $objectsData[$objectsDataIndex] = $currentObjectData;
  420.             }
  421.         }
  422.         if (is_array($object)) {
  423.             return $objectsData;
  424.         } else {
  425.             return $objectsData[0];
  426.         }
  427.     }
  428.     /**
  429.      * @param mixed|array $object
  430.      */
  431.     public static function objectToId($object)
  432.     {
  433.         $objects $object;
  434.         $isArray is_array($objects);
  435.         if (!$isArray) {
  436.             $objects = [$object];
  437.         }
  438.         $result = [];
  439.         foreach ($objects as $object) {
  440.             $result[] = $object->getId();
  441.         }
  442.         if ($isArray) {
  443.             return $result;
  444.         } else {
  445.             return $result[0];
  446.         }
  447.     }
  448.     public static function objectToStringId($object): string
  449.     {
  450.         return implode(","self::objectToId($object));
  451.     }
  452.     public static function sumObjectField($object$field)
  453.     {
  454.         $objects $object;
  455.         $isArray is_array($objects);
  456.         if (!$isArray) {
  457.             $objects = [$object];
  458.         }
  459.         $result 0;
  460.         $field "get" ucfirst($field);
  461.         foreach ($objects as $object) {
  462.             $result += $object->$field();
  463.         }
  464.         return $result;
  465.     }
  466.     /**
  467.      *
  468.      * $callback = function($curElement, $elementIndex, $key) {};
  469.      *
  470.      * @param $array
  471.      * @param null $callback
  472.      * @param null $childElementName
  473.      * @param null $childElementValue
  474.      * @param null $element
  475.      * @param null $skipElement
  476.      * @param null $childArraysElementValueRegex
  477.      * @param bool $returnDetailedResult
  478.      * @return array|int
  479.      */
  480.     static public function findIndexInArray($array$callback null$childElementName null$childElementValue null$element null,
  481.                                             $skipElement null$childArraysElementValueRegex nullbool $returnDetailedResult false,
  482.                                             $childElementMethodName null$childElementMethodResult null$childArraysElementValue null)
  483.     {
  484.         $elementIndex 0;
  485.         $foundIndex = -1;
  486.         $foundKey null;
  487.         $detailedResult = [];
  488.         foreach ($array as $key => $curElement) {
  489.             $found = (!$skipElement || $skipElement != $curElement) &&
  490.                 ((!$callback || $callback($curElement$elementIndex$key)) &&
  491.                     (!$childElementName || (isset($curElement[$childElementName]) && (!$childElementValue || $curElement[$childElementName] == $childElementValue))) &&
  492.                     (!$element || $element == $curElement) &&
  493.                     (!$childElementMethodName || call_user_func([$curElement$childElementMethodName]) == $childElementMethodResult));
  494.             if ($found && ($childArraysElementValueRegex || $childArraysElementValue)) {
  495.                 $found false;
  496.                 $detailedResult['foundChildElementValue'] = null;
  497.                 $tmpArray = ($childElementName $curElement[$childElementName] : $curElement);
  498.                 foreach ($tmpArray as $childKey => $curChildElement) {
  499.                     if ((!$childArraysElementValueRegex || preg_match($childArraysElementValueRegex$curChildElement)) &&
  500.                         (!$childArraysElementValue || $curChildElement == $childArraysElementValue))
  501.                     {
  502.                         $detailedResult['foundChildElementValue'] = $curChildElement;
  503.                         $found true;
  504.                         break;
  505.                     }
  506.                 }
  507.             }
  508.             if ($found) {
  509.                 $foundIndex $elementIndex;
  510.                 $foundKey $key;
  511.                 break;
  512.             }
  513.             $elementIndex++;
  514.         }
  515.         if ($returnDetailedResult) {
  516.             $detailedResult['index'] = $foundIndex;
  517.             $detailedResult['key'] = $foundKey;
  518.             return $detailedResult;
  519.         } else {
  520.             return $foundIndex;
  521.         }
  522.     }
  523.     /**
  524.      * @return array|int
  525.      */
  526.     static public function findIndexInArrayByElement($array$element null)
  527.     {
  528.         return self::findIndexInArray($arraynullnullnull$element);
  529.     }
  530.     public static function findInArrayByChildArrayElementValue($array$childArrayElementValue$childElementName null,
  531.                                                                bool $returnDetailedResult false)
  532.     {
  533.         return self::findInArray($arraynull$childElementNamenullnullnull,
  534.             nullnull$returnDetailedResultnull,
  535.             null$childArrayElementValue);
  536.     }
  537.     static public function findInArray($array$callback null$childElementName null$childElementValue null$element null,
  538.                                        $skipElement null$getResultElementValueWithName null,
  539.                                        $childArraysElementValueRegex null,
  540.                                        bool $returnDetailedResult false$childElementMethodName null$childElementMethodResult null,
  541.         $childArraysElementValue null)
  542.     {
  543.         $result self::findIndexInArray($array$callback$childElementName$childElementValue$element$skipElement$childArraysElementValueRegex,
  544.             $returnDetailedResult$childElementMethodName$childElementMethodResult$childArraysElementValue);
  545.         $index = ($returnDetailedResult $result['index'] : $result);
  546.         $subResult $index;
  547.         if ($index > -|| is_string($index)) {
  548.             $foundKey array_keys($array)[$index];
  549.             if ($getResultElementValueWithName) {
  550.                 $subResult $array[$foundKey][$getResultElementValueWithName];
  551.             } else {
  552.                 $subResult $array[$foundKey];
  553.             }
  554.         } else {
  555.             $subResult null;
  556.         }
  557.         if ($returnDetailedResult) {
  558.             $result['result'] = $subResult;
  559.         } else {
  560.             $result $subResult;
  561.         }
  562.         return $result;
  563.     }
  564.     public static function findInArrayByElementMethodResult($array$childElementMethodName$childElementMethodResult)
  565.     {
  566.         return self::findInArray($arraynullnullnullnullnull,
  567.             nullnullfalse$childElementMethodName,
  568.             $childElementMethodResult);
  569.     }
  570.     public static function convertArray(array $array$elementMethodName null)
  571.     {
  572.         foreach ($array as $key => $value) {
  573.             if ($elementMethodName) {
  574.                 $array[$key] = call_user_func([$value$elementMethodName]);
  575.             }
  576.         }
  577.         return $array;
  578.     }
  579.     public static function sumArray($array$elementMethodName null, array $keys null): float
  580.     {
  581.         if ($keys) {
  582.             return Other::sumArray(array_intersect_key($arrayarray_flip($keys)));
  583.         }
  584.         /** @var float $sum */
  585.         $sum 0.0;
  586.         foreach ($array as $key => $value) {
  587.             if ($elementMethodName) {
  588.                 $sum += (float)call_user_func([$value$elementMethodName]);
  589.             } else {
  590.                 $sum += (float)$value;
  591.             }
  592.         }
  593.         return $sum;
  594.     }
  595.     public static function getVarPath(?string $subPath null): string
  596.     {
  597.         $path self::getRootPath'/var/' . ($subPath ?: "")) ;
  598.         return $path;
  599.     }
  600.     public static function getRootPath(?string $subPath null): string
  601.     {
  602.         $path self::findParentPathWithDir(__DIR__, ['src''var']) . ($subPath ?: "");
  603.         return $path;
  604.     }
  605.     public static function getProjectDirName(): string
  606.     {
  607.         $rootPath explode("/"Other::getRootPath());
  608.         $dirName end($rootPath);
  609.         return $dirName;
  610.     }
  611.     public static function setSettings(array $settings nullstring $settingName null$settingValue null$fileName "settings.json"$isAbsolutePath false)
  612.     {
  613.         if (!$isAbsolutePath) {
  614.             $fileName self::getVarPath($fileName);
  615.         }
  616.         if ($settingName) {
  617.             $settings = [$settingName => $settingValue];
  618.         }
  619.         $currentSettings = [];
  620.         if (is_file($fileName)) {
  621.             $currentSettings json_decode(file_get_contents($fileName), true);
  622.         }
  623.         foreach ($settings as $key => $value) {
  624.             $currentSettings[$key] = $value;
  625.         }
  626.         self::writeTxtToFile($currentSettings$fileNamenulltrue);
  627.     }
  628.     /**
  629.      * @param string|null $settingName
  630.      * @param bool $nullIfNotExists
  631.      * @param $fileName
  632.      * @return array|mixed|null
  633.      * @throws \Exception
  634.      */
  635.     public static function getSettings(string $settingName nullbool $nullIfNotExists false$fileName "settings.json"$isAbsolutePath false)
  636.     {
  637.         if (!$isAbsolutePath) {
  638.             $fileName self::getVarPath($fileName);
  639.         }
  640.         $settings = [];
  641.         if (is_file($fileName)) {
  642.             $settings json_decode(file_get_contents($fileName), true);
  643.         }
  644.         if ($settingName) {
  645.             if (!isset($settings[$settingName])) {
  646.                 if ($nullIfNotExists) {
  647.                     return null;
  648.                 } else {
  649.                     throw new \Exception((is_file($fileName) ? "Setting not exists: $settingName"Settings file not exists: $fileName"));
  650.                 }
  651.             }
  652.             return $settings[$settingName];
  653.         } else {
  654.             return $settings;
  655.         }
  656.     }
  657.     public static function findInChildArray($array$childArrayKey$childArrayValue): ?array
  658.     {
  659.         foreach ($array as $key => $element) {
  660.             if (isset($element[$childArrayKey]) && $element[$childArrayKey] == $childArrayValue) {
  661.                 return ["key" => $key"childKey" => $childArrayKey"value" => $childArrayValue"childArray" => $element];
  662.             }
  663.         }
  664.         return null;
  665.     }
  666.     public static function getIdIndexedEntityArray(array $entities): array
  667.     {
  668.         $arr = [];
  669.         foreach ($entities as $item) {
  670.             $arr[$item->getId()] = $item;
  671.         }
  672.         return $arr;
  673.     }
  674.     public static function removeFilesByRegex($directory$regex) {
  675.         $files glob($directory '/*');
  676.         $removeFiles = [];
  677.         if ($files !== false) {
  678.             foreach ($files as $file) {
  679.                 if (preg_match($regexbasename($file))) {
  680.                     $removeFiles[] = $file;
  681.                 }
  682.             }
  683.             foreach ($removeFiles as $file) {
  684.                 unlink($file);
  685.             }
  686.         }
  687.     }
  688.     public static function getRequestAttributes(Request $request)
  689.     {
  690.         return array_intersect_key($request->attributes->all(),
  691.             array_flip(array_filter(array_keys($request->attributes->all()),
  692.                 function ($key) {return !str_starts_with($key"_");})));
  693.     }
  694.     public static function sleepMs($milliseconds) {
  695.         $microseconds $milliseconds 1000;
  696.         usleep($microseconds);
  697.     }
  698.     public static function filterArrayNotNull(array $arr): array
  699.     {
  700.         return array_filter($arr, function ($value) {
  701.             return $value !== null;
  702.         });
  703.     }
  704.     public static function assertObjectHydrated($objectbool $hydrateFlag null)
  705.     {
  706.         if (!$object && !$hydrateFlag) {
  707.             throw new \Exception("Object not hydrated");
  708.         }
  709.     }
  710.     /**
  711.      * @param array|mixed $value
  712.      * @param $callback
  713.      * @return void
  714.      */
  715.     public static function forEach($value$callback): void
  716.     {
  717.         if (is_array($value)) {
  718.             foreach ($value as $element) {
  719.                 $callback($element);
  720.             }
  721.         } else {
  722.             $callback($value);
  723.         }
  724.     }
  725.     public static function runProcess(string $namestring $args$throwOnNonZeroExitCode falsebool $async false): array
  726.     {
  727. //        $command = "$name " . escapeshellarg($args);
  728.         $command = ($async "nohup " "") . "$name $args. ($async " > " $_ENV['PYTHON_TELEGRAM_PATH'] . "/var/log/aaa 2>&1 & echo $!" "");
  729. //        if (strpos($command, "python3")) {
  730. //            throw new \Exception("$command");
  731. //        }
  732.         if ($async) {
  733.             exec($command$output);
  734.             $pid = (int)$output[0];
  735.             return [
  736.                 'pid' => $pid,
  737.             ];
  738.         }
  739.         // Open a process for the Python script
  740.         $descriptorspec = [
  741.             => ['pipe''r'], // stdin is a pipe that the child will read from
  742.             => ['pipe''w'], // stdout is a pipe that the child will write to
  743.             => ['pipe''w']  // stderr is a pipe that the child will write to
  744.         ];
  745.         $process proc_open($command$descriptorspec$pipes);
  746.         if (is_resource($process)) {
  747.             $status proc_get_status($process);
  748.             $pid $status['pid'] ?? null;
  749.             fclose($pipes[0]);
  750.             $stdout stream_get_contents($pipes[1]);
  751.             fclose($pipes[1]);
  752.             $stderr stream_get_contents($pipes[2]);
  753.             fclose($pipes[2]);
  754.             $exitCode proc_close($process);
  755.             // Output any errors
  756. //            if (!empty($stderr)) {
  757. //                throw new \Exception("Errors:\n" . $stderr) ;
  758. //            }
  759.             $result = [
  760.                 'stdout' => trim($stdout),
  761.                 'stderr' => $stderr,
  762.                 'exitCode' => $exitCode,
  763.                 "pid" => $pid,
  764.             ];
  765.             if ($throwOnNonZeroExitCode && $exitCode !== 0) {
  766.                 throw new \Exception("Exit code is not 0: " $stderr);
  767.             }
  768.             return $result;
  769.         } else {
  770.             throw new \Exception("Failed to open process.") ;
  771.         }
  772.     }
  773.     public static function hasArrayCurlFile(array $arr): bool
  774.     {
  775.         foreach ($arr as $value) {
  776.             if ($value instanceof \CURLFile) {
  777.                 return true;
  778.             }
  779.             if (is_array($value) && self::hasArrayCurlFile($value)) {
  780.                 return true;
  781.             }
  782.         }
  783.         return false;
  784.     }
  785.     /**
  786.      * @param array $arr
  787.      * @return array{curl: array, rest: array}
  788.      */
  789.     public static function unmergeArrayCurlFiles(array $arr): array
  790.     {
  791.         $result = [
  792.             "files" => [],
  793.             "rest" => [],
  794.         ];
  795.         foreach ($arr as $key => $value) {
  796.             if ($value instanceof \CURLFile) {
  797.                 $result["files"][$key] = $value;
  798.             } else {
  799.                 $result["rest"][$key] = $value;
  800.             }
  801.         }
  802.         return $result;
  803.     }
  804.     public static function tryDoSilent($callback$returnOnUnhandledError null, callable $onHandledError null, callable $onUnhandledError null,
  805.                                        callable $onSuccess null, array $handleExceptionClasses null)
  806.     {
  807.         if (!$onUnhandledError) {
  808.             $onUnhandledError = function (\Throwable $throwable) {};
  809.         }
  810.         return self::tryDo($callback$returnOnUnhandledError$onHandledError$onUnhandledError$onSuccess$handleExceptionClasses);
  811.     }
  812.     public static function tryDo($callback$returnOnUnhandledError null, callable $onHandledError null, callable $onUnhandledError null,
  813.                                  callable $onSuccess null, array $handleExceptionClasses null)
  814.     {
  815.         try {
  816.             $result $callback();
  817.             if ($onSuccess) {
  818.                 $onSuccess($result);
  819.             } else {
  820.                 return $result;
  821.             }
  822.         } catch (\Throwable $exception) {
  823.             if ($handleExceptionClasses && $onHandledError) {
  824.                 foreach ($handleExceptionClasses as $handledException) {
  825.                     if ($exception instanceof $handledException) {
  826.                         return $onHandledError($exception);
  827.                     }
  828.                 }
  829.             }
  830.             if ($onUnhandledError) {
  831.                 return $onUnhandledError($exception);
  832.             }
  833.             if ($returnOnUnhandledError) {
  834.                 return $returnOnUnhandledError;
  835.             }
  836.             throw $exception;
  837.         }
  838.     }
  839. }