Unverified Commit 9d4138cb authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2454915 by SaschaHannes, anevins, Spokje, ducktape, joseph.olstad,...

Issue #2454915 by SaschaHannes, anevins, Spokje, ducktape, joseph.olstad, marcoliver, dschenk, Dom., larowlan, isholgueras: Entity link annotations in HTML head are not valid HTML
parent 24a533ab
Loading
Loading
Loading
Loading
+46 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ public function view(EntityInterface $node, $view_mode = 'full', $langcode = NUL
      // This means that the page will vary by user.permissions. We also rely on
      // the access checking fallback to ensure the correct cacheability
      // metadata if we have to check access.
      if ($this->currentUser->isAuthenticated() || $url->access($this->currentUser)) {
      if ($this->isValidRel($rel) && ($this->currentUser->isAuthenticated() || $url->access($this->currentUser))) {
        // Set the node path as the canonical URL to prevent duplicate content.
        $build['#attached']['html_head_link'][] = [
          [
@@ -123,4 +123,49 @@ public function title(EntityInterface $node) {
    return $this->entityRepository->getTranslationFromContext($node)->label();
  }

  /**
   * Checks if rel attribute is w3c.org valid
   *
   * @param string $rel
   *   The unchecked rel attribute.
   *
   * @return bool
   *   The valid state
   *
   * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel
   */
  private function isValidRel($rel) : bool {
    // List of all supported rel tags.
    $validRelList = [
      'alternate',
      'author',
      'bookmark',
      'canonical',
      'dns-prefetch',
      'external',
      'help',
      'icon',
      'license',
      'manifest',
      'modulepreload',
      'next',
      'nofollow',
      'noopener',
      'noreferrer',
      'opener',
      'pingback',
      'preconnect',
      'prefetch',
      'preload',
      'prerender',
      'prev',
      'search',
      'shortcut icon',
      'shortlink',
      'stylesheet',
      'tag',
    ];
    return in_array($rel, $validRelList, TRUE);
  }

}
+2 −24
Original line number Diff line number Diff line
@@ -43,31 +43,10 @@ public function testHtmlHeadLinks() {

    // Link relations are present regardless of access for authenticated users.
    $result = $this->xpath('//link[@rel = "version-history"]');
    $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('version-history')->setAbsolute()->toString());
    $this->assertEmpty($result);

    $result = $this->xpath('//link[@rel = "edit-form"]');
    $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('edit-form')->setAbsolute()->toString());

    // Give anonymous users access to edit the node. Do this through the UI to
    // ensure caches are handled properly.
    $this->drupalLogin($this->rootUser);
    $edit = [
      'anonymous[edit own ' . $node->bundle() . ' content]' => TRUE,
    ];
    $this->drupalPostForm('admin/people/permissions', $edit, 'Save permissions');
    $this->drupalLogout();

    // Anonymous user's should now see the edit-form link but not the
    // version-history link.
    $this->drupalGet($node->toUrl());
    $result = $this->xpath('//link[@rel = "canonical"]');
    $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl()->setAbsolute()->toString());

    $result = $this->xpath('//link[@rel = "version-history"]');
    $this->assertEmpty($result, 'Version history not present for anonymous users without access.');

    $result = $this->xpath('//link[@rel = "edit-form"]');
    $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('edit-form')->setAbsolute()->toString());
    $this->assertEmpty($result);
  }

  /**
@@ -79,7 +58,6 @@ public function testLinkHeader() {
    $expected = [
      '<' . Html::escape($node->toUrl('canonical')->setAbsolute()->toString()) . '>; rel="canonical"',
      '<' . Html::escape($node->toUrl('canonical')->setAbsolute()->toString(), ['alias' => TRUE]) . '>; rel="shortlink"',
      '<' . Html::escape($node->toUrl('revision')->setAbsolute()->toString()) . '>; rel="revision"',
    ];

    $this->drupalGet($node->toUrl());