Coming from #2214241-327: Field default markup - removing the divitis

'#theme' => 'field' / template_preprocess_field() / field.html.twig expect the render array's '#items' entry to contain the field values as a FieldItemListInterface object. That is how the preprocessor and template can access the field definition (like, what's the field type, cardinality, etc...) : $element['#items']->getFieldDefinition()

quickedit_test_entity_view_alter(), added in #2057973: Don't add Edit module's data- attributes on pseudo fields (as used e.g. by Display Suite), uses a bespoke "rendered field" to the render array, that is hand-made rather than the actual output of an actual formatter.
It uses '#theme' => 'field' and thus triggers template_preprocess_field() / field.html.twig, but its content is not strictly compatible with what a real formatter would output (see FormatterBase::view()) - notably its '#items' entry is an array of values instead of an object implementing FieldItemListInterface :

function quickedit_test_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  if ($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'article') {
    $build['pseudo'] = array(
      '#theme' => 'field',
      // ...
      '#items' => array(
        0 => array(
          'value' => 'pseudo field',
        ),
      ),
      0 => array(
        '#markup' => 'pseudo field',
      ),
    );
  }
}

#2214241: Field default markup - removing the divitis is currently forced to introduce a safeguard check in template_preprocess_field() like :
$variables['multiple'] = is_object($element['#items']) ? $element['#items']->getFieldDefinition()->getFieldStorageDefinition()->isMultiple() : FALSE;

We should fix this, $element['#items'] should by contract be a FieldItemListInterface. template_preprocess_field() (or any other custom field preprocessors or templates trying to access the field definition) shouldn't have to safeguard for tests that take shortcuts :-)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched created an issue. See original summary.

yched’s picture

Wim Leers’s picture

Component: edit.module » quickedit.module

I should ping somebody with significant d.o rights about removing the old component.

Wim Leers’s picture

Hrm:

/**
 * Implements hook_entity_view_alter().
 */
function quickedit_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  $build['#attributes']['data-quickedit-entity-id'] = $entity->getEntityTypeId() . '/' . $entity->id();
}

So it is indeed 100% a test problem, i.e. the "simulation of a pseudofield generated by Display Suite" in quickedit_test_entity_view_alter() needs to be updated.

I don't know what exactly that should look like, but I think you do, yched? :)

Wim Leers’s picture

Issue tags: +Entity Field API
yched’s picture

So quickedit_entity_view_alter() is mimicking what DS "pseudo fields" do, to make sure that core's quickedit support them, correct ?

I'm not too familiar with DS pseudo fields, but I fear it might be tricky to make them go through '#theme' => 'field' *without* being backed by an "official field with an officially registered definition in that entity type + bundle".

Because :
- '#theme' => 'field' and its substack (preprocess + template) assume they have a FieldItemListInterface object to work with in #items
- Would need checking, but IIRC, it's not easy to build a bespoke, runtime FieldItemList object based on an arbitrary runtime field definition. The ContentEntity / Field system is (sadly, but late / hard to change) not designed on an injection pattern, field definitions are *pulled* from the official registry : TypedDataManager::getPropertyInstance() creates FieldItemLists using a "propertyDefinition" that is pulled from EntityManager::getFieldDefinitions(), which itself reads from field.field.* config records. So it's hard to do anything with a runtime field definition that's not in the registry :-/

swentel’s picture

Hmm yeah, I started fearing that. The reason why DS uses theme field is because DS also allows you to swap the field templates, for both 'core' fields, and letting the pseudo fields use theme_field is just convenient. But yes, this doesn't fly nicely anymore in D8.

I'll have to figure out whether I can register the fields that are created in DS UI or in code as something that TypedData will understand and then well run through a formatter I guess. However, we'd still need some kind of opt-out if possible.

Other - sad - option is to rework the code completely and register my own theme function. I'll have to think a bit about this - and also have a look at the code, it's been a while :)

yched’s picture

Well, if we could make TDM::getPropertyInstance() support "hey, please create a TD object using *this* definition I'm handing you", it could also be pretty handy for a lot of other cases ;-)

yched’s picture

Either way, not sure what's the exact use case quickedit_test_entity_view_alter() is supposed to test, but since what it is currently testing is wrong, shouldn't we just remove it ?

swentel’s picture

Well the use case is that since DS is using field_theme - which pretty much is the only contrib afaik doing that - quickedit picks in and adds a pencil to edit the field. Now, DS fields aren't necessarily editable data (sometimes it is, sometimes it's just simple markup, or maybe a combination of some fields wrapped into one output with some funky manipulations), and there's no widget either so the pencil simply does nothing and the javascript breaks completely.

swentel’s picture

Basically, I guess you could say that in some way, DS fields are computed, maybe that's a way out of it, haven't investigated that option yet.

swentel’s picture

Status: Active » Needs review
Issue tags: +DUGBE0609
FileSize
3.97 KB

Uploading patch that removes this check - will try to test later today with DS to see how I can get around it

swentel’s picture

Assigned: Unassigned » swentel

Looking at this today

Wim Leers’s picture

To be clear, I'd love to see this "pseudo field" support in Quick Edit removed :) It was added solely for Display Suite.

aspilicious’s picture

Well it's added for anyone that wants to use the field theme function. It's strange to have a theme function that only can be used in a specific use case.

But I do see DS is the only contrib module doing this trickery at the moment.

So Yeah +1 to remove it if we don't loose field templates in DS.

Damn, I wish I could be in Barcelona...

yched’s picture

It's strange to have a theme function that only can be used in a specific use case

Well, a theme function can only be expected to work for the use cases that provide the arguments it expects, that sounds fair ?
("You want to output a field value, fine, give me the corresponding FieldItemList object")

I mean, if theme functions / processors had proper signatures instead of a convenient array of args, that would only be natural ?

swentel’s picture

Found a workaround so DS can still use theme_field(), see patch for DS at #2563925: Figure out if we need to use a different theme function for our fields

Changes: introduce '#is_multiple' on FormatterBase.

Also removed another is_object() check in template_preprocess_field().

swentel’s picture

Assigned: swentel » Unassigned
aspilicious’s picture

You're right yched :)

Wim Leers’s picture

This patch fully reverts #2057973: Don't add Edit module's data- attributes on pseudo fields (as used e.g. by Display Suite). Therefore, from a Quick Edit POV, this is definitely RTBC.

The first 2 hunks make tiny modifications to Field API. Do those need additional test coverage?

yched’s picture

Thanks for reviving this @swentel

So the patch removes the current access to $field_item->getFieldDefinition() from template_preprocess_field(), and instead has the caller extract the info (is_multiple) and pass it explicitly from the outside. That way, DS can still make use of the theme hook passing a fake $field_item that doesn't have the definition.

I guess that works, until some other (custom / contrib) field preprocess or template wants to access $field_item->getFieldDefinition() (or otherwise uses $field_item as a FieldItemListInterface), then the DS calls will break as well ?

From #7

letting the pseudo fields use theme_field is just convenient

What would getting rid of that convenience mean eaxactly ?
Since, according to #10, DS using theme_field has the added drawback of kicking quick_edit in, which is not intended ?

swentel’s picture

I guess that works, until some other (custom / contrib) field preprocess or template wants to access $field_item->getFieldDefinition() (or otherwise uses $field_item as a FieldItemListInterface), then the DS calls will break as well ?

Good point, the only thing I can come up with is that we should document this in DS - maybe even on the project page - and add an additional property on our field so that custom/contrib knows that this will be a invalid field. I'm fairly sure that accessing the field definition won't happen every 5 minutes around the planet, so I can totally live with that.

We should probably open an issue allowing to create runtime field definitions so DS can create a 'fake' field then, that should be possible for 8.1 no ?

Since, according to #10, DS using theme_field has the added drawback of kicking quick_edit in, which is not intended ?

Quick edit doesn't kick in anymore in our patch for DS since we're telling our fields that their view mode is _custom - that check exist in quickedit itself already. So at least this part is fine.

aspilicious’s picture

1)
DS has a mechanism to inject any arbitrary output into the entity display.
By using the defualt core field template to wrap the output we can ensure the display looks OK for any non coder/themer.

2)
On top of that, we have a feature called "field templates", it allows people to customize the field wrappers on a field basis in the UI.
Technically it is using field theme suggestions. This feature is used a lot.

I'm pro looking at different ways to achieve this goal. But at the moment I have no clue how to do it properly AND at the moment my time is very limited as I only can work on DS one day each month. It would be sad to not have DS finished when 8.0.0 is out.

The only way to decouple this completly without losing to much time is "duplicating" the field theme templates.
But I don't think this ia future proof solution.

I guess that works, until some other (custom / contrib) field preprocess or template wants to access $field_item->getFieldDefinition() (or otherwise uses $field_item as a FieldItemListInterface), then the DS calls will break as well ?

Yes that's true, in DS itself, we have some "not so nice" object checks.

yched’s picture

Status: Needs review » Reviewed & tested by the community

Agreed that the drawback I pointed in #21 is probably not going to be too common, so that's probably the best way forward.

The underlying issue being :
- we should indeed be able to create an arbitrary runtime FieldItemList object with an arbitrary definition.
- as @swentel points, not sure what's the conceptual difference between DS pseudo-fields (arbitrary, admin-specified output wrapped in a field tpl) and computed fields. Except for computed fields still being blurry, of course :-/

So I guess that's an RTBC here :-)

Wim Leers’s picture

Yay! :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed e686c9d and pushed to 8.0.x. Thanks!

  • alexpott committed e686c9d on 8.0.x
    Issue #2550225 by swentel, yched, Wim Leers, aspilicious:...
swentel’s picture

Status: Fixed » Needs review
FileSize
1.54 KB

The wrong patch was committed, the one from #12, not #17

Attaching the interdiff from 17 again as a patch.

yched’s picture

Status: Needs review » Reviewed & tested by the community

Oops :-)

@alexpott : do you want a followup issue instead ?

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Oops indeed - thanks for noticing. Committed bfcba53 and pushed to 8.0.x. Thanks!

  • alexpott committed bfcba53 on 8.0.x
    Issue #2550225 by swentel, yched, Wim Leers, aspilicious:...

Status: Fixed » Closed (fixed)

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

star-szr’s picture