Unverified Commit f4fbbd1e authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2698057 by gambry, ryan.gibson, idebr, Mac_Weber, angelamnr, Martijn de...

Issue #2698057 by gambry, ryan.gibson, idebr, Mac_Weber, angelamnr, Martijn de Wit, chx, andypost, alexpott, Wim Leers, Jacine, dawehner, s_leu, Sam152: Add support for <nolink> and <none> to the LinkWidget UI
parent c7a275bf
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -79,6 +79,9 @@ protected static function getUriAsDisplayableString($uri) {
        $displayable_string = EntityAutocomplete::getEntityLabels([$entity]);
      }
    }
    elseif ($scheme === 'route') {
      $displayable_string = ltrim($displayable_string, 'route:');
    }

    return $displayable_string;
  }
@@ -111,6 +114,10 @@ protected static function getUserEnteredStringAsUri($string) {
      //    https://www.drupal.org/node/2423093.
      $uri = 'entity:node/' . $entity_id;
    }
    // Support linking to nothing.
    elseif (in_array($string, ['<nolink>', '<none>'], TRUE)) {
      $uri = 'route:' . $string;
    }
    // Detect a schemeless string, map to 'internal:' URI.
    elseif (!empty($string) && parse_url($string, PHP_URL_SCHEME) === NULL) {
      // @todo '<front>' is valid input for BC reasons, may be removed by
@@ -209,12 +216,12 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    // element prefix and description.
    if (!$this->supportsExternalLinks()) {
      $element['uri']['#field_prefix'] = rtrim(Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString(), '/');
      $element['uri']['#description'] = $this->t('This must be an internal path such as %add-node. You can also start typing the title of a piece of content to select it. Enter %front to link to the front page.', ['%add-node' => '/node/add', '%front' => '<front>']);
      $element['uri']['#description'] = $this->t('This must be an internal path such as %add-node. You can also start typing the title of a piece of content to select it. Enter %front to link to the front page. Enter %nolink to display link text only.', ['%add-node' => '/node/add', '%front' => '<front>', '%nolink' => '<nolink>']);
    }
    // If the field is configured to allow both internal and external links,
    // show a useful description.
    elseif ($this->supportsExternalLinks() && $this->supportsInternalLinks()) {
      $element['uri']['#description'] = $this->t('Start typing the title of a piece of content to select it. You can also enter an internal path such as %add-node or an external URL such as %url. Enter %front to link to the front page.', ['%front' => '<front>', '%add-node' => '/node/add', '%url' => 'http://example.com']);
      $element['uri']['#description'] = $this->t('Start typing the title of a piece of content to select it. You can also enter an internal path such as %add-node or an external URL such as %url. Enter %front to link to the front page. Enter %nolink to display link text only.', ['%front' => '<front>', '%add-node' => '/node/add', '%url' => 'http://example.com', '%nolink' => '<nolink>']);
    }
    // If the field is configured to allow only external links, show a useful
    // description.
+73 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Url;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
@@ -133,6 +134,11 @@ public function testURLValidation() {
      '<front>#example' => '&lt;front&gt;#example',
      '<front>?example=llama' => '&lt;front&gt;?example=llama',

      // Text-only links.
      '<nolink>' => '&lt;nolink&gt;',
      'route:<nolink>' => '&lt;nolink&gt;',
      '<none>' => '&lt;none&gt;',

      // Query string and fragment.
      '?example=llama' => '?example=llama',
      '#example' => '#example',
@@ -734,6 +740,73 @@ public function testEditNonNodeEntityLink() {
    $this->assertEquals($correct_link, $entity_test->get('field_link')->uri);
  }

  /**
   * Test <nolink> and <none> as link uri.
   */
  public function testNoLinkUri() {
    $field_name = mb_strtolower($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' => 'Read more about this entity',
      'bundle' => 'entity_test',
      'settings' => [
        'title' => DRUPAL_OPTIONAL,
        'link_type' => LinkItemInterface::LINK_INTERNAL,
      ],
    ])->save();

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

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

    // Test a link with <nolink> uri.
    $edit = [
      "{$field_name}[0][title]" => 'Title, no link',
      "{$field_name}[0][uri]" => '<nolink>',
    ];

    $this->drupalPostForm('/entity_test/add', $edit, t('Save'));
    preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
    $id = $match[1];
    $output = $this->renderTestEntity($id);
    $expected_link = (string) $this->container->get('link_generator')->generate('Title, no link', Url::fromUri('route:<nolink>'));
    $this->assertContains($expected_link, $output);

    // Test a link with <none> uri.
    $edit = [
      "{$field_name}[0][title]" => 'Title, none',
      "{$field_name}[0][uri]" => '<none>',
    ];

    $this->drupalPostForm('/entity_test/add', $edit, t('Save'));
    preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match);
    $id = $match[1];
    $output = $this->renderTestEntity($id);
    $expected_link = (string) $this->container->get('link_generator')->generate('Title, none', Url::fromUri('route:<none>'));
    $this->assertContains($expected_link, $output);
  }

  /**
   * Renders a test_entity and returns the output.
   *
+1 −1
Original line number Diff line number Diff line
@@ -197,7 +197,7 @@ public function runFieldUIItem($cardinality, $link_type, $title, $label, $field_

    $expected_help_texts = [
      LinkItemInterface::LINK_EXTERNAL => 'This must be an external URL such as <em class="placeholder">http://example.com</em>.',
      LinkItemInterface::LINK_GENERIC => 'You can also enter an internal path such as <em class="placeholder">/node/add</em> or an external URL such as <em class="placeholder">http://example.com</em>. Enter <em class="placeholder">&lt;front&gt;</em> to link to the front page.',
      LinkItemInterface::LINK_GENERIC => 'You can also enter an internal path such as <em class="placeholder">/node/add</em> or an external URL such as <em class="placeholder">http://example.com</em>. Enter <em class="placeholder">&lt;front&gt;</em> to link to the front page. Enter <em class="placeholder">&lt;nolink&gt;</em> to display link text only',
      LinkItemInterface::LINK_INTERNAL => rtrim(Url::fromRoute('<front>', [], ['absolute' => TRUE])->toString(), '/'),
    ];