aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapp/Controllers/feedController.php5
-rw-r--r--app/Controllers/importExportController.php25
-rw-r--r--app/Controllers/subscriptionController.php2
-rw-r--r--app/Models/Category.php2
-rw-r--r--app/Models/CategoryDAO.php2
-rw-r--r--app/Models/Context.php2
-rw-r--r--app/Models/Entry.php148
-rw-r--r--app/Models/EntryDAO.php11
-rw-r--r--app/Models/Feed.php35
-rw-r--r--app/Models/FeedDAO.php24
-rw-r--r--app/Models/TagDAO.php2
-rw-r--r--app/Models/View.php2
-rw-r--r--app/Services/ExportService.php18
-rw-r--r--app/Services/ImportService.php2
-rw-r--r--app/views/helpers/export/articles.phtml49
-rw-r--r--app/views/helpers/feed/update.phtml2
-rw-r--r--app/views/index/normal.phtml4
-rw-r--r--app/views/index/reader.phtml8
-rw-r--r--p/api/fever.php4
-rw-r--r--p/api/greader.php86
20 files changed, 232 insertions, 201 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index 0699844d8..31875fa56 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -74,7 +74,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
$feed->_kind($kind);
$feed->_attributes('', $attributes);
$feed->_httpAuth($http_auth);
- $feed->_category($cat_id);
+ $feed->_categoryId($cat_id);
switch ($kind) {
case FreshRSS_Feed::KIND_RSS:
case FreshRSS_Feed::KIND_RSS_FORCED:
@@ -425,6 +425,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
//Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->url(false) .
//', old hash ' . $existingHash . ', new hash ' . $entry->hash());
$entry->_isRead($mark_updated_article_unread ? false : null); //Change is_read according to policy.
+ $entry->_isFavorite(null); // Do not change favourite state
/** @var FreshRSS_Entry|null */
$entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry);
@@ -908,7 +909,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
}
//Get feed.
- $feed = $entry->feed(true);
+ $feed = $entry->feed();
if (!$feed) {
$this->view->fatalError = _t('feedback.sub.feed.selector_preview.no_feed');
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 8402e840d..a1e1106c1 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -249,6 +249,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
'feedUrl' => isset($item['feed_url']) ? $item['feed_url'] : '',
);
$item['id'] = isset($item['guid']) ? $item['guid'] : (isset($item['feed_url']) ? $item['feed_url'] : $item['published']);
+ $item['guid'] = $item['id'];
$table['items'][$i] = $item;
}
return json_encode($table);
@@ -284,7 +285,10 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
// First, we check feeds of articles are in DB (and add them if needed).
foreach ($items as $item) {
- if (empty($item['id'])) {
+ if (!isset($item['guid']) && isset($item['id'])) {
+ $item['guid'] = $item['id'];
+ }
+ if (empty($item['guid'])) {
continue;
}
if (empty($item['origin'])) {
@@ -326,11 +330,11 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
}
if ($feed != null) {
- $article_to_feed[$item['id']] = $feed->id();
+ $article_to_feed[$item['guid']] = $feed->id();
if (!isset($newFeedGuids['f_' . $feed->id()])) {
$newFeedGuids['f_' . $feed->id()] = array();
}
- $newFeedGuids['f_' . $feed->id()][] = safe_ascii($item['id']);
+ $newFeedGuids['f_' . $feed->id()][] = safe_ascii($item['guid']);
}
}
@@ -354,14 +358,14 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
$newGuids = array();
$this->entryDAO->beginTransaction();
foreach ($items as $item) {
- if (empty($item['id']) || empty($article_to_feed[$item['id']])) {
+ if (empty($item['guid']) || empty($article_to_feed[$item['guid']])) {
// Related feed does not exist for this entry, do nothing.
continue;
}
- $feed_id = $article_to_feed[$item['id']];
+ $feed_id = $article_to_feed[$item['guid']];
$author = isset($item['author']) ? $item['author'] : '';
- $is_starred = false;
+ $is_starred = null; // null is used to preserve the current state if that item exists and is already starred
$is_read = null;
$tags = empty($item['categories']) ? array() : $item['categories'];
$labels = array();
@@ -429,7 +433,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
}
$entry = new FreshRSS_Entry(
- $feed_id, $item['id'], $title, $author,
+ $feed_id, $item['guid'], $title, $author,
$content, $url, $published, $is_read, $is_starred
);
$entry->_id(uTimeString());
@@ -463,7 +467,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
}
$knownLabels[$labelName]['articles'][] = array(
//'id' => $entry->id(), //ID changes after commitNewEntries()
- 'id_feed' => $entry->feed(),
+ 'id_feed' => $entry->feedId(),
'guid' => $entry->guid(),
);
}
@@ -480,6 +484,9 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
$this->entryDAO->beginTransaction();
foreach ($knownLabels as $labelName => $knownLabel) {
$labelId = $knownLabel['id'];
+ if (!$labelId) {
+ continue;
+ }
foreach ($knownLabel['articles'] as $article) {
$entryId = $this->entryDAO->searchIdByGuid($article['id_feed'], $article['guid']);
if ($entryId != null) {
@@ -521,7 +528,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
try {
// Create a Feed object and add it in database.
$feed = new FreshRSS_Feed($url);
- $feed->_category(FreshRSS_CategoryDAO::DEFAULTCATEGORYID);
+ $feed->_categoryId(FreshRSS_CategoryDAO::DEFAULTCATEGORYID);
$feed->_name($name);
$feed->_website($website);
if (!empty($origin['disable'])) {
diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php
index cdf30b378..b699e9213 100644
--- a/app/Controllers/subscriptionController.php
+++ b/app/Controllers/subscriptionController.php
@@ -244,7 +244,7 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
}
if ($feedDAO->updateFeed($id, $values) !== false) {
- $feed->_category($cat);
+ $feed->_categoryId($cat);
$feed->faviconPrepare();
Minz_Request::good(_t('feedback.sub.feed.updated'), $url_redirect);
diff --git a/app/Models/Category.php b/app/Models/Category.php
index d75d7e21e..e5da764d3 100644
--- a/app/Models/Category.php
+++ b/app/Models/Category.php
@@ -219,7 +219,7 @@ class FreshRSS_Category extends Minz_Model {
foreach ($dryRunCategory->feeds() as $dryRunFeed) {
if (empty($existingFeeds[$dryRunFeed->url()])) {
// The feed does not exist in the current category, so add that feed
- $dryRunFeed->_category($this->id());
+ $dryRunFeed->_categoryId($this->id());
$ok &= ($feedDAO->addFeedObject($dryRunFeed) !== false);
} else {
$existingFeed = $existingFeeds[$dryRunFeed->url()];
diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php
index cef8e6d63..e9b873d72 100644
--- a/app/Models/CategoryDAO.php
+++ b/app/Models/CategoryDAO.php
@@ -108,7 +108,7 @@ SQL;
$valuesTmp['name'],
);
- if ($stm && $stm->execute($values)) {
+ if ($stm && $stm->execute($values) && $stm->rowCount() > 0) {
return $this->pdo->lastInsertId('`_category_id_seq`');
} else {
$info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo();
diff --git a/app/Models/Context.php b/app/Models/Context.php
index ab855966b..db8dd1f09 100644
--- a/app/Models/Context.php
+++ b/app/Models/Context.php
@@ -299,7 +299,7 @@ class FreshRSS_Context {
}
}
self::$current_get['feed'] = $id;
- self::$current_get['category'] = $feed->category();
+ self::$current_get['category'] = $feed->categoryId();
self::$name = $feed->name();
self::$description = $feed->description();
self::$get_unread = $feed->nbNotRead();
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index 72e59e38c..e383f9060 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -31,6 +31,7 @@ class FreshRSS_Entry extends Minz_Model {
* @var bool|null
*/
private $is_read;
+ /** @var bool|null */
private $is_favorite;
/**
@@ -213,17 +214,22 @@ class FreshRSS_Entry extends Minz_Model {
public function isFavorite() {
return $this->is_favorite;
}
- public function feed($object = false) {
- if ($object) {
- if ($this->feed == null) {
- $feedDAO = FreshRSS_Factory::createFeedDao();
- $this->feed = $feedDAO->searchById($this->feedId);
- }
- return $this->feed;
- } else {
- return $this->feedId;
+
+ /**
+ * @return FreshRSS_Feed|null|false
+ */
+ public function feed() {
+ if ($this->feed === null) {
+ $feedDAO = FreshRSS_Factory::createFeedDao();
+ $this->feed = $feedDAO->searchById($this->feedId);
}
+ return $this->feed;
}
+
+ public function feedId(): int {
+ return $this->feedId;
+ }
+
public function tags($asString = false) {
if ($asString) {
return $this->tags == null ? '' : '#' . implode(' #', $this->tags);
@@ -331,18 +337,21 @@ class FreshRSS_Entry extends Minz_Model {
$this->is_read = $value === null ? null : (bool)$value;
}
public function _isFavorite($value) {
- $this->is_favorite = $value;
+ $this->is_favorite = $value === null ? null : (bool)$value;
}
- public function _feed($value) {
- if ($value != null) {
- $this->feed = $value;
- $this->feedId = $this->feed->id();
- }
+
+ /** @param FreshRSS_Feed|null $feed */
+ public function _feed($feed) {
+ $this->feed = $feed;
+ $this->feedId = $this->feed == null ? 0 : $this->feed->id();
}
- private function _feedId($value) {
+
+ /** @param int|string $id */
+ private function _feedId($id) {
$this->feed = null;
- $this->feedId = intval($value);
+ $this->feedId = intval($id);
}
+
public function _tags($value) {
$this->hash = '';
if (!is_array($value)) {
@@ -558,7 +567,7 @@ class FreshRSS_Entry extends Minz_Model {
public function loadCompleteContent(bool $force = false): bool {
// Gestion du contenu
// Trying to fetch full article content even when feeds do not propose it
- $feed = $this->feed(true);
+ $feed = $this->feed();
if ($feed != null && trim($feed->pathEntries()) != '') {
$entryDAO = FreshRSS_Factory::createEntryDao();
$entry = $force ? null : $entryDAO->searchByGuid($this->feedId, $this->guid);
@@ -613,9 +622,110 @@ class FreshRSS_Entry extends Minz_Model {
'hash' => $this->hash(),
'is_read' => $this->isRead(),
'is_favorite' => $this->isFavorite(),
- 'id_feed' => $this->feed(),
+ 'id_feed' => $this->feedId(),
'tags' => $this->tags(true),
'attributes' => $this->attributes(),
);
}
+
+ /**
+ * Integer format conversion for Google Reader API format
+ * @param string|int $dec Decimal number
+ * @return string 64-bit hexa http://code.google.com/p/google-reader-api/wiki/ItemId
+ */
+ private static function dec2hex($dec): string {
+ return PHP_INT_SIZE < 8 ? // 32-bit ?
+ str_pad(gmp_strval(gmp_init($dec, 10), 16), 16, '0', STR_PAD_LEFT) :
+ str_pad(dechex($dec), 16, '0', STR_PAD_LEFT);
+ }
+
+ /**
+ * 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).
+ * @return array<string,mixed> A representation of this entry in a format compatible with Google Reader API
+ */
+ public function toGReader(string $mode = ''): array {
+
+ $feed = $this->feed();
+ $category = $feed == null ? null : $feed->category();
+
+ $item = [
+ 'id' => 'tag:google.com,2005:reader/item/' . self::dec2hex($this->id()),
+ 'crawlTimeMsec' => substr($this->dateAdded(true, true), 0, -3),
+ 'timestampUsec' => '' . $this->dateAdded(true, true), //EasyRSS & Reeder
+ 'published' => $this->date(true),
+ // 'updated' => $this->date(true),
+ 'title' => $this->title(),
+ 'summary' => ['content' => $this->content()],
+ 'canonical' => [
+ ['href' => htmlspecialchars_decode($this->link(), ENT_QUOTES)],
+ ],
+ 'alternate' => [
+ [
+ 'href' => htmlspecialchars_decode($this->link(), ENT_QUOTES),
+ 'type' => 'text/html',
+ ],
+ ],
+ 'categories' => [
+ 'user/-/state/com.google/reading-list',
+ ],
+ 'origin' => [
+ 'streamId' => 'feed/' . $this->feedId,
+ ],
+ ];
+ if ($mode === 'compat') {
+ $item['title'] = escapeToUnicodeAlternative($this->title(), false);
+ } elseif ($mode === 'freshrss') {
+ $item['guid'] = $this->guid();
+ unset($item['summary']);
+ $item['content'] = ['content' => $this->content()];
+ }
+ if ($category != null && $mode !== 'freshrss') {
+ $item['categories'][] = 'user/-/label/' . htmlspecialchars_decode($category->name(), ENT_QUOTES);
+ }
+ if ($feed != null) {
+ $item['origin']['htmlUrl'] = htmlspecialchars_decode($feed->website());
+ $item['origin']['title'] = $feed->name(); //EasyRSS
+ if ($mode === 'compat') {
+ $item['origin']['title'] = escapeToUnicodeAlternative($feed->name(), true);
+ } elseif ($mode === 'freshrss') {
+ $item['origin']['feedUrl'] = htmlspecialchars_decode($feed->url());
+ }
+ }
+ foreach ($this->enclosures() as $enclosure) {
+ if (!empty($enclosure['url']) && !empty($enclosure['type'])) {
+ $media = [
+ 'href' => $enclosure['url'],
+ 'type' => $enclosure['type'],
+ ];
+ if (!empty($enclosure['length'])) {
+ $media['length'] = intval($enclosure['length']);
+ }
+ $item['enclosure'][] = $media;
+ }
+ }
+ $author = $this->authors(true);
+ $author = trim($author, '; ');
+ if ($author != '') {
+ if ($mode === 'compat') {
+ $item['author'] = escapeToUnicodeAlternative($author, false);
+ } else {
+ $item['author'] = $author;
+ }
+ }
+ if ($this->isRead()) {
+ $item['categories'][] = 'user/-/state/com.google/read';
+ } elseif ($mode === 'freshrss') {
+ $item['categories'][] = 'user/-/state/com.google/unread';
+ }
+ if ($this->isFavorite()) {
+ $item['categories'][] = 'user/-/state/com.google/starred';
+ }
+ foreach ($this->tags() as $tagName) {
+ $item['categories'][] = 'user/-/label/' . htmlspecialchars_decode($tagName, ENT_QUOTES);
+ }
+ return $item;
+ }
}
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index 5faaac1fb..d69702c60 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -218,6 +218,9 @@ SQL;
if (!isset($valuesTmp['is_read'])) {
$valuesTmp['is_read'] = null;
}
+ if (!isset($valuesTmp['is_favorite'])) {
+ $valuesTmp['is_favorite'] = null;
+ }
if ($this->updateEntryPrepared === null) {
$sql = 'UPDATE `_entry` '
@@ -226,6 +229,7 @@ SQL;
. ', link=:link, date=:date, `lastSeen`=:last_seen'
. ', hash=' . static::sqlHexDecode(':hash')
. ', is_read=COALESCE(:is_read, is_read)'
+ . ', is_favorite=COALESCE(:is_favorite, is_favorite)'
. ', tags=:tags, attributes=:attributes '
. 'WHERE id_feed=:id_feed AND guid=:guid';
$this->updateEntryPrepared = $this->pdo->prepare($sql);
@@ -254,6 +258,11 @@ SQL;
} else {
$this->updateEntryPrepared->bindValue(':is_read', $valuesTmp['is_read'] ? 1 : 0, PDO::PARAM_INT);
}
+ if ($valuesTmp['is_favorite'] === null) {
+ $this->updateEntryPrepared->bindValue(':is_favorite', null, PDO::PARAM_NULL);
+ } else {
+ $this->updateEntryPrepared->bindValue(':is_favorite', $valuesTmp['is_favorite'] ? 1 : 0, PDO::PARAM_INT);
+ }
$this->updateEntryPrepared->bindParam(':id_feed', $valuesTmp['id_feed'], PDO::PARAM_INT);
$valuesTmp['tags'] = mb_strcut($valuesTmp['tags'], 0, 1023, 'UTF-8');
$valuesTmp['tags'] = safe_utf8($valuesTmp['tags']);
@@ -1102,7 +1111,7 @@ SQL;
. ($limit > 0 ? ' LIMIT ' . intval($limit) : '')); //TODO: See http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/
}
- public function listWhereRaw($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL,
+ private function listWhereRaw($type = 'a', $id = '', $state = FreshRSS_Entry::STATE_ALL,
$order = 'DESC', $limit = 1, $firstId = '', $filters = null, $date_min = 0) {
list($values, $sql) = $this->sqlListWhere($type, $id, $state, $order, $limit, $firstId, $filters, $date_min);
diff --git a/app/Models/Feed.php b/app/Models/Feed.php
index e39109b49..4de61167b 100644
--- a/app/Models/Feed.php
+++ b/app/Models/Feed.php
@@ -39,7 +39,9 @@ class FreshRSS_Feed extends Minz_Model {
/** @var int */
private $kind = 0;
/** @var int */
- private $category = 1;
+ private $categoryId = 1;
+ /** @var FreshRSS_Category|null */
+ private $category;
/** @var int */
private $nbEntries = -1;
/** @var int */
@@ -119,9 +121,22 @@ class FreshRSS_Feed extends Minz_Model {
public function hubUrl(): string {
return $this->hubUrl;
}
- public function category(): int {
+
+ /**
+ * @return FreshRSS_Category|null|false
+ */
+ public function category() {
+ if ($this->category === null) {
+ $catDAO = FreshRSS_Factory::createCategoryDao();
+ $this->category = $catDAO->searchById($this->categoryId);
+ }
return $this->category;
}
+
+ public function categoryId(): int {
+ return $this->categoryId;
+ }
+
public function entries() {
Minz_Log::warning(__method__ . ' is deprecated since FreshRSS 1.16.1!');
$simplePie = $this->load(false, true);
@@ -253,10 +268,16 @@ class FreshRSS_Feed extends Minz_Model {
$this->kind = $value;
}
- /** @param int $value */
- public function _category($value) {
- $value = intval($value);
- $this->category = $value >= 0 ? $value : 0;
+ /** @param FreshRSS_Category|null $cat */
+ public function _category($cat) {
+ $this->category = $cat;
+ $this->categoryId = $this->category == null ? 0 : $this->category->id();
+ }
+
+ /** @param int|string $id */
+ public function _categoryId($id) {
+ $this->category = null;
+ $this->categoryId = intval($id);
}
public function _name(string $value) {
@@ -700,7 +721,7 @@ class FreshRSS_Feed extends Minz_Model {
$archiving = $this->attributes('archiving');
if ($archiving == null) {
$catDAO = FreshRSS_Factory::createCategoryDao();
- $category = $catDAO->searchById($this->category());
+ $category = $catDAO->searchById($this->categoryId);
$archiving = $category == null ? null : $category->attributes('archiving');
if ($archiving == null) {
$archiving = FreshRSS_Context::$user_conf->archiving;
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index 8d54e7be2..233d2a715 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -82,7 +82,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
'id' => $feed->id(),
'url' => $feed->url(),
'kind' => $feed->kind(),
- 'category' => $feed->category(),
+ 'category' => $feed->categoryId(),
'name' => $feed->name(),
'website' => $feed->website(),
'description' => $feed->description(),
@@ -341,26 +341,6 @@ SQL;
}
/**
- * For API
- */
- public function arrayFeedCategoryNames(): array {
- $sql = <<<'SQL'
-SELECT f.id, f.name, c.name as c_name FROM `_feed` f
-INNER JOIN `_category` c ON c.id = f.category
-SQL;
- $stm = $this->pdo->query($sql);
- $res = $stm->fetchAll(PDO::FETCH_ASSOC);
- $feedCategoryNames = array();
- foreach ($res as $line) {
- $feedCategoryNames[$line['id']] = array(
- 'name' => $line['name'],
- 'c_name' => $line['c_name'],
- );
- }
- return $feedCategoryNames;
- }
-
- /**
* Use $defaultCacheDuration == -1 to return all feeds, without filtering them by TTL.
* @return array<FreshRSS_Feed>
*/
@@ -596,7 +576,7 @@ SQL;
$myFeed = new FreshRSS_Feed($dao['url'] ?? '', false);
$myFeed->_kind($dao['kind'] ?? FreshRSS_Feed::KIND_RSS);
- $myFeed->_category($category);
+ $myFeed->_categoryId($category);
$myFeed->_name($dao['name']);
$myFeed->_website($dao['website'] ?? '', false);
$myFeed->_description($dao['description'] ?? '');
diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php
index 49abbdefd..f232b2f9f 100644
--- a/app/Models/TagDAO.php
+++ b/app/Models/TagDAO.php
@@ -61,7 +61,7 @@ SQL;
$valuesTmp['name'],
);
- if ($stm && $stm->execute($values)) {
+ if ($stm && $stm->execute($values) && $stm->rowCount() > 0) {
return $this->pdo->lastInsertId('`_tag_id_seq`');
} else {
$info = $stm == null ? $this->pdo->errorInfo() : $stm->errorInfo();
diff --git a/app/Models/View.php b/app/Models/View.php
index 0169f130a..ab1780405 100644
--- a/app/Models/View.php
+++ b/app/Models/View.php
@@ -72,8 +72,6 @@ class FreshRSS_View extends Minz_View {
// Export / Import
public $content;
- public $entriesRaw;
- public $entriesId;
public $entryIdsTagNames;
public $list_title;
public $queryId;
diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php
index b5630f57f..ad0f5f5a8 100644
--- a/app/Services/ExportService.php
+++ b/app/Services/ExportService.php
@@ -71,17 +71,17 @@ class FreshRSS_Export_Service {
*/
public function generateStarredEntries($type) {
$view = new FreshRSS_View();
- $view->categories = $this->category_dao->listCategories();
+ $view->categories = $this->category_dao->listCategories(true);
$day = date('Y-m-d');
$view->list_title = _t('sub.import_export.starred_list');
$view->type = 'starred';
- $view->entriesId = $this->entry_dao->listIdsWhere(
+ $entriesId = $this->entry_dao->listIdsWhere(
$type, '', FreshRSS_Entry::STATE_ALL, 'ASC', -1
);
- $view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($view->entriesId);
+ $view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($entriesId);
// The following is a streamable query, i.e. must be last
- $view->entriesRaw = $this->entry_dao->listWhereRaw(
+ $view->entries = $this->entry_dao->listWhere(
$type, '', FreshRSS_Entry::STATE_ALL, 'ASC', -1
);
@@ -107,19 +107,19 @@ class FreshRSS_Export_Service {
}
$view = new FreshRSS_View();
- $view->categories = $this->category_dao->listCategories();
+ $view->categories = $this->category_dao->listCategories(true);
$view->feed = $feed;
$day = date('Y-m-d');
- $filename = "feed_{$day}_" . $feed->category() . '_' . $feed->id() . '.json';
+ $filename = "feed_{$day}_" . $feed->categoryId() . '_' . $feed->id() . '.json';
$view->list_title = _t('sub.import_export.feed_list', $feed->name());
$view->type = 'feed/' . $feed->id();
- $view->entriesId = $this->entry_dao->listIdsWhere(
+ $entriesId = $this->entry_dao->listIdsWhere(
'f', $feed->id(), FreshRSS_Entry::STATE_ALL, 'ASC', $max_number_entries
);
- $view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($view->entriesId);
+ $view->entryIdsTagNames = $this->tag_dao->getEntryIdsTagNames($entriesId);
// The following is a streamable query, i.e. must be last
- $view->entriesRaw = $this->entry_dao->listWhereRaw(
+ $view->entries = $this->entry_dao->listWhere(
'f', $feed->id(), FreshRSS_Entry::STATE_ALL, 'ASC', $max_number_entries
);
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 4cd866377..3fde32bb0 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -148,7 +148,7 @@ class FreshRSS_Import_Service {
try {
// Create a Feed object and add it in DB
$feed = new FreshRSS_Feed($url);
- $feed->_category($parent_cat->id());
+ $feed->_categoryId($parent_cat->id());
$parent_cat->addFeed($feed);
$feed->_name($name);
$feed->_website($website);
diff --git a/app/views/helpers/export/articles.phtml b/app/views/helpers/export/articles.phtml
index ad5210968..fd95ff741 100644
--- a/app/views/helpers/export/articles.phtml
+++ b/app/views/helpers/export/articles.phtml
@@ -18,51 +18,20 @@ if (empty($this->entryIdsTagNames)) {
$this->entryIdsTagNames = array();
}
-foreach ($this->entriesRaw as $entryRaw) {
- if ($entryRaw == null) {
+foreach ($this->entries as $entry) {
+ if ($entry == null) {
continue;
}
- $entry = FreshRSS_Entry::fromArray($entryRaw);
- if (!isset($this->feed)) {
- $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $entry->feed());
- if ($feed === null) {
- $feed = $entry->feed(true);
- }
- } else {
- $feed = $this->feed;
- }
- $article = array(
- 'id' => $entry->guid(),
- 'timestampUsec' => '' . $entry->id(),
- 'categories' => array_values($entry->tags()),
- 'title' => $entry->title(),
- 'author' => $entry->authors(true),
- 'published' => $entry->date(true),
- 'updated' => $entry->date(true),
- 'alternate' => array(array(
- 'href' => htmlspecialchars_decode($entry->link(), ENT_QUOTES),
- 'type' => 'text/html',
- )),
- 'content' => array(
- 'content' => $entry->content(),
- ),
- 'origin' => array(
- 'streamId' => $feed == null ? '' : $feed->id(),
- 'title' => $feed == null ? '' : $feed->name(),
- 'htmlUrl' => $feed == null ? '' : $feed->website(),
- 'feedUrl' => $feed == null ? '' : $feed->url(),
- )
- );
- $article['categories'][] = $entry->isRead() ? 'user/-/state/com.google/read' : 'user/-/state/com.google/unread';
- if ($entry->isFavorite()) {
- $article['categories'][] = 'user/-/state/com.google/starred';
- }
- $tagNames = isset($this->entryIdsTagNames['e_' . $entry->id()]) ? $this->entryIdsTagNames['e_' . $entry->id()] : array();
- foreach ($tagNames as $tagName) {
- $article['categories'][] = 'user/-/label/' . $tagName;
+ $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');
+
$line = json_encode($article, $options);
if ($line != '') {
if ($first) {
diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml
index 6f6044463..1e9e9afd2 100644
--- a/app/views/helpers/feed/update.phtml
+++ b/app/views/helpers/feed/update.phtml
@@ -69,7 +69,7 @@
<div class="group-controls">
<select name="category" id="category" class="w100">
<?php foreach ($this->categories as $cat) { ?>
- <option value="<?= $cat->id() ?>"<?= $cat->id() == $this->feed->category() ? ' selected="selected"' : '' ?>>
+ <option value="<?= $cat->id() ?>"<?= $cat->id() == $this->feed->categoryId() ? ' selected="selected"' : '' ?>>
<?= $cat->name() ?>
</option>
<?php } ?>
diff --git a/app/views/index/normal.phtml b/app/views/index/normal.phtml
index 348a42e89..6a4cb77eb 100644
--- a/app/views/index/normal.phtml
+++ b/app/views/index/normal.phtml
@@ -37,9 +37,9 @@ $today = @strtotime('today');
$this->entry = $item;
// We most likely already have the feed object in cache
- $this->feed = FreshRSS_CategoryDAO::findFeed($this->categories, $this->entry->feed());
+ $this->feed = FreshRSS_CategoryDAO::findFeed($this->categories, $this->entry->feedId());
if ($this->feed == null) {
- $this->feed = $this->entry->feed(true);
+ $this->feed = $this->entry->feed();
if ($this->feed == null) {
$this->feed = FreshRSS_Feed::example();
}
diff --git a/app/views/index/reader.phtml b/app/views/index/reader.phtml
index c9ef7fbd9..334cd4189 100644
--- a/app/views/index/reader.phtml
+++ b/app/views/index/reader.phtml
@@ -47,12 +47,12 @@ $MAX_TAGS_DISPLAYED = FreshRSS_Context::$user_conf->show_tags_max;
}
?><div class="flux<?= !$item->isRead() ? ' not_read' : '' ?><?= $item->isFavorite() ? ' favorite' : '' ?>" id="flux_<?= $item->id() ?>">
<article class="flux_content" dir="auto">
-
+
<div class="content <?= $content_width ?>">
<header>
<?php
- $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $item->feed()); //We most likely already have the feed object in cache
- if (empty($feed)) $feed = $item->feed(true);
+ $feed = FreshRSS_CategoryDAO::findFeed($this->categories, $item->feedId()); //We most likely already have the feed object in cache
+ if ($feed == null) $feed = $item->feed();
$favoriteUrl = array('c' => 'entry', 'a' => 'bookmark', 'params' => array('id' => $item->id()));
if ($item->isFavorite()) {
$favoriteUrl['params']['is_favorite'] = 0;
@@ -134,7 +134,7 @@ $MAX_TAGS_DISPLAYED = FreshRSS_Context::$user_conf->show_tags_max;
</div>
<?php } ?>
</header>
-
+
<div class="text">
<?= $item->content() ?>
</div>
diff --git a/p/api/fever.php b/p/api/fever.php
index d7d4ca603..b7f9b9167 100644
--- a/p/api/fever.php
+++ b/p/api/fever.php
@@ -365,7 +365,7 @@ class FeverAPI
/** @var FreshRSS_Feed $feed */
foreach ($myFeeds as $feed) {
- $ids[$feed->category()][] = $feed->id();
+ $ids[$feed->categoryId()][] = $feed->id();
}
foreach($ids as $category => $feedIds) {
@@ -493,7 +493,7 @@ class FeverAPI
}
$items[] = array(
'id' => '' . $entry->id(),
- 'feed_id' => $entry->feed(false),
+ 'feed_id' => $entry->feedId(),
'title' => escapeToUnicodeAlternative($entry->title(), false),
'author' => escapeToUnicodeAlternative(trim($entry->authors(true), '; '), false),
'html' => $entry->content(),
diff --git a/p/api/greader.php b/p/api/greader.php
index 9a96823d7..1ceb68f0d 100644
--- a/p/api/greader.php
+++ b/p/api/greader.php
@@ -30,13 +30,6 @@ $ORIGINAL_INPUT = file_get_contents('php://input', false, null, 0, 1048576);
if (PHP_INT_SIZE < 8) { //32-bit
/**
- * @param string|int $dec
- * @return string
- */
- function dec2hex($dec) {
- return str_pad(gmp_strval(gmp_init($dec, 10), 16), 16, '0', STR_PAD_LEFT);
- }
- /**
* @param string $hex
* @return string
*/
@@ -46,14 +39,6 @@ if (PHP_INT_SIZE < 8) { //32-bit
}
} else { //64-bit
/**
- * @param string|int $dec
- * @return string
- */
- function dec2hex($dec) {
- //http://code.google.com/p/google-reader-api/wiki/ItemId
- return str_pad(dechex($dec), 16, '0', STR_PAD_LEFT);
- }
- /**
* @param string $hex
* @return string
*/
@@ -526,8 +511,9 @@ function entriesToArray($entries) {
if (empty($entries)) {
return array();
}
- $feedDAO = FreshRSS_Factory::createFeedDao();
- $arrayFeedCategoryNames = $feedDAO->arrayFeedCategoryNames();
+ $catDAO = FreshRSS_Factory::createCategoryDao();
+ $categories = $catDAO->listCategories(true);
+
$tagDAO = FreshRSS_Factory::createTagDao();
$entryIdsTagNames = $tagDAO->getEntryIdsTagNames($entries);
if ($entryIdsTagNames == false) {
@@ -541,65 +527,15 @@ function entriesToArray($entries) {
if ($entry == null) {
continue;
}
- $f_id = $entry->feed();
- if (isset($arrayFeedCategoryNames[$f_id])) {
- $c_name = $arrayFeedCategoryNames[$f_id]['c_name'];
- $f_name = $arrayFeedCategoryNames[$f_id]['name'];
- } else {
- $c_name = '_';
- $f_name = '_';
- }
- $item = array(
- 'id' => 'tag:google.com,2005:reader/item/' . dec2hex($entry->id()), //64-bit hexa http://code.google.com/p/google-reader-api/wiki/ItemId
- 'crawlTimeMsec' => substr($entry->dateAdded(true, true), 0, -3),
- 'timestampUsec' => '' . $entry->dateAdded(true, true), //EasyRSS & Reeder
- 'published' => $entry->date(true),
- 'title' => escapeToUnicodeAlternative($entry->title(), false),
- 'summary' => array('content' => $entry->content()),
- 'canonical' => array(
- array('href' => htmlspecialchars_decode($entry->link(), ENT_QUOTES)),
- ),
- 'alternate' => array(
- array('href' => htmlspecialchars_decode($entry->link(), ENT_QUOTES)),
- ),
- 'categories' => array(
- 'user/-/state/com.google/reading-list',
- 'user/-/label/' . htmlspecialchars_decode($c_name, ENT_QUOTES),
- ),
- 'origin' => array(
- 'streamId' => 'feed/' . $f_id,
- 'title' => escapeToUnicodeAlternative($f_name, true), //EasyRSS
- //'htmlUrl' => $line['f_website'],
- ),
- );
- foreach ($entry->enclosures() as $enclosure) {
- if (!empty($enclosure['url']) && !empty($enclosure['type'])) {
- $media = [
- 'href' => $enclosure['url'],
- 'type' => $enclosure['type'],
- ];
- if (!empty($enclosure['length'])) {
- $media['length'] = intval($enclosure['length']);
- }
- $item['enclosure'][] = $media;
- }
- }
- $author = $entry->authors(true);
- $author = trim($author, '; ');
- if ($author != '') {
- $item['author'] = escapeToUnicodeAlternative($author, false);
- }
- if ($entry->isRead()) {
- $item['categories'][] = 'user/-/state/com.google/read';
- }
- 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/' . htmlspecialchars_decode($tagName, ENT_QUOTES);
+
+ $feed = FreshRSS_CategoryDAO::findFeed($categories, $entry->feedId());
+ $entry->_feed($feed);
+
+ if (isset($entryIdsTagNames['e_' . $entry->id()])) {
+ $entry->_tags($entryIdsTagNames['e_' . $entry->id()]);
}
- $items[] = $item;
+
+ $items[] = $entry->toGReader('compat');
}
return $items;
}