Browse Source

Implement the TTRSS getLabels operation; fixes #89

microsub
J. King 7 years ago
parent
commit
fbbf751214
  1. 36
      lib/Database.php
  2. 21
      lib/REST/TinyTinyRSS/API.php
  3. 55
      tests/REST/TinyTinyRSS/TestTinyTinyAPI.php
  4. 15
      tests/lib/Database/SeriesArticle.php

36
lib/Database.php

@ -937,6 +937,17 @@ class Database {
return $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues());
}
public function articleCount(string $user, Context $context = null): int {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
}
$context = $context ?? new Context;
$q = $this->articleQuery($user, $context);
$q->pushCTE("selected_articles");
$q->setBody("SELECT count(*) from selected_articles");
return $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue();
}
public function articleMark(string $user, array $data, Context $context = null): bool {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
@ -1000,17 +1011,6 @@ class Database {
return (bool) $out;
}
public function articleCount(string $user, Context $context = null): int {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
}
$context = $context ?? new Context;
$q = $this->articleQuery($user, $context);
$q->pushCTE("selected_articles");
$q->setBody("SELECT count(*) from selected_articles");
return $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->getValue();
}
public function articleStarred(string $user): array {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
@ -1026,6 +1026,20 @@ class Database {
)->run($user)->getRow();
}
public function articleLabelsGet(string $user, $id, bool $byName = false): array {
if (!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
}
$id = $this->articleValidateId($user, $id)['article'];
$out = $this->db->prepare("SELECT id,name from arsse_labels where owner is ? and exists(select id from arsse_label_members where article is ? and label is arsse_labels.id and assigned is 1)", "str", "int")->run($user, $id)->getAll();
if (!$out) {
return $out;
} else {
// flatten the result to return just the label ID or name
return array_column($out, !$byName ? "id" : "name");
}
}
public function articleCleanup(): bool {
$query = $this->db->prepare(
"WITH target_feed(id,subs) as (".

21
lib/REST/TinyTinyRSS/API.php

@ -553,6 +553,27 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler {
return ($id * -1 - self::LABEL_OFFSET);
}
public function opGetLabels(array $data): array {
// this function doesn't complain about invalid article IDs
$article = (isset($data['article_id']) && ValueInfo::id($data['article_id'])) ? (int) $data['article_id'] : 0;
try {
$list = $article ? Arsse::$db->articleLabelsGet(Arsse::$user->id, $article) : [];
} catch (ExceptionInput $e) {
$list = [];
}
$out = [];
foreach (Arsse::$db->labelList(Arsse::$user->id) as $l) {
$out[] = [
'id' => $this->labelOut($l['id']),
'caption' => $l['name'],
'fg_color' => "",
'bg_color' => "",
'checked' => in_array($l['id'], $list),
];
}
return $out;
}
public function opAddLabel(array $data) {
$in = [
'name' => isset($data['caption']) ? $data['caption'] : "",

55
tests/REST/TinyTinyRSS/TestTinyTinyAPI.php

@ -38,13 +38,13 @@ class TestTinyTinyAPI extends Test\AbstractTest {
['id' => 4, 'folder' => 6, 'top_folder' => 3, 'unread' => 6, 'updated' => "2017-10-09 15:58:34", 'favicon' => 'http://example.com/4.png'],
];
protected $labels = [
['id' => 5, 'articles' => 0, 'read' => 0],
['id' => 3, 'articles' => 100, 'read' => 94],
['id' => 1, 'articles' => 2, 'read' => 0],
['id' => 5, 'articles' => 0, 'read' => 0, 'name' => "Interesting"],
['id' => 3, 'articles' => 100, 'read' => 94, 'name' => "Fascinating"],
['id' => 1, 'articles' => 2, 'read' => 0, 'name' => "Logical"],
];
protected $usedLabels = [
['id' => 3, 'articles' => 100, 'read' => 94],
['id' => 1, 'articles' => 2, 'read' => 0],
['id' => 3, 'articles' => 100, 'read' => 94, 'name' => "Fascinating"],
['id' => 1, 'articles' => 2, 'read' => 0, 'name' => "Logical"],
];
protected function respGood($content = null, $seq = 0): Response {
@ -768,4 +768,49 @@ class TestTinyTinyAPI extends Test\AbstractTest {
];
$this->assertResponse($this->respGood($exp), $this->h->dispatch(new Request("POST", "", json_encode($in))));
}
public function testRetrieveLabelList() {
$in = [
['op' => "getLabels", 'sid' => "PriestsOfSyrinx"],
['op' => "getLabels", 'sid' => "PriestsOfSyrinx", 'article_id' => 1],
['op' => "getLabels", 'sid' => "PriestsOfSyrinx", 'article_id' => 2],
['op' => "getLabels", 'sid' => "PriestsOfSyrinx", 'article_id' => 3],
['op' => "getLabels", 'sid' => "PriestsOfSyrinx", 'article_id' => 4],
];
Phake::when(Arsse::$db)->labelList($this->anything())->thenReturn(new Result($this->labels));
Phake::when(Arsse::$db)->articleLabelsGet($this->anything(), 1)->thenReturn([1,3]);
Phake::when(Arsse::$db)->articleLabelsGet($this->anything(), 2)->thenReturn([3]);
Phake::when(Arsse::$db)->articleLabelsGet($this->anything(), 3)->thenReturn([]);
Phake::when(Arsse::$db)->articleLabelsGet($this->anything(), 4)->thenThrow(new ExceptionInput("idMissing"));
$exp = [
[
['id' => -1025, 'caption' => "Logical", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1027, 'caption' => "Fascinating", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1029, 'caption' => "Interesting", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
],
[
['id' => -1025, 'caption' => "Logical", 'fg_color' => "", 'bg_color' => "", 'checked' => true],
['id' => -1027, 'caption' => "Fascinating", 'fg_color' => "", 'bg_color' => "", 'checked' => true],
['id' => -1029, 'caption' => "Interesting", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
],
[
['id' => -1025, 'caption' => "Logical", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1027, 'caption' => "Fascinating", 'fg_color' => "", 'bg_color' => "", 'checked' => true],
['id' => -1029, 'caption' => "Interesting", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
],
[
['id' => -1025, 'caption' => "Logical", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1027, 'caption' => "Fascinating", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1029, 'caption' => "Interesting", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
],
[
['id' => -1025, 'caption' => "Logical", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1027, 'caption' => "Fascinating", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
['id' => -1029, 'caption' => "Interesting", 'fg_color' => "", 'bg_color' => "", 'checked' => false],
],
];
for ($a = 0; $a < sizeof($in); $a++) {
$this->assertResponse($this->respGood($exp[$a]), $this->h->dispatch(new Request("POST", "", json_encode($in[$a]))), "Test $a failed");
}
}
}

15
tests/lib/Database/SeriesArticle.php

@ -805,4 +805,19 @@ trait SeriesArticle {
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
Arsse::$db->editionLatest($this->user);
}
public function testListTheLabelsOfAnArticle() {
$this->assertEquals([2,1], Arsse::$db->articleLabelsGet("john.doe@example.com", 1));
$this->assertEquals([2], Arsse::$db->articleLabelsGet("john.doe@example.com", 5));
$this->assertEquals([], Arsse::$db->articleLabelsGet("john.doe@example.com", 2));
$this->assertEquals(["Fascinating","Interesting"], Arsse::$db->articleLabelsGet("john.doe@example.com", 1, true));
$this->assertEquals(["Fascinating"], Arsse::$db->articleLabelsGet("john.doe@example.com", 5, true));
$this->assertEquals([], Arsse::$db->articleLabelsGet("john.doe@example.com", 2, true));
}
public function testListTheLabelsOfAnArticleWithoutAuthority() {
Phake::when(Arsse::$user)->authorize->thenReturn(false);
$this->assertException("notAuthorized", "User", "ExceptionAuthz");
Arsse::$db->articleLabelsGet("john.doe@example.com", 1);
}
}

Loading…
Cancel
Save