Add retractions.enabled hidden pref to disable retraction checking
This commit is contained in:
parent
e69786bd69
commit
d353439980
3 changed files with 120 additions and 33 deletions
|
@ -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",
|
||||
|
|
|
@ -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", "[]");
|
||||
|
|
|
@ -62,18 +62,18 @@ describe("Retractions", function() {
|
|||
return item;
|
||||
}
|
||||
|
||||
describe("Notification Banner", function () {
|
||||
function bannerShown() {
|
||||
var container = win.document.getElementById('retracted-items-container');
|
||||
if (container.getAttribute('collapsed') == 'true') {
|
||||
return false;
|
||||
}
|
||||
if (!container.hasAttribute('collapsed')) {
|
||||
return true;
|
||||
}
|
||||
throw new Error("'collapsed' attribute not found");
|
||||
function bannerShown() {
|
||||
var container = win.document.getElementById('retracted-items-container');
|
||||
if (container.getAttribute('collapsed') == 'true') {
|
||||
return false;
|
||||
}
|
||||
if (!container.hasAttribute('collapsed')) {
|
||||
return true;
|
||||
}
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue