slight reorganization
This commit is contained in:
parent
e29d9c6577
commit
544d08cb00
@ -1,4 +1,4 @@
|
||||
CREATE table if not exists settings (
|
||||
id integer primary key auto_increment,
|
||||
setting text not null,
|
||||
value text not null)
|
||||
value text null)
|
||||
|
@ -1,4 +1,4 @@
|
||||
CREATE table if not exists settings (
|
||||
id integer primary key autoincrement,
|
||||
setting text not null,
|
||||
value text not null)
|
||||
value text null)
|
||||
|
25
footer.php
25
footer.php
@ -11,10 +11,30 @@
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if (count($varFooterLinks) > 0): ?>
|
||||
<div class="mb-5">
|
||||
<hr />
|
||||
|
||||
<div class="container mb-5">
|
||||
<?php
|
||||
$strSidebarContent = Settings::get("footer_content", "Copyright ©", true);
|
||||
?>
|
||||
|
||||
<?php if (strlen($strSidebarContent) > 0): ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div>
|
||||
<?php
|
||||
$varParsedown = new Parsedown();
|
||||
echo $varParsedown->text($strSidebarContent);
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (count($varFooterLinks) > 0): ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<?php foreach ($varFooterLinks as $varLink): ?>
|
||||
@ -26,6 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
|
17
header.php
17
header.php
@ -13,10 +13,25 @@
|
||||
|
||||
<div class="offcanvas offcanvas-start" id="sidebar">
|
||||
<div class="offcanvas-body">
|
||||
<?php
|
||||
$strSidebarContent = Settings::get("sidebar_content", "#### Sidebar Navigation", true);
|
||||
?>
|
||||
|
||||
<?php if (strlen($strSidebarContent) > 0): ?>
|
||||
<div class="mt-5">
|
||||
<?php
|
||||
$varParsedown = new Parsedown();
|
||||
echo $varParsedown->text($strSidebarContent);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($varSidebarLinks as $varLink): ?>
|
||||
<?php if (!UserAuth::visible($varLink["visibility"])) continue; ?>
|
||||
|
||||
<a class="btn btn-outline-secondary d-block w-100 mb-2" href="<?= $varLink["url"]; ?>"><i class="fa fa-fw fa-<?= $varLink["icon"]; ?> pe-2"></i> <?= $varLink["label"]; ?></a>
|
||||
<div class="mb-2">
|
||||
<a class="btn btn-outline-secondary w-100" href="<?= $varLink["url"]; ?>"><i class="fa fa-fw fa-<?= $varLink["icon"]; ?> pe-2"></i> <?= $varLink["label"]; ?></a>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
158
init.php
158
init.php
@ -35,163 +35,13 @@
|
||||
('Edit Links', '/edit/links', 'link', 'sidebar', 'admin'),
|
||||
('Edit CSS', '/settings/css', 'code', 'sidebar', 'admin'),
|
||||
('Edit JS', '/settings/js', 'code', 'sidebar', 'admin'),
|
||||
('Edit sidebar content', '/settings/sidebar_content', 'comment', 'sidebar', 'admin'),
|
||||
('Edit footer content', '/settings/footer_content', 'comment', 'sidebar', 'admin'),
|
||||
|
||||
('Copyright © 2025', '/', 'building', 'footer', '')"
|
||||
('Go home', '/', 'home', 'footer', ''),
|
||||
('Search', '/search', 'search', 'footer', '')"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Settings
|
||||
{
|
||||
public static function get($strSettingName, $strDefault="", $intSave=0)
|
||||
{
|
||||
global $c;
|
||||
|
||||
$varExisting = $c->query("
|
||||
SELECT *
|
||||
from settings
|
||||
where
|
||||
setting like ?
|
||||
order by
|
||||
id desc",
|
||||
$strSettingName);
|
||||
|
||||
if (count($varExisting) > 0)
|
||||
return $varExisting[0]["value"];
|
||||
|
||||
if ($intSave)
|
||||
Settings::set($strSettingName, $strDefault);
|
||||
|
||||
return $strDefault;
|
||||
}
|
||||
|
||||
public static function set($strSettingName, $strValue)
|
||||
{
|
||||
global $c;
|
||||
|
||||
$varExisting = $c->query("
|
||||
SELECT *
|
||||
from settings
|
||||
where
|
||||
setting like ?
|
||||
order by
|
||||
id desc",
|
||||
$strSettingName);
|
||||
|
||||
if (count($varExisting) !== 1)
|
||||
{
|
||||
$c->query("DELETE from settings where setting like ?", $strSettingName);
|
||||
$c->query("INSERT into settings (setting, value) values (?, ?)", $strSettingName, $strValue);
|
||||
}
|
||||
|
||||
$c->query(
|
||||
"UPDATE settings
|
||||
set
|
||||
value = ?
|
||||
where setting like ?",
|
||||
$strValue,
|
||||
$strSettingName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class UserAuth
|
||||
{
|
||||
public static function getUser()
|
||||
{
|
||||
global $c;
|
||||
try
|
||||
{
|
||||
$strToken = Cookie::get("token");
|
||||
|
||||
if ($strToken !== null)
|
||||
if (strlen($strToken) > 0)
|
||||
{
|
||||
$varSessions = $c->query(
|
||||
"SELECT *
|
||||
from sessions as s
|
||||
join users as u on u.username = s.username
|
||||
where
|
||||
s.token = ?
|
||||
and (
|
||||
s.expires is null
|
||||
or s.expires > current_timestamp
|
||||
)",
|
||||
$strToken);
|
||||
|
||||
if (count($varSessions) == 1)
|
||||
return $varSessions[0];
|
||||
}
|
||||
}
|
||||
catch (Exception $x) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function has($strColumnName)
|
||||
{
|
||||
global $c;
|
||||
$varUser = UserAuth::getUser();
|
||||
|
||||
if ($varUser == null)
|
||||
return false;
|
||||
|
||||
if (array_key_exists($strColumnName, $varUser))
|
||||
if (intval($varUser[$strColumnName]) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function require($strColumnName)
|
||||
{
|
||||
if (!UserAuth::has($strColumnName))
|
||||
{
|
||||
BootstrapRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
|
||||
Respond::redirect("/user/signin");
|
||||
}
|
||||
}
|
||||
|
||||
public static function visible($strVisibility)
|
||||
{
|
||||
global $c;
|
||||
|
||||
if (UserAuth::has("is_admin"))
|
||||
return true;
|
||||
|
||||
$varUser = UserAuth::getUser();
|
||||
$strUsername = $varUser["username"] ?? null;
|
||||
$varRegex = [
|
||||
["/user/i", ($varUser == null)],
|
||||
["/admin/i", (!UserAuth::has("is_admin"))],
|
||||
];
|
||||
|
||||
// Support arrays with username and visibility keys:
|
||||
if (is_array($strVisibility))
|
||||
{
|
||||
if (array_key_exists("username", $strVisibility))
|
||||
if ($strVisibility["username"] == $strUsername)
|
||||
return true;
|
||||
|
||||
if (!array_key_exists("visibility", $strVisibility))
|
||||
return false;
|
||||
|
||||
$strVisibility = $strVisibility["visibility"];
|
||||
}
|
||||
|
||||
if (preg_match("/{$strUsername}/i", $strVisibility)) return true;
|
||||
if (preg_match("/(every|any|all)/i", $strVisibility)) return true;
|
||||
|
||||
$intExit = 0;
|
||||
|
||||
foreach ($varRegex as $re)
|
||||
if (preg_match($re[0], $strVisibility))
|
||||
if ($re[1])
|
||||
$intExit = 1;
|
||||
|
||||
if ($intExit == 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
62
lib/Settings.php
Normal file
62
lib/Settings.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
class Settings
|
||||
{
|
||||
private static $varValues = null;
|
||||
|
||||
public static function get($strSettingName=null, $strDefault="", $intSave=0)
|
||||
{
|
||||
global $c;
|
||||
|
||||
if (Settings::$varValues == null)
|
||||
{
|
||||
$varRows = $c->query("SELECT * from settings order by setting");
|
||||
$varValues = [];
|
||||
|
||||
foreach ($varRows as $r)
|
||||
$varValues[$r["setting"]] = $r["value"];
|
||||
|
||||
Settings::$varValues = $varValues;
|
||||
}
|
||||
|
||||
if ($strSettingName == null)
|
||||
return Settings::$varValues;
|
||||
|
||||
if (array_key_exists($strSettingName, Settings::$varValues))
|
||||
return Settings::$varValues[$strSettingName];
|
||||
|
||||
if ($intSave)
|
||||
Settings::set($strSettingName, $strDefault);
|
||||
|
||||
return $strDefault;
|
||||
}
|
||||
|
||||
public static function set($strSettingName, $strValue)
|
||||
{
|
||||
Settings::$varValues = null;
|
||||
global $c;
|
||||
|
||||
$varExisting = $c->query("
|
||||
SELECT *
|
||||
from settings
|
||||
where
|
||||
setting like ?
|
||||
order by
|
||||
id desc",
|
||||
$strSettingName);
|
||||
|
||||
if (count($varExisting) !== 1)
|
||||
{
|
||||
$c->query("DELETE from settings where setting like ?", $strSettingName);
|
||||
$c->query("INSERT into settings (setting, value) values (?, ?)", $strSettingName, $strValue);
|
||||
}
|
||||
|
||||
$c->query(
|
||||
"UPDATE settings
|
||||
set
|
||||
value = ?
|
||||
where setting like ?",
|
||||
$strValue,
|
||||
$strSettingName);
|
||||
}
|
||||
}
|
||||
?>
|
107
lib/UserAuth.php
Normal file
107
lib/UserAuth.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
class UserAuth
|
||||
{
|
||||
public static function getUser()
|
||||
{
|
||||
global $c;
|
||||
try
|
||||
{
|
||||
$strToken = Cookie::get("token");
|
||||
|
||||
if ($strToken !== null)
|
||||
if (strlen($strToken) > 0)
|
||||
{
|
||||
$varSessions = $c->query(
|
||||
"SELECT *
|
||||
from sessions as s
|
||||
join users as u on u.username = s.username
|
||||
where
|
||||
s.token = ?
|
||||
and (
|
||||
s.expires is null
|
||||
or s.expires > current_timestamp
|
||||
)",
|
||||
$strToken);
|
||||
|
||||
if (count($varSessions) == 1)
|
||||
return $varSessions[0];
|
||||
}
|
||||
}
|
||||
catch (Exception $x) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function has($strColumnName)
|
||||
{
|
||||
global $c;
|
||||
$varUser = UserAuth::getUser();
|
||||
|
||||
if ($varUser == null)
|
||||
return false;
|
||||
|
||||
if (array_key_exists($strColumnName, $varUser))
|
||||
if (intval($varUser[$strColumnName]) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function require($strColumnName)
|
||||
{
|
||||
if (!UserAuth::has($strColumnName))
|
||||
{
|
||||
BootstrapRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
|
||||
Respond::redirect("/user/signin");
|
||||
}
|
||||
}
|
||||
|
||||
public static function visible($strVisibility)
|
||||
{
|
||||
global $c;
|
||||
|
||||
if (UserAuth::has("is_admin"))
|
||||
return true;
|
||||
|
||||
$varUser = UserAuth::getUser();
|
||||
$strUsername = $varUser["username"] ?? null;
|
||||
$varRegex = [
|
||||
["/user/i", ($varUser == null)],
|
||||
["/admin/i", (!UserAuth::has("is_admin"))],
|
||||
];
|
||||
|
||||
// Support arrays with username and visibility keys:
|
||||
if (is_array($strVisibility))
|
||||
{
|
||||
if (array_key_exists("username", $strVisibility))
|
||||
if ($strVisibility["username"] == $strUsername)
|
||||
return true;
|
||||
|
||||
if (!array_key_exists("visibility", $strVisibility))
|
||||
return false;
|
||||
|
||||
$strVisibility = $strVisibility["visibility"];
|
||||
}
|
||||
|
||||
// Handle hiding the post from non-admins:
|
||||
if (preg_match("/^(admin|hid(e|den)|invisible|no(ne|body)|private)$/i", $strVisibility))
|
||||
return false;
|
||||
|
||||
if (preg_match("/{$strUsername}/i", $strVisibility)) return true;
|
||||
|
||||
// Handle showing the post to everyone:
|
||||
if (preg_match("/^(|(every|any)(body|one))|all|public)$/i", $strVisibility))
|
||||
return true;
|
||||
|
||||
$intExit = 0;
|
||||
|
||||
foreach ($varRegex as $re)
|
||||
if (preg_match($re[0], $strVisibility))
|
||||
if ($re[1])
|
||||
$intExit = 1;
|
||||
|
||||
if ($intExit == 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
46
pages/directory.php
Normal file
46
pages/directory.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
global $c;
|
||||
$varPostLocations = $c->query("SELECT distinct location from posts order by location");
|
||||
$varLinks = $c->query("SELECT * from links order by sort");
|
||||
?>
|
||||
|
||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
||||
<div class="container justify-content-between">
|
||||
<div class="navbar-nav d-inline-flex align-items-center">
|
||||
<span class="navbar-brand">Directory</span>
|
||||
</div>
|
||||
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-6">
|
||||
<h5 class="mb-3"><i class="fa fa-fw fa-comment pe-2"></i> Posts</h5>
|
||||
<?php foreach ($varPostLocations as $i): ?>
|
||||
<?php
|
||||
$intPostCount = $c->query("SELECT count(*) as c from posts where location = ?", $i["location"])[0]["c"];
|
||||
?>
|
||||
<div class="border p-2 mb-2">
|
||||
<a class="link-underline link-underline-opacity-0" href="<?= $i["location"]; ?>"><i class="fa fa-fw fa-file pe-2"></i> <?= $i["location"]; ?></a>
|
||||
<small class="text-muted">— <?= $intPostCount !== 1? "{$intPostCount} posts": "{$intPostCount} post"; ?></small>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-6">
|
||||
<h5 class="mb-3"><i class="fa fa-fw fa-link pe-2"></i> Links</h5>
|
||||
<?php foreach ($varLinks as $i): ?>
|
||||
<?php if (!UserAuth::visible($i["visibility"])) continue; ?>
|
||||
<div class="border p-2 mb-2">
|
||||
<a class="link-underline link-underline-opacity-0" href="<?= $i["url"]; ?>"><i class="fa fa-fw fa-<?= $i["icon"]; ?> pe-2"></i> <?= $i["label"]; ?></a>
|
||||
<small class="text-muted">— <?= $i["position"]; ?></small>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
163
pages/edit/settings.php
Normal file
163
pages/edit/settings.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
global $c;
|
||||
|
||||
UserAuth::require("is_admin");
|
||||
|
||||
$varUser = UserAuth::getUser();
|
||||
$varRows = Settings::get();
|
||||
|
||||
$strInput = file_get_contents("php://input");
|
||||
|
||||
if (strlen($strInput) > 0)
|
||||
{
|
||||
$a = json_decode($strInput, true);
|
||||
$output = [];
|
||||
|
||||
foreach ($a as $r)
|
||||
{
|
||||
$strSetting = $r["setting"];
|
||||
$strValue = $r["value"];
|
||||
Settings::set($strSetting, $strValue);
|
||||
}
|
||||
|
||||
Respond::json(["message" => "success", "output" => $output]);
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
||||
|
||||
<div class="container justify-content-between">
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
<span class="navbar-brand">Options</span>
|
||||
<a class="btn btn-outline-success" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-nav d-inline-flex">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* https://github.com/twbs/bootstrap/issues/37184 */
|
||||
.dropdown-menu {
|
||||
z-index: 1040 !important;
|
||||
}
|
||||
|
||||
/*
|
||||
th:first-child,
|
||||
th:last-child {
|
||||
width: 7.5%;
|
||||
background: #F00 !important;
|
||||
}*/
|
||||
|
||||
.w-1 { width: 1%; }
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.w-input {
|
||||
width: 15em !important;
|
||||
}
|
||||
|
||||
tr td:first-child input[type="text"]
|
||||
{
|
||||
width: 5em !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="row my-5">
|
||||
<div class="col-lg-12">
|
||||
<?php if (count($varRows) > 0): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Setting</th>
|
||||
<th>Value<th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<?php foreach ($varRows as $k => $v): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control w-input" name="setting" value="<?= $k; ?>" />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<?php
|
||||
$strClass = "";
|
||||
if (preg_match("/\n/", $v))
|
||||
$strClass = "disabled readonly";
|
||||
?>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control w-input <?= $strClass; ?>" name="value" value="<?= $v; ?>" <?= $strClass; ?> />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<small>
|
||||
<a class="link-underline link-underline-opacity-0" href="/edit/setting/<?= $k; ?>">Edit in multi-line editor</a>
|
||||
</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
$("[name='setting']").each(function(i, x) {
|
||||
x = $(x);
|
||||
x.attr("readonly", 1);
|
||||
});
|
||||
|
||||
fnSerialize = function() {
|
||||
var a = [];
|
||||
$("table tbody tr").each(function(i, x) {
|
||||
x = $(x);
|
||||
|
||||
var valueInput = x.find("[name='value']").first();
|
||||
var o = {};
|
||||
|
||||
o["setting"] = x.find("[name='setting']").first().val().trim();
|
||||
o["value"] = valueInput.val();
|
||||
|
||||
if (valueInput.attr("disabled"))
|
||||
return;
|
||||
|
||||
a.push(o);
|
||||
});
|
||||
|
||||
console.log(a);
|
||||
return a;
|
||||
};
|
||||
|
||||
fnSave = function()
|
||||
{
|
||||
var data = fnSerialize();
|
||||
|
||||
$.ajax({
|
||||
url: "",
|
||||
method: "post",
|
||||
data: JSON.stringify(data),
|
||||
success: function(r)
|
||||
{
|
||||
console.log(r);
|
||||
window.location.href = window.location.href;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
</script>
|
54
pages/search.php
Normal file
54
pages/search.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
global $c;
|
||||
|
||||
$strPath = "/";
|
||||
$strPath .= implode("/", Request::getPathParts());
|
||||
|
||||
$varPosts = [];
|
||||
$strQuery = Request::getParam("q");
|
||||
|
||||
if ($strQuery !== null && strlen($strQuery) > 0)
|
||||
{
|
||||
$varPosts = $c->query(
|
||||
"SELECT *
|
||||
from posts as p
|
||||
where
|
||||
content like concat('%', ?, '%')
|
||||
order by
|
||||
created desc",
|
||||
$strQuery);
|
||||
|
||||
$i = 0;
|
||||
for ($i = 0; $i < count($varPosts); $i++)
|
||||
{
|
||||
$varOld = $varPosts[$i];
|
||||
$varOld["content"] = preg_replace("/({$strQuery})/i", "<mark>$1</mark>", $varOld["content"]);
|
||||
$varPosts[$i] = $varOld;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<form method="get">
|
||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
||||
<div class="container justify-content-between">
|
||||
<div class="navbar-nav d-inline-flex align-items-center">
|
||||
<span class="navbar-brand">Search</span>
|
||||
<input class="form-control me-2" type="text" name="q" value="<?= $strQuery; ?>" />
|
||||
|
||||
<button type="submit" class="btn btn-outline-info text-nowrap"><i class="fa fa-fw fa-search"></i> Go</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-nav d-inline-flex"></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<?php BootstrapRender::message(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php PostRender::rows($varPosts); ?>
|
Loading…
Reference in New Issue
Block a user