Problem/Motivation
It's currently impossible for end-users to manually pull metadata associated with media assets from the source into the Drupal media entity, after the entity is created. Similarly, the Thumbnail (which is not a metadata per se) is treated the same way, it is currently only retrieved from the source when the entity is first created.
Several scenarios have shown this is a big limitation, being a prominent example the situation when the source providing the thumbnail is remote (like an YouTube video), and the thumbnail is changed on the remote source after the entity has been created in Drupal. Currently there is no mechanism for users to update the Thumbnail in this scenario. The same is valid for all other metadata attributes that source plugins could define (name, filesize, filemime, width, height, etc).
This issue was spun-off from #2878119: Whether queued or not, update the media thumbnail and metadata before beginning the entity save database transaction.
Proposed resolution
Expose to the UI the possibility of end users with correct permissions to trigger an immediate update of the asset's metadata + thumbnail
Remaining tasks
Usability re-review, see #108 and the last paragraph of #138
#67, testing with multiple languages
#80.2 - a security item
#138 1-3.
User interface changes
- New contextual link "Update metadata" is available in the front-end

- New operation dropbutton "Update metadata" is available in the back-end

- New "Update metadata" action is available in media administrative views, as a bulk operation.

API changes
A new public method \Drupal\media\MediaInterface::updateMetadata() is added to the Media interface.
Data model changes
None
Release notes snippet
Adds the ability for users to manually trigger updating metadata on media entities (e.g. updating a more recent YouTube thumbnail).
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | 3_bulk_actions.png | 480.4 KB | marcoscano |
| #24 | 2_operation.png | 346.11 KB | marcoscano |
| #24 | 1_contextual.png | 68.83 KB | marcoscano |
Issue fork drupal-2983456
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
marcoscanoFirst suggestion:
- Create a new action plugin "Update metadata", that will trigger the metadata (+thumbnail) update logic and save the entity. This would be an immediate action, regardless if the type is configured to use queue or not.
- Enable this action in the Bulk Operations dropdown for the media overview page (and media library page)
- Expose this as a contextual link on the rendered entity
- Expose this as a secondary submit button on the edit form
Opinions?
Comment #3
marcoscanoThinking a bit more about this, maybe on the edit form we shouldn't have it. It would be cool to have a button with something like "Fetch metadata", which would just try to retrieve metadata values and populate the form mapped fields, without saving them into the entity, but I guess that's another issue. Having the action that updates and saves the metadata present in the edit form would be confusing because the user may have entered info in mapped fields and it may not be clear what would happen with them when they click "Save" vs "Update metadata". Let's just avoid that route.
So my proposal is:
- Create a new action plugin "Update metadata", that will trigger the metadata (+thumbnail) update logic and save the entity. This would be an immediate action, regardless if the type is configured to use queue or not.
- Enable this action in the Bulk Operations dropdown for the media overview page (and media library page)
- Expose this as a contextual link on the rendered entity
Comment #4
phenaproximaI like your proposal @marcoscano, but I think this will need usability review. Additionally, I think we'll need to block this work on anything except #2878119: Whether queued or not, update the media thumbnail and metadata before beginning the entity save database transaction, since that finalizes the metadata updating API. Therefore, I'm postponing on that issue.
Comment #5
marcoscanoStarting to proof-of-concept this.
Comment #6
chr.fritschI like these ideas. I think it would make sense to use the BatchAPI for updating multiple media items.
Comment #7
marcoscanoSo we realized that views doesn't yet support batch API for bulk operations. Instead of writing our own batch system, we will just wait for that to be solved generically in core, and instead only allow updating the metadata on individual items.
Still needs tests, and probably a re-roll on the latest patch from the other issue, but this is how things look like so far:
Comment #8
seanbLet's link #2603820: [PP-1] Allow selecting all entities in a given page or in every pages for bulk operations.
Do we need to protect this with a CSRF token?
Shouldn't we use something like a destination parameter for this?
Comment #10
deviantintegral commentedA small UX improvement would be if the link text was something like
Update from <source>. "Update from YouTube" seems much more straightforward than "metadata". Possibly even "Refresh"?Comment #12
jweirather commentedWondering/hopeful whether there are any updates here?
I've just updated to 8.7 and these patches don't appear to apply (via composer), and the features do not seem to be integrated OOTB. I do realize it's a moving target with moving parts, etc.
Alternatively, is there an effective workaround to manually update the media thumbnails?
Comment #14
dwwBased on #2878119-135: Whether queued or not, update the media thumbnail and metadata before beginning the entity save database transaction, it sounds like the media maintainers no longer think #2878119 is a good idea, that issue should be won't fix'ed, and we should plow ahead here with just the
updateMetadata()API change for media entities along with all the nice UI additions.This needs work for:
updateMetadata()media_update_8601()Trying to re-roll #2878119 manually really sucked. ;) I'd rather not have to try to do that again. If someone's already got this on a branch that would be "easy" to rebase, that'd be swell. I'd be happy to try to move it forward from there.
Thanks!
-Derek
Comment #15
seanbHere is a good starting point. This is based on 2983456-7-this-patch-only-do-not-test.patch in #7.
I think all we need is some tests (also for the update path to install the new action) and a UX review.
Also decided to not disable the new action in the media/media_library views by default, even though the batch API is not used. In theory updating metadata could be slower than other action, but I don't think this is necessarily a reason not to expose the option to users. I've tried updating 50 youtube video's (since that is all we show on 1 page), and that seemed to work fine, took about 2,5 seconds on my local machine.
Hopefully this helps!
Comment #16
seanbSome more thoughts for further iterations.
Use
foreach (array_keys($this->getTranslationLanguages()) as $langcode)?$this->hasTranslation($langcode)shouldn't be needed.Move this to a new protected
updateMappedMetadatamethod, it is duplicate code (also inprepareSave()).We need to check what to do if the source does not have a thumbnail. The
updateThumbnailmethod uses a default thumbnail when that happens, but not sure if we need additional logic to skip a thumbnail update in that case?Comment #18
dwwThanks, @seanB!
A huge # of those test failures are this:
I'm going to do a quick re-roll to include that and see how much closer to green that gets us. Stay tuned...
Comment #19
dwwUgh, having troubles with my local test environment again. :( Uploading here so the bot can verify the results. Hopefully this should help.
Comment #20
dwwAmazing, that's green. ;)
So, back to NW for:
- Feedback in #16 (which all seems legit and worth fixing)
- Tests
Comment #21
phenaproximaThese don't seem to be used?
I could be wrong, but I think the fact that this is using the entity API means that it should be a post-update function.
This probably needs a better doc comment. :) Also, maybe we should tag it explicitly
@internallike so:I know it's more verbose, but for DI reasons, can we use $this->entityTypeManager()->getStorage()->save()?
We should be using $this->messenger().
I think we can just use $this->getRedirectDestination() here.
I think we usually treat "metadata" as one word, so this should be updateMetadata().
I don't think we should be using $this->translations directly. Classes should use their own APIs. So $this->getTranslations() is preferable.
Can we inject the entity storage handler instead?
Comment #22
marcoscanoworking on this
Comment #23
marcoscano#16:
1) It seems you selected code from
::prepareSave(), while the patch is addingupdateMetaData(), which is probably where that came from? Since both code chunks do the same, I've updated both of them, under the risk of being pushed back for out-of-scope in the first method.2) 👏much better in a separate method!
3) IMHO we shouldn't worry too much trying to skip the update here. To me, a call to
::updateMetadata()is an explicit instruction to "update all you can", even if that means re-detecting that we need to use the default thumbnail...What we could consider doing, if #2878119: Whether queued or not, update the media thumbnail and metadata before beginning the entity save database transaction is indeed a wont' fix, is to remove this todo, which is in that method?
(I haven't done it here, though)
#21:
1) 👍
2) 👍
3) 👍
4) 👍
5) 👍
6) 👍
7) 👍
8) This was fixed when addressing feedback from #16
9) 👍
I will work on the missing tests tomorrow.
Comment #24
marcoscanoLet's see if the testbot likes this.
I also updated the issue summary and added some screenshots of the UI changes.
I'm not sure we need a change record for the new method added to the media interface?
Comment #26
marcoscanosorry, was too optimistic about what the MediaContextualLinksTest was about... Any suggestion about the cleanest way to check the contextual link appears there? Or should we just rely that if the link exists in config, it will be there because that's a separate API that is tested elsewhere?
Comment #27
seanb$should_map_field = $override_existing || ($translation->get($entity_field_name)->isEmpty() || $translation->hasSourceFieldChanged())?Also, we do the
$translation->hasField($entity_field_name)check after $translation->get($entity_field_name)->isEmpty()?Maybe this is even better:
Comment #29
marcoscanoThanks for reviewing!
1. I like your simplification, thanks! I've added an additional inline comment so to make it easier to read that conditional, but no strong opinions if you think it's too verbose.
I also added the contextual test back. It turns out that if we want to assert the contextual links themselves (and @seanb and myself think we should, since the links are provided by the media module), we need to convert the test into a javascript test, and do some javascript-y things to make them appear.
Also, crediting @Lendude who helped me figure out the above. Thanks!
Comment #30
phenaproximaProbably an automatic IDE fix; technically out of scope, but eh...I don't care much.
Nit: Why not simply use Action::create() here?
Is this necessary? For some reason, I was under the impression that the routing system would reflect on the controller method and determine automatically that it expects a media entity. No big deal, just not sure if my info is correct.
🙏
Should probably be "The media item for which to update metadata"?
Hmmm...isn't the whole idea of this issue to add an explicit updateMetadata() method? Wouldn't we call that instead, then save?
Shouldn't we just plain use $this->getRedirectDestination(), rather than checking if a specific URL query parameter is set?
Not a big deal, but I'm not entirely clear on why we would pass $translation into this method? Couldn't we just call $translation->updateMappedMetadata() and have it operate on itself?
Also, I know there's already been some bikeshedding on this, but I'd use "overwrite" instead of "override". Override implies that the previous value is remembered somewhere and can be reverted, but that's not case -- AFAICT, if $override_existing is TRUE, previous values are thrown away forever. That is an overwrite.
Under what circumstances would the field not exist?
This documentation is vague. We should document if, and how, existing values are overwritten here. We should also document how this interacts with translations, and we should say that this does NOT save the media item afterwards.
Comment #31
marcoscanoThanks for reviewing!
1) yeah.. sorry about that, that's me doing cmd-option-O too often so PHPStorm removes unused, that ends up sorting them too... I can roll it back if someone feels strongly about this change, but arguably having this in will prevent the next "me" in the line from adding noise to the patches? 😛
2) 👍
3) I honestly don't know, and I guess this came from the media revision route, that does have that in the route definition. 🤷♂️It's true if we remove these lines things appear to still work, so I just removed them for now.
4) 🙌
5) 👍
6) You are absolutely right! We missed it in one of the recent rerolls / feedback addressing. This also uncovers the lack of test coverage when using the controller. I've fixed the bug here, and I'll be creating a specific test for the controller next.
7) I think the idea here was to be able to send users to the media collection route, if the
destinationparam is _not_ present? Otherwise I believe this would cause a redirect loop?8) This helper method exists because we are trying to avoid some duplication when we need to do the same twice. The trick is, in one of the places this needs to happen inside an already existing loop that is also doing stuff with the
$translation, so I guess it's just simpler this way?I went ahead and replaced "override" with "overwrite", I'm always confused about when to use one or the other...
9) Probably a separate issue, but it turns out we are apparently never using
\Drupal\media\Entity\MediaType::setFieldMap(). This means that if a field gets deleted, we are probably not updating the fieldmap in the database (AFAICT). This is definitely something that should be fixed, but more generically, since the field map doesn't come from entity API, I think it's fair to be safe and only try to use a field we know exists in the entity.10) 👍
Comment #32
marcoscanoNow with a dedicated test for the controller.
Comment #33
marcoscanoNot sure what happened but I managed to mess up with the diffs. Now the correct files, sorry for the noise.
Comment #35
marcoscanoComment #36
marcoscanoAlso worth noting, on #10, @deviantintegral suggested we used better wording for the UI-facing texts.
While I agree that "Refresh from Youtube" is probably more self-explanatory than the current label, I'm afraid it would be very tricky to get this right in a reasonable effort, since "Youtube", in most cases, isn't a media type, but a provider name. Also, on non-remote sources, the "from" terminology might not be the best, such as "Refresh from File", or "Refresh from Image"...
Considering all this, I still think the generic "Update metadata" is a good compromise that is accurate in all scenarios. It could be argued also that users who don't know what "metadata" is (in the context of a media entity) are likely missing out some of the features of the media system, so it wouldn't hurt to let them figure out what that means... :P
Comment #37
bkosborne+1 to this. I need a public API to trigger metadata updates when the source field value has changed. Media module currently handles this automatically but the logic for determining if source value has changed is not quite sophisticated enough to detect certain situations. Specifically in my case, if the file entity for a file-based media entity is updated.
Having this committed would allow my module, Media Entity File Replace, to manually trigger a metadata update.
Comment #38
bkosborneComment #39
fgmOne use case I have on a site and haven't seen mentioned here is having the thumbnail be redefined on the video hosting platform (Vimeo in that specific case), and having to trigger a refresh on site while the URL of the media is constant but the actual thumbnail content changes (or I don't understand what's going on): this would mean not being able to rely on a thumbnail URL to compare whether the managed file association needs to be redone.
Comment #41
hardik_patel_12 commentedRe-rolling patch against 9.1.x-dev, kindly review a patch.
Comment #43
jonathanshawNovice to fix the trivial test fail
Comment #44
ridhimaabrol24 commentedFixing failed tests! Please review!
Comment #45
jonathanshawLooks good, thanks @ridhimaabrol24
Comment #47
vsujeetkumar commentedFixing Fail test, Please have a look.
Comment #49
phenaproximaThis is a major feature request, but also an important one, so I'm bumping priority.
Comment #50
ravi.shankar commentedComment #51
ravi.shankar commentedHere I have tried to fix failed tests and fixed some CS violations.
Comment #53
vsujeetkumar commentedFixing test.
Comment #55
vsujeetkumar commentedFixing test, Please review.
Comment #56
benjifisherUsability review
We looked at this issue at the #3173646: Drupal Usability Meeting 2020-09-29.
Thanks for the screenshots in the issue summary. I guess the main question is whether we can come up with something better than "update metadata" to describe the action.
I am setting the status to NW for a reroll (even though the current patch is less than two weeks old) and an issue summary update.
Not in scope for the usability review, but doesn't an API addition require a change record? I am adding the tag for that.
Comment #57
marcoscanoThanks for reviewing!
I just checked, and there is no reroll needed for 9.1.x, which is where this is would hopefully go, since it's a new feature.
Done
I expanded the documentation over at https://www.drupal.org/docs/8/core/modules/media/creating-and-configurin... to be more explicit about this metadata mapping.
Updated, I hope it's clearer now with examples.
There is no confirmation page for this operation.
Thanks for pointing it out! I'm no expert in change records, but I've given it a try here: #3174553: Added possibility to update metadata on media entities after entities are created Any feedback is welcome!
Thanks!
Comment #58
cbrody commentedGreat work - are there plans for a patch for 8.9.x?
Comment #60
froboy@benjifisher going back to the wording. I see a few notes in #10 and #36 and while 36 raises some technical challenges, I think 10 still has some good thoughts. I disagree with the sentiment in 36 that . IMHO it's our responsibility to meet users where they are.
From 36 is sounds like getting the source (e.g. "YouTube") is hard, but getting the type (e.g. "Video") is possible. I polled/brainstormed with a bunch of end users and content-focused folk on one of my teams with the question:
"Refresh video information" was their consensus. Given the options above I think we could abstract this to "Refresh <type> information".
Given the base media types, this would produce:
which all seem to sound reasonable (to me).
Comment #61
cweagansI tried this patch on my D8 project with media_entity_file_replace and found that the width and height of the images wasn't updated after using the new action on my media item.
Steps to reproduce:
1. Upload 400x400 image
2. See that the sizes in the media__field_media_image and media_field_data table are correct.
3. Replace the image with a 1024x1024 image
4. See that the sizes in those tables are still stored as 400x400
5. Run the action on the media item
6. See that the sizes are still 400x400
This causes issues with Focal Point, which uses those dimensions to figure out what the image should do. For now, I did the dumb thing and just reached into the database and updated the values manually when an image is replaced, but that's definitely not the "right" way to do it. I'm not sure if updated width and height attributes were expected as a result of this issue, but if they were, it's definitely not working.
Comment #62
anmolgoyal74 commentedRe-rolled for 8.9.x
Comment #64
phenaproximaThere's no need to reroll this for 8.9.x -- because it's a new feature, it will not be committed to that branch anyway. :) This is for 9.2.x or later.
Comment #65
marcoscanoComment #66
alexpottReviewing #55
This needs a test.
Let's use the list format - https://www.drupal.org/docs/develop/standards/api-documentation-and-comm...
It's great that this documents that the documentation says the entity thats returned needs saving.
At some point it'd be lovely to know if the entity has changed and therefore if a save is actually necessary. But that's out of scope.
One question I have is are we concerned about data loss through translations being unexpectedly overwritten?
This fails a coding standards check. Need to add
use Drupal\file\Entity\File as FileEntityand then$file = FileEntity::create([$media->enforceMetadataUpdate()->save()whereenforceMetadataUpdate()sets a protected property on the Media entity that is then checked inprepareSave().Comment #67
alexpottGiven the amount of multilingual logic in the code I think we should be testing multilingual media items here.
Comment #68
vsujeetkumar commentedThis patch fixes #66.2 and 66.4.
Comment #70
ankithashettyFixed test failures in #68, thanks!
Comment #71
rosk0Replying to #61 - @cweagans, if I understood you correctly issue of image dimensions not being updated once file is updated/changed is not related to this. Can you please create a new issue for it.
NW for #66.1, #66.3, #66.5 and #67.
Comment #72
rosk0This addresses #66.5 + some code style issues.
Still outstanding: #66.1, #66.3 and #67.
It feels like it should be two separate items/actions: "Update metadata" & "Update thumbnail".
Comment #73
jweowu commentedSome very minor tweaks from looking at the #72 interdiff:
1. Instead of:
I suggest:
2. And instead of:
I suggest generally doing the trivial/cheapest tests first:
Comment #75
kishor_kolekar commentedHey, I have tried to cover the points mentioned in #73
Please review
Comment #78
nikunj.shah commentedI have created Reroll of #75 for 9.3.x-dev. Please review.
Comment #79
steinmb commentedComing here from #3080666: oEmbed system doesn't work if thumbnail url does not have a file extension where Vimeo thumbnails is not correctly getting generated at all. Having an official way of re-generating them is pretty crucial to us.
Comment #80
larowlanthis should go in the list builder, no need to implement a hook for an entity which the module defines already
this is a CSRF vulnerability.
Either we need a CSRF token on the route, or we need this to be a confirm form.
I can do this anywhere on the internet
<img src="https://yoursite.com/media/3/update-metadata" />And if I can trick you into visiting that page, it will force regeneration without your knowledge.
This could lead to server load.
We can't put this in with a security issue in it
Comment #81
pghaemim commentedtrying to cover #80.2 adding csrf token to the "metadata-update" route.
Comment #82
chr.fritschFixing the tests and addressing 80.1
Comment #85
guypaddock commentedI do not understand why
Drupal\Tests\media\Functional\MediaUpdateMetadataControllerTestis failing; when run locally, it passes.Comment #86
guypaddock commentedThis patch is intended to force the test runner to dump out what the page output looks like when it fails, since Drupal Core does not save its browser output on Jenkins.
In all other respects, this is the same as #88 -- just trying to understand what the test runner sees that we do not see locally since the XPath matches locally.
Comment #87
guypaddock commentedTrying again, this time to get passed the code sniffer to get the debug output I need.
Comment #88
guypaddock commentedTest runner... just run the damned tests! I don't care about style right now...
Comment #89
jeroentI've created a reroll of #82 that applies on 9.4.x.
Comment #90
jeroentComment #92
guypaddock commentedThanks, @jeroenT! Hadn't considered just commenting out the inspections for debugging... that makes a lot of sense.
Ok, test runner... let's see if base-64-encoding the HTML gives us the context we crave.
Comment #94
guypaddock commentedInteresting... on Drupal CI the paths for the site have a subdirectory prefix, which explains the test failures:
This does not happen locally. Mystery solved; this should be a quick fix for the tests. Working on that now.
Comment #95
guypaddock commentedOk, added-in the site base path. This is the same as #89 with tests (hopefully) working now.
Also, I am attaching an inter-diff from 88 to this change since one wasn't previously attached. Cross-branch inter-diffs pose an interesting challenge; I am diffing the patches themselves since the changes are minimal. If anyone prefers a better way to get a cross-branch inter-diff, I am all ears!
Comment #96
guypaddock commentedSetting to NR.
Comment #97
ironsizide commentedI have used the patch in #95 with Drupal 9.3.5 and it's working well. Incidentally I am also using the patch from https://www.drupal.org/project/drupal/issues/3042423#comment-14357576 so a hook can pull hires thumbnails as well. The patch on this issue insures that if a video is edited so a higher resolution thumbnail is pulled the queue cam be run immediately and the new thumbnail is hooked up in the filesystem and used for the thumbnail display. Working like a charm.
Comment #98
edurenye commentedIf the video was deleted from YouTube, update metadata does not let you update the metadata, it just deletes the entity.
I wanna keep the video so it just show the usual YouTube box telling you the video was deleted.
Also if the video is not available in your region but is available in others it will remove the entity.
Comment #100
blazey commentedIf anyone's looking for a fix to the issue reported by @cweagans in #61 it's here: #3088168: Media thumbnail dimensions are wrong for YouTube videos.
Comment #101
thetailwind commentedI used the patch #95. It worked once or twice, now the option does not appear in the bulk menu. I tried removing the patch(via composer), updating the db(nothing to change), reapplying the patch, updating the db (nothing to change).
Additionally, sometimes when I run it on the individual media item, I get something like looks like JSON in an expanding text area.
Edit: I got the bulk option back by running this command:
drush ev "include 'core/modules/media/media.post_update.php'; media_post_update_install_update_metadata_action();"Not sure if this is isolated to me, but hope it helps someone else!
Comment #102
glynster commented@GuyPaddock your patch no longer applies:
Patch: 2983456-95-9.4.x.patch no longer applies but after upgrading to Drupal 9.4.4 the following error occurs:
Comment #103
ahebrank commentedHere's a reroll for 9.4.4.
Comment #104
ahebrank commented... and a fix for the style linter.
Comment #105
glynster commentedThanks @ahebrank applies smoothly again!
Comment #106
stijnhau commentedLatest patch works perfectly
Comment #107
anybodyStill the points from #98 need to be addressed to put this back to "Needs review".
What can we do to make progress with the usability review? (Needs usability review tag) Is it still needed for this bulk operation?
Comment #108
benjifisherThe best way to get a usability review is to join the weekly meeting and present the issue.See the #ux channel in Drupal Slack for the schedule.
If you cannot make it to the meeting, then either ping the same channel or add a comment to the issue for the weekly meeting, currently #3310096: Drupal Usability Meeting 2022-09-23 and ask for a review. Either way, make the issue easy to review: make sure the issue summary is up to date, so that people at the meeting do not have to read through the comments to understand the usability questions.
Most of the time, I prefer to have plain text in the "Proposed resolution" section and screenshots in the "User interface changes" section.
Also, review #56 and make sure that all the points raised there have been addressed.
Comment #109
kleve commentedPatch applies but 2 extra folder structures are added as well with the files included in the patch. Is anyone else having this problem? Guessing this is not something that should be happening?
Eg. the following added file
core/modules/media/config/install/system.action.media_update_metadata.yml
Is also added to the following locations
core/b/core/modules/media/config/install/system.action.media_update_metadata.yml
core/core/modules/media/config/install/system.action.media_update_metadata.yml
Using patch from #104
https://www.drupal.org/files/issues/2022-07-30/drupal-add_update_metadat...
Using drupal/core (9.4.7)
Comment #111
duaelfrI've been testing this patch on a 9.x live install and I had issues with the thumbnails update.
If a thumbnail already exists on the Media and we trigger the new update metadata function, the thumbnail is not updated. To make it work we have to:
From an usability point of view, I think that the user should only have to use the update metadata function then see the result immediately.
Comment #113
duaelfrIn the MR:
\Drupal\media\Entity\Media::getThumbnailUri()for force thumbnail update instead of using existing oneIn the attached patch:
Comment #115
duaelfrIn the MR:
\Drupal\media\MediaInterface::isMetadataUpdateEnforced()method\Drupal\media\Plugin\media\Source\OEmbed::getLocalThumbnailUri()to be able to force the thumbnail download\Drupal\media\Entity\Media::updateThumbnail()to flush thumbnail's images styles after updateIn the attached patch:
Comment #116
flyke commented#115 is missing the following use statement:
use Drupal\system\Entity\Action;which throws an error:
Error: Class 'Action' not found in media_post_update_install_update_metadata_action() (line 42 of /app/web/core/modules/media/media.post_update.php) #0 /app/vendor/drush/drush/src/Commands/core/UpdateDBCommands.php(321): media_post_update_install_update_metadata_action(Array)Comment #117
no sssweat commentedComment #118
duaelfr@No Sssweat The patch is only here for devs convenience but the real review has to be made on the !3037 Merge Request.
I checked in the MR and the appropriate
useproperly is included so the change should be effective on D10.As told in #116, the attached patch was faulty. Here is a new one for Drupal 9.5 users.
Comment #119
no sssweat commentedMy apologies @DuaelFr, I was not aware.
Thank you for enlightening me on how the drupal.org review process flows with GitLab these days.
Also, while I am at it, thank you for your contributions!
Comment #120
kjauslin commented@DuaelFr Thanks for the 9.5.x port of the patch in #118. Successfully using this with a custom MediaSource similar to OEmbed. There is one major issues I experience:
In function `GetLocalThumbnailUri` -`$files = $this->fileSystem->scanDirectory($directory, "/^$hash\..*/");`. scanDirectory will get unusably slow for very large number of files in a directory. The default media table use calls the GetLocalThumbnail function for every media. In my case there are 25'000 media and the page is taking a very long time to load. It would be better to use `file_exists` (maybe with fallback for image extensions). What do you think?
Otherwise working really nice.
Comment #121
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #122
gfarishyan commentedPatch for 9.5.3 users.
Comment #123
duaelfrPatch from #122 doesn't apply for me using composer. I could get it to partly apply using the patch utility but then I had fatal errors.
Here is a new reroll for Drupal 9.5.3
Comment #124
socialnicheguru commentedIs there an update hook to install this file? core/modules/media/config/install/system.action.media_update_metadata.yml
Comment #126
joevagyok commentedFor now, I just went through the patch in #123 to identify the reason why the patch doesn't apply.
I found some mix-up in there, namely with Media.php and the media.post_update.php parts. I have taken the gitlab pull request as reference and re-rolled the patch over 9.5.9 version of Drupal core.
Comment #127
joevagyok commentedFixed the spelling error in the #126 patch.
Comment #128
joevagyok commentedFixed assertion for "Update metadata" operation in test and reroll it for D10.0.x.
Comment #129
joevagyok commentedUploading the patch for D9.5.x as well, since #128 fails to apply to that version.
Comment #130
joevagyok commentedComment #131
smustgrave commented#3271688: Remove source from media mappings may be related as I found when using metadata and trading out an image on a media deletes the files.
Comment #132
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #133
jweowu commentedRe-roll of #129 against Drupal 10.1.x.
Comment #134
jweowu commentedRe-roll of #129 against Drupal 10.1.x.
(#133 accidentally included an empty file at a deleted file path.)
Comment #135
steinmb commentedComment #136
jweowu commented#120 is maybe a going concern?
(If that's pre-existing behaviour though, it could be a new issue.)
Comment #137
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #138
rkollerI came across this issue and applied the patch in #134. In general the functionality looks real good and useful. While testing and playing around I've noticed a few details:
1. The status message when running
Update metadataseems solely inform the user that the process started and ran, but not about its potential outcomes:a) You are able to update a media item several times in a row but each time you get the same status message returned:
Updated metadata on media item x. Just based on that status message, I would assume that the media item is getting updated with new changes on every run. But if you take a look at theUpdated-column on/admin/content/mediathe timestamp for the media item remains the same and shows an update event in the past. A discrepancy and disconnect between the status message and theUpdated-column.b) After that I was curious and got inspired by #98 what would be the status message if you update the metadata for a remote video media type's media item where the URL is not reachable because the server is unavailable/down. Not sure if it is a legitimate way to simulate that scenario, but I've simply switched off the WLAN connection while the site was still running locally in DDEV.
In a Safari window I got
You are not connected to the internetfor the URL of the remote video's media item. While when I ranUpdate metadataI've received the same status message "Updated metadata on media item x" and the media item's thumbnail got removed alongside.c) Not sure how likely it is that a local source file is getting deleted and the
Update metadataprocess is run, but I've manually removed the original image of an image media type's media item. Again I've received the status messageUpdated metadata on media item xwhile the thumbnail got removed as in b).I wonder if instead of informing the user that the process updating the metadata got started, would it be more helpful to provide information about the outcome of that process? That way the user would feel more in control. How about the following rough draft, not perfect at all, just wanted to communicate the gist about each scenario:
2. About the main question if there is a better alternative for describing the action compared to
Update metadata? I am uncertain if there is a one or two worded alternative that explains the process clear and unambiguous as a whole. But from my perspective it should be avoided to use loaded terms that might create assumptions, associations, and expectations on the user's end. I think more neutral terms should be used instead preferably. From my perspectiveUpdateas well asMetadataare such loaded terms.Updatesounds familiar in the context of updating for example Core or contrib modules but in the context of entities it feels sort of unusual - in particular for locally stored media items in contrast to the remote video ones. In addition to that the term sort of overlaps withEditone of the other options in the operations drop button. Personally my initial association was either to add something new to a media item and or it might entail additional pro-active manual steps.Metadata, on the other hand, generates certain expectations. For audio you have for example mp3tags for mp3s, for images and locally hosted videos there is EXIF data and documents like PDFs have extensive metadata too. But if you for example try to create a view based on any of the media items it turns out the metadata is mainly about the thumbnail (in Core out of the box only for remote video and image media types) and the metadata attributes (name, filesize, filemime, width, height, etc) as mentioned in the issue summary. That is totally fine but the termmetadatais potentially creating certain assumptions and expectations on the user's end and "might" lead into confusion therefore.The proposed alternative
Refresh(in #10 and #60) for the termUpdatemight be the more clear and neutral choice. From my perspective the termRefreshimplies a more unsupervised and automated process.But in both comments I disagree with the proposed alternative for the term
metadata. #10 suggestsRefresh from Youtubebut as @marcoscano points out in #36 not every media item is from Youtube therefore that suggestion is not applicable. On the other hand going with the labels suggested in #60 I consider those too wordy and it also raises the question what kind information is updated?But I think @devianintegral indirectly provided another viable alternative in #10 from my point of view. Why not use the term
Sourceinstead ofMetadata? The termSourceis more neutral but at the same time would imply that you synchronize your media items based on the informations available in the media item's source file. So how about the following changes?The drop button in the operations column
All options in the select field are single worded, I wonder if it would make sense to stay consistent here?
Bulk action options
For bulk actions I would provide some more context like the other options do and add "from source":
3. As recommended by @benjifisher in #56 https://www.drupal.org/docs/8/core/modules/media/creating-and-configurin... was already added as noted in #57.
But I wonder if it would make sense to create a help topic for the
Update metadatatask alongside. That way the user wouldn't have to leave the admin ui, plus it would be an easy and convenient way to explain the underlaying functionality as well what it entails aka what data is being updated/refreshed for the different media types.Those were just my personal observations. I think it would be still good to discuss the issue, in particular point 2 about the microcopy, in a larger group in the weekly usability meeting (as suggested by @benjifisher in #108).
Comment #139
japerryWe've ran into this bug from a slightly different angle with Acquia DAM. We have implemented our own Metadata Sync controller which will attempt to resave the media entity. However the following code in the media entity ensures that if you change the metadata on the external source, it'll never update Drupal because the actual source asset id hasn't changed.
In the meantime we've copied code from core and manually fixed it in our module. Once this issue is fixed, it'll make that code and our metadata sync controller redundant. So +1 to prioritizing a fix here!
Comment #140
marcoka commentedApplied #134 succesfully
I can "update" single items but the "update metadata" is not avaliable in the batch selection
Edit: My bad, did not see the db updates. Ran drush updb. Everything works fine now #134.
Comment #141
kensae commentedThe patch in #134 failed for Drupal 10.2 on the media.routing.yml file, so I've adapted the patch slightly.
Comment #142
tostinni commentedWe had a problema applying #141 following the change of
getMetada()intogetRawMedatain #3042423: Add new hook to Media module to modify OEmbed metadata #59So here is a patch to apply those changes.
Comment #143
duaelfrPatch from #142 was not applying because it has been created inside the core folder instead of at the root of the project.
This patch solves that issue and applies on 11.x (and 10.2)
Comment #144
duaelfrI rerolled MR !3037 on 11.x based on the code from #134 and #141 (next patches were missing some code).
The attached patch applies on Drupal 10.2
Comment #145
szato commentedThank you for this feature. Using it on D10.2.2.
For us, one issue remains: browser cache. E.g. updating YouTube video media, new thumbnails will be created but with the same hash (file name). If the browser cache is enabled, the new thumbnail will not be refreshed in the browser.
I'm attaching a patch to fix this issue, using timestamp as a suffix for thumbnail files, and care about removing the old ones on the force update. Moved image_path_flush().
The patch was created from MR3037 diff.
FYI: as @klausi noted, the scanDirectory() can become unusably slow if the directory contains many files.
Comment #146
joevagyok commented@szato, we faced the same issue, however we felt changing the logic around the thumbnail name generation might be an overkill and we refrained from solving front-end cache issue by changing the back-end logic.
We have varnish configured on our sites, which further complicates the issue.
So we applied the changedTime of the thumbnail entity to the URI of the image style served, as a get parameter, in an md5 encoded format.
Browser cache relies on the URI too, like varnish does, so cache-busting by get parameter is an acceptable solution which is well separated from the back-end logic of thumbnail generation.
However, we found that the changedTime on the thumbnail entity is not update when we trigger this action, so that might be something to address here!
Comment #147
szato commented@joevagyok, if you use
hook_preprocess_image_style(), then you can usefilemtime($variables['uri'])(the original image file modification time) for changedTime. I think it's better because the entity update time changes every time it's saved again, not just when the file is changed.Comment #149
luke.leberRebased against 11.x -- hopefully the test bot doesn't freak out 😅.
Additionally, the concern brought up in #98 is still valid. Upon manual testing, the following procedure results in data loss:
Comment #150
firewaller commented+1
Comment #151
agentrickardRelated to @japerry's comment in #139, I would note that this approach only handles base field values (string, integer, boolean), and there are cases where it would be important to have source data mapped to, say, a taxonomy term reference field.
The current code can't do that, but I would propose a follow-up issue to make it possible using an event handler.
I can work on that over in #3443757: Mapping metadata to reference field as a proof-of-concept. Posting here to see if there is an existing issue or indeed, a desire for that kind of feature.
Comment #152
recrit commentedNote: the latest MR 3037 does not have the browser cache busting that was added in #145.
Comment #154
karlsheaRebased on 11.x, I added most of #145 except for removing image_path_flush() in Media, that will affect every type not just OEmbed.
Edit: actually I removed #145, it looks like there was some disagreement.
Comment #156
recrit commented@KarlShea
Regarding your comment "I added most of #145 except for removing image_path_flush() in Media, that will affect every type not just OEmbed."
- That seems like an edge case. You would need to have another media type that is using the thumbnail file of an oEmbed resource. The normal usage would be a 1:1 of media to thumbnail file.
Regarding your comment "Edit: actually I removed #145, it looks like there was some disagreement."
There still needs to be a solution for busting cache - browser, edge cache, reverse proxy.
Options so far for cache busting:
1. The thumbnail generation approach as used in patch #145
Pros:
- Busts through all layers of caching - browser, edge cache reverse proxy.
- Automatically deletes the old file and any image styles for the old file.
- ???
Cons:
- A call to "getMetadata" for the "thumbnail_uri" assumes that the thumbnail is being set on the media entity. If it does not update the media, then this would cause deletion of the old file.
- ???
2. Add a modified timestamp URL query parameter as described in #146 and #147
Pros:
- Does not alter the thumbnail generation.
- ???
Cons:
- URL query parameters are not always respected by all layers of caching. For example, edge caching in Akamai could ignore the query parameter for some assets such images depending on the configuration in Akamai.
- Depending on the approach to get the modified time, you could be incurring a file system operation ("filemtime") on every image_style theme rendering.
- ???
Comment #157
duaelfrRerolled !3037 MR against 11.x
Patch attached for people needing this on 10.3.1
Comment #158
queenvictoria commentedHey @DuaelFr applying that patch in 10.3.1 causes update.php to fail with [error] The installed version of the /Media/ module is too old to update. Update to a
version prior to 11.0.0 first (missing updates:
media_post_update_remove_mappings_targeting_source_field).
.
Specifically: removing the following lines allows the database update to pass:
Comment #159
duaelfr@queenvictoria Thank you for letting me know! You're right, I did a mistake rerolling this and making the patch. Here is a new one.
Comment #160
banoodle commentedThank you, @DuaelFr for patch #157 for D10.3.
It applied cleanly and works well, but it introduces the following error when drush updb is run:
"The following update is specified as removed in hook_removed_post_updates() but still exists in the code base: media_post_update_oembed_loading_attribute"
Comment #161
jphelan commentedI was getting the same error as banoodle but patch 159 seems to have resolved it.
Comment #162
banoodle commentedOh, @jphelan, you are correct! I don't know why, but I didn't realize 159 is for 10.3 also. Thanks for pointing this out.
Patch for #159 works perfectly for me.
Comment #163
quietone commentedThanks to everyone for getting this working and to RTBC!
I started triage and immediately saw that the remaining tasks state that a usability review is needed. So, I went through the comments and I do not see a review. Setting back to needs work. I read through nearly all of the comments and noticed some that have not yet been addressed. I have listed those in the 'remaining tasks'.
So, this just needs to work through those items to finish this off.
Comment #164
quietone commentedComment #165
rkollerI've had already added it to our shortlist on #3468437: Drupal Usability Meeting 2024-08-23. But MR3037 needs a rebase, on a none case sensitive file system ( i am on a mac) i run into the following error:
it happens when the issue fork was created or last rebased before this issue went in https://git.drupalcode.org/project/drupal/-/commit/8b368d712d83900765744 on the 13th of august fixing spelling errors. the switch to camel case is the problem where the none case sensite file system in combination with git struggles and leads into this error.
Comment #166
rkollerUsability review
We first discussed this issue at #3475677: Drupal Usability Meeting 2024-09-27. The link to the recording is https://youtu.be/cWtwA63z-IE. For the record, the attendees at the usability meeting were @amazingrando, @anmolgoyal74, @benjifisher, @rkoller, @simohell, and @zetagraph.
We revisited this issue at #3477161: Drupal Usability Meeting 2024-10-04. The link to the second recording is https://youtu.be/JPxvcpNXY0Q. For the record, the attendees at the second usability meeting were @AaronMcHale, @avani.bhut, @benjifisher, @rkoller, @shaal, @simohell, and @zetagraph.
Yesterday we revisited this issue for a third time at #3485024: Drupal Usability Meeting 2024-11-08. The link to the recording is https://www.youtube.com/watch?v=8DqSpKVK768. For the record, the attendees at the usability meeting were @benjifisher, @rkoller, and @simohell.
After taking a look at the current state of the MR, we’ve mainly focused on the points raised in #138, since those cover most of the remaining open questions from an UX perspective, and we’ve assessed their validity and relevance.
1. First, we went through the different scenarios that might happen aside a successful update:
Scenario A (No changes and therefore nothing to update):
It was considered as a nice to have but optional, not a blocker at this point, since it is a difficult task to determine if a media item is changed or not. So we leave it up to the people working on this issue if they want to cover scenario A already within the scope of this issue or if they would prefer to move it to a followup issue. Our consensus for the status message was:
Nothing to update. Media item [x] remains unchanged.In contrast, the other two scenarios should definitely be covered within the scope of this issue, since in both cases content might be removed and/or lost. As Laura Klein stated in her book “Build Better Products” -
. To prevent any potential data loss, like missing thumbnails in the frontend, the group agreed on adding a confirmation step to each of the two scenarios. So that the user becomes aware, that something is off and that they might experience a potential subsequent data loss, when the metadata of a media item is updated from the source. In the case of remote media items, the source might simply be temporarily unavailable due to an outage, just as, for example, source files where the file folder is being mounted from a file system and that file system is unavailable - without a confirmation step, the data would get removed when the metadata is getting updated. Our recommendation for those two cases are as follows:
Scenario B (The local source of the media item is missing):
Description:
The source file for media item [x] is missing, unable to refresh.Buttons:
Remove thumbnailCancelStatus message after...
…the
Remove thumbnailbutton is clicked:Thumbnail removed for media item [x].…the
Cancel-button is clicked:Canceled. Media item [x] remains unchanged.Scenario C (The remote media item the source is unavailable):
Description:
The remote source for media item [x] is unavailable.Buttons:
RetryCancelStatus message after...
…the
Retrybutton is clicked and the refresh was successful:Updated metadata on media item [x], while if the refresh fails, the confirmation form is shown again.…the
Cancel-button is clicked:Canceled. Media item [x] remains unchanged.It has to be noted that we had a clear consensus about the importance of having a status message after a button on a confirmation form was pressed. There is always the possibility that someone is clicking a button on a confirmation form, either absent-minded or by a stray mouse click. The subsequent status message keeps the user in the loop and informed about the made choice.
Aside from the refresh of a single source, there is also the case of refreshing more than one source at once via bulk actions. Question is, how to handle things with more than one case of scenario B, more than one case of scenario C, or even a mix of both? You can’t run someone through a chain of tens of single confirmation pages. One option is that the confirmation pages for scenario B might be combined into a single page, the same as the confirmation pages for scenario C, or all confirmation pages for scenario B and C might be combined into a single confirmation page. But due to the fact that there is no existing UI pattern in Drupal Core yet, we don’t want to hold back the current issue, and we would recommend moving the bulk refresh of media items into a follow-up issue.
2. In regard to the microcopy, we considered the term
Refreshas suggested in #10 to be the more clear and accurate choice.Updateis a loaded term, in combination with the fact that all the other options (edit,delete,translate) on theOperationsdrop-down point to forms on other pages. That way, the user’s assumption might be thatUpdatealso points to a dedicated page or dialogue that entails an active manual interaction. In addition to that, all the other options in theOperationsdrop-down are single-worded verbs. Therefore, we would recommend the following change to theOperationsdrop-down option:Update metadata->RefreshThe term
metadatais also sort of an abstract and ambiguous term in regard to its scope in this context. It is not clear what kind of data is getting refreshed by the optionUpdate metadata. Is it only the associated fields or also something like the thumbnail, as already mentioned in the issue summary. To make things more explicit we would recommend the following change to the bulk action option label in the follow-up issue (again in line with the suggestion in #10):Update metadata->Refresh from source3. We also checked if there were already help topics for the other options available on the media page, but we were unable to find any. So we had the consensus that it wouldn’t be necessary to add any instructions about the
Refreshoption to the help topics at this point.4. One additional detail we’ve noticed during our testing. If you are manually replacing an image in the file system, then hit the
Update metadataoption, the thumbnail is properly updated onadmin/content/media. But if you now click theEdit-button for the media item and then click the link to the source file, the old replaced image is still shown. Could that be a caching issue? We haven’t had the time to investigate in more detail.I am setting the issue to
Needs workand remove theNeeds usability reviewtag. If you want more feedback from the usability team, a good way to reach out is in the #ux channel in Slack.Comment #167
w01f commentedWondering if this improvement will also work for images stored in cloud storage options such as S3, Azure, etc. via modules such as the S3 File System and Flysystem?
Once the images are stored in the external cloud storage, will this still work in capturing exif data on demand for already loaded/saved images and media?
Comment #168
duaelfrRerolled MR on last 11.x.
Made a minor change to help applying this with other patches.
Providing patches for 11.x and 10.5.x for composer.
Comment #170
carolpettirossi commentedThe thumbnail image provided by Vimeo does not get updated when I run update metadata. See the screencast attached for reference.
I'm using this along with the video_embed_field module.
Comment #172
codebymikey commentedAttached a rebased version of the MR that should still works on 11.3.x.
However, the latest version of the MR targeting
mainwill reference API that's only available on 11.4.0 (see https://www.drupal.org/node/3567619).Comment #173
recrit commentedstatic patch of the latest MR 3037
Comment #174
recrit commentedAttached is re-roll of for 11.3.x since the `2983456-media_update_metadata-11.3.x-172.diff` started to fail applying for 11.3.9.
The original patch and MRs have a new `Media::updateMappedMetadata()` method that is causing the conflicts with the latest changes to Media.php in this commit a0601071a0e7ab91dde7ab1389489869951c39f6. For that reason, the attached patch does not use the new `Media::updateMappedMetadata()` . It was only used in one place and will continue to cause conflicts with core.
Comment #175
joevagyok commentedThank you for this patch @recrit. It applies correctly and the feature is working as expected.
Comment #176
rkollerone question to @anybody. you have rebased two MRs recently. which one of the two is the one that should be used, MR3037 or MR8529?
Comment #177
anybody@rkoller sorry I just tried rebasing both, but as !8529 has merge target 10.4.x I guess that's the wrong one, but I'm not sure.
Code looks very similar, so after an interdiff we should probably just close and hide the wrong one to prevent further confusion.