feat: make the website load for different subdomains

This commit is contained in:
David Bailey 2024-01-11 10:37:19 +01:00
parent f00e97d294
commit d39595d577
4 changed files with 80 additions and 54 deletions

View file

@ -6,6 +6,7 @@ USE dragon_fire;
CREATE TABLE posts ( CREATE TABLE posts (
post_id INTEGER AUTO_INCREMENT, post_id INTEGER AUTO_INCREMENT,
host VARCHAR(64) NOT NULL,
post_path VARCHAR(255) NOT NULL, post_path VARCHAR(255) NOT NULL,
post_path_depth INTEGER NOT NULL DEFAULT 0, post_path_depth INTEGER NOT NULL DEFAULT 0,
@ -20,9 +21,9 @@ CREATE TABLE posts (
post_content MEDIUMTEXT, post_content MEDIUMTEXT,
PRIMARY KEY(post_id), PRIMARY KEY(post_id),
CONSTRAINT unique_post_path UNIQUE (post_path), CONSTRAINT unique_post UNIQUE (host, post_path),
INDEX(post_path), INDEX(host, post_path),
INDEX(post_path_depth, post_path), INDEX(post_path_depth, post_path),
INDEX(post_create_time), INDEX(post_create_time),
INDEX(post_update_time) INDEX(post_update_time)
@ -30,6 +31,7 @@ CREATE TABLE posts (
CREATE TABLE path_access_counts ( CREATE TABLE path_access_counts (
access_time DATETIME NOT NULL, access_time DATETIME NOT NULL,
host VARCHAR(64) NOT NULL,
post_path VARCHAR(255), post_path VARCHAR(255),
agent VARCHAR(255), agent VARCHAR(255),
referrer VARCHAR(255), referrer VARCHAR(255),
@ -37,10 +39,11 @@ CREATE TABLE path_access_counts (
path_access_count INTEGER DEFAULT 0, path_access_count INTEGER DEFAULT 0,
path_processing_time DOUBLE PRECISION DEFAULT 0, path_processing_time DOUBLE PRECISION DEFAULT 0,
PRIMARY KEY(access_time, post_path, agent, referrer) PRIMARY KEY(access_time, host, post_path, agent, referrer)
); );
CREATE TABLE feed_cache ( CREATE TABLE feed_cache (
host VARCHAR(64) NOT NULL,
search_path VARCHAR(255), search_path VARCHAR(255),
export_type VARCHAR(255), export_type VARCHAR(255),
@ -48,7 +51,7 @@ CREATE TABLE feed_cache (
feed_content MEDIUMTEXT, feed_content MEDIUMTEXT,
PRIMARY KEY(search_path, export_type) PRIMARY KEY(host, search_path, export_type)
); );
INSERT INTO posts (post_path, post_path_depth, post_metadata, post_content) INSERT INTO posts (post_path, post_path_depth, post_metadata, post_content)

View file

@ -3,8 +3,10 @@
class MySQLAdapter { class MySQLAdapter {
public $raw; public $raw;
function __construct() { function __construct($SITE_CONFIG) {
$db_params = json_decode(file_get_contents('secrets/db.json'), true); $this->SITE_CONFIG = $SITE_CONFIG;
$db_params = $SITE_CONFIG['db'];
try { try {
if(false !== getenv('MYSQL_HOST')) { if(false !== getenv('MYSQL_HOST')) {
@ -14,18 +16,16 @@ class MySQLAdapter {
getenv('MYSQL_PORT')); getenv('MYSQL_PORT'));
} }
else { else {
$this->raw = mysqli_connect($db_params['MYSQL_HOST'], $this->raw = mysqli_connect($db_params['host'],
$db_params['MYSQL_USER'], $db_params['MYSQL_PASSWORD'], $db_params['user'], $db_params['password'],
$db_params['MYSQL_DATABASE'], $db_params['database'],
$db_params['MYSQL_PORT']); $db_params['port']);
} }
} catch (\Throwable $th) { } catch (\Throwable $th) {
echo 'Connection failed<br>'; echo 'Connection failed<br>';
echo 'Error number: ' . mysqli_connect_errno() . '<br>'; echo 'Error number: ' . mysqli_connect_errno() . '<br>';
echo 'Error message: ' . mysqli_connect_error() . '<br>'; echo 'Error message: ' . mysqli_connect_error() . '<br>';
die(); die();
//throw $th;
} }
} }
@ -79,12 +79,13 @@ class MySQLAdapter {
$qry = " $qry = "
INSERT INTO posts INSERT INTO posts
(post_path, post_path_depth, post_metadata, post_content) (host, post_path, post_path_depth, post_metadata, post_content)
VALUES VALUES
( ?, ?, ?, ?) AS new ( ?, ?, ?, ?, ?) AS new
ON DUPLICATE KEY UPDATE post_path=new.post_path;"; ON DUPLICATE KEY UPDATE post_path=new.post_path;";
$this->_exec($qry, "siss", $this->_exec($qry, "ssiss",
$this->SITE_CONFIG['HTTP_HOST'],
$post_path, $post_path,
$path_depth, $path_depth,
json_encode($post_metadata), json_encode($post_metadata),
@ -110,27 +111,28 @@ class MySQLAdapter {
$qry = "INSERT INTO path_access_counts $qry = "INSERT INTO path_access_counts
(access_time, (access_time,
post_path, agent, referrer, host, post_path, agent, referrer,
path_access_count, path_access_count,
path_processing_time) path_processing_time)
VALUES ( from_unixtime(floor(unix_timestamp(CURRENT_TIMESTAMP) / 300)*300), VALUES ( from_unixtime(floor(unix_timestamp(CURRENT_TIMESTAMP) / 300)*300),
?, ?, ?, 1, ? ?, ?, ?, ?, 1, ?
) AS new ) AS new
ON DUPLICATE KEY ON DUPLICATE KEY
UPDATE path_access_count=path_access_counts.path_access_count+1, UPDATE path_access_count=path_access_counts.path_access_count+1,
path_processing_time=path_access_counts.path_processing_time+new.path_processing_time; path_processing_time=path_access_counts.path_processing_time+new.path_processing_time;
"; ";
$this->_exec($qry, "sssd", $post_path, $agent, $referrer, $time); $this->_exec($qry, "ssssd", $this->SITE_CONFIG['HTTP_HOST'], $post_path, $agent, $referrer, $time);
if(preg_match('/^user/', $agent)) { if(preg_match('/^user/', $agent)) {
$this->_exec("UPDATE posts SET post_access_count=post_access_count+1 WHERE post_path=?", "s", $post_path); $this->_exec("UPDATE posts SET post_access_count=post_access_count+1 WHERE post_path=? AND host=?", "ss",
$post_path, $this->SITE_CONFIG['HTTP_HOST']);
} }
} }
function get_post_access_counters() { function get_post_access_counters() {
$qry = " $qry = "
SELECT post_path, agent, path_access_count, path_processing_time SELECT host, post_path, agent, path_access_count, path_processing_time
FROM path_access_counts FROM path_access_counts
WHERE path_last_access_time > ( CURRENT_TIMESTAMP - INTERVAL 10 MINUTE ); WHERE path_last_access_time > ( CURRENT_TIMESTAMP - INTERVAL 10 MINUTE );
"; ";
@ -157,7 +159,7 @@ class MySQLAdapter {
function get_post_access_counters_line() { function get_post_access_counters_line() {
$qry = " $qry = "
SELECT access_time, post_path, agent, referrer, path_access_count, path_processing_time SELECT host, access_time, post_path, agent, referrer, path_access_count, path_processing_time
FROM path_access_counts FROM path_access_counts
WHERE access_time < ( CURRENT_TIMESTAMP - INTERVAL 6 MINUTE ) WHERE access_time < ( CURRENT_TIMESTAMP - INTERVAL 6 MINUTE )
ORDER BY access_time DESC; ORDER BY access_time DESC;
@ -169,7 +171,7 @@ class MySQLAdapter {
try { try {
$data = $this->_exec($qry, "")->fetch_all(MYSQLI_ASSOC); $data = $this->_exec($qry, "")->fetch_all(MYSQLI_ASSOC);
$data_prefix="access_metrics,host=" . $_SERVER['SERVER_NAME']; $data_prefix="access_metrics";
$out_data = ""; $out_data = "";
@ -180,7 +182,8 @@ class MySQLAdapter {
if($path == '') { if($path == '') {
$path = '/'; $path = '/';
} }
$out_data .= $data_prefix . ",agent=".$post_data['agent'].",path=".$path.",referrer=".$post_data['referrer']; $out_data .= $data_prefix . ",host=" . $post_data['host'] . ",agent=".$post_data['agent'];
$out_data .= ",path=".$path.",referrer=".$post_data['referrer'];
$out_data .= " access_sum=" . $post_data['path_access_count'] . ",time_sum=" . $post_data['path_processing_time']; $out_data .= " access_sum=" . $post_data['path_access_count'] . ",time_sum=" . $post_data['path_processing_time'];
$out_data .= " " . strtotime($post_data['access_time']) . "000000000\n"; $out_data .= " " . strtotime($post_data['access_time']) . "000000000\n";
@ -205,8 +208,8 @@ class MySQLAdapter {
$this->_exec(" $this->_exec("
UPDATE posts UPDATE posts
SET post_settings_cache=NULL SET post_settings_cache=NULL
WHERE post_path LIKE ?; WHERE host = ? AND post_path LIKE ?;
", "s", $post_path . "%"); ", "ss", $this->SITE_CONFIG['HTTP_HOST'], $post_path . "%");
} }
function update_or_create_post($post_path, $post_metadata, $post_content) { function update_or_create_post($post_path, $post_metadata, $post_content) {
@ -219,15 +222,16 @@ class MySQLAdapter {
$qry = " $qry = "
INSERT INTO posts INSERT INTO posts
(post_path, post_path_depth, post_metadata, post_content) (host, post_path, post_path_depth, post_metadata, post_content)
VALUES VALUES
( ?, ?, ?, ?) AS new ( ?, ?, ?, ?, ?) AS new
ON DUPLICATE KEY ON DUPLICATE KEY
UPDATE post_metadata=new.post_metadata, UPDATE post_metadata=new.post_metadata,
post_content=new.post_content, post_content=new.post_content,
post_update_time=CURRENT_TIMESTAMP;"; post_update_time=CURRENT_TIMESTAMP;";
$this->_exec($qry, "siss", $this->_exec($qry, "ssiss",
$this->SITE_CONFIG['HTTP_HOST'],
$post_path, $post_path,
$path_depth, $path_depth,
json_encode($post_metadata), json_encode($post_metadata),
@ -240,8 +244,8 @@ class MySQLAdapter {
$post_settings = $this->_exec(" $post_settings = $this->_exec("
SELECT post_path, post_settings_cache SELECT post_path, post_settings_cache
FROM posts FROM posts
WHERE post_path = ? WHERE post_path = ? AND host = ?
", "s", $post_path)->fetch_assoc(); ", "ss", $post_path, $this->SITE_CONFIG['HTTP_HOST'])->fetch_assoc();
if(!isset($post_settings)) { if(!isset($post_settings)) {
return []; return [];
@ -259,8 +263,8 @@ class MySQLAdapter {
$post_metadata = $this->_exec(" $post_metadata = $this->_exec("
SELECT post_path, post_metadata SELECT post_path, post_metadata
FROM posts FROM posts
WHERE post_path = ? WHERE post_path = ? AND host = ?
", "s", $post_path)->fetch_assoc(); ", "ss", $post_path, $this->SITE_CONFIG['HTTP_HOST'])->fetch_assoc();
if(isset($post_metadata['post_metadata'])) { if(isset($post_metadata['post_metadata'])) {
$post_metadata = json_decode($post_metadata['post_metadata'], true); $post_metadata = json_decode($post_metadata['post_metadata'], true);
@ -282,12 +286,13 @@ class MySQLAdapter {
$with_subposts = false, $with_settings = true) { $with_subposts = false, $with_settings = true) {
$qry = "SELECT * $qry = "SELECT *
FROM posts WHERE post_path = ? FROM posts
WHERE post_path = ? AND host = ?
"; ";
$post_path = $this->_sanitize_path($post_path); $post_path = $this->_sanitize_path($post_path);
$post_data = $this->_exec($qry, "s", $post_path)->fetch_assoc(); $post_data = $this->_exec($qry, "ss", $post_path, $this->SITE_CONFIG['HTTP_HOST'])->fetch_assoc();
if(!isset($post_data)) { if(!isset($post_data)) {
$post_data = ['found' => false]; $post_data = ['found' => false];
@ -319,12 +324,15 @@ class MySQLAdapter {
$qry = "SELECT post_path, post_metadata, post_update_time $qry = "SELECT post_path, post_metadata, post_update_time
FROM posts FROM posts
WHERE (post_path LIKE CONCAT(?,'/%')) WHERE
host = ?
AND (post_path LIKE CONCAT(?,'/%'))
AND post_path_depth = ? AND post_path_depth = ?
ORDER BY post_create_time DESC ORDER BY post_path ASC
LIMIT 10"; LIMIT 50";
$post_data = $this->_exec($qry, "si", $path, $path_depth+1)->fetch_all(MYSQLI_ASSOC); $post_data = $this->_exec($qry, "ssi", $this->SITE_CONFIG['HTTP_HOST'],
$path, $path_depth+1)->fetch_all(MYSQLI_ASSOC);
$fn = function($data) { $fn = function($data) {
return $this->_normalize_post_data($data); return $this->_normalize_post_data($data);

View file

@ -8,10 +8,10 @@ use Laminas\Feed\Writer\Feed;
class PostHandler extends MySQLAdapter { class PostHandler extends MySQLAdapter {
public $data_directory; public $data_directory;
function __construct() { function __construct($SITE_CONFIG) {
parent::__construct(); parent::__construct($SITE_CONFIG);
$this->data_directory = 'raw'; $this->data_directory = 'raw/' . $this->SITE_CONFIG['HTTP_HOST'];
} }
function _normalize_post_data($post_data) { function _normalize_post_data($post_data) {
@ -130,7 +130,8 @@ class PostHandler extends MySQLAdapter {
function try_get_cached_feed($path, $export_opt) { function try_get_cached_feed($path, $export_opt) {
$post_cache = $this->_exec("SELECT feed_content, feed_created_on $post_cache = $this->_exec("SELECT feed_content, feed_created_on
FROM feed_cache FROM feed_cache
WHERE search_path=? AND export_type=?", "ss", $path, $export_opt)->fetch_assoc(); WHERE host=? AND search_path=? AND export_type=?",
"sss", $this->SITE_CONFIG['HTTP_HOST'], $path, $export_opt)->fetch_assoc();
if(!isset($post_cache)) { if(!isset($post_cache)) {
return null; return null;
@ -145,12 +146,12 @@ class PostHandler extends MySQLAdapter {
$feed = @new Feed; $feed = @new Feed;
$feed->setTitle("DergFeed"); $feed->setTitle("DergFeed");
$feed->setLink("https://lucidragons.de" . $path); $feed->setLink($this->SITE_CONFIG['uri_prefix'] . $path);
$feed->setFeedLink("https://lucidragons.de/feeds/atom" . $path, "atom"); $feed->setFeedLink($this->SITE_CONFIG['uri_prefix'] . "/feeds/atom" . $path, "atom");
$feed->setDateModified(time()); $feed->setDateModified(time());
$feed->setDescription("DergenFeed for all your " . $path . " needs <3"); $feed->setDescription("DergenFeed for all your " . $path . " needs");
$feed_posts = $this->_exec("SELECT $feed_posts = $this->_exec("SELECT
post_path, post_path,
@ -158,9 +159,9 @@ class PostHandler extends MySQLAdapter {
post_content, post_content,
post_metadata post_metadata
FROM posts FROM posts
WHERE (post_path = ?) OR (post_path LIKE ?) WHERE (host = ?) AND ((post_path = ?) OR (post_path LIKE ?))
ORDER BY post_create_time DESC LIMIT 200", ORDER BY post_create_time DESC LIMIT 200",
"ss", $path, $path . '/%'); "sss", $this->SITE_CONFIG['HTTP_HOST'], $path, $path . '/%');
while($row = $feed_posts->fetch_array(MYSQLI_ASSOC)) { while($row = $feed_posts->fetch_array(MYSQLI_ASSOC)) {
$row = $this->_normalize_post_data($row); $row = $this->_normalize_post_data($row);
@ -173,7 +174,7 @@ class PostHandler extends MySQLAdapter {
$entry = $feed->createEntry(); $entry = $feed->createEntry();
$entry->setTitle($row['post_path'] . '> ' . $pmeta['title']); $entry->setTitle($row['post_path'] . '> ' . $pmeta['title']);
$entry->setLink('https://lucidragons.de' . $row['post_path']); $entry->setLink($this->SITE_CONFIG['uri_prefix'] . $row['post_path']);
$entry->setDateModified(strtotime($row['post_update_time'])); $entry->setDateModified(strtotime($row['post_update_time']));
$entry->setDateCreated(strtotime($row['post_create_time'])); $entry->setDateCreated(strtotime($row['post_create_time']));
@ -197,12 +198,13 @@ class PostHandler extends MySQLAdapter {
$feed = $this->construct_feed($path); $feed = $this->construct_feed($path);
$this->_exec("INSERT INTO feed_cache $this->_exec("INSERT INTO feed_cache
(search_path, export_type, feed_content) (host, search_path, export_type, feed_content)
VALUES VALUES
(?, 'atom', ?), (?, ?, 'atom', ?),
(?, 'rss', ?)", (?, ?, 'rss', ?)",
"ssss", $path, $feed->export('atom'), "ssssss",
$path, $feed->export('rss')); $this->SITE_CONFIG['HTTP_HOST'], $path, $feed->export('atom'),
$this->SITE_CONFIG['HTTP_HOST'], $path, $feed->export('rss'));
return $this->try_get_cached_feed($path, $export_opt); return $this->try_get_cached_feed($path, $export_opt);
} }

View file

@ -7,7 +7,20 @@ require_once 'vendor/autoload.php';
require_once 'post_adapter.php'; require_once 'post_adapter.php';
require_once 'fontawesome.php'; require_once 'fontawesome.php';
$adapter = new PostHandler(); use Symfony\Component\Yaml\Yaml;
$SERVER_HOST = $_SERVER['HTTP_HOST'];
if(!preg_match('/^[\w\.]+$/', $SERVER_HOST)) {
die();
}
$SERVER_PREFIX = "https://" . $SERVER_HOST;
$SITE_CONFIG = Yaml::parseFile('secrets/' . $SERVER_HOST . '.config.yml');
$SITE_CONFIG['uri_prefix'] = $SERVER_PREFIX;
$SITE_CONFIG['HTTP_HOST'] = $SERVER_HOST;
$adapter = new PostHandler($SITE_CONFIG);
$loader = new \Twig\Loader\FilesystemLoader(['./templates', './user_content']); $loader = new \Twig\Loader\FilesystemLoader(['./templates', './user_content']);