From 413670b09d8e13a5c7dd214d10e019b5bed345aa Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Mon, 16 Jun 2008 20:07:17 +0000 Subject: [PATCH] Restore tag rename and delete Tag comparisons are now case-insensitive, and old tags with case differences are migrated to the most-used tag or the tag linked to the oldest item --- .../content/zotero/bindings/tagselector.xml | 4 +- chrome/content/zotero/xpcom/data/tags.js | 18 ++++- chrome/content/zotero/xpcom/schema.js | 70 +++++++++++++++++-- 3 files changed, 80 insertions(+), 12 deletions(-) diff --git a/chrome/content/zotero/bindings/tagselector.xml b/chrome/content/zotero/bindings/tagselector.xml index 9e2f33559..771e9bfc9 100644 --- a/chrome/content/zotero/bindings/tagselector.xml +++ b/chrome/content/zotero/bindings/tagselector.xml @@ -555,9 +555,7 @@ } } - for each(var tagID in tagIDs) { - Zotero.Tags.remove(tagID); - } + Zotero.Tags.erase(tagIDs); Zotero.DB.commitTransaction() } diff --git a/chrome/content/zotero/xpcom/data/tags.js b/chrome/content/zotero/xpcom/data/tags.js index b46786b08..32a938708 100644 --- a/chrome/content/zotero/xpcom/data/tags.js +++ b/chrome/content/zotero/xpcom/data/tags.js @@ -75,6 +75,7 @@ Zotero.Tags = new function() { return _tagsByID[tagID].name; } + // Populate cache var tag = this.get(tagID); return _tagsByID[tagID] ? _tagsByID[tagID].name : false; @@ -85,6 +86,8 @@ Zotero.Tags = new function() { * Returns the tagID matching given tag and type */ function getID(name, type) { + name = name.toLowerCase(); + if (_tags[type] && _tags[type]['_' + name]) { return _tags[type]['_' + name]; } @@ -252,17 +255,26 @@ Zotero.Tags = new function() { var oldName = tagObj.name; var oldType = tagObj.type; var notifierData = {}; - notifierData[tagID] = { old: tag.serialize() }; + notifierData[tagID] = { old: tagObj.serialize() }; if (oldName == name) { Zotero.DB.commitTransaction(); return; } - // Check if the new tag already exists var sql = "SELECT tagID FROM tags WHERE name=? AND type=0"; var existingTagID = Zotero.DB.valueQuery(sql, name); - if (existingTagID) { + // New tag already exists as manual tag + if (existingTagID + // Tag check is case-insensitive, so make sure we have a + // different tag + && existingTagID != tagID) { + // Change case of existing manual tag before switching automatic + if (oldName.toLowerCase() == name.toLowerCase()) { + var sql = "UPDATE tags SET name=? WHERE tagID=?"; + Zotero.DB.query(sql, [name, existingTagID]); + } + var itemIDs = this.getTagItems(tagID); var existingItemIDs = this.getTagItems(existingTagID); diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index 48844b1f7..19e31f32a 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -1449,14 +1449,72 @@ Zotero.Schema = new function(){ statement.reset(); // Tags - var tags = Zotero.DB.query("SELECT * FROM tags"); + var tags = Zotero.DB.query("SELECT tagID, tag AS tag, tagType FROM tags"); + var newTags = []; + var cases = {}; + if (tags) { + // Find tags with multiple case forms + for each(var row in tags) { + var l = row.tag.toLowerCase(); + if (!cases[l]) { + cases[l] = []; + } + if (cases[l].indexOf(row.tag) == -1) { + cases[l].push(row.tag); + } + } + var done = {}; + for each(var row in tags) { + var l = row.tag.toLowerCase(); + + if (done[l]) { + continue; + } + done[l] = true; + + // Only one tag -- use + if (cases[l].length == 1) { + newTags.push(row); + continue; + } + + // Use most frequent + var counts = Zotero.DB.query("SELECT tag, COUNT(*) AS numItems FROM tags NATURAL JOIN itemTags WHERE tag LIKE ? GROUP BY tag ORDER BY numItems DESC", l); + if (counts[0].numItems != counts[1].numItems) { + var newTag = counts[0].tag; + } + // Use earliest + else { + var newTag = Zotero.DB.valueQuery("SELECT tag FROM tags NATURAL JOIN itemTags WHERE tag IN (SELECT tag FROM tags NATURAL JOIN itemTags NATURAL JOIN items WHERE tag LIKE ? ORDER BY dateAdded LIMIT 1) GROUP BY tag", l); + } + + // Point old to new + var types = Zotero.DB.columnQuery("SELECT DISTINCT tagType FROM tags WHERE tag LIKE ?", l); + for each(var type in types) { + var newTagID = Zotero.DB.valueQuery("SELECT tagID FROM tags WHERE tag=? AND tagType=?", [newTag, type]); + var oldIDs = Zotero.DB.columnQuery("SELECT tagID FROM tags WHERE tag LIKE ? AND tag != ? AND tagType=?", [l, l, type]); + if (!newTagID) { + if (oldIDs) { + newTagID = oldIDs[0]; + } + else { + newTagID = Zotero.DB.valueQuery("SELECT MAX(tagID)+1 FROM tags"); + Zotero.DB.query("INSERT INTO tags VALUES (?,?,?)", [newTagID, newTag, type]); + } + } + Zotero.DB.query("UPDATE OR REPLACE itemTags SET tagID=? WHERE tagID IN (" + oldIDs.map(function () '?').join() + ")", [newTagID].concat(oldIDs)); + newTags.push({ tagID: newTagID, tag: newTag, tagType: type }); + } + } + } + Zotero.DB.query("DROP TABLE tags"); - Zotero.DB.query("CREATE TABLE tags (\n tagID INTEGER PRIMARY KEY,\n name TEXT,\n type INT,\n dateModified DEFAULT CURRENT_TIMESTAMP NOT NULL,\n key TEXT NOT NULL UNIQUE,\n UNIQUE (name, type)\n)"); + Zotero.DB.query("CREATE TABLE tags (\n tagID INTEGER PRIMARY KEY,\n name TEXT COLLATE NOCASE,\n type INT,\n dateModified DEFAULT CURRENT_TIMESTAMP NOT NULL,\n key TEXT NOT NULL UNIQUE,\n UNIQUE (name, type)\n)"); var statement = Zotero.DB.getStatement("INSERT INTO tags (tagID, name, type, key) VALUES (?,?,?,?)"); - for (var j=0, len=tags.length; j