Merge pull request #575 from aurimasv/async_db-av
Async DB tweaks (attempt 2)
This commit is contained in:
commit
e4451d9002
7 changed files with 126 additions and 79 deletions
|
@ -24,12 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Zotero.Collection = function() {
|
Zotero.Collection = function() {
|
||||||
let dataTypes = [
|
Zotero.Collection._super.apply(this);
|
||||||
'primaryData',
|
|
||||||
'childCollections',
|
|
||||||
'childItems'
|
|
||||||
];
|
|
||||||
Zotero.DataObject.apply(this, ['collection', dataTypes]);
|
|
||||||
|
|
||||||
this._name = null;
|
this._name = null;
|
||||||
this._parentID = null;
|
this._parentID = null;
|
||||||
|
@ -42,9 +37,17 @@ Zotero.Collection = function() {
|
||||||
this._childItems = [];
|
this._childItems = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.Collection.prototype = Object.create(Zotero.DataObject.prototype);
|
Zotero.Collection._super = Zotero.DataObject;
|
||||||
|
Zotero.Collection.prototype = Object.create(Zotero.Collection._super.prototype);
|
||||||
Zotero.Collection.constructor = Zotero.Collection;
|
Zotero.Collection.constructor = Zotero.Collection;
|
||||||
|
|
||||||
|
Zotero.Collection.prototype._objectType = 'collection';
|
||||||
|
Zotero.Collection.prototype._dataTypes = Zotero.Collection._super.prototype._dataTypes.concat([
|
||||||
|
'primaryData',
|
||||||
|
'childCollections',
|
||||||
|
'childItems'
|
||||||
|
]);
|
||||||
|
|
||||||
Zotero.Collection.prototype.__defineGetter__('id', function () { return this._get('id'); });
|
Zotero.Collection.prototype.__defineGetter__('id', function () { return this._get('id'); });
|
||||||
Zotero.Collection.prototype.__defineSetter__('id', function (val) { this._set('id', val); });
|
Zotero.Collection.prototype.__defineSetter__('id', function (val) { this._set('id', val); });
|
||||||
Zotero.Collection.prototype.__defineGetter__('libraryID', function () { return this._get('libraryID'); });
|
Zotero.Collection.prototype.__defineGetter__('libraryID', function () { return this._get('libraryID'); });
|
||||||
|
|
|
@ -24,21 +24,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {String} objectType
|
|
||||||
* @param {String[]} dataTypes A set of data types that can be loaded for this data object
|
|
||||||
*
|
|
||||||
* @property {String} (readOnly) objectType
|
* @property {String} (readOnly) objectType
|
||||||
* @property {String} (readOnly) libraryKey
|
* @property {String} (readOnly) libraryKey
|
||||||
* @property {String|null} parentKey Null if no parent
|
* @property {String|null} parentKey Null if no parent
|
||||||
* @property {Integer|false|undefined} parentID False if no parent. Undefined if not applicable (e.g. search objects)
|
* @property {Integer|false|undefined} parentID False if no parent. Undefined if not applicable (e.g. search objects)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Zotero.DataObject = function (objectType, dataTypes) {
|
Zotero.DataObject = function () {
|
||||||
this._objectType = objectType;
|
let objectType = this._objectType;
|
||||||
this._ObjectType = objectType[0].toUpperCase() + objectType.substr(1);
|
this._ObjectType = objectType[0].toUpperCase() + objectType.substr(1);
|
||||||
this._objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
this._objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
||||||
this._dataTypes = dataTypes;
|
|
||||||
|
|
||||||
this._id = null;
|
this._id = null;
|
||||||
this._libraryID = null;
|
this._libraryID = null;
|
||||||
|
@ -57,27 +52,26 @@ Zotero.DataObject = function (objectType, dataTypes) {
|
||||||
this._clearChanged();
|
this._clearChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject, 'objectType', {
|
Zotero.DataObject.prototype._objectType = 'dataObject';
|
||||||
|
Zotero.DataObject.prototype._dataTypes = [];
|
||||||
|
|
||||||
|
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject.prototype, 'objectType', {
|
||||||
get: function() this._objectType
|
get: function() this._objectType
|
||||||
});
|
});
|
||||||
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject, 'libraryKey', {
|
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject.prototype, 'libraryKey', {
|
||||||
get: function() this._libraryID + "/" + this._key
|
get: function() this._libraryID + "/" + this._key
|
||||||
});
|
});
|
||||||
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject, 'parentKey', {
|
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject.prototype, 'parentKey', {
|
||||||
get: function() this._parentKey,
|
get: function() this._parentKey,
|
||||||
set: function(v) this._setParentKey(v)
|
set: function(v) this._setParentKey(v)
|
||||||
});
|
});
|
||||||
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject, 'parentID', {
|
Zotero.Utilities.Internal.defineProperty(Zotero.DataObject.prototype, 'parentID', {
|
||||||
get: function() this._getParentID(),
|
get: function() this._getParentID(),
|
||||||
set: function(v) this._setParentID(v)
|
set: function(v) this._setParentID(v)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Zotero.DataObject.prototype._get = function (field) {
|
Zotero.DataObject.prototype._get = function (field) {
|
||||||
if (this._objectType == 'item') {
|
|
||||||
throw new Error("_get is not valid for items");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this['_' + field] !== null) {
|
if (this['_' + field] !== null) {
|
||||||
return this['_' + field];
|
return this['_' + field];
|
||||||
}
|
}
|
||||||
|
@ -166,11 +160,6 @@ Zotero.DataObject.prototype._setParentID = function (id) {
|
||||||
* @return {Boolean} True if changed, false if stayed the same
|
* @return {Boolean} True if changed, false if stayed the same
|
||||||
*/
|
*/
|
||||||
Zotero.DataObject.prototype._setParentKey = function(key) {
|
Zotero.DataObject.prototype._setParentKey = function(key) {
|
||||||
if (this._objectType == 'item') {
|
|
||||||
if (!this.isNote() && !this.isAttachment()) {
|
|
||||||
throw new Error("_setParentKey() can only be called on items of type 'note' or 'attachment'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
key = Zotero.DataObjectUtilities.checkKey(key);
|
key = Zotero.DataObjectUtilities.checkKey(key);
|
||||||
|
|
||||||
if (this._parentKey == key) {
|
if (this._parentKey == key) {
|
||||||
|
|
|
@ -32,18 +32,7 @@ Zotero.Item = function(itemTypeOrID) {
|
||||||
throw ("Zotero.Item constructor only takes one parameter");
|
throw ("Zotero.Item constructor only takes one parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataTypes = [
|
Zotero.Item._super.apply(this);
|
||||||
'primaryData',
|
|
||||||
'itemData',
|
|
||||||
'note',
|
|
||||||
'creators',
|
|
||||||
'childItems',
|
|
||||||
'relatedItems', // TODO: remove
|
|
||||||
'tags',
|
|
||||||
'collections',
|
|
||||||
'relations'
|
|
||||||
];
|
|
||||||
Zotero.DataObject.apply(this, ['item', dataTypes]);
|
|
||||||
|
|
||||||
this._disabled = false;
|
this._disabled = false;
|
||||||
|
|
||||||
|
@ -100,10 +89,23 @@ Zotero.Item = function(itemTypeOrID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.Item.prototype = Object.create(Zotero.DataObject.prototype);
|
Zotero.Item._super = Zotero.DataObject;
|
||||||
|
Zotero.Item.prototype = Object.create(Zotero.Item._super.prototype);
|
||||||
Zotero.Item.constructor = Zotero.Item;
|
Zotero.Item.constructor = Zotero.Item;
|
||||||
|
|
||||||
Zotero.Item.prototype.__defineGetter__('objectType', function () { return 'item'; });
|
Zotero.Item.prototype._objectType = 'item';
|
||||||
|
Zotero.Item.prototype._dataTypes = Zotero.Item._super.prototype._dataTypes.concat([
|
||||||
|
'primaryData',
|
||||||
|
'itemData',
|
||||||
|
'note',
|
||||||
|
'creators',
|
||||||
|
'childItems',
|
||||||
|
'relatedItems', // TODO: remove
|
||||||
|
'tags',
|
||||||
|
'collections',
|
||||||
|
'relations'
|
||||||
|
]);
|
||||||
|
|
||||||
Zotero.Item.prototype.__defineGetter__('id', function () this._id);
|
Zotero.Item.prototype.__defineGetter__('id', function () this._id);
|
||||||
Zotero.Item.prototype.__defineGetter__('itemID', function () {
|
Zotero.Item.prototype.__defineGetter__('itemID', function () {
|
||||||
Zotero.debug("Item.itemID is deprecated -- use Item.id");
|
Zotero.debug("Item.itemID is deprecated -- use Item.id");
|
||||||
|
@ -149,6 +151,17 @@ Zotero.Item.prototype.isPrimaryField = function (fieldName) {
|
||||||
return Zotero.Items.isPrimaryField(fieldName);
|
return Zotero.Items.isPrimaryField(fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Zotero.Item.prototype._get = function (fieldName) {
|
||||||
|
throw new Error("_get is not valid for items");
|
||||||
|
}
|
||||||
|
|
||||||
|
Zotero.Item.prototype._setParentKey = function() {
|
||||||
|
if (!this.isNote() && !this.isAttachment()) {
|
||||||
|
throw new Error("_setParentKey() can only be called on items of type 'note' or 'attachment'");
|
||||||
|
}
|
||||||
|
|
||||||
|
Zotero.Item._super.prototype._setParentKey.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
|
@ -24,7 +24,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Zotero.Libraries = new function () {
|
Zotero.Libraries = new function () {
|
||||||
var _libraryData = {};
|
let _libraryData = {},
|
||||||
|
_userLibraryID,
|
||||||
|
_libraryDataLoaded = false;
|
||||||
|
|
||||||
|
Zotero.Utilities.Internal.defineProperty(this, 'userLibraryID', {
|
||||||
|
get: function() {
|
||||||
|
if (!_libraryDataLoaded) {
|
||||||
|
throw new Error("Library data not yet loaded");
|
||||||
|
}
|
||||||
|
return _userLibraryID;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.init = Zotero.Promise.coroutine(function* () {
|
this.init = Zotero.Promise.coroutine(function* () {
|
||||||
// Library data
|
// Library data
|
||||||
|
@ -36,25 +47,28 @@ Zotero.Libraries = new function () {
|
||||||
type: row.libraryType,
|
type: row.libraryType,
|
||||||
version: row.version
|
version: row.version
|
||||||
};
|
};
|
||||||
|
if (row.libraryType == 'user') {
|
||||||
|
_userLibraryID = row.libraryID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_libraryDataLoaded = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.exists = function (libraryID) {
|
function _getLibraryDataFromDB (libraryID) {
|
||||||
// Until there are other library types, this can just check groups,
|
var sql = "SELECT * FROM libraries WHERE libraryID=?";
|
||||||
// which already preload ids at startup
|
return Zotero.DB.queryAsync(sql, [libraryID])
|
||||||
try {
|
.then(function(rows) {
|
||||||
return !!Zotero.Groups.getGroupIDFromLibraryID(libraryID);
|
return rows[0];
|
||||||
}
|
});
|
||||||
catch (e) {
|
|
||||||
if (e.getMessage().indexOf("does not exist") != -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.add = function (libraryID, type) {
|
this.exists = function (libraryID) {
|
||||||
|
return _libraryData[libraryID] !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.add = Zotero.Promise.coroutine(function* (libraryID, type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'group':
|
case 'group':
|
||||||
break;
|
break;
|
||||||
|
@ -64,9 +78,16 @@ Zotero.Libraries = new function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
var sql = "INSERT INTO libraries (libraryID, libraryType) VALUES (?, ?)";
|
var sql = "INSERT INTO libraries (libraryID, libraryType) VALUES (?, ?)";
|
||||||
Zotero.DB.query(sql, [libraryID, type]);
|
yield Zotero.DB.queryAsync(sql, [libraryID, type]);
|
||||||
}
|
// Re-fetch from DB to get auto-filled defaults
|
||||||
|
var newData = yield _getLibraryDataFromDB(libraryID);
|
||||||
|
_libraryData[newData.libraryID] = {
|
||||||
|
type: newData.libraryType,
|
||||||
|
version: newData.version
|
||||||
|
};
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
});
|
||||||
|
|
||||||
this.dbLibraryID = function (libraryID) {
|
this.dbLibraryID = function (libraryID) {
|
||||||
return (libraryID == Zotero.Users.getCurrentLibraryID()) ? 0 : libraryID;
|
return (libraryID == Zotero.Users.getCurrentLibraryID()) ? 0 : libraryID;
|
||||||
|
@ -74,12 +95,10 @@ Zotero.Libraries = new function () {
|
||||||
|
|
||||||
|
|
||||||
this.getName = function (libraryID) {
|
this.getName = function (libraryID) {
|
||||||
if (!libraryID) {
|
|
||||||
return Zotero.getString('pane.collections.library');
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = this.getType(libraryID);
|
var type = this.getType(libraryID);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case 'user':
|
||||||
|
return Zotero.getString('pane.collections.library');
|
||||||
case 'group':
|
case 'group':
|
||||||
var groupID = Zotero.Groups.getGroupIDFromLibraryID(libraryID);
|
var groupID = Zotero.Groups.getGroupIDFromLibraryID(libraryID);
|
||||||
var group = Zotero.Groups.get(groupID);
|
var group = Zotero.Groups.get(groupID);
|
||||||
|
@ -92,10 +111,10 @@ Zotero.Libraries = new function () {
|
||||||
|
|
||||||
|
|
||||||
this.getType = function (libraryID) {
|
this.getType = function (libraryID) {
|
||||||
if (this.dbLibraryID(libraryID) === 0) {
|
if (libraryID === Zotero.Libraries.userLibraryID) {
|
||||||
return 'user';
|
return 'user';
|
||||||
}
|
}
|
||||||
if (!_libraryData[libraryID]) {
|
if (!this.exists(libraryID)) {
|
||||||
throw new Error("Library data not loaded for library " + libraryID);
|
throw new Error("Library data not loaded for library " + libraryID);
|
||||||
}
|
}
|
||||||
return _libraryData[libraryID].type;
|
return _libraryData[libraryID].type;
|
||||||
|
@ -106,7 +125,7 @@ Zotero.Libraries = new function () {
|
||||||
* @return {Integer}
|
* @return {Integer}
|
||||||
*/
|
*/
|
||||||
this.getVersion = function (libraryID) {
|
this.getVersion = function (libraryID) {
|
||||||
if (!_libraryData[libraryID]) {
|
if (!this.exists(libraryID)) {
|
||||||
throw new Error("Library data not loaded for library " + libraryID);
|
throw new Error("Library data not loaded for library " + libraryID);
|
||||||
}
|
}
|
||||||
return _libraryData[libraryID].version;
|
return _libraryData[libraryID].version;
|
||||||
|
@ -122,7 +141,7 @@ Zotero.Libraries = new function () {
|
||||||
version = parseInt(version);
|
version = parseInt(version);
|
||||||
var sql = "UPDATE libraries SET version=? WHERE libraryID=?";
|
var sql = "UPDATE libraries SET version=? WHERE libraryID=?";
|
||||||
yield Zotero.DB.queryAsync(sql, [version, libraryID]);
|
yield Zotero.DB.queryAsync(sql, [version, libraryID]);
|
||||||
_libraryData[libraryID] = version;
|
_libraryData[libraryID].version = version;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Zotero.Search = function() {
|
Zotero.Search = function() {
|
||||||
var dataTypes = [
|
Zotero.Search._super.apply(this);
|
||||||
'primaryData',
|
|
||||||
'conditions'
|
|
||||||
];
|
|
||||||
Zotero.DataObject.apply(this, ['search', dataTypes]);
|
|
||||||
|
|
||||||
this._name = null;
|
this._name = null;
|
||||||
|
|
||||||
|
@ -41,9 +37,16 @@ Zotero.Search = function() {
|
||||||
this._hasPrimaryConditions = false;
|
this._hasPrimaryConditions = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zotero.Search.prototype = Object.create(Zotero.DataObject.prototype);
|
Zotero.Search._super = Zotero.DataObject;
|
||||||
|
Zotero.Search.prototype = Object.create(Zotero.Search._super.prototype);
|
||||||
Zotero.Search.constructor = Zotero.Search;
|
Zotero.Search.constructor = Zotero.Search;
|
||||||
|
|
||||||
|
Zotero.Search.prototype._objectType = 'search';
|
||||||
|
Zotero.Search.prototype._dataTypes = Zotero.Search._super.prototype._dataTypes.concat([
|
||||||
|
'primaryData',
|
||||||
|
'conditions'
|
||||||
|
]);
|
||||||
|
|
||||||
Zotero.Search.prototype.getID = function(){
|
Zotero.Search.prototype.getID = function(){
|
||||||
Zotero.debug('Zotero.Search.getName() is deprecated -- use Search.id');
|
Zotero.debug('Zotero.Search.getName() is deprecated -- use Search.id');
|
||||||
return this._id;
|
return this._id;
|
||||||
|
|
|
@ -411,11 +411,7 @@ Zotero.Utilities = {
|
||||||
// Create a node and use the textContent property to do unescaping where
|
// Create a node and use the textContent property to do unescaping where
|
||||||
// possible, because this approach preserves line endings in the HTML
|
// possible, because this approach preserves line endings in the HTML
|
||||||
if(node === undefined) {
|
if(node === undefined) {
|
||||||
var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
node = Zotero.Utilities.Internal.getDOMDocument().createElement("div");
|
||||||
.createInstance(Components.interfaces.nsIDOMParser);
|
|
||||||
var domDocument = parser.parseFromString("<!DOCTYPE html><html></html>",
|
|
||||||
"text/html");
|
|
||||||
node = domDocument.createElement("div");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node.innerHTML = str;
|
node.innerHTML = str;
|
||||||
|
@ -440,6 +436,20 @@ Zotero.Utilities = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts text inside a DOM object to plain text preserving text formatting
|
||||||
|
* appropriate for given field
|
||||||
|
*
|
||||||
|
* @param {DOMNode} rootNode Node containing all the text that needs to be extracted
|
||||||
|
* @param {String} targetField Zotero item field that the text is meant for
|
||||||
|
*
|
||||||
|
* @return {String} Zotero formatted string
|
||||||
|
*/
|
||||||
|
"dom2text": function(rootNode, targetField) {
|
||||||
|
// TODO: actually do this
|
||||||
|
return Zotero.Utilities.trimInternal(rootNode.textContent);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap URLs and DOIs in <a href=""> links in plain text
|
* Wrap URLs and DOIs in <a href=""> links in plain text
|
||||||
*
|
*
|
||||||
|
|
|
@ -345,6 +345,16 @@ Zotero.Utilities.Internal = {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a DOMDocument object not attached to any window
|
||||||
|
*/
|
||||||
|
"getDOMDocument": function() {
|
||||||
|
return Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
||||||
|
.createInstance(Components.interfaces.nsIDOMParser)
|
||||||
|
.parseFromString("<!DOCTYPE html><html></html>", "text/html");
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generator that yields promises that delay for the given intervals
|
* A generator that yields promises that delay for the given intervals
|
||||||
*
|
*
|
||||||
|
@ -486,7 +496,7 @@ Zotero.Utilities.Internal = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines property on the object's prototype.
|
* Defines property on the object
|
||||||
* More compact way to do Object.defineProperty
|
* More compact way to do Object.defineProperty
|
||||||
*
|
*
|
||||||
* @param {Object} obj Target object
|
* @param {Object} obj Target object
|
||||||
|
@ -500,7 +510,7 @@ Zotero.Utilities.Internal = {
|
||||||
if (!desc.hasOwnProperty(p)) continue;
|
if (!desc.hasOwnProperty(p)) continue;
|
||||||
d[p] = desc[p];
|
d[p] = desc[p];
|
||||||
}
|
}
|
||||||
Object.defineProperty(obj.prototype, prop, d);
|
Object.defineProperty(obj, prop, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue