Routing, static views
This commit is contained in:
parent
0f1c86f210
commit
eb04206989
18
.htaccess
18
.htaccess
@ -1,14 +1,16 @@
|
||||
php_flag display_errors on
|
||||
Options -Indexes
|
||||
|
||||
DirectorySlash Off
|
||||
|
||||
RewriteEngine On
|
||||
RewriteRule ^api(/.*)?$ /index.php?api=$1 [L,QSA]
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
DirectorySlash Off
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d [OR]
|
||||
RewriteCond %{REQUEST_URI} "(\.idea|\.git|src|test|core)(/.*)?"
|
||||
RewriteRule ^(.*)$ /index.php?site=$1 [L,QSA]
|
||||
</IfModule>
|
||||
RewriteEngine On
|
||||
RewriteOptions AllowNoSlash
|
||||
RewriteRule ^((\.idea|\.git|src|test|core|static)(/.*)?)$ /index.php?site=$1 [L,QSA]
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*)$ /index.php?site=$1 [L,QSA]
|
@ -133,7 +133,7 @@ class CreateDatabase {
|
||||
->addRow("^/register(/)?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\Register")
|
||||
->addRow("^/confirmEmail(/)?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\ConfirmEmail")
|
||||
->addRow("^/acceptInvite(/)?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\AcceptInvite")
|
||||
->addRow("^/$", "dynamic", "\\Documents\\Welcome", NULL);
|
||||
->addRow("^/$", "static", "/static/welcome.html", NULL);
|
||||
|
||||
return $queries;
|
||||
}
|
||||
|
@ -29,12 +29,7 @@ namespace Documents\Admin {
|
||||
}
|
||||
|
||||
protected function initSources() {
|
||||
// $this->loadJQuery();
|
||||
$this->loadFontawesome();
|
||||
// $this->addJS(Script::CORE);
|
||||
// $this->addCSS(Link::CORE);
|
||||
// $this->addJS(Script::ADMIN);
|
||||
// $this->addCSS(Link::ADMIN);
|
||||
}
|
||||
|
||||
protected function initMetas() {
|
||||
|
@ -17,6 +17,7 @@ namespace Documents\Document404 {
|
||||
|
||||
use Elements\Body;
|
||||
use Elements\Head;
|
||||
use Elements\SimpleBody;
|
||||
use Views\View404;
|
||||
|
||||
class Head404 extends Head {
|
||||
@ -47,7 +48,7 @@ namespace Documents\Document404 {
|
||||
}
|
||||
}
|
||||
|
||||
class Body404 extends Body {
|
||||
class Body404 extends SimpleBody {
|
||||
|
||||
public function __construct($document) {
|
||||
parent::__construct($document);
|
||||
@ -57,10 +58,8 @@ namespace Documents\Document404 {
|
||||
http_response_code(404);
|
||||
}
|
||||
|
||||
public function getCode() {
|
||||
$html = parent::getCode();
|
||||
$html .= "<body>" . (new View404($this->getDocument())) . "</body>";
|
||||
return $html;
|
||||
protected function getContent() {
|
||||
return $this->load(View404::class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Documents {
|
||||
|
||||
use Documents\Welcome\WelcomeBody;
|
||||
use Documents\Welcome\WelcomeHead;
|
||||
use Elements\Document;
|
||||
use Objects\User;
|
||||
|
||||
class Welcome extends Document {
|
||||
public function __construct(User $user, ?string $view) {
|
||||
parent::__construct($user, WelcomeHead::class, WelcomeBody::class, $view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Documents\Welcome {
|
||||
|
||||
use Elements\Head;
|
||||
use Elements\SimpleBody;
|
||||
|
||||
class WelcomeHead extends Head {
|
||||
|
||||
public function __construct($document) {
|
||||
parent::__construct($document);
|
||||
}
|
||||
|
||||
protected function initSources() {
|
||||
$this->loadBootstrap();
|
||||
}
|
||||
|
||||
protected function initMetas() {
|
||||
return array(
|
||||
array('name' => 'viewport', 'content' => 'width=device-width, initial-scale=1.0'),
|
||||
array('name' => 'format-detection', 'content' => 'telephone=yes'),
|
||||
array('charset' => 'utf-8'),
|
||||
array("http-equiv" => 'expires', 'content' => '0'),
|
||||
array("name" => 'robots', 'content' => 'noarchive'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function initRawFields() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function initTitle() {
|
||||
return "Welcome";
|
||||
}
|
||||
}
|
||||
|
||||
class WelcomeBody extends SimpleBody {
|
||||
|
||||
public function __construct($document) {
|
||||
parent::__construct($document);
|
||||
}
|
||||
|
||||
protected function getContent() {
|
||||
return
|
||||
"<div class='container mt-5'>
|
||||
<div class='row'>
|
||||
<div class='col-lg-9 col-12 mx-auto'>
|
||||
<div class='jumbotron'>
|
||||
<h1>Congratulations!</h1>
|
||||
<p class='lead'>Your Web-Base Installation is now ready to use!</p>
|
||||
<hr class='my-4' />
|
||||
<p>
|
||||
You can now login into your <a href='/admin'>Administrator Dashboard</a> to adjust your settings
|
||||
and add routes & pages.
|
||||
You can add new documents and views by adding classes in the corresponding
|
||||
directories and link to them, by creating rules in the Administrator Dashboard.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ abstract class Head extends View {
|
||||
function __construct($document) {
|
||||
parent::__construct($document);
|
||||
$this->sources = array();
|
||||
$this->searchable = false;
|
||||
$this->metas = $this->initMetas();
|
||||
$this->rawFields = $this->initRawFields();
|
||||
$this->title = $this->initTitle();
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace Elements;
|
||||
|
||||
use External\PHPMailer\Exception;
|
||||
|
||||
abstract class View extends StaticView {
|
||||
|
||||
private Document $document;
|
||||
@ -25,6 +27,21 @@ abstract class View extends StaticView {
|
||||
public function isSearchable() { return $this->searchable; }
|
||||
public function getReference() { return $this->reference; }
|
||||
|
||||
protected function load(string $viewClass) : string {
|
||||
try {
|
||||
$reflectionClass = new \ReflectionClass($viewClass);
|
||||
if ($reflectionClass->isSubclassOf(View::class) && $reflectionClass->isInstantiable()) {
|
||||
$view = $reflectionClass->newInstanceArgs(array($this->getDocument()));
|
||||
$view->loadView();
|
||||
return $view;
|
||||
}
|
||||
} catch(\ReflectionException $e) {
|
||||
error_log($e->getMessage());
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private function loadLanguageModules() {
|
||||
$lang = $this->document->getUser()->getLanguage();
|
||||
foreach($this->langModules as $langModule) {
|
||||
|
@ -11,9 +11,11 @@ class LanguageFlags extends View {
|
||||
public function __construct($document) {
|
||||
parent::__construct($document);
|
||||
$this->languageFlags = array();
|
||||
$this->searchable = false;
|
||||
}
|
||||
|
||||
public function getCode() {
|
||||
public function loadView() {
|
||||
parent::loadView();
|
||||
|
||||
$request = new \Api\Language\Get($this->getDocument()->getUser());
|
||||
if ($request->execute()) {
|
||||
@ -51,8 +53,10 @@ class LanguageFlags extends View {
|
||||
"<img class=\"p-1 clickable\" src=\"/img/icons/lang/$langCode.gif\" alt=\"$langName\" title=\"$langName\">"
|
||||
);
|
||||
}
|
||||
|
||||
return implode('', $this->languageFlags);
|
||||
}
|
||||
}
|
||||
|
||||
public function getCode() {
|
||||
return implode('', $this->languageFlags);
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ class LoginBody extends Body {
|
||||
$backToStartPage = L("Back to Start Page");
|
||||
$stayLoggedIn = L("Stay logged in");
|
||||
|
||||
$flags = new LanguageFlags($this->getDocument());
|
||||
$flags = $this->load(LanguageFlags::class);
|
||||
$iconBack = $this->createIcon("arrow-circle-left");
|
||||
$domain = $_SERVER['HTTP_HOST'];
|
||||
$protocol = getProtocol();
|
||||
|
198
core/core.php
198
core/core.php
@ -1,104 +1,122 @@
|
||||
<?php
|
||||
|
||||
define("WEBBASE_VERSION", "0.1.0-alpha");
|
||||
define("WEBBASE_VERSION", "0.1.0-alpha");
|
||||
|
||||
function getSubclassesOf($parent) {
|
||||
$result = array();
|
||||
foreach (get_declared_classes() as $class) {
|
||||
if (is_subclass_of($class, $parent))
|
||||
$result[] = $class;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
function getProtocol() {
|
||||
return stripos($_SERVER['SERVER_PROTOCOL'], 'https') === 0 ? 'https' : 'http';
|
||||
}
|
||||
|
||||
function getProtocol() {
|
||||
return stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https' : 'http';
|
||||
}
|
||||
|
||||
function generateRandomString($length) : string {
|
||||
$randomString = '';
|
||||
if($length > 0) {
|
||||
$numCharacters = 26 + 26 + 10; // a-z + A-Z + 0-9
|
||||
for ($i = 0; $i < $length; $i++)
|
||||
{
|
||||
try {
|
||||
$num = random_int(0, $numCharacters - 1);
|
||||
} catch (Exception $e) {
|
||||
$num = rand(0, $numCharacters - 1);
|
||||
}
|
||||
|
||||
if($num < 26) $randomString .= chr(ord('a') + $num);
|
||||
else if($num - 26 < 26) $randomString .= chr(ord('A') + $num - 26);
|
||||
else $randomString .= chr(ord('0') + $num - 26 - 26);
|
||||
}
|
||||
}
|
||||
|
||||
return $randomString;
|
||||
}
|
||||
|
||||
function startsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
return (substr($haystack, 0, $length) === $needle);
|
||||
}
|
||||
|
||||
function endsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
if ($length == 0)
|
||||
return true;
|
||||
|
||||
return (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
|
||||
function intendCode($code, $escape=true) {
|
||||
$newCode = "";
|
||||
$first = true;
|
||||
$brackets = array();
|
||||
$intend = 0;
|
||||
|
||||
foreach(explode("\n", $code) as $line) {
|
||||
if(!$first) $newCode .= "\n";
|
||||
if($escape) $line = htmlspecialchars($line);
|
||||
$line = trim($line);
|
||||
|
||||
if(count($brackets) > 0 && startsWith($line, current($brackets))) {
|
||||
$intend = max(0, $intend - 2);
|
||||
array_pop($brackets);
|
||||
function generateRandomString($length): string {
|
||||
$randomString = '';
|
||||
if ($length > 0) {
|
||||
$numCharacters = 26 + 26 + 10; // a-z + A-Z + 0-9
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
try {
|
||||
$num = random_int(0, $numCharacters - 1);
|
||||
} catch (Exception $e) {
|
||||
$num = rand(0, $numCharacters - 1);
|
||||
}
|
||||
|
||||
$newCode .= str_repeat(" ", $intend);
|
||||
$newCode .= $line;
|
||||
$first = false;
|
||||
if ($num < 26) $randomString .= chr(ord('a') + $num);
|
||||
else if ($num - 26 < 26) $randomString .= chr(ord('A') + $num - 26);
|
||||
else $randomString .= chr(ord('0') + $num - 26 - 26);
|
||||
}
|
||||
}
|
||||
|
||||
if(endsWith($line, "{")) {
|
||||
$intend += 2;
|
||||
array_push($brackets, "}");
|
||||
} else if(endsWith($line, "(")) {
|
||||
$intend += 2;
|
||||
array_push($brackets, ")");
|
||||
}
|
||||
return $randomString;
|
||||
}
|
||||
|
||||
function startsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
return (substr($haystack, 0, $length) === $needle);
|
||||
}
|
||||
|
||||
function endsWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
if ($length == 0)
|
||||
return true;
|
||||
|
||||
return (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
|
||||
function intendCode($code, $escape = true) {
|
||||
$newCode = "";
|
||||
$first = true;
|
||||
$brackets = array();
|
||||
$intend = 0;
|
||||
|
||||
foreach (explode("\n", $code) as $line) {
|
||||
if (!$first) $newCode .= "\n";
|
||||
if ($escape) $line = htmlspecialchars($line);
|
||||
$line = trim($line);
|
||||
|
||||
if (count($brackets) > 0 && startsWith($line, current($brackets))) {
|
||||
$intend = max(0, $intend - 2);
|
||||
array_pop($brackets);
|
||||
}
|
||||
|
||||
return $newCode;
|
||||
}
|
||||
$newCode .= str_repeat(" ", $intend);
|
||||
$newCode .= $line;
|
||||
$first = false;
|
||||
|
||||
function replaceCssSelector($sel) {
|
||||
return preg_replace("~[.#<>]~", "_", preg_replace("~[:\-]~", "", $sel));
|
||||
}
|
||||
|
||||
function getClassPath($class, $suffix=true) {
|
||||
$path = str_replace('\\', '/', $class);
|
||||
$path = array_values(array_filter(explode("/", $path)));
|
||||
|
||||
if (strcasecmp($path[0], "api") === 0 && count($path) > 2 && strcasecmp($path[1], "Parameter") !== 0) {
|
||||
$path = "Api/" . $path[1] . "API";
|
||||
} else {
|
||||
$path = implode("/", $path);
|
||||
if (endsWith($line, "{")) {
|
||||
$intend += 2;
|
||||
array_push($brackets, "}");
|
||||
} else if (endsWith($line, "(")) {
|
||||
$intend += 2;
|
||||
array_push($brackets, ")");
|
||||
}
|
||||
|
||||
$suffix = ($suffix ? ".class" : "");
|
||||
return "core/$path$suffix.php";
|
||||
}
|
||||
|
||||
function createError($msg) {
|
||||
return json_encode(array("success" => false, "msg" => $msg));
|
||||
return $newCode;
|
||||
}
|
||||
|
||||
function replaceCssSelector($sel) {
|
||||
return preg_replace("~[.#<>]~", "_", preg_replace("~[:\-]~", "", $sel));
|
||||
}
|
||||
|
||||
function getClassPath($class, $suffix = true) {
|
||||
$path = str_replace('\\', '/', $class);
|
||||
$path = array_values(array_filter(explode("/", $path)));
|
||||
|
||||
if (strcasecmp($path[0], "api") === 0 && count($path) > 2 && strcasecmp($path[1], "Parameter") !== 0) {
|
||||
$path = "Api/" . $path[1] . "API";
|
||||
} else {
|
||||
$path = implode("/", $path);
|
||||
}
|
||||
|
||||
$suffix = ($suffix ? ".class" : "");
|
||||
return "core/$path$suffix.php";
|
||||
}
|
||||
|
||||
function createError($msg) {
|
||||
return json_encode(array("success" => false, "msg" => $msg));
|
||||
}
|
||||
|
||||
function serveStatic(string $webRoot, string $file): string {
|
||||
|
||||
$path = realpath($webRoot . "/" . $file);
|
||||
if (!startsWith($path, $webRoot . "/")) {
|
||||
http_response_code(406);
|
||||
return "<b>Access restricted, requested file outside web root:</b> " . htmlspecialchars($path);
|
||||
}
|
||||
|
||||
if (!file_exists($path) || !is_file($path) || !is_readable($path)) {
|
||||
http_response_code(500);
|
||||
return "<b>Unable to read file:</b> " . htmlspecialchars($path);
|
||||
}
|
||||
|
||||
$pathInfo = pathinfo($file);
|
||||
|
||||
// maybe I will allow more later…
|
||||
$allowedExtension = array("html", "htm");
|
||||
$ext = $pathInfo["extension"] ?? "";
|
||||
if (!in_array($ext, $allowedExtension)) {
|
||||
http_response_code(406);
|
||||
return "<b>Access restricted:</b> Extension '" . htmlspecialchars($ext) . "' not allowed.";
|
||||
}
|
||||
|
||||
$mimeType = mime_content_type($file);
|
||||
header("Content-Type: $mimeType");
|
||||
return readfile($file);
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) {
|
||||
$success = $req->execute(array("request" => $documentName));
|
||||
$response = "";
|
||||
if (!$success) {
|
||||
http_response_code(500);
|
||||
$response = "Unable to find route: " . $req->getLastError();
|
||||
} else {
|
||||
$route = $req->getResult()["route"];
|
||||
@ -106,8 +107,8 @@ if(isset($_GET["api"]) && is_string($_GET["api"])) {
|
||||
header("Location: $target");
|
||||
break;
|
||||
case "static":
|
||||
http_response_code(501);
|
||||
$response = "Not implemented yet.";
|
||||
$currentDir = dirname(__FILE__);
|
||||
$response = serveStatic($currentDir, $target);
|
||||
break;
|
||||
case "dynamic":
|
||||
$view = $route["extra"] ?? "";
|
||||
|
30
static/welcome.html
Normal file
30
static/welcome.html
Normal file
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="format-detection" content="telephone=yes">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="expires" content="0">
|
||||
<meta name="robots" content="noarchive">
|
||||
<title>Welcome</title>
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" type="text/css">
|
||||
<script type="text/javascript" src="/js/bootstrap.bundle.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-9 col-12 mx-auto">
|
||||
<div class="jumbotron">
|
||||
<h1>Congratulations!</h1>
|
||||
<p class="lead">Your Web-Base Installation is now ready to use!</p>
|
||||
<hr class="my-4" />
|
||||
<p>
|
||||
You can now login into your <a href="/admin">Administrator Dashboard</a> to adjust your settings
|
||||
and add routes & pages.
|
||||
You can add new documents and views by adding classes in the corresponding
|
||||
directories and link to them, by creating rules in the Administrator Dashboard.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
Loading…
Reference in New Issue
Block a user