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 "
Error retrieving list:
$this->error";
return;
}
$return = $this->returnURL == '' ? '' : '&from=' . urlencode($this->returnURL);
$hasItems = false;
echo '';
foreach ($this->dbList->items() as $it) {
$hasItems = true;
echo '' . hx_get("/item?id=$it->id$return", strip_tags($it->title)) . '
';
if ($this->showIndicators) {
if (!$it->isRead()) echo 'Unread ';
if ($it->isBookmarked()) echo 'Bookmarked ';
}
echo '' . date_time($it->updated_on ?? $it->published_on) . '';
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 '';
}
if (!$hasItems) {
echo '
There are no ' . strtolower($this->itemType) . ' items';
}
echo '
';
}
}