/// /// This file is part of CRIMSON. /// /// CRIMSON is free software; you can redistribute it and/or modify it /// under the terms of the GNU General Public License as published by /// the Free Software Foundation; either version 3 of the License, or (at /// your option) any later version. /// /// CRIMSON is distributed in the hope that it will be useful, but /// WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with CRIMSON. If not, see . /** * Gives access to imporant * needed utility functions for * accessing everything else! */ abstract class Base { // ======================================================== LOADABLE OBJECTS == // keep track of what has been loaded private static array $loaded = array(); /** * Loads a $type of object from a $dir with a given $name * @param string $name - the name of the object to load * @param string $dir - the directory theese objects are stored in * @param string $type - the type of the object */ private function load_type($name, $dir, $type): object|NULL { $path = $dir . '/' . $name . '.php'; // dont reload an ohject if (array_key_exists($path, self::$loaded)) return self::$loaded[$path]; // only load a object if it exists if (!file_exists($path)) return NULL; $parts = explode('/', $name); $part = end($parts); $class = ucfirst($part) . '_' . $type; require($path); $ref = NULL; try { $ref = new ReflectionClass($class); } catch (Exception $_e) {} if ($ref === NULL) return NULL; $obj = $ref->newInstance(); self::$loaded[$path] = $obj; return $obj; } /** * Loads a model * @param string $name - the name of the model to load */ public function load_model($name): Model|NULL { $dir = WEB_ROOT . '/_model'; return $this->load_type($name, $dir, 'model'); } /** * Loads a controller * @param string $name - the name of the controller to load */ public function load_controller($name): Controller|NULL { $dir = WEB_ROOT . '/_controller'; return $this->load_type($name, $dir, 'controller'); } // ==================================================================== LANG == // current loaded language strings private static array $loaded_lang = array(); private static array $loaded_files = array(); /** * Loads a php lang file into the lang array */ private function load_lang_file(string $file): void { if (isset(self::$loaded[$file])) return; self::$loaded[$file] = TRUE; $lang = self::$loaded_lang; require($file); self::$loaded_lang = $lang; } /** * Loads each php file lang strings in a directory */ private function load_lang_dir(string $dir): void { if ($handle = opendir($dir)) { while (false !== ($entry = readdir($handle))) { if ($entry === '.' || $entry === '..') continue; $this->load_lang_file($entry); } } } /** * Loads the given common lang */ public function load_lang(string ...$langs): array { $root = WEB_ROOT . '/lang'; foreach ($langs as $lang) { $file = "{$root}/{$lang}.php"; $dir = "{$root}/{$lang}"; if (file_exists($file)) $this->load_lang_file($file); else if (is_dir($dir)) $this->load_lang_dir($dir); } return self::$loaded_lang; } /** * Returns the currently loaded lang */ public function get_lang(): array { return self::$loaded_lang; } // ================================================================ DATABASE == // current database connection private static ?DatabaseHelper $db = NULL; /** * Loads the database */ public function db(): DatabaseHelper { if (!self::$db) self::$db = new DatabaseHelper(); return self::$db; } // ================================================================ METADATA == /** * Gets the stamp for a asset path * @param string $path */ public function asset_stamp(string $path): int { if (ENVIRONMENT == 'devlopment') return time(); if (isset(FILE_TIMES[$path])) return FILE_TIMES[$path]; return 0; } /** * Gets a full path url from a relative path * @param string $path * @param bool $timestamp */ public function get_url(string $path, bool $timestamp = FALSE): string { $scheme = 'http'; if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO']; $host = $_SERVER['HTTP_HOST']; if (ENVIRONMENT == 'production') { $default = CONFIG['domain']; $allowed = CONFIG['allowed_hosts']; if (!is_array($allowed)) $allowed = [$allowed]; if (!in_array($host, $allowed)) $host = $default; } $base = CONFIG['base_path']; $url = "{$scheme}://{$host}{$base}{$path}"; if ($timestamp) { $time = $this->asset_stamp($path); $url .= "?timestamp={$time}"; } return $url; } /** * Loads a js html link * @param string $path - the path to the js file */ public function link_js(string $path): string { $stamp = $this->asset_stamp("public/$path"); $href = $this->get_url("public/{$path}?timestamp={$stamp}"); return ''; } /** * Loads a css html link * @param string $path - the path to the css file */ public function link_css(string $path): string { $stamp = $this->asset_stamp("public/$path"); $href = $this->get_url("public/{$path}?timestamp={$stamp}"); return ''; } /** * Loads a css html link * @param string $path - the path to the css file */ public function embed_css(string $path): string { $file = PUBLIC_ROOT . '/' . $path; if (file_exists($file)) { $text = file_get_contents($file); return ""; } else { return ""; } } // =============================================================== HTTP POST == /** * Gets http POST data from $_POST if x-url-encoded, or parsed from * php://input if AJAX. Returns FALSE if input is not a post request, * or NULL if unable to parse request body. */ private function get_post_data() { static $data = NULL; if (isset($data)) return $data; // not a POST request if ($_SERVER['REQUEST_METHOD'] != 'POST') return NULL; // ajax if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { $data = json_decode(file_get_contents("php://input"), true); // on failure, make sure $data is FALSE and not NULL if (!$data) $data = FALSE; return $data; } // x-url-encoded or form-data $data = $_POST; return $data; } /** * Returns HTTP POST information if POST request. * @returns $_POST if $key is not set and request is POST. * @returns value at $key if $key is set and request is POST. * @returns FALSE if value at $key is not set and request is POST. * @returns FALSE if request is POST but has invalid body. * @returns NULL if request is not POST. */ public function post_data(?string $key = NULL) { $data = $this->get_post_data(); if (!$data) return $data; if (!$key) return $data; if (!isset($data[$key])) return FALSE; return $data[$key]; } }