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.
Problem/Motivation
When adding support for temporary files to be migrated we assumed the temporary path to be absolute because it was set to "/tmp" in the dumps. This is a wrong assumption.
Proposed resolution
* We need to remove these assumptions from the EntityFile destination.
* Update the FileUri process plugin.
* Make sure the source sets the correct data on the row so we have source_base_path in the destination.
Remaining tasks
Write patch and tests.
User interface changes
n/a
API changes
n/a
Comment | File | Size | Author |
---|---|---|---|
#42 | 2417975-41.patch | 26.2 KB | phenaproxima |
#39 | interdiff-2417975-36-39.txt | 22.73 KB | phenaproxima |
#39 | 2417975-39.patch | 26.2 KB | phenaproxima |
#36 | interdiff-2417975-33-36.txt | 1.32 KB | phenaproxima |
#36 | 2417975-36.patch | 19.55 KB | phenaproxima |
Comments
Comment #1
benjy CreditAttribution: benjy commentedPostponing on #2414365: File migration fails when the files are at a remote URI which introduces some unit tests for the file destination.
Comment #2
benjy CreditAttribution: benjy commentedPatch attached rolled on top of https://www.drupal.org/node/2414365#comment-9573297
Comment #3
Anonymous (not verified) CreditAttribution: Anonymous commentedI guess this is no longer postponed since #2414365: File migration fails when the files are at a remote URI made it in. Let's first see what the testbot thinks of this.
Comment #5
phenaproximaAt first glance, the patch looks good to me (and testbot has been passing the one that isn't marked "FAIL"...hmmm). Here it is again with a few relatively minor modifications (removed deprecated file-related functions calls in favor of injecting the file_system service).
Comment #7
phenaproximaEntityFileTest should now pass.
I added a not-very-elegant kludge to EntityFile::import() to work around a quirk of file_prepare_directory(). If FileSystemInterface::dirname() returns a scheme -- for example, passing
public://foobaz.txt
will returnpublic://
--, file_prepare_directory() will reject that URI and EntityFile will throw a MigrateException.The fix checks the output of FileSystemInterface::dirname() against a regex and runs it through FileSystemInterface::realpath() if it's a scheme without a path, before file_prepare_directory() is called.
Comment #8
phenaproximaUpdating status.
Comment #9
phenaproximaChanged preg_match() call to substr().
Comment #11
benjy CreditAttribution: benjy at CodeDrop commentedCan we get a fail patch to sure the new test works?
I'll have to think about the changes in the destination in regards to the dirname() etc.
Comment #12
phenaproximaSure thing. This patch should fail EntityFileTest with an exception like:
Drupal\migrate\MigrateException: Could not create directory <em class="placeholder">public://</em> in Drupal\migrate\Plugin\migrate\destination\EntityFile->import() (line 76 of /path/to/core/modules/migrate/src/Plugin/migrate/destination/EntityFile.php).
Comment #13
phenaproxima...and yet somehow it didn't fail. Strange; it fails quite nicely in my local environment.
Comment #14
phenaproximaSome of @chx's work in #2482329: Remove deprecated calls from EntityFile and make it less local overlaps with the work in #9 -- namely, the removal of deprecated calls and injection of the file_system service. I'm thinking that issue should be
postponed until this patch is committedclosed, and its fixes integrated into this patch.Comment #15
phenaproximaThis patch smoothes over EntityFile's handling of remote streams by checking if the source and destination URIs are both local. I didn't add any specific test cases for this, because a) I'm not sure what exactly how to go about testing this, and b) there are no remote stream wrappers bundled with core that don't extend LocalStream (which made me throw a WtfException on IRC).
Comment #19
phenaproximaAfter refactoring EntityFile, this passes the tests on my localhost.
Comment #20
phenaproximaDid a bit of minor refactoring requested by @chx after he reviewed.
Comment #21
phenaproximaRegarding a fail patch -- I'm not sure we need one, because it appears to be flat-out broken in HEAD. On the latest 8.0.x (e0aae8c), MigrateFileTest will fail epically with a fatal error, and EntityFileTest will fail with a warning and a MigrateException ("cannot create directory public://").
After applying the patch in #20, both tests pass with flying colors.
Comment #22
phenaproximaI <3 dependency injection. Updated the patch to inject the string_translation service into EntityFile.
Comment #23
phenaproximaThis integrates the changes from #2483939: EntityFile should throw an exception if the source file doesn't exist -- it ensures the source file exists and throws an exception if it doesn't.
Comment #24
phenaproximaAt @chx's suggestion, this patch refactors EntityFile so that file_prepare_directory() is only called if needed -- that is, if an initial attempt to save the destination file fails.
Comment #25
chx CreditAttribution: chx as a volunteer commentedThis looks awesome. Thanks much. I made two very minor changes please do NOT credit me: one empty() was not necessary and the only change in FileUri was whitespace so I reverted the file.
Comment #26
benjy CreditAttribution: benjy at CodeDrop commentedCan we not calculate this in the constructor?
We don't translate exception messages.
same here.
and again.
Also, I do wonder if we need some unit tests for some of those new methods in EntityFile such as isLocalUri(), isLocationUnchanged(), getDirectory()
Comment #27
chx CreditAttribution: chx as a volunteer commented> Can we not calculate this in the constructor?
When testing, you'd need to mock bundleinfo for no benefit so ... no. The rest, agreed.
Comment #28
phenaproximaRemoved translation from the exceptions.
Regarding unit tests for the helper methods -- I'm fully up for it, if it's not too much of a pain (or, for that matter, considered unkosher) to forcibly change those protected methods to public ones for testing.
Comment #29
benjy CreditAttribution: benjy at CodeDrop commentedNo problem, I was just trying to reduce the number of dependencies EntityFile has.
I don't see any problems with that, i've done it myself elsewhere.
This is interesting, why not just do the assertion?
Same here and i think one other place.
Comment #30
phenaproximaI added the instanceof assertions because, if the file isn't loaded, the test will try to access a non-object and thus blow up with a fatal error, which is annoying as hell. Adding a fail saves us a trip to the "Clean environment" button. :)
Comment #31
benjy CreditAttribution: benjy at CodeDrop commentedPersonally I think we should remove them, i've not seen this pattern in core before?
Comment #32
chx CreditAttribution: chx as a volunteer commentedI agree with benjy here.
Comment #33
phenaproximaRemoved the instanceof checks from MigrateFileTest, and added unit tests of EntityFile's protected helpers.
Comment #34
neclimdulAwesome work, this fixes a huge number of errors on my test import.
I agree but we can't do that here. :)
Just remove this.
Why?
?
Comment #35
phenaproximaRegarding #3 -- it was requested to have unit tests of those helper methods, which are all protected in EntityFile. So I had to override them with public versions in order to test. Everything else, is valid, and I will re-roll the patch today.
Comment #36
phenaproximaAll fixed, except for #3.
Comment #37
neclimdulDid another review and looks fine. Definitely fixes a lot of failures in my test site migration.
Comment #38
benjy CreditAttribution: benjy at CodeDrop commentedboolean|string
Missing return description.
same here
Huh? This test is in tests/src/Unit, we can't just make it a web test?
It seems funny to me to have html in exception messages, can't we just use @ instead if we're using SafeMarkup::format?
Normally, testing protected/private methods directly isn't usually recommended but I do think it adds value in this case. Regarding #3, you could have done it like so if you prefer:
Comment #39
phenaproximaAll fixed.
@benjy, I prefer the idea of using reflection to alter the method accessibility, so that's what I did in this patch. I also changed EntityFileTest to a KernelTestBase (turns out it doesn't really need to be a web test, thank Cthulhu) and moved it out of the unit test suite.
Comment #40
benjy CreditAttribution: benjy at CodeDrop commentedWhy not use the data provider pattern here like we did above in testSuccessfulCopies().
I guess that was left over from the PHPUnit test, we should at least be consistent?
Shame we need this, once #2304461: KernelTestBaseTNG™ lands, we should be able to get rid of it.
Comment #41
benjy CreditAttribution: benjy at CodeDrop commentedOK, lets do it. The test improvements can always be a follow-up once KernelTestBaseNG lands.
Comment #42
phenaproximaQuick re-roll.
Comment #43
benjy CreditAttribution: benjy at CodeDrop commentedBack to RTBC
Comment #45
phenaproxima*shakes fist at testbot*
Comment #49
phenaproximaBack to RTBC after testbot tantrum.
Comment #50
alexpottCommitted 6ac8e46 and pushed to 8.0.x. Thanks!
Fixed minor spelling mistakes on commit.