Routing, static views
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user