The TryingToScale PHP framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
tts_framework/src/main.inc.php

256 lines
7.5 KiB

<?php
declare(strict_types=1);
/**
* @author Robert Strutts <Robert@TryingToScale.com>
* @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();