GET /sitemap.xml
/srv/phlo/functions.php:102
Class "app" not found
phlo() phlo.php:30
phlo_app() phlo.php:8
phlo_app_jsonfile() app.php:5
- <?php
- function view(?string $body = null, ?string $title = null, array|string $css = [], array|string $js = [], array|string $defer = [], array|string $options = [], array $settings = [], ?string $ns = null, bool|string $uri = req, ...$cmds){
- !async && !is_bool($uri) && $uri !== req && location("/$uri");
- $app = phlo('app');
- $title && title($title);
- $css = array_merge((array)$css, (array)$app->css);
- $js = array_merge((array)$js, (array)$app->js);
- $defer = array_merge((array)$defer, (array)$app->defer);
- $options = implode(space, array_merge((array)$options, (array)$app->options, debug ? ['debug'] : []));
- $settings = array_merge($settings, (array)$app->settings);
- if (async){
- $uri !== false && $cmds['uri'] = $uri;
- $cmds['trans'] ??= true;
- $cmds['title'] = title();
- $css && $cmds['css'] = $css;
- $js && $cmds['js'] = $js;
- $defer && $cmds['defer'] = $defer;
- $cmds['options'] = $options;
- $cmds['settings'] = $settings;
- !is_null($body) && $cmds['inner']['body'] = $body;
- apply(...$cmds);
- }
- $body ??= $cmds['main'] ?? void;
- debug && $body .= lf.debug_render();
- $ns ??= $app->ns ?? 'app';
- $link = [];
- $head = tag('title', inner: title()).lf;
- $head .= '<meta name="viewport" content="'.($cmds['viewport'] ?? $app->viewport ?? 'width=device-width').'">'.lf;
- $app->description && $head .= "<meta name=\"description\" content=\"$app->description\">\n";
- $app->themeColor && $head .= "<meta name=\"theme-color\" content=\"$app->themeColor\">\n";
- $app->image && $head .= "<meta property=\"og:image\" content=\"$app->image\">\n";
- file_exists(www.$filename = 'favicon.ico') && $head .= "<link rel=\"favicon\" href=\"/$filename?".version."\">\n";
- file_exists(www.$filename = 'manifest.json') && $head .= "<link rel=\"manifest\" href=\"/$filename?".version."\">\n";
- file_exists(www.$filename = 'icons.png') && $link[] = "</$filename?".version.">; rel=preload; as=image";
- file_exists(www.$filename = "$ns.css") && [$link[] = "</$filename?".version.">; rel=preload; as=style", $head .= '<link rel="stylesheet" href="'.esc(slash.$filename.qm.version).'">'.lf];
- foreach ($css AS $item) $head .= '<link rel="stylesheet" href="'.esc($item).'">'.lf;
- file_exists(www.$filename = "$ns.js") && [$link[] = "</$ns.js?".version.">; rel=preload; as=script", $head .= '<script src="'.esc(slash.$filename.qm.version).'" defer></script>'.lf];
- foreach ($js AS $item) $head .= '<script src="'.esc($item).'"></script>'.lf;
- foreach ($defer AS $item) $head .= '<script src="'.esc($item).'" defer></script>'.lf;
- $app->head && $head .= $app->head;
- !build && $link && header('Link: '.implode(comma, $link), false);
- if ($lang = $cmds['lang'] ?? $app->lang ?? 'en') unset($cmds['lang']);
- $bodyAttrs = void;
- $options && $bodyAttrs .= " class=\"$options\"";
- $settings && $bodyAttrs .= loop($settings, fn($value, $key) => ' data-'.$key.'="'.esc($value).'"', void);
- die(DOM($body, $head, $lang, $bodyAttrs));
- }
- //Output instructions or start an output stream
- function apply(...$cmds){
- cli || phlo('app')->streaming || [header('Content-Type: application/json'), header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'), header('Pragma: no-cache')];
- debug && $cmds = debug_apply($cmds);
- die(json_encode($cmds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
- }
- function chunk(...$cmds){
- static $header;
- $header ??= first(true, cli || [header('Content-Type: text/event-stream'), phlo('app')->streaming = true]);
- echo json_encode($cmds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).lf;
- cli || [ob_flush(), flush()];
- }
- function output($content = null, $filename = null, $attachment = null, $file = null){
- header('Content-Type: '.mime($filename ?? basename($file ?? req)));
- header('Content-Length: '.strlen($content ??= file_get_contents($file)));
- if (is_bool($attachment) || $filename) header('Content-Disposition: '.($attachment ? 'attachment' : 'inline').';filename='.rawurlencode($filename ?? basename($file ?? req)));
- echo $content;
- exit;
- }
- //HTML tag functions
- function DOM($body = void, $head = void, $lang = 'en', $bodyAttrs = void){ return "<!DOCTYPE html>\n<html lang=\"$lang\">\n<head>\n$head</head>\n<body$bodyAttrs>\n$body\n</body>\n</html>"; }
- function tag($tagName, $inner = null, ...$args){ return "<$tagName".loop(array_filter($args, fn($value) => !is_null($value)), fn($value, $key) => space.strtr($key, [us => dash]).($value === true ? void : '="'.esc($value).'"'), void).'>'.(is_null($inner) ? void : "$inner</$tagName>"); }
- function button(...$args){ return tag('button', ...$args); }
- function input(...$args){ return tag('input', ...$args); }
- function select(...$args){ return tag('select', ...$args); }
- function textarea(...$args){ return tag('textarea', ...$args); }
- function title($title = null, $implode = ' - '){
- static $titles = [];
- if ($title) return $titles[] = $title;
- $titles[] = phlo('app')->title ?: 'Phlo '.phlo;
- return implode($implode, $titles);
- }
- function error(string $msg){
- if (cli) die("$msg\n");
- if (async) apply(error: $msg);
- print(DOM(strtr(esc($msg), [lf => br])).lf);
- exit(1);
- }
- //Handle Phlo object instances
- function phlo(?string $phloName = null, ...$args){
- static $list = [];
- if (is_null($phloName)) return array_keys($list);
- $phloName = strtr($phloName, [slash => us]);
- $handle = method_exists($phloName, '__handle') ? $phloName::__handle(...$args) : ($args ? null : $phloName);
- if ($handle === true){
- if (isset($list[$phloName])) return $list[$phloName]->objImport(...$args);
- $handle = $phloName;
- }
- elseif ($handle && isset($list[$handle])) return $list[$handle];
- $phlo = new $phloName(...$args);
- if ($handle) $list[$handle] = $phlo;
- if ($phlo->hasMethod('controller') && (!cli || $phloName !== 'app')) $phlo->controller();
- return $phlo;
- }
- //Phlo execution functions
- function phlo_exec($path, $obj, $call, $sync = true, ...$args){ return last(exec('/usr/bin/php '.rtrim($path, slash).'/app.php '.$obj.space.$call.loop($args, fn($arg) => str_contains($arg, space) || str_contains($arg, dq) || str_contains($arg, sq) || str_contains($arg, bt) || str_contains($arg, eq) || str_contains($arg, bs) || str_contains($arg, slash) ? ' "'.strtr($arg, [dq => bs.dq, '`' => '\`']).'"' : space.$arg, void).($sync ? void : ' > /dev/null 2>&1 &'), $res), $sync ? implode(lf, $res) : true); }
- function phlo_sync($obj, $call, ...$args){ return phlo_exec(www, $obj, $call, true, ...$args); }
- function phlo_async($obj, $call, ...$args){ return phlo_exec(www, $obj, $call, false, ...$args); }
- function phlo_exists($obj){ return file_exists(php.strtr($obj, [us => dot]).'.php'); }
- //Obj/array generator functions
- function arr(...$array){ return $array; }
- function obj(...$data){ return new obj(...$data); }
- function HTTP(string $url, array $headers = [], bool $JSON = false, $POST = null, $PUT = null, $PATCH = null, bool $DELETE = false, $agent = null){
- $curl = curl_init($url);
- if ($POST || $PUT || $PATCH){
- if (!is_null($POST)) [$method = 'POST', $content = $POST];
- elseif (!is_null($PUT)) [$method = 'PUT', $content = $PUT];
- elseif (!is_null($PATCH)) [$method = 'PATCH', $content = $PATCH];
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
- if ($JSON){
- !is_string($content) && $content = json_encode($content);
- array_push($headers, 'Content-Type: application/json', 'Content-Length: '.strlen($content));
- }
- curl_setopt($curl, CURLOPT_POSTFIELDS, $content);
- }
- elseif ($DELETE) curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
- $agent && curl_setopt($curl, CURLOPT_USERAGENT, $agent === true ? $_SERVER['HTTP_USER_AGENT'] : $agent);
- curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- return curl_exec($curl);
- }
- //Auth functions on IP or landing URL
- function auth_IP(...$list){
- if (($return = cli || phlo('session')->auth) || !$return = ($index = array_search($_SERVER['REMOTE_ADDR'], $list)) !== false) return $return;
- phlo('session')->auth = true;
- return is_int($index) ?: $index;
- }
- function auth_uri(...$list){
- if (($return = cli || phlo('session')->auth) || !$return = ($index = array_search(req, $list)) !== false) return $return;
- phlo('session')->auth = true;
- return is_int($index) ?: $index;
- }
- function auth_log($user){ file_put_contents(data.'access.log', date('j-n-Y H:i:s')." - $user - $_SERVER[REMOTE_ADDR]\n", FILE_APPEND); }
- //APCu cache function
- function apcu($key, $cb, $duration = 3600, bool $log = true){ return first($value = apcu_entry($key, $cb, $duration), $log && debug('C: '.(strlen($key) > 58 ? substr($key, 0, 55).'...' : $key).(is_array($value) ? ' ('.count($value).')' : (is_numeric($value) ? ":$value" : (is_string($value) ? ':string:'.strlen($value) : colon.gettype($value)))))); }
- //JSON functions
- function json_read($file, $assoc = null){ return json_decode(file_get_contents($file), $assoc) ?? error('Error reading '.esc($file)); }
- function json_write($file, $data, $flags = null){ return file_put_contents($file, json_encode($data, $flags ?? jsonFlags)); }
- //Argument handling functions
- function first(...$args){ return current($args); }
- function last(...$args){ return end($args); }
- //Encryption functions
- function encrypt($data, $key){ return base64_encode(($nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)).sodium_crypto_secretbox($data, $nonce, hash('sha256', $key, true))); }
- function decrypt($encrypted, $key){ return sodium_crypto_secretbox_open($ciphertext = substr($decoded = base64_decode($encrypted), SODIUM_CRYPTO_SECRETBOX_NONCEBYTES), substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES), hash('sha256', $key, true)); }
- // Time functions
- function age(int $time){ return time() - $time; }
- function age_human(int $age){ time_human(time() - $age); }
- function duration(int $decimals = 4, bool $float = false){ return ltrim(round($duration = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], $decimals), 0).($float ? void : 's'.($duration < .5 ? ' ('.round(1 / $duration).'/s)' : void)); }
- function time_human(?int $time = null){
- static $labels;
- $labels ??= last($labels = arr(seconds: 60, minutes: 60, hours: 24, days: 7, weeks: 4, months: 13, years: 1), defined('tsLabels') && $labels = array_combine(tsLabels, $labels), $labels);
- $age = time() - $time;
- foreach ($labels AS $range => $multiplier){
- if ($age / $multiplier < 1.66) break;
- $age /= $multiplier;
- }
- return round($age)." $range";
- }
- //Generic functions
- function active(bool $cond, string $classList = void){ return $cond || $classList ? ' class="'.$classList.($cond ? ($classList ? space : void).'active' : void).'"' : void; }
- function camel($text){ return lcfirst(str_replace(space, void, ucwords(lcfirst($text)))); }
- function create($items, Closure $keyCb, ?Closure $valueCb = null){ return array_combine(loop($items, $keyCb), $valueCb ? loop($items, $valueCb) : $items); }
- function debug(?string $msg = null){
- if (!debug) return;
- static $debug = [];
- if (!$msg) return debug ? $debug : null;
- $debug[] = substr($msg, 0, 160);
- }
- function esc($string){ return htmlspecialchars((string)$string); }
- function files(string|array $paths, string $ext = '*.*'){ return array_merge(...loop((array)$paths, fn($path) => glob("$path$ext"))); }
- function indent(string $string, int $depth = 1){ return ($tab = str_repeat(tab, $depth)).rtrim(strtr($string, [lf => lf.$tab]), tab); }
- function indentView(string $string, int $depth = 1){ return last($tab = str_repeat(tab, $depth), rtrim(preg_replace('/\n(\t*)</', "\n$1$tab<", $string), tab)); }
- function location(?string $location = null){ async ? apply(location: $location ?? true) : [header('Location: '.($location ?? ($_SERVER['HTTP_REFERER'] ?? slash))), exit]; }
- function loop(iterable $data, closure|array $cb, ?string $implode = null){
- $return = [];
- $isArray = is_array($cb);
- foreach ($data AS $key => $value) $return[$key] = $isArray ? $cb[0]->{$cb[1]}($value, $key) : $cb($value, $key);
- return is_null($implode) ? $return : implode($implode, $return);
- }
- function mime($filename){ return ['html' => 'text/html', 'css' => 'text/css', 'gif' => 'image/gif', 'ico' => 'image/x-icon', 'ini' => 'text/plain', 'js' => 'application/javascript', 'json' => 'application/json', 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'ogg' => 'audio/ogg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'pdf' => 'application/pdf', 'phlo' => 'application/phlo', 'php' => 'application/x-httpd-php', 'png' => 'image/png', 'svg' => 'image/svg+xml', 'txt' => 'text/plain', 'webp' => 'image/webp'][pathinfo($filename, PATHINFO_EXTENSION)] ?? 'application/octet-stream'; }
- function regex(string $pattern, string $subject, int $flags = 0, int $offset = 0):array { return last(str_starts_with($pattern, slash) || $pattern = "/$pattern/", preg_match($pattern, $subject, $match, $flags, $offset) ? $match : []); }
- function regex_all(string $pattern, string $subject, int $flags = 0, int $offset = 0):array { return last(str_starts_with($pattern, slash) || $pattern = "/$pattern/", preg_match_all($pattern, $subject, $matches, $flags, $offset) ? $matches : []); }
- function req(int $index, $length = null){
- static $parts;
- $parts ??= explode(slash, req);
- return is_null($length) ? ($parts[$index] ?? null) : (implode(slash, array_slice($parts, $index, $length < 0 ? null : $length)) ?: null);
- }
- function route(?string $method = null, string $path = void, ?bool $async = null, ?string $data = null, ?string $cb = null){
- if ($method && $method !== method) return;
- if (!is_null($async) && $async !== async) return;
- if ($data && phlo('payload')->objKeys !== explode(comma, $data)) return;
- $req = array_filter(explode(slash, req));
- $cbArgs = [];
- $index = -1;
- foreach (array_filter(explode(space, $path)) AS $index => $item){
- $reqItem = req($index);
- if (strpos($item, '$') === 0){
- $item = substr($item, 1);
- if (str_ends_with($item, '=*')){
- $cbArgs[substr($item, 0, -2)] = implode(slash, array_slice($req, $index));
- $index = count($req) - 1;
- break;
- }
- elseif (str_ends_with($item, '?')){
- $item = substr($item, 0, -1);
- if ($reqItem && $item !== $reqItem) return;
- $reqItem = $item === $reqItem;
- }
- elseif (strpos($item, '=')){
- list ($item, $default) = explode('=', $item, 2);
- $default = $default ?: null;
- }
- elseif (is_null($reqItem)) return;
- if (strpos($item, '.') && (list($item, $length) = explode(dot, $item, 2)) && strlen($reqItem) != $length) return false;
- if (strpos($item, ':')){
- (list ($item, $list) = explode(':', $item, 2)) && $list = explode(comma, $list);
- if (!$reqItem || in_array($reqItem, $list)) $cbArgs[$item] = $reqItem ?: $default ?? null;
- else return;
- }
- else $cbArgs[$item] = $reqItem ?? $default;
- }
- elseif ($item !== $reqItem) return;
- }
- if (isset($req[$index + 1])) return;
- if (!$cb) return obj(...$cbArgs);
- if ($cb(...$cbArgs) === false) return;
- exit;
- }
- function size_human(int $size, int $precision = 0){
- foreach (['b', 'Kb', 'Mb', 'Gb', 'Tb'] AS $range){
- if ($size / 1024 < 1) break;
- $size /= 1024;
- }
- return round($size, $precision).$range;
- }
- function slug(string $text):string { return trim(preg_replace('/[^a-z0-9]+/', dash, strtolower(iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text))), dash); }
- function token(int $length = 8, ?string $input = null, $sha1 = null){
- $sha1 ??= sha1($input ?? random_int(date('Y'), PHP_INT_MAX), true);
- $token = void;
- for ($i = 0; strlen($token) < $length; $i++) $token .= chr(ord('a') + (ord($sha1[$i % 20]) % 26));
- return $token;
- }