Problem/Motivation

From #749748: Contact, register and comment forms do not prefill with user info from browser

Looks like we're missing test coverage for anonymous contact info in comments.

      // @todo Complete test coverage for:
      //'comments'        => array(CommentItemInterface::OPEN, CommentItemInterface::CLOSED, CommentInterface::_HIDDEN),
      //// COMMENT_ANONYMOUS_MUST_CONTACT is irrelevant for this test.
      //'contact '        => array(COMMENT_ANONYMOUS_MAY_CONTACT, COMMENT_ANONYMOUS_MAYNOT_CONTACT),

But whilst looking into it, CommentLinksTest is a behemoth.

Proposed resolution

Make comment links unit testable by

  • Converting the logic to a service √
  • Injecting the dependencies √
  • Writing a data provider and adding PHP Unit tests. √
  • Fixing failures√

Remaining tasks

Fix the tests (make the asserts smarter than just assertEquals on $expected)
Patch

User interface changes

None

API changes

New CommentLinkBuilderInterface and new CommentLinkBuilder service
COMMENT_FORM_BELOW and COMMENT_FORM_SEPARATE_PAGE moved to Drupal\comment\Plugin\Field\FieldType\CommentItem::FORM_BELOW and FORM_SEPARATE_PAGE

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

larowlan’s picture

Assigned: Unassigned » larowlan

Having a look

larowlan’s picture

Wow that is a pants test.
Took 20 minutes on my local.
So first order of business - convert it to PHPUnit.

Here's the guts of it.

Needs - fix the $expected values.
Needs - PHPCS/Docblocks.

There are 1920 combinations, so this function is way off the cyclic complexity chart.

PHPUnit tests them in no time.

Test will fail miserably cause I've not gone through to set up the expected output yet.

Will need to think about how to do that smarter.

larowlan’s picture

Title: Missing test coverage for anonymous commenter contact details » Make comment links functionality testable and convert CommentLinkTest to PHPUnit
Issue summary: View changes
larowlan’s picture

Moving in the right direction

larowlan’s picture

Status: Active » Needs review
FileSize
57 KB
20.73 KB
46.61 KB

Finished PHP Unit tests, cleaned up original web test to just make sure that the hook is invoked and basic links are output - (now takes 53 secs instead of 20 mins locally) - remainder of the scenarios now handled instead by the much-faster PHP Unit - where we have 100% test coverage.

Status: Needs review » Needs work

The last submitted patch, 5: comment-links-2318251.3.patch, failed testing.

larowlan’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: +Needs change record
FileSize
1.13 KB
46.85 KB

whoops, changed my mind on which item to put the form constants on

larowlan’s picture

Issue summary: View changes
larowlan’s picture

thehong’s picture

I think comment is no longer tied to to Node, can you explain why NodeInterface is used in CommentLinkBuilder? Thanks

larowlan’s picture

At the moment links are only shown for nodes.

larowlan’s picture

Refactored away the Node bits, cause node module might not be enabled so those type hints aren't much use.
Also, we can make this generic and part of the formatter as planned.
Also fixed missing docblocks

Status: Needs review » Needs work

The last submitted patch, 12: comment-links-2318251.5.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
3.18 KB
209.36 KB

Yeah, $links was already being used » $entity_links

larowlan’s picture

re-roll

larowlan’s picture

thehong’s picture

+++ b/core/modules/comment/src/CommentLinkBuilder.php
@@ -0,0 +1,222 @@
+    $fields = $this->commentManager->getFields('node');

I think we should inject 'node' string to this service, it's easier for developer to use it for other entity.

andypost’s picture

andypost’s picture

@thehong "node" is a entity type argument, I can't get what you mean

thehong’s picture

@andypost Instead of

\Drupal::service('comment.link_builder')->buildLinks($node_links, $node, $context);

we should change it to:

\Drupal::service('comment.link_builder')->buildLinks('node', $node_links, $node, $context);

dawehner’s picture

\Drupal::service('comment.link_builder')->buildLinks('node', $node_links, $node, $context);

This doens't make sense. The entity itself ($node) already knows about everything which is needed. (it's entity type ID).
No need to fallback to Drupal 7 APIs.

Just an airport review.

  1. +++ b/core/modules/comment/comment.module
    @@ -48,16 +48,6 @@
     /**
    - * Comment form should be displayed on a separate page.
    - */
    -const COMMENT_FORM_SEPARATE_PAGE = 0;
    -
    -/**
    - * Comment form should be shown below post or list of comments.
    - */
    -const COMMENT_FORM_BELOW = 1;
    -
    

    <3

  2. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    + * Defines a class for building markup for comment links on a commented entity.
    + *
    + * Comment links include 'login to post new comment', 'add new comment' etc.
    + */
    

    i really like to have a proper one line description which explains what is going on.

  3. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +   * Current user proxy.
    +   *
    +   * @var \Drupal\Core\Session\AccountProxyInterface
    +   */
    

    Always typehint the accountinterface and don't talk about the proxy. this is just an implementation detail.

  4. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +    if ($view_mode == 'search_index' || $view_mode == 'search_result' || $view_mode == 'print') {
    +      // Do not add any links if the node displayed for:
    +      // - search indexing.
    ...
    +      // - print.
    +      return;
    +    }
    +
    ...
    +        if ($view_mode == 'rss') {
    +          // Add a comments RSS element which is a URL to the comments of this
    +          // entity.
    +          $options = array(
    +            'fragment' => 'comments',
    +            'absolute' => TRUE,
    +          );
    +          $entity->rss_elements[] = array(
    +            'key' => 'comments',
    +            'value' => $entity->url('canonical', $options),
    +          );
    +        }
    +        elseif ($view_mode == 'teaser') {
    

    I know this is out of scope but can't we somehow integrate these links properly into the entity display bits? These links should be for example be configurable per view mode.

  5. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +      $commenting_status = $entity->get($field_name)->status;
    +      if ($commenting_status) {
    

    Oh I nearly got tricked by the fact that status is a part of the comment field. Any reason to not use != CommentItemInterface::HIDDEN ?

  6. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +                'title' => $this->formatPlural($entity->get($field_name)->comment_count, '1 comment', '@count comments'),
    ...
    +                'html' => TRUE,
    

    Wait, this string does not contain any HTML, or does it?

  7. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +              if ($this->moduleHandler->moduleExists('history')) {
    +                $links['comment-new-comments'] = array(
    

    Urgs, would be so much better to kinda make it more flexible and less hardcoded

  8. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +                    'title' => $this->getStringTranslation()->translate('Jump to the first new comment of this posting.'),
    

    You have to use $this->t() otherwise potx cannot find it. Out of scope of this issue.

  9. +++ b/core/modules/comment/src/CommentLinkBuilder.php
    @@ -0,0 +1,222 @@
    +                  'html' => TRUE,
    

    Same question, this is not even HTML at all.

  10. +++ b/core/modules/comment/tests/src/CommentLinkBuilderTest.php
    @@ -0,0 +1,338 @@
    +      ->willReturn("Can't let you do that Dave.");
    +    $this->stringTranslation->expects($this->any())
    +      ->method('translate')
    +      ->willReturnArgument(0);
    +    $this->stringTranslation->expects($this->any())
    +      ->method('formatPlural')
    +      ->willReturnArgument(1);
    

    Can you use the getStringTranslationStub() method here? I could imagine that formatPlural is not supported? It would then be great to add support for it.

andypost’s picture

Overall it's a big step forward to clean-up spaghetti legacy for links!

1) The order of arguments just mimics hook_node_links_alter() & hook_comment_links_alter()
2) In context of comment services I think that better follow patterns #2188287: Split CommentManager in two by placing all render funcs into one CommentRenderHelper service
3) I'd suggest to extract conversion of constants to separate issue with own change record.

Also this patch just converts node links but I think comment links should be addressed here too.

+++ b/core/modules/comment/src/Plugin/Field/FieldType/CommentItemInterface.php
@@ -27,4 +27,14 @@
+  const FORM_SEPARATE_PAGE = 0;
...
+  const FORM_BELOW = 1;

+++ b/core/modules/comment/src/Tests/CommentTestBase.php
@@ -265,7 +266,7 @@ public function setCommentPreview($mode, $field_name = 'comment') {
-    $this->setCommentSettings('form_location', ($enabled ? COMMENT_FORM_BELOW : COMMENT_FORM_SEPARATE_PAGE), 'Comment controls ' . ($enabled ? 'enabled' : 'disabled') . '.', $field_name);
+    $this->setCommentSettings('form_location', ($enabled ? CommentItem::FORM_BELOW : CommentItem::FORM_SEPARATE_PAGE), 'Comment controls ' . ($enabled ? 'enabled' : 'disabled') . '.', $field_name);

+++ b/core/modules/comment/tests/src/CommentLinkBuilderTest.php
@@ -0,0 +1,338 @@
+      $this->getMockNode(FALSE, CommentItem::OPEN, CommentItem::FORM_BELOW, 1),
...
+        $this->getMockNode(TRUE, CommentItem::OPEN, CommentItem::FORM_BELOW, 1),
...
+      'form_location'            => array(CommentItemInterface::FORM_BELOW, CommentItemInterface::FORM_SEPARATE_PAGE),
...
+        if ($combination['comments'] == CommentItem::OPEN) {
...
+            if ($combination['view_mode'] == 'teaser' || ($combination['has_access_comments'] && $combination['comment_count']) || $combination['form_location'] == CommentItem::FORM_SEPARATE_PAGE) {
...
+              if ($combination['form_location'] == CommentItem::FORM_BELOW) {

Use CommentItemInterface for constants

larowlan’s picture

#17
Correct, we should use $entity->getEntityTypeId and not 'node' hardcoded

21.3 will fix
21.4 #2271349: Node and Comment ops links should be display components (which can be disabled) should sort that but also in #1920044: Move comment field settings that relate to rendering to formatter options we were making it configurable in the formatter (there is a patch there)
21.5 good call, cause there are two non-zero constants in effect here
21.6, 21.9 I think you are right, there are data attributes but rendering should sort them
21.7 Welcome suggestions, ideally history module would have its own link builder service I guess
21.8 we have $this->t() in scope so will fix
21.10 ooh didn't know we had that, nice

22.2 agreed it would fit better on CommentRenderHelper, perhaps CommentRenderBuilder would be a more apt name (bikeshed!). So depends if this or #2188287: Split CommentManager in two goes in first?
22.3 (CommentItem » CommentItemInterface) will fix, sorry

thanks thehong, andypost, dawehner

@thehong, do you have an irc nick so I can send some review karma your way - can't see it in your profile.

larowlan’s picture

Issue tags: -Needs change record
FileSize
12.73 KB
47.91 KB

Fixes as promised in #23

@andypost - I'd like to tackle comment links separately as they are a different kettle of fish (post render cache callback)

andypost’s picture

I think that only change record needed, +1 rtbc
@dawehner are you agree?

larowlan’s picture

Draft change record above

andypost’s picture

Status: Needs review » Reviewed & tested by the community

so let's go

Wim Leers’s picture

All I can say is: Wow!.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/modules/comment/comment.module
@@ -257,151 +247,7 @@ function comment_node_links_alter(array &$node_links, NodeInterface $node, array
+  \Drupal::service('comment.link_builder')->buildLinks($node_links, $node, $context);

Why not buildNodeLinks? To reflect the hook_node_links_alter() - also I think this should return the array of links and the alter hook should still add them - ie not pass $entity_links at all. That way if we ever move hook_node_links_alter to events we can have a build event and an alter event.

larowlan’s picture

Why not buildNodeLinks?

I think buildCommentedEntityLinks would be more appropriate - because longer term we want this to be used for more than just nodes. That would leave buildCommentLinks for the next step (to move the comment operation etc links over here).

also I think this should return the array of links

Ok will fix

larowlan’s picture

FileSize
4.07 KB
47.99 KB
andypost’s picture

Status: Needs review » Reviewed & tested by the community

great

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Thanks. Committed b6ba35f and pushed to 8.0.x. Thanks!

  • alexpott committed b6ba35f on 8.0.x
    Issue #2318251 by larowlan: Fixed Make comment links functionality...
larowlan’s picture

Published the change notice

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.