Problem/Motivation
If you add an image via /media/add/image, you can click the "Remove" button after uploading a file, and the file you just uploaded is immediately deleted.
If you try to upload an image via the media library, you can click a "Remove" button for the item before you save it. However, when you do that, the file is not deleted right away. It is marked as temporary (there is pre-existing test coverage to confirm this), and therefore cleaned up at a later time by cron. This isn't necessary a major problem, but it's both inconsistent and a little more "lax", from a privacy standpoint, than the normal file field widget.
Steps to reproduce
- Add a media field to the article node type configured with the media library widget
- Create a new article
- Open the media library
- Upload a new image
- Click the 'Remove' button in the second step of the add form
- The media item is removed, the uploaded file however is still available on the server

Proposed resolution
Immediately delete a media item's associated file when pressing 'Remove' after uploading something in the media library.
Remaining tasks
Write a patchReview- Commit
User interface changes
None.
API changes
None.
Data model changes
None.
Release notes snippet
When adding items to the media library, uploaded files associated with unsaved media items are immediately deleted when the media items are removed.
| Comment | File | Size | Author |
|---|---|---|---|
| #47 | 3073734-47.patch | 7.9 KB | oknate |
| #47 | 3073734-interdiff--45-47.txt | 1.41 KB | oknate |
| #45 | 3073734-45.patch | 13.61 KB | oknate |
| #45 | 3073734-45--no-extra-changes.patch | 8.02 KB | oknate |
| #44 | images-1-3-and-4.png | 396.17 KB | oknate |
Comments
Comment #2
idebr commentedAttached patch immediately deletes a media's file when pressing 'Remove' in the media creation modal.
Comment #4
idebr commentedAdded a sanity check to
\Drupal\media_library\Form\AddFormBase::removeButtonSubmit()file deletion for media without a file entity.Comment #6
idebr commentedComment #7
berdirShould we add a usage/status check before deleting to be sure?
I could imagine a few scenarios where it's not guaranteed to have a 1:1 relationship between media and file entities. For example, an automatic file deduplication module that would re-use an existing file if you upload one that was already used.
Comment #8
idebr commented#7 Yes that makes sense. I added a file usage check.
Comment #11
idebr commentedFixed the dependency injection in
\Drupal\media_library\Form\FileUploadFormComment #13
lendudeNitpicks:
'... when the file is not in use anywhere.' or something? On its own this comment doesn't add much.
This normally needs a change record and a 'See' to that change record. Is see this didn't happen for the
$opener_resolverchange, maybe it's not needed for experimental modules?Comment #14
idebr commented#13.1 Removed the code comment.
#13.2 Drafted a change record at https://www.drupal.org/node/3075165 and updated the
@trigger_erroraccordingly.Comment #15
phenaproximaRemoving defunct "D8Media" tag.
Comment #16
phenaproximaThank you for writing a test of this! That will be hugely helpful in committing this. Would you mind posting a fail patch (i.e., one that only contains the new test coverage), so we can be sure that the tests prove that the bug is fixed? :)
Comment #17
phenaproximaThe patch looks pretty damn good to me.
I think my only major complaint about this patch is that we don't need to worry about this file usage stuff in the OEmbed add form. So let's only add this to the FileUploadForm class, and only do this removal stuff there.
Comment #18
idebr commented#16 Added a test-only patch
#17 Removed the changes to \Drupal\media_library\Form\AddFormBase and \Drupal\media_library\Form\OEmbedForm. I think the draft change record I added #14 is no longer relevant now?
Comment #20
phenaproximaThis looks very, very good to me. Thanks for working on it!
I think we'll want an E_USER_DEPRECATED error for $file_usage here, similarly to what you had in a previous patch; it's quite likely that this class has been extended, so it's probably safer for us to have a deprecation notice for the new parameter. I just wanted to move it into FileUploadForm, rather than have it in AddFormBase.
I don't see anything else particularly wrong with this patch, but I'd ideally like @seanB to sign off as a fellow subsystem maintainer, and get a framework manager to commit it. File handling, especially usage tracking, can be tricky/flaky, so I want to be sure I'm not missing anything.
Comment #21
seanbApart from the things phenaproxima already noticed, this is looking good to me. So +1.
Yep, this needs a deprecation notice.
Checking the usage is probably no problem. Usage is not 100% reliable, but this is better than always blindly deleting the file.
Comment #22
idebr commented#20 / #21.1 Added a deprecation notice to
\Drupal\media_library\Form\FileUploadForm::__construct()and updated the change record: https://www.drupal.org/node/3075165#21.2 The file usage check was a suggestion by Berdir in #7. Since the media item in FileUploadForm is not yet saved, the risk of deleting files too eagerly becomes a lot smaller, but checking file usage allows other code to prevent that from happening.
Comment #23
berdirFWIW, I think change records on constructor argument changes are not necessary and just add noise, we've done hundreds of these. Both controllers and constructors are @internal, we're just being nice here. Base classes are a bit different, but we usually don't do change records for that either :) Now that you have it, possibly fine to keep?
Comment #25
seanbLooks good to me. Thanks!
Comment #26
xjmThis is at least major and maybe critical-ish because of the impacts on data integrity and privacy expectations. Thanks!
Comment #27
xjmThis is internally contradictory. I think we mean "and the
$file_usageargument will be required in 9.0.0"?Comment #28
xjmOK settling on "major" for now, pending the following information:
An IS update with more specific steps to reproduce and a comparison to the core widget will help us here. Thanks!
Comment #29
berdir> What happens when you follow the equivalent upload and "Remove" steps using the default file upload widget?
The same that happens with media AFAIK, the file never becomes permanent and is then eventually deleted after the configured timeframe (6h).
IMHO, this is a small improvement that isn't actually that big of a deal. Compared to the mess that we havewith not actually ever marking a file as temporary again based on file usage (by default) and having no automated or manual way at all to delete a file again in core ;)
Comment #30
idebr commented#27 Updated the wording in the deprecation notice.
#28.1 The 'Remove' button for a File widget should not remove a file, because the user can still navigate away and leave the entity untouched. For the media upload process, the media entity is not yet saved and the user is navigated away. This means the file can be safely removed.
#28.2 I think this question was covered in #29
Comment #32
seanbThanks idebr! Everything seems to be addressed. Also updated the steps to reproduce in the IS. RTBC!
Comment #33
seanbTo clarify, the remove button when adding media through media/add is the remove button of the source field. For local files this is a managed file element. This executes
file_managed_file_submit(). This deletes the actual created file entity.For the media library add form, the remove button in step 2 is a custom remove button, not the remove button of the source field. This executes
Drupal\media_library\Form\AddFormBase::removeButtonSubmit()and only removes the data from the add form, ensuring no new media item is created. The actual uploaded file is not deleted.That is why this patch is a great improvement.
Comment #34
phenaproximaCleaning up the IS to clarify what's going on here.
Comment #35
xjmLet's confirm that a normal file field and a media library item with this patch behave the same way when deleting a file (individual steps and what happens to the file at each step). Thanks!
Comment #36
phenaproximaStarting from 8.8.x HEAD with this patch applied, on the Standard profile with Media Library installed, and logged in as user 1:
Here's how file fields behave (this is what we want Media Library to do as well):
Now, add a media field to the Article content type. Just use the default settings, any cardinality, and ensure that the Image media type is one of the ones that can be referenced by the field.
So, this worked for me as expected. Restoring RTBC.
Comment #37
phenaproximaAdding a release note.
Comment #38
larowlanCan we align this with the proposed standard in #3024461: Adopt consistent deprecation format for core and contrib deprecation messages - @xjm asked about this earlier too
"... and the $file_usage argument will be required in drupal:9.0.0..."
Can we have additional test coverage for when there is a file usage record - that ensures the file is not deleted?
Thanks!
Comment #39
oknateAddressing #39:
1) Adding test coverage for file not being deleted if in use.
2) Updating the deprecation notice to follow the recommended pattern.
3) I made a few changes because of random failures. For example:
4) I made one coding standard change.
Comment #40
phenaproximaLooks great except for three very small things.
Isn't this a usage for the third file, not the second?
We can probably remove the
'title'key :)Can we also assert that the physical file exists? Something like:
Comment #41
oknateResponding to #40:
1. ✅Yes, now that I think about it, we removed the second file, but this was the fourth, so it's now in the third position. Counting under five is hard.
2. ✅Updated
3. ✅ Now with assertion that the physical file exists!
Comment #42
phenaproximaStill looks good, but a few more requests :)
Teensy nit: This can be
$removed_media = $form_state->get(['media', $delta]). No need for $added_media to be its own variable.We should probably also do a $this->assertFileNotExists(), to ensure it was physically deleted.
Why is the fourth file now in the third position? What does that mean?
No real need for the
'alt'key either, but I'll let it slide. :)Comment #43
oknateAddressing #42
1. ✅ Updated. We should probably add an issue to update this in AddFormBase too:
2. ✅ Added the assertion.
3. Literally, there are three images on the page, the fourth of the original four is now the third on the page. See the screenshot (on the next . comment). Perhaps we should refer to them differently? I updated it to refer to the variable name to be clearer.
I ran into frequent random failures. I added fixes as they were blocking me. But perhaps, I should leave them out and leave them for #3055648: Frequent random fail in \Drupal\Tests\media_library\FunctionalJavascript\MediaLibraryTest.
Here's a patch with the fixes. I'll try to post one without too.
Comment #44
oknateScreenshot referred to in #43.3:
Comment #45
oknateSame as #43, but in two versions:
1) One patch has all the extraneous changes removed.
2) The second patch has changes to fix the test when I was experiencing random failures on my local while running the test ::testWidgetUpload(), and one coding standard fix. I experienced many random failures in different places. Lots of room for improvement here.
Comment #46
phenaproximaThese lines should be swapped. If they're not, and $files is empty, then we'll be calling methods on FALSE, which will cause the test to die with a fatal error.
Why are we asserting this focus? We didn't change focus behavior elsewhere in the patch, so I'm not sure why this assertion is here? (I'm not complaining, of course; focus assertions are useful.)
RTBC for the no-extra-changes patch, once the first point is fixed. Please go right ahead and set this issue to that status once a new patch is up.
Comment #47
oknateAddressing #46.
1. ✅Swapped the lines.
2. ✅ Dropped the focus assertion. I was following the pattern above, but I don't think it's necessary here.
Comment #48
phenaproximaSeemingly unrelated random Postgres failure on #45, so I’ve queued #47 on all backends. Hopefully it passes; RTBC once it does.
Comment #49
webchickSaving issue credit. Everyone seems to have contributed positively to the solution here, so...
Comment #50
webchickAhem.
Comment #52
webchickThere we go.
This is a highly sensible patch that brings Media inline with Image/File fields. +1. I manually tested various permutations and couldn't find any problems (shock and horror!).
Committed and pushed to 8.8.x. Thanks a ton!! One fewer must-have out of the way. :D
Comment #53
idebr commentedI published the associated change record at https://www.drupal.org/node/3075165