瀏覽代碼

Fix TT-RSS import (#3553)

Alexandre Alapetite 5 年之前
父節點
當前提交
de40f3ad56
共有 4 個文件被更改,包括 37 次插入13 次删除
  1. 20 8
      app/Controllers/importExportController.php
  2. 5 0
      app/Models/DatabaseDAO.php
  3. 9 2
      app/Models/EntryDAO.php
  4. 3 3
      app/Services/ImportService.php

+ 20 - 8
app/Controllers/importExportController.php

@@ -189,7 +189,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 	private static function guessFileType($filename) {
 		if (substr_compare($filename, '.zip', -4) === 0) {
 			return 'zip';
-		} elseif (substr_compare($filename, '.opml', -5) === 0) {
+		} elseif (stripos($filename, 'opml') !== false) {
 			return 'opml';
 		} elseif (substr_compare($filename, '.json', -5) === 0) {
 			if (strpos($filename, 'starred') !== false) {
@@ -208,11 +208,15 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 	}
 
 	private function ttrssXmlToJson($xml) {
-		$table = (array)simplexml_load_string($xml, null, LIBXML_NOCDATA);
+		$table = (array)simplexml_load_string($xml, null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
 		$table['items'] = isset($table['article']) ? $table['article'] : array();
 		unset($table['article']);
 		for ($i = count($table['items']) - 1; $i >= 0; $i--) {
 			$item = (array)($table['items'][$i]);
+			$item = array_filter($item, function ($v) {
+					// Filter out empty properties, potentially reported as empty objects
+					return (is_string($v) && trim($v) !== '') || !empty($v);
+				});
 			$item['updated'] = isset($item['updated']) ? strtotime($item['updated']) : '';
 			$item['published'] = $item['updated'];
 			$item['content'] = array('content' => isset($item['content']) ? $item['content'] : '');
@@ -274,8 +278,14 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 
 		// First, we check feeds of articles are in DB (and add them if needed).
 		foreach ($items as $item) {
-			if (!isset($item['origin'])) {
-				$item['origin'] = array('title' => 'Import');
+			if (empty($item['id'])) {
+				continue;
+			}
+			if (empty($item['origin'])) {
+				$item['origin'] = [];
+			}
+			if (empty($item['origin']['title']) || trim($item['origin']['title']) === '') {
+				$item['origin']['title'] = 'Import';
 			}
 			if (!empty($item['origin']['feedUrl'])) {
 				$feedUrl = $item['origin']['feedUrl'];
@@ -338,7 +348,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 		$newGuids = array();
 		$this->entryDAO->beginTransaction();
 		foreach ($items as $item) {
-			if (empty($article_to_feed[$item['id']])) {
+			if (empty($item['id']) || empty($article_to_feed[$item['id']])) {
 				// Related feed does not exist for this entry, do nothing.
 				continue;
 			}
@@ -349,7 +359,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 			$is_read = null;
 			$tags = empty($item['categories']) ? array() : $item['categories'];
 			$labels = array();
-			for ($i = count($tags) - 1; $i >= 0; $i --) {
+			for ($i = count($tags) - 1; $i >= 0; $i--) {
 				$tag = trim($tags[$i]);
 				if (strpos($tag, 'user/-/') !== false) {
 					if ($tag === 'user/-/state/com.google/starred') {
@@ -383,6 +393,8 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 				$url = '';
 			}
 
+			$title = empty($item['title']) ? $url : $item['title'];
+
 			if (!empty($item['content']['content'])) {
 				$content = $item['content']['content'];
 			} elseif (!empty($item['summary']['content'])) {
@@ -408,7 +420,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 			}
 
 			$entry = new FreshRSS_Entry(
-				$feed_id, $item['id'], $item['title'], $author,
+				$feed_id, $item['id'], $title, $author,
 				$content, $url, $published, $is_read, $is_starred
 			);
 			$entry->_id(uTimeString());
@@ -493,7 +505,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
 		} elseif (!empty($origin['feedUrl'])) {
 			$website = $origin['feedUrl'];
 		}
-		$name = empty($origin['title']) ? '' : $origin['title'];
+		$name = empty($origin['title']) ? $website : $origin['title'];
 
 		try {
 			// Create a Feed object and add it in database.

+ 5 - 0
app/Models/DatabaseDAO.php

@@ -10,6 +10,11 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
 	const ER_BAD_TABLE_ERROR = '42S02';
 	const ER_DATA_TOO_LONG = '1406';
 
+	/**
+	 * Based on SQLite SQLITE_MAX_VARIABLE_NUMBER
+	 */
+	const MAX_VARIABLE_NUMBER = 998;
+
 	//MySQL InnoDB maximum index length for UTF8MB4
 	//https://dev.mysql.com/doc/refman/8.0/en/innodb-restrictions.html
 	const LENGTH_INDEX_UNICODE = 191;

+ 9 - 2
app/Models/EntryDAO.php

@@ -989,8 +989,16 @@ SQL;
 	}
 
 	public function listHashForFeedGuids($id_feed, $guids) {
+		$result = [];
 		if (count($guids) < 1) {
-			return array();
+			return $result;
+		} elseif (count($guids) > FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER) {
+			// Split a query with too many variables parameters
+			$guidsChunks = array_chunk($guids, FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER, true);
+			foreach ($guidsChunks as $guidsChunk) {
+				$result += $this->listHashForFeedGuids($id_feed, $guidsChunk);
+			}
+			return $result;
 		}
 		$guids = array_unique($guids);
 		$sql = 'SELECT guid, ' . $this->sqlHexEncode('hash') .
@@ -999,7 +1007,6 @@ SQL;
 		$values = array($id_feed);
 		$values = array_merge($values, $guids);
 		if ($stm && $stm->execute($values)) {
-			$result = array();
 			$rows = $stm->fetchAll(PDO::FETCH_ASSOC);
 			foreach ($rows as $row) {
 				$result[$row['guid']] = $row['hex_hash'];

+ 3 - 3
app/Services/ImportService.php

@@ -67,8 +67,8 @@ class FreshRSS_Import_Service {
 		//Sort with categories first
 		usort($opml_elements, function ($a, $b) {
 			return strcmp(
-				(isset($a['xmlUrl']) ? 'Z' : 'A') . $a['text'],
-				(isset($b['xmlUrl']) ? 'Z' : 'A') . $b['text']);
+				(isset($a['xmlUrl']) ? 'Z' : 'A') . (isset($a['text']) ? $a['text'] : ''),
+				(isset($b['xmlUrl']) ? 'Z' : 'A') . (isset($b['text']) ? $b['text'] : ''));
 		});
 
 		foreach ($opml_elements as $elt) {
@@ -86,7 +86,7 @@ class FreshRSS_Import_Service {
 				} else {
 					$ok = false;
 				}
-			} else {
+			} elseif (!empty($elt['text'])) {
 				// No xmlUrl? It should be a category!
 				$limit_reached = ($nb_cats >= $limits['max_categories']);
 				if (!FreshRSS_Context::$isCli && $limit_reached) {