diff options
| author | 2018-09-29 20:47:17 +0200 | |
|---|---|---|
| committer | 2018-09-29 20:47:17 +0200 | |
| commit | 8ee8a573f1f7e9cc45f9b3c46627d15670f14f3a (patch) | |
| tree | 14200758ab43e4031f60b46b8c6e9018b43e53af /p/api | |
| parent | 3ae1b57c9d2e23157be54e8fe9865b85872ff9e7 (diff) | |
Custom labels (#2027)
* First draft of custom tags
https://github.com/FreshRSS/FreshRSS/issues/928
https://github.com/FreshRSS/FreshRSS/issues/1367
* SMALLINT to BIGINT for id_entry
And uppercase SQL types
* Fix layout for unreads
* Start UI menu
* Change menu order
* Clean database helpers
https://github.com/FreshRSS/FreshRSS/pull/2027#discussion_r217971535
* Travis rules do not understand PostgreSQL constants
Grrr
* Tag controller + UI
* Add column attributes to tags
* Use only favicon for now, for label
* Fix styling for different themes
* Constant for maximum InnoDB index length in Unicode
https://github.com/FreshRSS/FreshRSS/pull/2027#discussion_r219052200
(I would have personnally prefered keeping the readability of a real
value instead of a constant, in this case of many SQL fields)
* Use FreshRSS_Factory::createCategoryDao
* Add view of all articles containing any tag
* Fix search in tags
* Mark as read tags
* Partial auto-update unread tags
* More auto update tag unreads
* Add tag deletion
* Do not purge tagged articles
* Minor comment
* Fix SQLite and UI bug
* Google Reader API support for user tags
Add SQL check that tag names must be distinct from category names
* whitespace
* Add missing API for EasyRSS
* Compatibility SQLite
Problematic parentheses
* Add SQL DISTINCT for cases with multiple tags
* Fix for PostgreSQL
PostgreSQL needs some additional type hint to avoid "could not determine
data type of parameter $1"
http://www.postgresql-archive.org/Could-not-determine-data-type-of-parameter-1-tp2171092p2171094.html
Diffstat (limited to 'p/api')
| -rw-r--r-- | p/api/fever.php | 4 | ||||
| -rw-r--r-- | p/api/greader.php | 167 |
2 files changed, 147 insertions, 24 deletions
diff --git a/p/api/fever.php b/p/api/fever.php index abbade768..bf38dc662 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -312,7 +312,7 @@ class FeverAPI { $groups = array(); - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $categories = $categoryDAO->listCategories(false, false); /** @var FreshRSS_Category $category */ @@ -457,7 +457,7 @@ class FeverAPI } if (isset($_REQUEST['group_ids'])) { - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $group_ids = explode(',', $_REQUEST['group_ids']); foreach ($group_ids as $id) { /** @var FreshRSS_Category $category */ diff --git a/p/api/greader.php b/p/api/greader.php index f5b84f7a1..27362082e 100644 --- a/p/api/greader.php +++ b/p/api/greader.php @@ -42,6 +42,12 @@ if (PHP_INT_SIZE < 8) { //32-bit } } +if (version_compare(PHP_VERSION, '5.4.0') >= 0) { + define('JSON_OPTIONS', JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); +} else { + define('JSON_OPTIONS', 0); +} + function headerVariable($headerName, $varName) { $header = ''; $upName = 'HTTP_' . strtoupper($headerName); @@ -234,7 +240,7 @@ function userInfo() { //https://github.com/theoldreader/api#user-info 'userName' => $user, 'userProfileId' => $user, 'userEmail' => FreshRSS_Context::$user_conf->mail_login, - ))); + ), JSON_OPTIONS)); } function tagList() { @@ -254,10 +260,24 @@ function tagList() { $tags[] = array( 'id' => 'user/-/label/' . $cName, //'sortid' => $cName, + 'type' => 'folder', //Inoreader ); } - echo json_encode(array('tags' => $tags)), "\n"; + unset($res); + + $tagDAO = FreshRSS_Factory::createTagDao(); + $labels = $tagDAO->listTags(true); + foreach ($labels as $label) { + $tags[] = array( + 'id' => 'user/-/label/' . $label->name(), + //'sortid' => $cName, + 'type' => 'tag', //Inoreader + 'unread_count' => $label->nbUnread(), + ); + } + + echo json_encode(array('tags' => $tags), JSON_OPTIONS), "\n"; exit(); } @@ -293,7 +313,7 @@ function subscriptionList() { ); } - echo json_encode(array('subscriptions' => $subscriptions)), "\n"; + echo json_encode(array('subscriptions' => $subscriptions), JSON_OPTIONS), "\n"; exit(); } @@ -310,7 +330,7 @@ function subscriptionEdit($streamNames, $titles, $action, $add = '', $remove = ' $addCatId = 0; $categoryDAO = null; if ($add != '' || $remove != '') { - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); } $c_name = ''; if ($add != '' && strpos($add, 'user/') === 0) { //user/-/label/Example ; user/username/label/Example @@ -391,13 +411,13 @@ function quickadd($url) { exit(json_encode(array( 'numResults' => 1, 'streamId' => $feed->id(), - ))); + ), JSON_OPTIONS)); } catch (Exception $e) { Minz_Log::error('quickadd error: ' . $e->getMessage(), API_LOG); die(json_encode(array( 'numResults' => 0, 'error' => $e->getMessage(), - ))); + ), JSON_OPTIONS)); } } @@ -407,7 +427,7 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl $totalUnreads = 0; $totalLastUpdate = 0; - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); foreach ($categoryDAO->listCategories(true, true) as $cat) { $catLastUpdate = 0; foreach ($cat->feeds() as $feed) { @@ -432,6 +452,14 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl } } + $tagDAO = FreshRSS_Factory::createTagDao(); + foreach ($tagDAO->listTags(true) as $label) { + $unreadcounts[] = array( + 'id' => 'user/-/label/' . $label->name(), + 'count' => $label->nbUnread(), + ); + } + $unreadcounts[] = array( 'id' => 'user/-/state/com.google/reading-list', 'count' => $totalUnreads, @@ -441,13 +469,21 @@ function unreadCount() { //http://blog.martindoms.com/2009/10/16/using-the-googl echo json_encode(array( 'max' => $totalUnreads, 'unreadcounts' => $unreadcounts, - )), "\n"; + ), JSON_OPTIONS), "\n"; exit(); } function entriesToArray($entries) { + if (empty($entries)) { + return array(); + } $feedDAO = FreshRSS_Factory::createFeedDao(); $arrayFeedCategoryNames = $feedDAO->arrayFeedCategoryNames(); + $tagDAO = FreshRSS_Factory::createTagDao(); + $entryIdsTagNames = $tagDAO->getEntryIdsTagNames($entries); + if ($entryIdsTagNames == false) { + $entryIdsTagNames = array(); + } $items = array(); foreach ($entries as $entry) { @@ -472,7 +508,6 @@ function entriesToArray($entries) { 'categories' => array( 'user/-/state/com.google/reading-list', 'user/-/label/' . $c_name, - //TODO: Add other tags ), 'origin' => array( 'streamId' => 'feed/' . $f_id, @@ -490,6 +525,10 @@ function entriesToArray($entries) { if ($entry->isFavorite()) { $item['categories'][] = 'user/-/state/com.google/starred'; } + $tagNames = isset($entryIdsTagNames['e_' . $entry->id()]) ? $entryIdsTagNames['e_' . $entry->id()] : array(); + foreach ($tagNames as $tagName) { + $item['categories'][] = 'user/-/label/' . $tagName; + } $items[] = $item; } return $items; @@ -511,10 +550,22 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex $type = 'f'; break; case 'label': - $type = 'c'; - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($include_target); - $include_target = $cat == null ? -1 : $cat->id(); + if ($cat != null) { + $type = 'c'; + $include_target = $cat->id(); + } else { + $tagDAO = FreshRSS_Factory::createTagDao(); + $tag = $tagDAO->searchByName($include_target); + if ($tag != null) { + $type = 't'; + $include_target = $tag->id(); + } else { + $type = 'A'; + $include_target = -1; + } + } break; default: $type = 'A'; @@ -559,7 +610,7 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex } } - echo json_encode($response), "\n"; + echo json_encode($response, JSON_OPTIONS), "\n"; exit(); } @@ -579,9 +630,22 @@ function streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude } elseif (strpos($streamId, 'user/-/label/') === 0) { $type = 'c'; $c_name = substr($streamId, 13); - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($c_name); - $id = $cat == null ? -1 : $cat->id(); + if ($cat != null) { + $type = 'c'; + $id = $cat->id(); + } else { + $tagDAO = FreshRSS_Factory::createTagDao(); + $tag = $tagDAO->searchByName($c_name); + if ($tag != null) { + $type = 't'; + $id = $tag->id(); + } else { + $type = 'A'; + $id = -1; + } + } } switch ($exclude_target) { @@ -625,7 +689,7 @@ function streamContentsItemsIds($streamId, $start_time, $count, $order, $exclude } } - echo json_encode($response), "\n"; + echo json_encode($response, JSON_OPTIONS), "\n"; exit(); } @@ -647,7 +711,7 @@ function streamContentsItems($e_ids, $order) { 'items' => $items, ); - echo json_encode($response), "\n"; + echo json_encode($response, JSON_OPTIONS), "\n"; exit(); } @@ -657,6 +721,7 @@ function editTag($e_ids, $a, $r) { } $entryDAO = FreshRSS_Factory::createEntryDao(); + $tagDAO = FreshRSS_Factory::createTagDao(); switch ($a) { case 'user/-/state/com.google/read': @@ -671,6 +736,30 @@ function editTag($e_ids, $a, $r) { break; case 'user/-/state/com.google/broadcast': break;*/ + default: + $tagName = ''; + if (strpos($a, 'user/-/label/') === 0) { + $tagName = substr($a, 13); + } else { + $user = Minz_Session::param('currentUser', '_'); + $prefix = 'user/' . $user . '/label/'; + if (strpos($a, $prefix) === 0) { + $tagName = substr($a, strlen($prefix)); + } + } + if ($tagName != '') { + $tag = $tagDAO->searchByName($tagName); + if ($tag == null) { + $tagDAO->addTag(array('name' => $tagName)); + $tag = $tagDAO->searchByName($tagName); + } + if ($tag != null) { + foreach ($e_ids as $e_id) { + $tagDAO->tagEntry($tag->id(), $e_id, true); + } + } + } + break; } switch ($r) { case 'user/-/state/com.google/read': @@ -679,6 +768,17 @@ function editTag($e_ids, $a, $r) { case 'user/-/state/com.google/starred': $entryDAO->markFavorite($e_ids, false); break; + default: + if (strpos($r, 'user/-/label/') === 0) { + $tagName = substr($r, 13); + $tag = $tagDAO->searchByName($tagName); + if ($tag != null) { + foreach ($e_ids as $e_id) { + $tagDAO->tagEntry($tag->id(), $e_id, false); + } + } + } + break; } exit('OK'); @@ -688,12 +788,20 @@ function renameTag($s, $dest) { if ($s != '' && strpos($s, 'user/-/label/') === 0 && $dest != '' && strpos($dest, 'user/-/label/') === 0) { $s = substr($s, 13); - $categoryDAO = new FreshRSS_CategoryDAO(); + $dest = substr($dest, 13); + + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($s); if ($cat != null) { - $dest = substr($dest, 13); $categoryDAO->updateCategory($cat->id(), array('name' => $dest)); exit('OK'); + } else { + $tagDAO = FreshRSS_Factory::createTagDao(); + $tag = $tagDAO->searchByName($s); + if ($tag != null) { + $tagDAO->updateTag($tag->id(), array('name' => $dest)); + exit('OK'); + } } } badRequest(); @@ -702,7 +810,7 @@ function renameTag($s, $dest) { function disableTag($s) { if ($s != '' && strpos($s, 'user/-/label/') === 0) { $s = substr($s, 13); - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($s); if ($cat != null) { $feedDAO = FreshRSS_Factory::createFeedDao(); @@ -711,6 +819,13 @@ function disableTag($s) { $categoryDAO->deleteCategory($cat->id()); } exit('OK'); + } else { + $tagDAO = FreshRSS_Factory::createTagDao(); + $tag = $tagDAO->searchByName($s); + if ($tag != null) { + $tagDAO->deleteTag($tag->id()); + exit('OK'); + } } } badRequest(); @@ -723,9 +838,17 @@ function markAllAsRead($streamId, $olderThanId) { $entryDAO->markReadFeed($f_id, $olderThanId); } elseif (strpos($streamId, 'user/-/label/') === 0) { $c_name = substr($streamId, 13); - $categoryDAO = new FreshRSS_CategoryDAO(); + $categoryDAO = FreshRSS_Factory::createCategoryDao(); $cat = $categoryDAO->searchByName($c_name); - $entryDAO->markReadCat($cat === null ? -1 : $cat->id(), $olderThanId); + if ($cat != null) { + $entryDAO->markReadCat($cat->id(), $olderThanId); + } else { + $tagDAO = FreshRSS_Factory::createTagDao(); + $tag = $tagDAO->searchByName($c_name); + if ($tag != null) { + $entryDAO->markReadTag($tag->id(), $olderThanId); + } + } } elseif ($streamId === 'user/-/state/com.google/reading-list') { $entryDAO->markReadEntries($olderThanId, false, -1); } |
