mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 09:02:41 +00:00
Fix up the rest of the subscriptionUpdate function
This commit is contained in:
parent
cc2f3ea996
commit
7414d3844e
3 changed files with 29 additions and 96 deletions
|
@ -1211,21 +1211,21 @@ class Database {
|
||||||
/** Attempts to refresh a subscribed newsfeed, returning an indication of success
|
/** Attempts to refresh a subscribed newsfeed, returning an indication of success
|
||||||
*
|
*
|
||||||
* @param string|null $user The user whose subscribed newsfeed is to be updated; this may be null to facilitate refreshing feeds from the CLI
|
* @param string|null $user The user whose subscribed newsfeed is to be updated; this may be null to facilitate refreshing feeds from the CLI
|
||||||
* @param integer $id The numerical identifier of the subscription to refresh
|
* @param integer $subID The numerical identifier of the subscription to refresh
|
||||||
* @param boolean $throwError Whether to throw an exception on failure in addition to storing error information in the database
|
* @param boolean $throwError Whether to throw an exception on failure in addition to storing error information in the database
|
||||||
*/
|
*/
|
||||||
public function subscriptionUpdate(?string $user, $id, bool $throwError = false): bool {
|
public function subscriptionUpdate(?string $user, $subID, bool $throwError = false): bool {
|
||||||
// check to make sure the feed exists
|
// check to make sure the feed exists
|
||||||
if (!V::id($id)) {
|
if (!V::id($subID)) {
|
||||||
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id, 'type' => "int > 0"]);
|
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id, 'type' => "int > 0"]);
|
||||||
}
|
}
|
||||||
$f = $this->db->prepareArray(
|
$f = $this->db->prepareArray(
|
||||||
"SELECT
|
"SELECT
|
||||||
url, las_mod as modified, etag, err_count, scrape as scrapers
|
url, las_mod as modified, etag, err_count, scrape as scrapers, keep_rule, block_rule
|
||||||
FROM arsse_subscriptions
|
FROM arsse_subscriptions
|
||||||
where id = ?",
|
where id = ?",
|
||||||
["int"]
|
["int"]
|
||||||
)->run($id)->getRow();
|
)->run($subID)->getRow();
|
||||||
if (!$f) {
|
if (!$f) {
|
||||||
throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
|
throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "feed", 'id' => $id]);
|
||||||
}
|
}
|
||||||
|
@ -1235,10 +1235,10 @@ class Database {
|
||||||
// here. When an exception is thrown it should update the database with the
|
// here. When an exception is thrown it should update the database with the
|
||||||
// error instead of failing; if other exceptions are thrown, we should simply roll back
|
// error instead of failing; if other exceptions are thrown, we should simply roll back
|
||||||
try {
|
try {
|
||||||
$feed = new Feed((int) $id, $f['url'], (string) Date::transform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password'], $scrape);
|
$feed = new Feed((int) $subID, $f['url'], (string) Date::transform($f['modified'], "http", "sql"), $f['etag'], $f['username'], $f['password'], $scrape);
|
||||||
if (!$feed->modified) {
|
if (!$feed->modified) {
|
||||||
// if the feed hasn't changed, just compute the next fetch time and record it
|
// if the feed hasn't changed, just compute the next fetch time and record it
|
||||||
$this->db->prepare("UPDATE arsse_subscriptions SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id = ?", 'datetime', 'int')->run($feed->nextFetch, $id);
|
$this->db->prepare("UPDATE arsse_subscriptions SET updated = CURRENT_TIMESTAMP, next_fetch = ? WHERE id = ?", 'datetime', 'int')->run($feed->nextFetch, $subID);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (Feed\Exception $e) {
|
} catch (Feed\Exception $e) {
|
||||||
|
@ -1246,7 +1246,7 @@ class Database {
|
||||||
$this->db->prepareArray(
|
$this->db->prepareArray(
|
||||||
"UPDATE arsse_subscriptions SET updated = CURRENT_TIMESTAMP, next_fetch = ?, err_count = err_count + 1, err_msg = ? WHERE id = ?",
|
"UPDATE arsse_subscriptions SET updated = CURRENT_TIMESTAMP, next_fetch = ?, err_count = err_count + 1, err_msg = ? WHERE id = ?",
|
||||||
['datetime', 'str', 'int']
|
['datetime', 'str', 'int']
|
||||||
)->run(Feed::nextFetchOnError($f['err_count']), $e->getMessage(), $id);
|
)->run(Feed::nextFetchOnError($f['err_count']), $e->getMessage(), $subID);
|
||||||
if ($throwError) {
|
if ($throwError) {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
@ -1260,19 +1260,29 @@ class Database {
|
||||||
}
|
}
|
||||||
if (sizeof($feed->newItems)) {
|
if (sizeof($feed->newItems)) {
|
||||||
$qInsertArticle = $this->db->prepareArray(
|
$qInsertArticle = $this->db->prepareArray(
|
||||||
"INSERT INTO arsse_articles(url,title,author,published,edited,guid,content,url_title_hash,url_content_hash,title_content_hash,feed,content_scraped) values(?,?,?,?,?,?,?,?,?,?,?,?)",
|
"INSERT INTO arsse_articles(url,title,author,published,edited,guid,url_title_hash,url_content_hash,title_content_hash,subscription,hidden) values(?,?,?,?,?,?,?,?,?,?,?)",
|
||||||
["str", "str", "str", "datetime", "datetime", "str", "str", "str", "str", "str", "int", "str"]
|
["str", "str", "str", "datetime", "datetime", "str", "str", "str", "str", "int", "bool"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (sizeof($feed->changedItems)) {
|
if (sizeof($feed->changedItems)) {
|
||||||
$qDeleteEnclosures = $this->db->prepare("DELETE FROM arsse_enclosures WHERE article = ?", 'int');
|
$qDeleteEnclosures = $this->db->prepare("DELETE FROM arsse_enclosures WHERE article = ?", 'int');
|
||||||
$qDeleteCategories = $this->db->prepare("DELETE FROM arsse_categories WHERE article = ?", 'int');
|
$qDeleteCategories = $this->db->prepare("DELETE FROM arsse_categories WHERE article = ?", 'int');
|
||||||
$qClearReadMarks = $this->db->prepare("UPDATE arsse_marks SET \"read\" = 0, modified = CURRENT_TIMESTAMP WHERE article = ? and \"read\" = 1", 'int');
|
|
||||||
$qUpdateArticle = $this->db->prepareArray(
|
$qUpdateArticle = $this->db->prepareArray(
|
||||||
"UPDATE arsse_articles SET url = ?, title = ?, author = ?, published = ?, edited = ?, modified = CURRENT_TIMESTAMP, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ?, content_scraped = ? WHERE id = ?",
|
"UPDATE arsse_articles SET \"read\" = 0, hidden = ?, url = ?, title = ?, author = ?, published = ?, edited = ?, modified = CURRENT_TIMESTAMP, guid = ?, content = ?, url_title_hash = ?, url_content_hash = ?, title_content_hash = ?, content_scraped = ? WHERE id = ?",
|
||||||
["str", "str", "str", "datetime", "datetime", "str", "str", "str", "str", "str", "str", "int"]
|
["bool", "str", "str", "str", "datetime", "datetime", "str", "str", "str", "str", "str", "str", "int"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// prepare the keep and block rules
|
||||||
|
try {
|
||||||
|
$keep = Rule::prep($f['keep_rule'] ?? "");
|
||||||
|
} catch (RuleException $e) {
|
||||||
|
$keep = "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$block = Rule::prep($f['block_rule'] ?? "");
|
||||||
|
} catch (RuleException $e) {
|
||||||
|
$block = "";
|
||||||
|
}
|
||||||
// determine if the feed icon needs to be updated, and update it if appropriate
|
// determine if the feed icon needs to be updated, and update it if appropriate
|
||||||
$tr = $this->db->begin();
|
$tr = $this->db->begin();
|
||||||
$icon = null;
|
$icon = null;
|
||||||
|
@ -1299,12 +1309,11 @@ class Database {
|
||||||
$article->publishedDate,
|
$article->publishedDate,
|
||||||
$article->updatedDate,
|
$article->updatedDate,
|
||||||
$article->id,
|
$article->id,
|
||||||
$article->content,
|
|
||||||
$article->urlTitleHash,
|
$article->urlTitleHash,
|
||||||
$article->urlContentHash,
|
$article->urlContentHash,
|
||||||
$article->titleContentHash,
|
$article->titleContentHash,
|
||||||
$feedID,
|
$subID,
|
||||||
$article->scrapedContent ?? null
|
!Rule::apply($keep, $block, $article->title, $article->categories)
|
||||||
)->lastId();
|
)->lastId();
|
||||||
// note the new ID for later use
|
// note the new ID for later use
|
||||||
$articleMap[$k] = $articleID;
|
$articleMap[$k] = $articleID;
|
||||||
|
@ -1322,6 +1331,7 @@ class Database {
|
||||||
// next update existing artricles which have been edited
|
// next update existing artricles which have been edited
|
||||||
foreach ($feed->changedItems as $articleID => $article) {
|
foreach ($feed->changedItems as $articleID => $article) {
|
||||||
$qUpdateArticle->run(
|
$qUpdateArticle->run(
|
||||||
|
!Rule::apply($keep, $block, $article->title, $article->categories),
|
||||||
$article->url,
|
$article->url,
|
||||||
$article->title,
|
$article->title,
|
||||||
$article->author,
|
$article->author,
|
||||||
|
@ -1346,34 +1356,10 @@ class Database {
|
||||||
}
|
}
|
||||||
// assign a new edition ID to this version of the article
|
// assign a new edition ID to this version of the article
|
||||||
$qInsertEdition->run($articleID);
|
$qInsertEdition->run($articleID);
|
||||||
$qClearReadMarks->run($articleID);
|
|
||||||
}
|
|
||||||
// hide or unhide any filtered articles
|
|
||||||
foreach ($feed->filteredItems as $user => $filterData) {
|
|
||||||
$hide = [];
|
|
||||||
$unhide = [];
|
|
||||||
foreach ($filterData['new'] as $index => $keep) {
|
|
||||||
if (!$keep) {
|
|
||||||
$hide[] = $articleMap[$index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($filterData['changed'] as $article => $keep) {
|
|
||||||
if (!$keep) {
|
|
||||||
$hide[] = $article;
|
|
||||||
} else {
|
|
||||||
$unhide[] = $article;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($hide) {
|
|
||||||
$this->articleMark($user, ['hidden' => true], (new Context)->articles($hide), false);
|
|
||||||
}
|
|
||||||
if ($unhide) {
|
|
||||||
$this->articleMark($user, ['hidden' => false], (new Context)->articles($unhide), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// lastly update the feed database itself with updated information.
|
// lastly update the feed database itself with updated information.
|
||||||
$this->db->prepareArray(
|
$this->db->prepareArray(
|
||||||
"UPDATE arsse_feeds SET title = ?, source = ?, updated = CURRENT_TIMESTAMP, modified = ?, etag = ?, err_count = 0, err_msg = '', next_fetch = ?, size = ?, icon = ? WHERE id = ?",
|
"UPDATE arsse_subscriptions SET feed_title = ?, source = ?, updated = CURRENT_TIMESTAMP, last_mod = ?, etag = ?, err_count = 0, err_msg = '', next_fetch = ?, size = ?, icon = ? WHERE id = ?",
|
||||||
["str", "str", "datetime", "strict str", "datetime", "int", "int", "int"]
|
["str", "str", "datetime", "strict str", "datetime", "int", "int", "int"]
|
||||||
)->run(
|
)->run(
|
||||||
$feed->data->title,
|
$feed->data->title,
|
||||||
|
@ -1383,7 +1369,7 @@ class Database {
|
||||||
$feed->nextFetch,
|
$feed->nextFetch,
|
||||||
sizeof($feed->data->items),
|
sizeof($feed->data->items),
|
||||||
$icon,
|
$icon,
|
||||||
$feedID
|
$subID
|
||||||
);
|
);
|
||||||
$tr->commit();
|
$tr->commit();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1410,30 +1396,6 @@ class Database {
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieves the set of filters users have applied to a given feed
|
|
||||||
*
|
|
||||||
* The result is an associative array whose keys are usernames, values
|
|
||||||
* being an array in turn with the following keys:
|
|
||||||
*
|
|
||||||
* - "keep": The "keep" rule as a prepared pattern; any articles which fail to match this rule are hidden
|
|
||||||
* - "block": The block rule as a prepared pattern; any articles which match this rule are hidden
|
|
||||||
*/
|
|
||||||
public function feedRulesGet(int $feedID): array {
|
|
||||||
$out = [];
|
|
||||||
$result = $this->db->prepare("SELECT owner, coalesce(keep_rule, '') as keep, coalesce(block_rule, '') as block from arsse_subscriptions where feed = ? and (coalesce(keep_rule, '') || coalesce(block_rule, '')) <> '' order by owner", "int")->run($feedID);
|
|
||||||
foreach ($result as $row) {
|
|
||||||
try {
|
|
||||||
$keep = Rule::prep($row['keep']);
|
|
||||||
$block = Rule::prep($row['block']);
|
|
||||||
} catch (RuleException $e) {
|
|
||||||
// invalid rules should not normally appear in the database, but it's possible
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$out[$row['owner']] = ['keep' => $keep, 'block' => $block];
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieves various identifiers for the latest $count articles in the given newsfeed. The identifiers are:
|
/** Retrieves various identifiers for the latest $count articles in the given newsfeed. The identifiers are:
|
||||||
*
|
*
|
||||||
* - "id": The database record key for the article
|
* - "id": The database record key for the article
|
||||||
|
|
14
lib/Feed.php
14
lib/Feed.php
|
@ -452,18 +452,4 @@ class Feed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function computeFilterRules(int $feedID): void {
|
|
||||||
$rules = Arsse::$db->feedRulesGet($feedID);
|
|
||||||
foreach ($rules as $user => $r) {
|
|
||||||
$stats = ['new' => [], 'changed' => []];
|
|
||||||
foreach ($this->newItems as $index => $item) {
|
|
||||||
$stats['new'][$index] = Rule::apply($r['keep'], $r['block'], $item->title, $item->categories);
|
|
||||||
}
|
|
||||||
foreach ($this->changedItems as $index => $item) {
|
|
||||||
$stats['changed'][$index] = Rule::apply($r['keep'], $r['block'], $item->title, $item->categories);
|
|
||||||
}
|
|
||||||
$this->filteredItems[$user] = $stats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,21 +147,6 @@ trait SeriesFeed {
|
||||||
$this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned
|
$this->assertResult([['id' => 1]], Arsse::$db->feedMatchIds(1, ['e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda'])); // this ID appears in both feed 1 and feed 2; only one result should be returned
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider provideFilterRules */
|
|
||||||
public function testGetRules(int $in, array $exp): void {
|
|
||||||
$this->assertSame($exp, Arsse::$db->feedRulesGet($in));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function provideFilterRules(): iterable {
|
|
||||||
return [
|
|
||||||
[1, ['jane.doe@example.com' => ['keep' => "`^(?i)[a-z]+`u", 'block' => "`3|6`u"], 'john.doe@example.com' => ['keep' => "", 'block' => "`^Sport$`u"]]],
|
|
||||||
[2, []],
|
|
||||||
[3, ['john.doe@example.com' => ['keep' => '`\w+`u', 'block' => ""]]],
|
|
||||||
[4, []],
|
|
||||||
[5, ['john.doe@example.com' => ['keep' => "", 'block' => "`and/or`u"]]],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testUpdateAFeed(): void {
|
public function testUpdateAFeed(): void {
|
||||||
// update a valid feed with both new and changed items
|
// update a valid feed with both new and changed items
|
||||||
Arsse::$db->feedUpdate(1);
|
Arsse::$db->feedUpdate(1);
|
||||||
|
|
Loading…
Reference in a new issue