Problem/Motivation

#2831940: Create file field widget on top of media entity is a big issue that's underway to support uploading files to an entity reference field for Media, and currently a blocker for the module to be exposed to users in the UI.

Meanwhile, though, media fields seem bewildering and broken to users who have no clear way to upload or find media they want to put in the media field. (It's an autocomplete field where you can type a keyword to locate the media you want, if the media has already been uploaded.) I think it could be beneficial to provide users some help on how to use the field, even when the module is still hidden.

Proposed resolution

  • Help users see that two actions are possible, either submitting new media or using existing media.
  • Provide links to the pages where they can actually list media and where they can search for it.
  • Use target="_blank" to prevent users from losing work by clicking on the link. This isn't nearly as helpful as #1510544: Allow to preview content in an actual live environment, but it will at least prevent disasters.
  • Since target="_blank" is discouraged from an accessibility perspective, mitigate this by indicating in the text that a new window will be opened.
  • Only show the message about creating new media if the user has access to do so for the types that the field supports.
  • Alter the widget form elements directly and provide a template for the help text so that it can be overridden by sites, themers, or other modules. (This was a recommendation from the usability review.
  • We do not use it as preconfigured options because it needs to be translatable (which a default description would not be). It's similar to the need in #2421001: Fix regression in the link widget where help text does not show: we want to add supplemental information to the users' configured data.

Remaining tasks

User interface changes

Before

The user has no idea what to do with the field unless they're used to entity reference autocompletes.

To address this, we give the user some guidance on their other options, with links (that open in new windows) to the relevant places that will help with those other tasks.

Data model changes

CommentFileSizeAuthor
#123 interdiff.txt1.89 KBeffulgentsia
#116 media-2936293-117.patch21.8 KBxjm
#114 media-interdiff-114.txt4.21 KBxjm
#114 media-2936293-114.patch23.54 KBxjm
#114 media-2936293-114-FAIL.patch23.41 KBxjm
#113 media-interdiff-113.txt7.33 KBxjm
#113 media-2936293-113.patch23.21 KBxjm
#108 2936293-108.patch22.29 KBtedbow
#108 interdiff-102-108.txt1.48 KBtedbow
#107 2936293-107.patch27.16 KBtedbow
#107 interdiff-102-107.txt1.48 KBtedbow
#102 media-interdiff-102.patch11.09 KBxjm
#102 media-2936293-102.patch22.26 KBxjm
#99 media-interdiff-91.txt1001 bytesxjm
#99 media-2936293-91.patch18.58 KBxjm
#98 media-interdiff-98.txt6.28 KBxjm
#98 media-2936293-98.patch18.54 KBxjm
#91 descriptions.png153.86 KBxjm
#90 media-interdiff-90.txt2.66 KBxjm
#90 media-2936293-90.patch18.24 KBxjm
#89 link_with_custom_description.png44.1 KBxjm
#89 link_markup_no_custom_description.png98.29 KBxjm
#89 link_no_custom_description.png35.43 KBxjm
#88 Create_Article___Site-Install.png48.84 KBxjm
#83 media-2936293-83.patch18 KBbenjifisher
#83 interdiff-2936293-80-83.txt1.28 KBbenjifisher
#80 media-interdiff-80.txt1.41 KBxjm
#80 media-2936293-80.patch18.1 KBxjm
#76 unlimited.png91.39 KBxjm
#76 limited_multiple.png83.32 KBxjm
#76 single.png72.35 KBxjm
#74 media-interdiff-73.txt8.01 KBxjm
#73 media-2936293-73.patch24.16 KBxjm
#70 media-widget-text.png87.28 KBsamuel.mortenson
#58 media-interdiff-58.txt3.16 KBxjm
#58 media-2936293-58.patch22.55 KBxjm
#58 media-interdiff-58.txt3.16 KBxjm
#58 media-2936293-58.patch22.55 KBxjm
#56 media-interdiff-56.txt14.31 KBxjm
#56 media-2936293-56.patch22.54 KBxjm
#51 media-interdiff-51.txt19.62 KBxjm
#51 media-2936293-51.patch20.74 KBxjm
#50 2936293-49.png143.19 KBphenaproxima
#50 interdiff-2936293-47-49.txt8.01 KBphenaproxima
#50 2936293-49.patch18.36 KBphenaproxima
#47 media-46-interdiff.txt5.54 KBxjm
#47 media-2936293-46.patch18.62 KBxjm
#42 2936293-41.patch17.04 KBtedbow
#42 interdiff-40-41.txt2.22 KBtedbow
#40 media-2936293-40.patch17.01 KBxjm
#26 multiple_media_field_wrapper_before_fix.png204.85 KBershov.andrey
#26 interdiff-2936293-25-26.txt1.46 KBershov.andrey
#26 2936293-26.patch20.19 KBershov.andrey
#26 multiple_media_field_wrapper_after.png79.49 KBershov.andrey
#25 interdiff-16-25.txt13.51 KBmarcoscano
#25 2936293-25.patch20.1 KBmarcoscano
#25 improved_descriptions.png45.07 KBmarcoscano
#16 autocomplete_new_descriptions1.png65.43 KBmarcoscano
#16 autocomplete_new_descriptions2.png58.99 KBmarcoscano
#16 autocomplete_new_descriptions3.png51.91 KBmarcoscano
#16 interdiff-9-16.txt11.62 KBmarcoscano
#16 2936293-16.patch11.56 KBmarcoscano
#9 docs-interdiff.txt493 bytesxjm
#9 media-2936293-9.patch10.74 KBxjm
#5 media-2936293-5.patch10.74 KBxjm
#2 media-widget-help-hotfix.patch10.82 KBxjm
widget_after.png95.3 KBxjm
widget_before.png91.12 KBxjm
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

xjm created an issue. See original summary.

xjm’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +Needs tests
FileSize
10.82 KB
xjm’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 2: media-widget-help-hotfix.patch, failed testing. View results

xjm’s picture

FileSize
10.74 KB

Just a merge conflict with a commit in HEAD this morning; fixed here.

xjm’s picture

Status: Needs work » Needs review
xjm’s picture

Issue summary: View changes

Status: Needs review » Needs work

The last submitted patch, 5: media-2936293-5.patch, failed testing. View results

xjm’s picture

Status: Needs work » Needs review
FileSize
10.74 KB
493 bytes

Thanks, testbot, for checking the syntax of my documentation example.

tedbow’s picture

Use target="_blank" to prevent users from losing work by clicking on the link. This isn't nearly as helpful as #1510544: Allow to preview content in an actual live environment, but it will at least prevent disasters.

Why not open this link in the off-canvas dialog instead? The dialog itself is no longer experimental.

The primary point of concern will be the links, since they take the user out of the context of their form. Is the target="_blank" a reasonable tradeoff for providing users a direct link to the pages?

They would remain in context.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

cilefen’s picture

Title: At least inform content aurthors where they can list and add media » At least inform content authors where they can list and add media
xjm’s picture

Regarding #10, that sounds more like a proposal for the main issue in #2831940: Create file field widget on top of media entity (and I think the Media Library would benefit from using offcanvas). It probably has some of the same pros and cons as using a modal. For this issue though I'm hoping to get something hotfix-ish in that will help a little sooner rather than later, since the widget issue is both difficult and risky.

webchick’s picture

Issue tags: +Needs usability review

Tagging for UX team review.

Gábor Hojtsy’s picture

The before/after screenshots only show the single form case, not the multivalue form case. Would be nice to see that. Comments on the text/behavior:

  1. +++ b/core/modules/media/media.module
    @@ -172,3 +173,99 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    $element['target_id']['#title'] = t('<h4>Use existing %title media</h4>', ['%title' => $label]);
    ...
    +    $elements['#title'] = t('<h4>Use existing %title media</h4>', ['%title' => $label]);
    

    I would not add "media" on the end of this. We should look at which media type names would need that tacked on to be meaningful. The one screenshot definitely does not need it IMHO, it looks distracting and computer generated.

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +173,99 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    $reuse_message = t('Type part of the media name. See the <a href=":list" target="_blank">media list</a> (opens a new window) to help locate media.', [':list' => Url::fromRoute('entity.media.collection')->toString()]);
    

    Can we filter for the right media type(s)? Otherwise people need to figure out there how to do it.

marcoscano’s picture

I love this issue!

IMHO, the target="_blank" is a very reasonable tradeoff, and justifiable in the context of the hotfix this is intended to address.

In this patch I have:
- Found that the new hook was only being invoked for cardinality -1, so other multiple fields were not getting the text. Tried to fix it, it appears to work now for me.
- Tweaked a bit the hook documentation in field.api.php
- Fixed some minor CS issues
- Found that the new text can get be confusing if the previous field also has a multiple-line description. Maybe we could wrap everything inside a fieldset container to make more obvious that all this text is from a single field?
- Addressed #15.1

- About #15.2:

Can we filter for the right media type(s)? Otherwise people need to figure out there how to do it.

Strictly speaking, the site could have disabled views, and in that case the collection route doesn't have filters. We could add some logic that sends to different links depending if Views is installed or not, but maybe that would be overkill? IMHO I believe it is safe to assume at this point that most users know how to use exposed filters? (or I may have completely misunderstood your point, please correct me if so).

Some screenshots:

Patch in #9:

Patch in #9 but invoking the hook also for non-unlimited cardinality fields:

Adding wrappers and addressing #15.1:

Still needs tests, I can work on that if we all agree on how it should look like.

seanB’s picture

This seems like a really good idea! Have a bunch of nits and suggestions to change some interface texts.

Besides that it at least needs tests for the new hook and making sure the description is shown for media entity reference field (and not shown for other entity reference auto complete fields), but I see it's already tagged accordingly.

Leaving to "needs review" for now to get more opinions.

  1. +++ b/core/modules/field/field.api.php
    @@ -221,6 +223,77 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
    + * To adjust the individual widgets for the values themselves, use
    

    I'm kind of surprised about this. We should probably add documentation to hook_field_widget_form_alter() to show that this hook exists as well.

  2. +++ b/core/modules/field/field.api.php
    @@ -221,6 +223,77 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
    + * To modify the widget for individual itesm, use
    

    Typo 'itesm'

  3. +++ b/core/modules/media/media.module
    @@ -172,3 +173,109 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  // On autocomplete widgets, add some help text to aid users know what to do.
    +  // Only act on entity reference fields that point to Media entities.
    

    This sentence feels a little weird to me? Maybe it's because English is not my first language.

    Could we change it to:
    Add a description to inform users where they can find and add new media. Only add the description on autocomplete widgets for entity reference field pointing to media.

    Feel free to ignore this if it doesn't make any sense.

  4. +++ b/core/modules/media/media.module
    @@ -172,3 +173,109 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +
    

    We can remove this blank line I think.

  5. +++ b/core/modules/media/media.module
    @@ -172,3 +173,109 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    $reuse_message = t('Type part of the media name. See the <a href=":list" target="_blank">media list</a> (opens a new window) to help locate media.', [':list' => Url::fromRoute('entity.media.collection')->toString()]);
    

    Again, English is not my first language but shouldn't "Type part" be "Type a part"

  6. +++ b/core/modules/media/media.module
    @@ -172,3 +173,109 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    // Only add the suffix if the user also has permission to create media. Some
    +    // sites might allow content authors to pick approved media but not to
    +    // submit their own.
    

    Can we show the message about the media list only once as well? Repeating that seems just as "spammy". Maybe something like:

    Type a part of the media name. See the media list (opens a new window) to help locate media. Create new media via the media add page (opens a new window), then add it by name to the field below.

  7. +++ b/core/modules/media/media.module
    @@ -172,3 +173,109 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +      $new_message = t('<h4>Uploading new %title</h4> Upload your media on the <a href=":add" target="_blank">media upload form</a> (opens a new window), then add it by name to the field below.', ['%title' => $label, ':add' => Url::fromRoute('entity.media.add_page')->toString()]);
    

    I proposed some small changes above. Mainly "upload" is not always applicable (for remote video for example). The link is to the media add page and not a media form, so that could be changed as well to avoid confusion.

xjm’s picture

Thanks @seanB, @marcoscano, and @Gábor Hojtsy! All good points.

For #17.1, the patch is also adding an @see to the other hooks, unless I've misunderstood.

For #17.5, "Type part of" and "Type a part of" can be used interchangeably. I'd suggest sticking with the shorter version even if it's only one character shorter. :)

xjm’s picture

Can we filter for the right media type(s)? Otherwise people need to figure out there how to do it.

I think this could be a followup issue since Views filters are fairly intuitive. However, what we might want to do is add Allowed media types: foo, bar to mitigate the "WTF I uploaded my 'Kitten video' media; where is it?" if the field only accepts 'Puppy video' media.

xjm’s picture

+++ b/core/modules/field/field.api.php
@@ -221,6 +223,77 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
+function hook_field_widget_multiple_form_alter(array &$elements, \Drupal\Core\Form\FormStateInterface $form_state, array $context) {

It might also be possible to do this by modifying the other hook in a BC way rather than adding API, but let's see what the UX team says before we spend time on that. :) (Ditto on tests.)

ckrina’s picture

Discussed in the UX calls and it looked fine for us as an MVP. The target="_blank" might not be the best solution, but the help text makes it good enough for MVP.

@roland.molnar mentioned that maybe some more text explaining how to extend the basic functionalities could help. One possible location might be Drupal's help.

Also it was suggested to add some more text in the description of the module, right now is: 'Create reusable media.'. But maybe it can be a followup issue.

DyanneNova’s picture

I think this makes sense for an MVP. I agree that target="_blank" isn't ideal, and that a Settings Tray dialogue would be better, but think this works in the interim.

My one nitpick is that I think "Upload new Photos and videos media" makes more sense than "Uploading new Photos and videos media" to match the wording of "Use existing Photos and videos media" vs "Using existing Photos and videos media"

tstoeckler’s picture

Adding this new hook is a great idea. I cannot overstate how excited I am about this idea. It is incredibly useful for very many different use-cases and a lot of new room for experimentation in contrib. Let's add this in a separate issue, though, and get a sign-off from one of the Field API maintainers ( === ['@amateescu'] ) please.

webchick’s picture

We reviewed this on the weekly Drupal Product Management call, and though there was much hand-wringing and gnashing of teeth, agreed with this as a stop-gap for the current behaviour to unblock exposing the module in the UI, since it is easily 3,000% better than what's in HEAD right now. (Though UX-wise, still not remotely comparable to even our most basic competitors out there, so we definitely have more work to do. :\)

marcoscano’s picture

Not sure if I covered all feedback, but this patch should address #17, #19, #22 and adds some tests.
Did not investigate the possibility of skipping the new hook (#20) because I feel there is some interest also outside of media to have it available? (based on #23)

Also, I think I would question the perception that the description text below each autocomplete element is spammy... Users tend not to read stuff. However, when they are trying to type something they are not sure what it is, it will be *certainly* read. Actually, I have the feeling that this is probably the most important piece of text that we are adding in this patch, so I would try to leave it there, even at the price of being repetitive if the field is multi-valued.

Please let me know if I missed something!

ershov.andrey’s picture

While testing patch from #25 I found that each time you add new item to the multi-value media field there is another fieldset added.
Before

So I've moved the fieldset creation code to the top of the alter function and now it's working as expected.
After

xjm’s picture

"Media multiple" indeed. :) Nice work @ershov.andrey!

xjm’s picture

Priority: Normal » Major

Promoting to major since this is now essentially the last blocker to make the core media module available to non-expert site builders.

xjm’s picture

Assigned: Unassigned » xjm

The most recent patch seems to have introduced:

Notice: Undefined index: #prefix in media_field_widget_multiple_entity_reference_autocomplete_form_alter() (line 281 of core/modules/media/media.module).

(That was with articles, cardinality 3; otherwise just Standard and Media out of the box.)

I'm working through debugging that now. Probably should also add to the tests for that. ;)

@tstoeckler and @marcoscano regarding the hook: hook_field_widget_form_alter() and hook_field_widget_WIDGET_TYPE_form_alter() already exist; they were added in #1204230: Missing hook_field_widget_form_alter(). I know this because that was my very first core issue. :) When it was added it could alter both single- and multi-value elements. However, since 8.0.0 shipped like this, we need to provide BC for the current behavior. That's why I started by hacking together a new hook. (So there are four of them here, rather than two.)

Agreed on the separate issue scope though for fixing that; I just included it here for the POC and didn't want to do additional work until the UX and Product teams had signed off.

xjm’s picture

xjm’s picture

Assigned: xjm » Unassigned
Status: Needs review » Needs work

Not actually debugging at the moment in case someone else wants to pick it up.

The code can probably be cleaned up a bit. We should also probably actually create a proper Twig template rather than concatenating a bunch of markup into Markup objects. (I didn't add this in the original patch because I just wanted to hack together something for UX review/testing.) Actually, adding the template will clean up the code in and of itself so try that first. :)

xjm’s picture

Issue summary: View changes

Ah and we also need a test to verify #26 does not happen.

xjm’s picture

Issue summary: View changes
xjm’s picture

Issue summary: View changes
xjm’s picture

Oh, forgot to mention that the notice in #29 is on the field add page in the Field UI (when it renders the widget for default values), not the node edit form.

Aside: adding a template will also address another concern that came up in the Media UX meeting, that they would not show this help text to a client and would instead use applicable contrib. If we add a template rather than hardcoding all this, modules/themes/sites can override it however they like.

xjm’s picture

Issue tags: -Needs usability review

Oh, this got its UX review already. Thanks reviewers!

xjm credited amateescu.

xjm’s picture

@amateescu reviewed #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields, which inadvertently included part or all of this issue. Oops. Here are the relevant points from his review that are not about the hook:

  1. +++ b/core/modules/media/media.module
    @@ -172,3 +173,125 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  if (!empty($element['target_id']['#type']) && ($element['target_id']['#type'] === 'entity_autocomplete') && ($element['target_id']['#target_type'] === 'media')) {
    

    Since this hook is altering a specific widget (entity_reference_autocomplete), we don't need to check the #type of the form element.

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +173,125 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +function media_field_widget_multiple_entity_reference_autocomplete_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
    

    The entity_reference_autocomplete widget does not handle multiple values, only entity_reference_autocomplete_tags does, so I assume this hook implementation is broken?

And as a general observation, the two hook implementations are duplicating quite a bit of non-trivial code (like access checking), is there a way to re-use some of that code?

Also crediting him for the review that's applicable to this issue.

xjm’s picture

Assigned: Unassigned » xjm

I'm working on the template implementation (or trying to) and also testing out a modified approach based on feedback in #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields.

xjm’s picture

Here is a (broken) patch that starts putting together a template. I copied the template from core/themes/classy/templates/form/field-multiple-value-form.html.twig, but it seems to be missing some of the variables that has, so it renders everything except the actual widget. I couldn't figure out how to add them without creating infinite recursion. :P Maybe I should be adding a theme suggestion or something?

tedbow’s picture

Status: Needs work » Needs review

Ok looked at the example the system block and what it does in system_theme

'block__system_branding_block' => [
      'render element' => 'elements',
      'base hook' => 'block',
    ],

Ad then it adds the extra stuff it needs in system_preprocess_block()

This seems to be what we need to do.

So I added media_preprocess_media_reference_help and added the are extra info there.

It seems to work.

tedbow’s picture

The last submitted patch, 40: media-2936293-40.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 42: 2936293-41.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

xjm’s picture

Thanks @tedbow!

Working on fixing the last bits now.

xjm’s picture

Assigned: xjm » Unassigned
Status: Needs work » Needs review

Okay, the attached patch finishes wiring this back up with a template instead of the wild, tangled jungle of render array alteration. :) We do still want to alter the actual element title from within our alter hook so that it appears in the correct place on the element's form. Next steps are:
Add back the access checking
Round out the tests.
Look into #38 more.
Finish tests for the blocker and get that in first so this patch can be rerolled on top of that.

Interdiff also adds the cardinality context from the latest direction in #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields, which was not included yet in the recent patches here. Edit: fixed a wrong issue link.

xjm’s picture

Status: Needs review » Needs work

The last submitted patch, 47: media-2936293-46.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

xjm’s picture

Assigned: Unassigned » xjm

I'm cleaning the test up a bit to use a data provider.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
18.36 KB
8.01 KB
143.19 KB

This should fix the tests. The assertions were quite out-of-date and looking for elements that didn't exist. Also DRYed things up a bit.

And here's a screenshot of the test running in Chrome:

The test, in Chrome

EDIT: I'd been working on this for about an hour before @xjm posted her comment, so hopefully this doesn't step on anyone's toes!

xjm’s picture

So on #50 I'd already been working on my version for a few hours, although we did make a couple similar changes. Here's what I did:

  • Add back the access handling for the media creation and listing.
  • Moved the test from the JS test to the functional test. While the test for the field add form help text needs JS, this one does not.
  • Rather than creating multiple fields on the same content type, use a data provider to thoroughly test a bunch of scenarios.

One other test that could be added is testing the button to add another element, which we could add as only one test in the JS test. Not necessarily blocking though.

Interdiff is against my earlier patch (sorry, I was working on this on and off all day).

xjm’s picture

I'll work a little more on cleaning the test up, inspired by @phenaproxima's patch.

davidhernandez’s picture

+++ b/core/modules/field/field.api.php
@@ -220,6 +222,77 @@ function hook_field_widget_WIDGET_TYPE_form_alter(&$element, \Drupal\Core\Form\F
+/**

+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -0,0 +1,60 @@
+
...
+

These spaces don't need to be here.

+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -0,0 +1,60 @@
+ * @todo I have no idea what I'm doing.

Lies and damn lies.

So, maybe it's just me, but something doesn't smell right. Do we ever put this much text in a template in core?

davidhernandez’s picture

I haven't applied this and gone through all the comments, but are we trying to make this consistent with the core fieldset template? If so, the fieldset element should have an attributes object and the label should have a wrapping span for the label text.

phenaproxima’s picture

Status: Needs review » Needs work
Issue tags: -Needs tests

This seems pretty damn good to me. The tests are quite thorough so I'm removing the tag.

  1. +++ b/core/lib/Drupal/Core/Field/WidgetBase.php
    @@ -311,12 +324,14 @@ public static function addMoreAjax(array $form, FormStateInterface $form_state)
       protected function formSingleElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    +      $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
         $element += [
    

    Nit: $cardinality should be outdented by two spaces.

  2. +++ b/core/modules/media/media.module
    @@ -66,6 +67,10 @@ function media_theme() {
    +      'base hook' => 'field_multiple_value_form',
    

    I don't understand what this does, so I assume it's necessary...

  3. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  if (!empty($elements[0]['target_id']['#type']) && ($elements[0]['target_id']['#type'] === 'entity_autocomplete') && ($elements[0]['target_id']['#target_type'] === 'media')) {
    

    Nit: The final two conditions are surrounded by superfluous parentheses.

  4. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    $use_existing_label = t('Use existing %title', ['%title' => $label]);
    

    Would it make more sense for $label to be the plural label of the target entity type?

  5. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +function media_preprocess_media_reference_help(&$variables) {
    

    $variables should be type hinted.

  6. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +      if (\Drupal::entityTypeManager()->getAccessControlHandler('media')->createAccess($bundle, \Drupal::currentUser())) {
    

    We don't need to pass \Drupal::currentUser() to the createAccess() call.

xjm’s picture

Status: Needs work » Needs review
FileSize
22.54 KB
14.31 KB
  1. Discussed some of the above with @davidhernandez. The places to compare for the fieldset markup and attributes are:
    core/themes/classy/templates/form/fieldset.html.twig
    and
    template_preprocess_fieldset() in core/includes/form.inc
  2. Regarding:

    So, maybe it's just me, but something doesn't smell right. Do we ever put this much text in a template in core?

    We don't generally,. We are adding it to the template here because we want to allow sites/themes/etc. to override all this. We could construct some of the various strings in the preprocess as well if needed; I just liked how nice and readable it was with the template and that themers could customize their own template and text entirely. This is very much not my area of expertise though so it could be better to assemble the longer strings in the preprocess and pass them in. I might look at that next.

  3. I don't understand what this does, so I assume it's necessary...

    Me neither but Ted added that and it made it work so... :D

  4. Nit: The final two conditions are surrounded by superfluous parentheses.

    I prefer them for readability when there are comparisons of long things, though not super fanatical about it. :) I've left it for now.

  5. Would it make more sense for $label to be the plural label of the target entity type?

    Deliberately did not do this. :) Translating plurals within another string is fraught because in many language the plural depends on where it is in the sentence etc. So we should avoid it where it's not strictly necessary.

  6. $variables should be type hinted.

    @davidhernandez said we haven't done this historically so I have left that out. :)

Attach refactors the tests more and also addresses #53 and #55.1 and 6. #54 is not yet addressed, nor the general question about what strings to put where.

The interdiff for the test is a bit messy because I moved some lines around, so probably easier to review the test as a whole.

phenaproxima’s picture

Status: Needs review » Needs work

That test is great. I really like it. Super thorough, and clear too!

  1. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,294 @@ public function testRenderedEntityReferencedMedia() {
    +    $this->assertEquals($field->getLabel(), $fieldset->find('css', 'legend')->getText());
    

    Should probably use assertSame() when checking strings; there's no real reason not to. We should also assert the legend exists (rather than courting fatal errors by assuming it does), like this:

    $this->assertSame($field->getLabel(), $this->session->elementExists('css', 'legend', $fieldset)->getText());

  2. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,294 @@ public function testRenderedEntityReferencedMedia() {
    +  /**
    +   * Asserts that the given texts are present exactly once.
    +   *
    +   * @param string[] $texts
    +   *   A list of the help texts to check.
    +   * @param bool $expected
    +   *   Whether or not the text is expected.
    +   */
    +  public function assertHelpTexts(array $texts, $selector = '') {
    

    Doc comment seems to be out of date :)

  3. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,294 @@ public function testRenderedEntityReferencedMedia() {
    +        $this->session->elementsCount('css', $selector . ":contains('$text')", 1);
    

    What if $text contains apostrophes/single quotes? Should we escape it first?

  4. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,294 @@ public function testRenderedEntityReferencedMedia() {
    +  /**
    +   * Asserts that a given link is not present.
    +   *
    +   * @param \Behat\Mink\Element\NodeElement $element
    +   *   The element to search.
    +   * @param string $text
    +   *   The link text.
    +   */
    +  protected function assertNoHelpLink(NodeElement $element, $text) {
    +    $this->assertHelpLink($element, $text, [], FALSE);
    +  }
    

    Not a big deal, but it seems weird for this to be a wrapper around assertHelpLink(). It could just be as simple as:

    $this->session->elementNotExists('named', ['link', $text], $element)

xjm’s picture

Attached addresses ##57. #54 is not yet addressed and the template could also use some accurate documentation of the available variables.

tedbow’s picture

Here is patch that just shows the media changes for review as the field API changes are being worked on in #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields

Look through @phenaproxima review in #57

All fixed.

For 4) \Drupal\Tests\media\Functional\MediaUiFunctionalTest::assertNoHelpLink no has another check so I think it should not be removed now.

tedbow’s picture

Status: Needs review » Needs work
  1. Re #55.2

    I don't understand what this does, so I assume it's necessary...

    and

    Me neither but Ted added that and it made it work so... :D

    Oh no!
    See #41 for where I got this idea from. I think some who knows the theme system better me to confirm that this is the proper way to do this.

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    foreach ($bundles as $bundle) {
    +      if (\Drupal::entityTypeManager()->getAccessControlHandler('media')->createAccess($bundle)) {
    +        $create_access = TRUE;
    +      }
    +    }
    

    We should add a break here after $create_access = TRUE;.

    We just need to know if the user has access to create 1 bundle. Check this access could be expensive if there are implementations of hook_entity_create_access

  3. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    if ($create_access === TRUE) {
    +      $variables['media_add_page'] = Url::fromRoute('entity.media.add_page')->toString();
    +    }
    

    If the user has access to add only 1 bundle then we should probably make the link to the add page just for that bundle to avoid confusion.

    The user could access only 1 bundle for this field but then other bundles that can't be referenced here.

  4. +++ b/core/modules/media/media.module
    @@ -172,3 +177,54 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    if (\Drupal::currentUser()->hasPermission('access media overview')) {
    

    Would it be better to check access against the actual route like
    Url::fromRoute('entity.media.collection')->access()
    Then if access on the route is altered this would be picked up. Not positive on this but it seems more robust.

tedbow’s picture

Addressing #60

  1. Not fixed
  2. Added the break but it changed to not use $create_access but rather $create_bundles because we need to keep track of whether the user has access to create 0, 1 or more than 1 bundles.

    So breaking on count($create_bundles) > 1

  3. Fixed use route entity.media.add_form if the user has access to create just 1 bundle
  4. fixed

The last submitted patch, 61: interdiff-58-61.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 61: 2936293-61.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tedbow’s picture

Status: Needs work » Needs review
FileSize
23.45 KB
4.47 KB

In #61 I forgot to update the tests. So this patch does:

  1. Updates the tests to check for the different route if the user can only create 1 media type
  2. Updates \Drupal\Tests\media\Functional\MediaUiFunctionalTest::providerTestMediaReferenceWidget to use keyed indexes because this is easier for debugging and test error results
  3. Fix a couple unused variables in \Drupal\Tests\media\Functional\MediaUiFunctionalTest::testMediaReferenceWidget
xjm’s picture

Assigned: xjm » Unassigned
FileSize
23 KB
1.56 KB

Latest proposal in #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields is to not include the cardinality in the context and just reference it from the form element array. So just making sure that works here.

Status: Needs review » Needs work

The last submitted patch, 65: media-2936293-65.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tedbow’s picture

Status: Needs work » Needs review
FileSize
592 bytes
23 KB
592 bytes
23 KB

Just a typo in variable name in #65

xjm’s picture

+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -0,0 +1,57 @@
+    {% trans %}
+      Create your media on the <a href="{{ media_add_page }}" target="_blank">media add page</a> (opens a new window), then add it by name to the field below.
+    {% endtrans %}
...
+  {% else %}
...
+      {% trans %}
+        See the <a href="{{ media_list }}" target="_blank">media list</a> (opens a new window) to help locate media.
+      {% endtrans %}

BTW per @davidhernandez's suggestions, we could move these two strings into variables and that would be a more normal amount of text in the template. (I do think the headers belong in the template for sure.)

xjm’s picture

Going to work more on that and on the other template improvements @davidhernandez suggested. Also just realized I accidentally left the issue assigned to myself, but re-assigning now. :)

samuel.mortenson’s picture

FileSize
87.28 KB

This is pretty good, and is an improvement on the standard entity reference field. Nice job 👍

1. One thing I noticed is that the name of the field is used for the "Create new ..." and "Use existing ..." text, which looks OK when the field is named something like "Media", but when you use something more specific (see below), it can look overly repetitive (and may be grammatically incorrect, i.e. "Create new "Vacation pictures" media").

Instead of using the field name, could we use the label of the bundle if only one bundle is targeted, or just "media" if multiple bundles are targeted?

2. The "Create new ..." text uses an h4 tag, which makes it larger than the "Use existing ..." label. Is this intentional? Could we just a strong tag instead?

3. The "Allowed media types ..." text uses the machine name of the Media types, instead of the label. Would look a bit nicer to use the label.

Example for this comment:

xjm’s picture

The "Create new ..." text uses an h4 tag, which makes it larger than the "Use existing ..." label. Is this intentional? Could we just a strong tag instead?

Not intentional. TBH I did not even notice. :) I think the h4 is more semantic (and also what we use elsewhere within fieldsets) but we can probably style the tag to match the legend.

xjm’s picture

Oh ah, regarding:

1. One thing I noticed is that the name of the field is used for the "Create new ..." and "Use existing ..." text, which looks OK when the field is named something like "Media", but when you use something more specific (see below), it can look overly repetitive (and may be grammatically incorrect, i.e. "Create new "Vacation pictures" media").

Instead of using the field name, could we use the label of the bundle if only one bundle is targeted, or just "media" if multiple bundles are targeted?

This is a pretty great idea actually. The fieldset legend already provides the title, and we already call it "media" elsewhere including elsewhere in the patch. I think we could probably just use "Create new media" and "Use existing media" consistently for simplicity.

xjm’s picture

Assigned: xjm » Unassigned
FileSize
24.16 KB

Attached addresses #54 and #70.

xjm’s picture

FileSize
8.01 KB
xjm’s picture

+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -30,21 +47,17 @@
-        {{ description.content }}
-      {% endif %}
+          {{ description.content }}
+    {% endif %}

Indentation change here was not intentional. But not uploading a new patch just yet in case this gets more feedback. (Whitespace doesn't need to block RTBC in any case.)

xjm’s picture

Issue summary: View changes
FileSize
72.35 KB
83.32 KB
91.39 KB

Once #2940201: hook_field_widget_form_alter() can no longer affect the whole widget for multi-value fields is committed (RTBC now), #75 can be also fixed in that reroll.

So close!

Here are some updated screenshots:

Single element

Multiple element limited to 3 values

Unlimited multivalue

xjm’s picture

Issue summary: View changes

Also updating the IS.

xjm’s picture

Saving issue credit for the many reviewers.

xjm’s picture

Assigned: Unassigned » xjm

Alright, the blocker is in now (with a slight API change), so I'm updating this one.

xjm’s picture

Assigned: xjm » Unassigned
FileSize
18.1 KB
1.41 KB

Here it is!

davidhernandez’s picture

+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -0,0 +1,70 @@
+      {% if media_list_link %}
...
+      {% if description.content %}

These ifs shouldn't be necessary. There is no markup being printed inside them, only Twig variables.

It is needed, for example, for the button and h4.

Also, no text in the template. yay \0/

benjifisher’s picture

Status: Needs review » Needs work

Just looking at the interdiff,

+++ b/core/modules/media/media.module
@@ -184,7 +184,7 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
 /**
  * Implements hook_field_widget_multiple_WIDGET_TYPE_form_alter().
  */

The docblock should be updated to match the new hook name.

Sorry, I do not have time to do a real review.

benjifisher’s picture

Status: Needs work » Needs review
FileSize
1.28 KB
18 KB

This makes the changes requested in #81 and #82. I have no opinion on #81.

xjm’s picture

Thanks @benjifisher and @davidhernandez.

samuel.mortenson’s picture

Status: Needs review » Reviewed & tested by the community

All my previous feedback has been addressed, and the patch is looking good now. Marking as RTBC, pending further review.

yoroy’s picture

Status: Reviewed & tested by the community » Needs review

Content wise this looks ok. For me "then add it by name *to* the form" felt slightly off, was thinking "then add it by name *in* the form below. I'll defer to the native speakers, no biggie I think.

Is there a reason why the texts below the form elements ("Type part of…") are not shown as actual descriptions for those fields? Currently these texts have a larger gap between them and the form field above, again looking slightly off.

xjm’s picture

Assigned: Unassigned » xjm

Thanks @yoroy.

Content wise this looks ok. For me "then add it by name *to* the form" felt slightly off, was thinking "then add it by name *in* the form below. I'll defer to the native speakers, no biggie I think.

"To" is definitely more idiomatic than "in". I would never use "in" in this context. :) (Prepositions are indeed the least logical or predictable part of any language I've studied...)

Is there a reason why the texts below the form elements ("Type part of…") are not shown as actual descriptions for those fields? Currently these texts have a larger gap between them and the form field above, again looking slightly off.

This is already inside the actual description div, similar to any field's. I think the gap is just a side effect of a <p> tag being wrapped around the text (which I added belatedly after remembering that the HTML spec requires (or required, back in the day) all text be wrapped in <p> and that <p> as a direct child of a <div> was not technically correct.

However, if we don't do that elsewhere in core, we shouldn't do it here. Looking into this now; if we don't use the <p> for other descriptions we shouldn't here; and if we do then maybe I'm missing a class that is supposed to be on it or its parent.

xjm’s picture

Issue summary: View changes
FileSize
48.84 KB

Looks like we don't use the <p> elsewhere by default (although I believe the site builder can add such markup to descriptions if they want), so I'm going to remove it.

xjm’s picture

Aha. So a very similar case in core is link fields, which are another similar reference field. They have one description provided by core that must be shownalongside any custom description the site builder might add.

If there is no custom help text, it's just displayed in a div, no parent.

If there is a custom text as well, it is displayed in an unordered list.

So I'll update our handy template to do just that.

xjm’s picture

Assigned: xjm » Unassigned
FileSize
18.24 KB
2.66 KB

Okay that took longer than I thought. Turns out there was a bug in the preprocess that was preventing the description class from being added. Attached fixes that, removes the <p> that are not used elsewhere in core and also adds the <ul> in the same pattern as it's used for link fields.

xjm’s picture

Issue summary: View changes
FileSize
153.86 KB
xjm’s picture

Issue summary: View changes

Oops, forgot to embed:

davidhernandez’s picture

Issue summary: View changes
+++ b/core/modules/media/templates/media-reference-help.html.twig
@@ -0,0 +1,66 @@
+      </h4><br />

Where did this wild BR come from? It shouldn't be needed for spacing following an H4. Is there some CSS forcing that inline? I didn't notice any in Seven with a quick look.

tim.plunkett’s picture

  1. +++ b/core/modules/media/media.module
    @@ -172,3 +180,77 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  Element::setAttributes($element, ['id']);
    +  RenderElement::setAttributes($element);
    +  $variables['attributes'] = isset($element['#attributes']) ? $element['#attributes'] : [];
    

    I don't understand the need for these 3.
    How do they improve upon the attribute handling in template_preprocess that will run for this first?
    Could use some comments.

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +180,77 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +      $bundle_labels[] = MediaType::load($bundle)->label();
    

    What about using the EntityTypeBundleInfo service? Or retrieving the labels directly from the element? See \Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection::buildConfigurationForm().
    NWing for this

  3. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -21,6 +26,13 @@ class MediaUiFunctionalTest extends MediaFunctionalTestBase {
    +  /**
    +   * The assertion session.
    +   *
    +   * @var \Behat\Mink\Session
    +   */
    +  protected $session;
    

    Why does this need to be stored? If it's a helper, I've never seen it done this way, I'd recommend not doing it and having a

    $assert_session = $this->assertSession();
    

    at the top of each method.

    If this is needed for some actual functional reason, that is scary and should be explicitly documented.

  4. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,296 @@ public function testRenderedEntityReferencedMedia() {
    +   * Test the default autocomplete widgets for media reference fields.
    

    Nit: start with "Tests"

  5. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +204,296 @@ public function testRenderedEntityReferencedMedia() {
    +    entity_get_form_display('node', $non_media_content_type->id(), 'default')
    ...
    +    entity_get_form_display('node', $content_type->id(), 'default')
    

    Nit: This is deprecated.

tim.plunkett’s picture

Status: Needs review » Needs work
xjm’s picture

Assigned: Unassigned » xjm

Re: #93:

Where did this wild BR come from? It shouldn't be needed for spacing following an H4. Is there some CSS forcing that inline? I didn't notice any in Seven with a quick look.

Yeah that is coming from the standard .label class that was added for #70.2 (AFAIK the standard class for formatting not-label things like labels.) I'm definitely trying to not add CSS that is nonstandard and to reuse the existing markup patterns... but if you know of a better one please let me know. :)

Re: #94

I don't understand the need for these 3.
How do they improve upon the attribute handling in template_preprocess that will run for this first?
Could use some comments.

Those are copied from core/includes/form.inc to address #54 because we are adding our own fieldset while overriding the field form template. Also not commented there, but at least we can add a comment to that effect. :)

Updating the patch for these things.

xjm’s picture

(Adding other reviewer credit.)

xjm’s picture

Status: Needs work » Needs review
FileSize
18.54 KB
6.28 KB

Attached addresses #94. I did not remove the feral <br /> as yet... (edit) as I am not sure what to do about that TBH.

xjm’s picture

Assigned: xjm » Unassigned
FileSize
18.58 KB
1001 bytes

Just fixing a pretty steep case of run-on sentence.

xjm’s picture

Issue summary: View changes

Also fixing embedding failure in the IS.

xjm’s picture

Assigned: Unassigned » xjm
Status: Needs review » Needs work

I realized this morning that we need to use the generic hook instead of the specific one, because the same text should be shown for (e.g.) the autocomplete tags widget.

Making that change now.

xjm’s picture

Assigned: xjm » Unassigned
Status: Needs work » Needs review
Issue tags: +Needs tests
FileSize
22.26 KB
11.09 KB

Okay wow. @tim.plunkett and I spent a bunch of time debugging this.

  1. The first problem was that we were applying the help text to the default widget (entity_reference_autocomplete), but ignoring the other three widgets available to entity reference fields in core. To address this, we move up from hook_field_widget_mutlivalue_WIDGET_TYPE_form_alter() to the generic hook_field_multivalue_form_alter() and check the field type (entity reference), target referenceable entity type (media), and widgets (entity_reference_autocomplete, entity_reference_autocomplete_tags, etc.)
     

  2. The second problem was that the hook was being invoked in the wrong place within WidgetBase. There are actually three scenarios possible for widgets:

    1. A widget for a field that only allows a single value.
    2. A widget for a field that allows multiple values, but only one value can be entered in each form element.
    3. A widget for a field that allows multiple values, and furthermore allows multiple values to be entered within a single form element.

    To resolve this, we need to move the hook invocation. This will also need its own issue and tests.
     

  3. The third problem was that the render array structure is utterly unreliable from widget to widget. The logic added in earlier patches unfortunately did not hold up under further usecases. With @tim.plunkett's help I changed all this to instead use the reliable objects that are available within the alter hook.

    To avoid passing lots of information to the preprocess in magic keys, I instead moved the logic back into the alter hook, and the preprocess now retrieves the relevant template variables passed to it in an array stored in $elements['#media_help']. This means the preprocess also becomes a lot cleaner, and we only have to debug and adjust business logic in one place rather than two. (@tim.plunkett had proposed removing the # from the child keys of $elements['#media_help'], but when I tried that they were stripped between the alter and preprocess, so I've left them for now.
     

  4. The fourth problem is that template_preprocess_field_multivalue_form() assumes the presence of an $element[#cardinality_multiple] key that does not actually exist for multivalue widgets. For now I'm just initializing it in the alter hook, but this seems like it needs a followup...

     

  5. The fifth problem is that element array structure of the options widgets does not seem to work with the multivalue field hook/template. However, select lists of options are less baffling to the user, so I think addressing this can be scoped to a followup.

    This needs more tests, too. I think we will want to add the widget as another parameter for the data provider.

Status: Needs review » Needs work

The last submitted patch, 102: media-interdiff-102.patch, failed testing. View results

xjm’s picture

Second "patch" is actually just the interdiff, sorry. But this is NW for tests and scoping anyway.

tim.plunkett’s picture

  1. +++ b/core/modules/media/media.module
    @@ -181,25 +181,97 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  if ($field_type !== 'entity_reference' ||  $target_type !== 'media') {
    +    return;
    +  }
    

    Yay early returns!

  2. +++ b/core/modules/media/media.module
    @@ -181,25 +181,97 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +    if (count($create_bundles) === 1) {
    +      $add_url = Url::fromRoute('entity.media.add_form')->setRouteParameter('media_type', $create_bundles[0])->toString();
    ...
    +    elseif (count($create_bundles) > 1) {
    +      $add_url = Url::fromRoute('entity.media.add_page')->toString();
    ...
    +    $elements['#media_help']['#media_add_help'] = t('Create your media on the <a href=":add_page" target="_blank">media add page</a> (opens a new window), then add it by name to the field below.', [':add_page' => $add_url]);
    

    Unless I'm missing something, there is an unwritten else case here in which $add_url will be an undefined variable. Aka, when there are no bundles?
    Adding $add_url = NULL; above and wrapping the last line in if ($add_url) would help

  3. +++ b/core/modules/media/media.module
    @@ -181,25 +181,97 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
         }
    +    $elements['#media_help']['#media_add_help'] = t('Create your media on the <a href=":add_page" target="_blank">media add page</a> (opens a new window), then add it by name to the field below.', [':add_page' => $add_url]);
    

    The double nested #-prefixed keys look off to me. What's the reason this is needed at the interior level?

  4. +++ b/core/modules/media/media.module
    @@ -181,25 +181,97 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  $cardinality = $context['items']->getFieldDefinition()->getFieldStorageDefinition()->getCardinality();
    

    Whenever I see code digging this deep I think of a skier on a slalom course. Not sure why. But, yikes! (also nothing to be done about that here, this is correct AFAIK).

  5. +++ b/core/modules/media/media.module
    @@ -220,42 +292,10 @@ function media_preprocess_media_reference_help(&$variables) {
    +    foreach ($element['#media_help'] as $key => $text) {
    +      $variables[substr($key, 1)] = $text;
         }
    

    If the # prefixes from above are removed, this substr call can be dropped. And in fact, the whole thing could be $variables += $element['#media_help'];

  6. +++ b/core/modules/media/templates/media-reference-help.html.twig
    @@ -25,7 +25,7 @@
    -    <span{{ legend_span_attributes.addClass(legend_span_classes) }}>{{ label }}</span>
    +    <span{{ legend_span_attributes.addClass(legend_span_classes) }}>{{ original_label }}</span>
    

    The need for this change is not clear to me, but seems okay?

xjm’s picture

#105.3 and 5 are already answered in #102.3. :)

For #105.6, I just decided the existing variable name was not specific/clear enough.

I'll fix #105.2 once I finish writing tests and @tedbow files our friendly followups.

tedbow’s picture

Status: Needs work » Needs review
FileSize
1.48 KB
27.16 KB

Created follow up issues and update @todo in patch

#2943020: Inform content authors where they can list and add media on all media reference widgets
#2943024: Ensure widget title is correct when adding media reference help text and links

UPDATE: sorry was not on 8.6.x when I created my new issue branch. will upload a new patch

tedbow’s picture

Here is the correct patch for #107

tedbow’s picture

The last submitted patch, 107: 2936293-107.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tim.plunkett’s picture

  1. +++ b/core/modules/media/media.module
    @@ -9,8 +9,11 @@
    +use Drupal\Core\Render\Markup;
    

    Unused

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +function media_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
    ...
    +  $field_type = $context['items']->getFieldDefinition()->getType();
    

    I think this function deserves a nice

    /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
    $field_definition = $context['items']->getFieldDefinition();

    at the top, so all further calls will typehint correctly.

  3. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +      $add_url = Url::fromRoute('entity.media.add_form')->setRouteParameter('media_type', $create_bundles[0])->toString();
    

    Super unimportant nit, but
    $add_url = Url::fromRoute('entity.media.add_form', ['media_type' => $create_bundles[0]])->toString(); is way more common

  4. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  $cardinality = $context['items']->getFieldDefinition()->getFieldStorageDefinition()->getCardinality();
    

    This is unused.

  5. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  //   Research and resolve this in htttps://www.drupal.org/node/2943020.
    

    Too many t's

  6. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  if (!empty($elements[0]['target_id']['#title'])) {
    +    $elements['#media_help']['#original_label'] = $elements[0]['target_id']['#title'];
    ...
    +    $elements['#media_help']['#original_label'] = $elements['#title'];
    ...
    +    $elements['#media_help']['#original_label'] = $elements['target_id']['#title'];
    

    This is what's causing the failures.

    In WidgetBase, if the cardinality is > 1, the " (value $delta)" part seen in the failures is appended to the title.
    Additionally, it is explicitly marked as '#title_display' => 'invisible' with a comment about how it's not expected to be rendered.

    If you want the correct title, $field_definition->getLabel() has it.

  7. +++ b/core/modules/media/media.module
    @@ -172,3 +179,123 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +  // Only present the help text about autcomplete on autocomplete widgets.
    

    First one is "autcomplete". Also, out of context that sentence reads a bit snarky :) (but there's totally more text below it and it's fine)

Status: Needs review » Needs work

The last submitted patch, 108: 2936293-108.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

xjm’s picture

Status: Needs work » Needs review
FileSize
23.21 KB
7.33 KB

Re: #111.2 those are a PHPStorm thing I guess. Not quite sure what to add as the datatypes don't match (getFieldDefinition() in the proposed snippet vs. getType() in the code).

Attached addresses the rest of #111 plus adds test cases for the tags-style widget. (The fix for #111.6 is from @tim.plunkett.)

xjm’s picture

Alright, I finally added the tests we've needed from #26 / #29. This coverage is pretty important because we've repeatedly broken the field settings form over the course of this issue, including in the most recent patches. To ensure it doesn't regress again, we create the media reference field through the UI rather than the API.

The fix has two parts. First, we should not be altering the field default values on the field settings form. That form is for site builders rather than content authors, and a lot of the info we would add is just not relevant, so it mostly adds noise and overhead. hook_field_widget_multivalue_form_alter() and friends already include a mechanism to distinguish the settings default form from the actual form with $context['default']. (It was added because of a bug very much like this one that was fixed in late 2011).

Secondly, I had a fragile line code that was trying to reference an array key that could be an undefined index. That's just bad PHP code, so I've fixed that as well to avoid other issues down the road.

I think this is finally ready (once the blocker lands and we reroll this on top of it).

The last submitted patch, 114: media-2936293-114-FAIL.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

xjm’s picture

Same patch, rolled on top of the fix to WidgetBase.

samuel.mortenson’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me 👍

larowlan’s picture

Screenshots look like a good interim step.

  1. +++ b/core/modules/media/media.module
    @@ -172,3 +178,128 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +function media_field_widget_multivalue_form_alter(array &$elements, FormStateInterface $form_state, array $context) {
    ...
    +  if (in_array($widget_plugin_id, array('entity_reference_autocomplete', 'entity_reference_autocomplete_tags'))) {
    +    $is_autocomplete = TRUE;
    

    Was there a reason why we didn't add new purpose built widgets that extend these instead of going down the alter path?

    We could limit their availability to just media ER fields with the isApplicable method.

    If the answer is, because we intend to remove all of this in the future and doing it as an alter hook means we don't have to support it forever but doing it as a stand-alone widget would mean we're supporting it till Drupal 9 - +100.

  2. +++ b/core/modules/media/media.module
    @@ -172,3 +178,128 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
    +      $variables[substr($key, 1)] = $text;
    

    The theme system does this for you, if you declare the variable names in 'variables' in your hook theme.

    Was there a reason we went with 'render element' instead of 'variables'?

  3. +++ b/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php
    @@ -192,6 +197,308 @@ public function testRenderedEntityReferencedMedia() {
    +  public function testMediaReferenceWidget($cardinality, array $media_type_create_access, $list_access, $widget_id = 'entity_reference_autocomplete') {
    

    Each of these provider cases installs a new Drupal site. Are we ok with that?

    If not, we can move to a doTestSomething() style approach where we feed the cases in, but have only one Drupal install for performance sake.

    Given we don't really need isolation here, because we aren't creating any content - we can change the config between each case.

xjm’s picture

Thanks @larowlan.

1. Was there a reason why we didn't add new purpose built widgets that extend these instead of going down the alter path?

We could limit their availability to just media ER fields with the isApplicable method.

If the answer is, because we intend to remove all of this in the future and doing it as an alter hook means we don't have to support it forever but doing it as a stand-alone widget would mean we're supporting it till Drupal 9 - +100.

The reason is that we want to be able to provide the text on existing widgets, rather than creating a new one that the site builder would need to know to select. For example, we'll want the help text on both regular autocomplete and tags-style autocomplete widgets, and we can eventually add the help text about creating to options widgets as well. That's why we use an alter hook.

Doing it this way also allows us to avoid API surface (as you've said), minimizes the disruptions/additions since this is an interim fix to replace all this with the Media Library Browser, and still allows module developers, themers, and site owners to customize the help text in whatever way they like (which is something else that came up in usability review).

2.

+++ b/core/modules/media/media.module
@@ -172,3 +178,128 @@ function media_form_field_ui_field_storage_add_form_alter(&$form, FormStateInter
+      $variables[substr($key, 1)] = $text;
The theme system does this for you, if you declare the variable names in 'variables' in your hook theme.

Was there a reason we went with 'render element' instead of 'variables'?

Hm, I don't understand the question. The line you list is only adding a small subset of the elements array, passed over from the alter hook where they were calculated. There are however other variables for the correct fieldset and form markup attributes that we're setting above. (We're overriding the field multiple form template, but incorporating markup and templating from the fieldset template.) Also there is both a render element and variables?

3. Each of these provider cases installs a new Drupal site. Are we ok with that?

If not, we can move to a doTestSomething() style approach where we feed the cases in, but have only one Drupal install for performance sake.

Given we don't really need isolation here, because we aren't creating any content - we can change the config between each case.

I did it this way on purpose because we had previous regressions on the issue where tests did not fail because there was a false positive from something else on the page. I've been running the test locally with its provider since I added it and it really doesn't take long at all. And developer time is after all more costly than hardware. :)

effulgentsia’s picture

this is just an interim fix

In that case, how about adding @internal to media-reference-help.html.twig with a link to the issue that will remove it? I also wonder if the theme system would allow us to prepend an _ to the theme hook name (- to the .html.twig name) as a further hint to contrib that this will get removed.

  • effulgentsia committed 05039c6 on 8.6.x
    Issue #2936293 by xjm, tedbow, marcoscano, ershov.andrey, phenaproxima,...

  • effulgentsia committed ab4fea3 on 8.5.x
    Issue #2936293 by xjm, tedbow, marcoscano, ershov.andrey, phenaproxima,...
effulgentsia’s picture

Version: 8.6.x-dev » 8.5.x-dev
Status: Reviewed & tested by the community » Fixed
FileSize
1.89 KB

I'm ok with #120 being explored/done in a post-beta followup. Therefore, pushed #116 (plus the coding standards fixes in this interdiff) to 8.6.x and 8.5.x.

xjm’s picture

Thanks @effulgentsia! Regarding #120, I still would not remove the template in a minor release. We should avoid using @internal in that way; the maintenance burden is not high enough to justify the disruption. And actually I don't want to mark it internal because we do want to let people override it. The media library will add a different widget that will become the default for new installs, but this help text will still be useful for the autocomplete widgets. So I did not file said issue. :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.