// if the insertion fails, throw if the delete flag is not set, otherwise return the existing ID
$id = (int) $this->db->prepare("SELECT id from arsse_subscriptions where owner = ? and url = ? and deleted = 1")->run($user, $url)->getValue();
$id = (int) $this->db->prepare("SELECT id from arsse_subscriptions where owner = ? and url = ? and deleted = 1", "str", "str")->run($user, $url)->getValue();
if (!$id) {
throw $e;
} else {
@ -857,7 +857,7 @@ class Database {
*/
public function subscriptionReveal(string $user, int ...$id): void {
$this->db->prepare("UPDATE arsse_subscriptions set deleted = 0, modified = CURRENT_TIMESTAMP where deleted = 1 and user = ? and id in ($inClause)", "str", $inTypes)->run($user, $inValues);
$this->db->prepare("UPDATE arsse_subscriptions set deleted = 0, modified = CURRENT_TIMESTAMP where deleted = 1 and owner = ? and id in ($inClause)", "str", $inTypes)->run($user, $inValues);
}
/** Lists a user's subscriptions, returning various data
@ -865,7 +865,7 @@ class Database {
* Each record has the following keys:
*
* - "id": The numeric identifier of the subscription
* - "feed": The numeric identifier of the underlying newsfeed
* - "feed": The numeric identifier of the subscription (historical)
* - "url": The URL of the newsfeed, after discovery and HTTP redirects
* - "title": The title of the newsfeed
* - "source": The URL of the source of the newsfeed i.e. its parent Web site
// if an ID is specified, add a suitable WHERE condition and bindings
// this condition facilitates the implementation of subscriptionPropertiesGet, which would otherwise have to duplicate the complex query; it takes precedence over a specified folder
@ -978,6 +978,7 @@ class Database {
[$folder]
);
$q->setWhere("owner = ?", "str", $user);
$q->setWhere("deleted = 0");
if ($folder) {
// if the specified folder exists, add a suitable WHERE condition
$q->setWhere("folder in (select folder from folders)");
public function subscriptionIcon(?string $user, int $id, bool $includeData = true): ?array {
$data = $includeData ? "i.data" : "null as data";
$q = new Query("SELECT i.id, i.url, i.type, $data from arsse_subscriptions as s join arsse_feeds as f on s.feed = f.id left join arsse_icons as i on f.icon = i.id");
$q = new Query("SELECT i.id, i.url, i.type, $data from arsse_subscriptions as s left join arsse_icons as i on s.icon = i.id");
$q->setWhere("s.id = ?", "int", $id);
$q->setWhere("s.deleted = 0");
if (isset($user)) {
$q->setWhere("s.owner = ?", "str", $user);
}
@ -1135,10 +1137,11 @@ class Database {
/** Returns the time at which any of a user's subscriptions (or a specific subscription) was last refreshed, as a DateTimeImmutable object */
public function subscriptionRefreshed(string $user, int $id = null): ?\DateTimeImmutable {
$q = new Query("SELECT max(arsse_feeds.updated) from arsse_feeds join arsse_subscriptions on arsse_subscriptions.feed = arsse_feeds.id");
protected function subscriptionRulesApply(string $user, int $id): void {
// start a transaction for read isolation
$tr = $this->begin();
$sub = $this->db->prepare("SELECT feed, coalesce(keep_rule, '') as keep, coalesce(block_rule, '') as block from arsse_subscriptions where owner = ? and id = ?", "str", "int")->run($user, $id)->getRow();
$sub = $this->db->prepare("SELECT id, coalesce(keep_rule, '') as keep, coalesce(block_rule, '') as block from arsse_subscriptions where owner = ? and id = ?", "str", "int")->run($user, $id)->getRow();
// invalid rules should not normally appear in the database, but it's possible
// in this case we should halt evaluation and just leave things as they are
return; // @codeCoverageIgnore
}
$articles = $this->db->prepare("SELECT id, title, coalesce(categories, 0) as categories from arsse_articles as a left join (select article, count(*) as categories from arsse_categories group by article) as c on a.id = c.article where a.feed = ?", "int")->run($feed)->getAll();
$articles = $this->db->prepare("SELECT id, title, coalesce(categories, 0) as categories from arsse_articles as a left join (select article, count(*) as categories from arsse_categories group by article) as c on a.id = c.article where a.subscription = ?", "int")->run($id)->getAll();
$hide = [];
$unhide = [];
foreach ($articles as $r) {
@ -1196,12 +1199,14 @@ class Database {
* @param string $user The user who owns the subscription to be validated
* @param integer $id The identifier of the subscription to validate
* @param boolean $subject Whether the subscription is the subject (true) rather than the object (false) of the operation being performed; this only affects the semantics of the error message if validation fails
* @param boolean $acceptDeleted Whether to consider a soft-deleted subscription as valid
$out = $this->db->prepare("SELECT id,feed from arsse_subscriptions where id = ? and owner = ?", "int", "str")->run($id, $user)->getRow();
$deleted = $acceptDeleted ? "deleted" : "0";
$out = $this->db->prepare("SELECT id, id from arsse_subscriptions where id = ? and owner = ? and deleted = $deleted", "int", "str")->run($id, $user)->getRow();
@ -535,7 +535,6 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase {
if (static::$stringOutput ?? false) {
$expected = $this->stringify($expected);
}
$this->assertCount(sizeof($expected), $data, "Number of result rows (".sizeof($data).") differs from number of expected rows (".sizeof($expected).")");