summaryrefslogtreecommitdiff
path: root/src/web/core/router.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/core/router.php')
-rw-r--r--src/web/core/router.php227
1 files changed, 104 insertions, 123 deletions
diff --git a/src/web/core/router.php b/src/web/core/router.php
index 1ad6cb5..2cda384 100644
--- a/src/web/core/router.php
+++ b/src/web/core/router.php
@@ -1,68 +1,91 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-class Router {
- // the loader
- private Loader $load;
-
- // the main model
- private Main_model $main;
-
- // the database
- private DatabaseHelper $db;
+class Router extends Component {
private bool $db_ready;
+ private bool $recursed;
+ private array $req;
/**
* Creates a router
* @param Loader $load - the main laoder object
*/
- function __construct($load) {
- $this->load = $load;
- $this->db = $load->db();
- $this->main = $this->load->model('main');
+ function __construct()
+ {
$this->db_ready = file_exists('/status/ready');
+ $this->recursed = FALSE;
+ $this->req = $this->get_req();
}
/**
- * @param string $path - the current request path
+ * @param string $path - the current request path
* Gets the current route
* @return array<string,mixed>
*/
- private function get_req_route($path): array {
+ private function get_req_route($path): array
+ {
// trim the path
$path = trim($path);
// remove first '/'
$path = substr($path, 1);
+
+ // get modified route
+ foreach ($GLOBALS['routes'] as $key => $value) {
+ $key = "/^{$key}$/";
+ if (!preg_match($key, $path, $matches))
+ continue;
+
+ $path = $value;
+
+ for ($i = 1; $i < count($matches); $i++) {
+ $path = str_replace(
+ "\\{$i}",
+ $matches[$i],
+ $path);
+ }
+
+ break;
+ }
+
// get path parts
$parts = explode('/', $path);
-
+ // get the length
$len = count($parts);
// get route info
$route = array();
// e.g. /
- if ($path === '') {
+ if ($path === '')
$route = array(
- 'app' => '',
+ 'app' => 'index',
'slug' => 'index',
+ 'args' => array(),
);
// e.g. /home /login
- } else if ($len === 1) {
+ else if ($len === 1)
$route = array(
'app' => $parts[0],
'slug' => 'index',
+ 'args' => array(),
);
// e.g. /home/posts
- } else {
+ else if ($len === 2)
$route = array (
- 'app' => implode('/', array_slice($parts, 0, -1)),
- 'slug' => end($parts)
+ 'app' => $parts[0],
+ 'slug' => $parts[1],
+ 'args' => array(),
+ );
+ // e.g. /home/posts/joe
+ else
+ $route = array (
+ 'app' => $parts[0],
+ 'slug' => $parts[1],
+ 'args' => array_slice($parts, 2),
);
- };
$routes = $GLOBALS['routes'];
- if (array_key_exists($route['app'], $routes)) {
- $parts = explode('/', $routes[$route['app']]);
+ if (isset($routes[$path])) {
+ $parts = explode('/', $routes[$path]);
if (count($parts) == 1) {
$route['app'] = $parts[0];
} else {
@@ -77,7 +100,8 @@ class Router {
/**
* Gets the users ip
*/
- private function get_ip(): string {
+ private function get_ip(): string
+ {
$ip = '';
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
@@ -93,13 +117,14 @@ class Router {
* Gets the curret request info
* @return array<string,mixed>
*/
- private function get_req(): array|bool {
+ private function get_req(): array
+ {
$method = $_SERVER['REQUEST_METHOD'];
-
$uri_str = $_SERVER['REQUEST_URI'];
$uri = parse_url($uri_str);
+
if (!$uri) {
- return FALSE;
+ $uri = array('path' => '/error');
}
$path = '';
@@ -121,138 +146,94 @@ class Router {
/**
* Handles a router error code
* @param int $code - the http error code
- * @param bool $recursed
*/
- private function handle_error(int $code, bool $recursed): void {
- if ($recursed) {
+ private function handle_error(int $code): void
+ {
+ if ($this->recursed)
die($code . ' (recursed)');
- }
- $uri_str = $_SERVER['REQUEST_URI'];
- $req = array();
- $req['slug'] = 'index';
- $req['app'] = 'error';
- $req['uri_str'] = $uri_str;
- $this->main->info = $req;
- $_GET['code'] = $code;
- $this->handle_req($req, TRUE);
+
+ $this->recursed = TRUE;
+ $this->req['app'] = 'error';
+ $this->req['slug'] = 'code';
+ $this->req['args'] = array($code);
+ $this->handle_req();
}
- /**
- * @param array<int,mixed> $req
- */
- private function load_htc(array $req, bool $recursed): void {
+ /**
+ * @param array<int,mixed> $req
+ */
+ private function load_htc(array $req): void
+ {
$parts = explode('/', $req['uri_str']);
$file = end($parts);
- $path = $GLOBALS['publicroot'] . '/polyfills/' . $file;
+ $path = PUBLIC_ROOT . '/polyfills/' . $file;
if (file_exists($path)) {
header('Content-type: text/x-component');
include($path);
} else {
- $this->handle_error(400, $recursed);
+ $this->handle_error(400);
}
}
/**
* @param array $req
- * @param array<int,mixed> $req
- * @param bool $recursed
+ * @param array<int,mixed> $req
*/
- private function handle_req(array $req, bool $recursed = FALSE): void {
-
- if ($recursed === false) {
- if (
- $this->db_ready === false &&
- in_array($req['app'], $GLOBALS['serviceable']) === false
- ) {
- $this->handle_error(503, $recursed);
- return;
- }
-
- if ($this->check_banned($req)) {
- $this->handle_error(401, $recursed);
+ public function handle_req(): void
+ {
+ if ($this->recursed === FALSE) {
+ // if we are in a recursing error handler
+ // we dont want to trigger a db 503 forever
+ // since its already active
+ if ($this->db_ready === FALSE) {
+ $this->handle_error(503);
return;
}
}
- if (!$req) {
- $this->handle_error(500, $recursed);
+ // server error if we cannot parse url
+ if (!$this->req) {
+ $this->handle_error(500);
return;
}
- if (str_ends_with($req['uri_str'], '.htc')) {
- $this->load_htc($req, $recursed);
+ // load htc if someone is requesting it (hi IE6 :3)
+ if (str_ends_with($this->req['uri_str'], '.htc')) {
+ $this->load_htc($this->req);
return;
}
- $controller = $this->load->controller($req['app']);
-
+ // load the controller
+ $controller = $this->load_controller($this->req['app']);
if ($controller === NULL) {
- $this->handle_error(404, $recursed);
+ $this->handle_error(404);
return;
}
$ref = NULL;
try {
- $ref = new ReflectionMethod($controller, $req['slug']);
+ $cls = new ReflectionClass($controller);
+ $mds = $cls->getMethods(ReflectionMethod::IS_PUBLIC);
+ foreach ($mds as $md) {
+ if ($md->name !== $this->req['slug'])
+ continue;
+ if (count($md->getParameters()) !=
+ count($this->req['args']))
+ continue;
+ $ref = $md;
+ break;
+ }
} catch (Exception $_e) {}
- if ($ref === NULL || !$ref->isPublic()) {
- $this->handle_error(404, $recursed);
+ if ($ref === NULL) {
+ $this->handle_error(404);
return;
-
}
- $ref->invoke($controller);
- }
-
- /**
- * @param array<int,mixed> $req
- */
- private function log_request(array $req): void {
- if (
- $req === FALSE ||
- $this->db_ready === FALSE ||
- in_array($req['app'], $GLOBALS['serviceable'])
- ) {
- return;
- }
-
- $query = $this->db
- ->insert_into('admin.request_log',
- 'ip', 'method', 'uri')
- ->values(
- $req['ip'], $req['method'], $req['uri_str']);
-
- $query->execute();
- }
-
- /**
- * @param array<int,mixed> $req
- */
- private function check_banned(array $req): bool {
- $ip = FALSE;
- if ($req) {
- $ip = $req['ip'];
- } else {
- $ip = $this->get_ip();
- }
- $query = $this->db
- ->select('TRUE')
- ->from('admin.banned')
- ->where('ip')->eq($ip);
-
- return !!($query->row());
- }
-
- /**
- * Handels the incomming reuqest
- */
- public function handle_request(): void {
- $req = $this->get_req();
- $this->log_request($req);
- $this->main->info = $req;
- $this->handle_req($req);
+ define('CONTEXT', $this->req);
+ Component::load_lang('common', $this->req['app']);
+ $ref->invokeArgs($controller, $this->req['args']);
}
}