Documents and Documentation (beta 1) (#23)
- Change to SQLite document store - Complete documentation on usage of Feed Reader Central - Update INSTALLING.md for new installation procedures Reviewed-on: #23
This commit was merged in pull request #23.
This commit is contained in:
145
src/start.php
145
src/start.php
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use BitBadger\PDODocument\Configuration;
|
||||
use FeedReaderCentral\{Key, Security, User};
|
||||
|
||||
require 'app-config.php';
|
||||
|
||||
@@ -15,7 +17,8 @@ session_start([
|
||||
* @param string $level The level (type) of the message
|
||||
* @param string $message The message itself
|
||||
*/
|
||||
function add_message(string $level, string $message): void {
|
||||
function add_message(string $level, string $message): void
|
||||
{
|
||||
if (!key_exists(Key::USER_MSG, $_SESSION)) $_SESSION[Key::USER_MSG] = array();
|
||||
$_SESSION[Key::USER_MSG][] = ['level' => $level, 'message' => $message];
|
||||
}
|
||||
@@ -25,7 +28,8 @@ function add_message(string $level, string $message): void {
|
||||
*
|
||||
* @param string $message The message to be displayed
|
||||
*/
|
||||
function add_error(string $message): void {
|
||||
function add_error(string $message): void
|
||||
{
|
||||
add_message('ERROR', $message);
|
||||
}
|
||||
|
||||
@@ -34,14 +38,22 @@ function add_error(string $message): void {
|
||||
*
|
||||
* @param string $message The message to be displayed
|
||||
*/
|
||||
function add_info(string $message): void {
|
||||
function add_info(string $message): void
|
||||
{
|
||||
add_message('INFO', $message);
|
||||
}
|
||||
|
||||
/** @var bool $is_htmx True if this request was initiated by htmx, false if not */
|
||||
$is_htmx = key_exists('HTTP_HX_REQUEST', $_SERVER) && !key_exists('HTTP_HX_HISTORY_RESTORE_REQUEST', $_SERVER);
|
||||
|
||||
function nav_link(string $link, bool $isFirst = false) {
|
||||
/**
|
||||
* Create a navigation link in the top right nav bar
|
||||
*
|
||||
* @param string $link The link to be placed
|
||||
* @param bool $isFirst True if this is the first link being placed, false if not
|
||||
*/
|
||||
function nav_link(string $link, bool $isFirst = false): void
|
||||
{
|
||||
$sep = $isFirst ? '' : ' | ';
|
||||
echo "<span>$sep$link</span>";
|
||||
}
|
||||
@@ -49,71 +61,53 @@ function nav_link(string $link, bool $isFirst = false) {
|
||||
/**
|
||||
* Render the title bar for the page
|
||||
*/
|
||||
function title_bar(): void {
|
||||
$version = display_version();; ?>
|
||||
<header hx-target=#main hx-push-url=true>
|
||||
<div><a href=/ class=title>Feed Reader Central</a><span class=version><?=$version?></span></div>
|
||||
<nav><?php
|
||||
if (key_exists(Key::USER_ID, $_SESSION)) {
|
||||
$db = Data::getConnection();
|
||||
try {
|
||||
$bookQuery = $db->prepare(<<<'SQL'
|
||||
SELECT EXISTS(
|
||||
SELECT 1
|
||||
FROM item INNER JOIN feed ON item.feed_id = feed.id
|
||||
WHERE feed.user_id = :id AND item.is_bookmarked = 1)
|
||||
SQL);
|
||||
$bookQuery->bindValue(':id', $_SESSION[Key::USER_ID]);
|
||||
$bookResult = $bookQuery->execute();
|
||||
$hasBookmarks = $bookResult && $bookResult->fetchArray(SQLITE3_NUM)[0];
|
||||
nav_link(hx_get('/feeds', 'Feeds'), true);
|
||||
if ($hasBookmarks) nav_link(hx_get('/?bookmarked', 'Bookmarked'));
|
||||
nav_link(hx_get('/search', 'Search'));
|
||||
nav_link(hx_get('/docs/', 'Docs'));
|
||||
nav_link('<a href=/user/log-off>Log Off</a>');
|
||||
if ($_SESSION[Key::USER_EMAIL] != Security::SINGLE_USER_EMAIL) {
|
||||
nav_link($_SESSION[Key::USER_EMAIL]);
|
||||
}
|
||||
} finally {
|
||||
$db->close();
|
||||
}
|
||||
} else {
|
||||
nav_link(hx_get('/user/log-on', 'Log On'), true);
|
||||
nav_link(hx_get('/docs/', 'Docs'));
|
||||
} ?>
|
||||
</nav>
|
||||
</header>
|
||||
<main id=main hx-target=this hx-push-url=true hx-swap="innerHTML show:window:top"><?php
|
||||
function title_bar(): void
|
||||
{
|
||||
$version = display_version();
|
||||
echo "<header hx-target=#main hx-push-url=true>"
|
||||
. "<div><a href=/ class=title>Feed Reader Central</a><span class=version>$version</span></div>"
|
||||
. "<nav>";
|
||||
if (key_exists(Key::USER_ID, $_SESSION)) {
|
||||
nav_link(hx_get('/feeds', 'Feeds'), true);
|
||||
if (User::hasBookmarks()) nav_link(hx_get('/?bookmarked', 'Bookmarked'));
|
||||
nav_link(hx_get('/search', 'Search'));
|
||||
nav_link(hx_get('/docs/', 'Docs'));
|
||||
nav_link('<a href=/user/log-off>Log Off</a>');
|
||||
if ($_SESSION[Key::USER_EMAIL] != Security::SINGLE_USER_EMAIL) {
|
||||
nav_link($_SESSION[Key::USER_EMAIL]);
|
||||
}
|
||||
} else {
|
||||
nav_link(hx_get('/user/log-on', 'Log On'), true);
|
||||
nav_link(hx_get('/docs/', 'Docs'));
|
||||
}
|
||||
echo '</nav></header>'
|
||||
. '<main id=main hx-target=this hx-push-url=true hx-swap="innerHTML show:window:top">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the page title
|
||||
* @param string $title The title of the page being displayed
|
||||
*/
|
||||
function page_head(string $title): void {
|
||||
function page_head(string $title): void
|
||||
{
|
||||
global $is_htmx;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<title><?=$title?> | Feed Reader Central</title><?php
|
||||
if (!$is_htmx) { ?>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1">
|
||||
<meta name=htmx-config content='{"historyCacheSize":0}'>
|
||||
<link href=/assets/style.css rel=stylesheet><?php
|
||||
} ?>
|
||||
</head>
|
||||
<body><?php
|
||||
echo '<!DOCTYPE html><html lang=en>'
|
||||
. "<head><title>$title | Feed Reader Central</title>";
|
||||
if (!$is_htmx) {
|
||||
echo '<meta name=viewport content="width=device-width, initial-scale=1">'
|
||||
. "<meta name=htmx-config content='{\"historyCacheSize\":0}'>"
|
||||
. '<link href=/assets/style.css rel=stylesheet>';
|
||||
}
|
||||
echo '</head><body>';
|
||||
if (!$is_htmx) title_bar();
|
||||
if (sizeof($messages = $_SESSION[Key::USER_MSG] ?? []) > 0) { ?>
|
||||
<div class=user_messages><?php
|
||||
array_walk($messages, function ($msg) { ?>
|
||||
<div class=user_message>
|
||||
<?=$msg['level'] == 'INFO' ? '' : "<strong>{$msg['level']}</strong><br>"?>
|
||||
<?=$msg['message']?>
|
||||
</div><?php
|
||||
}); ?>
|
||||
</div><?php
|
||||
if (sizeof($messages = $_SESSION[Key::USER_MSG] ?? []) > 0) {
|
||||
echo '<div class=user_messages>';
|
||||
array_walk($messages, function ($msg) {
|
||||
echo '<div class=user_message>'
|
||||
. ($msg['level'] == 'INFO' ? '' : "<strong>{$msg['level']}</strong><br>")
|
||||
. $msg['message'] . '</div>';
|
||||
});
|
||||
echo '</div>';
|
||||
$_SESSION[Key::USER_MSG] = [];
|
||||
}
|
||||
}
|
||||
@@ -121,12 +115,10 @@ function page_head(string $title): void {
|
||||
/**
|
||||
* Render the end of the page
|
||||
*/
|
||||
function page_foot(): void {
|
||||
global $is_htmx; ?>
|
||||
</main><?php
|
||||
if (!$is_htmx) echo '<script src=/assets/htmx.min.js></script>'; ?>
|
||||
</body>
|
||||
</html><?php
|
||||
function page_foot(): void
|
||||
{
|
||||
global $is_htmx;
|
||||
echo '</main>' . ($is_htmx ? '' : '<script src=/assets/htmx.min.js></script>') . '</body></html>';
|
||||
session_commit();
|
||||
}
|
||||
|
||||
@@ -135,14 +127,15 @@ function page_foot(): void {
|
||||
*
|
||||
* @param string $value A local URL to which the user should be redirected
|
||||
*/
|
||||
#[NoReturn]
|
||||
function frc_redirect(string $value): void {
|
||||
function frc_redirect(string $value): never
|
||||
{
|
||||
if (str_starts_with($value, 'http')) {
|
||||
http_response_code(400);
|
||||
die();
|
||||
}
|
||||
session_commit();
|
||||
header("Location: $value", true, 303);
|
||||
Configuration::resetPDO();
|
||||
die();
|
||||
}
|
||||
|
||||
@@ -152,7 +145,8 @@ function frc_redirect(string $value): void {
|
||||
* @param string $value The date/time string
|
||||
* @return string The standard format of a date/time, or '(invalid date)' if the date could not be parsed
|
||||
*/
|
||||
function date_time(string $value): string {
|
||||
function date_time(string $value): string
|
||||
{
|
||||
try {
|
||||
return (new DateTimeImmutable($value))->format(DATE_TIME_FORMAT);
|
||||
} catch (Exception) {
|
||||
@@ -168,7 +162,8 @@ function date_time(string $value): string {
|
||||
* @param string $extraAttrs Extra attributes for the anchor tag (must be attribute-encoded)
|
||||
* @return string The anchor tag with both `href` and `hx-get` attributes
|
||||
*/
|
||||
function hx_get(string $url, string $text, string $extraAttrs = ''): string {
|
||||
function hx_get(string $url, string $text, string $extraAttrs = ''): string
|
||||
{
|
||||
$attrs = $extraAttrs != '' ? " $extraAttrs" : '';
|
||||
return "<a href=\"$url\" hx-get=\"$url\"$attrs>$text</a>";
|
||||
}
|
||||
@@ -176,8 +171,8 @@ function hx_get(string $url, string $text, string $extraAttrs = ''): string {
|
||||
/**
|
||||
* Return a 404 Not Found
|
||||
*/
|
||||
#[NoReturn]
|
||||
function not_found(): void {
|
||||
function not_found(): never
|
||||
{
|
||||
http_response_code(404);
|
||||
die('Not Found');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user