Support from Acquia helps fund testing for Drupal Acquia logo

Comments

joachim’s picture

Title: Documentation problem with hook_field_widget_form_alter » no way for hook_field_widget_form_alter() to know if it is on a form or in defaults
Component: documentation » field system

Best I can find is this which is rather brittle:

  if (isset($context['form']['#title']) && $context['form']['#title'] == t('Default value')) {
    return;
  }
xjm’s picture

Ah, I ran into this as well. This is what I did:

  // Check for an existing entity ID.
  $entity_id = 0;
  if (!empty($form_state['build_info']['args'][0])) {
    $info = entity_get_info($context['instance']['entity_type']);
    $pseudo_entity = (object) $form_state['build_info']['args'][0];
    if (isset($pseudo_entity->{$info['entity keys']['id']})) {
      $entity_id = $pseudo_entity->{$info['entity keys']['id']};
    }
  }
xjm’s picture

So, to fix this, we'd add the entity and type explicitly to the context, maybe with the entity as FALSE or NULL when on the default form, or maybe with some flag as another piece of context info.

The problem in #1204230: Missing hook_field_widget_form_alter() was that field_multiple_value_form() doesn't get that info in context, so it can't pass it on to the alter hook.

Alan D.’s picture

In other hooks, entity is unset so this would be the consistent way of doing things in D7.

The way that I have been checking for the field default value form is:


  if (!isset($context['form']['#title']) || $context['form']['#title'] != t('Default value')) {
    // Alter standard entity widget form
  }
  else {
    // Alter instance default form
  }
joachim’s picture

Status: Active » Needs review
Issue tags: +Needs backport to D7
FileSize
1.84 KB

Here's a quick patch (untested, as the theme_username change has hosed my D8 and I haven't time to reinstall right now).

Given this doesn't change parameters, I reckon it could be backported.

Alan D.’s picture

This could be made a bit tighter by removing the if-else. Love to see this back-ported to D7!

Alan D.’s picture

The above patch missed one function call to the hook_field_widget_form pair and three API argument list updates. This is works fine on a development D7 site.

I assume that you can not use field_multiple_value_form() on the default value widget?

As an aside, what is the recommended markup of arguments. The field api uses both quoted and un-quoted:

 /**
  *   - "instance": The instance of the field.
  *   - instance: The instance of the field.
  */

[edit] The second one complies with the coding standard.

xjm’s picture

Title: no way for hook_field_widget_form_alter() to know if it is on a form or in defaults » No way for hook_field_widget_form_alter() to know if it is on a form or in defaults
Issue tags: +Needs tests

Nice, this seems like a straightforward enough way to fix this. Let's add test coverage for the new key.

Regarding how to document the keys, no quotes is the preferred standard. (There are outstanding documentation issues somewhere to clean this up.) Reference: http://drupal.org/node/1354#lists

Alan D.’s picture

Issue tags: +Needs tests

I leave the tests for someone else, these are not my strong point (I've only got about 5% coverage on my own contrib modules at the moment)

Goggled the argument standards, there are 380 still in head to correct ;)

Alan D.’s picture

Yuk. This applies to the actual widget form itself :(

I have found that an Ajax callback to a sub-component (using drupal_html_id()) fails here as the form is rebuilt and the id is updated. So you need to rebuild the entire widget or bypass the drupal_html_id() when generating the wrapper.

xjm’s picture

@Alan D., can you clarify? Are you saying the patch doesn't target only the default form element? If so, let's set the issue back to NW.

Alan D.’s picture

No this patch is fine, I'm referring to the widget form:

hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element);

The structure of my widget is:

id = drupal_html_id(field-name, delta, language);
widget-container
  ajax-trigger (targets id)
  ajax-target (has target id)

Each time the ajax-trigger is activated, the resulting ID returned from drupal_html_id() used to assign the ID to the ajax-target is incremented by one (ie: it works once, then it breaks as the ajax-target has a new ID).

In the particular case of the default value form, a manual ID is fine, otherwise drupal_html_id() is being used, so I have ended up using a variant on the above (#1) check to see if the $form['#title'] is set to t('Default value).

Long story short, maybe we need to flag a parameter to hook_field_widget_form() with a default flag too?

joachim’s picture

> Long story short, maybe we need to flag a parameter to hook_field_widget_form() with a default flag too?

Yes, I'd say we do. Just found out that hook suffers from the same problem.

tim.plunkett’s picture

Status: Needs review » Needs work

Per #12/13, also still needs tests.

Adagio’s picture

First attempt in here, so please let me know if anything can be improved. This is a rerolled patch to 8.x, and added tests. Not every codepath is tested. In hook_field_widget_properties_alter and hook_field_test_field_widget_form_alter, I set a message when $context['default'] is true, and check for those on the manage field form and an entity form.

So hook_field_widget_properties_ENTITY_TYPE_alter and hook_field_widget_WIDGET_TYPE_form_alter() is not covered in these tests currently. However they are called from the same places as the generic ones, so I figured this was decent coverage.

Adagio’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, drupal-default_value_form-1356824-15.patch, failed testing.

Adagio’s picture

Status: Needs work » Needs review
FileSize
6.77 KB
3.61 KB

Another go.

Status: Needs review » Needs work

The last submitted patch, drupal-default_value_form-1356824-18.patch, failed testing.

Adagio’s picture

Adagio’s picture

Status: Needs work » Needs review
tim.plunkett’s picture

Issue tags: -Needs tests
FileSize
7.2 KB
6.65 KB

Rerolled for some code style issues. I think this is ready to go.

marcingy’s picture

Status: Needs review » Reviewed & tested by the community

Looks good

xjm’s picture

Lovely. Thanks everyone!

catch’s picture

Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

I stared at this a couple of times, the $context['default'] looks a bit hacky to me, but the only idea I had was adding a new hook which is no good for Drupal 7 backport and probably not a good idea anyway.

Committed/pushed to 8.x, moving to 7.x for backport.

larowlan’s picture

Sorry to chime in this late but I think $element['#entity'] is NULL (in D7 at least) on the default form.

dcam’s picture

Status: Patch (to be ported) » Needs review
FileSize
6.61 KB
3.2 KB

Backported #22 to D7.

Alan D.’s picture

I don't think that this was committed :( Or if it was, the changes were lost when this area was refactored, assuming that this is still required.

See FieldInstance::getWidget()

mgifford’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs reroll

doesn't seem to apply now.

dcam’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
6.61 KB

Rerolled #27.

  • catch committed e1befb5 on 8.3.x
    Issue #1356824 by Adagio, Alan D., joachim, tim.plunkett: Fixed No way...

  • catch committed e1befb5 on 8.3.x
    Issue #1356824 by Adagio, Alan D., joachim, tim.plunkett: Fixed No way...

  • catch committed e1befb5 on 8.4.x
    Issue #1356824 by Adagio, Alan D., joachim, tim.plunkett: Fixed No way...

  • catch committed e1befb5 on 8.4.x
    Issue #1356824 by Adagio, Alan D., joachim, tim.plunkett: Fixed No way...

  • catch committed e1befb5 on 9.1.x
    Issue #1356824 by Adagio, Alan D., joachim, tim.plunkett: Fixed No way...