diff --git a/hanyuu.php b/hanyuu.php
index b73702c..da8ea05 100644
--- a/hanyuu.php
+++ b/hanyuu.php
@@ -14,6 +14,7 @@ define('HAU_DIR_SOURCE', HAU_ROOT . '/src');
define('HAU_DIR_LIBRARIES', HAU_ROOT . '/lib');
define('HAU_DIR_CONFIG', HAU_ROOT . '/config');
define('HAU_DIR_MIGRATIONS', HAU_ROOT . '/database');
+define('HAU_DIR_TEMPLATES', HAU_ROOT . '/templates');
define('HAU_NDX_PATH', HAU_DIR_LIBRARIES . '/index');
define('HAU_NDX_PATH_DEV', HAU_DIR_LIBRARIES . '/index-dev');
diff --git a/public/index.php b/public/index.php
index b118c11..6a3d888 100644
--- a/public/index.php
+++ b/public/index.php
@@ -3,7 +3,7 @@ namespace Hanyuu;
require_once __DIR__ . '/../hanyuu.php';
-$request = \Index\Http\HttpRequest::fromRequest();
-
$hau->setUpHttp();
-$hau->dispatchHttp($request);
+$hau->dispatchHttp(
+ \Index\Http\HttpRequest::fromRequest()
+);
diff --git a/src/HanyuuContext.php b/src/HanyuuContext.php
index 4d93afd..f64ff92 100644
--- a/src/HanyuuContext.php
+++ b/src/HanyuuContext.php
@@ -1,7 +1,6 @@
config = $config;
}
+ public function getSiteName(): string {
+ return $this->config->getValue('site:name', IConfig::T_STR, 'Hanyuu');
+ }
+
public function connectDb(?IDbConnection $dbConn = null): void {
$dbConn ??= DbTools::create($this->config->getValue('database:dsn', IConfig::T_STR, 'null'));
$dbConn->execute(self::DB_INIT);
@@ -45,6 +50,23 @@ class HanyuuContext {
return new FsDbMigrationRepo(HAU_DIR_MIGRATIONS);
}
+ public function getTemplating(): TemplateContext {
+ if($this->tpl === null) {
+ $this->tpl = new TemplateContext(HAU_DIR_TEMPLATES);
+ $this->tpl->setGlobal('hau', $this);
+ }
+
+ return $this->tpl;
+ }
+
+ public function renderTemplate(...$args): string {
+ return $this->getTemplating()->render(...$args);
+ }
+
+ public function getRouter(): IRouter {
+ return $this->router->getRouter();
+ }
+
public function setUpHttp(): void {
$this->router = new HttpFx;
$this->router->use('/', function($response) {
@@ -60,33 +82,29 @@ class HanyuuContext {
}
private function registerErrorPages(): void {
- /*$this->router->addErrorHandler(400, function($response) {
- $response->setContent(Template::renderRaw('errors.400'));
+ $this->router->addErrorHandler(400, function($response) {
+ $response->setContent($this->renderTemplate('errors/400'));
+ });
+ $this->router->addErrorHandler(401, function($response) {
+ $response->setContent($this->renderTemplate('errors/401'));
});
$this->router->addErrorHandler(403, function($response) {
- $response->setContent(Template::renderRaw('errors.403'));
+ $response->setContent($this->renderTemplate('errors/403'));
});
$this->router->addErrorHandler(404, function($response) {
- $response->setContent(Template::renderRaw('errors.404'));
+ $response->setContent($this->renderTemplate('errors/404'));
});
$this->router->addErrorHandler(500, function($response) {
- $response->setContent(file_get_contents(MSZ_TEMPLATES . '/500.html'));
+ $response->setContent(file_get_contents(HAU_DIR_TEMPLATES . '/errors/500.html'));
});
$this->router->addErrorHandler(503, function($response) {
- $response->setContent(file_get_contents(MSZ_TEMPLATES . '/503.html'));
- });*/
+ $response->setContent(file_get_contents(HAU_DIR_TEMPLATES . '/errors/503.html'));
+ });
}
private function registerHttpRoutes(): void {
$this->router->get('/', function($response, $request) {
- $siteName = $this->config->getValue('site:name', IConfig::T_STR, 'Hanyuu');
-
- return "\r\n"
- . "
{$siteName}\r\n"
- . "\r\n"
- . " Under Construction
\r\n"
- . " \r\n"
- . "\r\n";
+ return 503;
});
}
}
diff --git a/src/Templating/Template.php b/src/Templating/Template.php
new file mode 100644
index 0000000..a487c4b
--- /dev/null
+++ b/src/Templating/Template.php
@@ -0,0 +1,50 @@
+vars->setVar($name, $value);
+ }
+ public function removeVar(string $name): void {
+ $this->vars->removeVar($name);
+ }
+
+ public function render(array $vars = [], ?TemplateSelf $self = null): string {
+ if(!is_file($this->path))
+ throw new RuntimeException('Template file does not exist: ' . $this->path);
+
+ $self = new TemplateSelf($this->context->getFunctions() + $vars + $this->vars->getVars(), $self);
+ $self->tplPath = $this->path;
+
+ $self->var = fn(string $name, mixed $default = null) => $this->vars->getVar($name, $default);
+ $self->setVar = fn(string $name, mixed $value) => $this->vars->setVar($name, $value);
+ $self->remVar = fn(string $name) => $this->vars->removeVar($name);
+
+ $self->block = fn(string $name, mixed $contents) => $this->context->setBlock($name, new TemplateBlock($self, $contents));
+ $self->include = fn(string $name) => $this->context->render($name, [], $self);
+
+ $self->ctx = $this->context;
+ $self->extends = fn(string $name) => $self->extends = $name;
+
+ ob_start();
+ (static function() use ($self) { include $self->tplPath; })();
+ $buffer = ob_get_contents();
+ ob_end_clean();
+
+ if(is_string($self->extends)) {
+ if(!empty($buffer))
+ throw new RuntimeException('You cannot output from templates that extend another.');
+ $buffer = $this->context->render($self->extends, [], $self);
+ }
+
+ return $buffer;
+ }
+}
diff --git a/src/Templating/TemplateBlock.php b/src/Templating/TemplateBlock.php
new file mode 100644
index 0000000..664fc93
--- /dev/null
+++ b/src/Templating/TemplateBlock.php
@@ -0,0 +1,22 @@
+body)) {
+ ob_start();
+ ($this->body)($this->self);
+ $body = ob_get_contents();
+ ob_end_clean();
+ } else $body = strval($this->body);
+
+ return $body;
+ }
+}
diff --git a/src/Templating/TemplateContext.php b/src/Templating/TemplateContext.php
new file mode 100644
index 0000000..b25909b
--- /dev/null
+++ b/src/Templating/TemplateContext.php
@@ -0,0 +1,56 @@
+pathFormat = rtrim($path, '\\/') . DIRECTORY_SEPARATOR . '%s' . self::EXT;
+ $this->vars = new TemplateVars;
+ $this->defineFunction('global', $this->vars->getVar(...));
+ $this->defineFunction('getBlock', $this->getBlock(...));
+ $this->defineFunction('x', fn(string $string) => htmlspecialchars($string, ENT_QUOTES, 'utf-8', true));
+ }
+
+ public function setGlobal(string $name, mixed $value): void {
+ $this->vars->setVar($name, $value);
+ }
+ public function removeGlobal(string $name): void {
+ $this->vars->removeVar($name);
+ }
+
+ public function defineFunction(string $name, Closure|callable $function): void {
+ $this->functions[$name] = $function;
+ }
+ public function getFunctions(): array {
+ return $this->functions;
+ }
+
+ public function create(string $path): Template {
+ return new Template($this, new TemplateVars($this->vars), sprintf($this->pathFormat, $path));
+ }
+
+ public function exists(string $path): bool {
+ return is_file(sprintf($this->pathFormat, $path));
+ }
+
+ public function render(string $path, array $vars = [], ?TemplateSelf $self = null): string {
+ return $this->create($path)->render($vars, $self);
+ }
+
+ public function getBlock(string $name, mixed $default = ''): string {
+ return ($this->blocks[$name] ?? new TemplateBlock(new \stdClass, $default))->render();
+ }
+
+ public function setBlock(string $name, TemplateBlock $block): void {
+ $this->blocks[$name] = $block;
+ }
+}
diff --git a/src/Templating/TemplateSelf.php b/src/Templating/TemplateSelf.php
new file mode 100644
index 0000000..4ce9c31
--- /dev/null
+++ b/src/Templating/TemplateSelf.php
@@ -0,0 +1,32 @@
+members += $inherit->members;
+ }
+
+ public function __get(string $name): mixed {
+ return $this->members[$name];
+ }
+
+ public function __set(string $name, mixed $value): void {
+ $this->members[$name] = $value;
+ }
+
+ public function __isset(string $name): bool {
+ return isset($this->members[$name]);
+ }
+
+ public function __unset(string $name): void {
+ unset($this->members[$name]);
+ }
+
+ public function __call(string $name, array $args): mixed {
+ return ($this->members[$name])(...$args);
+ }
+}
diff --git a/src/Templating/TemplateVars.php b/src/Templating/TemplateVars.php
new file mode 100644
index 0000000..0b4fcf8
--- /dev/null
+++ b/src/Templating/TemplateVars.php
@@ -0,0 +1,32 @@
+vars;
+ if($this->parent !== null)
+ $vars += $this->parent->getVars();
+ return $vars;
+ }
+
+ public function getVar(string $name, mixed $default = null): mixed {
+ if(isset($this->vars[$name]))
+ return $this->vars[$name];
+ if($this->parent !== null)
+ return $this->parent->getVar($name, $default);
+ return $default;
+ }
+
+ public function setVar(string $name, mixed $value): void {
+ $this->vars[$name] = $value;
+ }
+
+ public function removeVar(string $name): void {
+ unset($this->vars[$name]);
+ }
+}
diff --git a/templates/errors/400.php b/templates/errors/400.php
new file mode 100644
index 0000000..c761851
--- /dev/null
+++ b/templates/errors/400.php
@@ -0,0 +1,5 @@
+extends('errors/master');
+
+$self->http_error_title = 'Error 400';
+$self->http_error_desc = 'Request is malformed.';
diff --git a/templates/errors/401.php b/templates/errors/401.php
new file mode 100644
index 0000000..91bfdb4
--- /dev/null
+++ b/templates/errors/401.php
@@ -0,0 +1,5 @@
+extends('errors/master');
+
+$self->http_error_title = 'Error 401';
+$self->http_error_desc = 'You must be authorised to be here.';
diff --git a/templates/errors/403.php b/templates/errors/403.php
new file mode 100644
index 0000000..f77a0a5
--- /dev/null
+++ b/templates/errors/403.php
@@ -0,0 +1,5 @@
+extends('errors/master');
+
+$self->http_error_title = 'Error 403';
+$self->http_error_desc = 'You are not authorised to be here.';
diff --git a/templates/errors/404.php b/templates/errors/404.php
new file mode 100644
index 0000000..aca80b9
--- /dev/null
+++ b/templates/errors/404.php
@@ -0,0 +1,5 @@
+extends('errors/master');
+
+$self->http_error_title = 'Error 404';
+$self->http_error_desc = 'Could not find what you were looking for.';
diff --git a/templates/errors/500.html b/templates/errors/500.html
new file mode 100644
index 0000000..3ffe87c
--- /dev/null
+++ b/templates/errors/500.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Error 500
+
+
+
+
+ Error 500
+ Something went horrendously wrong! Please report this if the error persists.
+
+
+
diff --git a/templates/errors/503.html b/templates/errors/503.html
new file mode 100644
index 0000000..7116aa9
--- /dev/null
+++ b/templates/errors/503.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Error 503
+
+
+
+
+ Under Construction
+
+
+
+
diff --git a/templates/errors/master.php b/templates/errors/master.php
new file mode 100644
index 0000000..8b0f7d5
--- /dev/null
+++ b/templates/errors/master.php
@@ -0,0 +1,9 @@
+extends('master');
+
+$self->block('body', function($self) {
+?>
+ =($self->http_error_title ?? 'Unknown Error');?>
+ =($self->http_error_desc ?? 'No additional information is available.');?>
+extends('master');
+
+$self->block('body', function($self) {
+?>
+
+ Under Construction
+
+
+
+
+
+
+
+ =$self->hau->getSiteName();?>
+
+
+ =$self->getBlock('body');?>
+
+