Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
When using MigrateFileFid, files are deleted on rollback, which is goes against the purpose of this class (I believe?), since it is often used to map to files that were already imported, as for example in:
$this->addFieldMapping('field_image', 'image')
->sourceMigration('MyMedia');
$this->addFieldMapping('field_image:file_class')
->defaultValue("MigrateFileFid");
Comment | File | Size | Author |
---|---|---|---|
#15 | preserve_files-1676652-15.patch | 3.11 KB | joelstein |
#14 | preserve_files-1676652-14.patch | 3.09 KB | mikeryan |
Comments
Comment #1
bpiwowar CreditAttribution: bpiwowar commentedAs a quick fix, I just copied the code from MigrateFile - this works
Comment #2
mikeryanI'd like a little more information - whatever migration initially migrated the file, if it had preserve_files set, should have added the file_usage row so MigrateFileFid wouldn't... Ahhh, I see it, because we set the count to 1 the fid rollback decrements and deletes it. OK, definitely something to look into.
Comment #3
mikeryanWell, now I'm having a similar problem in the FILE_EXISTS_REUSE case. I've never been entirely comfortable with using file_usage to accomplish this - for one thing, when can Migrate release its usage so people can manually delete files after migration? For another, it's tough to get the count just right.
When migrating files in their own migration (MigrateDestinationFile), ugly as it is we probably should replace the file_delete() call with our own version of file_delete() hacked to respect the preserve_files setting. Dealing with migrating files directly into a file/image field will be tougher - since we're not the ones calling file_delete() when the referencing entity is rolled back, we'll probably have to maintain the file_usage stuff as best we can for that case. This is another reason to consider migrating files in their own migration, rather than directly into the field, as a best practice, so some documentation/education is an element in minimizing the issues here.
Comment #4
mikeryanOK, I've committed the following changes:
Leaving open as a documentation issue - I want to highlight the behavior, and also emphasize using MigrateDestinationFile as a best practice.
Comment #5
joelstein CreditAttribution: joelstein commentedHow exactly is this supposed to work? I'm using migrate_d2d to create a DrupalFile6Migration (to migrate my files):
Then, in my DrupalNode6Migration override class, in the __construct method, I simply map the field with it's source migration and file_class of "MigrateFileFid":
I import all my files, which works great. Then I import my nodes, which also works. However, when I rollback my nodes, the corresponding logo files get deleted.
Where do I indicate that the files should be preserved on rollback?
Comment #6
mikeryanYou might try:
Comment #7
joelstein CreditAttribution: joelstein commentedThanks, Mike. However, the files were still deleted. Here's the code I used:
Comment #8
joelstein CreditAttribution: joelstein commentedFor what it's worth, looking at my Migrate UI field mapping page, it shows the following alert (with the code above):
"field_logo:preserve_files" was used as destination field in "" mapping but is not in list of destination fields
Since I'm using the MigrateFileFid file_class, won't this disable any customized field mapping for the file?
Comment #9
mikeryanI see it, although MigrateFileFid is calling markForPreservation, the preserveFiles flag is actually implemented in MigrateFile, that stuff needs to move down to MigrateFileBase...
Thanks.
Comment #10
konradj CreditAttribution: konradj commentedThis works for me.
migrate/plugins/destinations/file.inc
641c641
< $file->preserve_files = FALSE;
---
> //$file->preserve_files = FALSE;
This line prevents the markForPreservation to work in import
53 protected function markForPreservation($fid) {
54 if (!empty($this->preserveFiles)) {
I also got the same problem when i rollback article images.
Comment #11
rcross CreditAttribution: rcross commentedwe are at a point where we are having to write a module to store the file references and put them back in when doing an import, this is really wrong and I can't figure out why migrate is doing this.
Comment #12
icampanaI'm having the same problem, and in a big migration (about 100,000 nodes and 300,000 media files) is quite an issue when I need to rollback the nodes. I haven't found a solution yet, if I do I post it around here.
Comment #13
rcross CreditAttribution: rcross commentedI am bumping this to major (its a critical bug in my opinion though) since this bug is actually quite destructive - it deletes the files from the file system not just the references to them in the database.
Comment #14
mikeryanThis should address the issue with MigrateFileFid respecting preserve_files.
Comment #15
joelstein CreditAttribution: joelstein commentedFor documentation purposes, you'll want to add the parent class fields() in MigrateFile::fields():
Otherwise, your patch didn't work for me. The files are preserved upon rollback of my File migration, but not upon rollback of any migrations dependent upon the File migration (where the File migration is a sourceMigration() for one of the dependency migrations).
If I comment out the line as in comment #10 above, the files are preserved and dependent migrations won't delete the files.
Here's an updated patch which incorporates these two additions.
Comment #17
joelstein CreditAttribution: joelstein commentedNevermind, I take that back. I forgot to add the "preserve_file" in my dependent class. Yep, your patch works great, except you need to add the parent fields. Thanks!
Comment #18
mikeryanCommitted, with the parent fields added.