diff --git a/chrome/content/zotero/xpcom/data/collections.js b/chrome/content/zotero/xpcom/data/collections.js index 2377355c52..3cb7520862 100644 --- a/chrome/content/zotero/xpcom/data/collections.js +++ b/chrome/content/zotero/xpcom/data/collections.js @@ -27,9 +27,10 @@ /* * Primary interface for accessing Zotero collection */ -Zotero.Collections = new function() { - Zotero.DataObjects.apply(this, ['collection']); - this.constructor.prototype = new Zotero.DataObjects(); +Zotero.Collections = function() { + this.constructor = null; + + this._ZDO_object = 'collection'; this._primaryDataSQLParts = { collectionID: "O.collectionID", @@ -45,9 +46,13 @@ Zotero.Collections = new function() { hasChildCollections: "(SELECT COUNT(*) FROM collections WHERE " + "parentCollectionID=O.collectionID) != 0 AS hasChildCollections", hasChildItems: "(SELECT COUNT(*) FROM collectionItems WHERE " - + "collectionID=O.collectionID) != 0 AS hasChildItems " + + "collectionID=O.collectionID) != 0 AS hasChildItems" }; + + this._primaryDataSQLFrom = "FROM collections O " + + "LEFT JOIN collections CP ON (O.parentCollectionID=CP.collectionID)"; + /** * Add new collection to DB and return Collection object * @@ -74,55 +79,51 @@ Zotero.Collections = new function() { * Takes parent collectionID as optional parameter; * by default, returns root collections */ - this.getByParent = Zotero.Promise.coroutine(function* (libraryID, parent, recursive) { - var toReturn = []; + this.getByParent = Zotero.Promise.coroutine(function* (libraryID, parentID, recursive) { + let children; - if (!parent) { - parent = null; + if (parentID) { + let parent = yield this.getAsync(parentID); + yield parent.loadChildCollections(); + children = parent.getChildCollections(); + if (!children.length) Zotero.debug('No child collections in collection ' + parentID, 5); + } else if (libraryID || libraryID === 0) { + children = this.getCollectionsInLibrary(libraryID); + if (!children.length) Zotero.debug('No child collections in library ' + libraryID, 5); + } else { + throw new Error("Either library ID or parent collection ID must be provided to getNumCollectionsByParent"); } - var sql = "SELECT collectionID AS id, collectionName AS name FROM collections C " - + "WHERE libraryID=? AND parentCollectionID " + (parent ? '= ' + parent : 'IS NULL'); - var children = yield Zotero.DB.queryAsync(sql, [libraryID]); - - if (!children) { - Zotero.debug('No child collections of collection ' + parent, 5); - return toReturn; + if (!children.length) { + return children; } // Do proper collation sort - var collation = Zotero.getLocaleCollation(); - children.sort(function (a, b) { - return collation.compareString(1, a.name, b.name); - }); + children.sort(function (a, b) Zotero.localeCompare(a.name, b.name)); + if (!recursive) return children; + + let toReturn = []; for (var i=0, len=children.length; i 100) { @@ -145,8 +157,8 @@ Zotero.Collections = new function() { } sql = sql.substring(0, sql.length - 5); return Zotero.DB.columnQueryAsync(sql, sqlParams) - .then(function (collectionIDs) { - return asIDs ? collectionIDs : Zotero.Collections.get(collectionIDs); + .then(collectionIDs => { + return asIDs ? collectionIDs : this.get(collectionIDs); }); } @@ -186,32 +198,23 @@ Zotero.Collections = new function() { }); - this.erase = function (ids) { + this.erase = function(ids) { ids = Zotero.flattenArguments(ids); - Zotero.DB.beginTransaction(); - for each(var id in ids) { - var collection = this.getAsync(id); - if (collection) { - collection.erase(); + return Zotero.DB.executeTransaction(function* () { + for each(var id in ids) { + var collection = yield this.getAsync(id); + if (collection) { + yield collection.erase(); + } + collection = undefined; } - collection = undefined; - } - - this.unload(ids); - - Zotero.DB.commitTransaction(); - } + + this.unload(ids); + }); + }; + Zotero.DataObjects.call(this); - this.getPrimaryDataSQL = function () { - // This should be the same as the query in Zotero.Collection.load(), - // just without a specific collectionID - return "SELECT " - + Object.keys(this._primaryDataSQLParts).map(key => this._primaryDataSQLParts[key]).join(", ") + " " - + "FROM collections O " - + "LEFT JOIN collections CP ON (O.parentCollectionID=CP.collectionID) " - + "WHERE 1"; - } -} - + return this; +}.bind(Object.create(Zotero.DataObjects.prototype))(); diff --git a/chrome/content/zotero/xpcom/data/dataObjects.js b/chrome/content/zotero/xpcom/data/dataObjects.js index dff2bf4a0d..2c41a458bb 100644 --- a/chrome/content/zotero/xpcom/data/dataObjects.js +++ b/chrome/content/zotero/xpcom/data/dataObjects.js @@ -24,610 +24,608 @@ */ -Zotero.DataObjects = function (object, objectPlural, id, table) { - var self = this; +Zotero.DataObjects = function () { + if (!this._ZDO_object) throw new Error('this._ZDO_object must be set before calling Zotero.DataObjects constructor'); - if (!object) { - object = ''; + if (!this._ZDO_objects) { + this._ZDO_objects = Zotero.DataObjectUtilities.getObjectTypePlural(this._ZDO_object); + } + if (!this._ZDO_Object) { + this._ZDO_Object = this._ZDO_object.substr(0, 1).toUpperCase() + + this._ZDO_object.substr(1); + } + if (!this._ZDO_Objects) { + this._ZDO_Objects = this._ZDO_objects.substr(0, 1).toUpperCase() + + this._ZDO_objects.substr(1); } - // Override these variables in child objects - this._ZDO_object = object; - this._ZDO_objects = objectPlural ? objectPlural : object + 's'; - this._ZDO_Object = object.substr(0, 1).toUpperCase() + object.substr(1); - this._ZDO_Objects = this._ZDO_objects.substr(0, 1).toUpperCase() - + this._ZDO_objects.substr(1); - this._ZDO_id = (id ? id : object) + 'ID'; - this._ZDO_table = table ? table : this._ZDO_objects; - - // Certain object types don't have a libary and key and only use an id - switch (object) { - case 'relation': - this._ZDO_idOnly = true; - break; - - default: - this._ZDO_idOnly = false; + if (!this._ZDO_id) { + this._ZDO_id = this._ZDO_object + 'ID'; } - Zotero.defineProperty(this, 'idColumn', { - get: function() this._ZDO_id - }); + if (!this._ZDO_table) { + this._ZDO_table = this._ZDO_objects; + } + + if (!this.ObjectClass) { + this.ObjectClass = Zotero[this._ZDO_Object]; + } + + this.primaryDataSQLFrom = " " + this._primaryDataSQLFrom + " " + this._primaryDataSQLWhere; this._objectCache = {}; this._objectKeys = {}; this._objectIDs = {}; this._loadedLibraries = {}; this._loadPromise = null; - - // Public properties - this.table = this._ZDO_table; - - - this.init = function () { - return this._loadIDsAndKeys(); +} + +Zotero.DataObjects.prototype._ZDO_idOnly = false; + +// Public properties +Zotero.defineProperty(Zotero.DataObjects.prototype, 'idColumn', { + get: function() this._ZDO_id +}); +Zotero.defineProperty(Zotero.DataObjects.prototype, 'table', { + get: function() this._ZDO_table +}); + +Zotero.defineProperty(Zotero.DataObjects.prototype, 'primaryFields', { + get: function () Object.keys(this._primaryDataSQLParts) +}, {lazy: true}); + + +Zotero.DataObjects.prototype.init = function() { + return this._loadIDsAndKeys(); +} + + +Zotero.DataObjects.prototype.isPrimaryField = function (field) { + return this.primaryFields.indexOf(field) != -1; +} + + +/** + * Retrieves one or more already-loaded items + * + * If an item hasn't been loaded, an error is thrown + * + * @param {Array|Integer} ids An individual object id or an array of object ids + * @return {Zotero.[Object]|Array} A Zotero.[Object], if a scalar id was passed; + * otherwise, an array of Zotero.[Object] + */ +Zotero.DataObjects.prototype.get = function (ids) { + if (Array.isArray(ids)) { + var singleObject = false; + } + else { + var singleObject = true; + ids = [ids]; } + var toReturn = []; - this.__defineGetter__('primaryFields', function () { - var primaryFields = Object.keys(this._primaryDataSQLParts); - - // Once primary fields have been cached, get rid of getter for speed purposes - delete this.primaryFields; - this.primaryFields = primaryFields; - - return primaryFields; - }); - - - this.isPrimaryField = function (field) { - return this.primaryFields.indexOf(field) != -1; + for (let i=0; i} A Zotero.[Object], if a scalar id was passed; - * otherwise, an array of Zotero.[Object] - */ - this.get = function (ids) { - if (Array.isArray(ids)) { - var singleObject = false; - } - else { - var singleObject = true; - ids = [ids]; - } - - var toReturn = []; - - for (let i=0; i} A Zotero.[Object], if a scalar id was passed; + * otherwise, an array of Zotero.[Object] + */ +Zotero.DataObjects.prototype.getAsync = Zotero.Promise.coroutine(function* (ids, options) { + var toLoad = []; + var toReturn = []; + + if (!ids) { + throw new Error("No arguments provided to " + this._ZDO_Objects + ".get()"); + } + + if (Array.isArray(ids)) { + var singleObject = false; + } + else { + var singleObject = true; + ids = [ids]; + } + + for (let i=0; i} A Zotero.[Object], if a scalar id was passed; - * otherwise, an array of Zotero.[Object] - */ - this.getAsync = Zotero.Promise.coroutine(function* (ids, options) { + // New object to load + if (toLoad.length) { // Serialize loads if (this._loadPromise && this._loadPromise.isPending()) { yield this._loadPromise; } - var deferred = Zotero.Promise.defer(); + let deferred = Zotero.Promise.defer(); this._loadPromise = deferred.promise; - var toLoad = []; - var toReturn = []; - - if (!ids) { - throw new Error("No arguments provided to " + this._ZDO_Objects + ".get()"); - } - - if (Array.isArray(ids)) { - var singleObject = false; - } - else { - var singleObject = true; - ids = [ids]; - } - - for (let i=0; i} - Promise for a data object, or FALSE if not found - */ - this.getByLibraryAndKeyAsync = Zotero.Promise.coroutine(function* (libraryID, key, options) { - var id = this.getIDFromLibraryAndKey(libraryID, key); - if (!id) { - return false; - } - return Zotero[this._ZDO_Objects].getAsync(id, options); - }); - - - this.exists = function (itemID) { - return !!this.getLibraryAndKeyFromID(itemID); +} + + +/** + * @deprecated - Use Zotero.DataObjects.parseLibraryKey() + */ +Zotero.DataObjects.prototype.parseLibraryKeyHash = function (libraryKey) { + Zotero.debug("WARNING: " + this._ZDO_Objects + ".parseLibraryKeyHash() is deprecated -- use .parseLibraryKey() instead"); + var [libraryID, key] = libraryKey.split('_'); + if (!key) { + return false; + } + return { + libraryID: parseInt(libraryID), + key: key + }; +} + + +/** + * Retrieves an object by its libraryID and key + * + * @param {Integer} libraryID + * @param {String} key + * @return {Zotero.DataObject} Zotero data object, or FALSE if not found + */ +Zotero.DataObjects.prototype.getByLibraryAndKey = function (libraryID, key, options) { + var id = this.getIDFromLibraryAndKey(libraryID, key); + if (!id) { + return false; + } + return Zotero[this._ZDO_Objects].get(id, options); +}; + + +/** + * Asynchronously retrieves an object by its libraryID and key + * + * @param {Integer} - libraryID + * @param {String} - key + * @return {Promise} - Promise for a data object, or FALSE if not found + */ +Zotero.DataObjects.prototype.getByLibraryAndKeyAsync = Zotero.Promise.coroutine(function* (libraryID, key, options) { + var id = this.getIDFromLibraryAndKey(libraryID, key); + if (!id) { + return false; + } + return Zotero[this._ZDO_Objects].getAsync(id, options); +}); + + +Zotero.DataObjects.prototype.exists = function (itemID) { + return !!this.getLibraryAndKeyFromID(itemID); +} + + +/** + * @return {Array} Array with libraryID and key + */ +Zotero.DataObjects.prototype.getLibraryAndKeyFromID = function (id) { + return this._objectKeys[id] ? this._objectKeys[id] : false; +} + + +Zotero.DataObjects.prototype.getIDFromLibraryAndKey = function (libraryID, key) { + if (libraryID === null) { + throw new Error("libraryID cannot be NULL (did you mean 0?)"); + } + return (this._objectIDs[libraryID] && this._objectIDs[libraryID][key]) + ? this._objectIDs[libraryID][key] : false; +} + + +Zotero.DataObjects.prototype.getOlder = function (libraryID, date) { + if (!date || date.constructor.name != 'Date') { + throw ("date must be a JS Date in " + + "Zotero." + this._ZDO_Objects + ".getOlder()") } - - /** - * @return {Array} Array with libraryID and key - */ - this.getLibraryAndKeyFromID = function (id) { - return this._objectKeys[id] ? this._objectKeys[id] : false; + var sql = "SELECT ROWID FROM " + this._ZDO_table + + " WHERE libraryID=? AND clientDateModified?"; + if (ignoreFutureDates) { + sql += " AND clientDateModified<=CURRENT_TIMESTAMP"; } + return Zotero.DB.columnQuery(sql, [libraryID, Zotero.Date.dateToSQL(date, true)]); +} + + +/** + * @param {Integer} libraryID + * @return {Promise} A promise for an array of object ids + */ +Zotero.DataObjects.prototype.getUnsynced = function (libraryID) { + var sql = "SELECT " + this._ZDO_id + " FROM " + this._ZDO_table + + " WHERE libraryID=? AND synced=0"; + return Zotero.DB.columnQueryAsync(sql, [libraryID]); +} + + +/** + * Get JSON from the sync cache that hasn't yet been written to the + * main object tables + * + * @param {Integer} libraryID + * @return {Promise} A promise for an array of JSON objects + */ +Zotero.DataObjects.prototype.getUnwrittenData = function (libraryID) { + var sql = "SELECT data FROM syncCache SC " + + "LEFT JOIN " + this._ZDO_table + " " + + "USING (libraryID) " + + "WHERE SC.libraryID=? AND " + + "syncObjectTypeID IN (SELECT syncObjectTypeID FROM " + + "syncObjectTypes WHERE name='" + this._ZDO_object + "') " + + "AND IFNULL(O.version, 0) < SC.version"; + return Zotero.DB.columnQueryAsync(sql, [libraryID]); +} + + +/** + * Reload loaded data of loaded objects + * + * @param {Array|Number} ids - An id or array of ids + * @param {Array} [dataTypes] - Data types to reload (e.g., 'primaryData'), or all loaded + * types if not provided + * @param {Boolean} [reloadUnchanged=false] - Reload even data that hasn't changed internally. + * This should be set to true for data that was + * changed externally (e.g., globally renamed tags). + */ +Zotero.DataObjects.prototype.reload = Zotero.Promise.coroutine(function* (ids, dataTypes, reloadUnchanged) { + ids = Zotero.flattenArguments(ids); + Zotero.debug('Reloading ' + (dataTypes ? dataTypes + ' for ' : '') + + this._ZDO_objects + ' ' + ids); - this.getOlder = function (libraryID, date) { - if (!date || date.constructor.name != 'Date') { - throw ("date must be a JS Date in " - + "Zotero." + this._ZDO_Objects + ".getOlder()") - } - - var sql = "SELECT ROWID FROM " + this._ZDO_table - + " WHERE libraryID=? AND clientDateModified?"; - if (ignoreFutureDates) { - sql += " AND clientDateModified<=CURRENT_TIMESTAMP"; - } - return Zotero.DB.columnQuery(sql, [libraryID, Zotero.Date.dateToSQL(date, true)]); - } - - - /** - * @param {Integer} libraryID - * @return {Promise} A promise for an array of object ids - */ - this.getUnsynced = function (libraryID) { - var sql = "SELECT " + this._ZDO_id + " FROM " + this._ZDO_table - + " WHERE libraryID=? AND synced=0"; - return Zotero.DB.columnQueryAsync(sql, [libraryID]); - } - - - /** - * Get JSON from the sync cache that hasn't yet been written to the - * main object tables - * - * @param {Integer} libraryID - * @return {Promise} A promise for an array of JSON objects - */ - this.getUnwrittenData = function (libraryID) { - var sql = "SELECT data FROM syncCache SC " - + "LEFT JOIN " + this._ZDO_table + " " - + "USING (libraryID) " - + "WHERE SC.libraryID=? AND " - + "syncObjectTypeID IN (SELECT syncObjectTypeID FROM " - + "syncObjectTypes WHERE name='" + this._ZDO_object + "') " - + "AND IFNULL(O.version, 0) < SC.version"; - return Zotero.DB.columnQueryAsync(sql, [libraryID]); - } - - - /** - * Reload loaded data of loaded objects - * - * @param {Array|Number} ids - An id or array of ids - * @param {Array} [dataTypes] - Data types to reload (e.g., 'primaryData'), or all loaded - * types if not provided - * @param {Boolean} [reloadUnchanged=false] - Reload even data that hasn't changed internally. - * This should be set to true for data that was - * changed externally (e.g., globally renamed tags). - */ - this.reload = Zotero.Promise.coroutine(function* (ids, dataTypes, reloadUnchanged) { - ids = Zotero.flattenArguments(ids); - - Zotero.debug('Reloading ' + (dataTypes ? dataTypes + ' for ' : '') - + this._ZDO_objects + ' ' + ids); - - for (let i=0; i this._primaryDataSQLParts[val]).join(', ') + + this.primaryDataSQLFrom; + } +}, {lazy: true}); + +Zotero.DataObjects.prototype._primaryDataSQLWhere = "WHERE 1"; + +Zotero.DataObjects.prototype.getPrimaryDataSQLPart = function (part) { + var sql = this._primaryDataSQLParts[part]; + if (!sql) { + throw new Error("Invalid primary data SQL part '" + part + "'"); + } + return sql; +} + + +Zotero.DataObjects.prototype._load = Zotero.Promise.coroutine(function* (libraryID, ids, options) { + var loaded = {}; + + // If library isn't an integer (presumably false or null), skip it + if (parseInt(libraryID) != libraryID) { + libraryID = false; + } + + if (libraryID === false && !ids) { + throw new Error("Either libraryID or ids must be provided"); + } + + if (libraryID !== false && this._loadedLibraries[libraryID]) { + return loaded; + } + + // getPrimaryDataSQL() should use "O" for the primary table alias + var sql = this.primaryDataSQL; + var params = []; + if (libraryID !== false) { + sql += ' AND O.libraryID=?'; + params.push(libraryID); + } + if (ids) { + sql += ' AND O.' + this._ZDO_id + ' IN (' + ids.join(',') + ')'; + } + + var t = new Date(); + yield Zotero.DB.queryAsync( + sql, + params, + { + onRow: function (row) { + var id = row.getResultByIndex(this._ZDO_id); + var columns = Object.keys(this._primaryDataSQLParts); + var rowObj = {}; + for (let i=0; i { if (topic == 'idle' || topic == 'timer-callback') { var days = Zotero.Prefs.get('trashAutoEmptyDays'); if (!days) { @@ -551,20 +550,20 @@ Zotero.Items = new function() { // TODO: increase number after dealing with slow // tag.getLinkedItems() call during deletes var num = 10; - Zotero.Items.emptyTrash(null, days, num) - .then(function (deleted) { + this.emptyTrash(null, days, num) + .then(deleted => { if (!deleted) { - _emptyTrashTimer = null; + this._emptyTrashTimer = null; return; } // Set a timer to do more every few seconds - if (!_emptyTrashTimer) { - _emptyTrashTimer = Components.classes["@mozilla.org/timer;1"] + if (!this._emptyTrashTimer) { + this._emptyTrashTimer = Components.classes["@mozilla.org/timer;1"] .createInstance(Components.interfaces.nsITimer); } - _emptyTrashTimer.init( - _emptyTrashIdleObserver.observe, + this._emptyTrashTimer.init( + this._emptyTrashIdleObserver.observe, 5 * 1000, Components.interfaces.nsITimer.TYPE_ONE_SHOT ); @@ -572,8 +571,8 @@ Zotero.Items = new function() { } // When no longer idle, cancel timer else if (topic == 'back') { - if (_emptyTrashTimer) { - _emptyTrashTimer.cancel(); + if (this._emptyTrashTimer) { + this._emptyTrashTimer.cancel(); } } } @@ -581,7 +580,7 @@ Zotero.Items = new function() { var idleService = Components.classes["@mozilla.org/widget/idleservice;1"]. getService(Components.interfaces.nsIIdleService); - idleService.addIdleObserver(_emptyTrashIdleObserver, 305); + idleService.addIdleObserver(this._emptyTrashIdleObserver, 305); } @@ -624,28 +623,12 @@ Zotero.Items = new function() { }); - this.getPrimaryDataSQL = function () { - return "SELECT " - + Object.keys(this._primaryDataSQLParts).map((val) => this._primaryDataSQLParts[val]).join(', ') - + this.primaryDataSQLFrom; - }; - - - this.primaryDataSQLFrom = " FROM items O " - + "LEFT JOIN itemAttachments IA USING (itemID) " - + "LEFT JOIN items IAP ON (IA.parentItemID=IAP.itemID) " - + "LEFT JOIN itemNotes INo ON (O.itemID=INo.itemID) " - + "LEFT JOIN items INoP ON (INo.parentItemID=INoP.itemID) " - + "LEFT JOIN deletedItems DI ON (O.itemID=DI.itemID) " - + "WHERE 1"; - - this._postLoad = function (libraryID, ids) { if (!ids) { - if (!_cachedFields[libraryID]) { - _cachedFields[libraryID] = []; + if (!this._cachedFields[libraryID]) { + this._cachedFields[libraryID] = []; } - _cachedFields[libraryID] = this.primaryFields.concat(); + this._cachedFields[libraryID] = this.primaryFields.concat(); } } @@ -655,6 +638,7 @@ Zotero.Items = new function() { * * Why do we do this entirely in SQL? Because we're crazy. Crazy like foxes. */ + var _firstCreatorSQL = ''; function _getFirstCreatorSQL() { if (_firstCreatorSQL) { return _firstCreatorSQL; @@ -759,6 +743,7 @@ Zotero.Items = new function() { /* * Generate SQL to retrieve sortCreator field */ + var _sortCreatorSQL = ''; function _getSortCreatorSQL() { if (_sortCreatorSQL) { return _sortCreatorSQL; @@ -878,7 +863,7 @@ Zotero.Items = new function() { } - function getSortTitle(title) { + this.getSortTitle = function(title) { if (title === false || title === undefined) { return ''; } @@ -887,4 +872,8 @@ Zotero.Items = new function() { } return title.replace(/^[\[\'\"](.*)[\'\"\]]?$/, '$1') } -} + + Zotero.DataObjects.call(this); + + return this; +}.bind(Object.create(Zotero.DataObjects.prototype))(); diff --git a/chrome/content/zotero/xpcom/data/relations.js b/chrome/content/zotero/xpcom/data/relations.js index 310f39e97d..de60de5284 100644 --- a/chrome/content/zotero/xpcom/data/relations.js +++ b/chrome/content/zotero/xpcom/data/relations.js @@ -23,18 +23,15 @@ ***** END LICENSE BLOCK ***** */ -Zotero.Relations = new function () { - Zotero.DataObjects.apply(this, ['relation']); - this.constructor.prototype = new Zotero.DataObjects(); +Zotero.Relations = function () { + this.constructor = null; - this.__defineGetter__('relatedItemPredicate', function () "dc:relation"); - this.__defineGetter__('linkedObjectPredicate', function () "owl:sameAs"); - this.__defineGetter__('deletedItemPredicate', function () 'dc:isReplacedBy'); + this._ZDO_object = 'relation'; + this._ZDO_idOnly = true; - var _namespaces = { - dc: 'http://purl.org/dc/elements/1.1/', - owl: 'http://www.w3.org/2002/07/owl#' - }; + Zotero.defineProperty(this, 'relatedItemPredicate', {value: 'dc:relation'}); + Zotero.defineProperty(this, 'linkedObjectPredicate', {value: 'owl:sameAs'}); + Zotero.defineProperty(this, 'deletedItemPredicate', {value: 'dc:isReplacedBy'}); this.get = function (id) { if (typeof id != 'number') { @@ -52,7 +49,7 @@ Zotero.Relations = new function () { */ this.getByURIs = Zotero.Promise.coroutine(function* (subject, predicate, object) { if (predicate) { - predicate = _getPrefixAndValue(predicate).join(':'); + predicate = this._getPrefixAndValue(predicate).join(':'); } if (!subject && !predicate && !object) { @@ -141,7 +138,7 @@ Zotero.Relations = new function () { this.add = Zotero.Promise.coroutine(function* (libraryID, subject, predicate, object) { - predicate = _getPrefixAndValue(predicate).join(':'); + predicate = this._getPrefixAndValue(predicate).join(':'); var relation = new Zotero.Relation; if (!libraryID) { @@ -272,11 +269,15 @@ Zotero.Relations = new function () { return relation; } + this._namespaces = { + dc: 'http://purl.org/dc/elements/1.1/', + owl: 'http://www.w3.org/2002/07/owl#' + }; - function _getPrefixAndValue(uri) { + this._getPrefixAndValue = function(uri) { var [prefix, value] = uri.split(':'); if (prefix && value) { - if (!_namespaces[prefix]) { + if (!this._namespaces[prefix]) { throw ("Invalid prefix '" + prefix + "' in Zotero.Relations._getPrefixAndValue()"); } return [prefix, value]; @@ -290,4 +291,8 @@ Zotero.Relations = new function () { } throw ("Invalid namespace in URI '" + uri + "' in Zotero.Relations._getPrefixAndValue()"); } -} + + Zotero.DataObjects.call(this); + + return this; +}.bind(Object.create(Zotero.DataObjects.prototype))(); \ No newline at end of file diff --git a/chrome/content/zotero/xpcom/search.js b/chrome/content/zotero/xpcom/search.js index 6d67ebb262..cee68a6aaa 100644 --- a/chrome/content/zotero/xpcom/search.js +++ b/chrome/content/zotero/xpcom/search.js @@ -1637,29 +1637,25 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () { this._sqlParams = sqlParams.length ? sqlParams : false; }); -Zotero.Searches = new function(){ - Zotero.DataObjects.apply(this, ['search', 'searches', 'savedSearch', 'savedSearches']); - this.constructor.prototype = new Zotero.DataObjects(); +Zotero.Searches = function() { + this.constructor = null; - Object.defineProperty(this, "_primaryDataSQLParts", { - get: function () { - return _primaryDataSQLParts ? _primaryDataSQLParts : (_primaryDataSQLParts = { - savedSearchID: "O.savedSearchID", - name: "O.savedSearchName", - libraryID: "O.libraryID", - key: "O.key", - version: "O.version", - synced: "O.synced" - }); - } - }); + this._ZDO_object = 'search'; + this._ZDO_id = 'savedSearch'; + this._ZDO_table = 'savedSearches'; - - var _primaryDataSQLParts; + this._primaryDataSQLParts = { + savedSearchID: "O.savedSearchID", + name: "O.savedSearchName", + libraryID: "O.libraryID", + key: "O.key", + version: "O.version", + synced: "O.synced" + } this.init = Zotero.Promise.coroutine(function* () { - yield this.constructor.prototype.init.apply(this); + yield Zotero.DataObjects.prototype.init.apply(this); yield Zotero.SearchConditions.init(); }); @@ -1730,7 +1726,11 @@ Zotero.Searches = new function(){ + Object.keys(this._primaryDataSQLParts).map(key => this._primaryDataSQLParts[key]).join(", ") + " " + "FROM savedSearches O WHERE 1"; } -} + + Zotero.DataObjects.call(this); + + return this; +}.bind(Object.create(Zotero.DataObjects.prototype))();