Add retractions.enabled hidden pref to disable retraction checking

This commit is contained in:
Dan Stillman 2019-06-11 21:24:17 -04:00
parent e69786bd69
commit d353439980
3 changed files with 120 additions and 33 deletions

View file

@ -28,28 +28,21 @@ Zotero.Retractions = {
TYPE_PMID: 'p',
TYPE_NAMES: ['DOI', 'PMID'],
_prefObserverRegistered: false,
_initialized: false,
_version: 1,
_cacheFile: null,
_cacheVersion: null,
_cacheETag: null,
_cacheDOIPrefixLength: null,
_cachePMIDPrefixLength: null,
_cachePrefixList: new Set(), // Prefix strings from server
_queuedItems: new Set(),
_queuedPrefixStrings: new Set(),
_keyItems: {},
_itemKeys: {},
_retractedItems: new Set(),
_retractedItemsByLibrary: {},
_librariesWithRetractions: new Set(),
init: async function () {
this._cacheFile = OS.Path.join(Zotero.Profile.dir, 'retractions.json');
this._resetState();
if (!this._prefObserverRegistered) {
Zotero.Prefs.registerObserver('retractions.enabled', this._handlePrefChange.bind(this));
this._prefObserverRegistered = true;
}
if (!Zotero.Prefs.get('retractions.enabled')) {
return;
}
// Load mappings of keys (DOI hashes and PMIDs) to items and vice versa and register for
// item changes so they can be kept up to date in notify().
@ -89,6 +82,22 @@ Zotero.Retractions = {
}
},
_resetState: function () {
this._initialized = false;
this._keyItems = {};
this._itemKeys = {};
this._queuedItems = new Set();
this._queuedPrefixStrings = new Set();
this._retractedItems = new Set();
this._retractedItemsByLibrary = {};
this._librariesWithRetractions = new Set();
this._cacheVersion = null;
this._cacheETag = null;
this._cacheDOIPrefixLength = null;
this._cachePMIDPrefixLength = null;
this._cachePrefixList = new Set();
},
/**
* @param {Zotero.Item}
* @return {Boolean}
@ -193,6 +202,11 @@ Zotero.Retractions = {
},
notify: async function (action, type, ids, extraData) {
// The observer is removed when disabled but something might already be in progress
if (!this._initialized) {
return;
}
// Clean up cache on group deletion
if (action == 'delete' && type == 'group') {
for (let libraryID of ids) {
@ -646,11 +660,29 @@ Zotero.Retractions = {
await Zotero.Notifier.trigger('refresh', 'item', [itemID]);
},
_loadCacheFile: async function () {
if (!await OS.File.exists(this._cacheFile)) {
_removeAllEntries: async function () {
var libraryIDs = await Zotero.DB.columnQueryAsync(
"SELECT libraryID FROM items WHERE itemID IN (SELECT itemID FROM retractedItems)"
);
var itemIDs = await Zotero.DB.columnQueryAsync("SELECT itemID FROM retractedItems");
if (!itemIDs.length) {
return;
}
var data = JSON.parse(await Zotero.File.getContentsAsync(this._cacheFile));
await Zotero.DB.queryAsync("DELETE FROM retractedItems");
this._retractedItems.clear();
this._retractedItemsByLibrary = {};
for (let libraryID of libraryIDs) {
await this._updateLibraryRetractions(libraryID);
}
await Zotero.Notifier.trigger('refresh', 'item', itemIDs);
},
_loadCacheFile: async function () {
var cacheFile = OS.Path.join(Zotero.Profile.dir, 'retractions.json');
if (!await OS.File.exists(cacheFile)) {
return;
}
var data = JSON.parse(await Zotero.File.getContentsAsync(cacheFile));
if (data) {
this._processCacheData(data);
}
@ -680,6 +712,7 @@ Zotero.Retractions = {
* Cache prefix list in profile directory
*/
_saveCacheFile: async function (data, etag, doiPrefixLength, pmidPrefixLength) {
var cacheFile = OS.Path.join(Zotero.Profile.dir, 'retractions.json');
var cacheJSON = {
version: this._version,
etag,
@ -688,7 +721,7 @@ Zotero.Retractions = {
data
};
try {
await Zotero.File.putContentsAsync(this._cacheFile, JSON.stringify(cacheJSON));
await Zotero.File.putContentsAsync(cacheFile, JSON.stringify(cacheJSON));
this._processCacheData(cacheJSON);
}
catch (e) {
@ -705,6 +738,24 @@ Zotero.Retractions = {
return url;
},
_handlePrefChange: async function () {
// Enable
if (Zotero.Prefs.get('retractions.enabled')) {
await this.init();
}
// Disable
else {
if (this._notifierID) {
Zotero.Notifier.unregisterObserver(this._notifierID);
delete this._notifierID;
}
await this._removeAllEntries();
this._resetState();
let cacheFile = OS.Path.join(Zotero.Profile.dir, 'retractions.json');
await OS.File.remove(cacheFile);
}
},
// https://retractionwatch.com/retraction-watch-database-user-guide/retraction-watch-database-user-guide-appendix-b-reasons/
_reasonDescriptions: {
"Author Unresponsive": "Author(s) lack of communication after prior contact by Journal, Publisher or other original Authors",

View file

@ -192,4 +192,6 @@ pref("extensions.zotero.translators.supplementaryAsLink", false);
pref("extensions.zotero.translators.RIS.import.ignoreUnknown", true);
pref("extensions.zotero.translators.RIS.import.keepID", false);
// Retracted Items
pref("extensions.zotero.retractions.enabled", true);
pref("extensions.zotero.retractions.recentItems", "[]");

View file

@ -62,7 +62,6 @@ describe("Retractions", function() {
return item;
}
describe("Notification Banner", function () {
function bannerShown() {
var container = win.document.getElementById('retracted-items-container');
if (container.getAttribute('collapsed') == 'true') {
@ -74,6 +73,7 @@ describe("Retractions", function() {
throw new Error("'collapsed' attribute not found");
}
describe("Notification Banner", function () {
it("should show banner when retracted item is added", async function () {
var banner = win.document.getElementById('retracted-items-container');
assert.isFalse(bannerShown());
@ -158,4 +158,38 @@ describe("Retractions", function() {
assert.ok(zp.collectionsView.getRowIndexByID("R" + userLibraryID));
});
});
describe("retractions.enabled", function () {
beforeEach(function () {
Zotero.Prefs.clear('retractions.enabled');
});
it("should hide virtual collection and banner when false", async function () {
var item = await createRetractedItem();
await Zotero.Promise.delay(50);
var itemRetractionBox = win.document.getElementById('retraction-box');
assert.isFalse(itemRetractionBox.hidden);
var spies = [
sinon.spy(Zotero.Retractions, '_removeAllEntries'),
sinon.spy(Zotero.Retractions, 'getData')
];
Zotero.Prefs.set('retractions.enabled', false);
while (!spies[0].called || !spies[1].called) {
await Zotero.Promise.delay(50);
}
await spies[0].returnValues[0];
await spies[1].returnValues[0]
spies.forEach(spy => spy.restore());
assert.isFalse(Zotero.Retractions.isRetracted(item));
assert.isFalse(zp.collectionsView.getRowIndexByID("R" + userLibraryID));
assert.isFalse(bannerShown());
assert.isTrue(itemRetractionBox.hidden);
await item.eraseTx();
});
});
});