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.
205 lines
5.5 KiB
205 lines
5.5 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @author Robert Strutts <Robert@TryingToScale.com>
|
|
* @copyright Copyright (c) 2022, Robert Strutts.
|
|
* @license https://mit-license.org/
|
|
*/
|
|
|
|
namespace tts;
|
|
|
|
use Exception;
|
|
|
|
/**
|
|
*
|
|
* @todo Ensure tts JS error reporting works
|
|
* @todo
|
|
* @todo Make Cached Sessions
|
|
* @todo Force Database methods to try Cache First and Save Cache Data
|
|
*/
|
|
|
|
class app {
|
|
private $file;
|
|
private $class;
|
|
private $method;
|
|
private $params;
|
|
|
|
private function get_first_chunks(string $input): string {
|
|
$parts = explode('/', $input);
|
|
$last = array_pop($parts);
|
|
$parts = array(implode('/', $parts), $last);
|
|
return $parts[0];
|
|
}
|
|
|
|
private function get_last_part(string $input): string {
|
|
$reversedParts = explode('/', strrev($input), 2);
|
|
return strrev($reversedParts[0]);
|
|
}
|
|
|
|
/**
|
|
* Do not declare a return type here, as it will Error out!!
|
|
*/
|
|
public function __construct() {
|
|
$full_route = \bs_tts\site_helper::get_route();
|
|
$no_hmtl = str_replace(".html", "", $full_route);
|
|
|
|
// Find the Route
|
|
$route = $this->get_first_chunks($no_hmtl);
|
|
|
|
// Find the Method
|
|
$the_method = $this->get_last_part($no_hmtl);
|
|
|
|
$params = \bs_tts\site_helper::get_params();
|
|
|
|
// Now load Route
|
|
$is_from_the_controller = true; // TRUE for from Constructor...
|
|
$this->router($route, $the_method, $params, $is_from_the_controller);
|
|
}
|
|
|
|
private function get_ctrl_dir(): string {
|
|
$ctrl = (\tts\console_app::is_cli()) ? "cli_" : "";
|
|
return (\bs_tts\site_helper::get_testing()) ? "test_" : $ctrl;
|
|
}
|
|
|
|
/**
|
|
* Gets route and checks if valid
|
|
* @param string $route
|
|
* @param string $method
|
|
* @param bool $is_controller
|
|
* @retval action
|
|
*/
|
|
public function router(?string $route, ?string $method, $params, bool $is_controller = false) {
|
|
$ROOT = \bs_tts\site_helper::get_root();
|
|
$file = "";
|
|
$class = "";
|
|
|
|
if (\tts\request::is_empty($route)) {
|
|
$uri = '/app/' . \main_tts\configure::get('tts', 'default_project');
|
|
} else {
|
|
$uri = $route;
|
|
}
|
|
|
|
$filtered_uri = \tts\security::filter_uri($uri);
|
|
|
|
$safe_folders = \bs_tts\requires::filter_dir_path(
|
|
$this->get_first_chunks($filtered_uri)
|
|
);
|
|
if (\bs_tts\requires::is_dangerous($safe_folders)) {
|
|
$this->local404();
|
|
}
|
|
|
|
$safe_folders = rtrim($safe_folders, '/');
|
|
if (empty($ROOT)) {
|
|
$this->local404();
|
|
}
|
|
|
|
$safe_file = \bs_tts\requires::filter_dir_path(
|
|
$this->get_last_part($filtered_uri)
|
|
);
|
|
if (\bs_tts\requires::is_dangerous($safe_file)) {
|
|
$this->local404();
|
|
}
|
|
|
|
$test = $this->get_ctrl_dir();
|
|
$dir = \bs_tts\requires::safer_dir_exists($ROOT . \bs_tts\site_helper::get_project() . "{$test}controllers/" . $safe_folders);
|
|
|
|
//check for default site controller first
|
|
if ($dir === false) {
|
|
$this->local404();
|
|
} else {
|
|
$file = \bs_tts\requires::safer_file_exists(basename($safe_file) . '_ctrl.php', $dir);
|
|
if ($file !== false) {
|
|
$class = \tts\security::filter_class($safe_folders) . "\\" . \tts\security::filter_class($safe_file . "_ctrl");
|
|
} else {
|
|
$this->local404();
|
|
}
|
|
}
|
|
|
|
if (\tts\request::is_empty($method)) {
|
|
$method = ""; // Clear out :null if exists
|
|
}
|
|
|
|
if (substr($method, 0, 2) == '__') {
|
|
$method = ""; // Stop any magical methods being called
|
|
}
|
|
|
|
if ($is_controller === true) {
|
|
$this->file = $file;
|
|
$this->class = $class;
|
|
$this->method = $method;
|
|
$this->params = $params;
|
|
} else {
|
|
return $this->action($file, $class, $method, $params);
|
|
}
|
|
}
|
|
|
|
private function local404() {
|
|
\tts\page_not_found::tts_error404();
|
|
}
|
|
|
|
private function handle_my_errors($controller, string $method_name): void {
|
|
// if (! method_exists($controller, "skip_default_error_handler_for_" . $method_name)) {
|
|
// require_once \main_tts\TTS_FRAMEWORK . 'bootstrap/errors.php';
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Do controller action
|
|
* @param string $file
|
|
* @param string $class
|
|
* @param string $method
|
|
* @retval type
|
|
*/
|
|
private function action(string $file, string $class, string $method, $params) {
|
|
$safer_file = \bs_tts\requires::safer_file_exists($file);
|
|
if (! $safer_file) {
|
|
$this->local404();
|
|
}
|
|
if (empty($class)) {
|
|
$this->local404();
|
|
}
|
|
|
|
$use_api = \tts\request::is_api();
|
|
$test = $this->get_ctrl_dir();
|
|
|
|
$project_folder = \bs_tts\site_helper::get_project();
|
|
$call_class = "\\prj\\" . rtrim($project_folder, "/") . '\\' . $test . 'controllers\\' . $class;
|
|
$controller = new $call_class();
|
|
|
|
|
|
if ($use_api) {
|
|
if (empty($method)) {
|
|
$method = "index";
|
|
}
|
|
$method .= "_api";
|
|
if (method_exists($controller, $method)) {
|
|
$this->handle_my_errors($controller, $method);
|
|
return $controller->$method($params);
|
|
} else {
|
|
\tts\page_not_found::tts_error404_cli();
|
|
}
|
|
} else {
|
|
if (!empty($method) && method_exists($controller, $method)) {
|
|
$this->handle_my_errors($controller, $method);
|
|
return $controller->$method($params);
|
|
} else {
|
|
if (empty($method) && method_exists($controller, 'index')) {
|
|
$this->handle_my_errors($controller, 'index');
|
|
return $controller->index($params);
|
|
} else {
|
|
$this->local404();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Does load controller by calling action
|
|
*/
|
|
public function load_controller() {
|
|
return $this->action($this->file, $this->class, $this->method, $this->params);
|
|
}
|
|
|
|
} // end of app
|
|
|