diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index 54e3939706..9ae7aef4b0 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -1239,9 +1239,10 @@ Zotero.Attachments = new function () { this.canFindFileForItem = function (item) { + let pmcid = item.getField('PMCID') || item.getExtraField('PMCID'); return item.isRegularItem() && !item.isFeedItem - && (!!item.getField('DOI') || !!item.getField('url') || !!item.getExtraField('DOI')) + && (!!item.getField('DOI') || !!item.getField('url') || !!item.getExtraField('DOI') || !!pmcid) && this.FIND_AVAILABLE_FILE_TYPES.every(type => item.numFileAttachmentsWithContentType(type) == 0); }; @@ -1275,7 +1276,12 @@ Zotero.Attachments = new function () { var resolvers = []; var doi = item.getField('DOI') || item.getExtraField('DOI'); + var pmcid = item.getField('PMCID') || item.getExtraField('PMCID'); doi = Zotero.Utilities.cleanDOI(doi); + if (pmcid) { + let matches = pmcid.match(/\bPMC\d+\b/i); + pmcid = matches && matches[0].toUpperCase(); + } if (useDOI && doi) { doi = Zotero.Utilities.cleanDOI(doi); @@ -1300,6 +1306,13 @@ Zotero.Attachments = new function () { } } + if (useOA && pmcid) { + resolvers.push({ + pageURL: `https://pmc.ncbi.nlm.nih.gov/articles/${pmcid}/`, + accessMethod: 'oa' + }); + } + if (useOA && doi) { resolvers.push(async function () { let urls = await Zotero.Utilities.Internal.getOpenAccessPDFURLs(doi); diff --git a/test/tests/attachmentsTest.js b/test/tests/attachmentsTest.js index b4237d178f..ebc124fc40 100644 --- a/test/tests/attachmentsTest.js +++ b/test/tests/attachmentsTest.js @@ -1031,6 +1031,48 @@ describe("Zotero.Attachments", function () { assert.equal(await OS.File.stat(attachment.getFilePath()).size, pdfSize); }); + it("should include a PubMed Central resolver from a PMCID in Extra", async function () { + var item = createUnsavedDataObject('item', { itemType: 'journalArticle' }); + item.setField('title', 'Test'); + item.setField('extra', 'PMCID: PMC9262588'); + await item.saveTx(); + + var resolvers = Zotero.Attachments.getFileResolvers(item, ['oa']); + + assert.deepEqual(resolvers, [ + { + pageURL: 'https://pmc.ncbi.nlm.nih.gov/articles/PMC9262588/', + accessMethod: 'oa' + } + ]); + }); + + it("should include a PubMed Central resolver alongside DOI OA resolvers", async function () { + var item = createUnsavedDataObject('item', { itemType: 'journalArticle' }); + item.setField('title', 'Test'); + item.setField('DOI', '10.1093/nar/gkac173'); + item.setField('extra', 'PMCID: PMC9262588'); + await item.saveTx(); + + var resolvers = Zotero.Attachments.getFileResolvers(item, ['oa']); + + assert.lengthOf(resolvers, 2); + assert.deepEqual(resolvers[0], { + pageURL: 'https://pmc.ncbi.nlm.nih.gov/articles/PMC9262588/', + accessMethod: 'oa' + }); + assert.isFunction(resolvers[1]); + }); + + it("should allow finding files for an item with a PMCID in Extra", async function () { + var item = createUnsavedDataObject('item', { itemType: 'journalArticle' }); + item.setField('title', 'Test'); + item.setField('extra', 'PMCID: PMC9262588'); + await item.saveTx(); + + assert.isTrue(Zotero.Attachments.canFindFileForItem(item)); + }); + it("should add a PDF from a URL", async function () { var url = pageURL1; var item = createUnsavedDataObject('item', { itemType: 'journalArticle' }); diff --git a/test/tests/server_connectorTest.js b/test/tests/server_connectorTest.js index e5223f7051..c9bcfbd0a0 100644 --- a/test/tests/server_connectorTest.js +++ b/test/tests/server_connectorTest.js @@ -701,6 +701,52 @@ describe("Connector Server", function () { assert.isTrue(JSON.parse(response.responseText)); }); + it("should respond with 'true' if the item has a PMCID fallback", async function () { + const sessionID = Zotero.Utilities.randomString(); + const itemID = Zotero.Utilities.randomString(); + const body = { + sessionID, + items: [ + { + id: itemID, + itemType: "journalArticle", + title: "Test Article with PMCID", + extra: "PMCID: PMC9262588", + } + ] + }; + + let response = await httpRequest( + "POST", + connectorServerPath + "/connector/saveItems", + { + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(body) + } + ); + + assert.equal(response.status, 201); + + response = await httpRequest( + "POST", + connectorServerPath + "/connector/hasAttachmentResolvers", + { + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + sessionID, + itemID + }), + } + ); + + assert.equal(response.status, 200); + assert.isTrue(JSON.parse(response.responseText)); + }); + it("should respond with 'false' if the item has no OA attachments", async function () { const sessionID = Zotero.Utilities.randomString(); const itemID = Zotero.Utilities.randomString();