Problem/Motivation

#2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency is a critical issue, which changes entity base fields like node.title to be full entity fields, meaning they will use Field Formatters instead of custom Views formatters. This also makes them behave like entity fields for translation purposes (otherwise, multilingual field-based views are broken), which is why that is a critical issue and something we really need to do.

However, making that change loses functionality that fields like node.title had to "link this field to its entity". This is used in probably at least half of all field-based views (you usually want to display the node title as a link to the node, for instance). So, we can't really just lose that feature.

Proposed resolution

The proposal is that all "short string" entity field formatters would have a checkbox to link the field to the entity. This way, when node.title and other base entity fields are converted to being full entity fields in Views, using standard Entity Field formatters, they will inherit the "link to entity" checkbox" setting.

We probably don't need this on "long string" field formatters -- for instance you probably don't often need the ability to link the body to the node (you could do it in a view anyway with a Rewrite if you really needed it). Or on fields that aren't strings (normally you want string-based link text). So we'll just do it for "short string fields".

Remaining tasks

User interface changes

All "short field" entity field formatters will have a checkbox setting to link the field to the entity. This will be usable in Views, Entity display modes, etc.

API changes

There is an addition to the config schema for the string formatter for entity string fields.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Task, because its adds a new feature. (Yes, this is a feature, but it's needed to add back a necessary feature that will go away if the blocked critical is resolved.)
Issue priority Major because ... it unblocks a critical?
Disruption Not disruptive, because its adding a feature, no public API change

Comments

dawehner’s picture

Status: Active » Needs review
Issue tags: +VDC
StatusFileSize
new6.56 KB

.

amateescu’s picture

You need to take into account that $entity->urlInfo() can throw an exception. See #2355245: ER's label formatter needs to take into account that $entity->urlInfo() might throw an exception.

Status: Needs review » Needs work

The last submitted patch, 1: 2387019-1.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new6.62 KB
new969 bytes

Thank you for the tip!

dawehner’s picture

StatusFileSize
new617 bytes
new7.22 KB

Fixed the schema failures.

The last submitted patch, 4: 2387019-3.patch, failed testing.

amateescu’s picture

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -27,7 +32,89 @@
    +        '#title' => $this->t('Link to the @entity_label', ['@entity_label' => $entity_type->getLabel()]),
    +        '#type' => 'checkbox',
    

    #type should be first?

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -27,7 +32,89 @@
    +      $build['#markup'] = $this->t('Link to the @entity_label', ['@entity_label' => $entity_type->getLabel()]);
    

    Shouldn't this be "Links to ..."? We're not displaying an action here.

  3. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -38,7 +125,19 @@ public function viewElements(FieldItemListInterface $items) {
    +      if ($this->getSetting('entity_link') && ($entity = $items->getParent()->getValue()) && $entity->hasLinkTemplate('canonical')) {
    

    $entity = $items->getEntity().

  4. +++ b/core/modules/simpletest/src/AssertContentTrait.php
    @@ -141,6 +141,16 @@ protected function parse() {
    +  protected function getUrl() {
    

    Where is this used?

gábor hojtsy’s picture

Title: Make it possible to link to an entity for short strings » String field formatters cannot link to their parent entity
Category: Task » Bug report

This is a fabulous issue. Thanks so much for doing this. Only one comment.

+++ b/core/config/schema/core.entity.schema.yml
@@ -225,6 +225,13 @@ field.widget.settings.checkbox:
+    entity_link:

This is called link_to_entity in comment, etc. (and prior to that link_to_node, etc) in entity type specific cases. So using link_to_entity here would be consistent.

yched’s picture

Awesome, @dawehner++

A couple nitpicks:

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -27,7 +32,89 @@
    +      $container->get('entity.manager')
    

    Yeah, only used for the settingsForm() / settingsSummary(), meaning 1% of actual runtime uses of the class.
    Would it make sense to have a @todo to make it lazy ?

    No biggie I guess since any request that uses a field formatter will have the entity_manager instantiated anyway. Feel free to ignore :-)

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -27,7 +32,89 @@
    +    if ($this->fieldDefinition->getType() === 'string') {
    

    Might be worth a comment that the link option does not make sense for the other field types the formatter supports.

    Also, for symmetry, we should probably add the same condition on "field type === string" than in settingsForm() & viewElements(). If I manually edit my config to switch the 'entity_link' setting, it should still have no effect on other field types.

  3. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -27,7 +32,89 @@
    +      $build['#markup'] = $this->t('Link to the @entity_label', ['@entity_label' => $entity_type->getLabel()]);
    

    The image formatter says "Linked to .." in the summary - let's stay consistent with what's already there ?

    "Link to" is fine in the form since, there, it's about an action, but in the summary it's about a status.

  4. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -38,7 +125,19 @@ public function viewElements(FieldItemListInterface $items) {
    +      if ($this->getSetting('entity_link') && ($entity = $items->getParent()->getValue()) && $entity->hasLinkTemplate('canonical')) {
    

    You can use $entity = $items->getEntity(), it's shorter / clearer :-)

    Also, since this will be the same for all deltas, all of this ('entity_link' setting, link template, entity URL) could be computed once and for all outside the foreach ? (using the link option on a multi-valued string is likely to be a rare use case anyway, but well...)

Status: Needs review » Needs work

The last submitted patch, 5: 2387019-4.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new5.62 KB
new9.47 KB

Thank you so much for the quick reviews!

Shouldn't this be "Links to ..."? We're not displaying an action here.

Well, I went with a label similar with the ImageFormatter example, which is "Link image to ...".

Where is this used?

Note: The AssertContentTrait is using getUrl() when it parses the output. This patch now just moves the code from WebTestBase also to AssertContentTrait.

$entity = $items->getEntity().

Oh! This is much better!

This should also fix both failures.

This is called link_to_entity in comment, etc. (and prior to that link_to_node, etc) in entity type specific cases. So using link_to_entity here would be consistent.

Decided to went with that, good suggestion.

No biggie I guess since any request that uses a field formatter will have the entity_manager instantiated anyway. Feel free to ignore :-)

Agreed :) I think not injection depdencies is just a sign for lazyness :)

Also, for symmetry, we should probably add the same condition on "field type === string" than in settingsForm() & viewElements(). If I manually edit my config to switch the 'entity_link' setting, it should still have no effect on other field types.

... if you manually update your config, good luck anyway :) But I agree, let's make it consistent.

The image formatter says "Linked to .." in the summary - let's stay consistent with what's already there ?

Good suggestion!

Also, since this will be the same for all deltas, all of this ('entity_link' setting, link template, entity URL) could be computed once and for all outside the foreach ? (using the link option on a multi-valued string is likely to be a rare use case anyway, but well...)

Good suggestion as well.

Status: Needs review » Needs work

The last submitted patch, 11: 2387019-11.patch, failed testing.

The last submitted patch, 11: 2387019-11.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new437 bytes
new9.47 KB

Alright, let's fix the schema problem.

Status: Needs review » Needs work

The last submitted patch, 14: 2387019-14.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
Issue tags: +Ghent DA sprint
StatusFileSize
new10.4 KB
new945 bytes

Killed that.

dawehner’s picture

Category: Bug report » Task
Issue summary: View changes

.

Status: Needs review » Needs work

The last submitted patch, 16: 2387019-16.patch, failed testing.

jhodgdon’s picture

Issue summary: View changes

Clarifying issue summary

dawehner’s picture

Assigned: Unassigned » dawehner

Alright, talked with yched about a different approach, let's see how this works.d

dawehner’s picture

Priority: Major » Critical
Status: Needs work » Needs review
StatusFileSize
new18.37 KB

As we discused, this issue is needed in order to resolve the critical D8MI issue.
No interdiff, because its a full new approach, the interdiff does not really tell you anything.

yched’s picture

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/RawStringFormatter.php
    @@ -12,13 +12,12 @@
    + *   id = "raw_string",
    
    @@ -27,7 +26,7 @@
    +class RawStringFormatter extends FormatterBase {
    

    Actually, "raw" is probably not a great idea, as it kind of hints "non-escaped, non-sanitized", which is not the right message to send for a formatter :-)

    Since this formatter is kind of the simplest one you might think of (just prints the checkPlained value), maybe 'basic_formatter' ?

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
    @@ -19,15 +24,95 @@
    +    if ($this->fieldDefinition->getType() === 'string') {
    ...
    +    if ($this->fieldDefinition->getType() === 'string' && $this->getSetting('link_to_entity')) {
    
    @@ -35,10 +120,27 @@ class StringFormatter extends FormatterBase {
    +    if ($this->fieldDefinition->getType() === 'string' && $this->getSetting('link_to_entity') && ($entity = $items->getEntity()) && $entity->hasLinkTemplate('canonical')) {
    

    No need to check for the field type anymore :-)

berdir’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/RawStringFormatter.php
    @@ -12,13 +12,12 @@
      * @FieldFormatter(
    - *   id = "string",
    + *   id = "raw_string",
      *   label = @Translation("Plain text"),
    

    This will affect existing view display entities if you were using string for string_long fields.

    Just pointing out...

My only other thing was the same field definition check that @yched already pointed out. i think it's good to remove that, so that if you allow your field type for that formatter (formatter alter hook), then it works for that as well.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new18.29 KB
new9.6 KB

Thank you for the feedback!

larowlan’s picture

Really love this feature.
Reviewed code, couldn't fault it.
Manual review screenshots below.

I hate to be difficult - but changing all that config from 'string' to 'basic_string' is going to mean people in contrib land will have to do the same.
Any reason why we couldn't leave it as string and then make the new one 'string_link' ?

If there's a reason, then I think this is rtbc.

larowlan’s picture

yched’s picture

Any reason why we couldn't leave it as string and then make the new one 'string_link' ?

So the reasoning was that, for 'string' field type, we want only one formatter which optionally lets you link or not, rather than two formatters (one that links and one that doesn't). That's for consistency with how "link or not" works for image fields : it's an option within the image formatter.

Then it makes sense that this single formatter for the 'string' field type is the formatter that we call 'string', rather than "the 'string' formatter is used by a couple field types but *not* the 'string' field type, which in fact uses a formatter named 'string_link'".

yched’s picture

Silly question : would it make sense to have 'string_long' field type also use the 'string' formatter (the one that can link) ?

I kind of like the consistency of :
- 'string' / 'string_long' field types --> 'string' formatter
- 'email' / 'phone' / ... field types -> 'basic_string' formatter
But no strong opinion...

yched’s picture

Status: Needs review » Reviewed & tested by the community

re: #28 - discused with @dawehner, there's no use case for linking on long strings.

Current patch is RTBC as far as I'm concerned :-)

larowlan’s picture

Thanks @yched that makes sense - +1 RTBC from me then

catch’s picture

Looks good to me. I'd not have minded keeping the same name, but this is also a tiny update for contrib/custom code to make so I think that's OK given the issue is critical.

Not committing yet just so this has a bit longer than an hour at RTBC.

catch’s picture

Issue tags: +Needs change record

Will need some kind of change record though for that.

dawehner’s picture

Issue tags: -Needs change record

Sure, added the change record.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

gábor hojtsy’s picture

Issue tags: +D8MI, +language-content

Some retroactive D8MI tags.

Status: Fixed » Closed (fixed)

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