diff --git a/chrome/content/zotero/bindings/noteeditor.xml b/chrome/content/zotero/bindings/noteeditor.xml index d9b17c03e..37659c63a 100644 --- a/chrome/content/zotero/bindings/noteeditor.xml +++ b/chrome/content/zotero/bindings/noteeditor.xml @@ -417,48 +417,41 @@ 0) { - var x = this.boxObject.screenX; - var y = this.boxObject.screenY; - this.id('relatedPopup').openPopupAtScreen(x, y, false); - } - else { - this.id('related').add(); - } - }, this); + var relatedList = this.item.relatedItems; + if (relatedList.length > 0) { + var x = this.boxObject.screenX; + var y = this.boxObject.screenY; + this.id('relatedPopup').openPopupAtScreen(x, y, false); + } + else { + this.id('related').add(); + } ]]> diff --git a/chrome/content/zotero/bindings/relatedbox.xml b/chrome/content/zotero/bindings/relatedbox.xml index aa8cc30ef..3989dbbea 100644 --- a/chrome/content/zotero/bindings/relatedbox.xml +++ b/chrome/content/zotero/bindings/relatedbox.xml @@ -74,25 +74,20 @@ Zotero.Promise.check(this.item)); - var keys = this.item.relatedItems; - if (keys.length) { - let items = yield Zotero.Items.getAsync(keys) - .tap(() => Zotero.Promise.check(this.item)); - for (let item of items) { - r = r + item.getDisplayTitle() + ", "; - } - r = r.substr(0,r.length-2); + var r = ""; + + if (this.item) { + var keys = this.item.relatedItems; + if (keys.length) { + for (let key of keys) { + let item = Zotero.Items.getByLibraryAndKey(this.item.libraryID, key); + r = r + item.getDisplayTitle() + ", "; } + r = r.substr(0,r.length-2); } - - return r; - }, this); + } + + return r; ]]> @@ -129,89 +124,79 @@ - - Zotero.Promise.check(this.item)); - var relatedKeys = this.item.relatedItems; - for (var i = 0; i < relatedKeys.length; i++) { - let key = relatedKeys[i]; - let relatedItem = - yield Zotero.Items.getByLibraryAndKeyAsync( - this.item.libraryID, key - ) - .tap(() => Zotero.Promise.check(this.item)); - let id = relatedItem.id; - yield relatedItem.loadItemData() - .tap(() => Zotero.Promise.check(this.item)); - let icon = document.createElement("image"); - icon.className = "zotero-box-icon"; - let type = Zotero.ItemTypes.getName(relatedItem.itemTypeID); - if (type=='attachment') - { - switch (relatedItem.attaachmentLinkMode) { - case Zotero.Attachments.LINK_MODE_LINKED_URL: - type += '-web-link'; - break; - - case Zotero.Attachments.LINK_MODE_IMPORTED_URL: - type += '-snapshot'; - break; - - case Zotero.Attachments.LINK_MODE_LINKED_FILE: - type += '-link'; - break; - - case Zotero.Attachments.LINK_MODE_IMPORTED_FILE: - type += '-file'; - break; - } + - + this.updateCount(relatedKeys.length); + } + ]]> Zotero.Promise.check(this.mode)); - var tags = this.item.getTags(); - if (tags) { - for(var i = 0; i < tags.length; i++) - { - r = r + tags[i].tag + ", "; - } - r = r.substr(0,r.length-2); - } - } + var r = ""; - return r; - }, this); + if (this.item) { + var tags = this.item.getTags(); + if (tags) { + for(var i = 0; i < tags.length; i++) + { + r = r + tags[i].tag + ", "; + } + r = r.substr(0,r.length-2); + } + } + + return r; ]]> @@ -211,9 +207,6 @@ return Zotero.spawn(function* () { Zotero.debug('Reloading tags box'); - yield this.item.loadTags() - .tap(() => Zotero.Promise.check(this.mode)); - // Cancel field focusing while we're updating this._reloading = true; diff --git a/chrome/content/zotero/duplicatesMerge.js b/chrome/content/zotero/duplicatesMerge.js index 27bf6ec58..f6682aae7 100644 --- a/chrome/content/zotero/duplicatesMerge.js +++ b/chrome/content/zotero/duplicatesMerge.js @@ -131,9 +131,9 @@ var Zotero_Duplicates_Pane = new function () { // alternative values so that they're still available if the item box // modifies the item Zotero.spawn(function* () { - var diff = yield item.multiDiff(_otherItems, _ignoreFields); + var diff = item.multiDiff(_otherItems, _ignoreFields); if (diff) { - let itemValues = yield item.toJSON(); + let itemValues = item.toJSON(); for (let i in diff) { diff[i].unshift(itemValues[i] !== undefined ? itemValues[i] : ''); } @@ -141,8 +141,6 @@ var Zotero_Duplicates_Pane = new function () { } var newItem = yield item.copy(); - yield newItem.loadItemData(); - yield newItem.loadCreators(); itembox.item = newItem; }); } diff --git a/chrome/content/zotero/itemPane.js b/chrome/content/zotero/itemPane.js index 8c6dd2e1a..45bfad132 100644 --- a/chrome/content/zotero/itemPane.js +++ b/chrome/content/zotero/itemPane.js @@ -94,13 +94,11 @@ var ZoteroItemPane = new function() { _notesList.removeChild(_notesList.firstChild); } - yield item.loadChildItems(); let notes = yield Zotero.Items.getAsync(item.getNotes()); if (notes.length) { for (var i = 0; i < notes.length; i++) { let note = notes[i]; let id = notes[i].id; - yield note.loadItemData(); var icon = document.createElement('image'); icon.className = "zotero-box-icon"; @@ -148,7 +146,6 @@ var ZoteroItemPane = new function() { box.mode = 'edit'; } - yield Zotero.Promise.all([item.loadItemData(), item.loadCreators()]); box.item = item; }); diff --git a/chrome/content/zotero/locateMenu.js b/chrome/content/zotero/locateMenu.js index 836d101df..9d960f443 100644 --- a/chrome/content/zotero/locateMenu.js +++ b/chrome/content/zotero/locateMenu.js @@ -400,7 +400,6 @@ var Zotero_LocateMenu = new function() { } if(item.isRegularItem()) { - yield item.loadChildItems(); var attachments = item.getAttachments(); if(attachments) { // look through url fields for non-file:/// attachments diff --git a/chrome/content/zotero/recognizePDF.js b/chrome/content/zotero/recognizePDF.js index 316e089e1..4846282aa 100644 --- a/chrome/content/zotero/recognizePDF.js +++ b/chrome/content/zotero/recognizePDF.js @@ -395,7 +395,6 @@ var Zotero_RecognizePDF = new function() { } // put new item in same collections as the old one - yield item.loadCollections(); let itemCollections = item.getCollections(); for (let i = 0; i < itemCollections.length; i++) { let collection = yield Zotero.Collections.getAsync(itemCollections[i]); diff --git a/chrome/content/zotero/xpcom/api.js b/chrome/content/zotero/xpcom/api.js index 81229692f..fa5ec440e 100644 --- a/chrome/content/zotero/xpcom/api.js +++ b/chrome/content/zotero/xpcom/api.js @@ -56,7 +56,6 @@ Zotero.API = { if (!col) { throw new Error('Invalid collection ID or key'); } - yield col.loadChildItems(); results = col.getChildItems(); break; diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index 012170d9c..24ddfedbb 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -1090,8 +1090,7 @@ Zotero.Attachments = new function(){ Zotero.DB.requireTransaction(); - attachment.loadItemData(); - var newAttachment = yield attachment.clone(libraryID); + var newAttachment = attachment.clone(libraryID); if (attachment.isImportedAttachment()) { // Attachment path isn't copied over by clone() if libraryID is different newAttachment.attachmentPath = attachment.attachmentPath; diff --git a/chrome/content/zotero/xpcom/cite.js b/chrome/content/zotero/xpcom/cite.js index c542a99ef..467164b95 100644 --- a/chrome/content/zotero/xpcom/cite.js +++ b/chrome/content/zotero/xpcom/cite.js @@ -529,7 +529,6 @@ Zotero.Cite.System.prototype = { throw "Zotero.Cite.System.retrieveItem called on non-item "+item; } - throw new Error("Unimplemented"); var cslItem = Zotero.Utilities.itemToCSLJSON(zoteroItem); // TEMP: citeproc-js currently expects the id property to be the item DB id diff --git a/chrome/content/zotero/xpcom/collectionTreeRow.js b/chrome/content/zotero/xpcom/collectionTreeRow.js index d3a773475..f54a09045 100644 --- a/chrome/content/zotero/xpcom/collectionTreeRow.js +++ b/chrome/content/zotero/xpcom/collectionTreeRow.js @@ -295,6 +295,7 @@ Zotero.CollectionTreeRow.prototype.getSearchObject = Zotero.Promise.coroutine(fu // Create the outer (filter) search var s2 = new Zotero.Search(); + if (this.isTrash()) { s2.addCondition('deleted', 'true'); } diff --git a/chrome/content/zotero/xpcom/collectionTreeView.js b/chrome/content/zotero/xpcom/collectionTreeView.js index ced95a682..fc35fb239 100644 --- a/chrome/content/zotero/xpcom/collectionTreeView.js +++ b/chrome/content/zotero/xpcom/collectionTreeView.js @@ -526,7 +526,7 @@ Zotero.CollectionTreeView.prototype._addSortedRow = Zotero.Promise.coroutine(fun ); } else if (objectType == 'search') { - let search = yield Zotero.Searches.getAsync(id); + let search = Zotero.Searches.get(id); let libraryID = search.libraryID; let startRow = this._rowMap['L' + libraryID]; @@ -545,7 +545,6 @@ Zotero.CollectionTreeView.prototype._addSortedRow = Zotero.Promise.coroutine(fun var inSearches = false; for (let i = startRow; i < this.rowCount; i++) { let treeRow = this.getRow(i); - Zotero.debug(treeRow.id); beforeRow = i; // If we've reached something other than collections, stop @@ -1504,10 +1503,6 @@ Zotero.CollectionTreeView.prototype.canDropCheckAsync = Zotero.Promise.coroutine } if (dataType == 'zotero/item') { - if (treeRow.isCollection()) { - yield treeRow.ref.loadChildItems(); - } - var ids = data; var items = Zotero.Items.get(ids); var skip = true; @@ -1627,7 +1622,6 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r // If linked item is in the trash, undelete it and remove it from collections // (since it shouldn't be restored to previous collections) if (linkedItem.deleted) { - yield linkedItem.loadCollections(); linkedItem.setCollections(); linkedItem.deleted = false; yield linkedItem.save({ @@ -1693,7 +1687,7 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r } // Create new clone item in target library - var newItem = yield item.clone(targetLibraryID, false, !options.tags); + var newItem = item.clone(targetLibraryID, false, !options.tags); // Set Rights field for My Publications if (options.license) { @@ -1717,11 +1711,10 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r // Child notes if (options.childNotes) { - yield item.loadChildItems(); var noteIDs = item.getNotes(); - var notes = yield Zotero.Items.getAsync(noteIDs); + var notes = Zotero.Items.get(noteIDs); for each(var note in notes) { - let newNote = yield note.clone(targetLibraryID); + let newNote = note.clone(targetLibraryID); newNote.parentID = newItemID; yield newNote.save({ skipSelect: true @@ -1733,9 +1726,8 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r // Child attachments if (options.childLinks || options.childFileAttachments) { - yield item.loadChildItems(); var attachmentIDs = item.getAttachments(); - var attachments = yield Zotero.Items.getAsync(attachmentIDs); + var attachments = Zotero.Items.get(attachmentIDs); for each(var attachment in attachments) { var linkMode = attachment.attachmentLinkMode; @@ -1864,8 +1856,8 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r if (targetTreeRow.isPublications()) { let items = yield Zotero.Items.getAsync(ids); - let io = yield this._treebox.treeBody.ownerDocument.defaultView.ZoteroPane - .showPublicationsWizard(items); + let io = this._treebox.treeBody.ownerDocument.defaultView + .ZoteroPane.showPublicationsWizard(items); if (!io) { return; } diff --git a/chrome/content/zotero/xpcom/data/collection.js b/chrome/content/zotero/xpcom/data/collection.js index 7205c4211..b68b90e16 100644 --- a/chrome/content/zotero/xpcom/data/collection.js +++ b/chrome/content/zotero/xpcom/data/collection.js @@ -28,11 +28,8 @@ Zotero.Collection = function(params = {}) { this._name = null; - this._hasChildCollections = null; - this._childCollections = []; - - this._hasChildItems = false; - this._childItems = []; + this._childCollections = new Set(); + this._childItems = new Set(); Zotero.Utilities.assignProps(this, params, ['name', 'libraryID', 'parentID', 'parentKey', 'lastSync']); @@ -162,19 +159,13 @@ Zotero.Collection.prototype.loadFromRow = function(row) { Zotero.Collection.prototype.hasChildCollections = function() { - if (this._hasChildCollections !== null) { - return this._hasChildCollections; - } - this._requireData('primaryData'); - return false; + this._requireData('childCollections'); + return this._childCollections.size > 0; } Zotero.Collection.prototype.hasChildItems = function() { - if (this._hasChildItems !== null) { - return this._hasChildItems; - } - this._requireData('primaryData'); - return false; + this._requireData('childItems'); + return this._childItems.size > 0; } @@ -189,19 +180,11 @@ Zotero.Collection.prototype.getChildCollections = function (asIDs) { // Return collectionIDs if (asIDs) { - var ids = []; - for each(var col in this._childCollections) { - ids.push(col.id); - } - return ids; + return this._childCollections.values(); } // Return Zotero.Collection objects - var objs = []; - for each(var col in this._childCollections) { - objs.push(col); - } - return objs; + return Array.from(this._childCollections).map(id => this.ObjectsClass.get(id)); } @@ -215,13 +198,14 @@ Zotero.Collection.prototype.getChildCollections = function (asIDs) { Zotero.Collection.prototype.getChildItems = function (asIDs, includeDeleted) { this._requireData('childItems'); - if (this._childItems.length == 0) { + if (this._childItems.size == 0) { return []; } // Remove deleted items if necessary var childItems = []; - for each(var item in this._childItems) { + for (let itemID of this._childItems) { + let item = this.ChildObjects.get(itemID); if (includeDeleted || !item.deleted) { childItems.push(item); } @@ -229,19 +213,11 @@ Zotero.Collection.prototype.getChildItems = function (asIDs, includeDeleted) { // Return itemIDs if (asIDs) { - var ids = []; - for each(var item in childItems) { - ids.push(item.id); - } - return ids; + return childItems.map(item => item.id); } // Return Zotero.Item objects - var objs = []; - for each(var item in childItems) { - objs.push(item); - } - return objs; + return childItems.slice(); } Zotero.Collection.prototype._initSave = Zotero.Promise.coroutine(function* (env) { @@ -388,7 +364,6 @@ Zotero.Collection.prototype.addItems = Zotero.Promise.coroutine(function* (itemI return; } - yield this.loadChildItems(); var current = this.getChildItems(true); Zotero.DB.requireTransaction(); @@ -400,15 +375,14 @@ Zotero.Collection.prototype.addItems = Zotero.Promise.coroutine(function* (itemI continue; } - let item = yield this.ChildObjects.getAsync(itemID); - yield item.loadCollections(); + let item = this.ChildObjects.get(itemID); item.addToCollection(this.id); yield item.save({ skipDateModifiedUpdate: true }); } - yield this.loadChildItems(true); + yield this._loadDataType('childItems'); }); /** @@ -434,7 +408,6 @@ Zotero.Collection.prototype.removeItems = Zotero.Promise.coroutine(function* (it return; } - yield this.loadChildItems(); var current = this.getChildItems(true); return Zotero.DB.executeTransaction(function* () { @@ -447,7 +420,6 @@ Zotero.Collection.prototype.removeItems = Zotero.Promise.coroutine(function* (it } let item = yield this.ChildObjects.getAsync(itemID); - yield item.loadCollections(); item.removeFromCollection(this.id); yield item.save({ skipDateModifiedUpdate: true @@ -455,7 +427,7 @@ Zotero.Collection.prototype.removeItems = Zotero.Promise.coroutine(function* (it } }.bind(this)); - yield this.loadChildItems(true); + yield this._loadDataType('childItems'); }); @@ -464,13 +436,7 @@ Zotero.Collection.prototype.removeItems = Zotero.Promise.coroutine(function* (it **/ Zotero.Collection.prototype.hasItem = function(itemID) { this._requireData('childItems'); - - for (let i=0; i 0; + this._childCollections.delete(collectionID); } } @@ -971,8 +861,7 @@ Zotero.Collection.prototype._registerChildItem = function (itemID) { if (this._loaded.childItems) { let item = this.ChildObjects.get(itemID); if (item) { - this._hasChildItems = true; - this._childItems.push(item); + this._childItems.add(itemID); } } } @@ -983,12 +872,6 @@ Zotero.Collection.prototype._registerChildItem = function (itemID) { */ Zotero.Collection.prototype._unregisterChildItem = function (itemID) { if (this._loaded.childItems) { - for (let i = 0; i < this._childItems.length; i++) { - if (this._childItems[i].id == itemID) { - this._childItems.splice(i, 1); - break; - } - } - this._hasChildItems = this._childItems.length > 0; + this._childItems.delete(itemID); } } diff --git a/chrome/content/zotero/xpcom/data/collections.js b/chrome/content/zotero/xpcom/data/collections.js index a27263b10..75b185a8e 100644 --- a/chrome/content/zotero/xpcom/data/collections.js +++ b/chrome/content/zotero/xpcom/data/collections.js @@ -85,8 +85,7 @@ Zotero.Collections = function() { let children; if (parentID) { - let parent = yield Zotero.Collections.getAsync(parentID); - yield parent.loadChildCollections(); + let parent = Zotero.Collections.get(parentID); children = parent.getChildCollections(); } else if (libraryID) { let sql = "SELECT collectionID AS id FROM collections " @@ -156,6 +155,103 @@ Zotero.Collections = function() { } + this._loadChildCollections = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var sql = "SELECT C1.collectionID, C2.collectionID AS childCollectionID " + + "FROM collections C1 LEFT JOIN collections C2 ON (C1.collectionID=C2.parentCollectionID) " + + "WHERE C1.libraryID=?" + + (ids.length ? " AND C1.collectionID IN (" + ids.map(id => parseInt(id)).join(", ") + ")" : ""); + var params = [libraryID]; + var lastID; + var rows = []; + var setRows = function (collectionID, rows) { + var collection = this._objectCache[collectionID]; + if (!collection) { + throw new Error("Collection " + collectionID + " not found"); + } + + collection._childCollections = new Set(rows); + collection._loaded.childCollections = true; + collection._clearChanged('childCollections'); + }.bind(this); + + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let collectionID = row.getResultByIndex(0); + + if (lastID && collectionID !== lastID) { + setRows(lastID, rows); + rows = []; + } + + lastID = collectionID; + + let childCollectionID = row.getResultByIndex(1); + // No child collections + if (childCollectionID === null) { + return; + } + rows.push(childCollectionID); + } + } + ); + if (lastID) { + setRows(lastID, rows); + } + }); + + + this._loadChildItems = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var sql = "SELECT collectionID, itemID FROM collections " + + "LEFT JOIN collectionItems USING (collectionID) " + + "WHERE libraryID=?" + idSQL; + var params = [libraryID]; + var lastID; + var rows = []; + var setRows = function (collectionID, rows) { + var collection = this._objectCache[collectionID]; + if (!collection) { + throw new Error("Collection " + collectionID + " not found"); + } + + collection._childItems = new Set(rows); + collection._loaded.childItems = true; + collection._clearChanged('childItems'); + }.bind(this); + + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let collectionID = row.getResultByIndex(0); + + if (lastID && collectionID !== lastID) { + setRows(lastID, rows); + rows = []; + } + + lastID = collectionID; + + let itemID = row.getResultByIndex(1); + // No child items + if (itemID === null) { + return; + } + rows.push(itemID); + } + } + ); + if (lastID) { + setRows(lastID, rows); + } + }); + + this.registerChildCollection = function (collectionID, childCollectionID) { if (this._objectCache[collectionID]) { this._objectCache[collectionID]._registerChildCollection(childCollectionID); diff --git a/chrome/content/zotero/xpcom/data/creators.js b/chrome/content/zotero/xpcom/data/creators.js index e65d6e050..909de38c5 100644 --- a/chrome/content/zotero/xpcom/data/creators.js +++ b/chrome/content/zotero/xpcom/data/creators.js @@ -30,29 +30,35 @@ Zotero.Creators = new function() { var _cache = {}; + this.init = Zotero.Promise.coroutine(function* (libraryID) { + var sql = "SELECT * FROM creators"; + var rows = yield Zotero.DB.queryAsync(sql); + for (let i = 0; i < rows.length; i++) { + let row = rows[i]; + _cache[row.creatorID] = this.cleanData({ + // Avoid "DB column 'name' not found" warnings from the DB row Proxy + firstName: row.firstName, + lastName: row.lastName, + fieldMode: row.fieldMode + }); + } + }); + /* * Returns creator data in internal format for a given creatorID */ - this.getAsync = Zotero.Promise.coroutine(function* (creatorID) { + this.get = function (creatorID) { if (!creatorID) { throw new Error("creatorID not provided"); } - if (_cache[creatorID]) { - return this.cleanData(_cache[creatorID]); - } - - var sql = "SELECT * FROM creators WHERE creatorID=?"; - var row = yield Zotero.DB.rowQueryAsync(sql, creatorID); - if (!row) { + if (!_cache[creatorID]) { throw new Error("Creator " + creatorID + " not found"); } - return _cache[creatorID] = this.cleanData({ - firstName: row.firstName, // avoid "DB column 'name' not found" warnings from the DB row Proxy - lastName: row.lastName, - fieldMode: row.fieldMode - }); - }); + + // Return copy of data + return this.cleanData(_cache[creatorID]); + }; this.getItemsWithCreator = function (creatorID) { @@ -87,12 +93,10 @@ Zotero.Creators = new function() { id = yield Zotero.ID.get('creators'); let sql = "INSERT INTO creators (creatorID, firstName, lastName, fieldMode) " + "VALUES (?, ?, ?, ?)"; - let insertID = yield Zotero.DB.queryAsync( + yield Zotero.DB.queryAsync( sql, [id, data.firstName, data.lastName, data.fieldMode] ); - if (!id) { - id = insertID; - } + _cache[id] = data; } return id; }); diff --git a/chrome/content/zotero/xpcom/data/dataObject.js b/chrome/content/zotero/xpcom/data/dataObject.js index 183544f58..05d5b59c2 100644 --- a/chrome/content/zotero/xpcom/data/dataObject.js +++ b/chrome/content/zotero/xpcom/data/dataObject.js @@ -401,7 +401,7 @@ Zotero.DataObject.prototype.setRelations = function (newRelations) { // Relations are stored internally as a flat array with individual predicate-object pairs, // so convert the incoming relations to that - var newRelationsFlat = this._flattenRelations(newRelations); + var newRelationsFlat = this.ObjectsClass.flattenRelations(newRelations); var changed = false; if (oldRelations.length != newRelationsFlat.length) { @@ -457,8 +457,6 @@ Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function throw new Error(this._ObjectType + " is already in library " + libraryID); } - yield this.loadRelations(); - var predicate = Zotero.Relations.linkedObjectPredicate; var libraryObjectPrefix = Zotero.URI.getLibraryURI(libraryID) + "/" + this._objectTypePlural + "/"; @@ -514,8 +512,6 @@ Zotero.DataObject.prototype._addLinkedObject = Zotero.Promise.coroutine(function throw new Error("Can't add linked " + this._objectType + " in same library"); } - yield this.loadRelations(); - var predicate = Zotero.Relations.linkedObjectPredicate; var thisURI = Zotero.URI['get' + this._ObjectType + 'URI'](this); var objectURI = Zotero.URI['get' + this._ObjectType + 'URI'](object); @@ -539,7 +535,6 @@ Zotero.DataObject.prototype._addLinkedObject = Zotero.Promise.coroutine(function }); } else { - yield object.loadRelations(); object.addRelation(predicate, thisURI); yield object.save({ skipDateModifiedUpdate: true, @@ -551,9 +546,11 @@ Zotero.DataObject.prototype._addLinkedObject = Zotero.Promise.coroutine(function }); -/* - * Build object from database - */ +// +// Bulk data loading functions +// +// These are called by Zotero.DataObjects.prototype._loadDataType(). +// Zotero.DataObject.prototype.loadPrimaryData = Zotero.Promise.coroutine(function* (reload, failOnMissing) { if (this._loaded.primaryData && !reload) return; @@ -610,65 +607,6 @@ Zotero.DataObject.prototype.loadPrimaryData = Zotero.Promise.coroutine(function* }); -Zotero.DataObject.prototype.loadRelations = Zotero.Promise.coroutine(function* (reload) { - if (!this.ObjectsClass._relationsTable) { - throw new Error("Relations not supported for " + this._objectTypePlural); - } - - if (this._loaded.relations && !reload) { - return; - } - - Zotero.debug("Loading relations for " + this._objectType + " " + this.libraryKey); - - this._requireData('primaryData'); - - var sql = "SELECT predicate, object FROM " + this.ObjectsClass._relationsTable + " " - + "JOIN relationPredicates USING (predicateID) " - + "WHERE " + this.ObjectsClass.idColumn + "=?"; - var rows = yield Zotero.DB.queryAsync(sql, this.id); - - var relations = {}; - function addRel(predicate, object) { - if (!relations[predicate]) { - relations[predicate] = []; - } - relations[predicate].push(object); - } - - for (let i = 0; i < rows.length; i++) { - let row = rows[i]; - addRel(row.predicate, row.object); - } - - /*if (this._objectType == 'item') { - let getURI = Zotero.URI["get" + this._ObjectType + "URI"].bind(Zotero.URI); - let objectURI = getURI(this); - - // Related items are bidirectional, so include any pointing to this object - let objects = yield Zotero.Relations.getByPredicateAndObject( - Zotero.Relations.relatedItemPredicate, objectURI - ); - for (let i = 0; i < objects.length; i++) { - addRel(Zotero.Relations.relatedItemPredicate, getURI(objects[i])); - } - - // Also include any owl:sameAs relations pointing to this object - objects = yield Zotero.Relations.getByPredicateAndObject( - Zotero.Relations.linkedObjectPredicate, objectURI - ); - for (let i = 0; i < objects.length; i++) { - addRel(Zotero.Relations.linkedObjectPredicate, getURI(objects[i])); - } - }*/ - - // Relations are stored as predicate-object pairs - this._relations = this._flattenRelations(relations); - this._loaded.relations = true; - this._clearChanged('relations'); -}); - - /** * Reloads loaded, changed data * @@ -735,7 +673,7 @@ Zotero.DataObject.prototype._requireData = function (dataType) { * @param {Boolean} reload */ Zotero.DataObject.prototype._loadDataType = function (dataType, reload) { - return this["load" + dataType[0].toUpperCase() + dataType.substr(1)](reload); + return this._ObjectsClass._loadDataType(dataType, this.libraryID, [this.id]); } Zotero.DataObject.prototype.loadAllData = function (reload) { @@ -868,6 +806,16 @@ Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options) Zotero.debug('Updating database with new ' + this._objectType + ' data', 4); } + if (env.options.skipAll) { + [ + 'skipDateModifiedUpdate', + 'skipClientDateModifiedUpdate', + 'skipSyncedUpdate', + 'skipEditCheck', + 'skipSelect' + ].forEach(x => env.options[x] = true); + } + try { if (Zotero.DataObject.prototype._finalizeSave == this._finalizeSave) { throw new Error("_finalizeSave not implemented for Zotero." + this._ObjectType); @@ -1214,16 +1162,16 @@ Zotero.DataObject.prototype._finalizeErase = Zotero.Promise.coroutine(function* }); -Zotero.DataObject.prototype.toResponseJSON = Zotero.Promise.coroutine(function* (options) { +Zotero.DataObject.prototype.toResponseJSON = function (options) { // TODO: library block? return { key: this.key, version: this.version, meta: {}, - data: yield this.toJSON(options) + data: this.toJSON(options) }; -}); +} Zotero.DataObject.prototype._preToJSON = function (options) { @@ -1272,32 +1220,3 @@ Zotero.DataObject.prototype._disabledCheck = function () { + "use Zotero." + this._ObjectTypePlural + ".getAsync()"); } } - - -/** - * Flatten API JSON relations object into an array of unique predicate-object pairs - * - * @param {Object} relations - Relations object in API JSON format, with predicates as keys - * and arrays of URIs as objects - * @return {Array[]} - Predicate-object pairs - */ -Zotero.DataObject.prototype._flattenRelations = function (relations) { - var relationsFlat = []; - for (let predicate in relations) { - let object = relations[predicate]; - if (Array.isArray(object)) { - object = Zotero.Utilities.arrayUnique(object); - for (let i = 0; i < object.length; i++) { - relationsFlat.push([predicate, object[i]]); - } - } - else if (typeof object == 'string') { - relationsFlat.push([predicate, object]); - } - else { - Zotero.debug(object, 1); - throw new Error("Invalid relation value"); - } - } - return relationsFlat; -} diff --git a/chrome/content/zotero/xpcom/data/dataObjects.js b/chrome/content/zotero/xpcom/data/dataObjects.js index 762694435..0ce1a73e5 100644 --- a/chrome/content/zotero/xpcom/data/dataObjects.js +++ b/chrome/content/zotero/xpcom/data/dataObjects.js @@ -336,6 +336,253 @@ Zotero.DataObjects.prototype.getNewer = Zotero.Promise.method(function (libraryI }); +/** + * Loads data for a given data type + * @param {String} dataType + * @param {Integer} libraryID + * @param {Integer[]} [ids] + */ +Zotero.DataObjects.prototype._loadDataType = Zotero.Promise.coroutine(function* (dataType, libraryID, ids) { + var funcName = "_load" + dataType[0].toUpperCase() + dataType.substr(1) + // Single data types need an 's' (e.g., 'note' -> 'loadNotes()') + + ((dataType.endsWith('s') || dataType.endsWith('Data') ? '' : 's')); + if (!this[funcName]) { + throw new Error(`Zotero.${this._ZDO_Objects}.${funcName} is not a function`); + } + + if (ids && ids.length == 0) { + return; + } + + var t = new Date; + var libraryName = Zotero.Libraries.get(libraryID).name; + + var idSQL = ""; + if (ids) { + idSQL = " AND " + this.idColumn + " IN (" + ids.map(id => parseInt(id)).join(", ") + ")"; + } + + Zotero.debug("Loading " + dataType + + (ids + ? " for " + ids.length + " " + (ids.length == 1 ? this._ZDO_object : this._ZDO_objects) + : '') + + " in " + libraryName); + + yield this[funcName](libraryID, ids ? ids : [], idSQL); + + Zotero.debug(`Loaded ${dataType} in ${libraryName} in ${new Date() - t} ms`); +}); + +Zotero.DataObjects.prototype.loadAllData = Zotero.Promise.coroutine(function* (libraryID, ids) { + var t = new Date(); + var libraryName = Zotero.Libraries.get(libraryID).name; + + Zotero.debug("Loading all data" + + (ids ? " for " + ids.length + " " + this._ZDO_objects : '') + + " in " + libraryName); + + let dataTypes = this.ObjectClass.prototype._dataTypes; + for (let i = 0; i < dataTypes.length; i++) { + yield this._loadDataType(dataTypes[i], libraryID, ids); + } + + Zotero.debug(`Loaded all data in ${libraryName} in ${new Date() - t} ms`); +}); + + +Zotero.DataObjects.prototype._loadPrimaryData = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL, options) { + var loaded = {}; + + // If library isn't an integer (presumably false or null), skip it + if (parseInt(libraryID) != libraryID) { + libraryID = false; + } + + var sql = this.primaryDataSQL; + var params = []; + if (libraryID !== false) { + sql += ' AND O.libraryID=?'; + params.push(libraryID); + } + if (ids.length) { + sql += ' AND O.' + this._ZDO_id + ' IN (' + ids.join(',') + ')'; + } + + yield Zotero.DB.queryAsync( + sql, + params, + { + onRow: function (row) { + var id = row.getResultByName(this._ZDO_id); + var columns = Object.keys(this._primaryDataSQLParts); + var rowObj = {}; + for (let i=0; i} */ -Zotero.Item.prototype.clone = Zotero.Promise.coroutine(function* (libraryID, skipTags) { +Zotero.Item.prototype.clone = function (libraryID, skipTags) { Zotero.debug('Cloning item ' + this.id); if (libraryID !== undefined && libraryID !== null && typeof libraryID !== 'number') { throw new Error("libraryID must be null or an integer"); } - yield this.loadPrimaryData(); - if (libraryID === undefined || libraryID === null) { libraryID = this.libraryID; } @@ -3579,7 +3668,6 @@ Zotero.Item.prototype.clone = Zotero.Promise.coroutine(function* (libraryID, ski newItem.libraryID = libraryID; newItem.setType(this.itemTypeID); - yield this.loadItemData(); var fieldIDs = this.getUsedFields(); for (let i = 0; i < fieldIDs.length; i++) { let fieldID = fieldIDs[i]; @@ -3588,11 +3676,9 @@ Zotero.Item.prototype.clone = Zotero.Promise.coroutine(function* (libraryID, ski // Regular item if (this.isRegularItem()) { - yield this.loadCreators(); newItem.setCreators(this.getCreators()); } else { - yield this.loadNote(); newItem.setNote(this.getNote()); if (sameLibrary) { var parent = this.parentKey; @@ -3614,18 +3700,16 @@ Zotero.Item.prototype.clone = Zotero.Promise.coroutine(function* (libraryID, ski } if (!skipTags) { - yield this.loadTags(); newItem.setTags(this.getTags()); } if (sameLibrary) { // DEBUG: this will add reverse-only relateds too - yield this.loadRelations(); newItem.setRelations(this.getRelations()); } return newItem; -}); +} /** @@ -3721,8 +3805,6 @@ Zotero.Item.prototype.isCollection = function() { /** * Populate the object's data from an API JSON data object - * - * If this object is identified (has an id or library/key), loadAllData() must have been called. */ Zotero.Item.prototype.fromJSON = function (json) { if (!json.itemType && !this._itemTypeID) { @@ -3867,7 +3949,7 @@ Zotero.Item.prototype.fromJSON = function (json) { /** * @param {Object} options */ -Zotero.Item.prototype.toJSON = Zotero.Promise.coroutine(function* (options = {}) { +Zotero.Item.prototype.toJSON = function (options = {}) { var env = this._preToJSON(options); var mode = env.mode; @@ -3877,7 +3959,6 @@ Zotero.Item.prototype.toJSON = Zotero.Promise.coroutine(function* (options = {}) obj.itemType = Zotero.ItemTypes.getName(this.itemTypeID); // Fields - yield this.loadItemData(); for (let i in this._itemData) { let val = this.getField(i) + ''; if (val !== '' || mode == 'full') { @@ -3887,7 +3968,6 @@ Zotero.Item.prototype.toJSON = Zotero.Promise.coroutine(function* (options = {}) // Creators if (this.isRegularItem()) { - yield this.loadCreators() obj.creators = this.getCreatorsJSON(); } else { @@ -3912,18 +3992,18 @@ Zotero.Item.prototype.toJSON = Zotero.Promise.coroutine(function* (options = {}) if (this.isFileAttachment()) { if (options.syncedStorageProperties) { - obj.mtime = yield Zotero.Sync.Storage.Local.getSyncedModificationTime(this.id); - obj.md5 = yield Zotero.Sync.Storage.Local.getSyncedHash(this.id); + obj.mtime = this.attachmentSyncedModificationTime; + obj.md5 = this.attachmentSyncedHash; } else { - obj.mtime = (yield this.attachmentModificationTime) || null; - obj.md5 = (yield this.attachmentHash) || null; + // TEMP + //obj.mtime = (yield this.attachmentModificationTime) || null; + //obj.md5 = (yield this.attachmentHash) || null; } } } // Notes and embedded attachment notes - yield this.loadNote(); let note = this.getNote(); if (note !== "" || mode == 'full' || (mode == 'new' && this.isNote())) { obj.note = note; @@ -3932,7 +4012,6 @@ Zotero.Item.prototype.toJSON = Zotero.Promise.coroutine(function* (options = {}) // Tags obj.tags = []; - yield this.loadTags() var tags = this.getTags(); for (let i=0; i/)) { - note = Zotero.Utilities.htmlSpecialChars(note); - note = Zotero.Notes.notePrefix + '

' - + note.replace(/\n/g, '

') - .replace(/\t/g, '    ') - .replace(/ /g, '  ') - + '

' + Zotero.Notes.noteSuffix; - note = note.replace(/

\s*<\/p>/g, '

 

'); - let sql = "UPDATE itemNotes SET note=? WHERE itemID=?"; - yield Zotero.DB.queryAsync(sql, [note, this.id]); - } - - // Don't include
wrapper when returning value - let startLen = note.substr(0, 36).match(/^
/)[0].length; - let endLen = 6; // "
".length - note = note.substr(startLen, note.length - startLen - endLen); - } - - this._noteText = note ? note : ''; - } - - this._loaded.note = true; - this._clearChanged('note'); -}); - - Zotero.Item.prototype.loadDisplayTitle = Zotero.Promise.coroutine(function* (reload) { if (this._displayTitle !== null && !reload) { return; @@ -4097,7 +4082,6 @@ Zotero.Item.prototype.loadDisplayTitle = Zotero.Promise.coroutine(function* (rel var itemTypeName = Zotero.ItemTypes.getName(itemTypeID); if (title === "" && (itemTypeID == 8 || itemTypeID == 10)) { // 'letter' and 'interview' itemTypeIDs - yield this.loadCreators(); var creatorsData = this.getCreators(); var authors = []; var participants = []; @@ -4175,7 +4159,6 @@ Zotero.Item.prototype.loadDisplayTitle = Zotero.Promise.coroutine(function* (rel strParts.push(part); } - yield this.loadCreators() var creatorData = this.getCreator(0); if (creatorData && creatorData.creatorTypeID === 1) { // author strParts.push(creatorData.lastName); @@ -4189,156 +4172,6 @@ Zotero.Item.prototype.loadDisplayTitle = Zotero.Promise.coroutine(function* (rel }); -/* - * Load in the creators from the database - */ -Zotero.Item.prototype.loadCreators = Zotero.Promise.coroutine(function* (reload) { - if (this._loaded.creators && !reload) { - return; - } - - Zotero.debug("Loading creators for item " + this.libraryKey); - - if (!this.id) { - throw new Error('ItemID not set for item before attempting to load creators'); - } - - var sql = 'SELECT creatorID, creatorTypeID, orderIndex FROM itemCreators ' - + 'WHERE itemID=? ORDER BY orderIndex'; - var rows = yield Zotero.DB.queryAsync(sql, this.id); - - this._creators = []; - this._creatorIDs = []; - this._loaded.creators = true; - this._clearChanged('creators'); - - if (!rows) { - return true; - } - - var maxOrderIndex = -1; - for (var i=0; i maxOrderIndex) { - maxOrderIndex = row.orderIndex; - } - let creatorData = yield Zotero.Creators.getAsync(row.creatorID); - creatorData.creatorTypeID = row.creatorTypeID; - this._creators[i] = creatorData; - this._creatorIDs[i] = row.creatorID; - } - if (i <= maxOrderIndex) { - Zotero.debug("Fixing incorrect creator indexes for item " + this.libraryKey - + " (" + i + ", " + maxOrderIndex + ")", 2); - while (i <= maxOrderIndex) { - this._changed.creators[i] = true; - i++; - } - } - - return true; -}); - - -Zotero.Item.prototype.loadChildItems = Zotero.Promise.coroutine(function* (reload) { - if (this._loaded.childItems && !reload) { - return; - } - - if (this.isNote() || this.isAttachment()) { - return; - } - - // Attachments - this._attachments = { - rows: null, - chronologicalWithTrashed: null, - chronologicalWithoutTrashed: null, - alphabeticalWithTrashed: null, - alphabeticalWithoutTrashed: null - }; - var sql = "SELECT A.itemID, value AS title, CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed " - + "FROM itemAttachments A " - + "NATURAL JOIN items I " - + "LEFT JOIN itemData ID ON (fieldID=110 AND A.itemID=ID.itemID) " - + "LEFT JOIN itemDataValues IDV USING (valueID) " - + "LEFT JOIN deletedItems DI USING (itemID) " - + "WHERE parentItemID=?"; - // Since we do the sort here and cache these results, a restart will be required - // if this pref (off by default) is turned on, but that's OK - if (Zotero.Prefs.get('sortAttachmentsChronologically')) { - sql += " ORDER BY dateAdded"; - } - this._attachments.rows = yield Zotero.DB.queryAsync(sql, this.id); - - // - // Notes - // - this._notes = { - rows: null, - rowsEmbedded: null, - chronologicalWithTrashed: null, - chronologicalWithoutTrashed: null, - alphabeticalWithTrashed: null, - alphabeticalWithoutTrashed: null, - numWithTrashed: null, - numWithoutTrashed: null, - numWithTrashedWithEmbedded: null, - numWithoutTrashedWithoutEmbedded: null - }; - var sql = "SELECT N.itemID, title, CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed " - + "FROM itemNotes N " - + "NATURAL JOIN items I " - + "LEFT JOIN deletedItems DI USING (itemID) " - + "WHERE parentItemID=?"; - if (Zotero.Prefs.get('sortAttachmentsChronologically')) { - sql += " ORDER BY dateAdded"; - } - this._notes.rows = yield Zotero.DB.queryAsync(sql, this.id); - - this._loaded.childItems = true; - this._clearChanged('childItems'); -}); - - -Zotero.Item.prototype.loadTags = Zotero.Promise.coroutine(function* (reload) { - if (this._loaded.tags && !reload) { - return; - } - - if (!this._id) { - return; - } - var sql = "SELECT tagID AS id, name AS tag, type FROM itemTags " - + "JOIN tags USING (tagID) WHERE itemID=?"; - var rows = yield Zotero.DB.queryAsync(sql, this.id); - - this._tags = []; - for (let i=0; i 0 ? ',\n' : ''; let item = yield this.getAsync(ids[i], { noCache: true }); - var json = yield item.toResponseJSON(); + var json = item.toResponseJSON(); yield prefix + JSON.stringify(json, null, 4); } @@ -212,105 +215,24 @@ Zotero.Items = function() { }; - this._cachedFields = {}; - this.cacheFields = Zotero.Promise.coroutine(function* (libraryID, fields, items) { - if (items && items.length == 0) { - return; - } - - var t = new Date; - - fields = fields.concat(); - - // Needed for display titles for some item types - if (fields.indexOf('title') != -1) { - fields.push('reporter', 'court'); - } - - Zotero.debug("Caching fields [" + fields.join() + "]" - + (items ? " for " + items.length + " items" : '') - + " in library " + libraryID); - - if (items && items.length > 0) { - yield this._load(libraryID, items); - } - else { - yield this._load(libraryID); - } - - var primaryFields = []; - var fieldIDs = []; - for each(var field in fields) { - // Check if field already cached - if (this._cachedFields[libraryID] && this._cachedFields[libraryID].indexOf(field) != -1) { - continue; - } - - if (!this._cachedFields[libraryID]) { - this._cachedFields[libraryID] = []; - } - this._cachedFields[libraryID].push(field); - - if (this.isPrimaryField(field)) { - primaryFields.push(field); - } - else { - fieldIDs.push(Zotero.ItemFields.getID(field)); - if (Zotero.ItemFields.isBaseField(field)) { - fieldIDs = fieldIDs.concat(Zotero.ItemFields.getTypeFieldsFromBase(field)); - } - } - } - - if (primaryFields.length) { - var sql = "SELECT O.itemID, " - + primaryFields.map((val) => this.getPrimaryDataSQLPart(val)).join(', ') - + this.primaryDataSQLFrom + " AND O.libraryID=?"; - var params = [libraryID]; - if (items) { - sql += " AND O.itemID IN (" + items.join() + ")"; - } - yield Zotero.DB.queryAsync( - sql, - params, - { - onRow: function (row) { - let obj = { - itemID: row.getResultByIndex(0) - }; - for (let i=0; i maxOrderIndex) { + maxOrderIndex = row.orderIndex; + } + + let creatorData = Zotero.Creators.get(row.creatorID); + creatorData.creatorTypeID = row.creatorTypeID; + item._creators[index] = creatorData; + item._creatorIDs[index] = row.creatorID; + index++; } - Zotero.debug("Cached fields in " + ((new Date) - t) + "ms"); + if (index <= maxOrderIndex) { + fixIncorrectIndexes(item, index, maxOrderIndex); + } + }); + + + this._loadNotes = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var notesToUpdate = []; + + var sql = "SELECT itemID, note FROM items " + + "JOIN itemNotes USING (itemID) " + + "WHERE libraryID=?" + idSQL; + var params = [libraryID]; + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let itemID = row.getResultByIndex(0); + let item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not found"); + } + let note = row.getResultByIndex(1); + + // Convert non-HTML notes on-the-fly + if (note !== "") { + if (!note.substr(0, 36).match(/^
/)) { + note = Zotero.Utilities.htmlSpecialChars(note); + note = Zotero.Notes.notePrefix + '

' + + note.replace(/\n/g, '

') + .replace(/\t/g, '    ') + .replace(/ /g, '  ') + + '

' + Zotero.Notes.noteSuffix; + note = note.replace(/

\s*<\/p>/g, '

 

'); + notesToUpdate.push([item.id, note]); + } + + // Don't include
wrapper when returning value + let startLen = note.substr(0, 36).match(/^
/)[0].length; + let endLen = 6; // "
".length + note = note.substr(startLen, note.length - startLen - endLen); + } + + item._noteText = note ? note : ''; + item._loaded.note = true; + item._clearChanged('note'); + }.bind(this) + } + ); + + if (notesToUpdate.length) { + yield Zotero.DB.executeTransaction(function* () { + for (let i = 0; i < notesToUpdate.length; i++) { + let row = notesToUpdate[i]; + let sql = "UPDATE itemNotes SET note=? WHERE itemID=?"; + yield Zotero.DB.queryAsync(sql, [row[1], row[0]]); + } + }.bind(this)); + } + + // Mark notes and attachments without notes as loaded + sql = "SELECT itemID FROM items WHERE libraryID=?" + idSQL + + " AND itemTypeID IN (?, ?) AND itemID NOT IN (SELECT itemID FROM itemNotes)"; + params = [libraryID, Zotero.ItemTypes.getID('note'), Zotero.ItemTypes.getID('attachment')]; + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let itemID = row.getResultByIndex(0); + let item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not loaded"); + } + + item._noteText = ''; + item._loaded.note = true; + item._clearChanged('note'); + }.bind(this) + } + ); + }); + + + this._loadChildItems = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var params = [libraryID]; + var rows = []; + var onRow = function (row, setFunc) { + var itemID = row.getResultByIndex(0); + + if (lastItemID && itemID !== lastItemID) { + setFunc(lastItemID, rows); + rows = []; + } + + lastItemID = itemID; + rows.push({ + itemID: row.getResultByIndex(1), + title: row.getResultByIndex(2), + trashed: row.getResultByIndex(3) + }); + }; + + var sql = "SELECT parentItemID, A.itemID, value AS title, " + + "CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed " + + "FROM itemAttachments A " + + "JOIN items I ON (A.parentItemID=I.itemID) " + + "LEFT JOIN itemData ID ON (fieldID=110 AND A.itemID=ID.itemID) " + + "LEFT JOIN itemDataValues IDV USING (valueID) " + + "LEFT JOIN deletedItems DI USING (itemID) " + + "WHERE libraryID=?" + + (ids.length ? " AND parentItemID IN (" + ids.map(id => parseInt(id)).join(", ") + ")" : ""); + // Since we do the sort here and cache these results, a restart will be required + // if this pref (off by default) is turned on, but that's OK + if (Zotero.Prefs.get('sortAttachmentsChronologically')) { + sql += " ORDER BY parentItemID, dateAdded"; + } + var setAttachmentItem = function (itemID, rows) { + var item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not loaded"); + } + + item._attachments = { + rows, + chronologicalWithTrashed: null, + chronologicalWithoutTrashed: null, + alphabeticalWithTrashed: null, + alphabeticalWithoutTrashed: null + }; + }.bind(this); + var lastItemID = null; + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + onRow(row, setAttachmentItem); + } + } + ); + if (lastItemID) { + setAttachmentItem(lastItemID, rows); + } + + // + // Notes + // + sql = "SELECT parentItemID, N.itemID, title, " + + "CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed " + + "FROM itemNotes N " + + "JOIN items I ON (N.parentItemID=I.itemID) " + + "LEFT JOIN deletedItems DI USING (itemID) " + + "WHERE libraryID=?" + + (ids.length ? " AND parentItemID IN (" + ids.map(id => parseInt(id)).join(", ") + ")" : ""); + if (Zotero.Prefs.get('sortNotesChronologically')) { + sql += " ORDER BY parentItemID, dateAdded"; + } + var setNoteItem = function (itemID, rows) { + var item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not loaded"); + } + + item._notes = { + rows, + rowsEmbedded: null, + chronologicalWithTrashed: null, + chronologicalWithoutTrashed: null, + alphabeticalWithTrashed: null, + alphabeticalWithoutTrashed: null, + numWithTrashed: null, + numWithoutTrashed: null, + numWithTrashedWithEmbedded: null, + numWithoutTrashedWithoutEmbedded: null + }; + }.bind(this); + lastItemID = null; + rows = []; + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + onRow(row, setNoteItem); + } + } + ); + if (lastItemID) { + setNoteItem(lastItemID, rows); + } + + // Mark all top-level items as having child items loaded + sql = "SELECT itemID FROM items I WHERE libraryID=?" + idSQL + " AND itemID NOT IN " + + "(SELECT itemID FROM itemAttachments UNION SELECT itemID FROM itemNotes)"; + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + var itemID = row.getResultByIndex(0); + var item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not loaded"); + } + item._loaded.childItems = true; + item._clearChanged('childItems'); + }.bind(this) + } + ); + }); + + + this._loadTags = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var sql = "SELECT itemID, name, type FROM items " + + "LEFT JOIN itemTags USING (itemID) " + + "LEFT JOIN tags USING (tagID) WHERE libraryID=?" + idSQL; + var params = [libraryID]; + + var lastItemID; + var rows = []; + var setRows = function (itemID, rows) { + var item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not found"); + } + + item._tags = []; + for (let i = 0; i < rows.length; i++) { + let row = rows[i]; + item._tags.push(Zotero.Tags.cleanData(row)); + } + + item._loaded.tags = true; + item._clearChanged('tags'); + }.bind(this); + + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let itemID = row.getResultByIndex(0); + + if (lastItemID && itemID !== lastItemID) { + setRows(lastItemID, rows); + rows = []; + } + + lastItemID = itemID; + + // Item has no tags + let tag = row.getResultByIndex(1); + if (tag === null) { + return; + } + + rows.push({ + tag: tag, + type: row.getResultByIndex(2) + }); + }.bind(this) + } + ); + if (lastItemID) { + setRows(lastItemID, rows); + } + }); + + + this._loadCollections = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) { + var sql = "SELECT itemID, collectionID FROM items " + + "LEFT JOIN collectionItems USING (itemID) " + + "WHERE libraryID=?" + idSQL; + var params = [libraryID]; + + var lastItemID; + var rows = []; + var setRows = function (itemID, rows) { + var item = this._objectCache[itemID]; + if (!item) { + throw new Error("Item " + itemID + " not found"); + } + + item._collections = rows; + item._loaded.collections = true; + item._clearChanged('collections'); + }.bind(this); + + yield Zotero.DB.queryAsync( + sql, + params, + { + noCache: ids.length != 1, + onRow: function (row) { + let itemID = row.getResultByIndex(0); + + if (lastItemID && itemID !== lastItemID) { + setRows(lastItemID, rows); + rows = []; + } + + lastItemID = itemID; + let collectionID = row.getResultByIndex(1); + // No collections + if (collectionID === null) { + return; + } + rows.push(collectionID); + }.bind(this) + } + ); + if (lastItemID) { + setRows(lastItemID, rows); + } }); @@ -409,17 +725,11 @@ Zotero.Items = function() { var otherItemIDs = []; var itemURI = Zotero.URI.getItemURI(item); - yield item.loadTags(); - yield item.loadRelations(); var replPred = Zotero.Relations.replacedItemPredicate; var toSave = {}; toSave[this.id]; for each(var otherItem in otherItems) { - yield otherItem.loadChildItems(); - yield otherItem.loadCollections(); - yield otherItem.loadTags(); - yield otherItem.loadRelations(); let otherItemURI = Zotero.URI.getItemURI(otherItem); // Move child items to master @@ -632,16 +942,6 @@ Zotero.Items = function() { }); - this._postLoad = function (libraryID, ids) { - if (!ids) { - if (!this._cachedFields[libraryID]) { - this._cachedFields[libraryID] = []; - } - this._cachedFields[libraryID] = this.primaryFields.concat(); - } - } - - /* * Generate SQL to retrieve firstCreator field * diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js index 5b0ab097c..4eff4f016 100644 --- a/chrome/content/zotero/xpcom/db.js +++ b/chrome/content/zotero/xpcom/db.js @@ -630,7 +630,13 @@ Zotero.DBConnection.prototype.queryAsync = Zotero.Promise.coroutine(function* (s } } } - let rows = yield conn.executeCached(sql, params, onRow); + let rows; + if (options && options.noCache) { + rows = yield conn.execute(sql, params, onRow); + } + else { + rows = yield conn.executeCached(sql, params, onRow); + } // Parse out the SQL command being used let op = sql.match(/^[^a-z]*[^ ]+/i); if (op) { diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js index 920776eb1..ace81c4fe 100644 --- a/chrome/content/zotero/xpcom/itemTreeView.js +++ b/chrome/content/zotero/xpcom/itemTreeView.js @@ -82,7 +82,7 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree if (this._treebox) { if (this._needsSort) { - yield this.sort(); + this.sort(); } return; } @@ -133,11 +133,11 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree if (self._treebox.view.selection.count > 1) { switch (event.keyCode) { case 39: - self.expandSelectedRows().done(); + self.expandSelectedRows(); break; case 37: - self.collapseSelectedRows().done(); + self.collapseSelectedRows(); break; } @@ -148,7 +148,7 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree var key = String.fromCharCode(event.which); if (key == '+' && !(event.ctrlKey || event.altKey || event.metaKey)) { - self.expandAllRows().done(); + self.expandAllRows(); event.preventDefault(); return; } @@ -230,8 +230,8 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree // handleKeyPress() in zoteroPane.js. tree._handleEnter = function () {}; - yield this.sort(); - yield this.expandMatchParents(); + this.sort(); + this.expandMatchParents(); if (this._ownerDocument.defaultView.ZoteroPane_Local) { this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage(); @@ -266,13 +266,10 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree */ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(function* () { Zotero.debug('Refreshing items list for ' + this.id); - //if(!Zotero.ItemTreeView._haveCachedFields) yield Zotero.Promise.resolve(); - var cacheFields = ['title', 'date']; - - // Cache the visible fields so they don't load individually + // DEBUG: necessary? try { - var visibleFields = this.getVisibleFields(); + this._treebox.columns.count } // If treebox isn't ready, skip refresh catch (e) { @@ -286,33 +283,6 @@ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(f }); try { - for (let i=0; i=0; i--) { - yield this.toggleOpenState(rowsToOpen[i], true); + this.toggleOpenState(rowsToOpen[i], true); } this._refreshItemRowMap(); if (unsuppress) { //this._treebox.endUpdateBatch(); this.selection.selectEventsSuppressed = false; } -}); +} -Zotero.ItemTreeView.prototype.expandMatchParents = Zotero.Promise.coroutine(function* () { +Zotero.ItemTreeView.prototype.expandMatchParents = function () { // Expand parents of child matches if (!this._searchMode) { return; @@ -2001,7 +1952,7 @@ Zotero.ItemTreeView.prototype.expandMatchParents = Zotero.Promise.coroutine(func for (var i=0; i} - File hash, null if never synced, if false if - * file doesn't exist - */ - getSyncedHash: Zotero.Promise.coroutine(function* (itemID) { - var sql = "SELECT storageHash FROM itemAttachments WHERE itemID=?"; - var hash = yield Zotero.DB.valueQueryAsync(sql, itemID); - if (hash === false) { - throw new Error("Item " + itemID + " not found"); - } - return hash; - }), - - - /** - * @param {Integer} itemID - * @param {String} hash File hash - * @param {Boolean} [updateItem=FALSE] - Mark attachment item as unsynced - */ - setSyncedHash: Zotero.Promise.coroutine(function* (itemID, hash, updateItem) { - if (hash !== null && hash.length != 32) { - throw new Error("Invalid file hash '" + hash + "'"); - } - - Zotero.DB.requireTransaction(); - - var sql = "UPDATE itemAttachments SET storageHash=? WHERE itemID=?"; - yield Zotero.DB.queryAsync(sql, [hash, itemID]); - - if (updateItem) { - let item = yield Zotero.Items.getAsync(itemID); - yield item.updateSynced(false); - } + sql = "UPDATE itemAttachments SET syncState=? WHERE itemID IN (" + sql + ")"; + yield Zotero.DB.queryAsync(sql, [this.SYNC_STATE_TO_UPLOAD].concat(params)); }), @@ -678,11 +577,10 @@ Zotero.Sync.Storage.Local = { // Set the file mtime to the time from the server yield OS.File.setDates(path, null, new Date(parseInt(mtime))); - yield Zotero.DB.executeTransaction(function* () { - yield this.setSyncedHash(item.id, md5); - yield this.setSyncState(item.id, this.SYNC_STATE_IN_SYNC); - yield this.setSyncedModificationTime(item.id, mtime); - }.bind(this)); + item.attachmentSyncState = this.SYNC_STATE_IN_SYNC; + item.attachmentSyncedModificationTime = mtime; + item.attachmentSyncedHash = md5; + yield item.saveTx(); return new Zotero.Sync.Storage.Result({ localChanges: true @@ -1040,7 +938,7 @@ Zotero.Sync.Storage.Local = { for (let localItem of localItems) { // Use the mtime for the dateModified field, since that's all that's shown in the // CR window at the moment - let localItemJSON = yield localItem.toJSON(); + let localItemJSON = localItem.toJSON(); localItemJSON.dateModified = Zotero.Date.dateToISO( new Date(yield localItem.attachmentModificationTime) ); @@ -1101,8 +999,9 @@ Zotero.Sync.Storage.Local = { else { syncState = this.SYNC_STATE_FORCE_DOWNLOAD; } - let itemID = Zotero.Items.getIDFromLibraryAndKey(libraryID, conflict.left.key); - yield Zotero.Sync.Storage.Local.setSyncState(itemID, syncState); + let item = Zotero.Items.getByLibraryAndKey(libraryID, conflict.left.key); + item.attachmentSyncState = syncState; + yield item.save({ skipAll: true }); } }.bind(this)); return true; diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js index 13f64bc86..49c133c6b 100644 --- a/chrome/content/zotero/xpcom/storage/webdav.js +++ b/chrome/content/zotero/xpcom/storage/webdav.js @@ -288,15 +288,14 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { Zotero.debug("File mod time matches remote file -- skipping download of " + item.libraryKey); - yield Zotero.DB.executeTransaction(function* () { - var syncState = Zotero.Sync.Storage.Local.getSyncState(item.id); - // DEBUG: Necessary to update item? - var updateItem = syncState != 1; - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, metadata.mtime, updateItem - ); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + var updateItem = item.attachmentSyncState != 1 + item.attachmentSyncedModificationTime = metadata.mtime; + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); + // DEBUG: Necessary? + if (updateItem) { + yield item.updateSynced(false); + } return new Zotero.Sync.Storage.Result({ localChanges: true, // ? @@ -416,7 +415,7 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { } // Check if file already exists on WebDAV server - if ((yield Zotero.Sync.Storage.Local.getSyncState(item.id)) + if (item.attachmentSyncState != Zotero.Sync.Storage.Local.SYNC_STATE_FORCE_UPLOAD) { if (metadata.mtime) { // Local file time @@ -438,15 +437,14 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { // If WebDAV server already has file, update synced properties if (!changed) { - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, fmtime, true - ); - if (hash) { - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, hash); - } - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + item.attachmentSyncedModificationTime = fmtime; + if (hash) { + item.attachmentSyncedHash = hash; + } + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); + // skipAll doesn't mark as unsynced, so do that separately + yield item.updateSynced(false); return new Zotero.Sync.Storage.Result; } } @@ -460,9 +458,9 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { // API would ever be updated with the correct values, so we can't just wait for // the API to change.) If a conflict is found, we flag the item as in conflict // and require another file sync, which will trigger conflict resolution. - let smtime = yield Zotero.Sync.Storage.Local.getSyncedModificationTime(item.id); + let smtime = item.attachmentSyncedModificationTime; if (smtime != mtime) { - let shash = yield Zotero.Sync.Storage.Local.getSyncedHash(item.id); + let shash = item.attachmentSyncedHash; if (shash && metadata.md5 && shash == metadata.md5) { Zotero.debug("Last synced mod time for item " + item.libraryKey + " doesn't match time on storage server but hash does -- ignoring"); @@ -472,12 +470,13 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { Zotero.logError("Conflict -- last synced file mod time for item " + item.libraryKey + " does not match time on storage server" + " (" + smtime + " != " + mtime + ")"); - yield Zotero.DB.executeTransaction(function* () { - // Conflict resolution uses the synced mtime as the remote value, so set - // that to the WebDAV value, since that's the one in conflict. - yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, mtime); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_conflict"); - }); + + // Conflict resolution uses the synced mtime as the remote value, so set + // that to the WebDAV value, since that's the one in conflict. + item.attachmentSyncedModificationTime = mtime; + item.attachmentSyncState = "in_conflict"; + yield item.saveTx({ skipAll: true }); + return new Zotero.Sync.Storage.Result({ fileSyncRequired: true }); @@ -1191,7 +1190,10 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { throw new Error(Zotero.Sync.Storage.Mode.WebDAV.defaultError); } - return { mtime, md5 }; + return { + mtime: parseInt(mtime), + md5 + }; }), @@ -1243,11 +1245,12 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { // Update .prop file on WebDAV server yield this._setStorageFileMetadata(item); - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, params.mtime, true); - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, params.md5); - }); + item.attachmentSyncedModificationTime = params.mtime; + item.attachmentSyncedHash = params.md5; + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); + // skipAll doesn't mark as unsynced, so do that separately + yield item.updateSynced(false); try { yield OS.File.remove( diff --git a/chrome/content/zotero/xpcom/storage/zfs.js b/chrome/content/zotero/xpcom/storage/zfs.js index 43ee3744b..e8f2b4bfa 100644 --- a/chrome/content/zotero/xpcom/storage/zfs.js +++ b/chrome/content/zotero/xpcom/storage/zfs.js @@ -131,15 +131,13 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { } // Update local metadata and stop request, skipping file download - yield Zotero.DB.executeTransaction(function* () { - if (updateHash) { - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, requestData.md5); - } - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, requestData.mtime - ); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + item.attachmentSyncedModificationTime = requestData.mtime; + if (updateHash) { + item.attachmentSyncedHash = requestData.md5; + } + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); + return false; }), onProgress: function (a, b, c) { @@ -261,7 +259,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { var sql = "SELECT value FROM settings WHERE setting=? AND key=?"; var values = yield Zotero.DB.columnQueryAsync(sql, ['storage', 'zfsPurge']); - if (!values) { + if (!values.length) { return false; } @@ -353,7 +351,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { var headers = { "Content-Type": "application/x-www-form-urlencoded" }; - var storedHash = yield Zotero.Sync.Storage.Local.getSyncedHash(item.id); + var storedHash = item.attachmentSyncedHash; //var storedModTime = yield Zotero.Sync.Storage.getSyncedModificationTime(item.id); if (storedHash) { headers["If-Match"] = storedHash; @@ -538,17 +536,17 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { Zotero.debug(fileHash); if (json.data.md5 == fileHash) { - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, fileModTime - ); - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, fileHash); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + item.attachmentSyncedModificationTime = fileModTime; + item.attachmentSyncedHash = fileHash; + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); + return new Zotero.Sync.Storage.Result; } - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_conflict"); + item.attachmentSyncState = "in_conflict"; + yield item.saveTx({ skipAll: true }); + return new Zotero.Sync.Storage.Result({ fileSyncRequired: true }); @@ -767,11 +765,12 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { _updateItemFileInfo: Zotero.Promise.coroutine(function* (item, params) { // Mark as in-sync yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); + // Store file mod time and hash + item.attachmentSyncedModificationTime = params.mtime; + item.attachmentSyncedHash = params.md5; + item.attachmentSyncState = "in_sync"; + yield item.save({ skipAll: true }); - // Store file mod time and hash - yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, params.mtime); - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, params.md5); // Update sync cache with new file metadata and version from server var json = yield Zotero.Sync.Data.Local.getCacheObject( 'item', item.libraryID, item.key, item.version @@ -933,7 +932,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = { } // Check for conflict - if ((yield Zotero.Sync.Storage.Local.getSyncState(item.id)) + if (item.attachmentSyncState != Zotero.Sync.Storage.Local.SYNC_STATE_FORCE_UPLOAD) { if (info) { // Local file time diff --git a/chrome/content/zotero/xpcom/sync/syncEngine.js b/chrome/content/zotero/xpcom/sync/syncEngine.js index 23b1242ae..10d65e5e6 100644 --- a/chrome/content/zotero/xpcom/sync/syncEngine.js +++ b/chrome/content/zotero/xpcom/sync/syncEngine.js @@ -316,7 +316,7 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func // Conflict resolution else if (objectType == 'item') { conflicts.push({ - left: yield obj.toJSON(), + left: obj.toJSON(), right: { deleted: true } diff --git a/chrome/content/zotero/xpcom/sync/syncLocal.js b/chrome/content/zotero/xpcom/sync/syncLocal.js index 997f026c7..a2df6ce3c 100644 --- a/chrome/content/zotero/xpcom/sync/syncLocal.js +++ b/chrome/content/zotero/xpcom/sync/syncLocal.js @@ -512,7 +512,7 @@ Zotero.Sync.Data.Local = { objectType, obj.libraryID, obj.key, obj.version ); - let jsonDataLocal = yield obj.toJSON(); + let jsonDataLocal = obj.toJSON(); // For items, check if mtime or file hash changed in metadata, // which would indicate that a remote storage sync took place and @@ -780,7 +780,8 @@ Zotero.Sync.Data.Local = { markToDownload = true; } if (markToDownload) { - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "to_download"); + item.attachmentSyncState = "to_download"; + yield item.save({ skipAll: true }); } }), @@ -870,7 +871,6 @@ Zotero.Sync.Data.Local = { _saveObjectFromJSON: Zotero.Promise.coroutine(function* (obj, json, options) { try { - yield obj.loadAllData(); obj.fromJSON(json); if (!options.saveAsChanged) { obj.version = json.version; diff --git a/chrome/content/zotero/xpcom/timeline.js b/chrome/content/zotero/xpcom/timeline.js index ed473c9a0..fdf27afb3 100644 --- a/chrome/content/zotero/xpcom/timeline.js +++ b/chrome/content/zotero/xpcom/timeline.js @@ -31,7 +31,6 @@ Zotero.Timeline = { yield '\n'; for (let i=0; i items.add(item)); } @@ -720,7 +718,7 @@ Zotero.Translate.ItemGetter.prototype = { * Converts an attachment to array format and copies it to the export folder if desired */ "_attachmentToArray":Zotero.Promise.coroutine(function* (attachment) { - var attachmentArray = yield Zotero.Utilities.Internal.itemToExportFormat(attachment, this.legacy); + var attachmentArray = Zotero.Utilities.Internal.itemToExportFormat(attachment, this.legacy); var linkMode = attachment.attachmentLinkMode; if(linkMode != Zotero.Attachments.LINK_MODE_LINKED_URL) { var attachFile = attachment.getFile(); @@ -864,13 +862,13 @@ Zotero.Translate.ItemGetter.prototype = { var returnItemArray = yield this._attachmentToArray(returnItem); if(returnItemArray) return returnItemArray; } else { - var returnItemArray = yield Zotero.Utilities.Internal.itemToExportFormat(returnItem, this.legacy); + var returnItemArray = Zotero.Utilities.Internal.itemToExportFormat(returnItem, this.legacy); // get attachments, although only urls will be passed if exportFileData is off returnItemArray.attachments = []; var attachments = returnItem.getAttachments(); for each(var attachmentID in attachments) { - var attachment = yield Zotero.Items.getAsync(attachmentID); + var attachment = Zotero.Items.get(attachmentID); var attachmentInfo = yield this._attachmentToArray(attachment); if(attachmentInfo) { diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js index 001099194..d623696f2 100644 --- a/chrome/content/zotero/xpcom/utilities.js +++ b/chrome/content/zotero/xpcom/utilities.js @@ -1591,8 +1591,9 @@ Zotero.Utilities = { */ "itemToCSLJSON":function(zoteroItem) { if (zoteroItem instanceof Zotero.Item) { - return Zotero.Utilities.Internal.itemToExportFormat(zoteroItem). - then(Zotero.Utilities.itemToCSLJSON); + return this.itemToCSLJSON( + Zotero.Utilities.Internal.itemToExportFormat(zoteroItem) + ); } var cslType = CSL_TYPE_MAPPINGS[zoteroItem.itemType]; diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js index 5aca23268..e5d6e21dc 100644 --- a/chrome/content/zotero/xpcom/utilities_internal.js +++ b/chrome/content/zotero/xpcom/utilities_internal.js @@ -610,44 +610,7 @@ Zotero.Utilities.Internal = { * @param {Boolean} legacy Add mappings for legacy (pre-4.0.27) translators * @return {Promise} */ - "itemToExportFormat": new function() { - return Zotero.Promise.coroutine(function* (zoteroItem, legacy) { - var item = yield zoteroItem.toJSON(); - - item.uri = Zotero.URI.getItemURI(zoteroItem); - delete item.key; - - if (!zoteroItem.isAttachment() && !zoteroItem.isNote()) { - yield zoteroItem.loadChildItems(); - - // Include attachments - item.attachments = []; - let attachments = zoteroItem.getAttachments(); - for (let i=0; i x.libraryID); + for (let libraryID of libraryIDs) { + yield Zotero.Collections.loadAllData(libraryID); + yield Zotero.Searches.loadAllData(libraryID); + yield Zotero.Items.loadAllData(libraryID); + } + yield Zotero.QuickCopy.init(); Zotero.Items.startEmptyTrashTimer(); diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 6c835677e..dace7b126 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -1294,7 +1294,6 @@ var ZoteroPane = new function() var clearUndo = noteEditor.item ? noteEditor.item.id != item.id : false; noteEditor.parent = null; - yield item.loadNote(); noteEditor.item = item; // If loading new or different note, disable undo while we repopulate the text field @@ -1325,8 +1324,6 @@ var ZoteroPane = new function() else if (item.isAttachment()) { var attachmentBox = document.getElementById('zotero-attachment-box'); attachmentBox.mode = this.collectionsView.editable ? 'edit' : 'view'; - yield item.loadItemData(); - yield item.loadNote(); attachmentBox.item = item; document.getElementById('zotero-item-pane-content').selectedIndex = 3; @@ -1588,7 +1585,7 @@ var ZoteroPane = new function() var newItem; yield Zotero.DB.executeTransaction(function* () { - newItem = yield item.clone(null, !Zotero.Prefs.get('groups.copyTags')); + newItem = item.clone(null, !Zotero.Prefs.get('groups.copyTags')); yield newItem.save(); if (self.collectionsView.selectedTreeRow.isCollection() && newItem.isTopLevelItem()) { @@ -3641,7 +3638,6 @@ var ZoteroPane = new function() // Fall back to first attachment link if (!uri) { - yield item.loadChildItems(); let attachmentID = item.getAttachments()[0]; if (attachmentID) { let attachment = yield Zotero.Items.getAsync(attachmentID); @@ -3851,7 +3847,7 @@ var ZoteroPane = new function() }); - this.showPublicationsWizard = Zotero.Promise.coroutine(function* (items) { + this.showPublicationsWizard = function (items) { var io = { hasFiles: false, hasNotes: false, @@ -3863,14 +3859,12 @@ var ZoteroPane = new function() for (let i = 0; i < items.length; i++) { let item = items[i]; - yield item.loadItemData(); - yield item.loadChildItems(); - // Files if (!io.hasFiles && item.numAttachments()) { - let attachments = item.getAttachments(); - attachments = yield Zotero.Items.getAsync(attachments); - io.hasFiles = attachments.some(attachment => attachment.isFileAttachment()); + let attachmentIDs = item.getAttachments(); + io.hasFiles = Zotero.Items.get(attachmentIDs).some( + attachment => attachment.isFileAttachment() + ); } // Notes if (!io.hasNotes && item.numNotes()) { @@ -3887,7 +3881,7 @@ var ZoteroPane = new function() io.hasRights = allItemsHaveRights ? 'all' : (noItemsHaveRights ? 'none' : 'some'); window.openDialog('chrome://zotero/content/publicationsDialog.xul','','chrome,modal', io); return io.license ? io : false; - }); + }; /** diff --git a/components/zotero-protocol-handler.js b/components/zotero-protocol-handler.js index a0ce44e08..36c3d16d5 100644 --- a/components/zotero-protocol-handler.js +++ b/components/zotero-protocol-handler.js @@ -214,7 +214,7 @@ function ZoteroProtocolHandler() { else if (combineChildItems || !results[i].isRegularItem() || results[i].numChildren() == 0) { itemsHash[results[i].id] = [items.length]; - items.push(yield results[i].toJSON({ mode: 'full' })); + items.push(results[i].toJSON({ mode: 'full' })); // Flag item as a search match items[items.length - 1].reportSearchMatch = true; } @@ -241,7 +241,6 @@ function ZoteroProtocolHandler() { } } }; - yield item.loadChildItems(); func(item.getNotes()); func(item.getAttachments()); } @@ -252,7 +251,7 @@ function ZoteroProtocolHandler() { else { for (var i in unhandledParents) { itemsHash[results[i].id] = [items.length]; - items.push(yield results[i].toJSON({ mode: 'full' })); + items.push(results[i].toJSON({ mode: 'full' })); // Flag item as a search match items[items.length - 1].reportSearchMatch = true; } @@ -264,7 +263,7 @@ function ZoteroProtocolHandler() { if (!searchItemIDs[id] && !itemsHash[id]) { var item = yield Zotero.Items.getAsync(id); itemsHash[id] = items.length; - items.push(yield item.toJSON({ mode: 'full' })); + items.push(item.toJSON({ mode: 'full' })); } } @@ -279,10 +278,10 @@ function ZoteroProtocolHandler() { }; } if (item.isNote()) { - items[itemsHash[parentID]].reportChildren.notes.push(yield item.toJSON({ mode: 'full' })); + items[itemsHash[parentID]].reportChildren.notes.push(item.toJSON({ mode: 'full' })); } if (item.isAttachment()) { - items[itemsHash[parentID]].reportChildren.attachments.push(yield item.toJSON({ mode: 'full' })); + items[itemsHash[parentID]].reportChildren.attachments.push(item.toJSON({ mode: 'full' })); } } } @@ -299,7 +298,7 @@ function ZoteroProtocolHandler() { // add on its own if (searchItemIDs[parentID]) { itemsHash[parentID] = [items.length]; - items.push(yield parentItem.toJSON({ mode: 'full' })); + items.push(parentItem.toJSON({ mode: 'full' })); items[items.length - 1].reportSearchMatch = true; } else { @@ -312,14 +311,14 @@ function ZoteroProtocolHandler() { items.push(parentItem.toJSON({ mode: 'full' })); if (item.isNote()) { items[items.length - 1].reportChildren = { - notes: [yield item.toJSON({ mode: 'full' })], + notes: [item.toJSON({ mode: 'full' })], attachments: [] }; } else if (item.isAttachment()) { items[items.length - 1].reportChildren = { notes: [], - attachments: [yield item.toJSON({ mode: 'full' })] + attachments: [item.toJSON({ mode: 'full' })] }; } } @@ -609,7 +608,6 @@ function ZoteroProtocolHandler() { if (params.controller == 'data') { switch (params.scopeObject) { case 'collections': - yield collection.loadChildItems(); var results = collection.getChildItems(); break; diff --git a/test/content/support.js b/test/content/support.js index c4af200b2..38da3e99c 100644 --- a/test/content/support.js +++ b/test/content/support.js @@ -352,10 +352,9 @@ function getNameProperty(objectType) { return objectType == 'item' ? 'title' : 'name'; } -var modifyDataObject = Zotero.Promise.coroutine(function* (obj, params = {}, saveOptions) { +var modifyDataObject = function (obj, params = {}, saveOptions) { switch (obj.objectType) { case 'item': - yield obj.loadItemData(); obj.setField( 'title', params.title !== undefined ? params.title : Zotero.Utilities.randomString() @@ -366,7 +365,7 @@ var modifyDataObject = Zotero.Promise.coroutine(function* (obj, params = {}, sav obj.name = params.name !== undefined ? params.name : Zotero.Utilities.randomString(); } return obj.saveTx(saveOptions); -}); +}; /** * Return a promise for the error thrown by a promise, or false if none @@ -584,7 +583,7 @@ var generateItemJSONData = Zotero.Promise.coroutine(function* generateItemJSONDa for (let itemName in items) { let zItem = yield Zotero.Items.getAsync(items[itemName].id); - jsonData[itemName] = yield zItem.toJSON(options); + jsonData[itemName] = zItem.toJSON(options); // Don't replace some fields that _always_ change (e.g. item keys) // as long as it follows expected format diff --git a/test/resource/chai b/test/resource/chai index b369f2524..775281e13 160000 --- a/test/resource/chai +++ b/test/resource/chai @@ -1 +1 @@ -Subproject commit b369f252432c3486a66a0e93f441e4abb133d229 +Subproject commit 775281e138df26101fba1e554c516f47438851b5 diff --git a/test/resource/mocha b/test/resource/mocha index 2a8594424..44b004546 160000 --- a/test/resource/mocha +++ b/test/resource/mocha @@ -1 +1 @@ -Subproject commit 2a8594424c73ffeca41ef1668446372160528b4a +Subproject commit 44b0045463907b1d7963a2e9560c24d9552aac5d diff --git a/test/tests/collectionTest.js b/test/tests/collectionTest.js index 269f7ab15..41f975efc 100644 --- a/test/tests/collectionTest.js +++ b/test/tests/collectionTest.js @@ -152,7 +152,6 @@ describe("Zotero.Collection", function() { var collection2 = yield createDataObject('collection', { parentID: collection1.id }); yield collection1.saveTx(); - yield collection1.loadChildCollections(); var childCollections = collection1.getChildCollections(); assert.lengthOf(childCollections, 1); assert.equal(childCollections[0].id, collection2.id); @@ -163,8 +162,6 @@ describe("Zotero.Collection", function() { var collection2 = yield createDataObject('collection', { parentID: collection1.id }); yield collection1.saveTx(); - yield collection1.loadChildCollections(); - collection2.parentID = false; yield collection2.save() @@ -180,7 +177,6 @@ describe("Zotero.Collection", function() { item.addToCollection(collection.key); yield item.saveTx(); - yield collection.loadChildItems(); assert.lengthOf(collection.getChildItems(), 1); }) @@ -191,7 +187,6 @@ describe("Zotero.Collection", function() { item.addToCollection(collection.key); yield item.saveTx(); - yield collection.loadChildItems(); assert.lengthOf(collection.getChildItems(), 0); }) @@ -202,7 +197,6 @@ describe("Zotero.Collection", function() { item.addToCollection(collection.key); yield item.saveTx(); - yield collection.loadChildItems(); assert.lengthOf(collection.getChildItems(false, true), 1); }) }) diff --git a/test/tests/collectionTreeViewTest.js b/test/tests/collectionTreeViewTest.js index 742c66fac..f8a77e41b 100644 --- a/test/tests/collectionTreeViewTest.js +++ b/test/tests/collectionTreeViewTest.js @@ -390,12 +390,6 @@ describe("Zotero.CollectionTreeView", function() { parentItemID: item.id }); - // Hack to unload relations to test proper loading - // - // Probably need a better method for this - item._loaded.relations = false; - attachment._loaded.relations = false; - var ids = (yield drop('item', 'L' + group.libraryID, [item.id])).ids; yield cv.selectLibrary(group.libraryID); @@ -413,7 +407,7 @@ describe("Zotero.CollectionTreeView", function() { // Check attachment assert.isTrue(itemsView.isContainer(0)); - yield itemsView.toggleOpenState(0); + itemsView.toggleOpenState(0); assert.equal(itemsView.rowCount, 2); treeRow = itemsView.getRow(1); assert.equal(treeRow.ref.id, ids[1]); diff --git a/test/tests/creatorsTest.js b/test/tests/creatorsTest.js new file mode 100644 index 000000000..90ccf202a --- /dev/null +++ b/test/tests/creatorsTest.js @@ -0,0 +1,21 @@ +"use strict"; + +describe("Zotero.Creators", function() { + describe("#getIDFromData()", function () { + it("should create creator and cache data", function* () { + var data1 = { + firstName: "First", + lastName: "Last" + }; + var creatorID; + yield Zotero.DB.executeTransaction(function* () { + creatorID = yield Zotero.Creators.getIDFromData(data1, true); + }); + assert.typeOf(creatorID, 'number'); + var data2 = Zotero.Creators.get(creatorID); + assert.isObject(data2); + assert.propertyVal(data2, "firstName", data1.firstName); + assert.propertyVal(data2, "lastName", data1.lastName); + }); + }); +}); diff --git a/test/tests/dataObjectTest.js b/test/tests/dataObjectTest.js index 18b4f62d4..13f178d6c 100644 --- a/test/tests/dataObjectTest.js +++ b/test/tests/dataObjectTest.js @@ -56,7 +56,6 @@ describe("Zotero.DataObject", function() { yield obj.saveTx(); if (type == 'item') { - yield obj.loadItemData(); obj.setField('title', Zotero.Utilities.randomString()); } else { @@ -131,7 +130,6 @@ describe("Zotero.DataObject", function() { yield obj.saveTx(); if (type == 'item') { - yield obj.loadItemData(); obj.setField('title', Zotero.Utilities.randomString()); } else { @@ -294,7 +292,7 @@ describe("Zotero.DataObject", function() { let obj = yield createDataObject(type); let libraryID = obj.libraryID; let key = obj.key; - let json = yield obj.toJSON(); + let json = obj.toJSON(); yield Zotero.Sync.Data.Local.saveCacheObjects(type, libraryID, [json]); yield obj.eraseTx(); let versions = yield Zotero.Sync.Data.Local.getCacheObjectVersions( diff --git a/test/tests/dataObjectUtilitiesTest.js b/test/tests/dataObjectUtilitiesTest.js index 565f7d66c..bf425c1a2 100644 --- a/test/tests/dataObjectUtilitiesTest.js +++ b/test/tests/dataObjectUtilitiesTest.js @@ -25,11 +25,11 @@ describe("Zotero.DataObjectUtilities", function() { yield Zotero.DB.executeTransaction(function* () { var item = new Zotero.Item('book'); id1 = yield item.save(); - json1 = yield item.toJSON(); + json1 = item.toJSON(); var item = new Zotero.Item('book'); id2 = yield item.save(); - json2 = yield item.toJSON(); + json2 = item.toJSON(); }); var changes = Zotero.DataObjectUtilities.diff(json1, json2); diff --git a/test/tests/fileInterfaceTest.js b/test/tests/fileInterfaceTest.js index d098c2914..b3435593b 100644 --- a/test/tests/fileInterfaceTest.js +++ b/test/tests/fileInterfaceTest.js @@ -21,7 +21,7 @@ describe("Zotero_File_Interface", function() { let childItems = importedCollection[0].getChildItems(); let savedItems = {}; for (let i=0; i o.toResponseJSON())); + objectResponseJSON[type] = objects[type].map(o => o.toResponseJSON()); } server.respond(function (req) { @@ -457,12 +457,11 @@ describe("Zotero.Sync.Data.Engine", function () { var mtime = new Date().getTime(); var md5 = '57f8a4fda823187b91e1191487b87fe6'; - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, mtime); - yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, md5); - }); + item.attachmentSyncedModificationTime = mtime; + item.attachmentSyncedHash = md5; + yield item.saveTx({ skipAll: true }); - var itemResponseJSON = yield item.toResponseJSON(); + var itemResponseJSON = item.toResponseJSON(); itemResponseJSON.version = itemResponseJSON.data.version = lastLibraryVersion; itemResponseJSON.data.mtime = mtime; itemResponseJSON.data.md5 = md5; @@ -520,7 +519,7 @@ describe("Zotero.Sync.Data.Engine", function () { for (let type of types) { objects[type] = [yield createDataObject(type, { setTitle: true })]; objectNames[type] = {}; - objectResponseJSON[type] = yield Zotero.Promise.all(objects[type].map(o => o.toResponseJSON())); + objectResponseJSON[type] = objects[type].map(o => o.toResponseJSON()); } server.respond(function (req) { @@ -569,7 +568,6 @@ describe("Zotero.Sync.Data.Engine", function () { let version = o.version; let name = objectNames[type][key]; if (type == 'item') { - yield o.loadItemData(); assert.equal(name, o.getField('title')); } else { @@ -675,7 +673,7 @@ describe("Zotero.Sync.Data.Engine", function () { { key: obj.key, version: obj.version, - data: (yield obj.toJSON()) + data: obj.toJSON() } ] ); diff --git a/test/tests/syncLocalTest.js b/test/tests/syncLocalTest.js index 611ae7abb..3f5b82c7b 100644 --- a/test/tests/syncLocalTest.js +++ b/test/tests/syncLocalTest.js @@ -105,7 +105,7 @@ describe("Zotero.Sync.Data.Local", function() { for (let type of types) { let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type); let obj = yield createDataObject(type); - let data = yield obj.toJSON(); + let data = obj.toJSON(); data.key = obj.key; data.version = 10; let json = { @@ -130,7 +130,7 @@ describe("Zotero.Sync.Data.Local", function() { var type = 'item'; let obj = yield createDataObject(type, { version: 5 }); - let data = yield obj.toJSON(); + let data = obj.toJSON(); yield Zotero.Sync.Data.Local.saveCacheObjects( type, libraryID, [data] ); @@ -165,7 +165,7 @@ describe("Zotero.Sync.Data.Local", function() { for (let type of types) { let obj = yield createDataObject(type, { version: 5 }); - let data = yield obj.toJSON(); + let data = obj.toJSON(); yield Zotero.Sync.Data.Local.saveCacheObjects( type, libraryID, [data] ); @@ -175,7 +175,7 @@ describe("Zotero.Sync.Data.Local", function() { let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type); let obj = yield createDataObject(type, { version: 10 }); - let data = yield obj.toJSON(); + let data = obj.toJSON(); yield Zotero.Sync.Data.Local.saveCacheObjects( type, libraryID, [data] ); @@ -222,11 +222,8 @@ describe("Zotero.Sync.Data.Local", function() { yield Zotero.Sync.Data.Local.processSyncCacheForObjectType( libraryID, 'item', { stopOnError: true } ); - var id = Zotero.Items.getIDFromLibraryAndKey(libraryID, key); - assert.equal( - (yield Zotero.Sync.Storage.Local.getSyncState(id)), - Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD - ); + var item = Zotero.Items.getByLibraryAndKey(libraryID, key); + assert.equal(item.attachmentSyncState, Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD); }) it("should mark updated attachment items for download", function* () { @@ -239,18 +236,13 @@ describe("Zotero.Sync.Data.Local", function() { yield item.saveTx(); // Set file as synced - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, (yield item.attachmentModificationTime) - ); - yield Zotero.Sync.Storage.Local.setSyncedHash( - item.id, (yield item.attachmentHash) - ); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + item.attachmentSyncedModificationTime = yield item.attachmentModificationTime; + item.attachmentSyncedHash = yield item.attachmentHash; + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); // Simulate download of version with updated attachment - var json = yield item.toResponseJSON(); + var json = item.toResponseJSON(); json.version = 10; json.data.version = 10; json.data.md5 = '57f8a4fda823187b91e1191487b87fe6'; @@ -263,10 +255,7 @@ describe("Zotero.Sync.Data.Local", function() { libraryID, 'item', { stopOnError: true } ); - assert.equal( - (yield Zotero.Sync.Storage.Local.getSyncState(item.id)), - Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD - ); + assert.equal(item.attachmentSyncState, Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD); }) it("should ignore attachment metadata when resolving metadata conflict", function* () { @@ -276,19 +265,14 @@ describe("Zotero.Sync.Data.Local", function() { var item = yield importFileAttachment('test.png'); item.version = 5; yield item.saveTx(); - var json = yield item.toResponseJSON(); + var json = item.toResponseJSON(); yield Zotero.Sync.Data.Local.saveCacheObjects('item', libraryID, [json]); // Set file as synced - yield Zotero.DB.executeTransaction(function* () { - yield Zotero.Sync.Storage.Local.setSyncedModificationTime( - item.id, (yield item.attachmentModificationTime) - ); - yield Zotero.Sync.Storage.Local.setSyncedHash( - item.id, (yield item.attachmentHash) - ); - yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync"); - }); + item.attachmentSyncedModificationTime = yield item.attachmentModificationTime; + item.attachmentSyncedHash = yield item.attachmentHash; + item.attachmentSyncState = "in_sync"; + yield item.saveTx({ skipAll: true }); // Modify title locally, leaving item unsynced var newTitle = Zotero.Utilities.randomString(); @@ -307,10 +291,7 @@ describe("Zotero.Sync.Data.Local", function() { ); assert.equal(item.getField('title'), newTitle); - assert.equal( - (yield Zotero.Sync.Storage.Local.getSyncState(item.id)), - Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD - ); + assert.equal(item.attachmentSyncState, Zotero.Sync.Storage.Local.SYNC_STATE_TO_DOWNLOAD); }) }) @@ -348,7 +329,7 @@ describe("Zotero.Sync.Data.Local", function() { ) } ); - let jsonData = yield obj.toJSON(); + let jsonData = obj.toJSON(); jsonData.key = obj.key; jsonData.version = 10; let json = { @@ -426,7 +407,7 @@ describe("Zotero.Sync.Data.Local", function() { ) } ); - let jsonData = yield obj.toJSON(); + let jsonData = obj.toJSON(); jsonData.key = obj.key; jsonData.version = 10; let json = { @@ -496,7 +477,7 @@ describe("Zotero.Sync.Data.Local", function() { // Create object, generate JSON, and delete var obj = yield createDataObject(type, { version: 10 }); - var jsonData = yield obj.toJSON(); + var jsonData = obj.toJSON(); var key = jsonData.key = obj.key; jsonData.version = 10; let json = { @@ -544,7 +525,7 @@ describe("Zotero.Sync.Data.Local", function() { // Create object, generate JSON, and delete var obj = yield createDataObject(type, { version: 10 }); - var jsonData = yield obj.toJSON(); + var jsonData = obj.toJSON(); var key = jsonData.key = obj.key; jsonData.version = 10; let json = { @@ -576,7 +557,6 @@ describe("Zotero.Sync.Data.Local", function() { obj = objectsClass.getByLibraryAndKey(libraryID, key); assert.ok(obj); - yield obj.loadItemData(); assert.equal(obj.getField('title'), jsonData.title); }) @@ -594,7 +574,7 @@ describe("Zotero.Sync.Data.Local", function() { obj.setNote(""); obj.version = 10; yield obj.saveTx(); - var jsonData = yield obj.toJSON(); + var jsonData = obj.toJSON(); var key = jsonData.key = obj.key; let json = { key: obj.key, @@ -626,7 +606,6 @@ describe("Zotero.Sync.Data.Local", function() { obj = objectsClass.getByLibraryAndKey(libraryID, key); assert.ok(obj); - yield obj.loadNote(); assert.equal(obj.getNote(), noteText2); }) }) diff --git a/test/tests/translateTest.js b/test/tests/translateTest.js index 195413593..c2d51f223 100644 --- a/test/tests/translateTest.js +++ b/test/tests/translateTest.js @@ -175,7 +175,7 @@ describe("Zotero.Translate", function() { let newItems = yield saveItemsThroughTranslator("import", saveItems); let savedItems = {}; for (let i=0; i