Problem/Motivation
The most basic use case for referencing a media entity from other entities (nodes, users, etc) is through an Entity Reference field.
By default, this field outputs the referenced entity with the "Label" formatter. That's unlikely the preferred option for most users who reference media items from other entities.
Proposed resolution
Hook into the field creation process and define the display to use the "Rendered entity" formatter whenever the field being created is referencing media entities.
Remaining tasks
User interface changes
API changes
Introducing new alter hook hook_field_ui_preconfigured_options_alter
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #45 | interdiff-38-44.txt | 871 bytes | marcoscano |
| #44 | 2928699-44.patch | 14.71 KB | marcoscano |
| #38 | interdiff-36-38.txt | 1.6 KB | marcoscano |
| #38 | 2928699-38.patch | 14.74 KB | marcoscano |
| #36 | interdiff-34-36.txt | 12.51 KB | marcoscano |
Comments
Comment #2
marcoscanoWorking on it.
Comment #3
marcoscanoFirst shot, highly inspired in something similar Lightning does for field widgets :)
Comment #4
phenaproximaLooks great to me! Just needs tests.
Comment #5
seanbI'm just wondering, can we change the order of checking for new fields and entity reference field of type media?
I think the check for media fields is a little more expensive. We could probably return faster when there are no new components.
Comment #6
marcoscanoThanks for reviewing!
This should address #4 and #5.
Comment #7
amateescu commentedIn general we try not to hardcode the 'entity_reference' field type, but use the class and its descendants instead. See
field_field_config_presave()for an example.These are automatically provided by
setComponent()so they can be removed.Is there any reason for not using the region that's already configured in the view display?
Comment #8
amateescu commentedHowever, there is a much bigger problem with the current patch: doing it like this in a presave hook means that we always override the formatter for a newly added component, even when some code sets a specific formatter via
->setComponent($field_name, ['type' => 'my_custom_formatter']).Which makes we wonder.. why are we not doing what was proposed in #2831943-123: Use "rendered media" (not links) as default media field formatter; add modal to configure the used media view mode instead?
Comment #9
marcoscanoOh that's true, thanks for pointing it out.
Starting over then, with the approach of the alter hook.
As far as I could check, the alter hook with the results of
\Drupal\Core\Field\FieldTypePluginManager::getUiDefinitionsas suggested isn't enough, because the entity view display is being configured in\Drupal\field_ui\Form\FieldStorageAddForm::submitFormwith the direct results fromgetPreconfiguredOptions. Firing the hook always after we callgetPreconfiguredOptionsstill allows the module alterations to be preserved forgetUiDefinitionsthough.The attached patch seems to work fine for me. No interdiff because it's completely different from #6.
Thanks!
Comment #10
phenaproximaI like the overall approach in #9. However, I wonder if we need to do it by way of yet another alter hook.
What about this -- could we add a 'common_reference_options' array to the Media entity type annotation, and change EntityReferenceItem::getPreconfiguredOptions() to use that instead?
That way, the common options are still alterable in hook_entity_type_build() or hook_entity_type_alter(), and we don't need to introduce a new hook.
Comment #11
berdirYes, in the pargraphs module, we have this in the annotation:
And that just works, thanks to \Drupal\entity_reference_revisions\Plugin\Field\FieldType\EntityReferenceRevisionsItem::getPreconfiguredOptions. The only problem is with re-using existing fields, but there is an issue for that: #2717319: Provide better default configuration when re-using an existing field.
Comment #12
amateescu commentedTo be honest, I'd prefer the hook approach. #11 shows that's quite a lot of stuff to put in the entity annotation. But I don't have any strong feelings about it so I'll defer to whatever is preferred by the majority :)
Comment #13
phenaproximaYes, in the worst-case scenario. But I imagine that most uses of this functionality would be for very small tweaks that would not add much to the entity annotation at all. So I think it might ultimately be less verbose than a hook.
Comment #14
phenaproximaAlso, to be clear, the approach I suggest can still be hook-based (hook_entity_type_build() and hook_entity_type_alter()). I simply don't favor the idea of adding a new hook just for this. But I can probably be convinced otherwise.
Comment #15
marcoscanoI am no-one to give a valuable opinion :), but I think I would also prefer the alter-hook approach, with the purpose of being more explicit. The new hook is documented in
field.api.php, parsed by IDEs, docs APIs, etc, and clearly indicates what you can do with it. It seems to me that the annotation-based alternative + "generic" hook is harder to discover if you don't know the trick already.Comment #16
chr.fritschI don't favor to add a new hook for this, too. And I would go with the annotations if it doesn't blow them up heavily.
Comment #17
seanbFor most media sources there would be no special settings, for the cases there are, having some extra annotations would be acceptable for me. It's very clear to have everything together.
Comment #18
yoroy commentedLooking at https://www.drupal.org/files/issues/referencing_media_entities.mp4 this is shaping up very nicely.
For an even better default image media view mode I would suggest to order media before name. First show the cat, then show its name :)
Comment #19
marcoscanoSo it seems the majority prefers the annotation-based approach suggested in #10, which is OK for me then :)
However, the same alter hook proposed here would also solve #2862458: [META] Once media is enabled, having the File, Image and Media reference fields all listed is confusing, as shown in #2862458-61: [META] Once media is enabled, having the File, Image and Media reference fields all listed is confusing. I don't know any other alternative way of solving that issue (i.e. having a specific description for the "Media" field on the UI), without this alter hook. Maybe you can help me figure out a way? If so please let me know, I have some availability to move these 2 issues forward with the new approach(es) in the next days.
Thanks!
Comment #20
marcoscanoRe: #18:
Thanks @yoroy for the feedback!
The order of the fileds (title + image) however is part of the default config shipped in the standard profile (not something we are modifying here). In order to change that, IMHO it would make more sense to do it in a separate issue. I have opened #2930788: Do not show name by default in media displays for that.
Thanks!
Comment #21
yoroy commentedthank you @marcoscano, that's very much its own issue then indeed.
Comment #22
marcoscanoThis conversation happened in slack:
TL;DR;
Allowing modules be able to alter the output of
PreconfiguredFieldUiOptionsInterface::getPreconfiguredOptions()would potentially be a good addition in a generic context. As Sean said above, and these two issues (this one and #2862458) demonstrate, there are legitimate use cases for that.Under that perspective, could we give the hook_alter approach another chance? :)
Comment #23
amateescu commentedAs I said before, I'm a fan of the alter hook :) I should have done it myself when I wrote the "preconfigured options" stuff years ago, but there were too many things to do/fix at that time..
Comment #24
seanbI'm convinced, let go with the alter hook. It's useful for at least 2 media related issue at the moment. As mentioned in slack, changing the default form/view display for entity references doesn't sound like an edge case at all. Thanks for taking the time to discuss this marcoscano!
Comment #25
phenaproximaThis looks good and straightforward; just a few small cleanliness things.
$field_definition should also be mentioned in the doc block.
Is it possible to inject the module handler?
Nit: Can there be a blank line between these two "paragraphs"?
$options should be type hinted.
Ditto.
Under what circumstances would $field_definition['id'] be empty?
Comment #26
marcoscanoThanks for reviewing @phenaproxima!
This should address all points from #25.
Comment #28
marcoscanoSorry, the interdiff is not a patch :/
Comment #29
phenaproximaKickass. Back to the land of RTBC we go.
Comment #30
amateescu commentedVery nice progress, this is looking pretty good already. Here's a few points:
Unrelated changes :)
We need to use the fully qualified method name here,
::someMethodName()doesn't make too much sense in the context of an.api.phpfile.I'm not sure it's very useful to pass the entire
$definitionarray, I think passing the field type is enough."Pre-configured options" is a concept of the Field UI module, not the generic Field system, so the hook name should be
hook_field_ui_preconfigured_options_alter.Like I mentioned previously, we shouldn't hardcode the name of the entity reference field type, but get the actual class of the field type and check if the class is an instance of EntityReferenceItem.
See
field_field_config_presave()for an example.Extra empty line here.
Not very happy that we need to fire the alter hook in two places.. this probably means we should have a method on
FieldTypePluginManagerInterfacewhich gets the pre-configured options for a field type and, fires the alter hook and then returns the result.How about sending a new
$widget_settingsparameter instead?Same for
configureEntityViewDisplay().Also, we should have dedicated test coverage for the new hook. We already have a dedicated field type for testing pre-configured options (
\Drupal\field_test\Plugin\Field\FieldType\TestItemWithPreconfiguredOptions), so we should simply be able to alter that by implementing a hook infield_test.moduleand test it in\Drupal\field_ui\Tests\ManageFieldsTest::testPreconfiguredFields.Comment #31
marcoscanoThanks @amateescu for reviewing!
1. Fixed (Feeling sad while doing so, but fixed :)
2. Fixed
3. Fixed (However I feel that passing the whole definition would give implementers more context? For example, it could perhaps help in solving point 5 below in a cleaner way? e.g.
if (is_subclass_of($definition['class'], 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem')) { ...) But I don't feel strongly about it, so I just changed it anyway.4. Fixed
5. Fixed
6. Fixed
7. Fixed (Please feel free to suggest a better name for the new method, not quite happy with it but can't think of anything better.)
8. Fixed
9. Fixed. (I'm having some troubles with simpletest in my local so I couldn't verify the new test, let's see what the testbot says about it. Sorry for that if it doesn't pass.)
Comment #32
marcoscanoAnd now with the files...
Comment #34
marcoscanoFewer failures should happen now
Comment #35
amateescu commentedThanks, @marcoscano, this looks much better now! Here's a few more points that could be improved:
We don't really mentioned anywhere in core that a method invokes an alter hook, so I think we should remove all the mentions of 'alterable' from the method name and its documentation.
Is there any reason to have the field type class as an argument here? We're in the field type plugin manager so we can easily get the field type definition from its ID.
We need to capitalize 'id' here: ".. plugin ID."
As a continuation to the point above, this documentation is actually useful, so let's keep it :)
Instead two conditions we can use
is_a()here.Since the alteration is done by the field type manager, we don't need to inject the module handler anymore here.
Adding
$widget_settingsto this array should be handled in its ownifcondition, based whether a non-empty array was received by the method.Same as above, let's use
is_a().Can't we put this new test inside the existing
\Drupal\Tests\media\Functional\MediaUiFunctionalTesttest class?Comment #36
marcoscanoThanks @amateescu for reviewing!
This should address #35.
Comment #37
phenaproximaLooks quite good! Just a few very small things.
I don't think we need to say "...the alter hook". We can just say "implementing hook_field_ui_preconfigured_options_alter()".
Should say "preconfigured field options".
Can this just say "The field type plugin ID"?
Why do we need the
if (!empty())check?Same here -- why do we need to check if $formatter_settings is not empty?
Comment #38
marcoscanoThanks @phenaproxima for reviewing!
Re: #36.4 and #36.5, unless I misunderstood #35.7, the idea is to avoid unnecessarily adding a
'settings'key with an empty array?Comment #39
phenaproximaOkay, cool. I re-read the patch and can find nothing to complain about :) Let's go back to RTBC.
Comment #40
amateescu commentedLooks good to me as well now. Great work, Marcos!
I'm changing some metadata for this issue because the actual Media part is just the hook implementation. This makes me wonder if we also need a change record..
Comment #41
phenaproximaWe're adding a hook, so I suspect we do.
Comment #42
marcoscanoCreated the draft change record: https://www.drupal.org/node/2932468
Never wrote a CR before, so please feel free to indicate any adjustments needed :)
Thanks!
Comment #43
larowlando we need the $options local variable here, can we just inline it?
Do we want to add settings here too?
Comment #44
marcoscano@larowlan thanks for reviewing!
1. Fixed
2. We don't really need to. The "default" viewmode for media entities is already what we want to render, in most cases, so it's fine to just use the default settings. I originally thought of doing something like:
just as an example for developers, but then realized it doesn't make much sense to add this there if it's not strictly needed.
Did you have something else in mind?
Thanks!
Comment #45
marcoscanoForgot the interdiff for the patch in #44, sorry.
Comment #46
phenaproximaTestbot is happy, so back to RTBC.
Comment #48
marcoscanoTestbot glitch
Comment #49
vijaycs85+1 to RTBC. As the issue introducing new alter hook, we might need a change record?
Comment #50
marcoscanoThanks @vijaycs85!
There is a CR proposal in #42 , please feel free to comment on it if any adjustment is needed!
Comment #51
vijaycs85my bad, CR looks good.
Comment #52
phenaproximaThis is blocking #2862458: [META] Once media is enabled, having the File, Image and Media reference fields all listed is confusing as well.
Comment #53
phenaproximaComment #54
catchQuick note: +1 to the hook over the large annotation.
Comment #55
larowlanAdding review credits for @yoroy (manual testing with screencast), @phenaproxima and @amateescu (reviews) and @seanB (clearly involved in the design and scope as evidenced by IRC conversation)
Comment #57
larowlanCommitted as cf805af and pushed to 8.5.x.
Unpostponed the postponed issue.
Published the change record.