Set 'synced' to false automatically on save, unless value is changed

And add 'skipSyncedUpdate' option to leave untouched

Also move some save logic into Zotero.DataObject.prototype._saveData(),
and call that first.
This commit is contained in:
Dan Stillman 2015-05-13 19:30:22 -04:00
parent fa039971e6
commit 3f4eebe51c
5 changed files with 141 additions and 100 deletions

View file

@ -105,7 +105,10 @@ Zotero.Collection.prototype._set = function (field, value) {
if (this['_' + field] != value) {
this._markFieldChange(field, this['_' + field]);
this._changed.primaryData = true;
if (!this._changed.primaryData) {
this._changed.primaryData = {};
}
this._changed.primaryData[field] = true;
switch (field) {
default:
@ -286,51 +289,35 @@ Zotero.Collection.prototype._saveData = Zotero.Promise.coroutine(function* (env)
var options = env.options;
var collectionID = env.id = this._id = this.id ? this.id : yield Zotero.ID.get('collections');
var libraryID = env.libraryID = this.libraryID || Zotero.Libraries.userLibraryID;
var key = env.key = this._key = this.key ? this.key : this._generateKey();
var libraryType = env.libraryType = Zotero.Libraries.getType(libraryID);
Zotero.debug("Saving collection " + this.id);
var columns = [
'collectionID',
env.sqlColumns.push(
'collectionName',
'parentCollectionID',
'libraryID',
'key',
'version',
'synced'
];
var sqlValues = [
collectionID ? { int: collectionID } : null,
'parentCollectionID'
);
env.sqlValues.push(
{ string: this.name },
env.parent ? env.parent : null,
this.libraryID,
key,
this.version ? this.version : 0,
this.synced ? 1 : 0
];
if (isNew || !options.skipClientDateModified) {
columns.push('clientDateModified');
sqlValues.push(Zotero.DB.transactionDateTime);
}
env.parent ? env.parent : null
);
if (isNew) {
let placeholders = columns.map(function () '?').join();
let sql = "INSERT INTO collections (" + columns.join(', ') + ") "
env.sqlColumns.unshift('collectionID');
env.sqlValues.unshift(collectionID ? { int: collectionID } : null);
let placeholders = env.sqlColumns.map(function () '?').join();
let sql = "INSERT INTO collections (" + env.sqlColumns.join(', ') + ") "
+ "VALUES (" + placeholders + ")";
var insertID = yield Zotero.DB.queryAsync(sql, sqlValues);
var insertID = yield Zotero.DB.queryAsync(sql, env.sqlValues);
if (!collectionID) {
collectionID = env.id = insertID;
}
}
else {
columns.shift();
sqlValues.push(sqlValues.shift());
let sql = 'UPDATE collections SET '
+ columns.map(function (x) x + '=?').join(', ')
+ ' WHERE collectionID=?';
yield Zotero.DB.queryAsync(sql, sqlValues);
+ env.sqlColumns.map(function (x) x + '=?').join(', ') + ' WHERE collectionID=?';
env.sqlValues.push(collectionID ? { int: collectionID } : null);
yield Zotero.DB.queryAsync(sql, env.sqlValues);
}
if (this._changed.parentKey) {

View file

@ -587,6 +587,7 @@ Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options)
// Create transaction
if (env.options.tx) {
let 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);
@ -596,6 +597,7 @@ Zotero.DataObject.prototype.save = Zotero.Promise.coroutine(function* (options)
// Use existing transaction
else {
Zotero.DB.requireTransaction();
Zotero.DataObject.prototype._saveData.call(this, env);
yield this._saveData(env);
yield Zotero.DataObject.prototype._finalizeSave.call(this, env);
return this._finalizeSave(env);
@ -662,8 +664,38 @@ Zotero.DataObject.prototype._initSave = Zotero.Promise.coroutine(function* (env)
return true;
});
Zotero.DataObject.prototype._saveData = function () {
throw new Error("_saveData is an abstract method");
Zotero.DataObject.prototype._saveData = function (env) {
var libraryID = env.libraryID = this.libraryID || Zotero.Libraries.userLibraryID;
var key = env.key = this._key = this.key ? this.key : this._generateKey();
env.sqlColumns = [
'libraryID',
'key'
];
env.sqlValues = [
libraryID,
key
];
if (this._changed.primaryData && this._changed.primaryData.version) {
env.sqlColumns.push('version');
env.sqlValues.push(this.version || 0);
}
if (this._changed.primaryData && this._changed.primaryData.synced) {
env.sqlColumns.push('synced');
env.sqlValues.push(this.synced ? 1 : 0);
}
// Set synced to 0 by default
else if (!env.isNew && !env.options.skipSyncedUpdate) {
env.sqlColumns.push('synced');
env.sqlValues.push(0);
}
if (env.isNew || !env.options.skipClientDateModified) {
env.sqlColumns.push('clientDateModified');
env.sqlValues.push(Zotero.DB.transactionDateTime);
}
};
Zotero.DataObject.prototype._finalizeSave = Zotero.Promise.coroutine(function* (env) {

View file

@ -1181,14 +1181,13 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
var isNew = env.isNew;
var options = env.options;
var libraryType = env.libraryType = Zotero.Libraries.getType(env.libraryID);
var itemTypeID = this.itemTypeID;
if (!itemTypeID) {
throw new Error("Item type must be set before saving");
}
var sqlColumns = [];
var sqlValues = [];
var reloadParentChildItems = {};
//
@ -1196,26 +1195,14 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
//
// If available id value, use it -- otherwise we'll use autoincrement
var itemID = env.id = this._id = this.id ? this.id : yield Zotero.ID.get('items');
var libraryID = env.libraryID = this.libraryID || Zotero.Libraries.userLibraryID;
var key = env.key = this._key = this.key ? this.key : this._generateKey();
var libraryType = env.libraryType = Zotero.Libraries.getType(libraryID);
sqlColumns.push(
env.sqlColumns.push(
'itemTypeID',
'dateAdded',
'libraryID',
'key',
'version',
'synced'
'dateAdded'
);
sqlValues.push(
env.sqlValues.push(
{ int: itemTypeID },
this.dateAdded ? this.dateAdded : Zotero.DB.transactionDateTime,
this.libraryID,
key,
this.version ? this.version : 0,
this.synced ? 1 : 0
this.dateAdded ? this.dateAdded : Zotero.DB.transactionDateTime
);
// If a new item and Date Modified hasn't been provided, or an existing item and
@ -1224,29 +1211,24 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
if (!this.dateModified
|| ((!this._changed.primaryData || !this._changed.primaryData.dateModified)
&& !options.skipDateModifiedUpdate)) {
sqlColumns.push('dateModified');
sqlValues.push(Zotero.DB.transactionDateTime);
env.sqlColumns.push('dateModified');
env.sqlValues.push(Zotero.DB.transactionDateTime);
}
// Otherwise, if a new Date Modified was provided, use that. (This would also work when
// skipDateModifiedUpdate was passed and there's an existing value, but in that case we
// can just not change the field at all.)
else if (this._changed.primaryData && this._changed.primaryData.dateModified) {
sqlColumns.push('dateModified');
sqlValues.push(this.dateModified);
}
if (isNew || !options.skipClientDateModifiedUpdate) {
sqlColumns.push('clientDateModified');
sqlValues.push(Zotero.DB.transactionDateTime);
env.sqlColumns.push('dateModified');
env.sqlValues.push(this.dateModified);
}
if (isNew) {
sqlColumns.unshift('itemID');
sqlValues.unshift(parseInt(itemID));
env.sqlColumns.unshift('itemID');
env.sqlValues.unshift(parseInt(itemID));
let sql = "INSERT INTO items (" + sqlColumns.join(", ") + ") "
+ "VALUES (" + sqlValues.map(function () "?").join() + ")";
var insertID = yield Zotero.DB.queryAsync(sql, sqlValues);
let sql = "INSERT INTO items (" + env.sqlColumns.join(", ") + ") "
+ "VALUES (" + env.sqlValues.map(function () "?").join() + ")";
var insertID = yield Zotero.DB.queryAsync(sql, env.sqlValues);
if (!itemID) {
itemID = env.id = insertID;
}
@ -1256,9 +1238,9 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
}
}
else {
let sql = "UPDATE items SET " + sqlColumns.join("=?, ") + "=? WHERE itemID=?";
sqlValues.push(parseInt(itemID));
yield Zotero.DB.queryAsync(sql, sqlValues);
let sql = "UPDATE items SET " + env.sqlColumns.join("=?, ") + "=? WHERE itemID=?";
env.sqlValues.push(parseInt(itemID));
yield Zotero.DB.queryAsync(sql, env.sqlValues);
if (!env.options.skipNotifier) {
Zotero.Notifier.trigger('modify', 'item', itemID, env.notifierData);

View file

@ -145,48 +145,32 @@ Zotero.Search.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
var options = env.options;
var searchID = env.id = this._id = this.id ? this.id : yield Zotero.ID.get('savedSearches');
var libraryID = env.libraryID = this.libraryID || Zotero.Libraries.userLibraryID;
var key = env.key = this._key = this.key ? this.key : this._generateKey();
var libraryType = env.libraryType = Zotero.Libraries.getType(libraryID);
var columns = [
'savedSearchID',
env.sqlColumns.push(
'savedSearchName',
'libraryID',
'key',
'version',
'synced'
];
var placeholders = columns.map(function () '?').join();
var sqlValues = [
searchID ? { int: searchID } : null,
{ string: this.name },
this.libraryID,
key,
this.version ? this.version : 0,
this.synced ? 1 : 0
];
if (isNew || !options.skipClientDateModified) {
columns.push('clientDateModified');
sqlValues.push(Zotero.DB.transactionDateTime);
}
'savedSearchID'
);
env.sqlValues.push(
{ string: this.name }
);
if (isNew) {
let placeholders = columns.map(function () '?').join();
let sql = "INSERT INTO savedSearches (" + columns.join(', ') + ") "
env.sqlColumns.unshift('savedSearchID');
env.sqlValues.unshift(searchID ? { int: searchID } : null);
let placeholders = env.sqlColumns.map(function () '?').join();
let sql = "INSERT INTO savedSearches (" + env.sqlColumns.join(', ') + ") "
+ "VALUES (" + placeholders + ")";
var insertID = yield Zotero.DB.queryAsync(sql, sqlValues);
var insertID = yield Zotero.DB.queryAsync(sql, env.sqlValues);
if (!searchID) {
searchID = env.id = insertID;
}
}
else {
columns.shift();
sqlValues.push(sqlValues.shift());
let sql = 'UPDATE savedSearches SET '
+ columns.map(function (x) x + '=?').join(', ')
+ ' WHERE savedSearchID=?';
yield Zotero.DB.queryAsync(sql, sqlValues);
+ env.sqlColumns.map(function (x) x + '=?').join(', ') + ' WHERE savedSearchID=?';
env.sqlValues.push(searchID ? { int: searchID } : null);
yield Zotero.DB.queryAsync(sql, env.sqlValues);
}
if (!isNew) {

View file

@ -29,6 +29,62 @@ describe("Zotero.DataObject", function() {
})
})
describe("#synced", function () {
it("should be set to false after creating item", function* () {
var item = new Zotero.Item("book");
var id = yield item.saveTx();
item = yield Zotero.Items.getAsync(id);
assert.isFalse(item.synced);
yield Zotero.Items.erase(id);
});
it("should be set to true when changed", function* () {
var item = new Zotero.Item("book");
var id = yield item.saveTx();
item = yield Zotero.Items.getAsync(id);
item.synced = 1;
yield item.save();
assert.ok(item.synced);
yield Zotero.Items.erase(id);
});
it("should be set to false after modifying item", function* () {
var item = new Zotero.Item("book");
var id = yield item.saveTx();
item = yield Zotero.Items.getAsync(id);
item.synced = 1;
yield item.save();
yield item.loadItemData();
item.setField('title', 'test');
yield item.save();
assert.isFalse(item.synced);
yield Zotero.Items.erase(id);
});
it("should be unchanged if skipSyncedUpdate passed", function* () {
var item = new Zotero.Item("book");
var id = yield item.saveTx();
item = yield Zotero.Items.getAsync(id);
item.synced = 1;
yield item.save();
yield item.loadItemData();
item.setField('title', 'test');
yield item.save({
skipSyncedUpdate: true
});
assert.ok(item.synced);
yield Zotero.Items.erase(id);
});
})
describe("#save()", function () {
it("should add new identifiers to cache", function* () {
// Collection