Path module calls getInternalPath without checking if the url is routed

Created on 16 February 2023, almost 2 years ago
Updated 14 August 2024, 4 months ago

Problem/Motivation

When customising the toUrl method of an entity, such as with bundle classes, its possible to return non-routable Url objects.

\Drupal\path\Plugin\Field\FieldType\PathFieldItemList::computeValue assumes that all Urls returned by \Drupal\Core\Entity\EntityInterface::toUrl are routable.

When this code path executes, with a non-routable Url, the following exception is thrown:

UnexpectedValueException: Unrouted URIs do not have internal representations. in Drupal\Core\Url->getInternalPath() (line 798 of core/lib/Drupal/Core/Url.php).

Drupal\path\Plugin\Field\FieldType\PathFieldItemList->computeValue() (Line: 33)
....

Path.module should simply handle non-routable Urls.

Original report

I'm using a bundle class to override the toUrl() method on a particular node type. In particular, there's a link field that, if populated, will be used by the toUrl() method. The reason is that we want to allow cards to link to internal or external links (or no link whatsoever) as elegantly as possible. The code looks like this:

  public function toUrl($rel = 'canonical', array $options = []) {
    if ($rel === 'canonical') {
      if (!empty($this->field_link->uri)) {
        return Url::fromUri($this->field_link->uri);
      }
      else {
        return Url::fromRoute('<nolink>');
      }
    }
    return parent::toUrl($rel, $options);
  }

I can successfully create such a node and the behavior of toUrl is as hoped.

Unfortunately, editing the node is not so smooth. The path module throws an erro:

UnexpectedValueException: Unrouted URIs do not have internal representations. in Drupal\Core\Url->getInternalPath() (line 798 of core/lib/Drupal/Core/Url.php).

Drupal\path\Plugin\Field\FieldType\PathFieldItemList->computeValue() (Line: 33)
....

When I fix that by hacking core a bit then I get to the next exception:

UnexpectedValueException: Unrouted URIs do not have internal representations. in Drupal\Core\Url->getInternalPath() (line 798 of core/lib/Drupal/Core/Url.php).

Drupal\path\Plugin\Field\FieldWidget\PathWidget->formElement(Object, 0, Array, Array, Object) (Line: 19)
....

When I fix that then everything is grand.

These exceptions happen even if the url alias element is not on the node form display for this node type.

Steps to reproduce

Return a non-routable Url from a entity::toUrl, such as with a bundle class.

Proposed resolution

path.module needs to check that $entity->toUrl()->isRouted() in addition to its existing checks for !$entity->isNew() in a couple places.

Remaining tasks

Tips for manual testing

Apply the test-only patch.

Enable entity_test, path, and path_entity_test_external. (To enable test modules, add $settings['extension_discovery_scan_tests'] = TRUE; to your settings.php.)

Then go to /entity_test_external/add and create and edit these entities. See the errors.

Then apply the fix and see that creating and editing these entities works. And everything should still work for nodes and media, etc.

User interface changes

N/A

API changes

TBD

Data model changes

N/A

Release notes snippet

TBD

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Path 

Last updated 32 minutes ago

  • Maintained by
  • 🇬🇧United Kingdom @catch
Created by

🇺🇸United States danflanagan8 St. Louis, US

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024