First cut of item-with-feed and list impl
- Add strict types to all files - Convert many queries to document commands
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Bookmark Partial Handler
|
||||
@@ -7,30 +7,17 @@
|
||||
*/
|
||||
|
||||
use BitBadger\Documents\DocumentException;
|
||||
use BitBadger\Documents\SQLite\Configuration;
|
||||
use BitBadger\Documents\SQLite\Find;
|
||||
use BitBadger\Documents\SQLite\Patch;
|
||||
use FeedReaderCentral\Item;
|
||||
use FeedReaderCentral\Key;
|
||||
use FeedReaderCentral\Security;
|
||||
use FeedReaderCentral\ItemWithFeed;
|
||||
use FeedReaderCentral\Table;
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
$id = $_GET['id'];
|
||||
|
||||
// TODO: adapt query once "by fields" is available
|
||||
$db = Configuration::dbConn();
|
||||
$existsQuery = $db->prepare(
|
||||
'SELECT item.id FROM item INNER JOIN feed ON feed.id = item.feed_id WHERE item.id = :id AND feed.user_id = :user');
|
||||
$existsQuery->bindValue(':id', $id);
|
||||
$existsQuery->bindValue(':user', $_SESSION[Key::USER_ID]);
|
||||
$existsResult = $existsQuery->execute();
|
||||
$exists = $existsResult ? $existsResult->fetchArray(SQLITE3_ASSOC) : false;
|
||||
|
||||
if (!$exists) not_found();
|
||||
if (!$item = ItemWithFeed::retrieveById($id)) not_found();
|
||||
|
||||
if (key_exists('action', $_GET)) {
|
||||
$flag = match ($_GET['action']) {
|
||||
@@ -40,15 +27,14 @@ if (key_exists('action', $_GET)) {
|
||||
};
|
||||
if (isset($flag)) {
|
||||
try {
|
||||
Patch::byId(Table::ITEM, $id, ['is_bookmarked' => $flag], $db);
|
||||
Patch::byId(Table::ITEM, $id, ['is_bookmarked' => $flag]);
|
||||
$item->is_bookmarked = $flag;
|
||||
} catch (DocumentException $ex) {
|
||||
add_error("$ex");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$item = Find::byId(Table::ITEM, $id, Item::class)) not_found();
|
||||
|
||||
$action = $item->isBookmarked() ? 'remove' : 'add';
|
||||
$icon = $item->isBookmarked() ? 'added' : 'add'; ?>
|
||||
<button class="bookmark <?=$action?>" type=button role=button hx-patch="/bookmark?id=<?=$id?>&action=<?=$action?>"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Add/Edit/Delete Feed Page
|
||||
*
|
||||
@@ -25,7 +26,6 @@ if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
||||
Delete::byFields(Table::ITEM, [Field::EQ('feed_id', $feed->id)]);
|
||||
Delete::byId(Table::FEED, $feed->id);
|
||||
add_info('Feed “' . htmlentities($feed->title) . '” deleted successfully');
|
||||
$db->close();
|
||||
frc_redirect('/feeds');
|
||||
} catch (DocumentException $ex) {
|
||||
add_error("$ex");
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Feed Item List Page
|
||||
*
|
||||
* Lists items in a given feed (all, unread, or bookmarked)
|
||||
*/
|
||||
|
||||
use BitBadger\Documents\SQLite\Configuration;
|
||||
use FeedReaderCentral\Feed;
|
||||
use FeedReaderCentral\ItemList;
|
||||
use FeedReaderCentral\Security;
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
if (!($feed = Feed::retrieveById($_GET['id']))) not_found();
|
||||
|
||||
$db = Configuration::dbConn();
|
||||
$list = match (true) {
|
||||
key_exists('unread', $_GET) => ItemList::unreadForFeed($feed->id, $db),
|
||||
key_exists('bookmarked', $_GET) => ItemList::bookmarkedForFeed($feed->id, $db),
|
||||
default => ItemList::allForFeed($feed->id, $db)
|
||||
key_exists('unread', $_GET) => ItemList::unreadForFeed($feed->id),
|
||||
key_exists('bookmarked', $_GET) => ItemList::bookmarkedForFeed($feed->id),
|
||||
default => ItemList::allForFeed($feed->id)
|
||||
};
|
||||
|
||||
page_head(($list->itemType != '' ? "$list->itemType Items | " : '') . strip_tags($feed['title']));
|
||||
@@ -32,4 +30,3 @@ if ($list->itemType == '') {
|
||||
}
|
||||
$list->render();
|
||||
page_foot();
|
||||
$db->close();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Feed Maintenance Page
|
||||
*
|
||||
@@ -12,12 +13,11 @@ use BitBadger\Documents\Query;
|
||||
use BitBadger\Documents\SQLite\Custom;
|
||||
use FeedReaderCentral\Feed;
|
||||
use FeedReaderCentral\Key;
|
||||
use FeedReaderCentral\Security;
|
||||
use FeedReaderCentral\Table;
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
// TODO: adapt query when document list is done
|
||||
$field = Field::EQ('user_id', $_SESSION[Key::USER_ID], '@user');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Home Page
|
||||
*
|
||||
@@ -8,15 +9,15 @@
|
||||
use BitBadger\Documents\SQLite\Configuration;
|
||||
use FeedReaderCentral\Feed;
|
||||
use FeedReaderCentral\ItemList;
|
||||
use FeedReaderCentral\Security;
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
$db = Configuration::dbConn();
|
||||
if (key_exists('refresh', $_GET)) {
|
||||
$db = Configuration::dbConn();
|
||||
$refreshResult = Feed::refreshAll($db);
|
||||
$db->close();
|
||||
if (key_exists('ok', $refreshResult)) {
|
||||
add_info('All feeds refreshed successfully');
|
||||
} else {
|
||||
@@ -25,8 +26,8 @@ if (key_exists('refresh', $_GET)) {
|
||||
}
|
||||
|
||||
$list = match (true) {
|
||||
key_exists('bookmarked', $_GET) => ItemList::allBookmarked($db),
|
||||
default => ItemList::allUnread($db)
|
||||
key_exists('bookmarked', $_GET) => ItemList::allBookmarked(),
|
||||
default => ItemList::allUnread()
|
||||
};
|
||||
$title = "Your $list->itemType Items";
|
||||
|
||||
@@ -39,4 +40,3 @@ if ($list->itemType == 'Unread') {
|
||||
echo '</h1>';
|
||||
$list->render();
|
||||
page_foot();
|
||||
$db->close();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Item View Page
|
||||
@@ -7,22 +7,19 @@
|
||||
*/
|
||||
|
||||
use BitBadger\Documents\DocumentException;
|
||||
use BitBadger\Documents\SQLite\Configuration;
|
||||
use BitBadger\Documents\SQLite\Delete;
|
||||
use BitBadger\Documents\SQLite\Patch;
|
||||
use FeedReaderCentral\Item;
|
||||
use FeedReaderCentral\Key;
|
||||
use FeedReaderCentral\Security;
|
||||
use FeedReaderCentral\ItemWithFeed;
|
||||
use FeedReaderCentral\Table;
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
try {
|
||||
// "Keep as New" button sends a POST request to reset the is_read flag before going back to the item list
|
||||
if (Item::retrieveByIdForUser($_POST['id'])) {
|
||||
if (ItemWithFeed::existsById($_POST['id'])) {
|
||||
Patch::byId(Table::ITEM, $_POST['id'], ['is_read' => 0]);
|
||||
}
|
||||
frc_redirect($_POST['from']);
|
||||
@@ -35,7 +32,7 @@ $from = $_GET['from'] ?? '/';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
||||
try {
|
||||
if (Item::retrieveByIdForUser($_GET['id'])) {
|
||||
if (ItemWithFeed::existsById($_GET['id'])) {
|
||||
Delete::byId(Table::ITEM, $_GET['id']);
|
||||
}
|
||||
} catch (DocumentException $ex) {
|
||||
@@ -44,43 +41,29 @@ if ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
|
||||
frc_redirect($from);
|
||||
}
|
||||
|
||||
// TODO: convert this query
|
||||
$db = Configuration::dbConn();
|
||||
$query = $db->prepare(<<<'SQL'
|
||||
SELECT item.title AS item_title, item.item_link, item.published_on, item.updated_on, item.content,
|
||||
feed.title AS feed_title
|
||||
FROM item INNER JOIN feed ON feed.id = item.feed_id
|
||||
WHERE item.id = :id
|
||||
AND feed.user_id = :user
|
||||
SQL);
|
||||
$query->bindValue(':id', $_GET['id']);
|
||||
$query->bindValue(':user', $_SESSION[Key::USER_ID]);
|
||||
$result = $query->execute();
|
||||
$item = $result ? $result->fetchArray(SQLITE3_ASSOC) : false;
|
||||
if (!$item = ItemWithFeed::retrieveById($_GET['id'])) not_found();
|
||||
|
||||
if ($item) {
|
||||
try {
|
||||
Patch::byId(Table::ITEM, $_GET['id'], ['is_read' => 1], $db);
|
||||
} catch (DocumentException $ex) {
|
||||
add_error("$ex");
|
||||
}
|
||||
try {
|
||||
Patch::byId(Table::ITEM, $_GET['id'], ['is_read' => 1]);
|
||||
} catch (DocumentException $ex) {
|
||||
add_error("$ex");
|
||||
}
|
||||
|
||||
$published = date_time($item['published_on']);
|
||||
$updated = isset($item['updated_on']) ? date_time($item['updated_on']) : null;
|
||||
$published = date_time($item->published_on);
|
||||
$updated = isset($item->updated_on) ? date_time($item->updated_on) : null;
|
||||
|
||||
page_head(htmlentities("{$item['item_title']} | {$item['feed_title']}")); ?>
|
||||
page_head(htmlentities("$item->title | {$item->feed->title}")); ?>
|
||||
<h1 class=item_heading>
|
||||
<span class=bookmark hx-get="/bookmark?id=<?=$_GET['id']?>" hx-trigger=load hx-target=this hx-swap=outerHTML
|
||||
hx-push-url=false></span>
|
||||
<a href="<?=$item['item_link']?>" target=_blank rel=noopener><?=strip_tags($item['item_title'])?></a><br>
|
||||
<a href="<?=$item->item_link?>" target=_blank rel=noopener><?=strip_tags($item->title)?></a><br>
|
||||
</h1>
|
||||
<div class=item_published>
|
||||
From <strong><?=htmlentities($item['feed_title'])?></strong><br>
|
||||
Published <?=date_time($item['published_on'])?><?=$updated && $updated != $published ? " (Updated $updated)" : ''?>
|
||||
From <strong><?=htmlentities($item->feed->title)?></strong><br>
|
||||
Published <?=date_time($item->published_on)?><?=$updated && $updated != $published ? " (Updated $updated)" : ''?>
|
||||
</div>
|
||||
<article>
|
||||
<div class=item_content><?=str_replace('<a ', '<a target=_blank rel=noopener ', $item['content'])?></div>
|
||||
<div class=item_content><?=str_replace('<a ', '<a target=_blank rel=noopener ', $item->content)?></div>
|
||||
<form class=action_buttons action=/item method=POST hx-post=/item>
|
||||
<input type=hidden name=id value=<?=$_GET['id']?>>
|
||||
<input type=hidden name=from value="<?=$from?>">
|
||||
@@ -90,4 +73,3 @@ page_head(htmlentities("{$item['item_title']} | {$item['feed_title']}")); ?>
|
||||
</form>
|
||||
</article><?php
|
||||
page_foot();
|
||||
$db->close();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Item Search Page
|
||||
@@ -6,20 +6,15 @@
|
||||
* Search for items across all feeds
|
||||
*/
|
||||
|
||||
use BitBadger\Documents\SQLite\Configuration;
|
||||
use FeedReaderCentral\ItemList;
|
||||
use FeedReaderCentral\Security;
|
||||
|
||||
include '../start.php';
|
||||
|
||||
Security::verifyUser();
|
||||
FeedReaderCentral\Security::verifyUser();
|
||||
|
||||
$search = $_GET['search'] ?? '';
|
||||
$items = $_GET['items'] ?? 'all';
|
||||
|
||||
$db = Configuration::dbConn();
|
||||
if ($search != '') {
|
||||
$list = ItemList::matchingSearch($search, $items == 'bookmarked', $db);
|
||||
$list = FeedReaderCentral\ItemList::matchingSearch($search, $items == 'bookmarked');
|
||||
}
|
||||
|
||||
page_head('Item Search'); ?>
|
||||
@@ -46,4 +41,3 @@ page_head('Item Search'); ?>
|
||||
} ?>
|
||||
</article><?php
|
||||
page_foot();
|
||||
$db->close();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* User Log Off Page
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<?php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* User Log On Page
|
||||
*
|
||||
* Accepts the user's e-mail address (multi-user) and password (multi-user or single-user-with-password) and attempts
|
||||
* to log them on to Feed Reader Central
|
||||
*/
|
||||
|
||||
include '../../start.php';
|
||||
|
||||
use FeedReaderCentral\Key;
|
||||
|
||||
Reference in New Issue
Block a user