true, 'false', '(false)' => false, 'empty', '(empty)' => '', 'null', '(null)' => null, default => $value, }; } } if (!function_exists('getValue')) { function getValue(mixed $var): mixed { return ($var instanceof Closure) ? $var() : $var; } } if (!function_exists('makeDate')) { /** * Make Date Time Object. * * @param string|int $date Defaults to now * @param string|DateTimeZone|null $tz For given $date, not for display. * * @return Date */ function makeDate(string|int $date = 'now', DateTimeZone|string|null $tz = null): Date { if (ctype_digit((string)$date)) { $date = '@' . $date; } if (null === $tz) { $tz = date_default_timezone_get(); } if (!($tz instanceof DateTimeZone)) { $tz = new DateTimeZone($tz); } return (new Date($date))->setTimezone($tz); } } if (!function_exists('ag')) { function ag(array $array, string|null $path, mixed $default = null, string $separator = '.'): mixed { if (null === $path) { return $array; } if (array_key_exists($path, $array)) { return $array[$path]; } if (!str_contains($path, $separator)) { return $array[$path] ?? getValue($default); } foreach (explode($separator, $path) as $segment) { if (is_array($array) && array_key_exists($segment, $array)) { $array = $array[$segment]; } else { return getValue($default); } } return $array; } } if (!function_exists('ag_set')) { /** * Set an array item to a given value using "dot" notation. * * If no key is given to the method, the entire array will be replaced. * * @param array $array * @param string $path * @param mixed $value * @param string $separator * * @return array return modified array. */ function ag_set(array $array, string $path, mixed $value, string $separator = '.'): array { $keys = explode($separator, $path); $at = &$array; while (count($keys) > 0) { if (1 === count($keys)) { if (is_array($at)) { $at[array_shift($keys)] = $value; } else { throw new RuntimeException("Can not set value at this path ($path) because its not array."); } } else { $path = array_shift($keys); if (!isset($at[$path])) { $at[$path] = []; } $at = &$at[$path]; } } return $array; } } if (!function_exists('ag_exists')) { /** * Determine if the given key exists in the provided array. * * @param array $array * @param string|int $path * @param string $separator * * @return bool */ function ag_exists(array $array, string|int $path, string $separator = '.'): bool { if (is_int($path)) { return isset($array[$path]); } foreach (explode($separator, $path) as $lookup) { if (isset($array[$lookup])) { $array = $array[$lookup]; } else { return false; } } return true; } } if (!function_exists('ag_delete')) { /** * Delete given key path. * * @param array $array * @param int|string $path * @param string $separator * @return array */ function ag_delete(array $array, string|int $path, string $separator = '.'): array { if (array_key_exists($path, $array)) { unset($array[$path]); return $array; } if (is_int($path)) { if (isset($array[$path])) { unset($array[$path]); } return $array; } $items = &$array; $segments = explode($separator, $path); $lastSegment = array_pop($segments); foreach ($segments as $segment) { if (!isset($items[$segment]) || !is_array($items[$segment])) { continue; } $items = &$items[$segment]; } if (null !== $lastSegment && array_key_exists($lastSegment, $items)) { unset($items[$lastSegment]); } return $array; } } if (!function_exists('fixPath')) { function fixPath(string $path): string { return rtrim(implode(DIRECTORY_SEPARATOR, explode(DIRECTORY_SEPARATOR, $path)), DIRECTORY_SEPARATOR); } } if (!function_exists('fsize')) { function fsize(string|int $bytes = 0, bool $showUnit = true, int $decimals = 2, int $mod = 1000): string { $sz = 'BKMGTP'; $factor = floor((strlen((string)$bytes) - 1) / 3); return sprintf("%.{$decimals}f", (int)($bytes) / ($mod ** $factor)) . ($showUnit ? $sz[(int)$factor] : ''); } } if (!function_exists('saveWebhookPayload')) { function saveWebhookPayload(ServerRequestInterface $request, string $name, array $parsed = []): void { $content = [ 'query' => $request->getQueryParams(), 'parsed' => $request->getParsedBody(), 'server' => $request->getServerParams(), 'body' => (string)$request->getBody(), 'attributes' => $request->getAttributes(), 'cParsed' => $parsed, ]; @file_put_contents( Config::get('tmpDir') . '/webhooks/' . sprintf( 'webhook.%s.%d.json', $name, (string)ag($request->getServerParams(), 'X_REQUEST_ID', time()) ), json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ); } } if (!function_exists('saveRequestPayload')) { function saveRequestPayload(ServerRequestInterface $request): void { $content = [ 'query' => $request->getQueryParams(), 'parsed' => $request->getParsedBody(), 'server' => $request->getServerParams(), 'body' => (string)$request->getBody(), 'attributes' => $request->getAttributes(), ]; @file_put_contents( Config::get('tmpDir') . '/webhooks/' . sprintf( 'request.%s.json', (string)ag($request->getServerParams(), 'X_REQUEST_ID', time()) ), json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ); } } if (!function_exists('jsonResponse')) { function jsonResponse(int $status, array $body, $headers = []): ResponseInterface { $headers['Content-Type'] = 'application/json'; return new Response( status: $status, headers: $headers, body: json_encode( $body, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_SLASHES ) ); } } if (!function_exists('httpClientChunks')) { /** * Handle Response Stream as Chunks * * @param ResponseStreamInterface $responseStream * @return Generator * * @throws TransportExceptionInterface */ function httpClientChunks(ResponseStreamInterface $responseStream): Generator { foreach ($responseStream as $chunk) { yield $chunk->getContent(); } } } if (!function_exists('preServeHttpRequest')) { function preServeHttpRequest(ServerRequestInterface $request): ServerRequestInterface { foreach (Config::get('supported', []) as $server) { assert($server instanceof ServerInterface); $request = $server::processRequest($request); } return $request; } } if (!function_exists('queuePush')) { function queuePush(StateInterface $entity): void { if (!$entity->hasGuids()) { return; } try { $cache = Container::get(CacheInterface::class); $list = $cache->get('queue', []); $list[$entity->id] = $entity->getAll(); $cache->set('queue', $list); } catch (\Psr\SimpleCache\InvalidArgumentException $e) { Container::get(LoggerInterface::class)->error($e->getMessage(), $e->getTrace()); } } } if (!function_exists('afterLast')) { function afterLast(string $subject, string $search): string { if (empty($search)) { return $subject; } $position = mb_strrpos($subject, $search, 0); if (false === $position) { return $subject; } return mb_substr($subject, $position + mb_strlen($search)); } } if (!function_exists('makeServer')) { /** * @param array{name:string|null, type:string, url:string, token:string|int|null, user:string|int|null, persist:array, options:array} $server * @param string|null $name server name. * @return ServerInterface * * @throws RuntimeException if configuration is wrong. */ function makeServer(array $server, string|null $name = null): ServerInterface { if (null === ($serverType = ag($server, 'type'))) { throw new RuntimeException('No server type was selected.'); } if (null === ag($server, 'url')) { throw new RuntimeException('No url was set for server.'); } if (null === ($class = Config::get("supported.{$serverType}", null))) { throw new RuntimeException( sprintf( 'Unexpected server type was given. Was expecting [%s] but got \'%s\' instead.', $serverType, implode('|', Config::get("supported", [])) ) ); } return Container::getNew($class)->setUp( name: $name ?? ag($server, 'name', fn() => md5(ag($server, 'url'))), url: new Uri(ag($server, 'url')), token: ag($server, 'token', null), userId: ag($server, 'user', null), uuid: ag($server, 'uuid', null), persist: ag($server, 'persist', []), options: ag($server, 'options', []), ); } } if (!function_exists('arrayToString')) { function arrayToString(array $arr, string $separator = ', '): string { $list = []; foreach ($arr as $key => $val) { if (is_object($val)) { if (($val instanceof JsonSerializable)) { $val = json_encode($val, flags: JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } elseif (($val instanceof Stringable) || method_exists($val, '__toString')) { $val = (string)$val; } else { $val = [ spl_object_hash($val) => get_class($val), ...(array)$val ]; } } if (is_array($val)) { $val = json_encode($val, flags: JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } else { $val = $val ?? 'None'; } $list[] = sprintf("(%s: %s)", $key, $val); } return implode($separator, $list); } } if (!function_exists('commandContext')) { function commandContext(): string { if (env('IN_DOCKER')) { return sprintf('docker exec -ti %s console ', env('CONTAINER_NAME', 'watchstate')); } return ($_SERVER['argv'][0] ?? 'php console') . ' '; } }