WIP on document conversion

This commit is contained in:
2024-05-30 21:58:54 -04:00
parent cfa56ec44f
commit df20936af2
34 changed files with 674 additions and 204 deletions

View File

@@ -1,4 +1,24 @@
<?php
namespace FeedReaderCentral;
use BitBadger\Documents\Field;
use BitBadger\Documents\Query;
use BitBadger\Documents\SQLite\Custom;
use BitBadger\Documents\SQLite\Document;
use BitBadger\Documents\SQLite\Find;
use BitBadger\Documents\SQLite\Patch;
use BitBadger\Documents\SQLite\Results;
use DateTimeInterface;
use DOMDocument;
use DOMElement;
use DOMException;
use DOMNode;
use Exception;
use FeedReaderCentral\Domain\Feed as FeedDocument;
use FeedReaderCentral\Domain\Item;
use FeedReaderCentral\Domain\Table;
use SQLite3;
use SQLite3Result;
/**
* Feed retrieval, parsing, and manipulation
@@ -110,7 +130,7 @@ class Feed {
}
}
$feed = new Feed();
$feed = new static();
$feed->title = self::rssValue($channel, 'title');
$feed->url = $url;
$feed->updatedOn = Data::formatDate($updatedOn);
@@ -267,21 +287,23 @@ class Feed {
* @return bool|SQLite3Result The result if the update is successful, false if it failed
*/
private static function updateItem(int $itemId, FeedItem $item, SQLite3 $db): bool|SQLite3Result {
$query = $db->prepare(<<<'SQL'
UPDATE item
SET title = :title,
published_on = :published,
updated_on = :updated,
content = :content,
is_read = 0
WHERE id = :id
SQL);
$query->bindValue(':title', $item->title);
$query->bindValue(':published', $item->publishedOn);
$query->bindValue(':updated', $item->updatedOn);
$query->bindValue(':content', $item->content);
$query->bindValue(':id', $itemId);
return $query->execute();
Patch::byId(Table::ITEM, $itemId, $item->patchFields(), $db);
// $query = $db->prepare(<<<'SQL'
// UPDATE item
// SET title = :title,
// published_on = :published,
// updated_on = :updated,
// content = :content,
// is_read = 0
// WHERE id = :id
// SQL);
// $query->bindValue(':title', $item->title);
// $query->bindValue(':published', $item->publishedOn);
// $query->bindValue(':updated', $item->updatedOn);
// $query->bindValue(':content', $item->content);
// $query->bindValue(':id', $itemId);
// return $query->execute();
return true;
}
/**
@@ -293,21 +315,23 @@ class Feed {
* @return bool|SQLite3Result The result if the update is successful, false if it failed
*/
private static function addItem(int $feedId, FeedItem $item, SQLite3 $db): bool|SQLite3Result {
$query = $db->prepare(<<<'SQL'
INSERT INTO item (
feed_id, item_guid, item_link, title, published_on, updated_on, content
) VALUES (
:feed, :guid, :link, :title, :published, :updated, :content
)
SQL);
$query->bindValue(':feed', $feedId);
$query->bindValue(':guid', $item->guid);
$query->bindValue(':link', $item->link);
$query->bindValue(':title', $item->title);
$query->bindValue(':published', $item->publishedOn);
$query->bindValue(':updated', $item->updatedOn);
$query->bindValue(':content', $item->content);
return $query->execute();
Document::insert(Table::ITEM, Item::fromFeedItem($feedId, $item), $db);
// $query = $db->prepare(<<<'SQL'
// INSERT INTO item (
// feed_id, item_guid, item_link, title, published_on, updated_on, content
// ) VALUES (
// :feed, :guid, :link, :title, :published, :updated, :content
// )
// SQL);
// $query->bindValue(':feed', $feedId);
// $query->bindValue(':guid', $item->guid);
// $query->bindValue(':link', $item->link);
// $query->bindValue(':title', $item->title);
// $query->bindValue(':published', $item->publishedOn);
// $query->bindValue(':updated', $item->updatedOn);
// $query->bindValue(':content', $item->content);
// return $query->execute();
return true;
}
/**
@@ -321,6 +345,7 @@ class Feed {
public static function updateItems(int $feedId, Feed $feed, DateTimeInterface $lastChecked, SQLite3 $db): array {
$results =
array_map(function ($item) use ($db, $feedId) {
// TODO: convert this query
$existsQuery = $db->prepare(
'SELECT id, published_on, updated_on FROM item WHERE feed_id = :feed AND item_guid = :guid');
$existsQuery->bindValue(':feed', $feedId);
@@ -357,6 +382,7 @@ class Feed {
}
try {
// TODO: convert this query
$sql = match (PURGE_TYPE) {
self::PURGE_READ => 'AND is_read = 1',
self::PURGE_BY_DAYS => 'AND date(coalesce(updated_on, published_on)) < date(:oldest)',
@@ -401,21 +427,24 @@ class Feed {
$itemUpdate = self::updateItems($feedId, $feed, $lastChecked, $db);
if (key_exists('error', $itemUpdate)) return $itemUpdate;
$urlUpdate = $url == $feed->url ? '' : ', url = :url';
$feedUpdate = $db->prepare(<<<SQL
UPDATE feed
SET title = :title,
updated_on = :updated,
checked_on = :checked
$urlUpdate
WHERE id = :id
SQL);
$feedUpdate->bindValue(':title', $feed->title);
$feedUpdate->bindValue(':updated', $feed->updatedOn);
$feedUpdate->bindValue(':checked', Data::formatDate('now'));
$feedUpdate->bindValue(':id', $feedId);
if ($urlUpdate != '') $feedUpdate->bindValue(':url', $feed->url);
if (!$feedUpdate->execute()) return Data::error($db);
$patch = ['title' => $feed->title, 'updated_on' => $feed->updatedOn, 'checked_on' => Data::formatDate('now')];
if ($url == $feed->url) $patch['url'] = $feed->url;
Patch::byId(Table::FEED, $feedId, $patch, $db);
// $urlUpdate = $url == $feed->url ? '' : ', url = :url';
// $feedUpdate = $db->prepare(<<<SQL
// UPDATE feed
// SET title = :title,
// updated_on = :updated,
// checked_on = :checked
// $urlUpdate
// WHERE id = :id
// SQL);
// $feedUpdate->bindValue(':title', $feed->title);
// $feedUpdate->bindValue(':updated', $feed->updatedOn);
// $feedUpdate->bindValue(':checked', Data::formatDate('now'));
// $feedUpdate->bindValue(':id', $feedId);
// if ($urlUpdate != '') $feedUpdate->bindValue(':url', $feed->url);
// if (!$feedUpdate->execute()) return Data::error($db);
return PURGE_TYPE == self::PURGE_NONE ? ['ok' => true] : self::purgeItems($feedId, $db);
}
@@ -432,49 +461,55 @@ class Feed {
$feed = $feedExtract['ok'];
$existsQuery = $db->prepare('SELECT COUNT(*) FROM feed WHERE user_id = :user AND url = :url');
$existsQuery->bindValue(':user', $_SESSION[Key::USER_ID]);
$existsQuery->bindValue(':url', $feed->url);
if (!($exists = $existsQuery->execute())) return Data::error($db);
if ($exists->fetchArray(SQLITE3_NUM)[0] > 0) return ['error' => "Already subscribed to feed $feed->url"];
$whereUserAndUrl = ' WHERE ' . Query::whereByField(Field::EQ('user_id', ''), '@user')
. ' AND ' . Query::whereByField(Field::EQ('url', ''), '@url');
$userAndUrlParams = ['@user' => $_SESSION[Key::USER_ID], '@url' => $feed->url];
if (Custom::scalar('SELECT EXISTS (SELECT 1 FROM ' . Table::FEED . $whereUserAndUrl . ')', $userAndUrlParams,
Results::toExists(...), $db)) {
return ['error' => "Already subscribed to feed $feed->url"];
}
$query = $db->prepare(<<<'SQL'
INSERT INTO feed (
user_id, url, title, updated_on, checked_on
) VALUES (
:user, :url, :title, :updated, :checked
)
SQL);
$query->bindValue(':user', $_SESSION[Key::USER_ID]);
$query->bindValue(':url', $feed->url);
$query->bindValue(':title', $feed->title);
$query->bindValue(':updated', $feed->updatedOn);
$query->bindValue(':checked', Data::formatDate('now'));
if (!$query->execute()) return Data::error($db);
Document::insert(Table::FEED, FeedDocument::fromParsed($feed), $db);
// $query = $db->prepare(<<<'SQL'
// INSERT INTO feed (
// user_id, url, title, updated_on, checked_on
// ) VALUES (
// :user, :url, :title, :updated, :checked
// )
// SQL);
// $query->bindValue(':user', $_SESSION[Key::USER_ID]);
// $query->bindValue(':url', $feed->url);
// $query->bindValue(':title', $feed->title);
// $query->bindValue(':updated', $feed->updatedOn);
// $query->bindValue(':checked', Data::formatDate('now'));
// if (!$query->execute()) return Data::error($db);
$doc = Custom::single(Query::selectFromTable(Table::FEED) . $whereUserAndUrl, $userAndUrlParams,
Results::fromData(...), Domain\Feed::class, $db);
if (!$doc) return ['error' => 'Could not retrieve inserted feed'];
$feedId = $db->lastInsertRowID();
$result = self::updateItems($feedId, $feed, date_create_immutable(WWW_EPOCH), $db);
$result = self::updateItems($doc->id, $feed, date_create_immutable(WWW_EPOCH), $db);
if (key_exists('error', $result)) return $result;
return ['ok' => $feedId];
return ['ok' => $doc->id];
}
/**
* Update an RSS feed
*
* @param array $existing The existing RSS feed
* @param FeedDocument $existing The existing RSS feed
* @param string $url The URL with which the existing feed should be modified
* @param SQLite3 $db The database connection on which to execute the update
* @return bool[]|string[] [ 'ok' => true ] if successful, [ 'error' => message ] if not
*/
public static function update(array $existing, string $url, SQLite3 $db): array {
public static function update(FeedDocument $existing, string $url, SQLite3 $db): array {
// TODO: convert this query (need to make Query\Patch::update visible)
$query = $db->prepare('UPDATE feed SET url = :url WHERE id = :id AND user_id = :user');
$query->bindValue(':url', $url);
$query->bindValue(':id', $existing['id']);
$query->bindValue(':id', $existing->id);
$query->bindValue(':user', $_SESSION[Key::USER_ID]);
if (!$query->execute()) return Data::error($db);
return self::refreshFeed($existing['id'], $url, $db);
return self::refreshFeed($existing->id, $url, $db);
}
/**
@@ -520,12 +555,14 @@ class Feed {
*
* @param int $feedId The ID of the feed to retrieve
* @param SQLite3 $db A database connection to use to retrieve the feed
* @return array|bool The data for the feed if found, false if not found
* @return FeedDocument|false The data for the feed if found, false if not found
*/
public static function retrieveById(int $feedId, SQLite3 $db): array|bool {
$query = $db->prepare('SELECT * FROM feed WHERE id = :id AND user_id = :user');
$query->bindValue(':id', $feedId);
$query->bindValue(':user', $_SESSION[Key::USER_ID]);
return ($result = $query->execute()) ? $result->fetchArray(SQLITE3_ASSOC) : false;
public static function retrieveById(int $feedId, SQLite3 $db): FeedDocument|false {
$doc = Find::byId(Table::FEED, $feedId, FeedDocument::class, $db);
return $doc && $doc->user_id == $_SESSION[Key::USER_ID] ? $doc : false;
// $query = $db->prepare('SELECT * FROM feed WHERE id = :id AND user_id = :user');
// $query->bindValue(':id', $feedId);
// $query->bindValue(':user', $_SESSION[Key::USER_ID]);
// return ($result = $query->execute()) ? $result->fetchArray(SQLITE3_ASSOC) : false;
}
}