aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2023-09-04 10:09:37 +0200
committerGravatar GitHub <noreply@github.com> 2023-09-04 10:09:37 +0200
commit1c7c1016f4a5147003ed1c438b8a386a63a53cab (patch)
treea0639042ac205cd20863cd24496e79ddae3f562e
parentda405ceee628dca739a12b234a6094a8ebae9c94 (diff)
Fix JSON export/import (#5626)
* Fix import with empty content fix https://github.com/FreshRSS/FreshRSS/issues/5622 Cherry picks on https://github.com/FreshRSS/FreshRSS/pull/5584 * Fix export of tags / labels Article-defined tags were wrongly exported as user-defined labels. * Fix export of tags / labels Article-defined tags were wrongly exported as user-defined labels. * Fix bug with many labels * Better typing * Comments
-rw-r--r--app/Controllers/importExportController.php13
-rw-r--r--app/Models/Entry.php9
-rw-r--r--app/Models/TagDAO.php13
-rw-r--r--app/views/helpers/export/articles.phtml6
-rw-r--r--lib/lib_rss.php1
-rw-r--r--p/api/greader.php6
6 files changed, 25 insertions, 23 deletions
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 9c18b608f..807a355db 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -309,7 +309,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
$limits = FreshRSS_Context::$system_conf->limits;
// First, we check feeds of articles are in DB (and add them if needed).
- foreach ($items as $item) {
+ foreach ($items as &$item) {
if (!isset($item['guid']) && isset($item['id'])) {
$item['guid'] = $item['id'];
}
@@ -382,7 +382,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
// Then, articles are imported.
$newGuids = [];
$this->entryDAO->beginTransaction();
- foreach ($items as $item) {
+ foreach ($items as &$item) {
if (empty($item['guid']) || empty($article_to_feed[$item['guid']])) {
// Related feed does not exist for this entry, do nothing.
continue;
@@ -427,14 +427,17 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
} else {
$url = '';
}
+ if (!is_string($url)) {
+ $url = '';
+ }
$title = empty($item['title']) ? $url : $item['title'];
- if (!empty($item['content']['content'])) {
+ if (isset($item['content']['content']) && is_string($item['content']['content'])) {
$content = $item['content']['content'];
- } elseif (!empty($item['summary']['content'])) {
+ } elseif (isset($item['summary']['content']) && is_string($item['summary']['content'])) {
$content = $item['summary']['content'];
- } elseif (!empty($item['content'])) {
+ } elseif (isset($item['content']) && is_string($item['content'])) {
$content = $item['content']; //FeedBin
} else {
$content = '';
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 7da27e409..b70e7e2ab 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -846,12 +846,12 @@ HTML;
/**
* N.B.: To avoid expensive lookups, ensure to set `$entry->_feed($feed)` before calling this function.
- * N.B.: You might have to populate `$entry->_tags()` prior to calling this function.
* @param string $mode Set to `'compat'` to use an alternative Unicode representation for problematic HTML special characters not decoded by some clients;
* set to `'freshrss'` for using FreshRSS additions for internal use (e.g. export/import).
+ * @param array<string> $labels List of labels associated to this entry.
* @return array<string,mixed> A representation of this entry in a format compatible with Google Reader API
*/
- public function toGReader(string $mode = ''): array {
+ public function toGReader(string $mode = '', array $labels = []): array {
$feed = $this->feed();
$category = $feed == null ? null : $feed->category();
@@ -935,8 +935,11 @@ HTML;
if ($this->isFavorite()) {
$item['categories'][] = 'user/-/state/com.google/starred';
}
+ foreach ($labels as $labelName) {
+ $item['categories'][] = 'user/-/label/' . htmlspecialchars_decode($labelName, ENT_QUOTES);
+ }
foreach ($this->tags() as $tagName) {
- $item['categories'][] = 'user/-/label/' . htmlspecialchars_decode($tagName, ENT_QUOTES);
+ $item['categories'][] = htmlspecialchars_decode($tagName, ENT_QUOTES);
}
return $item;
}
diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php
index 0704fd9f7..80a0e7688 100644
--- a/app/Models/TagDAO.php
+++ b/app/Models/TagDAO.php
@@ -383,7 +383,11 @@ SQL;
// Split a query with too many variables parameters
$idsChunks = array_chunk($entries, FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER);
foreach ($idsChunks as $idsChunk) {
- $values += $this->getTagsForEntries($idsChunk);
+ $valuesChunk = $this->getTagsForEntries($idsChunk);
+ if (!is_array($valuesChunk)) {
+ return false;
+ }
+ $values = array_merge($values, $valuesChunk);
}
return $values;
}
@@ -419,9 +423,10 @@ SQL;
}
/**
- * For API
- * @param array<FreshRSS_Entry|numeric-string> $entries
- * @return array<string,array<string>>
+ * Produces an array: for each entry ID (prefixed by `e_`), associate a list of labels.
+ * Used by API and by JSON export, to speed up queries (would be very expensive to perform a label look-up on each entry individually).
+ * @param array<FreshRSS_Entry|numeric-string> $entries the list of entries for which to retrieve the labels.
+ * @return array<string,array<string>> An array of the shape `[e_id_entry => ["label 1", "label 2"]]`
*/
public function getEntryIdsTagNames(array $entries): array {
$result = [];
diff --git a/app/views/helpers/export/articles.phtml b/app/views/helpers/export/articles.phtml
index 60041339b..1db627bf7 100644
--- a/app/views/helpers/export/articles.phtml
+++ b/app/views/helpers/export/articles.phtml
@@ -26,11 +26,7 @@ foreach ($this->entries as $entry) {
$feed = $this->feed ?? FreshRSS_CategoryDAO::findFeed($this->categories, $entry->feedId());
$entry->_feed($feed);
- if (isset($this->entryIdsTagNames['e_' . $entry->id()])) {
- $entry->_tags($this->entryIdsTagNames['e_' . $entry->id()]);
- }
-
- $article = $entry->toGReader('freshrss');
+ $article = $entry->toGReader('freshrss', $this->entryIdsTagNames['e_' . $entry->id()] ?? []);
$line = json_encode($article, $options);
if ($line != '') {
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index 9d995c6d6..356d5bc0d 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -330,7 +330,6 @@ function customSimplePie(array $attributes = array()): SimplePie {
return $simplePie;
}
-/** @param string $data */
function sanitizeHTML(string $data, string $base = '', ?int $maxLength = null): string {
if ($data === '' || ($maxLength !== null && $maxLength <= 0)) {
return '';
diff --git a/p/api/greader.php b/p/api/greader.php
index e42736869..a014a4db1 100644
--- a/p/api/greader.php
+++ b/p/api/greader.php
@@ -573,11 +573,7 @@ final class GReaderAPI {
}
$entry->_feed($feed);
- if (isset($entryIdsTagNames['e_' . $entry->id()])) {
- $entry->_tags($entryIdsTagNames['e_' . $entry->id()]);
- }
-
- $items[] = $entry->toGReader('compat');
+ $items[] = $entry->toGReader('compat', $entryIdsTagNames['e_' . $entry->id()] ?? []);
}
return $items;
}