Link-widget throws exception when rebuilding a form with an invalid uri

Created on 8 February 2023, almost 2 years ago
Updated 1 March 2024, 10 months ago

Problem/Motivation

I ran into a little issue with paragraphs where one of the paragraphs has a linkit-field (its widget extends the link field widget). When the user types in an invalid uri and then tries to add a new paragraph-item, an exception is preventing the new paragraph to be added.
One part of the problem is that the add-more button in paragraphs has a limit_validation_errors, so no validation is done or error is shown at all. I tried removing this, but that didn't work properly: it would validate the whole form and show error-messages in a way that's confusing for the user. After a bit of digging, I found that the error is an exception thrown when trying to make an Url-object from the invalid uri. So after adding a try/catch, it works fine :)

I think the problem is because the form is rebuilt without proper validation. In this case, the link-field considers the default value to be validated and tries to build a url-object out of the value. This fails, because the value is not a valid uri.

Steps to reproduce

  • requires the paragraphs module
  • setup a node type that has a paragraph field, which has a link-field
  • go to the node-add form
  • type in an invalid uri: just some random letters is fine
  • press the button to add another paragraph item
  • no error is shown, and also no new paragraph-item is added: the exception is in the log

Alternate steps:

  • Install Drupal with standard profile
  • Add link field (machine name: field_link) to Article content type. Allow both internal and external URLs.
  • Use some method (e.g. migration, cli) other than the node form to create and save Article node with an invalid URL. Such as using Drush: drush php-eval "Drupal::entityTypeManager()->getStorage('node')->create(['type' => 'article', 'title' => 'test', 'field_link' => ['uri' => 'www.example.com']])->save();"
  • Update `content_editor` role permissions and make sure:
    • content editor has permission to edit any Article content
    • content editor does not have permission to link to any page
  • Create a new user and assign content editor role
  • Log in as content editor
  • Go to edit the node and observe:
    The website encountered an unexpected error. Try again later.
    
    InvalidArgumentException: The URI 'www.example.com' is invalid. You must use a valid URI scheme. in Drupal\Core\Url::fromUri() (line 293 of core/lib/Drupal/Core/Url.php).
    Drupal\link\Plugin\Field\FieldType\LinkItem->getUrl() (Line: 194)
    Drupal\link\Plugin\Field\FieldWidget\LinkWidget->formElement(Object, 0, Array, Array, Object) (Line: 440)
    Drupal\Core\Field\WidgetBase->formSingleElement(Object, 0, Array, Array, Object) (Line: 210)
    Drupal\Core\Field\WidgetBase->formMultipleElements(Object, Array, Object) (Line: 111)
    Drupal\Core\Field\WidgetBase->form(Object, Array, Object) (Line: 186)
    Drupal\Core\Entity\Entity\EntityFormDisplay->buildForm(Object, Array, Object) (Line: 121)
    Drupal\Core\Entity\ContentEntityForm->form(Array, Object) (Line: 127)
    Drupal\node\NodeForm->form(Array, Object) (Line: 107)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 536)
    Drupal\Core\Form\FormBuilder->retrieveForm('node_article_edit_form', Object) (Line: 283)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 591)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 182)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
    
  • Proposed resolution

    Add a try/catch around getting the url-object.

    Remaining tasks

    Add tests

    User interface changes

    -

    API changes

    -

    Data model changes

    -

    Release notes snippet

πŸ› Bug report
Status

Fixed

Version

10.2 ✨

Component
LinkΒ  β†’

Last updated 6 days ago

Created by

πŸ‡³πŸ‡±Netherlands spadxiii

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

Merge Requests

Comments & Activities

Production build 0.71.5 2024