Fix insert statements; other minor tweaks

This commit is contained in:
2024-06-09 18:01:04 -04:00
parent edc9a218b7
commit 3dc314b2e3
9 changed files with 117 additions and 102 deletions

View File

@@ -3,7 +3,7 @@
namespace FeedReaderCentral;
use BitBadger\PDODocument\{
Configuration, Custom, Document, DocumentException, DocumentList, Exists, Field, Find, Parameters, Patch, Query
Configuration, Custom, DocumentException, DocumentList, Exists, Field, Find, Parameters, Patch, Query
};
use DateTimeInterface;
@@ -50,14 +50,12 @@ class Feed
*/
public static function fromParsed(ParsedFeed $parsed): static
{
$it = new static();
$it->user_id = $_SESSION[Key::USER_ID];
$it->url = $parsed->url;
$it->title = $parsed->title;
$it->updated_on = $parsed->updatedOn;
$it->checked_on = Data::formatDate('now');
return $it;
return new static(
user_id: $_SESSION[Key::USER_ID],
url: $parsed->url,
title: $parsed->title,
updated_on: $parsed->updatedOn,
checked_on: Data::formatDate('now'));
}
/**
@@ -78,10 +76,10 @@ class Feed
if ($existing) {
if ($existing->published_on != $item->publishedOn
|| ($existing->updated_on != ($item->updatedOn ?? ''))) {
Patch::byId(Table::ITEM, $existing->id, $item->patchFields());
Item::update($existing->id, $item);
}
} else {
Document::insert(Table::ITEM, Item::fromFeedItem($feedId, $item));
Item::add($feedId, $item);
}
return ['ok' => true];
} catch (DocumentException $ex) {
@@ -113,7 +111,7 @@ class Feed
$sql .= ' AND ' . Query::whereByFields([$readField]);
} elseif (PURGE_TYPE == self::PURGE_BY_DAYS) {
$fields[] = Field::EQ('', Data::formatDate('-' . PURGE_NUMBER . ' day'), ':oldest');
$sql .= " AND date(coalesce(data->>'updated_on', data->>'published_on)) < date(:oldest)";
$sql .= " AND date(coalesce(data->>'updated_on', data->>'published_on')) < date(:oldest)";
} elseif (PURGE_TYPE == self::PURGE_BY_COUNT) {
$fields[] = Field::EQ('', PURGE_NUMBER, ':keep');
$id = Configuration::$idField;
@@ -189,7 +187,10 @@ class Feed
return ['error' => "Already subscribed to feed $feed->url"];
}
Document::insert(Table::FEED, self::fromParsed($feed));
Custom::nonQuery(<<<'SQL'
INSERT INTO feed (data)
VALUES (json_set(:data, '$.id', (SELECT coalesce(max(data->>'id'), 0) + 1 FROM feed)))
SQL, Parameters::json(':data', self::fromParsed($feed)));
$doc = Find::firstByFields(Table::FEED, $fields, static::class);
if (!$doc) return ['error' => 'Could not retrieve inserted feed'];

View File

@@ -2,6 +2,8 @@
namespace FeedReaderCentral;
use BitBadger\PDODocument\{Custom, DocumentException, Parameters, Patch};
/**
* An item from a feed
*/
@@ -47,21 +49,42 @@ class Item
}
/**
* Create an item document from a parsed feed item
* Add an item
*
* @param int $feedId The ID of the feed to which this item belongs
* @param ParsedItem $item The parsed feed item
* @return static The item document
* @param int $feedId The ID of the feed to which the item belongs
* @param ParsedItem $parsed The parsed item from the feed XML
* @throws DocumentException If any is encountered
*/
public static function fromFeedItem(int $feedId, ParsedItem $item): static
public static function add(int $feedId, ParsedItem $parsed): void
{
return new static(
feed_id: $feedId,
title: $item->title,
item_guid: $item->guid,
item_link: $item->link,
published_on: $item->publishedOn,
updated_on: $item->updatedOn,
content: $item->content);
Custom::nonQuery(<<<'SQL'
INSERT INTO item (data)
VALUES (json_set(:data, '$.id', (SELECT coalesce(max(data->>'id'), 0) + 1 FROM item)))
SQL, Parameters::json(':data', new static(
feed_id: $feedId,
title: $parsed->title,
item_guid: $parsed->guid,
item_link: $parsed->link,
published_on: $parsed->publishedOn,
updated_on: $parsed->updatedOn,
content: $parsed->content)));
}
/**
* Update an item
*
* @param int $id The ID of the item to be updated
* @param ParsedItem $parsed The parsed item from the feed XML
* @throws DocumentException If any is encountered
*/
public static function update(int $id, ParsedItem $parsed): void
{
Patch::byId(Table::ITEM, $id, [
'title' => $parsed->title,
'published_on' => $parsed->publishedOn,
'updated_on' => $parsed->updatedOn,
'content' => $parsed->content,
'is_read' => 0
]);
}
}

View File

@@ -9,39 +9,19 @@ use DOMNode;
*/
class ParsedItem
{
/** @var string The title of the feed item */
public string $title = '';
/** @var string The unique ID for the feed item */
public string $guid = '';
/** @var string The link to the original content */
public string $link = '';
/** @var string When this item was published */
public string $publishedOn = '';
/** @var ?string When this item was last updated */
public ?string $updatedOn = null;
/** @var string The content for the item */
public string $content = '';
/**
* Get the fields needed to update the item in the database
* Constructor
*
* @return array The fields needed tu update an item
* @param string $guid The unique ID for the feed item
* @param string $title The title of the feed item
* @param string $link The link to the original content
* @param string $publishedOn When this item was published
* @param string|null $updatedOn When this item was last updated
* @param string $content The content for the item
*/
public function patchFields(): array
{
return [
'title' => $this->title,
'published_on' => $this->publishedOn,
'updated_on' => $this->updatedOn,
'content' => $this->content,
'is_read' => 0
];
}
private function __construct(public string $guid = '', public string $title = '', public string $link = '',
public string $publishedOn = '', public ?string $updatedOn = null,
public string $content = '') { }
/**
* Construct a feed item from an Atom feed's `<entry>` tag
@@ -64,15 +44,13 @@ class ParsedItem
}
if ($link == '' && str_starts_with($guid, 'http')) $link = $guid;
$item = new static();
$item->guid = $guid;
$item->title = ParsedFeed::atomValue($node, 'title');
$item->link = $link;
$item->publishedOn = Data::formatDate(ParsedFeed::atomValue($node, 'published'));
$item->updatedOn = Data::formatDate(ParsedFeed::atomValue($node, 'updated'));
$item->content = ParsedFeed::atomValue($node, 'content');
return $item;
return new static(
guid: $guid,
title: ParsedFeed::atomValue($node, 'title'),
link: $link,
publishedOn: Data::formatDate(ParsedFeed::atomValue($node, 'published')),
updatedOn: Data::formatDate(ParsedFeed::atomValue($node, 'updated')),
content: ParsedFeed::atomValue($node, 'content'));
}
/**
@@ -87,16 +65,14 @@ class ParsedItem
$updNodes = $node->getElementsByTagNameNS(ParsedFeed::ATOM_NS, 'updated');
$encNodes = $node->getElementsByTagNameNS(ParsedFeed::CONTENT_NS, 'encoded');
$item = new static();
$item->guid = $itemGuid == 'guid not found' ? ParsedFeed::rssValue($node, 'link') : $itemGuid;
$item->title = ParsedFeed::rssValue($node, 'title');
$item->link = ParsedFeed::rssValue($node, 'link');
$item->publishedOn = Data::formatDate(ParsedFeed::rssValue($node, 'pubDate'));
$item->updatedOn = Data::formatDate($updNodes->length > 0 ? $updNodes->item(0)->textContent : null);
$item->content = $encNodes->length > 0
? $encNodes->item(0)->textContent
: ParsedFeed::rssValue($node, 'description');
return $item;
return new static(
guid: $itemGuid == 'guid not found' ? ParsedFeed::rssValue($node, 'link') : $itemGuid,
title: ParsedFeed::rssValue($node, 'title'),
link: ParsedFeed::rssValue($node, 'link'),
publishedOn: Data::formatDate(ParsedFeed::rssValue($node, 'pubDate')),
updatedOn: Data::formatDate($updNodes->length > 0 ? $updNodes->item(0)->textContent : null),
content: $encNodes->length > 0
? $encNodes->item(0)->textContent
: ParsedFeed::rssValue($node, 'description'));
}
}

View File

@@ -2,7 +2,7 @@
namespace FeedReaderCentral;
use BitBadger\PDODocument\{Custom, Document, DocumentException, Field, Find, Parameters, Query};
use BitBadger\PDODocument\{Custom, DocumentException, Field, Find, Parameters, Query};
use BitBadger\PDODocument\Mapper\ExistsMapper;
/**
@@ -40,7 +40,10 @@ class User
*/
public static function add(string $email, string $password): void
{
Document::insert(Table::USER, new User(email: $email, password: $password));
Custom::nonQuery(<<<'SQL'
INSERT INTO user (data)
VALUES (json_set(:data, '$.id', (SELECT coalesce(max(data->>'id'), 0) + 1 FROM user)))
SQL, Parameters::json(':data', new User(email: $email, password: $password)));
}
/**