<?php
namespace App\Library\Utils\Other;
use App\Library\Utils\Dev\ReflectionUtils\ReflectionUtils;
use App\Library\Utils\StringUtils;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\HttpFoundation\Request;
class Other
{
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @param string $defaultAnswerMsg
* @return array|mixed|string|string[]|null
*/
public static function askUser(InputInterface $input, OutputInterface $output, $helper, $questionTxt, &$replaceAll = null,
$defaultAnswerMsg = null, $noMsg = null, $stopMsg = null,
array $answers = null, $defaultAnswer = "yes", $useYesNoAllAnswers = true, $allowAnyInput = false,
$stopInputOnEmptyAnswer = false, array $generateMenu = null)
{
$answer = null;
$yesNoAllAnswers = ['y', 'n', 'a', 's', 'yes', 'no', 'all'];
if ($answers === null) $answers = [];
$answers = array_merge(
($useYesNoAllAnswers ? $yesNoAllAnswers : []),
($answers ? $answers : []),
($stopInputOnEmptyAnswer ? ["stop"] : [])
);
if ($stopInputOnEmptyAnswer) $defaultAnswer = "stop";
if (!in_array($defaultAnswer, $answers)) {
$defaultAnswer = null;
}
$answerShortcuts = ['s', 'y', 'n', 'a'];
$answerShortcutReplacements = ['stop', 'yes', 'no', 'all'];
if ($generateMenu) {
$menuItemNumber = 0;
foreach ($generateMenu as $menuItemData) {
$menuCaption = ($menuItemData[1] ? $menuItemData[1] : $menuItemData[2]);
$answerReplacement = $menuItemData[2];
if (!$answerReplacement) continue;
$menuItemNumber++;
$answerStr = ($menuItemData[0] ? $menuItemData[0] : strval($menuItemNumber));
$questionTxt .= "\n" . $answerStr . ". " . $menuCaption . " ";
$answers = array_merge($answers, [$answerStr, $answerReplacement]);
if (strlen($answerStr) == 1) {
$answerShortcuts = array_merge($answerShortcuts, [$answerStr]);
$answerShortcutReplacements = array_merge($answerShortcutReplacements, [$answerReplacement]);
}
}
}
if ($defaultAnswer) $questionTxt .= "\nPress Enter - " . ($defaultAnswerMsg ? $defaultAnswerMsg : $defaultAnswer) . ' ';
while (!$replaceAll && (!$answer || (!$allowAnyInput && !in_array($answer, $answers)))) {
$question = new Question($questionTxt, '[DEFAULT]');
$answer = $helper->ask($input, $output, $question);
if ($answer == '[DEFAULT]') $answer = $defaultAnswer;
if (strlen($answer) == '1') {
$answer = str_replace($answerShortcuts, $answerShortcutReplacements, $answer);
}
}
if ($answer == 'no') {
if ($noMsg) echo $noMsg;
} else if ($answer == 'yes' || $answer == 'all') {
if ($answer == 'all') $replaceAll = true;
} else if ($answer == 'stop') {
if ($stopMsg) echo $stopMsg;
return null;
}
return $answer;
}
public static function findParentPathWithDir($path, $childDirNames)
{
if (!is_array($childDirNames)) {
$childDirNames = [$childDirNames];
}
while (true) {
$path = realpath($path . "/..");
$continueSearch = false;
foreach ($childDirNames as $childDirName) {
if (($continueSearch = !is_dir($path . "/" . $childDirName))) break;
}
if (!$continueSearch) break;
}
return $path;
}
static public function getPathStructure($path)
{
$result = [
'segments' => explode("/", $path),
];
$result['fileNameWithExtension'] = $result['segments'][array_key_last($result['segments'])];
$fileNameWithExtensionArr = explode(".", $result['fileNameWithExtension']);
$result['extension'] = $fileNameWithExtensionArr[array_key_last($fileNameWithExtensionArr)];
unset($fileNameWithExtensionArr[array_key_last($fileNameWithExtensionArr)]);
$result['fileNameWithoutExtension'] = implode(".", $fileNameWithExtensionArr);
$result['lastSegment'] = $result['segments'][array_key_last($result['segments'])];
$pathWithoutLastSegment = $result['segments'];
unset($pathWithoutLastSegment[array_key_last($pathWithoutLastSegment)]);
$pathWithoutLastSegment = implode("/", $pathWithoutLastSegment);
$result['pathWithoutLastSegment'] = $pathWithoutLastSegment;
return $result;
}
public static function getAllSubdirs($path, $asString = false, bool $addFilesString, $_dirLevel = "", $recursively = true)
{
$dirStructure = [];
$strDirStructure = "";
foreach (scandir($path) as $objName) {
if ($objName != "." && $objName != ".." & is_dir($path . DIRECTORY_SEPARATOR . $objName)) {
if ($asString) {
$filesString = "";
if ($addFilesString) {
$addFilesCount = 3;
foreach (glob("$path/$objName/*") as $filePath) {
if (is_dir($filePath)) {
continue;
}
if ($addFilesCount == 0) {
$filesString .= ($filesString ? ", " : "") . "...";
break;
}
$filesString .= ($filesString ? ", " : "") . self::getPathStructure($filePath)['lastSegment'];
$addFilesCount--;
}
if (strlen($filesString) > 150) {
$filesString = substr($filesString, 0, 150) . "...";
}
if ($filesString) {
$filesString = " ($filesString)";
}
}
$strDirStructure .= $_dirLevel . '- ' . $objName . $filesString . "\r\n" .
self::getAllSubdirs($path . DIRECTORY_SEPARATOR . $objName, true, $addFilesString, $_dirLevel . " ", true);
} else {
$dirStructure[$objName] = ($recursively ? self::getAllSubdirs($path . DIRECTORY_SEPARATOR . $objName, false, $addFilesString, "", true) :
$path . DIRECTORY_SEPARATOR . $objName);
}
}
}
if ($asString) {
return $strDirStructure;
} else {
return $dirStructure;
}
}
public static function createGuid(int $length = 16)
{
$guid = bin2hex(openssl_random_pseudo_bytes($length));
return $guid;
}
public static function createToken(): string
{
return self::createGuid(32);
}
/**
* @param array|string $addDataBefore
* @param array|string|mixed $data
* @param $fileNameWithoutExtension
*/
public static function appendLog($data, $fileNameWithoutExtension = 'tests', $addDataBefore = null, $toOneLine = true)
{
try {
$path = null;
if (is_file($fileNameWithoutExtension)) {
$path = $fileNameWithoutExtension;
} else {
$path = self::findParentPathWithDir(__DIR__, ['src', 'var']) . '/var/log/' . $fileNameWithoutExtension . ".log";
}
if (is_array($data)) {
// $data = json_encode($data);
$data = ($toOneLine ? StringUtils::arrayToOneLineString($data) : var_export($data, true));
}
if ($addDataBefore) {
if (is_array($addDataBefore)) {
$addDataBeforeArr = $addDataBefore;
$addDataBefore = "";
foreach ($addDataBeforeArr as $dataLable => $dataTmp) {
if (is_object($dataTmp) && (ReflectionUtils::hasParentClass($dataTmp, [\Exception::class, \Error::class]))) {
if (is_numeric($dataLable)) {
$dataLable = get_class($dataTmp);
}
$dataTmp = $dataTmp->getMessage() . ". (File: " . $dataTmp->getFile() . ":" . $dataTmp->getLine() .
". Trace: " . var_export(self::getBacktrace($dataTmp->getTrace()), true) . ")";
}
if (!is_numeric($dataLable)) {
$dataLable = ucfirst($dataLable);
}
$addNext = "";
if (is_numeric($dataLable) && is_string($dataTmp)) {
$addNext = ucfirst($dataTmp);
} else {
if (is_bool($dataTmp) || is_null($dataTmp)) {
$dataTmp = json_encode($dataTmp);
}
$addNext = "{$dataLable}: " . $dataTmp;
}
$addDataBefore .= ($addDataBefore ? ". " : "") . $addNext;
}
}
$data = $addDataBefore . $data . "\r\n";
}
self::writeTxtToFile($data, $path, null, false, null, null,
false, true, true);
} catch (\Exception $exception) {
try {
self::writeTxtToFile("Cant append log. Exception: {$exception->getMessage()}. {$exception->getFile()}:{$exception->getLine()}" , $path,
null, false, null, null,
false, true, true);
} catch (\Exception $exception) {
}
}
}
public static function canAddDebugLog(): bool
{
return isset($_ENV["DEBUG_LOG"]) && $_ENV["DEBUG_LOG"] == 1;
}
public static function appendTestLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'tests', $addDataBefore, $toOneLine);
}
public static function appendQueryLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'queryLog', $addDataBefore, $toOneLine);
}
public static function appendPyTgStderrLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'pyTgStderrLog', $addDataBefore, $toOneLine);
}
public static function appendSuccessRoomAccessLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'successRoomAccess', $addDataBefore, $toOneLine);
}
public static function appendUserStartedStreamLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'userStartedStream', $addDataBefore, $toOneLine);
}
public static function appendAuthLog($data, $addDataBefore = null, $toOneLine = true)
{
self::appendLog($data, 'authLog', $addDataBefore, $toOneLine);
}
/**
* {@inheritdoc}
* @return null
*/
static function writeTxtToFile($data, $fileName = 'logs.txt', string $findRootDirName = null, bool $jsonEncode = false,
$caption = null, $do_var_export = false, $is_all_defined_vars = false, $addDate = false,
bool $append = false)
{
if ($findRootDirName) {
$logDirPath = "./";
$logDirRealPath = null;
$dirLevel = 0;
while (!str_ends_with(($logDirRealPath = realpath($logDirPath)), "/" . $findRootDirName)) {
$logDirPath .= "../";
$dirLevel++;
if ($dirLevel == 500) {
throw new \Exception('Cant\'t find root dir.');
}
}
$fileName = $logDirRealPath . "/" . $fileName;
}
try {
if ($is_all_defined_vars) {
if ($caption == null) {
$caption = "all_defined_vars";
}
$allVars = [];
foreach ($data as $varName => $varData) {
$isClassObj = !is_bool($varData) && !is_int($varData) && !is_float($varData) && !is_string($varData) && !is_array($varData);
if ($isClassObj) {
$allVars[$varName] = get_class($varData);
} else {
$allVars[$varName] = $varData;
}
if (is_array($varData)) {
$allVars[$varName] = array_keys($varData);
}
}
$data = $allVars;
}
} catch (\Exception $ex) {
$data = "error: " . $ex->getMessage();
}
if ($do_var_export) {
$data = var_export($data, true);
}
if ($caption) {
// $data = $caption . "-->\n" . $data . "\n<--" . $caption;
$data = $caption . ": " . $data;
}
if ($addDate) {
$data = (new \DateTime())->format('d.m.Y H:i:s') . ": " . $data;
}
$flags = 0;
if ($append) {
$flags = FILE_APPEND | LOCK_EX;
}
if ($jsonEncode) {
$data = json_encode($data, JSON_PRETTY_PRINT);
}
$myfile = file_put_contents($fileName, $data . PHP_EOL, $flags);
}
public static function getHostUrl($slashAtEnd = true): string
{
$url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER['SERVER_NAME'] .
(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] ? ":" . $_SERVER['SERVER_PORT'] : "") .
($slashAtEnd ? "/" : "");
return $url;
}
public static function filterArray($array, $callback = null, $childElementMethodName = null, $childElementMethodResult = null): array
{
$array = array_filter($array, function ($curElement) use ($callback, $childElementMethodName, $childElementMethodResult) {
$result = (!$callback || ($callback($curElement)) &&
(!$childElementMethodName || call_user_func([$curElement, $childElementMethodName]) == $childElementMethodResult));
return $result;
});
return $array;
}
public static function getBacktrace(array $backtrace = null): ?array
{
if (!$backtrace) {
$backtrace = debug_backtrace();
}
foreach ($backtrace as &$trace) {
if (isset($trace['file']) && isset($trace["line"]) && isset($trace["function"])) {
$trace = "{$trace['file']}:{$trace["line"]} (->{$trace["function"]})";
} else {
$trace = "...";
}
}
return $backtrace;
}
public static function removeKey(array $array, string $key): array
{
unset($array[$key]);
return $array;
}
/**
* @param null|array|mixed $object
* @param array|mixed $data
* @param \Closure|null $createObjectCallback
*/
public function setObjectDataFromArray($object = null, $data, $includedDataKeys = null,
\Closure $createObjectCallback = null,
$beforeObjectPersistCallback = null)
{
if ($object && !is_array($object)) {
$object = [$object];
}
if (!is_array($data)) {
$data = [$data];
}
$objectIndex = -1;
foreach ($data as $currentData) {
$objectIndex++;
$currentObject = null;
if (!$object) {
$currentObject = $createObjectCallback();
} else {
$currentObject = $object[$objectIndex];
}
foreach ($currentData as $setMethod => $dataElement) {
if ($includedDataKeys && !in_array($setMethod, $includedDataKeys)) {
continue;
}
$setMethod = 'set' . ucfirst($setMethod);
if (method_exists($currentObject, $setMethod)) {
$currentObject->{$setMethod}($dataElement);
}
}
if (!$object) {
if (!$beforeObjectPersistCallback || $beforeObjectPersistCallback($currentObject, $currentData)) {
$this->em->persist($currentObject);
$this->em->flush();
}
}
}
}
/**
* @param mixed|array $object
*/
public static function objectToArray($object, $includedDataKeys, $onDataCreateCallback = null,
array $overrideKeyNames = null): array
{
$objects = $object;
if (!is_array($objects)) {
$objects = [$object];
}
$objectsData = [];
$objectsDataIndex = -1;
foreach ($objects as $currentObject) {
$objectsDataIndex++;
$currentObjectData = [];
foreach ($includedDataKeys as $dataKey) {
$getMethod = 'get' . ucfirst($dataKey);
if ($overrideKeyNames) {
if (in_array($dataKey, array_keys($overrideKeyNames))) {
$dataKey = $overrideKeyNames[$dataKey];
}
}
$currentObjectData[$dataKey] = $currentObject->{$getMethod}();
}
if ($onDataCreateCallback) {
$currentObjectData = $onDataCreateCallback($currentObject, $currentObjectData);
}
if ($currentObjectData) {
$objectsData[$objectsDataIndex] = $currentObjectData;
}
}
if (is_array($object)) {
return $objectsData;
} else {
return $objectsData[0];
}
}
/**
* @param mixed|array $object
*/
public static function objectToId($object)
{
$objects = $object;
$isArray = is_array($objects);
if (!$isArray) {
$objects = [$object];
}
$result = [];
foreach ($objects as $object) {
$result[] = $object->getId();
}
if ($isArray) {
return $result;
} else {
return $result[0];
}
}
public static function objectToStringId($object): string
{
return implode(",", self::objectToId($object));
}
public static function sumObjectField($object, $field)
{
$objects = $object;
$isArray = is_array($objects);
if (!$isArray) {
$objects = [$object];
}
$result = 0;
$field = "get" . ucfirst($field);
foreach ($objects as $object) {
$result += $object->$field();
}
return $result;
}
/**
*
* $callback = function($curElement, $elementIndex, $key) {};
*
* @param $array
* @param null $callback
* @param null $childElementName
* @param null $childElementValue
* @param null $element
* @param null $skipElement
* @param null $childArraysElementValueRegex
* @param bool $returnDetailedResult
* @return array|int
*/
static public function findIndexInArray($array, $callback = null, $childElementName = null, $childElementValue = null, $element = null,
$skipElement = null, $childArraysElementValueRegex = null, bool $returnDetailedResult = false,
$childElementMethodName = null, $childElementMethodResult = null, $childArraysElementValue = null)
{
$elementIndex = 0;
$foundIndex = -1;
$foundKey = null;
$detailedResult = [];
foreach ($array as $key => $curElement) {
$found = (!$skipElement || $skipElement != $curElement) &&
((!$callback || $callback($curElement, $elementIndex, $key)) &&
(!$childElementName || (isset($curElement[$childElementName]) && (!$childElementValue || $curElement[$childElementName] == $childElementValue))) &&
(!$element || $element == $curElement) &&
(!$childElementMethodName || call_user_func([$curElement, $childElementMethodName]) == $childElementMethodResult));
if ($found && ($childArraysElementValueRegex || $childArraysElementValue)) {
$found = false;
$detailedResult['foundChildElementValue'] = null;
$tmpArray = ($childElementName ? $curElement[$childElementName] : $curElement);
foreach ($tmpArray as $childKey => $curChildElement) {
if ((!$childArraysElementValueRegex || preg_match($childArraysElementValueRegex, $curChildElement)) &&
(!$childArraysElementValue || $curChildElement == $childArraysElementValue))
{
$detailedResult['foundChildElementValue'] = $curChildElement;
$found = true;
break;
}
}
}
if ($found) {
$foundIndex = $elementIndex;
$foundKey = $key;
break;
}
$elementIndex++;
}
if ($returnDetailedResult) {
$detailedResult['index'] = $foundIndex;
$detailedResult['key'] = $foundKey;
return $detailedResult;
} else {
return $foundIndex;
}
}
/**
* @return array|int
*/
static public function findIndexInArrayByElement($array, $element = null)
{
return self::findIndexInArray($array, null, null, null, $element);
}
public static function findInArrayByChildArrayElementValue($array, $childArrayElementValue, $childElementName = null,
bool $returnDetailedResult = false)
{
return self::findInArray($array, null, $childElementName, null, null, null,
null, null, $returnDetailedResult, null,
null, $childArrayElementValue);
}
static public function findInArray($array, $callback = null, $childElementName = null, $childElementValue = null, $element = null,
$skipElement = null, $getResultElementValueWithName = null,
$childArraysElementValueRegex = null,
bool $returnDetailedResult = false, $childElementMethodName = null, $childElementMethodResult = null,
$childArraysElementValue = null)
{
$result = self::findIndexInArray($array, $callback, $childElementName, $childElementValue, $element, $skipElement, $childArraysElementValueRegex,
$returnDetailedResult, $childElementMethodName, $childElementMethodResult, $childArraysElementValue);
$index = ($returnDetailedResult ? $result['index'] : $result);
$subResult = $index;
if ($index > -1 || is_string($index)) {
$foundKey = array_keys($array)[$index];
if ($getResultElementValueWithName) {
$subResult = $array[$foundKey][$getResultElementValueWithName];
} else {
$subResult = $array[$foundKey];
}
} else {
$subResult = null;
}
if ($returnDetailedResult) {
$result['result'] = $subResult;
} else {
$result = $subResult;
}
return $result;
}
public static function findInArrayByElementMethodResult($array, $childElementMethodName, $childElementMethodResult)
{
return self::findInArray($array, null, null, null, null, null,
null, null, false, $childElementMethodName,
$childElementMethodResult);
}
public static function convertArray(array $array, $elementMethodName = null)
{
foreach ($array as $key => $value) {
if ($elementMethodName) {
$array[$key] = call_user_func([$value, $elementMethodName]);
}
}
return $array;
}
public static function sumArray($array, $elementMethodName = null, array $keys = null): float
{
if ($keys) {
return Other::sumArray(array_intersect_key($array, array_flip($keys)));
}
/** @var float $sum */
$sum = 0.0;
foreach ($array as $key => $value) {
if ($elementMethodName) {
$sum += (float)call_user_func([$value, $elementMethodName]);
} else {
$sum += (float)$value;
}
}
return $sum;
}
public static function getVarPath(?string $subPath = null): string
{
$path = self::getRootPath( '/var/' . ($subPath ?: "")) ;
return $path;
}
public static function getRootPath(?string $subPath = null): string
{
$path = self::findParentPathWithDir(__DIR__, ['src', 'var']) . ($subPath ?: "");
return $path;
}
public static function setSettings(array $settings = null, string $settingName = null, $settingValue = null, $fileName = "settings.json", $isAbsolutePath = false)
{
if (!$isAbsolutePath) {
$fileName = self::getVarPath($fileName);
}
if ($settingName) {
$settings = [$settingName => $settingValue];
}
$currentSettings = [];
if (is_file($fileName)) {
$currentSettings = json_decode(file_get_contents($fileName), true);
}
foreach ($settings as $key => $value) {
$currentSettings[$key] = $value;
}
self::writeTxtToFile($currentSettings, $fileName, null, true);
}
/**
* @param string|null $settingName
* @param bool $nullIfNotExists
* @param $fileName
* @return array|mixed|null
* @throws \Exception
*/
public static function getSettings(string $settingName = null, bool $nullIfNotExists = false, $fileName = "settings.json", $isAbsolutePath = false)
{
if (!$isAbsolutePath) {
$fileName = self::getVarPath($fileName);
}
$settings = [];
if (is_file($fileName)) {
$settings = json_decode(file_get_contents($fileName), true);
}
if ($settingName) {
if (!isset($settings[$settingName])) {
if ($nullIfNotExists) {
return null;
} else {
throw new \Exception((is_file($fileName) ? "Setting not exists: $settingName" : "Settings file not exists: $fileName"));
}
}
return $settings[$settingName];
} else {
return $settings;
}
}
public static function findInChildArray($array, $childArrayKey, $childArrayValue): ?array
{
foreach ($array as $key => $element) {
if (isset($element[$childArrayKey]) && $element[$childArrayKey] == $childArrayValue) {
return ["key" => $key, "childKey" => $childArrayKey, "value" => $childArrayValue, "childArray" => $element];
}
}
return null;
}
public static function getIdIndexedEntityArray(array $entities): array
{
$arr = [];
foreach ($entities as $item) {
$arr[$item->getId()] = $item;
}
return $arr;
}
public static function removeFilesByRegex($directory, $regex) {
$files = glob($directory . '/*');
$removeFiles = [];
if ($files !== false) {
foreach ($files as $file) {
if (preg_match($regex, basename($file))) {
$removeFiles[] = $file;
}
}
foreach ($removeFiles as $file) {
unlink($file);
}
}
}
public static function getRequestAttributes(Request $request)
{
return array_intersect_key($request->attributes->all(),
array_flip(array_filter(array_keys($request->attributes->all()),
function ($key) {return !str_starts_with($key, "_");})));
}
public static function sleepMs($milliseconds) {
$microseconds = $milliseconds * 1000;
usleep($microseconds);
}
public static function filterArrayNotNull(array $arr): array
{
return array_filter($arr, function ($value) {
return $value !== null;
});
}
public static function assertObjectHydrated($object, bool $hydrateFlag = null)
{
if (!$object && !$hydrateFlag) {
throw new \Exception("Object not hydrated");
}
}
/**
* @param array|mixed $value
* @param $callback
* @return void
*/
public static function forEach($value, $callback): void
{
if (is_array($value)) {
foreach ($value as $element) {
$callback($element);
}
} else {
$callback($value);
}
}
public static function runProcess(string $name, string $args, $throwOnNonZeroExitCode = false, bool $async = false): array
{
// $command = "$name " . escapeshellarg($args);
$command = ($async ? "nohup " : "") . "$name $args" . ($async ? " > " . $_ENV['PYTHON_TELEGRAM_PATH'] . "/var/log/aaa 2>&1 & echo $!" : "");
// if (strpos($command, "python3")) {
// throw new \Exception("$command");
// }
if ($async) {
exec($command, $output);
$pid = (int)$output[0];
return [
'pid' => $pid,
];
}
// Open a process for the Python script
$descriptorspec = [
0 => ['pipe', 'r'], // stdin is a pipe that the child will read from
1 => ['pipe', 'w'], // stdout is a pipe that the child will write to
2 => ['pipe', 'w'] // stderr is a pipe that the child will write to
];
$process = proc_open($command, $descriptorspec, $pipes);
if (is_resource($process)) {
$status = proc_get_status($process);
$pid = $status['pid'] ?? null;
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$exitCode = proc_close($process);
// Output any errors
// if (!empty($stderr)) {
// throw new \Exception("Errors:\n" . $stderr) ;
// }
$result = [
'stdout' => trim($stdout),
'stderr' => $stderr,
'exitCode' => $exitCode,
"pid" => $pid,
];
if ($throwOnNonZeroExitCode && $exitCode !== 0) {
throw new \Exception("Exit code is not 0: " . $stderr);
}
return $result;
} else {
throw new \Exception("Failed to open process.") ;
}
}
}