Proposed resolution

The widget form element only contains the field name which is not enough to retrieve the field configuration at later hooks. For example in the chosen module we would need the field configuration to be available in the pre render function. To be able to call the \Drupal\field\Entity\FieldConfig::loadByName() function we need the above data.

Proposed resolution

The entity type and bundle values can be added in the form function of the WidgetBase Class.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mr.york created an issue. See original summary.

mr.york’s picture

mr.york’s picture

Status: Active » Needs review
Aron Novak’s picture

Status: Needs review » Reviewed & tested by the community

I did a quick test, also reviewed the code. It's a trivial addition to expose more information for later, the only potential question is if there's already a way to grab this info, if not, it should be fine.

catch’s picture

Status: Reviewed & tested by the community » Needs review

hook_field_widget_form_alter() has access to the widget plugin instance, which in turn would let you get the field definition via $context['widget']->fieldDefinition()

    if ($element) {
      // Allow modules to alter the field widget form element.
      $context = array(
        'form' => $form,
        'widget' => $this,
        'items' => $items,
        'delta' => $delta,
        'default' => $this->isDefaultValueWidget($form_state),
      );
      \Drupal::moduleHandler()->alter(array('field_widget_form', 'field_widget_' . $this->getPluginId() . '_form'), $element, $form_state, $context);
    }

Can you explain why that isn't enough?

If it isn't, could use test coverage I think.

jhedstrom’s picture

I may be missing something, but when I started looking into #5 as an alternative approach, I don't think the protected WidgetBase::$fieldDefinition property is available (no getter method). There is a protected method to access to the field settings via WidgetBase::getFieldSettings(), but even if that were a public method it wouldn't be usable since the method isn't part of any interface.

mr.york’s picture

Status: Needs review » Reviewed & tested by the community

The approach suggested in #5 would only be a workaround for the problem.
In Drupal 8 its not enough that we know the name of the field, to load the informations necessary in a hook.
(https://api.drupal.org/api/drupal/core!modules!field!src!Entity!FieldCon...)
To get the field configuration in a hook, we need to know the entity machine name and the bundle of the field.
Is there a good reason why these informations are not getting into the elements variable?

In the hook suggested by #5 the $context['widget']->fieldDefinition is protected, and so its methods cannot be called.
And I could not find any method in the WidgetBase class that would help in this situation either.

catch’s picture

Status: Reviewed & tested by the community » Needs review

OK that's a good point that $this->fieldDefinition isn't available - but why not add public function getFieldDefinition() to WidgetFormBase() then?

jhedstrom’s picture

add public function getFieldDefinition() to WidgetFormBase()

That would probably be the most flexible solution here.

tim.plunkett’s picture

Version: 8.0.x-dev » 8.2.x-dev
Issue tags: +Needs tests
nagy.balint’s picture

So every module that needs these data needs to implement this alter and add the information into the element?

But if there are more than one module doing this in the system that seems to not be very efficient.

Is there a good reason why we would not add this basic information into the element by default like in the patch?

jhedstrom’s picture

So every module that needs these data needs to implement this alter and add the information into the element?

That's a good point. I don't see the harm in adding these details, but we'll still need a test.

Also, while we could make a public method getFieldDefinition() to WidgetBase, it wouldn't be part of any sort of interface, so contrib modules that relied on its usage could only do so for widgets that extend that class.

mr.york’s picture

Status: Needs review » Needs work

The last submitted patch, 13: the_widget_form_element-2678824-13-only-test.patch, failed testing.

mr.york’s picture

Status: Needs work » Needs review
FileSize
3.15 KB
mr.york’s picture

Status: Needs review » Reviewed & tested by the community

Wrote little tests.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

@mr.york "Reviewed & tested by the community" means that the fix has been reviewed and tested by someone other than the patch author.

Aron Novak’s picture

Status: Needs review » Reviewed & tested by the community

Just did a review, the code itself is fine, I have just a general feeling that the Widget-related things would deserve a separate test class, we modify Field\WidgetBase, and test it in field\Kernel\FieldAttachOtherTest , when for example there's field\Kernel\WidgetPluginManagerTest (sure, this does not belong there), but i think this is out of scope here, as this test already tests things related to widgets.

nagy.balint’s picture

+1

This is blocking #2117827: "None" showing up as an option in multiselect. in the chosen module.

alexpott’s picture

Category: Feature request » Task
Issue tags: -Needs tests +Contributed project blocker

I don't think this is really a feature - just a task - and it is blocking contrib. Given it's BC I wonder whether we should consider for 8.1.1?

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Also no one has given a good response to why #8 is not the way to go?

nagy.balint’s picture

I thought #11 was a good reason, seeing that this patch only adds 2 lines, that probably should be available anyways without having to do all sorts of workarounds to get the data.
Of course that function could be available as described in #8 but then maybe it could be done in a separate issue, and could be used for some other more complex requirement.

mr.york’s picture

Status: Needs review » Reviewed & tested by the community
jhedstrom’s picture

Also no one has given a good response to why #8 is not the way to go?

I agree #11 is a pretty good reason. Also, I mentioned that a method on a base class could not be relied on the same way as an interface class in #12. Contrib could only get information on widgets directly extending from the base class, but if a widget didn't use that base class, the method would not reliably be there.

Could we add the method to WidgetBase and WidgetInterface in a point release, or is that considered an API change?

star-szr’s picture

This looks to me like a reasonable solution and unless I'm missing something the pattern is something we use elsewhere (unfortunately) when we're not dealing with real objects. In this case a render array. Often it's hard to determine context and from what I'm seeing this is contextual information that is probably useful in many cases. I think the hypothetical OO render API would be helpful here if we wanted to keep it cleaner. Luckily the amount of data is quite small here so I don't think it's too concerning.

alexpott’s picture

So I think it would be possible to add getFieldDefinition to WidgetBaseInterface in 8.2.x - in fact that interface has the following documentation:

 * This interface details base wrapping methods that most widget implementations
 * will want to directly inherit from Drupal\Core\Field\WidgetBase. See
 * Drupal\Core\Field\WidgetInterface for methods that will more likely be
 * overridden in actual widget implementations.

Which seems pretty analogous to what we want to do here. If someone can point to a widget in the wild not extending WidgetBase then we can explored the solution in #15. That solution is problematic because what happens when we want to do add the next thing from the field definition to the render element.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

After discussing this more with @catch, I think we should try to avoid less #random in render arrays - see #2702061: Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering) for why. Yes this is a long way off - but we have a better way available here and one that means everything from the field definition is available - not just what we in core deem necessary.

jhedstrom’s picture

Assigned: mr.york » jhedstrom

I'm going to work on the interface change.

jhedstrom’s picture

Assigned: jhedstrom » Unassigned
Status: Needs work » Postponed (maintainer needs more info)

I went to add this method to the interface, but then when looking into tests, I found this in the field_test_field_widget_form_alter() implementation:

  $field_definition = $context['items']->getFieldDefinition();

Looking into WidgetBase::formSingleElement(), the $context['items'] implements FieldItemListInterface, which definitely has access to the field definition.

So, this may be works as designed?

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

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

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

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

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.

jhedstrom’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)

Closing out.