Problem/Motivation

In Drupal\node\Plugin\views\row\Rss::render:

$node->link = $node->toUrl('canonical', ['absolute' => TRUE])->toString();

Similar code exists in comment too.

If you have a field called link this will set $node->link->uri and do nothing else. Later

$item->link = $node->link;

Now clearly this wanted to put a string in there but instead this is a field item list and TwigExtension throws a fatal.

Steps to reproduce

  1. Remove the field_ prefix
  2. Add a field called link
  3. Add a node
  4. Create an RSS view
  5. Watch the WSOD

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Charlie ChX Negyesi created an issue. See original summary.

Ghost of Drupal Past’s picture

Title: Field called "link" breaks RSS » Field called "link" breaks the RSS Views plugins
Issue summary: View changes
longwave’s picture

Why does $node->link need to be set at all, can't it be set directly on $item?

Ghost of Drupal Past’s picture

Status: Active » Needs review
FileSize
2.44 KB

The problem is backwards compatibility: it's not impossible during the entity build process someone changes $node->link .

Now that I slept on it, fixing this is not that hard, just need to be explicit about it. After all, if some code does a $node->link = 'foo' during entity build that also just changes $node->link->uri much the same as the core code does so just retrieve that.

Berdir’s picture

That does seem like a weird fix, because the code is going to mess up your link field value. A few lines above, there is:

$node->link = $node->toUrl('canonical', ['absolute' => TRUE])->toString();

Honestly, what this is doing seems completely bogus.

Why set $node->link when the same function just a few lines down just fetches it again. It *does* pass the node through entity view builder inbetween, but I struggle to see why anyone would want to do something with $node->link during that time. Change the link target? They could do that in preprocess.

As far as I see, $node isn't even available through $item or the template later on, just the node ID.

Personally, I'd be happy to define that the behavior of arbitrary stuff that's put on nodes is not covered by BC, although we do have some very frequently used ones, like original or in_preview, we can make exceptions there.

So we could just switch this out to $item->link = $node->toUrl('canonical', ['absolute' => TRUE])->toString(); IMHO. We could even for BC check for $node->link being set and not being a field and then use that, together with a deprecation message. the only thing that would break is then trying to read that property during a hook_entity_view(). There might be ways to deal that too, e.g. set the property if not defined as a field (if that happens, the code would break anyway) and if it was changed, trigger a deprecation. But as mentioned, perfectly happy to not bother with that.

I can see that there are a handful of modules that use rss_elements (http://grep.xnddx.ru/search?text=-%3Erss_elements), I see the use case for that, but link?

I'd love to deprecate the ability to just put random stuff on entity objects completely as well a deprecating __get/__set, we have issues to instead have some kind of temporary storage that's explicit about it.

longwave’s picture

Version: 10.0.x-dev » 9.3.x-dev

I traced the origin of this code back to the very first version of Views for D7, it was added while porting Views from D6.

I think this is just a historical artifact and agree with @Berdir that this shouldn't be relied upon as an internal implementation detail of RSS output; as stated if someone wants to change the link they should probably be doing it in preprocess anyway.

Ghost of Drupal Past’s picture

FileSize
1.77 KB

To be fair, if not for BC this is the only sensible fix because if there is a field called link then assigning $node->link actually loses user entered data.

longwave’s picture

Status: Needs review » Reviewed & tested by the community

#7 is the simplest way to solve this issue. I checked the BC policy and the closest thing I can find is:

While the Render and Form APIs themselves are stable, the exposed data structures used to build and cache pages and forms are not.

which to me means I think we are OK to make this change.

  • catch committed c7f050d on 9.3.x
    Issue #3218024 by Charlie ChX Negyesi, longwave, Berdir: Field called "...

  • catch committed 5556b40 on 9.2.x
    Issue #3218024 by Charlie ChX Negyesi, longwave, Berdir: Field called "...
catch’s picture

Version: 9.3.x-dev » 9.2.x-dev
Status: Reviewed & tested by the community » Fixed

Yes #7 looks fine to me as well and #8 is correct on the bc policy.

Committed/pushed to 9.3.x and cherry-picked to 9.2.x, thanks!

Status: Fixed » Closed (fixed)

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