In a node migration I added the mapping to a file field. The values get assigned in prepareRow(). It seems that the file field handler already saves the file before calling the node migrations function prepare(). In prepare I have some cases where I want to remove some files by unsetting them:

$entity->field_attachment[LANGUAGE_NONE][$delta] = 0.

The file is not in file_usage table but still in file_managed.

On form submission removing a file attachment from a node will also take care of deleting the file and removing the entry from file_managed. This should also be the case on migration.

Comments

osopolar’s picture

Title: Removing file in prepare() should remove it also from database. » Removing file from entity in prepare() should remove it also from database.
mikeryan’s picture

Category: Bug report » Support request
Status: Active » Postponed (maintainer needs more info)

No, I don't think so. At the prepare() stage, if an application is messing around with the node object that has already been constructed, it's on that application to make sure the result is self-consistent. It's simply not practical to take the node object after prepare() and figure out what might have changed that would have implications elsewhere.

May I ask, why are you doing this in prepare() rather than filtering the files you want to keep in prepareRow()? That seems much cleaner (and performant, given that files are being copied unnecessarily) than deleting field instances in prepare()...

osopolar’s picture

@mikeryan: Thanks for asking. I am using the class MigrateDestinationMedia from the migrate_extras project where the function rewriteImgTags() is invoked by prepare(). In some cases this will lead to duplicate files as these images are also part of a file attachment (drupal 5 file upload) migrated to a file field. So I remove files that are already handled by the media module from the file field in prepare(). As there are less than 100 nodes with these attachments the performance aspect is not that important here.

mikeryan’s picture

Status: Postponed (maintainer needs more info) » Active

Don't forget to reset the status from "Postponed (maintainer needs more info)" to Active for greater visibility.

mikeryan’s picture

Status: Active » Postponed (maintainer needs more info)

If you're removing duplicates, you would still want to keep the file_managed entry, right? Whichever of the dupes you're keeping will still need to point at it...

Regardless, I'm afraid I just don't see where Migrate can clean this up for you...

osopolar’s picture

Status: Postponed (maintainer needs more info) » Active

I had in mind that setting $entity->field_attachment[LANGUAGE_NONE][$delta] = 0 would trigger the same mechanism as removing a file from a entity (for example on a node edit form submit). There the usage will be set to 0 an if I remember well it gets removed from the files_managed table too, isn't it. But maybe it is not important, I found a workaround: deleting all unused files with a drush script, see sandbox project file delete

mikeryan’s picture

Status: Active » Closed (won't fix)

The update hooks are able to compare to the original node and see something's been removed, when things are being added and later removed in the prepare() process Migrate has no insight into that.