diff --git a/backend.php b/backend.php
index b4b58a787..cee8c26ce 100644
--- a/backend.php
+++ b/backend.php
@@ -211,7 +211,6 @@
case "view":
$id = db_escape_string($_GET["id"]);
- $feed_id = db_escape_string($_GET["feed"]);
$cids = split(",", db_escape_string($_GET["cids"]));
$mode = db_escape_string($_GET["mode"]);
$omode = db_escape_string($_GET["omode"]);
@@ -224,9 +223,9 @@
// just gets marked as read (it already exists in client cache)
if ($mode == "") {
- outputArticleXML($link, $id, $feed_id);
+ outputArticleXML($link, $id, false);
} else if ($mode == "zoom") {
- outputArticleXML($link, $id, $feed_id, true, true);
+ outputArticleXML($link, $id, false, true, true);
} else {
catchupArticleById($link, $id, 0);
ccache_update($link, $feed_id, $_SESSION["uid"]);
@@ -235,7 +234,7 @@
if (!$_SESSION["bw_limit"]) {
foreach ($cids as $cid) {
if ($cid) {
- outputArticleXML($link, $cid, $feed_id, false);
+ outputArticleXML($link, $cid, false, false);
}
}
}
diff --git a/functions.php b/functions.php
index 02521b313..5c285c4e2 100644
--- a/functions.php
+++ b/functions.php
@@ -754,9 +754,8 @@
foreach ($iterator as $item) {
- if ($_GET['xdebug']) {
+ if ($_GET['xdebug'] == 2) {
print_r($item);
-
}
if ($use_simplepie) {
@@ -857,7 +856,7 @@
}
}
- if ($_GET["xdebug"]) {
+ if ($_GET["xdebug"] == 2) {
print "update_rss_feed: content: ";
print_r(htmlspecialchars($entry_content));
}
@@ -1135,7 +1134,7 @@
// do we allow duplicate posts with same GUID in different feeds?
if (get_pref($link, "ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
- $dupcheck_qpart = "AND feed_id = '$feed'";
+ $dupcheck_qpart = "AND (feed_id = '$feed' OR feed_id IS NULL)";
} else {
$dupcheck_qpart = "";
}
@@ -1213,6 +1212,10 @@
$entry_int_id = db_fetch_result($result, 0, "int_id");
}
} else {
+ if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
+ _debug("update_rss_feed: user record FOUND");
+ }
+
$entry_ref_id = db_fetch_result($result, 0, "ref_id");
$entry_int_id = db_fetch_result($result, 0, "int_id");
}
@@ -1589,6 +1592,8 @@
$rtl_content = false, $last_updated = false, $last_error = false,
$fg_content = false, $bg_content = false) {
+ if (!$feed_title) $feed_title = getFeedTitle($link, $feed_id, false);
+
if (file_exists($icon_file) && filesize($icon_file) > 0) {
$feed_icon = "";
} else {
@@ -2467,7 +2472,7 @@
}
} else if ($n_feed == -4) {
$match_part = "true";
- } else if ($n_feed > 0) {
+ } else if ($n_feed >= 0) {
$result = db_query($link, "SELECT id FROM ttrss_feeds
WHERE parent_feed = '$n_feed'
@@ -2503,7 +2508,11 @@
return $unread;
} else {
- $match_part = "feed_id = '$n_feed'";
+ if ($n_feed != 0) {
+ $match_part = "feed_id = '$n_feed'";
+ } else {
+ $match_part = "feed_id IS NULL";
+ }
}
} else if ($feed < -10) {
@@ -2514,12 +2523,18 @@
}
if ($match_part) {
-
+
+ if ($n_feed != 0) {
+ $from_qpart = "ttrss_user_entries,ttrss_feeds,ttrss_entries";
+ $feeds_qpart = "ttrss_feeds.hidden = false AND
+ ttrss_user_entries.feed_id = ttrss_feeds.id AND";
+ } else {
+ $from_qpart = "ttrss_user_entries,ttrss_entries";
+ }
+
$result = db_query($link, "SELECT count(int_id) AS unread
- FROM ttrss_user_entries,ttrss_feeds,ttrss_entries WHERE
- ttrss_user_entries.feed_id = ttrss_feeds.id AND
+ FROM $from_qpart WHERE
ttrss_user_entries.ref_id = ttrss_entries.id AND
- ttrss_feeds.hidden = false AND
$age_qpart AND
$unread_qpart AND ($match_part) AND ttrss_user_entries.owner_uid = " . $owner_uid);
@@ -2633,7 +2648,7 @@
$ret_arr = array();
- for ($i = -1; $i >= -4; $i--) {
+ for ($i = 0; $i >= -4; $i--) {
$count = getFeedUnread($link, $i);
@@ -2969,6 +2984,8 @@
return __("Fresh articles");
} else if ($id == -4) {
return __("All articles");
+ } else if ($id == 0) {
+ return __("Archived articles");
} else if ($id < -10) {
$label_id = -$id - 11;
$result = db_query($link, "SELECT caption FROM ttrss_labels2 WHERE id = '$label_id'");
@@ -3231,7 +3248,7 @@
$query_strategy_part = "ttrss_entries.id > 0";
$vfeed_query_part = "(SELECT title FROM ttrss_feeds WHERE
id = feed_id) as feed_title,";
- } else if ($feed >= 0 && $search && $search_mode == "this_cat") {
+ } else if ($feed > 0 && $search && $search_mode == "this_cat") {
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
@@ -3260,7 +3277,7 @@
$query_strategy_part = "ttrss_entries.id > 0";
}
- } else if ($feed >= 0) {
+ } else if ($feed > 0) {
if ($cat_view) {
@@ -3292,6 +3309,8 @@
$query_strategy_part = "feed_id = '$feed'";
}
}
+ } else if ($feed == 0) { // starred virtual feed
+ $query_strategy_part = "feed_id IS NULL";
} else if ($feed == -1) { // starred virtual feed
$query_strategy_part = "marked = true";
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
@@ -3450,6 +3469,16 @@
} */
}
+ if ($feed != "0") {
+ $from_qpart = "ttrss_entries,ttrss_user_entries,ttrss_feeds$ext_tables_part";
+ $feed_check_qpart = "ttrss_feeds.hidden = false AND
+ ttrss_user_entries.feed_id = ttrss_feeds.id AND";
+
+ } else {
+ $from_qpart = "ttrss_entries,ttrss_user_entries$ext_tables_part
+ LEFT JOIN ttrss_feeds ON (feed_id = ttrss_feeds.id)";
+ }
+
$query = "SELECT DISTINCT
guid,
ttrss_entries.id,ttrss_entries.title,
@@ -3462,11 +3491,10 @@
".SUBSTRING_FOR_DATE."(updated,1,19) as updated_noms,
author,score
FROM
- ttrss_entries,ttrss_user_entries,ttrss_feeds$ext_tables_part
+ $from_qpart
WHERE
$group_limit_part
- ttrss_feeds.hidden = false AND
- ttrss_user_entries.feed_id = ttrss_feeds.id AND
+ $feed_check_qpart
ttrss_user_entries.ref_id = ttrss_entries.id AND
ttrss_user_entries.owner_uid = '$owner_uid' AND
$search_query_part
@@ -3507,6 +3535,8 @@
$limit_query_part");
}
+ if (!$feed_title) $feed_title = getFeedTitle($link, $feed_id);
+
return array($result, $feed_title, $feed_site_url, $last_error);
}
@@ -4017,6 +4047,9 @@
$catchup_feed_link = "javascript:catchupCurrentFeed()";
$catchup_sel_link = "javascript:catchupSelection()";
+ $archive_sel_link = "javascript:archiveSelection()";
+ $delete_sel_link = "javascript:deleteSelection()";
+
if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
$sel_all_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)";
@@ -4116,6 +4149,15 @@
print "
".__('Entire feed').
"";
+ if ($feed_id != "0") {
+ print "".__('Selection:')."
+ ".__('Archive')."";
+ } else {
+ print "".__('Selection:')."
+ ".__('Move back')."
+ ".__('Delete')."";
+ }
+
//print "--------";
print "".__('Assign label:')."";
@@ -4194,41 +4236,41 @@
$num_published = getFeedUnread($link, -2);
$num_fresh = getFeedUnread($link, -3);
$num_total = getFeedUnread($link, -4);
+ $num_archive = getFeedUnread($link, 0);
$class = "virt";
if ($num_total > 0) $class .= "Unread";
- printFeedEntry(-4, $class, __("All articles"), $num_total,
+ printFeedEntry(-4, $class, false, $num_total,
+ "images/tag.png", $link);
+
+ $class = "virt";
+
+ if ($num_archive > 0) $class .= "Unread";
+
+ printFeedEntry(0, $class, false, $num_archive,
"images/tag.png", $link);
$class = "virt";
if ($num_fresh > 0) $class .= "Unread";
- printFeedEntry(-3, $class, __("Fresh articles"), $num_fresh,
+ printFeedEntry(-3, $class, false, $num_fresh,
"images/fresh.png", $link);
$class = "virt";
if ($num_starred > 0) $class .= "Unread";
- $is_ie = (strpos($_SESSION["client.userAgent"], "MSIE") !== false);
-
- if ($is_ie) {
- $mark_img_ext = "gif";
- } else {
- $mark_img_ext = "png";
- }
-
- printFeedEntry(-1, $class, __("Starred articles"), $num_starred,
- "images/mark_set.$mark_img_ext", $link);
+ printFeedEntry(-1, $class, false, $num_starred,
+ "images/mark_set.png", $link);
$class = "virt";
if ($num_published > 0) $class .= "Unread";
- printFeedEntry(-2, $class, __("Published articles"), $num_published,
+ printFeedEntry(-2, $class, false, $num_published,
"images/pub_set.gif", $link);
if (get_pref($link, 'ENABLE_FEED_CATS')) {
@@ -4616,12 +4658,12 @@
$zoom_mode = false) {
/* we can figure out feed_id from article id anyway, why do we
- * pass feed_id here? */
+ * pass feed_id here? let's ignore the argument :( */
$result = db_query($link, "SELECT feed_id FROM ttrss_user_entries
WHERE ref_id = '$id'");
- $feed_id = db_fetch_result($result, 0, "feed_id");
+ $feed_id = (int) db_fetch_result($result, 0, "feed_id");
if (!$zoom_mode) { print " ";
# } else {
- print "";
+ print " | ";
print "$updated_fmt | ";
+ print "$updated_fmt | ";
print "$score_pic | ";
@@ -5600,8 +5642,14 @@
* @return void
*/
function clear_feed_articles($link, $id) {
- $result = db_query($link, "DELETE FROM ttrss_user_entries
+
+ if ($id != 0) {
+ $result = db_query($link, "DELETE FROM ttrss_user_entries
WHERE feed_id = '$id' AND marked = false AND owner_uid = " . $_SESSION["uid"]);
+ } else {
+ $result = db_query($link, "DELETE FROM ttrss_user_entries
+ WHERE feed_id IS NULL AND marked = false AND owner_uid = " . $_SESSION["uid"]);
+ }
$result = db_query($link, "DELETE FROM ttrss_entries WHERE
(SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0");
@@ -6320,9 +6368,22 @@
function remove_feed($link, $id, $owner_uid) {
if ($id > 0) {
+
+ /* save starred articles in Archived feed */
+
+ db_query($link, "BEGIN");
+
+ db_query($link, "UPDATE ttrss_user_entries SET feed_id = NULL
+ WHERE feed_id = '$id' AND
+ marked = true AND owner_uid = $owner_uid");
+
+ /* remove the feed */
+
db_query($link, "DELETE FROM ttrss_feeds
WHERE id = '$id' AND owner_uid = $owner_uid");
+ db_query($link, "COMMIT");
+
if (file_exists(ICONS_DIR . "/$id.ico")) {
unlink(ICONS_DIR . "/$id.ico");
}
diff --git a/modules/backend-rpc.php b/modules/backend-rpc.php
index 686602d6f..326c669fb 100644
--- a/modules/backend-rpc.php
+++ b/modules/backend-rpc.php
@@ -86,6 +86,57 @@
return;
}
+ if ($subop == "delete") {
+ $ids = db_escape_string($_GET["ids"]);
+
+ $result = db_query($link, "DELETE FROM ttrss_user_entries
+ WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
+
+ print "";
+ getGlobalCounters($link);
+ if (get_pref($link, 'ENABLE_FEED_CATS')) {
+ getCategoryCounters($link);
+ }
+ print "";
+
+ return;
+ }
+
+ if ($subop == "unarchive") {
+ $ids = db_escape_string($_GET["ids"]);
+
+ $result = db_query($link, "UPDATE ttrss_user_entries
+ SET feed_id = orig_feed_id
+ WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
+
+ print "";
+ getGlobalCounters($link);
+ if (get_pref($link, 'ENABLE_FEED_CATS')) {
+ getCategoryCounters($link);
+ }
+ print "";
+
+ return;
+ }
+
+ if ($subop == "archive") {
+ $ids = db_escape_string($_GET["ids"]);
+
+ $result = db_query($link, "UPDATE ttrss_user_entries
+ SET orig_feed_id = feed_id, feed_id = NULL, marked = true
+ WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
+
+ print "";
+ getGlobalCounters($link);
+ if (get_pref($link, 'ENABLE_FEED_CATS')) {
+ getCategoryCounters($link);
+ }
+ print "";
+
+ return;
+ }
+
+
if ($subop == "publ") {
$pub = $_REQUEST["pub"];
$id = db_escape_string($_REQUEST["id"]);
diff --git a/schema/ttrss_schema_mysql.sql b/schema/ttrss_schema_mysql.sql
index 95edaffdd..c6de60287 100644
--- a/schema/ttrss_schema_mysql.sql
+++ b/schema/ttrss_schema_mysql.sql
@@ -133,7 +133,8 @@ create index ttrss_entries_date_entered_index on ttrss_entries(date_entered);
create table ttrss_user_entries (
int_id integer not null primary key auto_increment,
ref_id integer not null,
- feed_id int not null,
+ feed_id int,
+ orig_feed_id int,
owner_uid integer not null,
marked bool not null default 0,
published bool not null default 0,
@@ -145,6 +146,8 @@ create table ttrss_user_entries (
foreign key (ref_id) references ttrss_entries(id) ON DELETE CASCADE,
index (feed_id),
foreign key (feed_id) references ttrss_feeds(id) ON DELETE CASCADE,
+ index (orig_feed_id),
+ foreign key (orig_feed_id) references ttrss_feeds(id) ON DELETE SET NULL,
index (owner_uid),
foreign key (owner_uid) references ttrss_users(id) ON DELETE CASCADE) TYPE=InnoDB;
@@ -226,7 +229,7 @@ create table ttrss_tags (id integer primary key auto_increment,
create table ttrss_version (schema_version int not null) TYPE=InnoDB;
-insert into ttrss_version values (59);
+insert into ttrss_version values (60);
create table ttrss_enclosures (id serial not null primary key,
content_url text not null,
diff --git a/schema/ttrss_schema_pgsql.sql b/schema/ttrss_schema_pgsql.sql
index 0b6f719e1..7afebb5d9 100644
--- a/schema/ttrss_schema_pgsql.sql
+++ b/schema/ttrss_schema_pgsql.sql
@@ -121,7 +121,8 @@ create index ttrss_entries_date_entered_index on ttrss_entries(date_entered);
create table ttrss_user_entries (
int_id serial not null primary key,
ref_id integer not null references ttrss_entries(id) ON DELETE CASCADE,
- feed_id int references ttrss_feeds(id) ON DELETE CASCADE not null,
+ feed_id int references ttrss_feeds(id) ON DELETE CASCADE,
+ orig_feed_id int references ttrss_feeds(id) ON DELETE SET NULL,
owner_uid integer not null references ttrss_users(id) ON DELETE CASCADE,
marked boolean not null default false,
published boolean not null default false,
@@ -202,7 +203,7 @@ create index ttrss_tags_owner_uid_index on ttrss_tags(owner_uid);
create table ttrss_version (schema_version int not null);
-insert into ttrss_version values (59);
+insert into ttrss_version values (60);
create table ttrss_enclosures (id serial not null primary key,
content_url text not null,
diff --git a/schema/versions/mysql/60.sql b/schema/versions/mysql/60.sql
new file mode 100644
index 000000000..a2c023354
--- /dev/null
+++ b/schema/versions/mysql/60.sql
@@ -0,0 +1,12 @@
+begin;
+
+alter table ttrss_user_entries change feed_id feed_id integer null;
+
+alter table ttrss_user_entries add column orig_feed_id integer;
+update ttrss_user_entries set orig_feed_id = NULL;
+
+alter table ttrss_user_entries add constraint FOREIGN KEY (orig_feed_id) REFERENCES ttrss_feeds(id) ON DELETE SET NULL;
+
+update ttrss_version set schema_version = 60;
+
+commit;
diff --git a/schema/versions/pgsql/60.sql b/schema/versions/pgsql/60.sql
new file mode 100644
index 000000000..39a2e202b
--- /dev/null
+++ b/schema/versions/pgsql/60.sql
@@ -0,0 +1,12 @@
+begin;
+
+alter table ttrss_user_entries alter column feed_id drop not null;
+
+alter table ttrss_user_entries add column orig_feed_id integer;
+update ttrss_user_entries set orig_feed_id = NULL;
+
+alter table ttrss_user_entries add constraint "$4" FOREIGN KEY (orig_feed_id) REFERENCES ttrss_feeds(id) ON DELETE SET NULL;
+
+update ttrss_version set schema_version = 60;
+
+commit;
diff --git a/viewfeed.js b/viewfeed.js
index 9515cca6d..ef3ab2c6c 100644
--- a/viewfeed.js
+++ b/viewfeed.js
@@ -1321,6 +1321,106 @@ function catchupPage() {
}
}
+function deleteSelection() {
+
+ try {
+
+ var rows;
+
+ if ($("headlinesList")) {
+ rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
+ } else {
+ rows = cdmGetSelectedArticles();
+ }
+
+ if (rows.length == 0) {
+ alert(__("No articles are selected."));
+ return;
+ }
+
+
+ var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
+ var str;
+ var op;
+
+ if (getActiveFeedId() != 0) {
+ str = __("Delete %d selected articles in %s?");
+ } else {
+ str = __("Delete %d selected articles?");
+ }
+
+ str = str.replace("%d", rows.length);
+ str = str.replace("%s", fn);
+
+ if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
+ return;
+ }
+
+ query = "backend.php?op=rpc&subop=delete&ids=" + param_escape(rows);
+
+ debug(query);
+
+ new Ajax.Request(query, {
+ onComplete: function(transport) {
+ viewCurrentFeed();
+ } });
+
+ } catch (e) {
+ exception_error("archiveSelection", e);
+ }
+}
+
+function archiveSelection() {
+
+ try {
+
+ var rows;
+
+ if ($("headlinesList")) {
+ rows = getSelectedTableRowIds("headlinesList", "RROW", "RCHK");
+ } else {
+ rows = cdmGetSelectedArticles();
+ }
+
+ if (rows.length == 0) {
+ alert(__("No articles are selected."));
+ return;
+ }
+
+
+ var fn = getFeedName(getActiveFeedId(), activeFeedIsCat());
+ var str;
+ var op;
+
+ if (getActiveFeedId() != 0) {
+ str = __("Archive %d selected articles in %s?");
+ op = "archive";
+ } else {
+ str = __("Move %d archived articles back?");
+ op = "unarchive";
+ }
+
+ str = str.replace("%d", rows.length);
+ str = str.replace("%s", fn);
+
+ if (getInitParam("confirm_feed_catchup") == 1 && !confirm(str)) {
+ return;
+ }
+
+ query = "backend.php?op=rpc&subop="+op+"&ids=" + param_escape(rows);
+
+ debug(query);
+
+ new Ajax.Request(query, {
+ onComplete: function(transport) {
+ viewCurrentFeed();
+ } });
+
+ } catch (e) {
+ exception_error("archiveSelection", e);
+ }
+}
+
function catchupSelection() {
try {