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_PMID: 'p',
|
||||||
TYPE_NAMES: ['DOI', 'PMID'],
|
TYPE_NAMES: ['DOI', 'PMID'],
|
||||||
|
|
||||||
|
_prefObserverRegistered: false,
|
||||||
_initialized: false,
|
_initialized: false,
|
||||||
_version: 1,
|
_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 () {
|
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
|
// 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().
|
// 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}
|
* @param {Zotero.Item}
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
|
@ -193,6 +202,11 @@ Zotero.Retractions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
notify: async function (action, type, ids, extraData) {
|
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
|
// Clean up cache on group deletion
|
||||||
if (action == 'delete' && type == 'group') {
|
if (action == 'delete' && type == 'group') {
|
||||||
for (let libraryID of ids) {
|
for (let libraryID of ids) {
|
||||||
|
@ -646,11 +660,29 @@ Zotero.Retractions = {
|
||||||
await Zotero.Notifier.trigger('refresh', 'item', [itemID]);
|
await Zotero.Notifier.trigger('refresh', 'item', [itemID]);
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadCacheFile: async function () {
|
_removeAllEntries: async function () {
|
||||||
if (!await OS.File.exists(this._cacheFile)) {
|
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;
|
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) {
|
if (data) {
|
||||||
this._processCacheData(data);
|
this._processCacheData(data);
|
||||||
}
|
}
|
||||||
|
@ -680,6 +712,7 @@ Zotero.Retractions = {
|
||||||
* Cache prefix list in profile directory
|
* Cache prefix list in profile directory
|
||||||
*/
|
*/
|
||||||
_saveCacheFile: async function (data, etag, doiPrefixLength, pmidPrefixLength) {
|
_saveCacheFile: async function (data, etag, doiPrefixLength, pmidPrefixLength) {
|
||||||
|
var cacheFile = OS.Path.join(Zotero.Profile.dir, 'retractions.json');
|
||||||
var cacheJSON = {
|
var cacheJSON = {
|
||||||
version: this._version,
|
version: this._version,
|
||||||
etag,
|
etag,
|
||||||
|
@ -688,7 +721,7 @@ Zotero.Retractions = {
|
||||||
data
|
data
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await Zotero.File.putContentsAsync(this._cacheFile, JSON.stringify(cacheJSON));
|
await Zotero.File.putContentsAsync(cacheFile, JSON.stringify(cacheJSON));
|
||||||
this._processCacheData(cacheJSON);
|
this._processCacheData(cacheJSON);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
@ -705,6 +738,24 @@ Zotero.Retractions = {
|
||||||
return url;
|
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/
|
// https://retractionwatch.com/retraction-watch-database-user-guide/retraction-watch-database-user-guide-appendix-b-reasons/
|
||||||
_reasonDescriptions: {
|
_reasonDescriptions: {
|
||||||
"Author Unresponsive": "Author(s) lack of communication after prior contact by Journal, Publisher or other original Authors",
|
"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.ignoreUnknown", true);
|
||||||
pref("extensions.zotero.translators.RIS.import.keepID", false);
|
pref("extensions.zotero.translators.RIS.import.keepID", false);
|
||||||
|
|
||||||
|
// Retracted Items
|
||||||
|
pref("extensions.zotero.retractions.enabled", true);
|
||||||
pref("extensions.zotero.retractions.recentItems", "[]");
|
pref("extensions.zotero.retractions.recentItems", "[]");
|
||||||
|
|
|
@ -62,18 +62,18 @@ describe("Retractions", function() {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("Notification Banner", function () {
|
function bannerShown() {
|
||||||
function bannerShown() {
|
var container = win.document.getElementById('retracted-items-container');
|
||||||
var container = win.document.getElementById('retracted-items-container');
|
if (container.getAttribute('collapsed') == 'true') {
|
||||||
if (container.getAttribute('collapsed') == 'true') {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!container.hasAttribute('collapsed')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw new Error("'collapsed' attribute not found");
|
|
||||||
}
|
}
|
||||||
|
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 () {
|
it("should show banner when retracted item is added", async function () {
|
||||||
var banner = win.document.getElementById('retracted-items-container');
|
var banner = win.document.getElementById('retracted-items-container');
|
||||||
assert.isFalse(bannerShown());
|
assert.isFalse(bannerShown());
|
||||||
|
@ -158,4 +158,38 @@ describe("Retractions", function() {
|
||||||
assert.ok(zp.collectionsView.getRowIndexByID("R" + userLibraryID));
|
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…
Add table
Add a link
Reference in a new issue