Load reverse relations mappings at startup
This allows Zotero.Relations.getByPredicateAndObject()/getByObject() and Zotero.Item::getLinkedItem()/Zotero.Collection::getLinkedCollection() to be synchronous, which is necessary for word processor integration.
This commit is contained in:
parent
5d3e7f555c
commit
da45df06cc
12 changed files with 187 additions and 92 deletions
|
@ -1517,7 +1517,7 @@ Zotero.CollectionTreeView.prototype.canDropCheckAsync = Zotero.Promise.coroutine
|
|||
|
||||
// Cross-library drag
|
||||
if (treeRow.ref.libraryID != item.libraryID) {
|
||||
let linkedItem = yield item.getLinkedItem(treeRow.ref.libraryID, true);
|
||||
let linkedItem = item.getLinkedItem(treeRow.ref.libraryID, true);
|
||||
if (linkedItem && !linkedItem.deleted) {
|
||||
// For drag to root, skip if linked item exists
|
||||
if (treeRow.isLibrary(true)) {
|
||||
|
@ -1623,7 +1623,7 @@ Zotero.CollectionTreeView.prototype.drop = Zotero.Promise.coroutine(function* (r
|
|||
var targetLibraryType = Zotero.Libraries.get(targetLibraryID).libraryType;
|
||||
|
||||
// Check if there's already a copy of this item in the library
|
||||
var linkedItem = yield item.getLinkedItem(targetLibraryID, true);
|
||||
var linkedItem = item.getLinkedItem(targetLibraryID, true);
|
||||
if (linkedItem) {
|
||||
// If linked item is in the trash, undelete it and remove it from collections
|
||||
// (since it shouldn't be restored to previous collections)
|
||||
|
|
|
@ -446,9 +446,9 @@ Zotero.DataObject.prototype.setRelations = function (newRelations) {
|
|||
* calling this directly.
|
||||
*
|
||||
* @param {Integer} [libraryID]
|
||||
* @return {Promise<Zotero.DataObject>|false} Linked object, or false if not found
|
||||
* @return {Zotero.DataObject|false} Linked object, or false if not found
|
||||
*/
|
||||
Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function* (libraryID, bidirectional) {
|
||||
Zotero.DataObject.prototype._getLinkedObject = function (libraryID, bidirectional) {
|
||||
if (!libraryID) {
|
||||
throw new Error("libraryID not provided");
|
||||
}
|
||||
|
@ -466,7 +466,7 @@ Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function
|
|||
for (let i = 0; i < uris.length; i++) {
|
||||
let uri = uris[i];
|
||||
if (uri.startsWith(libraryObjectPrefix)) {
|
||||
let obj = yield Zotero.URI['getURI' + this._ObjectType](uri);
|
||||
let obj = Zotero.URI['getURI' + this._ObjectType](uri);
|
||||
if (!obj) {
|
||||
Zotero.debug("Referenced linked " + this._objectType + " '" + uri + "' not found "
|
||||
+ "in Zotero." + this._ObjectType + "::getLinked" + this._ObjectType + "()", 2);
|
||||
|
@ -479,7 +479,7 @@ Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function
|
|||
// Then try relations with this as an object
|
||||
if (bidirectional) {
|
||||
var thisURI = Zotero.URI['get' + this._ObjectType + 'URI'](this);
|
||||
var objects = yield Zotero.Relations.getByPredicateAndObject(
|
||||
var objects = Zotero.Relations.getByPredicateAndObject(
|
||||
this._objectType, predicate, thisURI
|
||||
);
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
|
@ -496,7 +496,7 @@ Zotero.DataObject.prototype._getLinkedObject = Zotero.Promise.coroutine(function
|
|||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -830,14 +830,14 @@ Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options)
|
|||
}
|
||||
|
||||
// Create transaction
|
||||
let result
|
||||
if (env.options.tx) {
|
||||
let result = yield Zotero.DB.executeTransaction(function* () {
|
||||
result = yield Zotero.DB.executeTransaction(function* () {
|
||||
Zotero.DataObject.prototype._saveData.call(this, env);
|
||||
yield this._saveData(env);
|
||||
yield Zotero.DataObject.prototype._finalizeSave.call(this, env);
|
||||
return this._finalizeSave(env);
|
||||
}.bind(this), env.transactionOptions);
|
||||
return result;
|
||||
}
|
||||
// Use existing transaction
|
||||
else {
|
||||
|
@ -845,8 +845,10 @@ Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options)
|
|||
Zotero.DataObject.prototype._saveData.call(this, env);
|
||||
yield this._saveData(env);
|
||||
yield Zotero.DataObject.prototype._finalizeSave.call(this, env);
|
||||
return this._finalizeSave(env);
|
||||
result = this._finalizeSave(env);
|
||||
}
|
||||
this._postSave(env);
|
||||
return result;
|
||||
}
|
||||
catch(e) {
|
||||
return this._recoverFromSaveError(env, e)
|
||||
|
@ -906,6 +908,9 @@ Zotero.DataObject.prototype._initSave = Zotero.Promise.coroutine(function* (env)
|
|||
Zotero.DB.addCurrentCallback("rollback", func);
|
||||
}
|
||||
|
||||
env.relationsToRegister = [];
|
||||
env.relationsToUnregister = [];
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
|
@ -967,6 +972,7 @@ Zotero.DataObject.prototype._finalizeSave = Zotero.Promise.coroutine(function* (
|
|||
// Convert predicates to ids
|
||||
for (let i = 0; i < toAdd.length; i++) {
|
||||
toAdd[i][0] = yield Zotero.RelationPredicates.add(toAdd[i][0]);
|
||||
env.relationsToRegister.push([toAdd[i][0], toAdd[i][1]]);
|
||||
}
|
||||
yield Zotero.DB.queryAsync(
|
||||
sql + toAdd.map(x => "(?, ?, ?)").join(", "),
|
||||
|
@ -987,13 +993,15 @@ Zotero.DataObject.prototype._finalizeSave = Zotero.Promise.coroutine(function* (
|
|||
toRemove[i][1]
|
||||
]
|
||||
);
|
||||
env.relationsToUnregister.push([toRemove[i][0], toRemove[i][1]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (env.isNew) {
|
||||
if (!env.skipCache) {
|
||||
// Register this object's identifiers in Zotero.DataObjects
|
||||
// Register this object's identifiers in Zotero.DataObjects. This has to happen here so
|
||||
// that the object exists for the reload() in objects' finalizeSave methods.
|
||||
this.ObjectsClass.registerObject(this);
|
||||
}
|
||||
// If object isn't being reloaded, disable it, since its data may be out of date
|
||||
|
@ -1006,6 +1014,23 @@ Zotero.DataObject.prototype._finalizeSave = Zotero.Promise.coroutine(function* (
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Actions to perform after DB transaction
|
||||
*/
|
||||
Zotero.DataObject.prototype._postSave = function (env) {
|
||||
for (let i = 0; i < env.relationsToRegister.length; i++) {
|
||||
let rel = env.relationsToRegister[i];
|
||||
Zotero.debug(rel);
|
||||
Zotero.Relations.register(this._objectType, this.id, rel[0], rel[1]);
|
||||
}
|
||||
for (let i = 0; i < env.relationsToUnregister.length; i++) {
|
||||
let rel = env.relationsToUnregister[i];
|
||||
Zotero.Relations.unregister(this._objectType, this.id, rel[0], rel[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Zotero.DataObject.prototype._recoverFromSaveError = Zotero.Promise.coroutine(function* (env) {
|
||||
yield this.reload(null, true);
|
||||
this._clearChanged();
|
||||
|
|
|
@ -500,7 +500,7 @@ Zotero.DataObjects.prototype._loadRelations = Zotero.Promise.coroutine(function*
|
|||
let objectURI = getURI(this);
|
||||
|
||||
// Related items are bidirectional, so include any pointing to this object
|
||||
let objects = yield Zotero.Relations.getByPredicateAndObject(
|
||||
let objects = Zotero.Relations.getByPredicateAndObject(
|
||||
Zotero.Relations.relatedItemPredicate, objectURI
|
||||
);
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
|
@ -508,7 +508,7 @@ Zotero.DataObjects.prototype._loadRelations = Zotero.Promise.coroutine(function*
|
|||
}
|
||||
|
||||
// Also include any owl:sameAs relations pointing to this object
|
||||
objects = yield Zotero.Relations.getByPredicateAndObject(
|
||||
objects = Zotero.Relations.getByPredicateAndObject(
|
||||
Zotero.Relations.linkedObjectPredicate, objectURI
|
||||
);
|
||||
for (let i = 0; i < objects.length; i++) {
|
||||
|
|
|
@ -1492,7 +1492,7 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
|
|||
// If undeleting, remove any merge-tracking relations
|
||||
let predicate = Zotero.Relations.replacedItemPredicate;
|
||||
let thisURI = Zotero.URI.getItemURI(this);
|
||||
let mergeItems = yield Zotero.Relations.getByPredicateAndObject(
|
||||
let mergeItems = Zotero.Relations.getByPredicateAndObject(
|
||||
'item', predicate, thisURI
|
||||
);
|
||||
for (let mergeItem of mergeItems) {
|
||||
|
|
|
@ -36,6 +36,82 @@ Zotero.Relations = new function () {
|
|||
};
|
||||
|
||||
var _types = ['collection', 'item'];
|
||||
var _subjectsByPredicateIDAndObject = {};
|
||||
var _subjectPredicatesByObject = {};
|
||||
|
||||
|
||||
this.init = Zotero.Promise.coroutine(function* () {
|
||||
// Load relations for different types
|
||||
for (let type of _types) {
|
||||
let t = new Date();
|
||||
Zotero.debug(`Loading ${type} relations`);
|
||||
|
||||
let sql = "SELECT * FROM " + type + "Relations "
|
||||
+ "JOIN relationPredicates USING (predicateID)";
|
||||
yield Zotero.DB.queryAsync(
|
||||
sql,
|
||||
false,
|
||||
{
|
||||
onRow: function (row) {
|
||||
this.register(
|
||||
type,
|
||||
row.getResultByIndex(0),
|
||||
row.getResultByIndex(1),
|
||||
row.getResultByIndex(2)
|
||||
);
|
||||
}.bind(this)
|
||||
}
|
||||
);
|
||||
|
||||
Zotero.debug(`Loaded ${type} relations in ${new Date() - t} ms`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.register = function (objectType, subjectID, predicate, object) {
|
||||
var predicateID = Zotero.RelationPredicates.getID(predicate);
|
||||
|
||||
if (!_subjectsByPredicateIDAndObject[objectType]) {
|
||||
_subjectsByPredicateIDAndObject[objectType] = {};
|
||||
}
|
||||
if (!_subjectPredicatesByObject[objectType]) {
|
||||
_subjectPredicatesByObject[objectType] = {};
|
||||
}
|
||||
|
||||
// _subjectsByPredicateIDAndObject
|
||||
var o = _subjectsByPredicateIDAndObject[objectType];
|
||||
if (!o[predicateID]) {
|
||||
o[predicateID] = {};
|
||||
}
|
||||
if (!o[predicateID][object]) {
|
||||
o[predicateID][object] = new Set();
|
||||
}
|
||||
o[predicateID][object].add(subjectID);
|
||||
|
||||
// _subjectPredicatesByObject
|
||||
o = _subjectPredicatesByObject[objectType];
|
||||
if (!o[object]) {
|
||||
o[object] = {};
|
||||
}
|
||||
if (!o[object][predicateID]) {
|
||||
o[object][predicateID] = new Set();
|
||||
}
|
||||
o[object][predicateID].add(subjectID);
|
||||
};
|
||||
|
||||
|
||||
this.unregister = function (objectType, subjectID, predicate, object) {
|
||||
var predicateID = Zotero.RelationPredicates.getID(predicate);
|
||||
|
||||
if (!_subjectsByPredicateIDAndObject[objectType]
|
||||
|| !_subjectsByPredicateIDAndObject[objectType][predicateID]
|
||||
|| !_subjectsByPredicateIDAndObject[objectType][predicateID][object]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_subjectsByPredicateIDAndObject[objectType][predicateID][object].delete(subjectID)
|
||||
_subjectPredicatesByObject[objectType][object][predicateID].delete(subjectID)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -44,18 +120,22 @@ Zotero.Relations = new function () {
|
|||
* @param {String} objectType - Type of relation to search for (e.g., 'item')
|
||||
* @param {String} predicate
|
||||
* @param {String} object
|
||||
* @return {Promise<Zotero.DataObject[]>}
|
||||
* @return {Zotero.DataObject[]}
|
||||
*/
|
||||
this.getByPredicateAndObject = Zotero.Promise.coroutine(function* (objectType, predicate, object) {
|
||||
this.getByPredicateAndObject = function (objectType, predicate, object) {
|
||||
var objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
|
||||
if (predicate) {
|
||||
predicate = this._getPrefixAndValue(predicate).join(':');
|
||||
}
|
||||
var sql = "SELECT " + objectsClass.idColumn + " FROM " + objectType + "Relations "
|
||||
+ "JOIN relationPredicates USING (predicateID) WHERE predicate=? AND object=?";
|
||||
var ids = yield Zotero.DB.columnQueryAsync(sql, [predicate, object]);
|
||||
return yield objectsClass.getAsync(ids, { noCache: true });
|
||||
});
|
||||
|
||||
var predicateID = Zotero.RelationPredicates.getID(predicate);
|
||||
|
||||
var o = _subjectsByPredicateIDAndObject[objectType];
|
||||
if (!o || !o[predicateID] || !o[predicateID][object]) {
|
||||
return [];
|
||||
}
|
||||
return objectsClass.get(Array.from(o[predicateID][object].values()));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -63,24 +143,25 @@ Zotero.Relations = new function () {
|
|||
*
|
||||
* @param {String} objectType - Type of relation to search for (e.g., 'item')
|
||||
* @param {String} object
|
||||
* @return {Promise<Object[]>} - Promise for an object with a Zotero.DataObject as 'subject'
|
||||
* and a predicate string as 'predicate'
|
||||
* @return {Object[]} - An array of objects with a Zotero.DataObject as 'subject'
|
||||
* and a predicate string as 'predicate'
|
||||
*/
|
||||
this.getByObject = Zotero.Promise.coroutine(function* (objectType, object) {
|
||||
this.getByObject = function (objectType, object) {
|
||||
var objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
|
||||
var sql = "SELECT " + objectsClass.idColumn + " AS id, predicate "
|
||||
+ "FROM " + objectType + "Relations JOIN relationPredicates USING (predicateID) "
|
||||
+ "WHERE object=?";
|
||||
var predicateIDs = [];
|
||||
var o = _subjectPredicatesByObject[objectType][object];
|
||||
if (!o) {
|
||||
return [];
|
||||
}
|
||||
var toReturn = [];
|
||||
var rows = yield Zotero.DB.queryAsync(sql, object);
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
toReturn.push({
|
||||
subject: yield objectsClass.getAsync(rows[i].id, { noCache: true }),
|
||||
predicate: rows[i].predicate
|
||||
});
|
||||
for (let predicateID in o) {
|
||||
o[predicateID].forEach(subjectID => toReturn.push({
|
||||
subject: objectsClass.get(subjectID),
|
||||
predicate: Zotero.RelationPredicates.getName(predicateID)
|
||||
}));
|
||||
}
|
||||
return toReturn;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
this.updateUser = Zotero.Promise.coroutine(function* (toUserID) {
|
||||
|
@ -93,14 +174,32 @@ Zotero.Relations = new function () {
|
|||
}
|
||||
Zotero.DB.requireTransaction();
|
||||
for (let type of _types) {
|
||||
var sql = "UPDATE " + type + "Relations SET "
|
||||
+ "object=REPLACE(object, 'zotero.org/users/" + fromUserID + "', "
|
||||
+ "'zotero.org/users/" + toUserID + "')";
|
||||
let sql = `SELECT DISTINCT object FROM ${type}Relations WHERE object LIKE ?`;
|
||||
let objects = yield Zotero.DB.columnQueryAsync(
|
||||
sql, 'http://zotero.org/users/' + fromUserID + '/%'
|
||||
);
|
||||
Zotero.DB.addCurrentCallback("commit", function () {
|
||||
for (let object of objects) {
|
||||
let subPrefs = this.getByObject(type, object);
|
||||
let newObject = object.replace(
|
||||
new RegExp("^http://zotero.org/users/" + fromUserID + "/(.*)"),
|
||||
"http://zotero.org/users/" + toUserID + "/$1"
|
||||
);
|
||||
for (let subPref of subPrefs) {
|
||||
this.unregister(type, subPref.subject.id, subPref.predicate, object);
|
||||
this.register(type, subPref.subject.id, subPref.predicate, newObject);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
sql = "UPDATE " + type + "Relations SET "
|
||||
+ "object=REPLACE(object, 'zotero.org/users/" + fromUserID + "/', "
|
||||
+ "'zotero.org/users/" + toUserID + "/')";
|
||||
yield Zotero.DB.queryAsync(sql);
|
||||
|
||||
var objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(type);
|
||||
var objects = objectsClass.getLoaded();
|
||||
for (let object of objects) {
|
||||
let loadedObjects = objectsClass.getLoaded();
|
||||
for (let object of loadedObjects) {
|
||||
yield object.reload(['relations'], true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3139,8 +3139,6 @@ Zotero.Integration.URIMap.prototype.getZoteroItemForURIs = function(uris) {
|
|||
|
||||
// Next try getting URI directly
|
||||
try {
|
||||
// TEMP
|
||||
throw new Error("getURIItem() is now async");
|
||||
zoteroItem = Zotero.URI.getURIItem(uri);
|
||||
if(zoteroItem) {
|
||||
// Ignore items in the trash
|
||||
|
@ -3152,42 +3150,14 @@ Zotero.Integration.URIMap.prototype.getZoteroItemForURIs = function(uris) {
|
|||
}
|
||||
} catch(e) {}
|
||||
|
||||
// Try merged item mappings
|
||||
var seen = [];
|
||||
|
||||
// Follow merged item relations until we find an item or hit a dead end
|
||||
while (!zoteroItem) {
|
||||
var relations = Zotero.Relations.getByURIs(uri, Zotero.Relations.replacedItemPredicate);
|
||||
// No merged items found
|
||||
if(!relations.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
uri = relations[0].object;
|
||||
|
||||
// Keep track of mapped URIs in case there's a circular relation
|
||||
if(seen.indexOf(uri) != -1) {
|
||||
var msg = "Circular relation for '" + uri + "' in merged item mapping resolution";
|
||||
Zotero.debug(msg, 2);
|
||||
Components.utils.reportError(msg);
|
||||
break;
|
||||
}
|
||||
seen.push(uri);
|
||||
|
||||
try {
|
||||
// TEMP
|
||||
throw new Error("getURIItem() is now async");
|
||||
zoteroItem = Zotero.URI.getURIItem(uri);
|
||||
if(zoteroItem) {
|
||||
// Ignore items in the trash
|
||||
if(zoteroItem.deleted) {
|
||||
zoteroItem = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
// Try merged item mapping
|
||||
var replacer = Zotero.Relations.getByPredicateAndObject(
|
||||
'item', Zotero.Relations.replacedItemPredicate, uri
|
||||
);
|
||||
if (replacer.length && !replacer[0].deleted) {
|
||||
zoteroItem = replacer;
|
||||
}
|
||||
|
||||
if(zoteroItem) break;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ Zotero.Report.HTML = new function () {
|
|||
}
|
||||
for (let i=0; i<rels.length; i++) {
|
||||
let rel = rels[i];
|
||||
let relItem = yield Zotero.URI.getURIItem(rel);
|
||||
let relItem = Zotero.URI.getURIItem(rel);
|
||||
if (relItem) {
|
||||
content += '\t\t\t\t\t<li id="item_' + relItem.key + '">';
|
||||
content += escapeXML(relItem.getDisplayTitle());
|
||||
|
|
|
@ -191,13 +191,13 @@ Zotero.URI = new function () {
|
|||
* Convert an item URI into an item
|
||||
*
|
||||
* @param {String} itemURI
|
||||
* @return {Promise<Zotero.Item|FALSE>}
|
||||
* @return {Zotero.Item|false}
|
||||
*/
|
||||
this.getURIItem = Zotero.Promise.method(function (itemURI) {
|
||||
this.getURIItem = function (itemURI) {
|
||||
var obj = this._getURIObject(itemURI, 'item');
|
||||
if (!obj) return false;
|
||||
return Zotero.Items.getByLibraryAndKeyAsync(obj.libraryID, obj.key);
|
||||
});
|
||||
return Zotero.Items.getByLibraryAndKey(obj.libraryID, obj.key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -225,13 +225,13 @@ Zotero.URI = new function () {
|
|||
*
|
||||
* @param {String} collectionURI
|
||||
* @param {Zotero.Collection|FALSE}
|
||||
* @return {Promise<Zotero.Collection|FALSE>}
|
||||
* @return {Zotero.Collection|false}
|
||||
*/
|
||||
this.getURICollection = Zotero.Promise.method(function (collectionURI) {
|
||||
this.getURICollection = function (collectionURI) {
|
||||
var obj = this._getURIObject(collectionURI, 'collection');
|
||||
if (!obj) return false;
|
||||
return Zotero.Collections.getByLibraryAndKeyAsync(obj.libraryID, obj.key);
|
||||
});
|
||||
return Zotero.Collections.getByLibraryAndKey(obj.libraryID, obj.key);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -626,6 +626,7 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
|
|||
yield Zotero.Searches.init();
|
||||
yield Zotero.Creators.init();
|
||||
yield Zotero.Groups.init();
|
||||
yield Zotero.Relations.init()
|
||||
|
||||
let libraryIDs = Zotero.Libraries.getAll().map(x => x.libraryID);
|
||||
for (let libraryID of libraryIDs) {
|
||||
|
|
|
@ -424,7 +424,7 @@ describe("Zotero.CollectionTreeView", function() {
|
|||
assert.equal(treeRow.ref.libraryID, group.libraryID);
|
||||
assert.equal(treeRow.ref.id, ids[0]);
|
||||
// New item should link back to original
|
||||
var linked = yield item.getLinkedItem(group.libraryID);
|
||||
var linked = item.getLinkedItem(group.libraryID);
|
||||
assert.equal(linked.id, treeRow.ref.id);
|
||||
|
||||
// Check attachment
|
||||
|
@ -434,7 +434,7 @@ describe("Zotero.CollectionTreeView", function() {
|
|||
treeRow = itemsView.getRow(1);
|
||||
assert.equal(treeRow.ref.id, ids[1]);
|
||||
// New attachment should link back to original
|
||||
linked = yield attachment.getLinkedItem(group.libraryID);
|
||||
linked = attachment.getLinkedItem(group.libraryID);
|
||||
assert.equal(linked.id, treeRow.ref.id);
|
||||
|
||||
return group.eraseTx();
|
||||
|
@ -466,7 +466,7 @@ describe("Zotero.CollectionTreeView", function() {
|
|||
var item = yield createDataObject('item', false, { skipSelect: true });
|
||||
yield drop('item', 'L' + group.libraryID, [item.id]);
|
||||
|
||||
var droppedItem = yield item.getLinkedItem(group.libraryID);
|
||||
var droppedItem = item.getLinkedItem(group.libraryID);
|
||||
droppedItem.setCollections([collection.id]);
|
||||
droppedItem.deleted = true;
|
||||
yield droppedItem.saveTx();
|
||||
|
|
|
@ -411,7 +411,7 @@ describe("Zotero.DataObject", function() {
|
|||
var item2URI = Zotero.URI.getItemURI(item2);
|
||||
|
||||
yield item2.addLinkedItem(item1);
|
||||
var linkedItem = yield item1.getLinkedItem(item2.libraryID);
|
||||
var linkedItem = item1.getLinkedItem(item2.libraryID);
|
||||
assert.equal(linkedItem.id, item2.id);
|
||||
})
|
||||
|
||||
|
@ -422,7 +422,7 @@ describe("Zotero.DataObject", function() {
|
|||
var item2 = yield createDataObject('item', { libraryID: group.libraryID });
|
||||
|
||||
yield item2.addLinkedItem(item1);
|
||||
var linkedItem = yield item2.getLinkedItem(item1.libraryID);
|
||||
var linkedItem = item2.getLinkedItem(item1.libraryID);
|
||||
assert.isFalse(linkedItem);
|
||||
})
|
||||
|
||||
|
@ -433,7 +433,7 @@ describe("Zotero.DataObject", function() {
|
|||
var item2 = yield createDataObject('item', { libraryID: group.libraryID });
|
||||
|
||||
yield item2.addLinkedItem(item1);
|
||||
var linkedItem = yield item2.getLinkedItem(item1.libraryID, true);
|
||||
var linkedItem = item2.getLinkedItem(item1.libraryID, true);
|
||||
assert.equal(linkedItem.id, item1.id);
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@ describe("Zotero.Relations", function () {
|
|||
]
|
||||
})
|
||||
yield item.saveTx();
|
||||
var objects = yield Zotero.Relations.getByPredicateAndObject(
|
||||
var objects = Zotero.Relations.getByPredicateAndObject(
|
||||
'item', 'owl:sameAs', 'http://zotero.org/groups/1/items/SRRMGSRM'
|
||||
);
|
||||
assert.lengthOf(objects, 1);
|
||||
|
|
Loading…
Reference in a new issue