Problem/Motivation

CommentLinksBuilder does the following things

  • Hides links on the (hard-coded) search_index, search_result and print view modes*
  • For rss view mode builds the comments element in the xml
  • In the teaser view mode
    • If the user has access comments permission - shows the comment count link*
    • If history module is also enabled - shows the new comment count link*
    • If the user has post comments permission - shows the 'add new comment' link (link varies depending on comment-form location)*
    • If the user is anonymous shows the 'login or register' to post comments link*
  • In other views modes (beside the hard-coded search_index, search_result, print and teaser view modes)
    • If the user has post comments permission - shows the 'add new comment' link (link varies depending on comment-form location)*

The bulk of the logic lives in the buildCommentedEntityLinks method.
Most of these feel to me like we're trying to do too many things for too many people.
A lot of this is done with hard-coded view-modes - so can't be replicated easily if someone wants to add a new view-mode called teaser-front - the teaser behaviour can't be configured - it is hard wired.

Complexity

As a result of the ever-growing list of functionality this method (buildCommentedEntityLinks) is one of the most complex in core.
PHPMD reports it has an npath complexity of 1204 and a Cyclomatic Complexity of 27. Limits we should be aiming for as worst-case-scenarios are 200 and 10 respectively.
Over in #1920044: Move comment field settings that relate to rendering to formatter options the complexity gets worse.

APIs not features

Core should be focussing on providing an API so individual sites/contrib who need these features can add them.
At present they'd be spending a lot of time undoing assumptions in core.

Not all doom and gloom

Whilst this method is complex, because we have decoupled it we have near 100% phpunit test-coverage - although this requires 580 test combinations - which is an awful lot. But test coverage and decoupling should make refactoring easier.

History

The cyclic complexity of comment_node_view the D7 predecessor is 21, so things have got slightly worse in the D8 cycle - because of the following.

Other issues to touch this code

Proposed resolution

Do a critical stocktake of what CommentLinksBuilder does.
Remove the non-essential elements - I've marked candidates above with * - in my opinion these are site-specific features - I realise their historic inclusion is tied to Drupal's blog beginnings and their usage on Drupal.org - but I don't feel they belong anymore.
Try to leverage formatters for functionality.
Ship standard profile with display mode default configuration that provides the functionality.
Don't provide it in comment module.
Defer non-core features to contrib.

Remaining tasks

Stocktake of functionality
Examine history that brought us to this point.
Decide on if removing the proposed items is appropriate and seek committer approval to proceed.
Remove them and move them to standard profile or contrib depending on suitability of formatters.

User interface changes

Some elements provided by comment module by default will be removed or deferred to standard profile and even contrib.

API changes

Unsure at this stage, but possibly CommentLinksBuilder will be removed in most-part in favour of new formatters.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Task because we have to support this mess for many years to come - so we need to be sure
Issue priority Major because we have to support this for a long time - and it is a decent mess at the moment
Prioritized changes A factor in this issue is performance of the default install/functionality of core.
Disruption This will upset theme developers who might be targetting these elements

Comments

larowlan’s picture

Title: Simplify what CommentLinksBuilder is doing » Simplify what CommentLinksBuilder is doing - consider removing a lot of the functionality
larowlan’s picture

Issue summary: View changes
larowlan’s picture

Justification of items marked with * in issue summary

  • In the teaser view mode
    • If the user has access comments permission - shows the comment count link

      This could go to a formatter

    • If history module is also enabled - shows the new comment count link

      This too could go to a formatter

    • If the user has post comments permission - shows the 'add new comment' link (link varies depending on comment-form location)

      same - formatter

    • If the user is anonymous shows the 'login or register' to post comments link

      same - formatter

  • In other views modes (beside the hard-coded search_index, search_result, print and teaser view modes)
    • If the user has post comments permission - shows the 'add new comment' link (link varies depending on comment-form location)

      - this might seem great for the full view mode, but all other view modes getting an 'add new comment' link sounds like something that site-builder/themers will have to work to undo on most sites - either in their tpl (content.links) or some other fashion if they need some links, just not comment ones.

  • Hides links on the (hard-coded) search_index, search_result and print view modes

    - With all the other links gone - the only use case remaining is for rss, this can go back inline in comment_node_view

larowlan’s picture

I will put together a CommentLinkFormatter and see how it looks - this assumes that the 'add new comment' link shown in full/default view mode will go.

wim leers’s picture

Title: Simplify what CommentLinksBuilder is doing - consider removing a lot of the functionality » Simplify what CommentLinkBuilder is doing - consider removing a lot of the functionality
wim leers’s picture

Having worked on #1991684: Node history markers (comment & node "new" indicator, "x new comments" links) forces render caching to be per user, I remember what an incredible PITA this was. Fully agreed on this being more complex than it should be.

Thoughts:

  1. we literally have if ($this->moduleHandler->moduleExists('history')) { in there. This is simply ridiculous. We could easily move this into the History module, thanks to hook_node_links_alter()
  2. it could help a lot of if we didn't hardcode certain logic to certain view modes, but if we made that configurable?
catch’s picture

Moving history stuff to history module is good - we didn't have a separate history module until relatively recently.

If history module has to check for comment module I think we can live with that, better than vice versa. Formatter might save doing even that.

Generally cleaning this up agreed on doing that and fine in terms of beta changes policy at https://www.drupal.org/node/2368133 - this makes things better for contrib, reduces fragility in core, only 'disruption' is likely to be gutting big chunks out of this function.

Crell’s picture

Generally agreed on simplifying here. Its predecessor in D6/7 was my go-to example of excessive complexity in the past. :-) My main question is that "punt this to a formatter" seems like a hand-wavy answer. A field can only have one formatter per view mode at a time; if there's 50 possible links that are reasonable to be there, moving the big blob of logic from this function to a formatter doesn't really improve matters, does it? How would we avoid just moving the ugly around?

Is there anything else we could factor out nicely, like the history links?

wim leers’s picture

My main question is that "punt this to a formatter" seems like a hand-wavy answer.

Agreed on this — it's not clear to me either how that is going to fix things.

Could you explain that some more, larowlan?

larowlan’s picture

I have some ideas, will put together a patch to demonstrate it

larowlan’s picture

making some progress here, hoping to get something posted at the weekend

larowlan’s picture

So here's the formatter idea.
This can take care of all of the teaser stuff, putting it into view-mode settings.
Each link is a plugin.
Nice and small units instead of one mega-unit.
The formatter uses the plugin manager to collect the 'comment link' plugins.
Shows a settings form to let the user pick the ones they want.
So on teaser view mode you could display 'comment links' instead of hidden and remove the hard-coded teaser stuff in the link builder.
Note this also moves the link builder service into a common Drupal\comment\Links namespace.

Haven't implemented any plugins yet - just their names so you get the idea.

If people think this is worth pursuing, will move it along and split the link builder service into these discrete plugins.

larowlan’s picture

+++ b/core/modules/comment/src/Links/CommentLinkPluginBase.php
@@ -0,0 +1,65 @@
+   * Constructs a \Drupal\tour\Plugin\tour\tip\TipPluginText object.

clearly c/p fail

larowlan’s picture

Oh screenshots would be nice

jibran’s picture

This looks nice for WIP.

wim leers’s picture

I like it UI-wise and managing-complexity-wise. Each plugin is instantiated only once and not per commented entity, which is good, otherwise this'd cost us a lot performance-wise.
It's possible that this approach is going to cost us some performance (using the plugin system is another serious abstraction layer), but I suspect this is going to be fine/acceptable.

EDIT: I had looked at the UI from the screenshots. Apparently this requires selecting a different comment field formatter on the commented entity (i.e. choose "Comment links" instead of "Comment list" at /admin/structure/types/manage/article/display). I'd expect this to make the "Links" field on the comment entity itself configurable (i.e. at /admin/structure/comment/manage/comment/display)?

+1 to continue along this path. Ideally with profiling before it gets committed, on a page with 10 commentable nodes, which is the typical expensive case.

andypost’s picture

#19 looks great!
I'm also think about performance impact

larowlan’s picture

@WimLeers - yes these links are only for the commented entity, not the individual comments.
In terms of making sure to only instantiate them once - agree.

In terms of selecting 'comment links' instead of 'comment list' - most of these links are hard-coded to be shown on the teaser view-mode - where the comment list isn't in use anyway.

Agree on performance.

Crell’s picture

Architecturally I like this direction. Good use of plugins! I also agree with Wim that, from a UX perspective, I would expect to configure this on the comment, not on the node/user/whatever. (Comments can have view modes; I could want to have the links different in different comment view modes, allowing for, say, a "most recent comments" block that doesn't have links but does have body excerpts while full comments have all links.)

+++ b/core/modules/comment/src/Links/CommentLinkPluginBase.php
@@ -0,0 +1,65 @@
+abstract class CommentLinkPluginBase extends PluginBase implements CommentLinkPluginInterface, ContainerFactoryPluginInterface {

Side note: I would love it if we could start using traits for these instead of base classes. :-P (I know, I know, consistency. But a base class can use a trait, too.)

larowlan’s picture

@Crell we can already configure the comment display.
These links aren't on the comment, they're on the commented entity.
Thanks for the reviews, just need to find time now :)

Crell’s picture

Oh! OK. Do the on-comment links work this way as well? (Seems like it would make sense for all "links on entities" to work in a similar fashion, no?)

larowlan’s picture

@Crell
I did propose that over in #2271349: Node and Comment ops links should be display components (which can be disabled)
We ended up with links as a generic display component, i.e. you can have all or none.
I agree that picking the individual ones would be better, but I think that its probably too late for 8.0.0.

Crell’s picture

Hm. Well, let's forge ahead here and maybe we can make a DX argument for the other later. :-) (If not, eh, there are more versions.)

andypost’s picture

moshe weitzman’s picture

Version: 8.0.x-dev » 8.1.x-dev
larowlan’s picture

Yeah we should get product owner sign-off here I guess

yesct’s picture

jonathanshaw’s picture

Seems like as we're past the 8.0 point we should pick up #20-22 again for consistency

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

webchick’s picture

It would help me tremendously if there was a concise before/after behaviour description. I don't quite understand if the *ed things in the issue summary will all be removed from core altogether, or simply moved to alternate, more modern implementations. If there's no functionality loss/UX regression, and this is all under-the-hood refactoring, then there's no need for product manager sign-off.

catch’s picture

@webchick I think the proposal is to actually remove some of the links from core altogether, but agreed it could use a better issue summary (or a mockup/patch that just hacks them out and screenshots).

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

yoroy’s picture

removing tag for now, the requests in #31 and #32 still stand.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Was going to tag stale-issue-content but this seems like it's probably still relevant.

andypost’s picture

yes, and while comment's module fate is unclear we lack of opinions

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.