///
/// 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];
}
}