Issue #1272870 by mvc, mgifford, xjm, Drupali, Everett Zufelt: Fixed No semantics for nested comments / bad for screen-readers.

8.0.x
webchick 2012-10-27 12:41:47 -07:00
parent 95ce944803
commit 6c7fa21356
3 changed files with 158 additions and 38 deletions

View File

@ -1657,6 +1657,30 @@ function template_preprocess_comment(&$variables) {
$variables['permalink'] = l(t('Permalink'), $uri['path'], $uri['options']);
$variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['author'], '!datetime' => $variables['created']));
if ($comment->pid > 0) {
// Fetch and store the parent comment information for use in templates.
$comment_parent = comment_load($comment->pid);
$variables['parent_comment'] = $comment_parent;
$variables['parent_author'] = theme('username', array('account' => $comment_parent));
$variables['parent_created'] = format_date($comment_parent->created);
$variables['parent_changed'] = format_date($comment_parent->changed);
$uri_parent = $comment_parent->uri();
$uri_parent['options'] += array('attributes' => array('class' => 'permalink', 'rel' => 'bookmark'));
$variables['parent_title'] = l($comment_parent->subject, $uri_parent['path'], $uri_parent['options']);
$variables['parent_permalink'] = l(t('Parent permalink'), $uri_parent['path'], $uri_parent['options']);
$variables['parent'] = t('In reply to !parent_title by !parent_username',
array('!parent_username' => $variables['parent_author'], '!parent_title' => $variables['parent_title']));
}
else {
$variables['parent_comment'] = '';
$variables['parent_author'] = '';
$variables['parent_created'] = '';
$variables['parent_changed'] = '';
$variables['parent_title'] = '';
$variables['parent_permalink'] = '';
$variables['parent'] = '';
}
// Preprocess fields.
field_attach_preprocess('comment', $comment, $variables['elements'], $variables);

View File

@ -40,64 +40,138 @@ class CommentThreadingTest extends CommentTestBase {
$this->drupalLogin($this->web_user);
$subject_text = $this->randomName();
$comment_text = $this->randomName();
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
$comment_loaded = comment_load($comment->id);
$this->assertTrue($this->commentExists($comment), 'Comment #1. Comment found.');
$this->assertEqual($comment_loaded->thread, '01/');
$comment1 = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
// Confirm that the comment was created and has the correct threading.
$comment1_loaded = comment_load($comment1->id);
$this->assertTrue($this->commentExists($comment1), 'Comment #1. Comment found.');
$this->assertEqual($comment1_loaded->thread, '01/');
// Confirm that there is no reference to a parent comment.
$this->assertNoParentLink($comment1->id);
// Reply to comment #1 creating comment #2.
$this->drupalLogin($this->web_user);
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #2. Reply found.');
$this->assertEqual($reply_loaded->thread, '01.00/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment1->id);
$comment2 = $this->postComment(NULL, $this->randomName(), '', TRUE);
// Confirm that the comment was created and has the correct threading.
$comment2_loaded = comment_load($comment2->id);
$this->assertTrue($this->commentExists($comment2, TRUE), 'Comment #2. Reply found.');
$this->assertEqual($comment2_loaded->thread, '01.00/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment2->id, $comment1->id);
// Reply to comment #2 creating comment #3.
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply->id);
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #3. Second reply found.');
$this->assertEqual($reply_loaded->thread, '01.00.00/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment2->id);
$comment3 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
// Confirm that the comment was created and has the correct threading.
$comment3_loaded = comment_load($comment3->id);
$this->assertTrue($this->commentExists($comment3, TRUE), 'Comment #3. Second reply found.');
$this->assertEqual($comment3_loaded->thread, '01.00.00/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment3->id, $comment2->id);
// Reply to comment #1 creating comment #4.
$this->drupalLogin($this->web_user);
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($comment), 'Comment #4. Third reply found.');
$this->assertEqual($reply_loaded->thread, '01.01/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment1->id);
$comment4 = $this->postComment(NULL, $this->randomName(), '', TRUE);
// Confirm that the comment was created and has the correct threading.
$comment4_loaded = comment_load($comment4->id);
$this->assertTrue($this->commentExists($comment4), 'Comment #4. Third reply found.');
$this->assertEqual($comment4_loaded->thread, '01.01/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment4->id, $comment1->id);
// Post comment #2 overall comment #5.
$this->drupalLogin($this->web_user);
$subject_text = $this->randomName();
$comment_text = $this->randomName();
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
$comment_loaded = comment_load($comment->id);
$this->assertTrue($this->commentExists($comment), 'Comment #5. Second comment found.');
$this->assertEqual($comment_loaded->thread, '02/');
$comment5 = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
// Confirm that the comment was created and has the correct threading.
$comment5_loaded = comment_load($comment5->id);
$this->assertTrue($this->commentExists($comment5), 'Comment #5. Second comment found.');
$this->assertEqual($comment5_loaded->thread, '02/');
// Confirm that there is no link to a parent comment.
$this->assertNoParentLink($comment5->id);
// Reply to comment #5 creating comment #6.
$this->drupalLogin($this->web_user);
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #6. Reply found.');
$this->assertEqual($reply_loaded->thread, '02.00/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment5->id);
$comment6 = $this->postComment(NULL, $this->randomName(), '', TRUE);
// Confirm that the comment was created and has the correct threading.
$comment6_loaded = comment_load($comment6->id);
$this->assertTrue($this->commentExists($comment6, TRUE), 'Comment #6. Reply found.');
$this->assertEqual($comment6_loaded->thread, '02.00/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment6->id, $comment5->id);
// Reply to comment #6 creating comment #7.
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply->id);
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #7. Second reply found.');
$this->assertEqual($reply_loaded->thread, '02.00.00/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment6->id);
$comment7 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
// Confirm that the comment was created and has the correct threading.
$comment7_loaded = comment_load($comment7->id);
$this->assertTrue($this->commentExists($comment7, TRUE), 'Comment #7. Second reply found.');
$this->assertEqual($comment7_loaded->thread, '02.00.00/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment7->id, $comment6->id);
// Reply to comment #5 creating comment #8.
$this->drupalLogin($this->web_user);
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
$reply_loaded = comment_load($reply->id);
$this->assertTrue($this->commentExists($comment), 'Comment #8. Third reply found.');
$this->assertEqual($reply_loaded->thread, '02.01/');
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment5->id);
$comment8 = $this->postComment(NULL, $this->randomName(), '', TRUE);
// Confirm that the comment was created and has the correct threading.
$comment8_loaded = comment_load($comment8->id);
$this->assertTrue($this->commentExists($comment8), 'Comment #8. Third reply found.');
$this->assertEqual($comment8_loaded->thread, '02.01/');
// Confirm that there is a link to the parent comment.
$this->assertParentLink($comment8->id, $comment5->id);
}
/**
* Asserts that the link to the specified parent comment is present.
*
* @parm int $cid
* The comment ID to check.
* @param int $pid
* The expected parent comment ID.
*/
protected function assertParentLink($cid, $pid) {
// This pattern matches a markup structure like:
// <a id="comment-2"></a>
// <article>
// <p class="parent">
// <a href="...comment-1"></a>
// </p>
// </article>
$pattern = "//a[@id='comment-$cid']/following-sibling::article//p[contains(@class, 'parent')]//a[contains(@href, 'comment-$pid')]";
$this->assertFieldByXpath($pattern, NULL, format_string(
'Comment %cid has a link to parent %pid.',
array(
'%cid' => $cid,
'%pid' => $pid,
)
));
}
/**
* Asserts that the specified comment does not have a link to a parent.
*
* @parm int $cid
* The comment ID to check.
*/
protected function assertNoParentLink($cid) {
// This pattern matches a markup structure like:
// <a id="comment-2"></a>
// <article>
// <p class="parent"></p>
// </article>
$pattern = "//a[@id='comment-$cid']/following-sibling::article//p[contains(@class, 'parent')]";
$this->assertNoFieldByXpath($pattern, NULL, format_string(
'Comment %cid does not have a link to a parent.',
array(
'%cid' => $cid,
)
));
}
}

View File

@ -43,6 +43,20 @@
* modules, intended to be displayed after the main title tag that appears in
* the template.
*
* These variables are provided to give context about the parent comment (if
* any):
* - $comment_parent: Full parent comment object (if any).
* - $parent_author: Equivalent to $author for the parent comment.
* - $parent_created: Equivalent to $created for the parent comment.
* - $parent_changed: Equivalent to $changed for the parent comment.
* - $parent_title: Equivalent to $title for the parent comment.
* - $parent_permalink: Equivalent to $permalink for the parent comment.
* - $parent: A text string of parent comment submission information created
* from $parent_author and $parent_created during
* template_preprocess_comment(). This information is presented to help
* screen readers follow lengthy discussion threads. You can hide this from
* sighted users using the class element-invisible.
*
* These two variables are provided for context:
* - $comment: Full comment object.
* - $node: Node entity the comments are attached to.
@ -67,6 +81,14 @@
<footer>
<?php print $user_picture; ?>
<p class="submitted"><?php print $submitted; ?></p>
<?php
// Indicate the semantic relationship between parent and child comments
// for accessibility. The list is difficult to navigate in a screen
// reader without this information.
if ($parent):
?>
<p class="parent element-invisible"><?php print $parent; ?></p>
<?php endif; ?>
<?php print $permalink; ?>
</footer>