* @copyright Copyright (c) 2022, Robert Strutts. * @license https://mit-license.org/ */ namespace main_tts; unset($_REQUEST); // Request is dangerious as order of Vars is not Known unset($_GET); // Super Globals are not Filtered, so unset them unset($_POST); $mem_baseline = memory_get_usage(); $fw_dir = __DIR__; if (basename($fw_dir) === "dist") { define('FW_DIR', dirname(__DIR__, 1) . '/'); } else { define('FW_DIR', __DIR__ . '/'); } const TTS_FRAMEWORK = FW_DIR; $up_one = dirname(TTS_FRAMEWORK, 1); $vendor = $up_one; define("TTS_VENDOR", $vendor . "/vendor/"); final class views { public static function ob_start(): void { if (extension_loaded('mbstring')) { ob_start('mb_output_handler'); } else { ob_start(); } } } if (\bs_tts\site_helper::get_testing() === false) { views::ob_start(); } final class errors { private static $handle_global_errors = true; private static $handle_shutdown_errors = true; private static $handle_exceptions = true; public static function set_handle_shutdown_errors(bool $do_handle_errors): void { self::$handle_shutdown_errors = $do_handle_errors; } public static function get_handle_shutdown_errors(): bool { return self::$handle_shutdown_errors; } public static function set_handle_exceptions(bool $do_handle_errors): void { self::$handle_exceptions = $do_handle_errors; } public static function get_handle_exceptions(): bool { return self::$handle_exceptions; } public static function set_handle_global_errors(bool $do_handle_errors): void { self::$handle_global_errors = $do_handle_errors; } public static function get_handle_global_errors(): bool { return self::$handle_global_errors; } } final class configure { private static $config = []; protected function __construct() { } public static function exists() { // an Alias to has return self::has(func_get_args()); } public static function has(string $name, $key = false): bool { if ($key === false) { return (isset(self::$config[strtolower($name)])) ? true : false; } return (isset(self::$config[strtolower($name)][strtolower($key)])) ? true : false; } public static function get(string $name, $key = false) { if (isset(self::$config[strtolower($name)])) { $a = self::$config[strtolower($name)]; if ($key === false) { return $a; } if (isset($a[$key])) { return $a[$key]; } } return null; } public static function update() { // an Alias to set return self::set(func_get_args()); } public static function set(string $name, $value): void { self::$config[strtolower($name)] = $value; } public static function set_key(string $name, string $key, $value): void { self::$config[strtolower($name)][strtolower($key)] = $value; } public static function add_to_key(string $name, string $key, $value): void { self::$config[strtolower($name)][strtolower($key)][] = $value; } public static function wipe(string $name, $key = false): void { if (! self::exists($name, $key)) { return; } if ($key === false) { \bs_tts\common::wipe(self::$config[strtolower($name)]); } \bs_tts\common::wipe(self::$config[strtolower($name)][strtolower($key)]); } public static function load_array(array $a): void { if (isset($a) && is_array($a)) { foreach ($a as $name => $value) { self::$config[$name] = $value; } } unset($a); } } final class registry { private static $registry = []; protected function __construct() { } public static function get(string $name, $key = false) { if (isset(self::$registry[strtolower($name)])) { $a = self::$registry[strtolower($name)]; if ($key === false) { return $a; } if (isset($a[$key])) { return $a[$key]; } } return null; } public static function set(string $name, $value): bool { if (array_key_exists(strtolower($name), self::$registry)) { return false; } self::$registry[strtolower($name)] = $value; return true; } } final class di { protected $services = []; public function register(string $service_name, callable $callable): void { $this->services[$service_name] = $callable; } public function has(string $service_name): bool { return (array_key_exists($service_name, $this->services)); } public function exists(string $service_name) { // an Alias to has return $this->has($service_name); } /* Note args may be an object or an array maybe more...! * This will Call/Execute the service */ public function get_service( string $service_name, $args = [], ...$more ) { if ($this->has($service_name) ) { return $this->services[$service_name]($args, $more); } return $this->resolve($service_name); // Try to Auto-Wire } public function get_auto(string $service_name) { if ($this->has($service_name) ) { return $this->services[$service_name]($this); } return $this->resolve($service_name); // Try to Auto-Wire } public function __set(string $service_name, callable $callable): void { $this->register($service_name, $callable); } public function __get(string $service_name) { return $this->get_service($service_name); } public function list_services_as_array(): array { return array_keys($this->services); } public function list_services_as_string(): string { return implode(',', array_keys($this->services)); } public function resolve(string $service_name) { try { $reflection_class = new \ReflectionClass($service_name); } catch (\ReflectionException $e) { if (! is_live()) { var_dump($e->getTrace()); echo $e->getMessage(); exit; } else { throw new \Exception("Failed to resolve resource: {$service_name}!"); } } if (! $reflection_class->isInstantiable()) { throw new \Exception("The Service class: {$service_name} is not instantiable."); } $constructor = $reflection_class->getConstructor(); if (! $constructor) { return new $service_name; } $parameters = $constructor->getParameters(); if (! $parameters) { return new $service_name; } $dependencies = array_map( function(\ReflectionParameter $param) { $name = $param->getName(); $type = $param->getType(); if (! $type) { throw new \Exception("Failed to resolve class: {$service_name} becasue param {$name} is missing a type hint."); } if ($type instanceof \ReflectionUnionType) { throw new \Exception("Failed to resolve class: {$service_name} because of union type for param {$name}."); } if ($type instanceof \ReflectionNamedType && ! $type->isBuiltin()) { return $this->get_auto($type->getName()); } throw new \Exception("Failed to resolve class {$service_name} because of invalid param {$param}."); }, $parameters ); return $reflection_class->newInstanceArgs($dependencies); } } // Initialize our Dependency Injector registry::set('di', new di()); // Setup php for working with Unicode data, if possible if (extension_loaded('mbstring')) { mb_internal_encoding('UTF-8'); mb_http_output('UTF-8'); mb_language('uni'); mb_regex_encoding('UTF-8'); setlocale(LC_ALL, "en_US.UTF-8"); } function is_live() { return (\bs_tts\common::get_bool(configure::get('tts', 'live'))); } require_once TTS_FRAMEWORK . 'bootstrap/common.php'; require_once TTS_FRAMEWORK . 'bootstrap/requires.php'; require_once TTS_FRAMEWORK . 'bootstrap/auto_loader.php'; registry::set('loader', new \bs_tts\Psr4AutoloaderClass); registry::get('loader')->register(); registry::get('loader')->add_namespace("bs_tts", TTS_FRAMEWORK . "bootstrap"); registry::get('loader')->add_namespace("tts", TTS_FRAMEWORK . "classes"); registry::get('loader')->add_namespace("tts", TTS_FRAMEWORK . "tests"); require_once TTS_FRAMEWORK . 'bootstrap/errors.php'; function set_ns() { \bs_tts\site_helper::set_project_namespace(); }