diff --git a/lib/Database.php b/lib/Database.php index f8ef9da..e738dfd 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -948,7 +948,7 @@ class Database { return $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue(); } - public function articleMark(string $user, array $data, Context $context = null): bool { + public function articleMark(string $user, array $data, Context $context = null): int { if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } @@ -1008,7 +1008,7 @@ class Database { } // commit the transaction $tr->commit(); - return (bool) $out; + return $out; } public function articleStarred(string $user): array { @@ -1253,7 +1253,7 @@ class Database { } } - public function labelArticlesSet(string $user, $id, Context $context = null, bool $remove = false, bool $byName = false): bool { + public function labelArticlesSet(string $user, $id, Context $context = null, bool $remove = false, bool $byName = false): int { if (!Arsse::$user->authorize($user, __FUNCTION__)) { throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); } @@ -1291,7 +1291,7 @@ class Database { } // commit the transaction $tr->commit(); - return (bool) $out; + return $out; } protected function labelValidateId(string $user, $id, bool $byName, bool $checkDb = true, bool $subject = false): array { diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index 0d6726a..dc440de 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -75,6 +75,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { 'mode' => ValueInfo::T_INT, 'field' => ValueInfo::T_INT, 'data' => ValueInfo::T_STRING, + 'pref_name' => ValueInfo::T_STRING, ]; const FATAL_ERR = [ 'seq' => null, @@ -641,11 +642,20 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } public function opSetArticleLabel(array $data): array { - if (!$data['article_ids'] || !$data['label_id']) { - throw new Exception("INCORRECT_USAGE"); - } $label = $this->labelIn($data['label_id']); $articles = explode(",", $data['article_ids']); $assign = $data['assign'] ?? false; + $out = 0; + $in = array_chunk($data['article_ids'], 50); + for ($a = 0; $a < sizeof($in); $a++) { + // initialize the matching context + $c = new Context; + $c->articles($in[$a]); + try { + $out += Arsse::$db->labelArticlesSet(Arsse::$user->id, $label, $c, !$assign); + } catch (ExceptionInput $e) { + } + } + return ['status' => "OK", 'updated' => $out]; } } diff --git a/tests/REST/NextCloudNews/TestNCNV1_2.php b/tests/REST/NextCloudNews/TestNCNV1_2.php index 53aaba3..f72f10d 100644 --- a/tests/REST/NextCloudNews/TestNCNV1_2.php +++ b/tests/REST/NextCloudNews/TestNCNV1_2.php @@ -703,7 +703,7 @@ class TestNCNV1_2 extends Test\AbstractTest { public function testMarkAFolderRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(1)->latestEdition(2112))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->folder(42)->latestEdition(2112))->thenThrow(new ExceptionInput("idMissing")); // folder doesn't exist $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/folders/1/read", $in, 'application/json'))); @@ -718,7 +718,7 @@ class TestNCNV1_2 extends Test\AbstractTest { public function testMarkASubscriptionRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(1)->latestEdition(2112))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->subscription(42)->latestEdition(2112))->thenThrow(new ExceptionInput("idMissing")); // subscription doesn't exist $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/feeds/1/read", $in, 'application/json'))); @@ -733,7 +733,7 @@ class TestNCNV1_2 extends Test\AbstractTest { public function testMarkAllItemsRead() { $read = ['read' => true]; $in = json_encode(['newestItemId' => 2112]); - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->latestEdition(2112))->thenReturn(42); $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/read", $in, 'application/json'))); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/read?newestItemId=2112"))); @@ -747,13 +747,13 @@ class TestNCNV1_2 extends Test\AbstractTest { $unread = ['read' => false]; $star = ['starred' => true]; $unstar = ['starred' => false]; - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->edition(1))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->edition(1))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $read, (new Context)->edition(42))->thenThrow(new ExceptionInput("subjectMissing")); // edition doesn't exist doesn't exist - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unread, (new Context)->edition(2))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unread, (new Context)->edition(2))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unread, (new Context)->edition(47))->thenThrow(new ExceptionInput("subjectMissing")); // edition doesn't exist doesn't exist - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $star, (new Context)->article(3))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $star, (new Context)->article(3))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $star, (new Context)->article(2112))->thenThrow(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->article(4))->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->article(4))->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $unstar, (new Context)->article(1337))->thenThrow(new ExceptionInput("subjectMissing")); // article doesn't exist doesn't exist $exp = new Response(204); $this->assertEquals($exp, $this->h->dispatch(new Request("PUT", "/items/1/read"))); @@ -785,7 +785,7 @@ class TestNCNV1_2 extends Test\AbstractTest { $inStar[$a][$b] = ['feedId' => 2112, 'guidHash' => $inStar[$a][$b]]; } } - Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), $this->anything())->thenReturn(true); + Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), $this->anything())->thenReturn(42); Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->editions([]))->thenThrow(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->editions($in[1]))->thenThrow(new ExceptionInput("tooLong")); // data model function limited to 50 items for multiples Phake::when(Arsse::$db)->articleMark(Arsse::$user->id, $this->anything(), (new Context)->articles([]))->thenThrow(new ExceptionInput("tooShort")); // data model function requires one valid integer for multiples