PHP 8.4+ 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.
 
 

297 lines
8.9 KiB

<?php
declare(strict_types=1);
/**
* @author Robert Strutts
* @copyright Copyright (c) 2022, Robert Strutts.
* @license MIT
*/
namespace CodeHydrater\bootstrap;
// Polyfill for PHP 4 to 7
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
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();
require_once CodeHydrater_FRAMEWORK . 'bootstrap/errors.php';
final class views {
public static function ob_start(): void {
if (extension_loaded('mbstring')) {
ob_start('mb_output_handler');
} else {
ob_start();
}
}
}
if (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) {
common::wipe(self::$config[strtolower($name)]);
}
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 (common::get_bool(configure::get('CodeHydrater', 'live')));
}
require_once CodeHydrater_FRAMEWORK . 'bootstrap/common.php';
require_once CodeHydrater_FRAMEWORK . 'bootstrap/requires.php';
require_once CodeHydrater_FRAMEWORK . 'bootstrap/auto_loader.php';
registry::set('loader', new Psr4AutoloaderClass);
registry::get('loader')->register();
registry::get('loader')->add_namespace("CodeHydrater\bootstrap", CodeHydrater_FRAMEWORK . "bootstrap");
registry::get('loader')->add_namespace("CodeHydrater", CodeHydrater_FRAMEWORK . "classes");
registry::get('loader')->add_namespace("Project", CodeHydrater_PROJECT);
load_all::init(CodeHydrater_PROJECT);
$returned_route = \CodeHydrater\router::execute();
if ($returned_route["found"] === false) {
$app = new \CodeHydrater\app();
$app->load_controller();
}