www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit f1ed5f1f03f5e1144bab55dc0df7c40be6373924
parent 89833e2da7a763bb6b2df5701a1652d587e1176d
Author: Dan Stillman <dstillman@zotero.org>
Date:   Sun, 10 Aug 2014 15:00:08 -0400

Remove obsolete file (Zotero.Tag no longer exists)

Diffstat:
Dchrome/content/zotero/xpcom/data/tag.js | 779-------------------------------------------------------------------------------
1 file changed, 0 insertions(+), 779 deletions(-)

diff --git a/chrome/content/zotero/xpcom/data/tag.js b/chrome/content/zotero/xpcom/data/tag.js @@ -1,779 +0,0 @@ -/* - ***** BEGIN LICENSE BLOCK ***** - - Copyright © 2009 Center for History and New Media - George Mason University, Fairfax, Virginia, USA - http://zotero.org - - This file is part of Zotero. - - Zotero is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Zotero is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Zotero. If not, see <http://www.gnu.org/licenses/>. - - ***** END LICENSE BLOCK ***** -*/ - - -Zotero.Tag = function () { - if (arguments[0]) { - throw ("Zotero.Tag constructor doesn't take any parameters"); - } - - this._init(); -} - -Zotero.Tag.prototype._init = function () { - // Public members for access by public methods -- do not access directly - this._id = null; - this._libraryID = null - this._key = null; - this._name = null; - this._type = null; - this._dateAdded = null; - this._dateModified = null; - - this._loaded = false; - this._changed = false; - this._previousData = false; - - this._linkedItemsLoaded = false; - this._linkedItems = {}; - this._linkedItemIDsToAdd = []; - this._linkedItemIDsToRemove = []; -} - - -Zotero.Tag.prototype.__defineGetter__('objectType', function () { return 'tag'; }); -Zotero.Tag.prototype.__defineGetter__('id', function () { return this._get('id'); }); -Zotero.Tag.prototype.__defineSetter__('id', function (val) { this._set('id', val); }); -Zotero.Tag.prototype.__defineGetter__('libraryID', function () { return this._get('libraryID'); }); -Zotero.Tag.prototype.__defineSetter__('libraryID', function (val) { return this._set('libraryID', val); }); -Zotero.Tag.prototype.__defineGetter__('key', function () { return this._get('key'); }); -Zotero.Tag.prototype.__defineSetter__('key', function (val) { this._set('key', val) }); -Zotero.Tag.prototype.__defineGetter__('name', function () { return this._get('name'); }); -Zotero.Tag.prototype.__defineSetter__('name', function (val) { this._set('name', val); }); -Zotero.Tag.prototype.__defineGetter__('type', function () { return this._get('type'); }); -Zotero.Tag.prototype.__defineSetter__('type', function (val) { this._set('type', val); }); -Zotero.Tag.prototype.__defineGetter__('dateAdded', function () { return this._get('dateAdded'); }); -Zotero.Tag.prototype.__defineSetter__('dateAdded', function (val) { this._set('dateAdded', val); }); -Zotero.Tag.prototype.__defineGetter__('dateModified', function () { return this._get('dateModified'); }); -Zotero.Tag.prototype.__defineSetter__('dateModified', function (val) { this._set('dateModified', val); }); -Zotero.Tag.prototype.__defineGetter__('key', function () { return this._get('key'); }); - -Zotero.Tag.prototype.__defineSetter__('linkedItems', function (arr) { this._setLinkedItems(arr); }); - - -Zotero.Tag.prototype._get = function (field) { - if ((this._id || this._key) && !this._loaded) { - this.load(); - } - return this['_' + field]; -} - - -Zotero.Tag.prototype._set = function (field, val) { - switch (field) { - case 'id': - case 'libraryID': - case 'key': - if (field == 'libraryID') { - val = Zotero.DataObjectUtilities.checkLibraryID(val); - } - - if (val == this['_' + field]) { - return; - } - - if (this._loaded) { - throw ("Cannot set " + field + " after object is already loaded in Zotero.Tag._set()"); - } - - //this._checkValue(field, val); - - this['_' + field] = val; - return; - - case 'name': - val = Zotero.Utilities.trim(val); - break; - } - - if (this.id || this.key) { - if (!this._loaded) { - this.load(); - } - } - else { - this._loaded = true; - } - - if (this['_' + field] != val) { - this._prepFieldChange(field); - - switch (field) { - default: - this['_' + field] = val; - } - } -} - - -/** - * Check if tag exists in the database - * - * @return bool TRUE if the tag exists, FALSE if not - */ -Zotero.Tag.prototype.exists = function() { - if (!this.id) { - throw ('tagID not set in Zotero.Tag.exists()'); - } - - var sql = "SELECT COUNT(*) FROM tags WHERE tagID=?"; - return !!Zotero.DB.valueQuery(sql, this.id); -} - - -/* - * Build tag from database - */ -Zotero.Tag.prototype.load = function() { - var id = this._id; - var key = this._key; - var libraryID = this._libraryID; - var desc = id ? id : libraryID + "/" + key; - - Zotero.debug("Loading data for tag " + desc + " in Zotero.Tag.load()"); - - if (!id && !key) { - throw ("ID or key not set in Zotero.Tag.load()"); - } - - var sql = "SELECT * FROM tags WHERE "; - if (id) { - sql += "tagID=?"; - var params = id; - } - else { - sql += "key=? AND libraryID=?"; - var params = [key, libraryID]; - } - var row = Zotero.DB.rowQuery(sql, params); - - if (!row) { - return; - } - - this.loadFromRow(row); - return true; -} - - -Zotero.Tag.prototype.loadFromRow = function (row) { - this._init(); - for (var col in row) { - //Zotero.debug("Setting field '" + col + "' to '" + row[col] + "' for tag " + this.id); - switch (col) { - case 'clientDateModified': - continue; - - case 'tagID': - this._id = row[col]; - continue; - - case 'libraryID': - this['_' + col] = row[col]; - continue; - } - this['_' + col] = (!row[col] && row[col] !== 0) ? '' : row[col]; - } - this._loaded = true; -} - - - -/** - * Returns items linked to this tag - * - * @param {Boolean} asIDs Return as itemIDs - * @return {Array} Array of Zotero.Item instances or itemIDs, - * or FALSE if none - */ -Zotero.Tag.prototype.getLinkedItems = function (asIDs) { - if (!this._linkedItemsLoaded) { - this._loadLinkedItems(); - } - - if (Zotero.Utilities.isEmpty(this._linkedItems)) { - return []; - } - - // Return itemIDs - if (asIDs) { - return Object.keys(this._linkedItems); - } - - // Return Zotero.Item objects - return [item for each(item in this._linkedItems)]; -} - - -Zotero.Tag.prototype.countLinkedItems = function () { - return Object.keys(this._linkedItems).length; -} - - -Zotero.Tag.prototype.addItem = function (itemID) { - if (!this._linkedItemsLoaded) { - this._loadLinkedItems(); - } - - if (this._linkedItems[itemID]) { - Zotero.debug("Item " + itemID + " already has tag " - + this.id + " in Zotero.Tag.addItem()"); - return false; - } - - var item = Zotero.Items.get(itemID); - if (!item) { - throw new Error("Can't link invalid item " + itemID + " to tag " + this.id); - } - this._prepFieldChange('linkedItems'); - this._linkedItems[itemID] = item; - this._linkedItemIDsToAdd.push(itemID); - this._linkedItemIDsToRemove = this._linkedItemIDsToRemove.filter(function (x) x != itemID); - return true; -} - - -Zotero.Tag.prototype.removeItem = function (itemID) { - if (!this._linkedItemsLoaded) { - this._loadLinkedItems(); - } - - if (!this._linkedItems[itemID]) { - Zotero.debug("Item " + itemID + " doesn't have tag " - + this.id + " in Zotero.Tag.removeItem()"); - return false; - } - - this._prepFieldChange('linkedItems'); - delete this._linkedItems[itemID]; - this._linkedItemIDsToAdd = this._linkedItemIDsToAdd.filter(function (x) x != itemID); - this._linkedItemIDsToRemove.push(itemID); - return true; -} - - -Zotero.Tag.prototype.save = function (full) { - Zotero.Tags.editCheck(this); - - // Default to manual tag - if (!this.type) { - this.type = 0; - } - - if (this.type != 0 && this.type != 1) { - Zotero.debug(this); - throw ('Invalid tag type ' + this.type + ' for tag ' + this.id + ' in Zotero.Tag.save()'); - } - - if (!this.name) { - throw ('Tag ' + this.id + ' name is empty in Zotero.Tag.save()'); - } - - if (!this._changed) { - Zotero.debug("Tag " + this.id + " has not changed"); - return false; - } - - - Zotero.DB.beginTransaction(); - - var isNew = !this.id || !this.exists(); - - try { - // how to know if date modified changed (in server code too?) - - var tagID = this.id ? this.id : Zotero.ID.get('tags'); - - Zotero.debug("Saving tag " + this.id); - - var key = this.key ? this.key : this._generateKey(); - - var columns = [ - 'tagID', - 'name', - 'type', - 'dateAdded', - 'dateModified', - 'clientDateModified', - 'libraryID', - 'key' - ]; - var placeholders = columns.map(function () '?').join(); - var sqlValues = [ - tagID ? { int: tagID } : null, - { string: this.name }, - { int: this.type }, - // If date added isn't set, use current timestamp - this.dateAdded ? this.dateAdded : Zotero.DB.transactionDateTime, - // If date modified hasn't changed, use current timestamp - this._changed.dateModified ? - this.dateModified : Zotero.DB.transactionDateTime, - Zotero.DB.transactionDateTime, - this.libraryID ? this.libraryID : 0, - key - ]; - - try { - if (isNew) { - var sql = "INSERT INTO tags (" + columns.join(', ') + ") " - + "VALUES (" + placeholders + ")"; - var insertID = Zotero.DB.query(sql, sqlValues); - if (!tagID) { - tagID = insertID; - } - } - else { - // Remove tagID from beginning - columns.shift(); - sqlValues.shift(); - sqlValues.push(tagID); - - var sql = "UPDATE tags SET " + columns.join("=?, ") + "=?" - + " WHERE tagID=?"; - Zotero.DB.query(sql, sqlValues); - } - } - catch (e) { - // If an incoming tag is the same as an existing tag, but with a different key, - // then delete the old tag and add its linked items to the new tag - if (typeof e == 'string' && - (e.indexOf('columns libraryID, name, type are not unique') != -1 - || e.indexOf('NS_ERROR_STORAGE_CONSTRAINT') != -1)) { - Zotero.debug("Tag matches existing tag with different key -- delete old tag and merging items"); - - // GET existing tag - var existing = Zotero.Tags.getIDs(this.name, this.libraryID); - if (!existing) { - throw new Error("Existing tag not found"); - } - for each(var id in existing) { - var tag = Zotero.Tags.get(id, true); - if (tag.type == this.type) { - var linked = tag.getLinkedItems(true); - Zotero.Tags.erase(id); - Zotero.Tags.purge(id); - break; - } - } - - // Save again - if (isNew) { - var sql = "INSERT INTO tags (" + columns.join(', ') + ") " - + "VALUES (" + placeholders + ")"; - var insertID = Zotero.DB.query(sql, sqlValues); - if (!tagID) { - tagID = insertID; - } - } - else { - var sql = "UPDATE tags SET " + columns.join("=?, ") + "=?" - + " WHERE tagID=?"; - Zotero.DB.query(sql, sqlValues); - } - - // TEMP: until getLinkedItems() returns only arrays - linked = linked ? linked : []; - var linked2 = this.getLinkedItems(true); - linked2 = linked2 ? linked2 : []; - linked = linked.concat(linked2); - - this.linkedItems = Zotero.Utilities.arrayUnique(linked); - } - else { - throw (e); - } - } - - // Linked items - if (full || this._changed.linkedItems) { - var removed = []; - var newids = []; - var currentIDs = this.getLinkedItems(true); - if (!currentIDs) { - currentIDs = []; - } - - // Use the database for comparison instead of relying on the cache - // This is necessary for a syncing edge case (described in sync.js). - if (full) { - var sql = "SELECT itemID FROM itemTags WHERE tagID=?"; - var dbItemIDs = Zotero.DB.columnQuery(sql, tagID); - if (dbItemIDs) { - removed = Zotero.Utilities.arrayDiff(dbItemIDs, currentIDs); - newids = Zotero.Utilities.arrayDiff(currentIDs, dbItemIDs); - } - else { - newids = currentIDs; - } - } - else { - removed = this._linkedItemIDsToRemove; - newids = this._linkedItemIDsToAdd; - } - - if (removed.length) { - var done = 0; - var maxItems = 998; // stay below compiled limit - var numItems = removed.length; - - var pairs = []; - for each(var itemID in removed) { - pairs.push(itemID + "-" + tagID); - } - - let tempRemoved = removed.concat(); - - do { - var chunk = tempRemoved.splice(0, maxItems); - - var sql = "DELETE FROM itemTags WHERE tagID=? " - + "AND itemID IN (" + chunk.map(function () '?').join() + ")"; - Zotero.DB.query(sql, [tagID].concat(chunk)); - - done += chunk.length; - } - while (done < numItems); - - Zotero.Notifier.trigger('remove', 'item-tag', pairs); - } - - if (newids.length) { - var sql = "INSERT OR IGNORE INTO itemTags (itemID, tagID) VALUES (?,?)"; - var insertStatement = Zotero.DB.getStatement(sql); - - var pairs = []; - for each(var itemID in newids) { - insertStatement.bindInt32Parameter(0, itemID); - insertStatement.bindInt32Parameter(1, tagID); - - try { - insertStatement.execute(); - } - catch (e) { - Zotero.debug("itemID: " + itemID); - Zotero.debug("tagID: " + tagID); - throw (e + ' [ERROR: ' + Zotero.DB.getLastErrorString() + ']'); - } - - pairs.push(itemID + "-" + tagID); - } - - Zotero.Notifier.trigger('add', 'item-tag', pairs); - } - - // TODO: notify linked items of name changes? - Zotero.Notifier.trigger('modify', 'item', removed.concat(newids)); - } - - Zotero.DB.commitTransaction(); - } - catch (e) { - Zotero.DB.rollbackTransaction(); - throw (e); - } - - // If successful, set values in object - if (!this.id) { - this._id = tagID; - } - - if (!this.key) { - this._key = key; - } - - if (isNew) { - Zotero.Notifier.trigger('add', 'tag', this.id); - } - else { - Zotero.Notifier.trigger('modify', 'tag', this.id, this._previousData); - } - - this._reset(); - Zotero.Tags.reload(this.id); - - return this.id; -} - - -/** - * Compares this tag to another - * - * Returns a two-element array containing two objects with the differing values, - * or FALSE if no differences - * - * @param {Zotero.Tag} tag Zotero.Tag to compare this item to - * @param {Boolean} includeMatches Include all fields, even those that aren't different - * @param {Boolean} ignoreOnlyDateModified If no fields other than dateModified - * are different, just return false - */ -Zotero.Tag.prototype.diff = function (tag, includeMatches, ignoreOnlyDateModified) { - var diff = []; - var thisData = this.serialize(); - var otherData = tag.serialize(); - var numDiffs = Zotero.Tags.diff(thisData, otherData, diff, includeMatches); - - // For the moment, just compare linked items and increase numDiffs if any differences - var d1 = Zotero.Utilities.arrayDiff( - thisData.linkedItems, otherData.linkedItems - ); - var d2 = Zotero.Utilities.arrayDiff( - otherData.linkedItems, thisData.linkedItems - ); - numDiffs += d1.length + d2.length; - - if (d1.length || d2.length) { - numDiffs += d1.length + d2.length; - diff[0].linkedItems = d1; - diff[1].linkedItems = d2; - } - else { - diff[0].linkedItems = []; - diff[1].linkedItems = []; - } - - // DEBUG: ignoreOnlyDateModified wouldn't work if includeMatches was set? - if (numDiffs == 0 || - (ignoreOnlyDateModified && numDiffs == 1 - && diff[0].primary && diff[0].primary.dateModified)) { - return false; - } - - return diff; -} - - -Zotero.Tag.prototype.serialize = function () { - var linkedItems = this.getLinkedItems(true); - - var obj = { - primary: { - tagID: this.id, - libraryID: this.libraryID, - key: this.key, - dateAdded: this.dateAdded, - dateModified: this.dateModified - }, - fields: { - name: this.name, - type: this.type, - }, - linkedItems: linkedItems ? linkedItems : [] - }; - return obj; -} - - -/** - * Remove tag from all linked items - * - * Tags.erase() should be used instead of tag.erase() for deleting multiple tags - * - * Actual deletion of tag occurs in Zotero.Tags.purge() - */ -Zotero.Tag.prototype.erase = function () { - Zotero.debug('Deleting tag ' + this.id); - - if (!this.id) { - return; - } - - var linkedItems = []; - var linkedItemsNotifierData = {}; - - Zotero.DB.beginTransaction(); - - // Deletion done in Zotero.Tags.purge() - //var deletedTagNotifierData = {}; - //deletedTagNotifierData[this.id] = { old: this.serialize() }; - - var sql = "SELECT itemID FROM itemTags WHERE tagID=?"; - var linkedItemIDs = Zotero.DB.columnQuery(sql, this.id); - - if (!linkedItemIDs) { - Zotero.DB.commitTransaction(); - return; - } - - var sql = "DELETE FROM itemTags WHERE tagID=?"; - Zotero.DB.query(sql, this.id); - - var itemTags = []; - for each(var itemID in linkedItemIDs) { - var item = Zotero.Items.get(itemID) - if (!item) { - throw ('Linked item not found in Zotero.Tag.erase()'); - } - linkedItems.push(itemID); - linkedItemsNotifierData[itemID] = { old: item.serialize() }; - - itemTags.push(itemID + '-' + this.id); - } - - // Deletion done in Zotero.Tags.purge() - //Zotero.Tags.unload(this.id); - - Zotero.Notifier.trigger('remove', 'item-tag', itemTags); - - // Send notification of linked items - if (linkedItems.length) { - Zotero.Notifier.trigger('modify', 'item', linkedItems, linkedItemsNotifierData); - } - - // Deletion done in Zotero.Tags.purge() - //Zotero.Notifier.trigger('delete', 'tag', this.id, deletedTagNotifierData); - - Zotero.DB.commitTransaction(); - - this._reset(); - - Zotero.Prefs.set('purge.tags', true); -} - - -Zotero.Tag.prototype._reset = function () { - var id = this._id; - var libraryID = this._libraryID; - var key = this._key; - this._init(); - this._id = id; - this._libraryID = libraryID; - this._key = key; -} - - -Zotero.Tag.prototype._loadLinkedItems = function() { - if (!this.id && !this.key) { - this._linkedItemsLoaded = true; - return; - } - - if (!this._loaded) { - this.load(); - } - - if (!this.id) { - this._linkedItemsLoaded = true; - return; - } - - var sql = "SELECT itemID FROM itemTags WHERE tagID=?"; - var ids = Zotero.DB.columnQuery(sql, this.id) || []; - - this._linkedItems = {}; - - for (let i=0; i<ids.length; i++) { - let id = ids[i]; - this._linkedItems[id] = Zotero.Items.get(id); - } - - this._linkedItemsLoaded = true; -} - - -Zotero.Tag.prototype._setLinkedItems = function (itemIDs) { - if (!this._linkedItemsLoaded) { - this._loadLinkedItems(); - } - - if (!Array.isArray(itemIDs)) { - throw new Error('itemIDs must be an array'); - } - - var numCurrent = this.countLinkedItems(); - - if (itemIDs.length == 0) { - if (numCurrent == 0) { - Zotero.debug('No linked items added', 4); - return false; - } - - // No items passed, so remove all currently linked items - this._prepFieldChange('linkedItems'); - this._linkedItems = {}; - this._linkedItemIDsToAdd = []; - this._linkedItemIDsToRemove = this.getLinkedItems(true); - return true; - } - - // Get all new items - for (let i=0; i<itemIDs.length; i++) { - let id = itemIDs[i]; - if (isNaN(parseInt(id))) { - throw new Error("Invalid itemID '" + itemIDs[i] + "'"); - } - - if (this._linkedItems[id]) { - Zotero.debug("Item " + id + " is already linked to tag " + this.id); - } - else { - this._linkedItemIDsToAdd.push(id); - } - } - - // If no new items and the old and new lengths match, none are being removed either - if (!this._linkedItemIDsToAdd.length && numCurrent == itemIDs.length) { - Zotero.debug('Linked items not changed in Zotero.Tag._setLinkedItems()', 4); - return false; - } - - this._prepFieldChange('linkedItems'); - - // Rebuild linked items with items that exist - var items = Zotero.Items.get(itemIDs) || []; - this._linkedItems = {}; - for (let i=0; i<items.length; i++) { - this._linkedItems[items[i].id] = items[i]; - } - - // Mark items not found for removal - for (let i=0; i<itemIDs.length; i++) { - let id = itemIDs[i]; - if (!this._linkedItems[id]) { - this._linkedItemIDsToRemove.push(id); - } - } - - return true; -} - - -Zotero.Tag.prototype._prepFieldChange = function (field) { - if (!this._changed) { - this._changed = {}; - } - this._changed[field] = true; - - // Save a copy of the data before changing - // TODO: only save previous data if tag exists - if (this.id && this.exists() && !this._previousData) { - this._previousData = this.serialize(); - } -} - - -Zotero.Tag.prototype._generateKey = function () { - return Zotero.Utilities.generateObjectKey(); -} -