Initial commit
Couldnt keep the history unfortunately.
This commit is contained in:
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes;
|
||||
|
||||
use Klein\Klein;
|
||||
|
||||
use App\Classes\Db;
|
||||
|
||||
use App\Model\SectionModel;
|
||||
use App\Model\PageModel;
|
||||
|
||||
class Router {
|
||||
|
||||
protected static $router;
|
||||
protected static $routes = [];
|
||||
|
||||
public static function _init(): void {
|
||||
self::$router = new Klein();
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
/**
|
||||
* Load all routes into the Klein object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function fire(): void
|
||||
{
|
||||
$path = parse_url($_SERVER['REQUEST_URI'])['path'];
|
||||
$check = str_replace('.', '', $path);
|
||||
|
||||
// If it's a dynamic file or the file doesn't exist, go through the router.
|
||||
if ($path == $check || !file_exists(getcwd() . $path)) {
|
||||
|
||||
Db::load();
|
||||
self::setDefaultLayout();
|
||||
self::loadConfigRoutes();
|
||||
self::loadDbRoutes();
|
||||
|
||||
// Process basic routes
|
||||
foreach (self::$routes as $route) {
|
||||
// If route does not match the base url
|
||||
if ($route[0] != $path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ["/example/my-page", "ExampleController", "action", "" : ["view", "title", "description"]],
|
||||
self::addBasicRoute(['GET', 'POST'], $route);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
self::createNavigation();
|
||||
self::setHttpError();
|
||||
|
||||
self::$router->dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CRUD routes
|
||||
* Example usage: Router::resource('/example', 'CrudController');
|
||||
*
|
||||
* @param string $route The URL location
|
||||
* @param string $controller Controller to handle this route
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resource(string $route, string $controller): void
|
||||
{
|
||||
/*
|
||||
* HTTP Verb Part (URL) Action (Method)
|
||||
*
|
||||
* GET /route indexAction
|
||||
* GET /route/create createAction
|
||||
* POST /route storeAction
|
||||
* GET /route/{id} showAction
|
||||
* GET /route/{id}/edit editAction
|
||||
* PUT/PATCH /route/{id} updateAction
|
||||
* DELETE /route/{id} destroyAction
|
||||
*/
|
||||
|
||||
self::addRoute(['GET'], [$route, $controller, 'indexAction']);
|
||||
self::addRoute(['GET'], [$route . '/create', $controller, 'createAction']);
|
||||
self::addRoute(['POST'], [$route, $controller, 'storeAction']);
|
||||
self::addRoute(['GET'], [$route . '/[i:id]', $controller, 'showAction', ['id']]);
|
||||
self::addRoute(['GET'], [$route . '/[i:id]/edit', $controller, 'editAction', ['id']]);
|
||||
self::addRoute(['PUT', 'PATCH'], [$route . '/[i:id]', $controller, 'updateAction', ['id']]);
|
||||
self::addRoute(['DELETE'], [$route . '/[i:id]', $controller, 'destroyAction', ['id']]);
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
protected static function setDefaultLayout(): void
|
||||
{
|
||||
self::$router->respond(function ($request, $response, $service) {
|
||||
$service->layout('../app/views/layouts/default.php');
|
||||
});
|
||||
}
|
||||
|
||||
protected static function loadConfigRoutes(): void
|
||||
{
|
||||
if (file_exists('../route.php')) {
|
||||
self::$routes = require_once '../route.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all pages in the Db to self::$routes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function loadDbRoutes(): void
|
||||
{
|
||||
// Load all sections from Db
|
||||
$sections = SectionModel::selectAll('*', 'WHERE `active` = 1 ORDER BY `order` ASC');
|
||||
|
||||
// Return if no sections
|
||||
if (!_exists($sections)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load all pages from Db
|
||||
$pages = PageModel::selectAll('DISTINCT page.*', '
|
||||
LEFT JOIN page_has_content ON page_has_content.page_id = page.id
|
||||
LEFT JOIN content ON content.id = page_has_content.content_id
|
||||
WHERE page.active = 1 AND content.active = 1
|
||||
ORDER BY page.order ASC;
|
||||
');
|
||||
|
||||
// Return if no pages
|
||||
if (!_exists($pages)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Select id column
|
||||
$section = array_column($sections, 'section', 'id');
|
||||
|
||||
// Loop through all pages
|
||||
foreach ($pages as $pageKey => $page) {
|
||||
// Skip if section isn't created / active
|
||||
if (!_exists($section, $page['section_id'])) { continue; }
|
||||
|
||||
// url = /section/page
|
||||
$url = '/' . $section[$page['section_id']] . '/' . $page['page'];
|
||||
|
||||
// Add route
|
||||
self::$routes[] = [$url, 'PageController', 'route', $page['id']];
|
||||
}
|
||||
|
||||
// Cache sections and pages
|
||||
Db::setSections($sections);
|
||||
Db::setPages($pages);
|
||||
}
|
||||
|
||||
protected static function addRoute(array $method = [], array $data = []): void
|
||||
{
|
||||
if (!_exists($method) || !_exists($data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$route = $data[0] ?? '';
|
||||
$controller = $data[1] ?? '';
|
||||
$action = $data[2] ?? '';
|
||||
$param = $data[3] ?? [];
|
||||
if ($route == '' || $controller == '' || $action == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Klein route
|
||||
self::$router->respond($method, $route, function($request, $response, $service)
|
||||
use($controller, $action, $param) {
|
||||
|
||||
// Create new Controller object
|
||||
$controller = '\App\Controllers\\' . $controller;
|
||||
$controller = new $controller(self::$router);
|
||||
|
||||
$stillValid = true;
|
||||
|
||||
// If method does not exist in object
|
||||
if (!method_exists($controller, $action)) {
|
||||
$stillValid = false;
|
||||
}
|
||||
|
||||
// If no valid permissions
|
||||
if ($controller->getAdminSection() &&
|
||||
$controller->getLoggedIn() == false) {
|
||||
$stillValid = false;
|
||||
}
|
||||
|
||||
// Call Controller action
|
||||
if ($stillValid) {
|
||||
|
||||
// Loop through params
|
||||
$params = [];
|
||||
foreach ($param as $name) {
|
||||
$params[] = $request->param($name);
|
||||
}
|
||||
|
||||
return $controller->{$action}(...$params);
|
||||
}
|
||||
else {
|
||||
$controller->throw404();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static function addBasicRoute(array $method = [], array $route = []): void
|
||||
{
|
||||
if (!_exists($method) || !_exists($route)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Klein route
|
||||
self::$router->respond($method, $route[0], function() use($route) {
|
||||
|
||||
// Create new Controller object
|
||||
$controller = '\App\Controllers\\' . $route[1];
|
||||
$controller = new $controller(self::$router);
|
||||
|
||||
// Complete action variable
|
||||
if ($route[2] == '') {
|
||||
$route[2] = 'indexAction';
|
||||
}
|
||||
else {
|
||||
$route[2] .= 'Action';
|
||||
}
|
||||
|
||||
$stillValid = true;
|
||||
|
||||
// If method does not exist in object
|
||||
if (!method_exists($controller, $route[2])) {
|
||||
$stillValid = false;
|
||||
}
|
||||
|
||||
// If no valid permissions
|
||||
if ($controller->getAdminSection() &&
|
||||
$controller->getLoggedIn() == false) {
|
||||
$stillValid = false;
|
||||
}
|
||||
|
||||
// Call Controller action
|
||||
if ($stillValid) {
|
||||
if (is_array($route[3])) {
|
||||
return $controller->{$route[2]}(
|
||||
$route[3][0] ?? '',
|
||||
$route[3][1] ?? '',
|
||||
$route[3][2] ?? ''
|
||||
);
|
||||
}
|
||||
else if ($route[3] != '') {
|
||||
return $controller->{$route[2]}($route[3]);
|
||||
}
|
||||
else {
|
||||
return $controller->{$route[2]}();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$controller->throw404();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static function createNavigation(): void
|
||||
{
|
||||
// Pull from cache
|
||||
$sections = Db::getSections();
|
||||
$pages = Db::getPages();
|
||||
|
||||
// [
|
||||
// [
|
||||
// 'section url',
|
||||
// 'title',
|
||||
// ['page url', 'title'],
|
||||
// ['page url', 'titleOfPage2'],
|
||||
// ],
|
||||
// [],
|
||||
// [],
|
||||
// ]
|
||||
|
||||
$navigation = [];
|
||||
|
||||
// Generate sections
|
||||
foreach ($sections as $section) {
|
||||
// Skip hidden sections
|
||||
if ($section['hide_navigation'] == '1') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add URL, title to ID
|
||||
$navigation[$section['id']] = [
|
||||
$section['section'], $section['title']
|
||||
];
|
||||
}
|
||||
|
||||
// Generate pages
|
||||
foreach ($pages as $page) {
|
||||
// Skip hidden sections
|
||||
if (!_exists($navigation, $page['section_id'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip hidden pages
|
||||
if ($page['hide_navigation'] == '1') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add [URL, title] to ID
|
||||
$navigation[$page['section_id']][] = [
|
||||
$page['page'], $page['title']
|
||||
];
|
||||
}
|
||||
|
||||
self::$router->service()->navigation = $navigation;
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
protected static function setHttpError(): void
|
||||
{
|
||||
self::$router->onHttpError(function($code) {
|
||||
$service = self::$router->service();
|
||||
|
||||
switch ($code) {
|
||||
case 404:
|
||||
|
||||
$service->escape = function (?string $string) {
|
||||
return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
};
|
||||
|
||||
self::$router->response()->sendHeaders(true, true);
|
||||
$service->pageTitle = 'Error 404 (Not Found)';
|
||||
$service->render('../app/views/errors/404.php');
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------//
|
||||
|
||||
public static function getRoutes(): array
|
||||
{
|
||||
return self::$routes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Router::_init();
|
||||
|
||||
// @Todo
|
||||
// - combine addRoute and addBasicroute functionality
|
||||
Reference in New Issue
Block a user