Browse Source

initial work on nested categories

Andrew Dolgov 11 years ago
parent
commit
2a060a9456
4 changed files with 246 additions and 30 deletions
  1. 123 2
      classes/feeds.php
  2. 118 23
      classes/pref_feeds.php
  3. 1 1
      include/functions.php
  4. 4 4
      js/PrefFeedTree.js

+ 123 - 2
classes/feeds.php

@@ -842,6 +842,8 @@ class Feeds extends Protected_Handler {
 			}
 		}
 
+		$this->feedlist_process_category('root', &$feedlist);
+
 /*		if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
 			if (get_pref($this->link, "FEEDS_SORT_BY_UNREAD")) {
 				$order_by_qpart = "order_id,category,unread DESC,title";
@@ -858,12 +860,125 @@ class Feeds extends Protected_Handler {
 
 		/* real feeds */
 
+		/* if ($enable_cats)
+			$order_by_qpart = "ttrss_feed_categories.order_id,category,
+				ttrss_feeds.order_id,title";
+		else
+			$order_by_qpart = "title";
+
+		$query = "SELECT ttrss_feeds.id, ttrss_feeds.title,
+			".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated_noms,
+			cat_id,last_error,
+			COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."') AS category,
+			ttrss_feed_categories.collapsed,
+			value AS unread
+			FROM ttrss_feeds LEFT JOIN ttrss_feed_categories
+				ON (ttrss_feed_categories.id = cat_id)
+			LEFT JOIN ttrss_counters_cache
+				ON
+					(ttrss_feeds.id = feed_id)
+			WHERE
+				ttrss_feeds.owner_uid = '$owner_uid' AND parent_cat IS NULL
+			ORDER BY $order_by_qpart";
+
+		$result = db_query($this->link, $query);
+
+		$actid = $_REQUEST["actid"];
+
+		if (db_num_rows($result) > 0) {
+
+			$category = "";
+
+			if (!$enable_cats)
+				$cat['items'] = array();
+			else
+				$cat = false;
+
+			while ($line = db_fetch_assoc($result)) {
+
+				$feed = htmlspecialchars(trim($line["title"]));
+
+				if (!$feed) $feed = "[Untitled]";
+
+				$feed_id = $line["id"];
+				$unread = $line["unread"];
+
+				$cat_id = $line["cat_id"];
+				$tmp_category = $line["category"];
+
+				if ($category != $tmp_category && $enable_cats) {
+
+					$category = $tmp_category;
+
+					$collapsed = sql_bool_to_bool($line["collapsed"]);
+
+					// workaround for NULL category
+					if ($category == __("Uncategorized")) {
+						$collapsed = get_pref($this->link, "_COLLAPSED_UNCAT");
+					}
+
+					if ($cat) array_push($feedlist['items'], $cat);
+
+					$cat = $this->feedlist_init_cat($cat_id, $collapsed);
+				}
+
+				$updated = make_local_datetime($this->link, $line["updated_noms"], false);
+
+				array_push($cat['items'], $this->feedlist_init_feed($feed_id,
+					$feed, $unread, $line['last_error'], $updated));
+			}
+
+			if ($enable_cats) {
+				array_push($feedlist['items'], $cat);
+			} else {
+				$feedlist['items'] = array_merge($feedlist['items'], $cat['items']);
+			}
+
+		} */
+
+		return $feedlist;
+	}
+
+	private function feedlist_process_category($cat_id, &$feedlist) {
+		$owner_uid = $_SESSION['uid'];
+		$enable_cats = get_pref($this->link, 'ENABLE_FEED_CATS');
+
+		if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
+			if (get_pref($this->link, "FEEDS_SORT_BY_UNREAD")) {
+				$order_by_qpart = "order_id,category,unread DESC,title";
+			} else {
+				$order_by_qpart = "order_id,category,title";
+			}
+		} else {
+			if (get_pref($this->link, "FEEDS_SORT_BY_UNREAD")) {
+				$order_by_qpart = "unread DESC,title";
+			} else {
+				$order_by_qpart = "title";
+			}
+		}
+
+		if ($enable_cats)
+			$order_by_qpart = "ttrss_feed_categories.order_id,category,
+				ttrss_feeds.order_id,title";
+		else
+			$order_by_qpart = "title";
+
+		/* real feeds */
+
 		if ($enable_cats)
 			$order_by_qpart = "ttrss_feed_categories.order_id,category,
 				ttrss_feeds.order_id,title";
 		else
 			$order_by_qpart = "title";
 
+		if (!$enable_cats) {
+			$parent_qpart = "true";
+		} else if ($cat_id == 'root') {
+			$parent_qpart = 'parent_cat IS NULL';
+		} else {
+			$parent_qpart = 'parent_cat = '.db_escape_string($cat_id);
+		}
+
 		$query = "SELECT ttrss_feeds.id, ttrss_feeds.title,
 			".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated_noms,
 			cat_id,last_error,
@@ -876,7 +991,7 @@ class Feeds extends Protected_Handler {
 				ON
 					(ttrss_feeds.id = feed_id)
 			WHERE
-				ttrss_feeds.owner_uid = '$owner_uid'
+				ttrss_feeds.owner_uid = '$owner_uid' AND $parent_qpart
 			ORDER BY $order_by_qpart";
 
 		$result = db_query($this->link, $query);
@@ -918,6 +1033,13 @@ class Feeds extends Protected_Handler {
 					if ($cat) array_push($feedlist['items'], $cat);
 
 					$cat = $this->feedlist_init_cat($cat_id, $collapsed);
+
+					if ($cat_id) {
+						$cat_items = $this->feedlist_process_category($cat_id, &$feedlist);
+						if (count($cat_items) > 0) {
+							array_push($cat['items'], $cat_items);
+						}
+					}
 				}
 
 				$updated = make_local_datetime($this->link, $line["updated_noms"], false);
@@ -934,7 +1056,6 @@ class Feeds extends Protected_Handler {
 
 		}
 
-		return $feedlist;
 	}
 
 

+ 118 - 23
classes/pref_feeds.php

@@ -32,6 +32,55 @@ class Pref_Feeds extends Protected_Handler {
 		return;
 	}
 
+	private function get_category_items($cat_id) {
+
+		$items = array();
+
+		$result = db_query($this->link, "SELECT id, title FROM ttrss_feed_categories
+				WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat = '$cat_id' ORDER BY order_id, title");
+
+		while ($line = db_fetch_assoc($result)) {
+
+			$cat = array();
+			$cat['id'] = 'CAT:' . $line['id'];
+			$cat['bare_id'] = $feed_id;
+			$cat['name'] = $line['title'];
+			$cat['items'] = array();
+			$cat['checkbox'] = false;
+			$cat['type'] = 'category';
+
+			$cat['items'] = $this->get_category_items($line['id']);
+
+			$cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
+
+			if (count($cat['items']) > 0 || $show_empty_cats)
+				array_push($items, $cat);
+
+		}
+
+		$feed_result = db_query($this->link, "SELECT id, title, last_error,
+			".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
+			FROM ttrss_feeds
+			WHERE cat_id = '$cat_id' AND owner_uid = ".$_SESSION["uid"].
+			"$search_qpart ORDER BY order_id, title");
+
+		while ($feed_line = db_fetch_assoc($feed_result)) {
+			$feed = array();
+			$feed['id'] = 'FEED:' . $feed_line['id'];
+			$feed['bare_id'] = $feed_line['id'];
+			$feed['name'] = $feed_line['title'];
+			$feed['checkbox'] = false;
+			$feed['error'] = $feed_line['last_error'];
+			$feed['icon'] = getFeedIcon($feed_line['id']);
+			$feed['param'] = make_local_datetime($this->link,
+				$feed_line['last_updated'], true);
+
+			array_push($items, $feed);
+		}
+
+		return $items;
+	}
+
 	function getfeedtree() {
 
 		$search = $_SESSION["prefs_feed_search"];
@@ -48,7 +97,7 @@ class Pref_Feeds extends Protected_Handler {
 			$show_empty_cats = get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
 
 			$result = db_query($this->link, "SELECT id, title FROM ttrss_feed_categories
-				WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY order_id, title");
+				WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title");
 
 			while ($line = db_fetch_assoc($result)) {
 				$cat = array();
@@ -59,25 +108,7 @@ class Pref_Feeds extends Protected_Handler {
 				$cat['checkbox'] = false;
 				$cat['type'] = 'category';
 
-				$feed_result = db_query($this->link, "SELECT id, title, last_error,
-					".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
-					FROM ttrss_feeds
-					WHERE cat_id = '".$line['id']."' AND owner_uid = ".$_SESSION["uid"].
-					"$search_qpart ORDER BY order_id, title");
-
-				while ($feed_line = db_fetch_assoc($feed_result)) {
-					$feed = array();
-					$feed['id'] = 'FEED:' . $feed_line['id'];
-					$feed['bare_id'] = $feed_line['id'];
-					$feed['name'] = $feed_line['title'];
-					$feed['checkbox'] = false;
-					$feed['error'] = $feed_line['last_error'];
-					$feed['icon'] = getFeedIcon($feed_line['id']);
-					$feed['param'] = make_local_datetime($this->link,
-						$feed_line['last_updated'], true);
-
-					array_push($cat['items'], $feed);
-				}
+				$cat['items'] = $this->get_category_items($line['id']);
 
 				$cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
 
@@ -176,17 +207,77 @@ class Pref_Feeds extends Protected_Handler {
 			(get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true'));
 	}
 
+	private function process_category_order($data_map, $item_id, $parent_id = false) {
+#		print "C: $item_id P: $parent_id\n";
+		$bare_id = substr($item_id, strpos($item_id, ':')+1);
+
+		if ($item_id != 'root') {
+			if ($parent_id && $parent_id != 'root') {
+				$parent_bare_id = substr($parent_id, strpos($parent_id, ':')+1);
+				$parent_qpart = db_escape_string($parent_bare_id);
+			} else {
+				$parent_qpart = 'NULL';
+			}
+
+			db_query($this->link, "UPDATE ttrss_feed_categories
+				SET parent_cat = $parent_qpart WHERE id = '$bare_id' AND
+				owner_uid = " . $_SESSION["uid"]);
+		}
+
+		$order_id = 0;
+
+		$cat = $data_map[$item_id];
+
+		if ($cat && is_array($cat)) {
+			foreach ($cat as $item) {
+				$id = $item['_reference'];
+				$bare_id = substr($id, strpos($id, ':')+1);
+
+#				print "[$order_id] $id/$bare_id\n";
+
+				if ($item['_reference']) {
+
+					if (strpos($id, "FEED") === 0) {
+
+						db_query($this->link, "UPDATE ttrss_feeds
+								SET order_id = '$order_id' WHERE id = '$bare_id' AND
+								owner_uid = " . $_SESSION["uid"]);
+
+					} else if (strpos($id, "CAT:") === 0) {
+						$this->process_category_order(&$data_map, $item['_reference'], $item_id);
+
+						if ($item_id != 'root') {
+							$parent_qpart = db_escape_string($bare_id);
+						} else {
+							$parent_qpart = 'NULL';
+						}
+
+						db_query($this->link, "UPDATE ttrss_feed_categories
+								SET order_id = '$order_id' WHERE id = '$bare_id' AND
+								owner_uid = " . $_SESSION["uid"]);
+					}
+				}
+
+				++$order_id;
+			}
+		}
+	}
+
 	function savefeedorder() {
 		$data = json_decode($_POST['payload'], true);
 
+		#file_put_contents("/tmp/saveorder.json", $_POST['payload']);
+		#$data = json_decode(file_get_contents("/tmp/saveorder.json"), true);
+
 		if (is_array($data) && is_array($data['items'])) {
 			$cat_order_id = 0;
 
 			$data_map = array();
+			$root_item = false;
 
 			foreach ($data['items'] as $item) {
 
-				if ($item['id'] != 'root') {
+#				if ($item['id'] != 'root') {
 					if (is_array($item['items'])) {
 						if (isset($item['items']['_reference'])) {
 							$data_map[$item['id']] = array($item['items']);
@@ -194,10 +285,14 @@ class Pref_Feeds extends Protected_Handler {
 							$data_map[$item['id']] =& $item['items'];
 						}
 					}
+				if ($item['id'] == 'root') {
+					$root_item = $item['id'];
 				}
 			}
 
-			foreach ($data['items'][0]['items'] as $item) {
+			$this->process_category_order(&$data_map, $root_item);
+
+			/* foreach ($data['items'][0]['items'] as $item) {
 				$id = $item['_reference'];
 				$bare_id = substr($id, strpos($id, ':')+1);
 
@@ -230,7 +325,7 @@ class Pref_Feeds extends Protected_Handler {
 						++$feed_order_id;
 					}
 				}
-			}
+			} */
 		}
 
 		return;

+ 1 - 1
include/functions.php

@@ -1,6 +1,6 @@
 <?php
 	define('EXPECTED_CONFIG_VERSION', 25);
-	define('SCHEMA_VERSION', 92);
+	define('SCHEMA_VERSION', 93);
 
 	mb_internal_encoding("UTF-8");
 	date_default_timezone_set('UTC');

+ 4 - 4
js/PrefFeedTree.js

@@ -5,7 +5,7 @@ dojo.require("lib.CheckBoxTree");
 dojo.require("dojo.data.ItemFileWriteStore");
 
 dojo.declare("fox.PrefFeedStore", dojo.data.ItemFileWriteStore, {
-	
+
 	_saveEverything: function(saveCompleteCallback, saveFailedCallback,
 								newFileContentString) {
 
@@ -17,7 +17,7 @@ dojo.declare("fox.PrefFeedStore", dojo.data.ItemFileWriteStore, {
 			load: saveCompleteCallback});
 	},
 
-});		
+});
 
 dojo.declare("fox.PrefFeedTree", lib.CheckBoxTree, {
 	_createTreeNode: function(args) {
@@ -42,7 +42,7 @@ dojo.declare("fox.PrefFeedTree", lib.CheckBoxTree, {
 		this.tree.model.store.save();
 	},
 	getRowClass: function (item, opened) {
-		return (!item.error || item.error == '') ? "dijitTreeRow" : 
+		return (!item.error || item.error == '') ? "dijitTreeRow" :
 			"dijitTreeRow Error";
 	},
 	getIconClass: function (item, opened) {
@@ -71,7 +71,7 @@ dojo.declare("fox.PrefFeedTree", lib.CheckBoxTree, {
 			return ((id.match("CAT:") && position == "over") ||
 				(id.match("FEED:") && position != "over"));
 		} else if (source_id.match("CAT:")) {
-			return ((id.match("CAT:") && position != "over") ||
+			return ((id.match("CAT:") && !id.match("CAT:0")) ||
 				(id.match("root") && position == "over"));
 		}
 	},