Problem/Motivation

If you have a file field on an entity without a canonical link template, visiting file/ID/usage throws an exception.

The reason is that the EntityLabel plugin unconditionally calls toUrl().

To reproduce, install contact_storage, add a file filed to the contact form, fill out the contact form and then visit the file usage page for that file.

Proposed resolution

Check if the canonical link template exists before trying to display a link.

Other places and views plugins might be affected by this too.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Berdir created an issue. See original summary.

xjm’s picture

Issue tags: +VDC
alexpott’s picture

Issue tags: +Triaged core major

Discussed with @xjm and @catch. We agree that this is major because if an entity don't have a canonical link template and you attach file fields a core provided view will break.

gaborpeter’s picture

Assigned: Unassigned » gaborpeter
Status: Active » Needs work
Issue tags: +DCTransylvania
gaborpeter’s picture

Assigned: gaborpeter » Unassigned
Status: Needs work » Needs review
StatusFileSize
new141.06 KB
new807 bytes

I've been able to reproduce the bug, patch attached.
Thanks for the example module, it helped to speed up the process.
After patch screenshot attached as well.

mariancalinro’s picture

Status: Needs review » Reviewed & tested by the community

The code looks good.
I tested on simplytest.me, and can confirm that it works.

joshi.rohit100’s picture

Status: Reviewed & tested by the community » Needs work

Instead to get all templates first and then check, we also have hasLinkTemplate() for entity.

mariancalinro’s picture

Assigned: Unassigned » mariancalinro
Status: Needs work » Active
gaborpeter’s picture

Status: Active » Needs review
StatusFileSize
new755 bytes

You're totally right, thanks for the tip.
Here is the tested patch.

mariancalinro’s picture

Assigned: mariancalinro » Unassigned
StatusFileSize
new738 bytes
gaborpeter’s picture

Patch #10 works for me, you're right getEntityType() is not needed as well.

berdir’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Fix looks good but we need tests.

I assume we have existing tests for the file usage page. In that test, also enable entity_test and pick one of the entity types tere that don't have a canonical link template. create one and add a usage to a file, then make sure the page doesn't break and doesn't try to create a link for that.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

justachris’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new2.38 KB
new3.1 KB

Added WebTest pretty much following the directions outlined by @berdir in #12

Interdiff is the test-only patch

The last submitted patch, 14: file_usage_view_breaks-2676552-14-test-only.patch, failed testing.

swentel’s picture

+++ b/core/modules/file/src/Tests/FileListingTest.php
@@ -145,6 +146,48 @@ function testFileListingPages() {
+      'name' => $entity_name,
...
+    // Linked entity name should not be displayed if there is no link template.
+    $this->assertNoLink($entity_name, 'Linked entity not added to usage listing');

I'm wondering whether we should add a positive assert as well, something like assertText($entity_name) ? I always like those more a little more. Shouldn't hold up commit though, rest looks good to me.

justachris’s picture

Good idea @swentel
Added the positive assertion for the entity name. Had to replace the test entity type used with another to allow the entity name to display.

The last submitted patch, 17: file_usage_view_breaks-2676552-17-test-only.patch, failed testing.

mbovan’s picture

Stumbled upon this... It looks like we need to explicitly set make_link to FALSE if there is no "canonical" template. Otherwise, in case of multiple usages, no-canonical entity's name is linked with a URL from a canonical-entity.

Uploaded a patch with 2 usages (canonical/non-canonical) as test-only example.

Status: Needs review » Needs work

The last submitted patch, 19: file_usage_view_breaks-2676552-19.patch, failed testing.

mbovan’s picture

Status: Needs work » Needs review
StatusFileSize
new3.54 KB

Correct patch.

justachris’s picture

Status: Needs review » Needs work

@mbovan Good catch on output with multiple usages on the file. Can you upload an updated test-only patch to show a test failure in that scenario?

Setting to Needs Work since I think that updating the tests to show that failure is relevant to the issue.

mbovan’s picture

Status: Needs work » Needs review

Actually, I got an exception while working on a client project where the fix is a patch from #21.

On a clear 8.1.x branch, I cannot reproduce it... Also, seems like node usage #19 patch is not failing on testbot, so I'm removing my patches and pointing to #17 as the latest valid patch, for now...

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +DevDaysMilan

This solves the problem, seemed to be quite reasonable.

alexpott’s picture

Also if we #2402533: Provide File::createFileUrl() as a replacement for the deprecated File:url() implementation then this issue is fixed for files - but not for other entities without a canonical template.

joshi.rohit100’s picture

Yes thats right. If I remember correctly, I faced this issue in paragraph module as well as there was no canonical for that.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/views/src/Plugin/views/field/EntityLabel.php
@@ -105,8 +105,13 @@ public function render(ResultRow $values) {
+      if ($entity->hasLinkTemplate('canonical')) {
+        $this->options['alter']['make_link'] = TRUE;
+        $this->options['alter']['url'] = $entity->toUrl();
+      }
+      else {
+        $this->options['alter']['make_link'] = FALSE;
+      }

I don't think we should be checking for a link template here. I think we need to be calling $entity->toUrl() and catching UndefinedLinkTemplateException and EntityMalformedException and in this instance setting make_link to FALSE.

This is because it is possible to provide URLs without link templates - see #2402533: Provide File::createFileUrl() as a replacement for the deprecated File:url() implementation and also the uri_callback annotation.

chr.fritsch’s picture

Status: Needs work » Needs review
StatusFileSize
new3.96 KB

I adjusted the patch with alex hints

mtodor’s picture

Patch looks good.

cyberschorsch’s picture

Status: Needs review » Reviewed & tested by the community

Looks good for me as well.
Marking as RTBC

xjm’s picture

+++ b/core/modules/views/src/Plugin/views/field/EntityLabel.php
@@ -105,8 +107,14 @@ public function render(ResultRow $values) {
+      try {
+        $this->options['alter']['url'] = $entity->toUrl();
+        $this->options['alter']['make_link'] = TRUE;
+      } catch (UndefinedLinkTemplateException $e) {
+        $this->options['alter']['make_link'] = FALSE;
+      } catch (EntityMalformedException $e) {
+        $this->options['alter']['make_link'] = FALSE;
+      }

One small thing we could clean up here is that this does not follow our coding standards for control structures -- see: https://www.drupal.org/coding-standards#controlstruct

This could be fixed on commit (so leaving RTBC), but also would be easy to clean up in a patch. :)

chr.fritsch’s picture

StatusFileSize
new3.97 KB

Just fixing the coding style issues

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/file/src/Tests/FileListingTest.php
    @@ -145,6 +146,55 @@ function testFileListingPages() {
    +    // Entity name should be displayed, but not linked if there is no canonical
    +    // link template.
    

    This comment is not quite right - it is if Entity::toUrl throws an exception.

  2. +++ b/core/modules/file/src/Tests/FileListingTest.php
    @@ -145,6 +146,55 @@ function testFileListingPages() {
    +    $this->assertNoLink($entity_name, 'Linked entity name not added to file usage listing.');
    

    This test will break once #2402533: Provide File::createFileUrl() as a replacement for the deprecated File:url() implementation lands... which indicates we should have a test that is not tied to file entities. Maybe using the entity_test entity and not having a canonical link.

chr.fritsch’s picture

Status: Needs work » Needs review
StatusFileSize
new3.96 KB

1. Fixed

2. We discussed that with alexpott and came to the point that #2402533: Provide File::createFileUrl() as a replacement for the deprecated File:url() implementation will not break the test, because the test covers the relation from a file to an entity. Not the other way round

So IMHO we can move this fast to RTBC

alexpott’s picture

@chr.fritsch yep #34.2 was wrong - sorry everyone.

cyberschorsch’s picture

Status: Needs review » Reviewed & tested by the community

Then we are done here :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed bbcd3bd and pushed to 8.1.x and 8.2.x. Thanks!

diff --git a/core/modules/views/src/Plugin/views/field/EntityLabel.php b/core/modules/views/src/Plugin/views/field/EntityLabel.php
index 3c7ccfb..967fd52 100644
--- a/core/modules/views/src/Plugin/views/field/EntityLabel.php
+++ b/core/modules/views/src/Plugin/views/field/EntityLabel.php
@@ -110,9 +110,11 @@ public function render(ResultRow $values) {
       try {
         $this->options['alter']['url'] = $entity->toUrl();
         $this->options['alter']['make_link'] = TRUE;
-      } catch (UndefinedLinkTemplateException $e) {
+      }
+      catch (UndefinedLinkTemplateException $e) {
         $this->options['alter']['make_link'] = FALSE;
-      } catch (EntityMalformedException $e) {
+      }
+      catch (EntityMalformedException $e) {
         $this->options['alter']['make_link'] = FALSE;
       }
     }

Fixed coding standards on commit.

  • alexpott committed 705b75c on 8.2.x
    Issue #2676552 by justAChris, mbovan, chr.fritsch, gaborpeter,...

  • alexpott committed bbcd3bd on 8.1.x
    Issue #2676552 by justAChris, mbovan, chr.fritsch, gaborpeter,...

Status: Fixed » Closed (fixed)

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

gábor hojtsy’s picture

Issue tags: +Media Initiative
gábor hojtsy’s picture

Issue tags: -Media Initiative +D8Media

Fix for use of current tag. Sorry for using the wrong one.

rosinegrean’s picture

Issue tags: -DCTransylvania