Documents and Documentation (beta 1) #23

Merged
danieljsummers merged 16 commits from doc-experiment into main 2024-06-12 02:07:36 +00:00
12 changed files with 67 additions and 104 deletions
Showing only changes of commit edc9a218b7 - Show all commits

4
src/composer.lock generated
View File

@ -12,7 +12,7 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://git.bitbadger.solutions/bit-badger/pdo-document", "url": "https://git.bitbadger.solutions/bit-badger/pdo-document",
"reference": "2d8f8b6e8728f8fbe0d801e2bc529a678f65ad9b" "reference": "a10ecbb1cdfdf6dd8ab3c1884b09d9ba987b7ff5"
}, },
"require": { "require": {
"ext-pdo": "*", "ext-pdo": "*",
@ -36,7 +36,7 @@
"Test\\Integration\\SQLite\\": "./tests/integration/sqlite" "Test\\Integration\\SQLite\\": "./tests/integration/sqlite"
} }
}, },
"time": "2024-06-08T14:49:52+00:00" "time": "2024-06-08T16:57:13+00:00"
}, },
{ {
"name": "netresearch/jsonmapper", "name": "netresearch/jsonmapper",

View File

@ -269,9 +269,7 @@ class Feed
*/ */
public static function retrieveById(int $feedId): static|false public static function retrieveById(int $feedId): static|false
{ {
define('PDO_DOC_DEBUG_SQL', true);
$doc = Find::byId(Table::FEED, $feedId, static::class); $doc = Find::byId(Table::FEED, $feedId, static::class);
echo "Feed $feedId: " . ($doc ? 'found it' : 'not found');
return $doc && $doc->user_id == $_SESSION[Key::USER_ID] ? $doc : false; return $doc && $doc->user_id == $_SESSION[Key::USER_ID] ? $doc : false;
} }
} }

View File

@ -53,7 +53,7 @@ class ItemList
$this->dbList = Custom::list( $this->dbList = Custom::list(
ItemWithFeed::SELECT_WITH_FEED . ' WHERE ' ItemWithFeed::SELECT_WITH_FEED . ' WHERE '
. Query::whereByFields(array_filter($allFields, fn($it) => $it->paramName <> ':search')) . Query::whereByFields(array_filter($allFields, fn($it) => $it->paramName <> ':search'))
. $searchWhere, . "$searchWhere ORDER BY coalesce(item.data->>'updated_on', item.data->>'published_on') DESC",
Parameters::addFields($allFields, []), new DocumentMapper(ItemWithFeed::class)); Parameters::addFields($allFields, []), new DocumentMapper(ItemWithFeed::class));
} catch (DocumentException $ex) { } catch (DocumentException $ex) {
$this->error = "$ex"; $this->error = "$ex";

View File

@ -6,10 +6,8 @@
* This will display a button which will either add or remove a bookmark for a given item. * This will display a button which will either add or remove a bookmark for a given item.
*/ */
use BitBadger\PDODocument\DocumentException; use BitBadger\PDODocument\{DocumentException, Patch};
use BitBadger\PDODocument\Patch; use FeedReaderCentral\{ItemWithFeed, Table};
use FeedReaderCentral\ItemWithFeed;
use FeedReaderCentral\Table;
include '../start.php'; include '../start.php';

View File

@ -6,18 +6,14 @@
* Allows users to add, edit, and delete feeds * Allows users to add, edit, and delete feeds
*/ */
use BitBadger\PDODocument\Delete; use BitBadger\PDODocument\{Delete, DocumentException, Field};
use BitBadger\PDODocument\DocumentException; use FeedReaderCentral\{Feed, Security, Table};
use BitBadger\PDODocument\Field;
use FeedReaderCentral\Feed;
use FeedReaderCentral\Security;
use FeedReaderCentral\Table;
include '../../start.php'; include '../../start.php';
Security::verifyUser(); Security::verifyUser();
$feedId = $_GET['id'] ?? ''; $feedId = key_exists('id', $_GET) ? (int)$_GET['id'] : -1;
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') { if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
try { try {
@ -37,10 +33,11 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($isNew) { if ($isNew) {
$result = Feed::add($_POST['url']); $result = Feed::add($_POST['url']);
} else { } else {
$toEdit = Feed::retrieveById($_POST['id']); $feedId = (int)$_POST['id'];
$toEdit = Feed::retrieveById($feedId);
$result = $toEdit $result = $toEdit
? Feed::update($toEdit, $_POST['url']) ? Feed::update($toEdit, $_POST['url'])
: ['error' => "Feed {$_POST['id']} not found"]; : ['error' => "Feed $feedId not found"];
} }
if (key_exists('ok', $result)) { if (key_exists('ok', $result)) {
add_info('Feed saved successfully'); add_info('Feed saved successfully');
@ -53,16 +50,13 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
} }
} }
if ($feedId == 'new') { if ($feedId == -1) {
$title = 'Add RSS Feed'; $title = 'Add RSS Feed';
$feed = new Feed(); $feed = new Feed(id: -1);
$feed->id = $_GET['id'];
} else { } else {
$title = 'Edit RSS Feed'; $title = 'Edit RSS Feed';
if ($feedId == 'error') { if ($feedId == 'error') {
$feed = new Feed(); $feed = new Feed(id: (int)$_POST['id'], url: $_POST['url'] ?? '');
$feed->id = $_POST['id'] ?? '';
$feed->url = $_POST['url'] ?? '';
} elseif (!($feed = Feed::retrieveById((int)$feedId))) not_found(); } elseif (!($feed = Feed::retrieveById((int)$feedId))) not_found();
} }

View File

@ -6,8 +6,7 @@
* Lists items in a given feed (all, unread, or bookmarked) * Lists items in a given feed (all, unread, or bookmarked)
*/ */
use FeedReaderCentral\Feed; use FeedReaderCentral\{Feed, ItemList};
use FeedReaderCentral\ItemList;
include '../../start.php'; include '../../start.php';
@ -22,11 +21,11 @@ $list = match (true) {
default => ItemList::allForFeed($feed->id) default => ItemList::allForFeed($feed->id)
}; };
page_head(($list->itemType != '' ? "$list->itemType Items | " : '') . strip_tags($feed['title'])); page_head(($list->itemType != '' ? "$list->itemType Items | " : '') . strip_tags($feed->title));
if ($list->itemType == '') { if ($list->itemType == '') {
echo '<h1>' . htmlentities($feed['title']) . '</h1>'; echo '<h1>' . htmlentities($feed->title) . '</h1>';
} else { } else {
echo '<h1 class=item_heading>' . htmlentities($feed['title']) . '</h1>'; echo '<h1 class=item_heading>' . htmlentities($feed->title) . '</h1>';
echo "<div class=item_published>$list->itemType Items</div>"; echo "<div class=item_published>$list->itemType Items</div>";
} }
$list->render(); $list->render();

View File

@ -6,14 +6,9 @@
* List feeds and provide links for maintenance actions * List feeds and provide links for maintenance actions
*/ */
use BitBadger\PDODocument\Custom; use BitBadger\PDODocument\{Custom, Field, Query};
use BitBadger\PDODocument\Field; use BitBadger\PDODocument\Mapper\{ArrayMapper, DocumentMapper};
use BitBadger\PDODocument\Mapper\ArrayMapper; use FeedReaderCentral\{Feed, Key, Table};
use BitBadger\PDODocument\Mapper\DocumentMapper;
use BitBadger\PDODocument\Query;
use FeedReaderCentral\Feed;
use FeedReaderCentral\Key;
use FeedReaderCentral\Table;
include '../start.php'; include '../start.php';

View File

@ -6,8 +6,7 @@
* Displays a list of unread or bookmarked items for the current user * Displays a list of unread or bookmarked items for the current user
*/ */
use FeedReaderCentral\Feed; use FeedReaderCentral\{Feed, ItemList};
use FeedReaderCentral\ItemList;
include '../start.php'; include '../start.php';
@ -21,7 +20,6 @@ if (key_exists('refresh', $_GET)) {
add_error(nl2br($refreshResult['error'])); add_error(nl2br($refreshResult['error']));
} }
} }
//const PDO_DOC_DEBUG_SQL = true;
$list = match (true) { $list = match (true) {
key_exists('bookmarked', $_GET) => ItemList::allBookmarked(), key_exists('bookmarked', $_GET) => ItemList::allBookmarked(),

View File

@ -6,11 +6,8 @@
* Retrieves and displays an item from a feed belonging to the current user * Retrieves and displays an item from a feed belonging to the current user
*/ */
use BitBadger\PDODocument\DocumentException; use BitBadger\PDODocument\{Delete, DocumentException, Patch};
use BitBadger\PDODocument\Delete; use FeedReaderCentral\{ItemWithFeed, Table};
use BitBadger\PDODocument\Patch;
use FeedReaderCentral\ItemWithFeed;
use FeedReaderCentral\Table;
include '../start.php'; include '../start.php';
@ -38,9 +35,7 @@ $from = $_GET['from'] ?? '/';
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') { if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
try { try {
if (ItemWithFeed::existsById($id)) { if (ItemWithFeed::existsById($id)) Delete::byId(Table::ITEM, $id);
Delete::byId(Table::ITEM, $id);
}
} catch (DocumentException $ex) { } catch (DocumentException $ex) {
add_error("$ex"); add_error("$ex");
} }

View File

@ -9,8 +9,7 @@
include '../../start.php'; include '../../start.php';
use FeedReaderCentral\Key; use FeedReaderCentral\{Key, Security};
use FeedReaderCentral\Security;
Security::verifyUser(redirectIfAnonymous: false); Security::verifyUser(redirectIfAnonymous: false);

View File

@ -1,8 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use FeedReaderCentral\Key; use FeedReaderCentral\{Key, Security, User};
use FeedReaderCentral\Security;
use FeedReaderCentral\User;
require 'app-config.php'; require 'app-config.php';
@ -12,8 +10,6 @@ session_start([
'cookie_httponly' => true, 'cookie_httponly' => true,
'cookie_samesite' => 'Strict']); 'cookie_samesite' => 'Strict']);
//const PDO_DOC_DEBUG_SQL = true;
/** /**
* Add a message to be displayed at the top of the page * Add a message to be displayed at the top of the page
* *
@ -66,26 +62,25 @@ function nav_link(string $link, bool $isFirst = false): void
*/ */
function title_bar(): void function title_bar(): void
{ {
$version = display_version(); ?> $version = display_version();
<header hx-target=#main hx-push-url=true> echo "<header hx-target=#main hx-push-url=true>"
<div><a href=/ class=title>Feed Reader Central</a><span class=version><?=$version?></span></div> . "<div><a href=/ class=title>Feed Reader Central</a><span class=version>$version</span></div>"
<nav><?php . "<nav>";
if (key_exists(Key::USER_ID, $_SESSION)) { if (key_exists(Key::USER_ID, $_SESSION)) {
nav_link(hx_get('/feeds', 'Feeds'), true); nav_link(hx_get('/feeds', 'Feeds'), true);
if (User::hasBookmarks()) nav_link(hx_get('/?bookmarked', 'Bookmarked')); if (User::hasBookmarks()) nav_link(hx_get('/?bookmarked', 'Bookmarked'));
nav_link(hx_get('/search', 'Search')); nav_link(hx_get('/search', 'Search'));
nav_link(hx_get('/docs/', 'Docs')); nav_link(hx_get('/docs/', 'Docs'));
nav_link('<a href=/user/log-off>Log Off</a>'); nav_link('<a href=/user/log-off>Log Off</a>');
if ($_SESSION[Key::USER_EMAIL] != Security::SINGLE_USER_EMAIL) { if ($_SESSION[Key::USER_EMAIL] != Security::SINGLE_USER_EMAIL) {
nav_link($_SESSION[Key::USER_EMAIL]); nav_link($_SESSION[Key::USER_EMAIL]);
} }
} else { } else {
nav_link(hx_get('/user/log-on', 'Log On'), true); nav_link(hx_get('/user/log-on', 'Log On'), true);
nav_link(hx_get('/docs/', 'Docs')); nav_link(hx_get('/docs/', 'Docs'));
} ?> }
</nav> echo '</nav></header>'
</header> . '<main id=main hx-target=this hx-push-url=true hx-swap="innerHTML show:window:top">';
<main id=main hx-target=this hx-push-url=true hx-swap="innerHTML show:window:top"><?php
} }
/** /**
@ -94,28 +89,24 @@ function title_bar(): void
*/ */
function page_head(string $title): void function page_head(string $title): void
{ {
global $is_htmx; ?> global $is_htmx;
<!DOCTYPE html> echo '<!DOCTYPE html><html lang=en>'
<html lang=en> . "<head><title>$title | Feed Reader Central</title>";
<head> if (!$is_htmx) {
<title><?=$title?> | Feed Reader Central</title><?php echo '<meta name=viewport content="width=device-width, initial-scale=1">'
if (!$is_htmx) { ?> . "<meta name=htmx-config content='{\"historyCacheSize\":0}'>"
<meta name=viewport content="width=device-width, initial-scale=1"> . '<link href=/assets/style.css rel=stylesheet>';
<meta name=htmx-config content='{"historyCacheSize":0}'> }
<link href=/assets/style.css rel=stylesheet><?php echo '</head><body>';
} ?>
</head>
<body><?php
if (!$is_htmx) title_bar(); if (!$is_htmx) title_bar();
if (sizeof($messages = $_SESSION[Key::USER_MSG] ?? []) > 0) { ?> if (sizeof($messages = $_SESSION[Key::USER_MSG] ?? []) > 0) {
<div class=user_messages><?php echo '<div class=user_messages>';
array_walk($messages, function ($msg) { ?> array_walk($messages, function ($msg) {
<div class=user_message> echo '<div class=user_message>'
<?=$msg['level'] == 'INFO' ? '' : "<strong>{$msg['level']}</strong><br>"?> . ($msg['level'] == 'INFO' ? '' : "<strong>{$msg['level']}</strong><br>")
<?=$msg['message']?> . $msg['message'] . '</div>';
</div><?php });
}); ?> echo '</div>';
</div><?php
$_SESSION[Key::USER_MSG] = []; $_SESSION[Key::USER_MSG] = [];
} }
} }
@ -125,11 +116,8 @@ function page_head(string $title): void
*/ */
function page_foot(): void function page_foot(): void
{ {
global $is_htmx; ?> global $is_htmx;
</main><?php echo '</main>' . ($is_htmx ? '' : '<script src=/assets/htmx.min.js></script>') . '</body></html>';
if (!$is_htmx) echo '<script src=/assets/htmx.min.js></script>'; ?>
</body>
</html><?php
session_commit(); session_commit();
} }

View File

@ -8,8 +8,7 @@
* On initial installation, rename this file to user-config.php and configure it as desired * On initial installation, rename this file to user-config.php and configure it as desired
*/ */
use FeedReaderCentral\Feed; use FeedReaderCentral\{Feed, Security};
use FeedReaderCentral\Security;
/** /**
* Which security model should the application use? Options are: * Which security model should the application use? Options are: