From 0bc6b2ccc61dc5059ad9e3c477f8d56b1d31a962 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Fri, 12 Mar 2021 06:26:59 -0500 Subject: [PATCH] Transfer annotations when converting linked files to stored files Previously, any annotations on the linked file were partially deleted, leaving broken `items` rows without `itemAnnotations` rows. --- chrome/content/zotero/xpcom/attachments.js | 5 ++++- chrome/content/zotero/xpcom/data/items.js | 23 +++++++++++++++++++++ test/tests/attachmentsTest.js | 24 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index ccb3b6cd49..25a29609e5 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -2553,7 +2553,7 @@ Zotero.Attachments = new function(){ this.convertLinkedFileToStoredFile = async function (item, options = {}) { - if (item.attachmentLinkMode != Zotero.Attachments.LINK_MODE_LINKED_FILE) { + if (!item.isLinkedFileAttachment()) { throw new Error("Not a linked-file attachment"); } @@ -2572,6 +2572,9 @@ Zotero.Attachments = new function(){ newItem.fromJSON(json); await newItem.saveTx(); + // Move child annotations and embedded-image attachments + await Zotero.Items.moveChildItems(item, newItem); + // Copy relations pointing to the old item await Zotero.Relations.copyObjectSubjectRelations(item, newItem); var newFile; diff --git a/chrome/content/zotero/xpcom/data/items.js b/chrome/content/zotero/xpcom/data/items.js index 6815c0faee..9c78dc3b8f 100644 --- a/chrome/content/zotero/xpcom/data/items.js +++ b/chrome/content/zotero/xpcom/data/items.js @@ -875,6 +875,29 @@ Zotero.Items = function() { }); + /** + * Move child items from one item to another + * + * @param {Zotero.Item} fromItem + * @param {Zotero.Item} toItem + * @return {Promise} + */ + this.moveChildItems = async function (fromItem, toItem) { + // Annotations on files + if (fromItem.isFileAttachment()) { + await Zotero.DB.executeTransaction(async function () { + let annotations = fromItem.getAnnotations(); + for (let annotation of annotations) { + annotation.parentItemID = toItem.id; + await annotation.save(); + } + }.bind(this)); + } + + // TODO: Other things as necessary + }; + + this.merge = function (item, otherItems) { Zotero.debug("Merging items"); diff --git a/test/tests/attachmentsTest.js b/test/tests/attachmentsTest.js index 1bcfc60012..53f32e32aa 100644 --- a/test/tests/attachmentsTest.js +++ b/test/tests/attachmentsTest.js @@ -1339,6 +1339,30 @@ describe("Zotero.Attachments", function() { }); + it("should move annotations to stored file", async function () { + var item = await createDataObject('item'); + var relatedItem = await createDataObject('item'); + + var originalFile = OS.Path.join(getTestDataDirectory().path, 'test.pdf'); + var attachment = await Zotero.Attachments.linkFromFile({ + file: originalFile, + title: 'Title', + parentItemID: item.id + }); + var annotation1 = await createAnnotation('highlight', attachment); + var annotation2 = await createAnnotation('note', attachment); + + var newAttachment = await Zotero.Attachments.convertLinkedFileToStoredFile(attachment); + + assert.isFalse(Zotero.Items.exists(attachment.id)); + assert.isTrue(Zotero.Items.exists(annotation1.id)); + assert.isTrue(Zotero.Items.exists(annotation2.id)); + + var annotations = newAttachment.getAnnotations(); + assert.lengthOf(annotations, 2); + }); + + it("should move a linked file to a stored file with `move: true`", async function () { var item = await createDataObject('item');