summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2026-02-23 22:57:27 -0500
committerFreya Murphy <freya@freyacat.org>2026-02-23 22:57:27 -0500
commitf373ead95fb5beb962c376b5b7b46dfde8ac4e57 (patch)
treec99df23521ff2a5e5e2e4627c525a5e99dc2e3ae /src
parentadd 96x96 logo (diff)
downloadwebsite-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.tar.gz
website-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.tar.bz2
website-f373ead95fb5beb962c376b5b7b46dfde8ac4e57.zip
update website to work with crimson framework
Diffstat (limited to '')
-rw-r--r--src/db/migrations/0003.sql11
-rw-r--r--src/public/css/prism.css3
-rw-r--r--src/public/favicon.ico (renamed from src/public/icons/favicon.ico)bin4286 -> 4286 bytes
-rw-r--r--src/scss/main.scss3
-rw-r--r--src/web/_controller/_comments.php4
-rw-r--r--src/web/_controller/_meta.php4
-rw-r--r--src/web/_controller/blog.php1
-rw-r--r--src/web/_controller/bucket.php1
-rw-r--r--src/web/_controller/error.php3
-rw-r--r--src/web/_controller/home.php10
-rw-r--r--src/web/_controller/projects.php1
-rw-r--r--src/web/_model/_comments.php26
-rw-r--r--src/web/_model/blog.php7
-rw-r--r--src/web/_model/bucket.php5
-rw-r--r--src/web/_model/error.php11
-rw-r--r--src/web/_model/home.php10
-rw-r--r--src/web/_model/projects.php3
-rw-r--r--src/web/_views/head.php2
-rw-r--r--src/web/_views/header.php6
-rw-r--r--src/web/config.php41
-rw-r--r--src/web/core/component.php119
-rw-r--r--src/web/core/controller.php65
-rw-r--r--src/web/core/core.php109
-rw-r--r--src/web/core/model.php39
-rw-r--r--src/web/core/router.php208
-rw-r--r--src/web/helpers/database.php323
-rw-r--r--src/web/helpers/lang.php90
-rw-r--r--src/web/helpers/sanitize.php8
-rw-r--r--src/web/index.php48
-rw-r--r--src/web/lang/error.php58
-rw-r--r--src/web/lib/aria.php (renamed from src/web/helpers/aria.php)0
-rw-r--r--src/web/lib/hooks.php10
-rw-r--r--src/web/lib/ie.php (renamed from src/web/helpers/ie.php)0
-rw-r--r--src/web/lib/image.php (renamed from src/web/helpers/image.php)6
-rw-r--r--src/web/lib/markdown.php (renamed from src/web/helpers/markdown.php)0
35 files changed, 124 insertions, 1111 deletions
diff --git a/src/db/migrations/0003.sql b/src/db/migrations/0003.sql
new file mode 100644
index 0000000..1e47e73
--- /dev/null
+++ b/src/db/migrations/0003.sql
@@ -0,0 +1,11 @@
+BEGIN TRANSACTION;
+SET search_path = public;
+
+-- Migration Start
+ALTER SCHEMA admin RENAME TO website;
+-- Migration End;
+
+-- Set Current Revision
+UPDATE sys.database_info SET curr_revision = 4 WHERE name = current_database();
+
+COMMIT TRANSACTION;
diff --git a/src/public/css/prism.css b/src/public/css/prism.css
deleted file mode 100644
index 5137f0c..0000000
--- a/src/public/css/prism.css
+++ /dev/null
@@ -1,3 +0,0 @@
-/* PrismJS 1.29.0
-https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+awk+bash+c+csharp+cpp+elixir+erlang+go+java+javadoclike+kotlin+lua+markup-templating+php+plsql+racket+ruby+rust+sass+scss+scala+scheme+sql+typescript+zig */
-code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}
diff --git a/src/public/icons/favicon.ico b/src/public/favicon.ico
index 1fae1b9..1fae1b9 100644
--- a/src/public/icons/favicon.ico
+++ b/src/public/favicon.ico
Binary files differ
diff --git a/src/scss/main.scss b/src/scss/main.scss
index 1148ba1..b9ef3ee 100644
--- a/src/scss/main.scss
+++ b/src/scss/main.scss
@@ -77,6 +77,9 @@ html {
font-family: $font;
font-size: 120%;
background: #181818;
+}
+
+body {
background-image: url("../img/background.jpg?ref=2");
background-repeat: repeat;
background-size: 512px;
diff --git a/src/web/_controller/_comments.php b/src/web/_controller/_comments.php
index 3b8fe35..c81ae9d 100644
--- a/src/web/_controller/_comments.php
+++ b/src/web/_controller/_comments.php
@@ -5,6 +5,7 @@ class _comments_controller extends Controller {
function __construct() {
$this->comments_model = $this->load_model('_comments');
+ $this->load_lang('common');
}
public function comments(string $page, string $ref): void {
@@ -12,7 +13,8 @@ class _comments_controller extends Controller {
$this->view('comments', array(
'comments' => $data,
'ref' => $ref,
- 'page' => $page
+ 'page' => $page,
+ 'ip', $this->comments_model->get_ip(),
));
}
diff --git a/src/web/_controller/_meta.php b/src/web/_controller/_meta.php
index 9ea3f47..ac9f682 100644
--- a/src/web/_controller/_meta.php
+++ b/src/web/_controller/_meta.php
@@ -1,6 +1,10 @@
<?php /* Copyright (c) 2024 Freya Murphy */
class _meta_controller extends Controller {
+ function __construct() {
+ $this->load_lang('common');
+ }
+
public function robots(): void
{
header("Content-Type: text/plain");
diff --git a/src/web/_controller/blog.php b/src/web/_controller/blog.php
index 2ea45df..9cb93e5 100644
--- a/src/web/_controller/blog.php
+++ b/src/web/_controller/blog.php
@@ -8,6 +8,7 @@ class Blog_controller extends Controller {
{
$this->blog_model = $this->load_model('blog');
$this->comments_controller = $this->load_controller('_comments');
+ $this->load_lang('common', 'blog');
}
public function index(): void
diff --git a/src/web/_controller/bucket.php b/src/web/_controller/bucket.php
index e14f9b6..460f862 100644
--- a/src/web/_controller/bucket.php
+++ b/src/web/_controller/bucket.php
@@ -6,6 +6,7 @@ class Bucket_controller extends Controller {
function __construct()
{
$this->bucket_model = $this->load_model('bucket');
+ $this->load_lang('common', 'bucket');
}
public function index(): void
diff --git a/src/web/_controller/error.php b/src/web/_controller/error.php
index 9efbb7e..ed89a89 100644
--- a/src/web/_controller/error.php
+++ b/src/web/_controller/error.php
@@ -6,6 +6,7 @@ class Error_controller extends Controller {
function __construct()
{
$this->error_model = $this->load_model('error');
+ $this->load_lang('common', 'error');
}
public function code(int $code): void
@@ -18,7 +19,7 @@ class Error_controller extends Controller {
parent::index();
$this->load_lang('error');
- $data = $this->error_model->get_data($code);
+ $data = $this->error_model->get_error_data($code);
$this->view('header', $data);
$this->view('error/main', $data);
$this->view('footer', $data);
diff --git a/src/web/_controller/home.php b/src/web/_controller/home.php
index 89e67e8..28ccd1e 100644
--- a/src/web/_controller/home.php
+++ b/src/web/_controller/home.php
@@ -1,11 +1,19 @@
<?php /* Copyright (c) 2024 Freya Murphy */
class Home_controller extends Controller {
+ private $home_model;
+
+ function __construct()
+ {
+ $this->home_model = $this->load_model('home');
+ $this->load_lang('common', 'home');
+ }
+
public function index(): void
{
parent::index();
- $data = Model::get_base_data();
+ $data = $this->home_model->get_data();
$this->view('header', $data);
$this->view('home/main', $data);
$this->view('footer', $data);
diff --git a/src/web/_controller/projects.php b/src/web/_controller/projects.php
index fea4664..35274b5 100644
--- a/src/web/_controller/projects.php
+++ b/src/web/_controller/projects.php
@@ -6,6 +6,7 @@ class Projects_controller extends Controller {
function __construct()
{
$this->projects_model = $this->load_model('projects');
+ $this->load_lang('common', 'projects');
}
public function index(): void
diff --git a/src/web/_model/_comments.php b/src/web/_model/_comments.php
index 3518508..765fda8 100644
--- a/src/web/_model/_comments.php
+++ b/src/web/_model/_comments.php
@@ -36,10 +36,10 @@ class _comments_model extends Model {
public function get_comments($page)
{
- $ip = CONTEXT['ip'];
+ $ip = $this->get_ip();
$query = $this->db()
->select('*')
- ->from('admin.comment c')
+ ->from('website.comment c')
->where('c.page')
->eq($page)
->query('AND (
@@ -53,12 +53,30 @@ class _comments_model extends Model {
public function post_comment($author, $content, $page, $vulgar)
{
- $ip = CONTEXT['ip'];
+ $ip = $this->get_ip();
return $this->db()
- ->insert_into('admin.comment',
+ ->insert_into('website.comment',
'author', 'content', 'page', 'ip', 'vulgar')
->values($author, $content, $page, $ip, $vulgar)
->execute();
}
+ public function get_ip(): ?string
+ {
+ $headers = array (
+ 'HTTP_CLIENT_IP',
+ 'HTTP_X_FORWARDED_FOR',
+ 'HTTP_X_FORWARDED',
+ 'HTTP_FORWARDED_FOR',
+ 'HTTP_FORWARDED',
+ 'HTTP_X_REAL_IP',
+ 'REMOTE_ADDR'
+ );
+ foreach ($headers as $header) {
+ if (isset($_SERVER[$header]))
+ return $_SERVER[$header];
+ }
+ return NULL;
+ }
+
}
diff --git a/src/web/_model/blog.php b/src/web/_model/blog.php
index 94ca049..6446564 100644
--- a/src/web/_model/blog.php
+++ b/src/web/_model/blog.php
@@ -30,7 +30,7 @@ class Blog_model extends Model {
}
public function get_data(): array {
- $data = parent::get_base_data('blog');
+ $data = parent::get_data();
$this->load_blog($data);
$data['title'] = lang('title');
$data['desc'] = lang('blog_short_desc');
@@ -68,7 +68,7 @@ class Blog_model extends Model {
* @return bool|null|array
*/
public function get_post($name): ?array {
- $data = parent::get_base_data();
+ $data = parent::get_data();
$post = $this->render_post($name);
if (!$post) {
return NULL;
@@ -97,7 +97,7 @@ class Blog_model extends Model {
* @return bool|null|array
*/
public function get_writeup($name): ?array {
- $data = parent::get_base_data();
+ $data = parent::get_data();
$writeup = $this->render_writeup($name);
if (!$writeup) {
return NULL;
@@ -108,4 +108,3 @@ class Blog_model extends Model {
return $data;
}
}
-?>
diff --git a/src/web/_model/bucket.php b/src/web/_model/bucket.php
index 374836e..7c426b7 100644
--- a/src/web/_model/bucket.php
+++ b/src/web/_model/bucket.php
@@ -3,7 +3,9 @@ class Bucket_model extends Model {
public function get_data(): ?array
{
- $data = parent::get_base_data();
+ $data = parent::get_data();
+ $data['title'] = lang('first_name');
+ $data['desc'] = lang('default_short_desc');
if (array_key_exists('name', $_GET))
$data['name'] = $_GET['name'];
@@ -18,4 +20,3 @@ class Bucket_model extends Model {
return $data;
}
}
-?>
diff --git a/src/web/_model/error.php b/src/web/_model/error.php
index 08046f3..74bbd20 100644
--- a/src/web/_model/error.php
+++ b/src/web/_model/error.php
@@ -5,21 +5,22 @@ class Error_model extends Model {
{
http_response_code($code);
$data['title'] = $code;
- $msg = ucfirst(lang('error_' . $code, FALSE));
+ $msg = status_code_msg($code);
+ if (!$msg && $code == 0)
+ $msg = lang('error_0');
if (!$msg) {
$error_text = lang('error', NULL);
$msg = $error_text[array_rand($error_text)];
$msg = sprintf($msg, $code);
}
$data['msg'] = $msg;
-
+ $data['desc'] = $msg;
}
- public function get_data(int $code): array
+ public function get_error_data(int $code): array
{
- $data = parent::get_base_data('error');
+ $data = parent::get_data();
$this->get_msg($data, $code);
return $data;
}
}
-?>
diff --git a/src/web/_model/home.php b/src/web/_model/home.php
new file mode 100644
index 0000000..d1041db
--- /dev/null
+++ b/src/web/_model/home.php
@@ -0,0 +1,10 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+class Home_model extends Model {
+
+ public function get_data(): ?array {
+ $data = parent::get_data();
+ $data['title'] = lang('first_name');
+ $data['desc'] = lang('default_short_desc');
+ return $data;
+ }
+}
diff --git a/src/web/_model/projects.php b/src/web/_model/projects.php
index 537bce5..fbf37c8 100644
--- a/src/web/_model/projects.php
+++ b/src/web/_model/projects.php
@@ -31,11 +31,10 @@ class Projects_model extends Model {
public function get_data(): ?array
{
- $data = parent::get_base_data();
+ $data = parent::get_data();
$this->load_projects($data);
$data['title'] = lang('title');
$data['desc'] = lang('short_desc');
return $data;
}
}
-?>
diff --git a/src/web/_views/head.php b/src/web/_views/head.php
index ab7bb1b..1ca6954 100644
--- a/src/web/_views/head.php
+++ b/src/web/_views/head.php
@@ -23,7 +23,7 @@
<link rel="manifest" href="/manifest.json">
<?php
/* Main CSS */
- if (CONTEXT['app'] != 'bucket')
+ if (ROUTER->req['app'] != 'bucket')
echo $this->link_css('css/main.css');
/* IE 4-7 Styles */
diff --git a/src/web/_views/header.php b/src/web/_views/header.php
index 90a31ea..f6b4740 100644
--- a/src/web/_views/header.php
+++ b/src/web/_views/header.php
@@ -17,15 +17,15 @@
<li class="ie-nav">
<?=ilang('action_home',
href: $this->get_url('home'),
- container: 'h2'
+ subtype: 'h2'
)?></li>
<li><?=ilang('action_projects',
href: $this->get_url('projects'),
- container: 'h2'
+ subtype: 'h2'
)?></li>
<li><?=ilang('action_blog',
href: $this->get_url('blog'),
- container: 'h2'
+ subtype: 'h2'
)?></li>
</ul>
</div>
diff --git a/src/web/config.php b/src/web/config.php
index 8689b8e..4a4e830 100644
--- a/src/web/config.php
+++ b/src/web/config.php
@@ -1,26 +1,33 @@
<?php /* Copyright (c) 2024 Freya Murphy */
-// ENVIRONMENT
+// CONFIG
+// config values needed across the website
//
-// devlopment - do not cache any assets
-// - use http host provided by user
+// domain - the default domain for the website
//
-// production - use generated timestamps for each file
-// - hard code http host to 'domain' lang string
+// allowed_hosts - accepted domains to use for the website
//
-define('ENVIRONMENT', 'devlopment');
-
-// CONFIG
+// base_path - the base path the website is located at
//
-// config values needed across the website
-
-define('CONFIG', array(
+// theme_color - html hex color used for browser metadata
+//
+// routes - array of regex keys that match the request path and
+// - place it with the value if it matches
+// - e.g. '' => 'home' sends / to /home
+//
+// style - single or list of css styles to load on specific routes
+//
+// js - single or list of js script to load on specific routes
+//
+// autoload - list of directories to autoload all PHP files in them
+//
+define('SITE_CONFIG', array(
/* core config settings */
- 'domain' => 'freya.cat',
- 'allowed_hosts' => ['freya.cat', 'www.freya.cat'],
- 'base_path' => '/',
+ 'domain' => getenv("WEBSITE_HOST"),
+ 'allowed_hosts' => explode(" ", getenv("WEBSITE_ALLOWED_HOSTS")),
+ 'base_path' => getenv("WEBSITE_BASE_PATH"),
'theme_color' => '#181818',
- 'git_url' => 'https://g.freya.cat/freya',
+ 'git_url' => 'https://g.freya.cat',
/* route overides */
'routes' => array(
'' => 'home',
@@ -39,4 +46,8 @@ define('CONFIG', array(
'js' => array(
'blog' => 'js/prism.js',
),
+ /* directories to autoload php code */
+ 'autoload' => array('/third_party', '/lib'),
));
+
+define('ASSET_ROOT', PHP_ROOT . '/assets');
diff --git a/src/web/core/component.php b/src/web/core/component.php
deleted file mode 100644
index 376e24d..0000000
--- a/src/web/core/component.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-/**
- * Gives access to imporant
- * needed utility functions for
- * accessing everything else!
- */
-abstract class Component extends Core {
-
- // keep track of what has been loaded
- private static array $loaded = array();
-
-// ============================= LOADABLE OBJECTS ==
-
- /**
- * Loads a $type of object from a $dir with a given $name
- * @param string $name - the name of the object to load
- * @param string $dir - the directory theese objects are stored in
- * @param string $type - the type of the object
- */
- private function load_type($name, $dir, $type): object|NULL
- {
-
- $path = $dir . '/' . $name . '.php';
-
- // dont reload an ohject
- if (array_key_exists($path, Component::$loaded))
- return Component::$loaded[$path];
-
- // only load a object if it exists
- if (!file_exists($path))
- return NULL;
-
-
- $parts = explode('/', $name);
- $part = end($parts);
- $class = ucfirst($part) . '_' . $type;
- require($path);
-
- $ref = NULL;
- try {
- $ref = new ReflectionClass($class);
- } catch (Exception $_e) {}
-
- if ($ref === NULL)
- return NULL;
-
- $obj = $ref->newInstance();
- Component::$loaded[$path] = $obj;
-
- return $obj;
- }
-
- /**
- * Loads a model
- * @param string $name - the name of the model to load
- */
- protected function load_model($name): Model|NULL
- {
- $dir = WEB_ROOT . '/_model';
- return $this->load_type($name, $dir, 'model');
- }
-
- /**
- * Loads a controller
- * @param string $name - the name of the controller to load
- */
- public function load_controller($name): Controller|NULL
- {
- $dir = WEB_ROOT . '/_controller';
- return $this->load_type($name, $dir, 'controller');
- }
-
-// ========================================= LANG ==
-
- /**
- * Loads a php lang file into the lang array
- */
- private static function load_lang_file(string $file): void
- {
- $lang = $GLOBALS['__lang'];
- require($file);
- $GLOBALS['__lang'] = $lang;
- }
-
- /**
- * Loads each php file lang strings in a directory
- */
- private static function load_lang_dir(string $dir): void
- {
- if ($handle = opendir($dir)) {
- while (false !== ($entry = readdir($handle))) {
- if ($entry === '.' || $entry === '..')
- continue;
- Component::load_lang_file($entry);
- }
- }
- }
-
- /**
- * Loads the given common lang
- */
- protected static function load_lang(string ...$langs): void
- {
- $root = WEB_ROOT . '/lang';
-
- foreach ($langs as $lang) {
- $file = "{$root}/{$lang}.php";
- $dir = "{$root}/{$lang}";
-
- if (file_exists($file))
- Component::load_lang_file($file);
- else if (is_dir($dir))
- Component::load_lang_dir($dir);
-
- }
- }
-
-}
diff --git a/src/web/core/controller.php b/src/web/core/controller.php
deleted file mode 100644
index ca892e2..0000000
--- a/src/web/core/controller.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-abstract class Controller extends Component {
-
- /**
- * Default index for a app, empty
- */
- public function index(): void {}
-
- /**
- * Redirectes to a link
- */
- public function redirect(string $link): void
- {
- header('Location: '. $link, true, 301);
- die();
- }
-
- /**
- * Lodas a view
- */
- protected function view(string $__name, array $data = array()): void
- {
- $__path = WEB_ROOT . '/_views/' . $__name . '.php';
- if (is_file($__path)) {
- extract($data);
- require($__path);
- }
- }
-
- /**
- * Loads a erorr page with a given
- * error code
- */
- protected function error(int $code): void
- {
- $error_controller = $this->load_controller('error');
- $error_controller->code($code);
- die();
- }
-
- /**
- * Returns HTTP POST information if POST request.
- * Returns 405 Method Not Allowed if not.
- *
- * If $key is specified, returns only that key. otherwise
- * returns HTTP 400 Bad Request;
- */
- protected function post_data(?string $key = NULL): array|string
- {
- // only post requests allowed
- if ($_SERVER['REQUEST_METHOD'] != 'POST')
- $this->error(405);
-
- // return entire $_POST array
- if (!$key)
- return $_POST;
-
- if (!isset($_POST[$key]))
- $this->error(400);
-
- return $_POST[$key];
- }
-
-}
diff --git a/src/web/core/core.php b/src/web/core/core.php
deleted file mode 100644
index 4c341c2..0000000
--- a/src/web/core/core.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-/**
- * Core functions needed everywhere
- */
-abstract class Core {
-
- private static ?DatabaseHelper $db = NULL;
-
- /**
- * Loads the database
- */
- public static function db(): DatabaseHelper
- {
- if (!Component::$db)
- Component::$db = new DatabaseHelper();
- return Component::$db;
- }
-
- /**
- * Gets the stamp for a asset path
- * @param string $path
- */
- public static function asset_stamp(string $path): int
- {
- if (ENVIRONMENT == 'devlopment')
- return time();
- if (isset(FILE_TIMES[$path]))
- return FILE_TIMES[$path];
- return 0;
- }
-
- /**
- * Gets a full path url from a relative path
- * @param string $path
- * @param bool $timestamp
- */
- public static function get_url(string $path, bool $timestamp = FALSE): string
- {
- $scheme = 'http';
- if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']))
- $scheme = $_SERVER['HTTP_X_FORWARDED_PROTO'];
-
- $host = $_SERVER['HTTP_HOST'];
-
- if (ENVIRONMENT == 'production') {
- $default = CONFIG['domain'];
- $allowed = CONFIG['allowed_hosts'];
- if (!is_array($allowed))
- $allowed = [$allowed];
- if (!in_array($host, $allowed))
- $host = $default;
- }
-
- $base = CONFIG['base_path'];
- $url = "{$scheme}://{$host}{$base}{$path}";
- if ($timestamp) {
- $time = Core::asset_stamp($path);
- $url .= "?timestamp={$time}";
- }
- return $url;
- }
-
- /**
- * Loads a js html link
- * @param string $path - the path to the js file
- */
- public static function link_js(string $path): string
- {
- $stamp = Core::asset_stamp("public/$path");
- $href = Core::get_url("public/{$path}?timestamp={$stamp}");
- return '<script src="'. $href .'"></script>';
- }
-
- /**
- * Loads a css html link
- * @param string $path - the path to the css file
- */
- public static function link_css(string $path): string
- {
- $stamp = Core::asset_stamp("public/$path");
- $href = Core::get_url("public/{$path}?timestamp={$stamp}");
- return '<link rel="stylesheet" href="'. $href .'">';
- }
-
- /**
- * Loads a css html link
- * @param string $path - the path to the css file
- */
- public static function embed_css(string $path): string
- {
- $file = PUBLIC_ROOT . '/' . $path;
- if (file_exists($file)) {
- $text = file_get_contents($file);
- return "<style>{$text}</style>";
- } else {
- return "";
- }
- }
-
- /**
- * Formats a ISO date
- * @param $iso_date the ISO date
- */
- public static function format_date(string $iso_date): string
- {
- return date("Y-m-d D H:i", strtotime($iso_date)) . ' EST';
- }
-}
diff --git a/src/web/core/model.php b/src/web/core/model.php
deleted file mode 100644
index 6a42a98..0000000
--- a/src/web/core/model.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-abstract class Model extends Component {
-
- /**
- * @return array<string,mixed>
- */
- public static function get_base_data(?string $app = NULL): array
- {
- $data = array();
- $data['title'] = lang('first_name');
- $data['desc'] = lang('default_short_desc');
- $data['css'] = array();
- $data['js'] = array();
-
- $style = CONFIG['style'];
- $js = CONFIG['js'];
-
- if (!$app)
- $app = CONTEXT['app'];
-
- if (isset($style[$app])) {
- $css = $style[$app];
- if (!is_array($css))
- $css = array($css);
- $data['css'] = $css;
- }
-
- if (isset($js[$app])) {
- $js = $js[$app];
- if (!is_array($js))
- $js = array($js);
- $data['js'] = $js;
- }
-
- return $data;
- }
-
-}
diff --git a/src/web/core/router.php b/src/web/core/router.php
deleted file mode 100644
index 6a543aa..0000000
--- a/src/web/core/router.php
+++ /dev/null
@@ -1,208 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-class Router extends Component {
-
- private bool $db_ready;
- private bool $recursed;
- private array $req;
-
- /**
- * Creates a router
- * @param Loader $load - the main laoder object
- */
- function __construct()
- {
- $this->db_ready = file_exists('/status/ready');
- $this->recursed = FALSE;
- $this->req = $this->get_req();
- }
-
- /**
- * @param string $path - the current request path
- * Gets the current route
- * @return array<string,mixed>
- */
- private function get_req_route($path): array
- {
- // trim the path
- $path = trim($path);
- // remove first '/'
- $path = substr($path, 1);
-
- // get modified route
- $routes = CONFIG['routes'];
- foreach ($routes as $key => $value) {
- $key = "/^{$key}$/";
- if (!preg_match($key, $path, $matches))
- continue;
-
- $path = $value;
-
- for ($i = 1; $i < count($matches); $i++) {
- $path = str_replace(
- "\\{$i}",
- $matches[$i],
- $path);
- }
-
- break;
- }
-
- // get path parts
- $parts = explode('/', $path);
- // get the length
- $len = count($parts);
- // get route info
- $route = array();
- $route['app'] = $len > 0 ? $parts[0] : 'index';
- $route['slug'] = $len > 1 ? $parts[1] : 'index';
- $route['args'] = array_slice($parts, 2);
-
- return $route;
- }
-
- /**
- * Gets the users ip
- */
- private function get_ip(): ?string
- {
- $headers = array (
- 'HTTP_CLIENT_IP',
- 'HTTP_X_FORWARDED_FOR',
- 'HTTP_X_FORWARDED',
- 'HTTP_FORWARDED_FOR',
- 'HTTP_FORWARDED',
- 'HTTP_X_REAL_IP',
- 'REMOTE_ADDR'
- );
- foreach ($headers as $header) {
- if (isset($_SERVER[$header]))
- return $_SERVER[$header];
- }
- return NULL;
- }
-
- /**
- * Gets the curret request info
- * @return array<string,mixed>
- */
- private function get_req(): array
- {
- $method = $_SERVER['REQUEST_METHOD'];
- $uri_str = $_SERVER['REQUEST_URI'];
- $uri = parse_url($uri_str);
-
- if (!$uri) {
- $uri = array('path' => '/error');
- }
-
- $path = '';
- if (array_key_exists('path', $uri)) {
- $path = $uri['path'];
- }
-
- return array_merge(
- array(
- 'uri' => $uri,
- 'uri_str' => $uri_str,
- 'method' => $method,
- 'ip' => $this->get_ip()
- ),
- $this->get_req_route($path),
- );
- }
-
- /**
- * Handles a router error code
- * @param int $code - the http error code
- */
- private function handle_error(int $code): void
- {
- if ($this->recursed)
- die($code . ' (recursed)');
-
- $this->recursed = TRUE;
- $this->req['app'] = 'error';
- $this->req['slug'] = 'code';
- $this->req['args'] = array($code);
- $this->handle_req();
- }
-
- /**
- * @param array<int,mixed> $req
- */
- private function load_htc(array $req): void
- {
- $parts = explode('/', $req['uri_str']);
- $file = end($parts);
- $path = PUBLIC_ROOT . '/polyfills/' . $file;
-
- if (file_exists($path)) {
- header('Content-type: text/x-component');
- include($path);
- } else {
- $this->handle_error(400);
- }
- }
-
- /**
- * @param array $req
- * @param array<int,mixed> $req
- */
- public function handle_req(): void
- {
- if ($this->recursed === FALSE) {
- // if we are in a recursing error handler
- // we dont want to trigger a db 503 forever
- // since its already active
- if ($this->db_ready === FALSE) {
- $this->handle_error(503);
- return;
- }
- }
-
- // server error if we cannot parse url
- if (!$this->req) {
- $this->handle_error(500);
- return;
- }
-
- // load htc if someone is requesting it (hi IE6 :3)
- if (str_ends_with($this->req['uri_str'], '.htc')) {
- $this->load_htc($this->req);
- return;
- }
-
- // load the controller
- $controller = $this->load_controller($this->req['app']);
- if ($controller === NULL) {
- $this->handle_error(404);
- return;
- }
-
- $ref = NULL;
- try {
- $cls = new ReflectionClass($controller);
- $mds = $cls->getMethods(ReflectionMethod::IS_PUBLIC);
- foreach ($mds as $md) {
- if ($md->name !== $this->req['slug'])
- continue;
- if (count($md->getParameters()) !=
- count($this->req['args']))
- continue;
- $ref = $md;
- break;
- }
- } catch (Exception $_e) {}
-
- if ($ref === NULL) {
- $this->handle_error(404);
- return;
- }
-
- define('CONTEXT', $this->req);
- Component::load_lang('common', $this->req['app']);
- $ref->invokeArgs($controller, $this->req['args']);
- }
-
-}
diff --git a/src/web/helpers/database.php b/src/web/helpers/database.php
deleted file mode 100644
index 82c711d..0000000
--- a/src/web/helpers/database.php
+++ /dev/null
@@ -1,323 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-function __nullify(mixed $val): mixed
-{
- if (!$val) {
- return NULL;
- } else {
- return $val;
- }
-}
-
-class DatabaseQuery {
-
- private \PDO $conn;
- private string $query;
-
- private bool $where;
- private bool $set;
-
- private array $param;
-
- function __construct(\PDO $conn)
- {
- $this->conn = $conn;
- $this->query = '';
-
- $this->set = FALSE;
- $this->where = FALSE;
- $this->param = array();
- }
-
- ///
- /// ARBITRARY QUERY
- ///
-
- public function query(string $query): DatabaseQuery
- {
- $this->query .= $query;
- return $this;
- }
-
- ///
- /// SELECT
- ///
-
- public function select(string $select): DatabaseQuery
- {
- $this->query .= "SELECT $select\n";
- return $this;
- }
-
- public function from(string $from): DatabaseQuery
- {
- $this->query .= "FROM $from\n";
- return $this;
- }
-
- ///
- /// INSERT
- ///
-
- public function insert_into(string $insert, string ...$columns): DatabaseQuery
- {
- $this->query .= "INSERT INTO $insert\n (";
- foreach ($columns as $idx => $column) {
- if ($idx !== 0) {
- $this->query .= ",";
- }
- $this->query .= $column;
- }
- $this->query .= ")\n";
- return $this;
- }
-
- public function values(mixed ...$values): DatabaseQuery
- {
- $this->query .= "VALUES (";
- foreach ($values as $idx => $value) {
- if ($idx !== 0) {
- $this->query .= ",";
- }
- $this->query .= "?";
- array_push($this->param, $value);
- }
- $this->query .= ")\n";
- return $this;
- }
-
- ///
- /// WHERE
- ///
-
- public function where(string $cond): DatabaseQuery
- {
- if (!$this->where) {
- $this->where = TRUE;
- $this->query .= "WHERE ";
- } else {
- $this->query .= "AND ";
- }
- $this->query .= "$cond ";
- return $this;
- }
-
- /**
- * @param array<mixed> $array
- */
- public function where_in(string $column, array $array): DatabaseQuery
- {
- if (!$this->where) {
- $this->where = TRUE;
- $this->query .= "WHERE ";
- } else {
- $this->query .= "AND ";
- }
- if (empty($array)) {
- $this->query .= "FALSE\n";
- return $this;
- }
- $in = $this->in($array);
- $this->query .= "$column $in\n";
- return $this;
- }
-
- /**
- * @param array<mixed> $array
- */
- private function in(array $array): DatabaseQuery
- {
- $in = 'IN (';
- foreach ($array as $idx => $item) {
- if ($idx != 0) {
- $in .= ",";
- }
- $in .= "?";
- array_push($this->param, $item);
- }
- $in .= ")";
- return $in;
- }
-
- ///
- /// OPERATORS
- ///
-
- public function like(mixed $item): DatabaseQuery
- {
- $this->query .= "LIKE ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function eq(mixed $item): DatabaseQuery
- {
- $this->query .= "= ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function ne(mixed $item): DatabaseQuery
- {
- $this->query .= "<> ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function lt(mixed $item): DatabaseQuery
- {
- $this->query .= "< ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- public function le(mixed $item): DatabaseQuery
- {
- $this->query .= "<= ?\n";
- array_push($this->param, $item);
- return $this;
- }
-
- ///
- /// JOINS
- ///
-
- public function join(string $table, string $on, string $type = 'LEFT'): DatabaseQuery
- {
- $this->query .= "$type JOIN $table ON $on\n";
- return $this;
- }
-
- ///
- /// LIMIT, OFFSET, ORDER
- ///
-
- public function limit(int $limit): DatabaseQuery
- {
- $this->query .= "LIMIT ?\n";
- array_push($this->param, $limit);
- return $this;
- }
-
- public function offset(int $offset): DatabaseQuery
- {
- $this->query .= "OFFSET ?\n";
- array_push($this->param, $offset);
- return $this;
- }
-
- public function order_by(string $column, string $order = 'ASC'): DatabaseQuery
- {
- $this->query .= "ORDER BY " . $column . ' ' . $order . ' ';
- return $this;
- }
-
- ///
- /// COLLECT
- ///
-
- public function rows(mixed ...$params): ?array
- {
- $args = $this->param;
- foreach ($params as $param) {
- array_push($args, $param);
- }
- $stmt = $this->conn->prepare($this->query);
- try {
- $stmt->execute($args);
- } catch (Exception $ex) {
- echo $ex;
- echo '<br> >> caused by <<<br>';
- echo str_replace("\n", "<br>", $this->query);
- }
- return __nullify($stmt->fetchAll(PDO::FETCH_ASSOC));
- }
-
- public function row(mixed ...$params): ?array
- {
- $args = $this->param;
- foreach ($params as $param) {
- array_push($args, $param);
- }
- $stmt = $this->conn->prepare($this->query);
- $stmt->execute($args);
- return __nullify($stmt->fetch(PDO::FETCH_ASSOC));
- }
-
- public function execute(mixed ...$params): bool
- {
- $args = $this->param;
- foreach ($params as $param) {
- array_push($args, $param);
- }
- $stmt = $this->conn->prepare($this->query);
- try {
- $stmt->execute($args);
- return TRUE;
- } catch (Exception $_e) {
- echo $_e;
- echo '<br> >> caused by <<<br>';
- echo str_replace("\n", "<br>", $this->query);
- return FALSE;
- }
- }
-}
-
-/**
- * DatabaseHelper
- * allows queries on the
- * postgres database
- */
-class DatabaseHelper {
-
- private ?\PDO $conn;
-
- function __construct()
- {
- $this->conn = NULL;
- }
-
- private function connect(): \PDO
- {
- if ($this->conn === NULL) {
- $user = getenv("POSTGRES_USER");
- $pass = getenv("POSTGRES_PASSWORD");
- $db = getenv("POSTGRES_DB");
- $host = 'db';
- $port = '5432';
-
- $conn_str = sprintf("pgsql:host=%s;port=%d;dbname=%s;user=%s;password=%s",
- $host,
- $port,
- $db,
- $user,
- $pass
- );
- $this->conn = new \PDO($conn_str);
- $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
- }
- return $this->conn;
- }
-
- public function select(string $select): DatabaseQuery
- {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->select($select);
- }
-
- public function insert_into(string $insert, string ...$columns): DatabaseQuery
- {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->insert_into($insert, ...$columns);
- }
-
- public function query(string $query_str): DatabaseQuery
- {
- $conn = $this->connect();
- $query = new DatabaseQuery($conn);
- return $query->query($query_str);
- }
-}
-
diff --git a/src/web/helpers/lang.php b/src/web/helpers/lang.php
deleted file mode 100644
index 72167fc..0000000
--- a/src/web/helpers/lang.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-$__lang = array();
-
-/**
- * @param ?array<string,mixed> $sub
- */
-function lang(
- string $key,
- ?string $default = NULL,
- ?array $sub = NULL) {
- $lang = $GLOBALS['__lang'];
- if(array_key_exists($key, $lang)) {
- if ($sub) {
- return sprintf($lang[$key], ...$sub);
- } else {
- return $lang[$key];
- }
- } else if ($default !== NULL) {
- return $default;
- } else {
- trigger_error('Undefined lang string: ' . $key, E_USER_WARNING);
- return $key;
- }
-}
-
-/**
- * @param array<string,string> $attrs
- * @param ?array<string,mixed> $sub
- */
-function ilang(
- string $key,
- ?string $class = NULL,
- ?string $id = NULL,
- ?string $href = NULL,
- ?string $click = NULL,
- array $attrs = array(),
- ?array $sub = NULL,
- bool $button = FALSE,
- string $container = 'span'
-) {
- $text = ucfirst(lang($key . "_text", FALSE, sub: $sub));
- $tip = lang($key . "_tip", FALSE, sub: $sub);
- $icon = lang($key . "_icon", FALSE);
- $content = lang($key . "_content", FALSE);
-
- if ($click || $button) {
- echo '<button ';
- } else {
- echo '<a ';
- }
- if ($tip) {
- echo 'title="' . $tip . '" ';
- echo 'aria-label="' . $tip . '" ';
- }
- if ($class) {
- echo 'class="' . $class . '" ';
- }
- if ($id) {
- echo 'id="' . $id . '" ';
- }
- if ($click) {
- echo 'onclick="' . $click . '" ';
- }
- if ($href) {
- echo 'href="' . $href . '" ';
- }
- foreach ($attrs as $key => $attr) {
- echo $key . '="' . $attr . '" ';
- }
- echo '> ';
- if ($icon) {
- echo '<i class="' . $icon . '">';
- if ($content) {
- echo $content;
- }
- echo '</i>';
- }
- if ($text) {
- echo '<' . $container;
- if ($icon) {
- echo ' class="ml-sm"';
- }
- echo '>' . $text . '</' . $container . '>';
- }
- if ($click || $button) {
- echo '</button>';
- } else {
- echo '</a>';
- }
-}
diff --git a/src/web/helpers/sanitize.php b/src/web/helpers/sanitize.php
deleted file mode 100644
index 495c249..0000000
--- a/src/web/helpers/sanitize.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-function esc(string $data): string {
- $data = str_replace('&', '&amp;', $data);
- $data = str_replace('<', '&lt;', $data);
- $data = str_replace('>', '&gt;', $data);
- return $data;
-}
diff --git a/src/web/index.php b/src/web/index.php
deleted file mode 100644
index 9958b1b..0000000
--- a/src/web/index.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php /* Copyright (c) 2024 Freya Murphy */
-
-// ========================= ENVIRONMENT ==
-
-ini_set('html_errors', '1');
-ini_set('browscap', 'browscap.ini');
-date_default_timezone_set('America/New_York');
-
-// FOLDER_ROOT
-//
-// define folder directiroy paths based on this file
-define('PHP_ROOT', realpath(dirname(__FILE__) . '/..'));
-define('WEB_ROOT', PHP_ROOT . '/web');
-define('ASSET_ROOT', PHP_ROOT . '/assets');
-define('PUBLIC_ROOT', PHP_ROOT . '/public');
-
-// ========================== BOOTSTRAP ==
-
-// load the config
-require(WEB_ROOT . '/config.php');
-
-// load all third party
-require(WEB_ROOT . '/third_party/parsedown.php');
-require(WEB_ROOT . '/third_party/parsedown_extra.php');
-
-// load all the helpers
-require(WEB_ROOT . '/helpers/ie.php');
-require(WEB_ROOT . '/helpers/lang.php');
-require(WEB_ROOT . '/helpers/aria.php');
-require(WEB_ROOT . '/helpers/image.php');
-require(WEB_ROOT . '/helpers/markdown.php');
-require(WEB_ROOT . '/helpers/database.php');
-require(WEB_ROOT . '/helpers/sanitize.php');
-
-// load all core files
-require(WEB_ROOT . '/core/core.php');
-require(WEB_ROOT . '/core/component.php');
-require(WEB_ROOT . '/core/controller.php');
-require(WEB_ROOT . '/core/model.php');
-require(WEB_ROOT . '/core/router.php');
-
-
-// load file stamps
-require(WEB_ROOT . '/stamp.php');
-
-// ============================== START ==
-
-(new Router())->handle_req();
diff --git a/src/web/lang/error.php b/src/web/lang/error.php
index 549700d..449d18f 100644
--- a/src/web/lang/error.php
+++ b/src/web/lang/error.php
@@ -1,64 +1,6 @@
<?php /* Copyright (c) 2024 Freya Murphy */
$lang['error_0'] = 'Why the actual fuck is there an error zero??';
-$lang['error_100'] = "Continue";
-$lang['error_101'] = "Switching Protocols";
-$lang['error_200'] = "OK";
-$lang['error_201'] = "Created";
-$lang['error_202'] = "Accepted";
-$lang['error_203'] = "Non-Authoritative Information";
-$lang['error_204'] = "No Content";
-$lang['error_205'] = "Reset Content";
-$lang['error_206'] = "Partial Content";
-$lang['error_300'] = "Multiple Choices";
-$lang['error_301'] = "Moved Permanently";
-$lang['error_302'] = "Found";
-$lang['error_303'] = "See Other";
-$lang['error_304'] = "Not Modified";
-$lang['error_305'] = "Use Proxy";
-$lang['error_306'] = "unused";
-$lang['error_307'] = "Temporary Redirect";
-$lang['error_308'] = "Permanent Redirect";
-$lang['error_400'] = "Bad Request";
-$lang['error_401'] = "Unauthorized";
-$lang['error_402'] = "Payment Required";
-$lang['error_403'] = "Forbidden";
-$lang['error_404'] = "Not Found";
-$lang['error_405'] = "Method Not Allowed";
-$lang['error_406'] = "Not Acceptable";
-$lang['error_407'] = "Proxy Authentication Required";
-$lang['error_408'] = "Request Timeout";
-$lang['error_409'] = "Conflict";
-$lang['error_410'] = "Gone";
-$lang['error_411'] = "Length Required";
-$lang['error_412'] = "Precondition Failed";
-$lang['error_413'] = "Content Too Large";
-$lang['error_414'] = "URI Too Long";
-$lang['error_415'] = "Unsupported Media Type";
-$lang['error_416'] = "Range Not Satisfiable";
-$lang['error_417'] = "Expectation Failed";
-$lang['error_418'] = "I'm a teapot";
-$lang['error_421'] = "Misdirected Request";
-$lang['error_422'] = "Unprocessable Content";
-$lang['error_423'] = "Locked";
-$lang['error_424'] = "Failed Dependency";
-$lang['error_425'] = "Too Early";
-$lang['error_426'] = "Upgrade Required";
-$lang['error_428'] = "Precondition Required";
-$lang['error_429'] = "Too Many Requests";
-$lang['error_431'] = "Request Header Fields Too Large";
-$lang['error_451'] = "Unavailable For Legal Reasons";
-$lang['error_500'] = "Whoops! Server error :(";
-$lang['error_501'] = "Not Implemented";
-$lang['error_502'] = "Bad Gateway";
-$lang['error_503'] = "Service Unavailable";
-$lang['error_504'] = "Gateway Timeout";
-$lang['error_505'] = "HTTP Version Not Supported";
-$lang['error_506'] = "Variant Also Negotiates";
-$lang['error_507'] = "Insufficient Storage";
-$lang['error_508'] = "Loop Detected";
-$lang['error_510'] = "Not Extended";
-$lang['error_511'] = "Network Authentication Required";
$lang['error'] = [
'How the fuck did you get here.',
'A known error has occoured',
diff --git a/src/web/helpers/aria.php b/src/web/lib/aria.php
index 0e06b97..0e06b97 100644
--- a/src/web/helpers/aria.php
+++ b/src/web/lib/aria.php
diff --git a/src/web/lib/hooks.php b/src/web/lib/hooks.php
new file mode 100644
index 0000000..70853e1
--- /dev/null
+++ b/src/web/lib/hooks.php
@@ -0,0 +1,10 @@
+<?php /* Copyright (c) 2024 Freya Murphy */
+
+function CRIMSON_pre_route_hook(Router $router): void {
+}
+
+function CRIMSON_error_hook(?array $req, int $code): never {
+ $error_controller = ROUTER->load_controller('error');
+ $error_controller->code($code);
+ CRIMSON_DIE();
+}
diff --git a/src/web/helpers/ie.php b/src/web/lib/ie.php
index ead6c1a..ead6c1a 100644
--- a/src/web/helpers/ie.php
+++ b/src/web/lib/ie.php
diff --git a/src/web/helpers/image.php b/src/web/lib/image.php
index d4683fe..7b6ec0e 100644
--- a/src/web/helpers/image.php
+++ b/src/web/lib/image.php
@@ -1,5 +1,7 @@
<?php /* Copyright (c) 2024 Freya Murphy */
+
+
function __get_mime($type)
{
switch ($type) {
@@ -30,7 +32,7 @@ function __make_source(
} else {
$media = '';
}
- $path = Core::get_url('public/' . $name . '.' . $format, TRUE);
+ $path = Base::get_url('public/' . $name . '.' . $format, TRUE);
$mime = __get_mime($format);
return sprintf('<source type="%s" srcset="%s" %s>',
$mime, $path, $media);
@@ -68,7 +70,7 @@ function image(
}
$format = end($formats);
- $path = Core::get_url('public/' . $name . '.' . $format, TRUE);
+ $path = Base::get_url('public/' . $name . '.' . $format, TRUE);
$out .= "<img src=\"$path\"";
if ($alt) {
$alt = lang($alt);
diff --git a/src/web/helpers/markdown.php b/src/web/lib/markdown.php
index 5279a1f..5279a1f 100644
--- a/src/web/helpers/markdown.php
+++ b/src/web/lib/markdown.php