* @copyright Copyright (c) 2022, Robert Strutts. * @license https://mit-license.org/ */ namespace main_tts; unset($_REQUEST); // Request is dangerious unset($_GET); unset($_POST); $mem_baseline = memory_get_usage(); const TTS_FRAMEWORK = __DIR__ . '/'; $up_one = dirname(__DIR__, 1); define("TTS_VENDOR", $up_one . "/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 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 (! \main_tts\configure::set('tts', 'live')) { var_dump($e->getTrace()); echo $e->getMessage(); exit; } } 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"); } require_once TTS_FRAMEWORK . 'bootstrap/errors.php'; 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 \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"); \bs_tts\site_helper::set_project_namespace();