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.
353 lines
8.1 KiB
353 lines
8.1 KiB
<?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: |
|
|
|
// @Todo: find out why this was needed and remove if possible |
|
$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
|
|
|