Verified Commit fdd8dcc0 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3340154 by godotislate, smustgrave: Link-widget throws exception when...

Issue #3340154 by godotislate, smustgrave: Link-widget throws exception when rebuilding a form with an invalid uri

(cherry picked from commit 6b4fa61d)
parent 9fb6b609
Loading
Loading
Loading
Loading
Loading
+18 −4
Original line number Diff line number Diff line
@@ -184,14 +184,28 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    /** @var \Drupal\link\LinkItemInterface $item */
    $item = $items[$delta];

    $display_uri = NULL;
    if (!$item->isEmpty()) {
      try {
        // The current field value could have been entered by a different user.
        // However, if it is inaccessible to the current user, do not display it
        // to them.
        if (\Drupal::currentUser()->hasPermission('link to any page') || $item->getUrl()->access()) {
          $display_uri = static::getUriAsDisplayableString($item->uri);
        }
      }
      catch (\InvalidArgumentException $e) {
        // If $item->uri is invalid, show value as is, so the user can see what
        // to edit.
        // @todo Add logging here in https://www.drupal.org/project/drupal/issues/3348020
        $display_uri = $item->uri;
      }
    }
    $element['uri'] = [
      '#type' => 'url',
      '#title' => $this->t('URL'),
      '#placeholder' => $this->getSetting('placeholder_url'),
      // The current field value could have been entered by a different user.
      // However, if it is inaccessible to the current user, do not display it
      // to them.
      '#default_value' => (!$item->isEmpty() && (\Drupal::currentUser()->hasPermission('link to any page') || $item->getUrl()->access())) ? static::getUriAsDisplayableString($item->uri) : NULL,
      '#default_value' => $display_uri,
      '#element_validate' => [[static::class, 'validateUriElement']],
      '#maxlength' => 2048,
      '#required' => $element['#required'],
+68 −0
Original line number Diff line number Diff line
@@ -884,4 +884,72 @@ protected function renderTestEntity($id, $view_mode = 'full', $reset = TRUE) {
    return (string) $output;
  }

  /**
   * Test link widget exception handled if link uri value is invalid.
   */
  public function testLinkWidgetCaughtExceptionEditingInvalidUrl(): void {
    $field_name = $this->randomMachineName();
    $this->fieldStorage = FieldStorageConfig::create([
      'field_name' => $field_name,
      'entity_type' => 'entity_test',
      'type' => 'link',
      'cardinality' => 1,
    ]);
    $this->fieldStorage->save();
    FieldConfig::create([
      'field_storage' => $this->fieldStorage,
      'label' => 'Link',
      'bundle' => 'entity_test',
      'settings' => [
        'title' => DRUPAL_OPTIONAL,
        'link_type' => LinkItemInterface::LINK_GENERIC,
      ],
    ])->save();

    $entityTypeManager = $this->container->get('entity_type.manager');
    $entityTypeManager
      ->getStorage('entity_form_display')
      ->load('entity_test.entity_test.default')
      ->setComponent($field_name, [
        'type' => 'link_default',
      ])
      ->save();

    $entityTypeManager
      ->getStorage('entity_view_display')
      ->create([
        'targetEntityType' => 'entity_test',
        'bundle' => 'entity_test',
        'mode' => 'full',
        'status' => TRUE,
      ])
      ->setComponent($field_name, [
        'type' => 'link',
      ])
      ->save();

    // Entities can be saved without validation, for example via migration.
    // Link fields may contain invalid uris such as external URLs without
    // scheme.
    $invalidUri = 'www.example.com';
    $invalidLinkUrlEntity = $entityTypeManager
      ->getStorage('entity_test')
      ->create([
        'name' => 'Test entity with invalid link URL',
        $field_name => ['uri' => $invalidUri],
      ]);
    $invalidLinkUrlEntity->save();

    // If a user without 'link to any page' permission edits an entity, widget
    // checks access by converting uri to Url object, which will throw an
    // InvalidArgumentException if uri is invalid.
    $this->drupalLogin($this->drupalCreateUser([
      'view test entity',
      'administer entity_test content',
    ]));
    $this->drupalGet("/entity_test/manage/{$invalidLinkUrlEntity->id()}/edit");
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->fieldValueEquals("{$field_name}[0][uri]", $invalidUri);
  }

}