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.
- #731724: Convert comment settings into a field to make them work with CMI and non-node entities - because we have more than one field to deal with
- #1991684: Node history markers (comment & node "new" indicator, "x new comments" links) forces render caching to be per user - because we are dealing with render-cache for the personalisation stuff
Other issues to touch this code
- #449718: node_feed() is using the old node building API
- #339929: Move node links into $node->content
- #4861: comment module uses standard _link() hook
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
| 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 |
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | comment-links-simplify-man-2377849.1.do-not-test.patch | 19.67 KB | larowlan |
Comments
Comment #1
larowlanComment #2
larowlanComment #3
larowlanJustification of items marked with * in issue summary
This could go to a formatter
This too could go to a formatter
same - formatter
same - formatter
- 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.
- With all the other links gone - the only use case remaining is for rss, this can go back inline in comment_node_view
Comment #4
larowlanI 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.
Comment #5
wim leersComment #6
wim leersHaving 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:
if ($this->moduleHandler->moduleExists('history')) {in there. This is simply ridiculous. We could easily move this into the History module, thanks tohook_node_links_alter()Comment #7
catchMoving 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.
Comment #8
Crell commentedGenerally 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?
Comment #9
wim leersAgreed on this — it's not clear to me either how that is going to fix things.
Could you explain that some more, larowlan?
Comment #10
larowlanI have some ideas, will put together a patch to demonstrate it
Comment #11
larowlanmaking some progress here, hoping to get something posted at the weekend
Comment #12
larowlanSo 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.
Comment #13
larowlanclearly c/p fail
Comment #14
larowlanOh screenshots would be nice
Comment #15
jibranThis looks nice for WIP.
Comment #16
wim leersI 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.
Comment #17
andypost#19 looks great!
I'm also think about performance impact
Comment #18
larowlan@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.
Comment #19
Crell commentedArchitecturally 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.)
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.)
Comment #20
larowlan@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 :)
Comment #21
Crell commentedOh! 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?)
Comment #22
larowlan@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.
Comment #23
Crell commentedHm. 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.)
Comment #24
andypost@Crell there's #1875974: Abstract 'component type' specific code out of EntityDisplay to unify the components of entities
Comment #25
moshe weitzman commentedComment #26
mikeryanThought I had commented here earlier - +1 for unraveling this rats' nest, which has given us issues like #2588547: CommentLinkBuilder causes fatal error when comment field not named 'comment', #2593869: Using "New comments" field in a view breaks if history module not enabled, #2594201: No choice of comment field to use for "New comments" view field...
Comment #27
larowlanYeah we should get product owner sign-off here I guess
Comment #28
yesct commentedComment #29
jonathanshawSeems like as we're past the 8.0 point we should pick up #20-22 again for consistency
Comment #31
webchickIt 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.
Comment #32
catch@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).
Comment #36
yoroy commentedremoving tag for now, the requests in #31 and #32 still stand.
Comment #48
smustgrave commentedWas going to tag stale-issue-content but this seems like it's probably still relevant.
Comment #49
andypostyes, and while comment's module fate is unclear we lack of opinions