185 lines
6.8 KiB
PHP
185 lines
6.8 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
namespace FeedReaderCentral;
|
|
|
|
use BitBadger\PDODocument\Configuration;
|
|
use BitBadger\PDODocument\Custom;
|
|
use BitBadger\PDODocument\DocumentException;
|
|
use BitBadger\PDODocument\DocumentList;
|
|
use BitBadger\PDODocument\Field;
|
|
use BitBadger\PDODocument\Parameters;
|
|
use BitBadger\PDODocument\Query;
|
|
use BitBadger\PDODocument\Mapper\DocumentMapper;
|
|
|
|
/**
|
|
* A list of items to be displayed
|
|
*
|
|
* This is a wrapper for retrieval and display of arbitrary lists of items based on a SQLite result.
|
|
*/
|
|
class ItemList
|
|
{
|
|
/** @var DocumentList<ItemWithFeed> The items matching the criteria, lazily iterable */
|
|
private DocumentList $dbList;
|
|
|
|
/** @var string The error message generated by executing a query */
|
|
public string $error = '';
|
|
|
|
/**
|
|
* Is there an error condition associated with this list?
|
|
*
|
|
* @return bool True if there is an error condition associated with this list, false if not
|
|
*/
|
|
public function isError(): bool
|
|
{
|
|
return $this->error != '';
|
|
}
|
|
|
|
/** @var bool Whether to render a link to the feed to which the item belongs */
|
|
public bool $linkFeed = false;
|
|
|
|
/** @var bool Whether to display the feed to which the item belongs */
|
|
public bool $displayFeed = false;
|
|
|
|
/** @var bool Whether to show read / bookmarked indicators on posts */
|
|
public bool $showIndicators = false;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $itemType The type of item being displayed (unread, bookmark, etc.)
|
|
* @param string $returnURL The URL to which the item page should return once the item has been viewed
|
|
* @param array|Field[] $fields The fields to use to restrict the results
|
|
* @param string $searchWhere Additional WHERE clause to use for searching
|
|
*/
|
|
private function __construct(public string $itemType, public string $returnURL = '', array $fields = [],
|
|
string $searchWhere = '')
|
|
{
|
|
$allFields = [Data::userIdField(Table::FEED), ...$fields];
|
|
try {
|
|
$this->dbList = Custom::list(
|
|
ItemWithFeed::SELECT_WITH_FEED . ' WHERE '
|
|
. Query::whereByFields(array_filter($allFields, fn($it) => $it->paramName <> ':search'))
|
|
. $searchWhere,
|
|
Parameters::addFields($allFields, []), new DocumentMapper(ItemWithFeed::class));
|
|
} catch (DocumentException $ex) {
|
|
$this->error = "$ex";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create an item list with all the current user's bookmarked items
|
|
*
|
|
* @return static An item list with all bookmarked items
|
|
*/
|
|
public static function allBookmarked(): static
|
|
{
|
|
$list = new static('Bookmarked', '/?bookmarked', [Data::bookmarkField(qualifier: Table::ITEM)]);
|
|
$list->linkFeed = true;
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Create an item list with all the current user's unread items
|
|
*
|
|
* @return static An item list with all unread items
|
|
*/
|
|
public static function allUnread(): static
|
|
{
|
|
$list = new static('Unread', fields: [Data::unreadField(Table::ITEM)]);
|
|
$list->linkFeed = true;
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Create an item list with all items for the given feed
|
|
*
|
|
* @param int $feedId The ID of the feed for which items should be retrieved
|
|
* @return static An item list with all items for the given feed
|
|
*/
|
|
public static function allForFeed(int $feedId): static
|
|
{
|
|
$list = new static('', "/feed/items?id=$feedId", [Data::feedField($feedId, Table::FEED)]);
|
|
$list->showIndicators = true;
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Create an item list with unread items for the given feed
|
|
*
|
|
* @param int $feedId The ID of the feed for which items should be retrieved
|
|
* @return static An item list with unread items for the given feed
|
|
*/
|
|
public static function unreadForFeed(int $feedId): static
|
|
{
|
|
return new static('Unread', "/feed/items?id=$feedId&unread",
|
|
[Data::feedField($feedId, Table::FEED), Data::unreadField(Table::ITEM)]);
|
|
}
|
|
|
|
/**
|
|
* Create an item list with bookmarked items for the given feed
|
|
*
|
|
* @param int $feedId The ID of the feed for which items should be retrieved
|
|
* @return static An item list with bookmarked items for the given feed
|
|
*/
|
|
public static function bookmarkedForFeed(int $feedId): static
|
|
{
|
|
return new static('Bookmarked', "/feed/items?id=$feedId&bookmarked",
|
|
[Data::feedField($feedId, Table::FEED), Data::bookmarkField(qualifier: Table::ITEM)]);
|
|
}
|
|
|
|
/**
|
|
* Create an item list with items matching given search terms
|
|
*
|
|
* @param string $search The item search terms / query
|
|
* @param bool $isBookmarked Whether to restrict the search to bookmarked items
|
|
* @return static An item list match the given search terms
|
|
*/
|
|
public static function matchingSearch(string $search, bool $isBookmarked): static
|
|
{
|
|
$fields = [Field::EQ('content', $search, ':search')];
|
|
if ($isBookmarked) $fields[] = Data::bookmarkField(qualifier: Table::ITEM);
|
|
$list = new static('Matching' . ($isBookmarked ? ' Bookmarked' : ''),
|
|
"/search?search=$search&items=" . ($isBookmarked ? 'bookmarked' : 'all'), $fields,
|
|
' AND ' . Table::ITEM . ".data->>'" . Configuration::$idField . "' IN "
|
|
. '(SELECT ROWID FROM item_search WHERE content MATCH :search)');
|
|
$list->showIndicators = true;
|
|
$list->displayFeed = true;
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* Render this item list
|
|
*/
|
|
public function render(): void
|
|
{
|
|
if ($this->isError()) {
|
|
echo "<p>Error retrieving list:<br>$this->error";
|
|
return;
|
|
}
|
|
$return = $this->returnURL == '' ? '' : '&from=' . urlencode($this->returnURL);
|
|
$hasItems = false;
|
|
echo '<article>';
|
|
foreach ($this->dbList->items() as $it) {
|
|
$hasItems = true;
|
|
echo '<p>' . hx_get("/item?id=$it->id$return", strip_tags($it->title)) . '<br><small>';
|
|
if ($this->showIndicators) {
|
|
if (!$it->isRead()) echo '<strong>Unread</strong> ';
|
|
if ($it->isBookmarked()) echo '<strong>Bookmarked</strong> ';
|
|
}
|
|
echo '<em>' . date_time($it->updated_on ?? $it->published_on) . '</em>';
|
|
if ($this->linkFeed) {
|
|
echo ' • ' .
|
|
hx_get("/feed/items?id={$it->feed->id}&" . strtolower($this->itemType),
|
|
htmlentities($it->feed->title));
|
|
} elseif ($this->displayFeed) {
|
|
echo ' • ' . htmlentities($it->feed->title);
|
|
}
|
|
echo '</small>';
|
|
}
|
|
if (!$hasItems) {
|
|
echo '<p><em>There are no ' . strtolower($this->itemType) . ' items</em>';
|
|
}
|
|
echo '</article>';
|
|
}
|
|
}
|