Quellcode durchsuchen

API: Add continuation mode

https://github.com/marienfressinaud/FreshRSS/issues/443
Needed for e.g. EasyRSS
Alexandre Alapetite vor 12 Jahren
Ursprung
Commit
fc6769c1b1
3 geänderte Dateien mit 36 neuen und 18 gelöschten Zeilen
  1. 1 1
      app/Controllers/indexController.php
  2. 13 9
      app/Models/EntryDAO.php
  3. 22 8
      p/api/greader.php

+ 1 - 1
app/Controllers/indexController.php

@@ -126,7 +126,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
 		$keepHistoryDefault = $this->view->conf->keep_history_default;
 
 		try {
-			$entries = $entryDAO->listWhere($getType, $getId, $state, $order, $nb + 1, $first, $filter, $date_min, $keepHistoryDefault);
+			$entries = $entryDAO->listWhere($getType, $getId, $state, $order, $nb + 1, $first, $filter, $date_min, true, $keepHistoryDefault);
 
 			// Si on a récupéré aucun article "non lus"
 			// on essaye de récupérer tous les articles

+ 13 - 9
app/Models/EntryDAO.php

@@ -376,7 +376,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
 		return isset ($entries[0]) ? $entries[0] : null;
 	}
 
-	private function sqlListWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $keepHistoryDefault = 0) {
+	private function sqlListWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) {
 		$where = '';
 		$joinFeed = false;
 		$values = array();
@@ -429,11 +429,15 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
 			$where .= 'AND e1.id ' . ($order === 'DESC' ? '<=' : '>=') . $firstId . ' ';
 		}
 		if (($date_min > 0) && ($type !== 's')) {
-			$where .= 'AND (e1.id >= ' . $date_min . '000000 OR e1.is_read = 0 OR e1.is_favorite = 1 OR (f.keep_history <> 0';
-			if (intval($keepHistoryDefault) === 0) {
-				$where .= ' AND f.keep_history <> -2';	//default
+			$where .= 'AND (e1.id >= ' . $date_min . '000000';
+			if ($showOlderUnreadsorFavorites) {	//Lax date constraint
+				$where .= ' OR e1.is_read = 0 OR e1.is_favorite = 1 OR (f.keep_history <> 0';
+				if (intval($keepHistoryDefault) === 0) {
+					$where .= ' AND f.keep_history <> -2';	//default
+				}
+				$where .= ')';
 			}
-			$where .= ')) ';
+			$where .= ') ';
 			$joinFeed = true;
 		}
 		$search = '';
@@ -494,8 +498,8 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
 			. ($limit > 0 ? ' LIMIT ' . $limit : ''));	//TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/
 	}
 
-	public function listWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $keepHistoryDefault = 0) {
-		list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $keepHistoryDefault);
+	public function listWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) {
+		list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $showOlderUnreadsorFavorites, $keepHistoryDefault);
 
 		$sql = 'SELECT e.id, e.guid, e.title, e.author, UNCOMPRESS(e.content_bin) AS content, e.link, e.date, e.is_read, e.is_favorite, e.id_feed, e.tags '
 		     . 'FROM `' . $this->prefix . 'entry` e '
@@ -510,8 +514,8 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo {
 		return self::daoToEntry ($stm->fetchAll (PDO::FETCH_ASSOC));
 	}
 
-	public function listIdsWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $keepHistoryDefault = 0) {	//For API
-		list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $keepHistoryDefault);
+	public function listIdsWhere($type = 'a', $id = '', $state = 'all', $order = 'DESC', $limit = 1, $firstId = '', $filter = '', $date_min = 0, $showOlderUnreadsorFavorites = false, $keepHistoryDefault = 0) {	//For API
+		list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filter, $date_min, $showOlderUnreadsorFavorites, $keepHistoryDefault);
 
 		$stm = $this->bd->prepare($sql);
 		$stm->execute($values);

+ 22 - 8
p/api/greader.php

@@ -288,7 +288,7 @@ function unreadCount() {
 	exit();
 }
 
-function streamContents($path, $include_target, $start_time, $count, $order, $exclude_target)
+function streamContents($path, $include_target, $start_time, $count, $order, $exclude_target, $continuation)
 {//http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI	http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed
 	logMe('streamContents(' . $include_target . ")\n");
 	header('Content-Type: application/json; charset=UTF-8');
@@ -326,8 +326,12 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex
 			break;
 	}
 
+	if (!empty($continuation)) {
+		$count++;	//Shift by one element
+	}
+
 	$entryDAO = new FreshRSS_EntryDAO();
-	$entries = $entryDAO->listWhere($type, $include_target, $state, $order === 'o' ? 'ASC' : 'DESC', $count, '', '', $start_time);
+	$entries = $entryDAO->listWhere($type, $include_target, $state, $order === 'o' ? 'ASC' : 'DESC', $count, $continuation, '', $start_time);
 
 	$items = array();
 	foreach ($entries as $entry) {
@@ -371,11 +375,20 @@ function streamContents($path, $include_target, $start_time, $count, $order, $ex
 		$items[] = $item;
 	}
 
-	echo json_encode(array(
+	if (!empty($continuation)) {
+		array_shift($items);	//Discard first element that was already sent in the previous response
+	}
+
+	$response = array(
 		'id' => 'user/-/state/com.google/reading-list',
 		'updated' => time(),
 		'items' => $items,
-	)), "\n";
+	);
+	if ((count($entries) >= $count) && (!empty($entry))) {
+		$response['continuation'] = $entry->id();
+	}
+
+	echo json_encode($response), "\n";
 	exit();
 }
 
@@ -520,27 +533,28 @@ elseif ($pathInfos[1] === 'reader' && $pathInfos[2] === 'api' && isset($pathInfo
 			$count = isset($_GET['n']) ? intval($_GET['n']) : 20;	//n=[integer] : The maximum number of results to return.
 			$order = isset($_GET['r']) ? $_GET['r'] : 'd';	//r=[d|n|o] : Sort order of item results. d or n gives items in descending date order, o in ascending order.
 			$start_time = isset($_GET['ot']) ? intval($_GET['ot']) : 0;	//ot=[unix timestamp] : The time from which you want to retrieve items. Only items that have been crawled by Google Reader after this time will be returned.
+			$continuation = isset($_GET['c']) ? $_GET['c'] : '';	//Continuation token. If a StreamContents response does not represent all items in a timestamp range, it will have a continuation attribute. The same request can be re-issued with the value of that attribute put in this parameter to get more items
 			if (isset($pathInfos[5]) && $pathInfos[5] === 'contents' && isset($pathInfos[6])) {
 				if (isset($pathInfos[7])) {
 					if ($pathInfos[6] === 'feed') {
 						$include_target = $pathInfos[7];
-						StreamContents($pathInfos[6], $include_target, $start_time, $count, $order, $exclude_target);
+						StreamContents($pathInfos[6], $include_target, $start_time, $count, $order, $exclude_target, $continuation);
 					} elseif ($pathInfos[6] === 'user' && isset($pathInfos[8]) && isset($pathInfos[9])) {
 						if ($pathInfos[8] === 'state') {
 							if ($pathInfos[9] === 'com.google' && isset($pathInfos[10])) {
 								if ($pathInfos[10] === 'reading-list' || $pathInfos[10] === 'starred') {
 									$include_target = '';
-									streamContents($pathInfos[10], $include_target, $start_time, $count, $order, $exclude_target);
+									streamContents($pathInfos[10], $include_target, $start_time, $count, $order, $exclude_target, $continuation);
 								}
 							}
 						} elseif ($pathInfos[8] === 'label') {
 							$include_target = $pathInfos[9];
-							streamContents($pathInfos[8], $include_target, $start_time, $count, $order, $exclude_target);
+							streamContents($pathInfos[8], $include_target, $start_time, $count, $order, $exclude_target, $continuation);
 						}
 					}
 				} else {	//EasyRSS
 					$include_target = '';
-					streamContents('reading-list', $include_target, $start_time, $count, $order, $exclude_target);
+					streamContents('reading-list', $include_target, $start_time, $count, $order, $exclude_target, $continuation);
 				}
 			} elseif ($pathInfos[5] === 'items') {
 				if ($pathInfos[6] === 'ids' && isset($_GET['s'])) {