Add a basic router system

This commit is contained in:
Kazhnuz 2025-03-28 21:13:44 +01:00
parent 4f88b8f6c2
commit 5c9d1e4d58
10 changed files with 251 additions and 3 deletions

View file

@ -0,0 +1,21 @@
<?php
function index() {
global $renderer;
// Prepare data for the view
$renderer->prepare('title', 'Home Page');
$renderer->prepare('content', 'Welcome to the home page!');
// Display the view using the namespace
$renderer->display('home');
}
function closed() {
global $renderer;
// Prepare data for the view
$renderer->prepare('title', 'Game closed');
$renderer->prepare('content', 'The game is currently closed for maintanence. Please check back later.');
// Display the view using the namespace
$renderer->display('home');
}

View file

@ -24,10 +24,10 @@ define('DS', DIRECTORY_SEPARATOR);
// PHP paths for init
define('PATH_ROOT', __DIR__.DS);
define('PATH_BOOT', PATH_ROOT.'kernel'.DS.'boot'.DS);
define('PATH_KERNEL', PATH_ROOT.'kernel'.DS);
// Init
require(PATH_BOOT.'init.php');
require(PATH_BOOT.'site.php');
require(PATH_KERNEL.'init.php');
require(PATH_KERNEL.'core.php');
?>

11
kernel/core.php Normal file
View file

@ -0,0 +1,11 @@
<?php
$router = new Router();
$renderer = new Renderer();
// Register namespaces with their required authorization levels
$router->registerNamespace('admin', 2, false); // Admin namespace requires level 2
$router->registerNamespace('user', 1, false); // User namespace requires level 1
$router->registerNamespace('site', 0, false); // Site namespace requires level 0
$router->loadController();

38
kernel/init.php Normal file
View file

@ -0,0 +1,38 @@
<?php // The initialisation of the kernel of dragon-fork
// Dragon Fork version
define('DRAGONFORK_VERSION', '0.0.1');
define('DRAGONFORK_CODENAME', '');
define('DRAGONFORK_RELEASE_DATE', '2024-08-23');
define('DRAGONFORK_BUILD', '20240806');
// Change to TRUE for debugging
define('DEBUG_MODE', TRUE);
define('DEBUG_TYPE', 'INFO'); // INFO, TRACE
// This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user.
ini_set("display_errors", 0);
// Even when display_errors is on, errors that occur during PHP's startup sequence are not displayed.
// It's strongly recommended to keep display_startup_errors off, except for debugging.
ini_set('display_startup_errors', 0);
// If disabled, error message will be solely plain text instead HTML code.
ini_set("html_errors", 0);
// Tells whether script error messages should be logged to the server's error log or error_log.
ini_set('log_errors', 1);
if (DEBUG_MODE) {
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
} else {
error_reporting(E_ERROR);
}
include(PATH_KERNEL . 'lib.php');
include(PATH_KERNEL . 'cookies.php');
include(PATH_KERNEL . 'renderer.php');
include(PATH_KERNEL . 'namespace.php');
include(PATH_KERNEL . 'router.php');
$link = opendb();

30
kernel/namespace.php Normal file
View file

@ -0,0 +1,30 @@
<?php
/**
* Handle one of the game namespace
*
* The game namespace allow us to compartimentate the game
* into several domain, each with their own level of authentification
* - The "site" domain will be available to non-authentified users
* - The "game" domain will be available to authentified, non-banned users
* - The "user" domain will be available to authentified, non-banned users
* - The "admin" domain will be available to admins
*
* This allow to more simply handle authorisation
*/
class NamespaceHandler {
private $name;
private $authLevel;
public $haveCharacterId;
public function __construct($name, $authLevel, $haveCharacterId) {
$this->name = $name;
$this->authLevel = $authLevel;
$this->haveCharacterId = $haveCharacterId;
}
public function canShow() {
// FIXME: handle auth level correctly
return $this->authLevel < 1000;
}
}

38
kernel/renderer.php Normal file
View file

@ -0,0 +1,38 @@
<?php
/**
* Basic wrapper around twig
*/
class Renderer {
private $twig;
private $data = [];
public function __construct() {
$loader = new \Twig\Loader\FilesystemLoader(PATH_ROOT . '/theme/default/');
$this->twig = new \Twig\Environment($loader);
}
public function prepare($key, $value) {
$this->data[$key] = $value;
}
public function display($template) {
global $router;
try {
echo $this->twig->render("{$router->namespace}/{$template}.twig", $this->data);
die();
} catch (\Twig\Error\LoaderError $e) {
$this->error(500);
}
}
public function error($errorCode) {
$errorTemplate = PATH_ROOT . "/theme/default/error/{$errorCode}.twig";
if (file_exists($errorTemplate)) {
echo $this->twig->render("error/{$errorCode}.twig");
} else {
echo $this->twig->render("error/generic.twig");
}
die();
}
}

74
kernel/router.php Normal file
View file

@ -0,0 +1,74 @@
<?php
/**
* Route the page to a controller.
* Use the following syntax /{{namespace}}/{{controller}}/{{function}}
*
* TODO: handle non-get request
*/
class Router {
public $namespace;
public $controller;
public $func;
public $characterId = -1;
private $namespaces = [];
private $currentNamespaceHandler;
public function registerNamespace($name, $authLevel, $haveCharacterId) {
$this->namespaces[$name] = new NamespaceHandler($name, $authLevel, $haveCharacterId);
}
public function loadController() {
global $renderer;
$this->parseUrl();
if (!$this->currentNamespaceHandler->canShow()) {
$renderer->error(403);
}
$controllerFile = $this->getControllerPath();
require_once $controllerFile;
if (is_callable($this->func)) {
call_user_func($this->func);
} else {
$renderer->error(404);
}
}
private function getFromUrl($requestParts, $index, $default) {
return (isset($requestParts[$index]) && $requestParts[$index] != null) ? $requestParts[$index] : $default;
}
private function parseUrl() {
global $renderer;
$requestUri = trim($_SERVER['REQUEST_URI'], '/');
$requestParts = explode('/', $requestUri);
$this->namespace = $this->getFromUrl($requestParts, 0, 'site');
if (!isset($this->namespaces[$this->namespace])) {
$renderer->error(404);
}
$this->currentNamespaceHandler = $this->namespaces[$this->namespace];
if ($this->currentNamespaceHandler->haveCharacterId) {
$this->characterId = $this->getFromUrl($requestParts, 1, -1);
$this->controller = $this->getFromUrl($requestParts, 2, "pages");
$this->func = $this->getFromUrl($requestParts, 3, "index");
} else {
$this->controller = $this->getFromUrl($requestParts, 1, "pages");
$this->func = $this->getFromUrl($requestParts, 2, "index");
}
}
private function getControllerPath() {
global $renderer;
$controllerPath = PATH_ROOT . "controllers/{$this->namespace}/{$this->controller}.php";
if (!file_exists($controllerPath)) {
$renderer->error(404);
}
return $controllerPath;
}
}

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 Not Found</title>
</head>
<body>
<h1>404 Not Found</h1>
<p>The page you are looking for does not exist.</p>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error</title>
</head>
<body>
<h1>Error</h1>
<p>I am error.</p>
</body>
</html>

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
<p>{{ content }}</p>
</body>
</html>