Problem/Motivation

Blocks #2559971: Make SafeMarkup::format() return a safe string object to remove reliance on a static, unpredictable safe list

CommentForm does a loadByProperties using the formatted username. This is nonsense. In fact much of the code involved with previewing comments and comment forms is based on extremely old code that is no longer need.

This patch will changes the way an admin can edit the name of the user who makes the comment. In HEAD we have a single field that is switched to do different things in different situations:

  • Anonymous user on the comment add form or comment preview it is a free text field for the anon user to provide a name
  • Logged in user on the comment add form or comment preview it is a item field that displays the name to the user (this is unnecessary the user knows their name and makes the form basically uncacheable)
  • Comment admin whilst editing someone else's comment - it is an entity reference autocomplete field

Proposed resolution

Remove all the old unnecessary code... and bring some sanity to the form and make it cacheable:

  • A free text field to allow anon's to add provide their name - this field is not displayed to logged in users and is displayed to comment admins when editing
  • No username is displayed to logged in users in the comment add form or preview.
  • Comments admins are displayed a new entity reference field so they can change the owner of a comment

Remaining tasks

Review
Commit

User interface changes

For a logged in user they no longer have their name displayed in the comment form.

API changes

None

Data model changes

None

CommentFileSizeAuthor
#91 interdiff-89-90.txt3.28 KBeffulgentsia
#91 2571909-2-90.patch17.34 KBeffulgentsia
#89 2571909-2-89.patch19.14 KBalexpott
#89 88-89-interdiff.txt3.94 KBalexpott
#88 2571909-2-88.patch17.09 KBalexpott
#88 80-88-interdiff.txt6.98 KBalexpott
#86 Screenshot 2015-09-26 09.55.21.png28.02 KBlarowlan
#86 Screenshot 2015-09-26 09.55.00.png42.17 KBlarowlan
#86 Screenshot 2015-09-26 09.54.11.png34.48 KBlarowlan
#86 Screenshot 2015-09-26 09.54.01.png44.49 KBlarowlan
#86 Screenshot 2015-09-26 09.53.46.png52.01 KBlarowlan
#86 Screenshot 2015-09-26 09.53.42.png60.51 KBlarowlan
#86 Screenshot 2015-09-26 09.51.11.png57.62 KBlarowlan
#80 2571909-2-80.patch17.19 KBalexpott
#80 68-80-interdiff.txt1.96 KBalexpott
#68 2571909-68.patch16.9 KBupchuk
#68 interdiff-68.txt501 bytesupchuk
#66 2571909-2-66.patch16.95 KBalexpott
#66 61-66-interdiff.txt2.16 KBalexpott
#61 interdiff.txt1.28 KBwim leers
#61 2571909-61.patch16.06 KBwim leers
#60 Screen Shot 2015-09-25 at 11.08.55.png36.42 KBwim leers
#59 interdiff.txt2.98 KBwim leers
#59 2571909-59.patch14.9 KBwim leers
#57 2571909-2-57.patch14.9 KBalexpott
#57 54-57-interdiff.txt5.32 KBalexpott
#54 comment-name-field-2571909.34-reroll.patch19.96 KBstefan.r
#42 2571909-42.patch1.8 KBstefan.r
#41 2571909-41.patch15.59 KBstefan.r
#33 comment-name-field-2571909.34.patch15.47 KBlarowlan
#33 interdiff.txt886 byteslarowlan
#32 comment-name-field-2571909.32.patch15.41 KBlarowlan
#32 interdiff.txt972 byteslarowlan
#27 interdiff.txt710 byteslauriii
#27 commentform_selects-2571909-27.patch15.47 KBlauriii
#24 interdiff.txt1022 byteslauriii
#24 commentform_selects-2571909-24.patch15.47 KBlauriii
#18 comment-name-field-2571909.18.patch15.3 KBlarowlan
#18 interdiff.txt10.64 KBlarowlan
#7 2571909-7.patch6.84 KBalexpott
#7 2571909-7.test-only.patch1013 bytesalexpott

Comments

alexpott created an issue. See original summary.

larowlan’s picture

This field can only be edited by admins, are you saying the default value is not username?

larowlan’s picture

Can with on this tomorrow, unless someone beats me to it

mr.baileys’s picture

Assigned: Unassigned » mr.baileys
alexpott’s picture

The last submitted patch, 7: 2571909-7.test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 7: 2571909-7.patch, failed testing.

andypost’s picture

+++ b/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module
@@ -5,15 +5,14 @@
     if (\Drupal::state()->get('user_hooks_test_user_format_name_alter_safe', FALSE)) {
-      $name = SafeMarkup::format('<em>@uid</em>', array('@uid' => $account->id()));
+      // Make $name a SafeStringInterface object.
+      $name = t('<em>@id</em>', ['@id' => $account->id()]);
     }
     else {
       $name = '<em>' . $account->id() . '</em>';

Any reason to make it translatable?
this string will appear in translations without need

mr.baileys’s picture

Assigned: mr.baileys » Unassigned
morenstrat’s picture

larowlan’s picture

Component: other » comment.module
larowlan’s picture

Title: CommentForm selects using the user formatted name » PP-1 CommentForm selects using the user formatted name
Status: Needs work » Postponed
larowlan’s picture

Title: PP-1 CommentForm selects using the user formatted name » CommentForm selects using the user formatted name
Status: Postponed » Needs work

Looked at the patch, no its not

larowlan’s picture

Sigh #2227503: Apply formatters and widgets to Comment base fields would probably have resolved this. Wonder if its too late

larowlan’s picture

Assigned: Unassigned » larowlan

working on fails

larowlan’s picture

Assigned: larowlan » Unassigned
Status: Needs work » Needs review
StatusFileSize
new10.64 KB
new15.3 KB

The last submitted patch, 7: 2571909-7.test-only.patch, failed testing.

The last submitted patch, 7: 2571909-7.patch, failed testing.

znerol’s picture

Closing #2566245: Comment author name overridden by hook_user_format_name_alter() as a duplicate of this issue, since the patch here is actually solving the problem in a more appropriate way. IMHO it would be appropriate to give @dunix credits here though.

andypost’s picture

+++ b/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module
@@ -5,15 +5,14 @@
-      $name = SafeMarkup::format('<em>@uid</em>', array('@uid' => $account->id()));
+      // Make $name a SafeStringInterface object.
+      $name = t('<em>@id</em>', ['@id' => $account->id()]);

still issue

your_inner_alexpott’s picture

@andypost if l.d.o picks up translatable strings from test modules then that is the issue - no?

lauriii’s picture

StatusFileSize
new15.47 KB
new1022 bytes

Trying to proceed this since this would help #2559971: Make SafeMarkup::format() return a safe string object to remove reliance on a static, unpredictable safe list

I think we could create SafeString object there manually even though its internal because its only for a testing purpose. I added a @todo to point out that it could be changed to SafeMarkup::format() after it returns a SafeString object.

Status: Needs review » Needs work

The last submitted patch, 24: commentform_selects-2571909-24.patch, failed testing.

The last submitted patch, 24: commentform_selects-2571909-24.patch, failed testing.

lauriii’s picture

Status: Needs work » Needs review
StatusFileSize
new15.47 KB
new710 bytes

Status: Needs review » Needs work

The last submitted patch, 27: commentform_selects-2571909-27.patch, failed testing.

The last submitted patch, 27: commentform_selects-2571909-27.patch, failed testing.

stefan.r’s picture

Priority: Major » Critical

this is blocking a critical

larowlan’s picture

Assigned: Unassigned » larowlan

working on the test fail, pinging laurii on irc for guidance

larowlan’s picture

Assigned: larowlan » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new972 bytes
new15.41 KB

As discussed on irc

larowlan’s picture

StatusFileSize
new886 bytes
new15.47 KB

As per discussion on irc with @stefan_r

The last submitted patch, 32: comment-name-field-2571909.32.patch, failed testing.

amateescu’s picture

Should we be worried that the patch from #32 failed on the old testbot but passed on DrupalCI, or is that just random failure?

stefan.r’s picture

@amateescu I think that may have been a random failure indeed - thanks for spotting that.

We changed <em class="placeholder"> to <em>, so let's change the test just to be sure.

stefan.r’s picture

I ran #32 lot's of times times locally. Could not reproduce this so I don't think the specific <em> in #34 was the problem - let's ignore the failure?

MacBook-Pro-de-sr:core sr$ git apply comment-name-field-2571909.32.patch 
MacBook-Pro-de-sr:core sr$ php scripts/run-tests.sh --repeat 100 --url http://localhost/drupal/ --class "Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExposedFilter"
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes                                      
Drupal\user\Tests\Views\HandlerFilterUserNameTest::testExpos  16 passes
dawehner’s picture

We wondered why this changed more than actually needed. Yes, using #access would be nice, but why is that in scope of this particular issue?
@stefan.r and @dawehner could not figure that out.

stefan.r’s picture

considering this has been bumped to critical maybe let's revert any out of scope changes?

nlisgo’s picture

  1. +++ b/core/modules/comment/src/CommentForm.php
    @@ -152,29 +152,23 @@ public function form(array $form, FormStateInterface $form_state) {
    +        'data-drupal-default-value' => $config->get('anonymous')
    

    comma needed at end of line.

  2. +++ b/core/modules/comment/src/Tests/CommentAnonymousTest.php
    @@ -100,7 +100,7 @@ function testAnonymous() {
         // Make sure the user data appears correctly when editing the comment.
    

    The message can be in single quotes now as it no longer has an apostrophe.

Found a couple of little niggles.

stefan.r’s picture

StatusFileSize
new15.59 KB

reroll - includes the nits from #40

stefan.r’s picture

StatusFileSize
new1.8 KB

minimal patch just to see what fails

The last submitted patch, 41: 2571909-41.patch, failed testing.

The last submitted patch, 41: 2571909-41.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 42: 2571909-42.patch, failed testing.

stefan.r’s picture

this seems like an unrelated fail? Value array ( ) is equal to value array ( 0 => array ( 'title' => 'example EN', 'sticky' => 'Off', ), 1 => array ( 'title' => 'example ES', 'sticky' => 'On', ), ).

Status: Needs work » Needs review

stefan.r queued 42: 2571909-42.patch for re-testing.

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/modules/comment/src/CommentForm.php
@@ -263,16 +257,27 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
-    if (!$this->currentUser->isAnonymous()) {
-      // Assign the owner based on the given user name - none means anonymous.
-      $accounts = $this->entityManager->getStorage('user')
-        ->loadByProperties(array('name' => $author_name));
-      $account = reset($accounts);
-      $uid = $account ? $account->id() : 0;
-      $comment->setOwnerId($uid);

This is also extremely problematic - which is why I split up the name element into two elements. The latest patch does not address this loadByProperties().

Furthermore the solution has the added benefit of getting has quite a few steps closer to making the comment add form cacheable which is in everyone's interest. This is because there are way less conditionals when building the form. Also less conditionals make it more robust and easier to test.

larowlan’s picture

+1 for going back to #33

alexpott’s picture

The patch in #32's failure on pifr (old testbot) is a known pifr issue that sometimes occurs and definitely is not caused by this patch.
GET http://ec2-52-11-109-200.us-west-2.compute.amazonaws.com/checkout/test_user_name?uid=ktp2q43a returned 0 (0 bytes).

alexpott’s picture

Another reason to do #33 is that having the anonymous user entered name in a different field from the admin edited user entity reference is that they are completely different things. Trying to make them the same thing results in errors like this.

larowlan’s picture

It also brings us closer to #2227503: Apply formatters and widgets to Comment base fields which has separate widgets for each field (with access controlled by the existing field access)

Status: Needs work » Needs review

stefan.r queued 42: 2571909-42.patch for re-testing.

stefan.r’s picture

StatusFileSize
new19.96 KB

yeah why not - reuploading #41

Status: Needs review » Needs work

The last submitted patch, 54: comment-name-field-2571909.34-reroll.patch, failed testing.

The last submitted patch, 54: comment-name-field-2571909.34-reroll.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new5.32 KB
new14.9 KB

Removing unrelated hunks from #54 and fixing tests.

upchuk’s picture

I think #2572553: Incomprehensible validation message when anonymous tries to submit comment with an existing username is related since we get some weird validation issues because of the Name field...

wim leers’s picture

Issue tags: +DrupalCon Barcelona 2015
StatusFileSize
new14.9 KB
new2.98 KB
  1. +++ b/core/modules/comment/src/CommentForm.php
    @@ -152,29 +152,23 @@ public function form(array $form, FormStateInterface $form_state) {
    +      '#description' => $this->t('Leave blank for %anonymous.', array('%anonymous' => $config->get('anonymous'))),
    

    Nit: we use the short array syntax elsewhere, so also should here.

  2. +++ b/core/modules/comment/src/CommentForm.php
    @@ -263,16 +257,27 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
    +    // Empty author-ID should revert to anonymous.
    

    Nit: s/author-ID/author ID/

  3. +++ b/core/modules/comment/src/CommentForm.php
    @@ -263,16 +257,27 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
    +      if ($author_id || !$form['author']['name']['#access']) {
    

    #access can also be an AccessResultInterface object.
    Nope, I was wrong, this code fully controls #access, and therefore it can never be an AccessResultInterface object, hence the code is correct.

  4. +++ b/core/modules/comment/src/Tests/CommentPreviewTest.php
    @@ -200,6 +204,8 @@ function testCommentEditPreviewSave() {
    +    // Web-user cannot change the comment-author.
    

    Nit: s/Web-user/Web user/ + s/comment-author/comment author/

  5. +++ b/core/modules/comment/src/Tests/CommentTestBase.php
    @@ -70,6 +70,9 @@ protected function setUp() {
    +      // Username's aren't shown in comment edit form autocomplete unless this
    

    Nit: s/Username's/Usernames/

I fixed all these nits.

wim leers’s picture

Issue summary: View changes
StatusFileSize
new36.42 KB
+++ b/core/modules/comment/src/CommentForm.php
@@ -152,29 +152,23 @@ public function form(array $form, FormStateInterface $form_state) {
-      $form['author']['name']['#cache']['contexts'][] = 'user';

We no longer set this cache context, because it is no longer necessary.

\o/ \o/ \o/ \o/

This is what it now looks like, for all users, including an authenticated user:

wim leers’s picture

StatusFileSize
new16.06 KB
new1.28 KB

#60 means we can now finally delete this piece of code, which TBH should've already been removed in #2543334: Auto-placeholdering for #lazy_builder with bubbling of contexts and tags, but now is also completely unnecessary, which is even better :)

wim leers’s picture

+++ b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
@@ -190,16 +190,6 @@ public function viewElements(FieldItemListInterface $items) {
-          if ($this->currentUser->isAuthenticated()) {
-            $output['comment_form']['#cache']['contexts'][] = 'user';
-          }

This part in particular of #61 is now wrong and must be updated here, in this issue, so it remains in sync with CommentForm, i.e. with this particular part that is now gone:

+++ b/core/modules/comment/src/CommentForm.php
@@ -152,29 +152,23 @@ public function form(array $form, FormStateInterface $form_state) {
-    elseif ($this->currentUser->isAuthenticated()) {
-      $form['author']['name']['#type'] = 'item';
-      $form['author']['name']['#value'] = $form['author']['name']['#default_value'];
-      $form['author']['name']['#theme'] = 'username';
-      $form['author']['name']['#account'] = $this->currentUser;
-      $form['author']['name']['#cache']['contexts'][] = 'user';
-    }

And if we remove that first quoted bit, we might as well remove the entire thing, which is exactly what the #61 interdiff does.

Status: Needs review » Needs work

The last submitted patch, 61: 2571909-61.patch, failed testing.

The last submitted patch, 61: 2571909-61.patch, failed testing.

alexpott’s picture

Assigned: Unassigned » alexpott

Working on this

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new2.16 KB
new16.95 KB

Fixing tests and removing more dead code.

andypost’s picture

Overall this great, just nits

  1. +++ b/core/modules/comment/src/Tests/CommentTestBase.php
    @@ -70,6 +70,9 @@ protected function setUp() {
    +      // Usernames aren't shown in comment edit form autocomplete unless this
    +      // permission is granted.
    +      'access user profiles',
    

    looks a separate bug

  2. +++ b/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module
    @@ -5,7 +5,7 @@
    +use Drupal\Core\Render\SafeString;
    

    looks new use is unused

upchuk’s picture

StatusFileSize
new501 bytes
new16.9 KB

Removing the unused 'use' statement.

jhedstrom’s picture

re: #67.1, not a bug really, since that permission is intentional, similar to not being able to see a node title if one cannot access the node.

This isn't actually true :)

upchuk’s picture

Did some manual testing of the Comment preview and things seem to look ok, except for a couple of issues tackled elsewhere:

* #2574597: Comment body doesn't show up in preview for Anonymous users
* #2572553: Incomprehensible validation message when anonymous tries to submit comment with an existing username

upchuk’s picture

berdir’s picture

Assigned: alexpott » Unassigned
Status: Needs review » Reviewed & tested by the community
Issue tags: +Performance

Ok, we had lots of reviews, manual testing, found various bugs but nothing caused by this. Code looks good to me as well, awesome cleanup and performance improvement.

wim leers’s picture

Issue tags: +D8 cacheability
alexpott’s picture

Issue summary: View changes
effulgentsia’s picture

Adding credit to @dunix per #21.

effulgentsia’s picture

Adding issues from #70 and #71 as related issues. I haven't fully wrapped my head around what the nature of that relationship is though: i.e., whether they're completely independent issues or in some way affected by this.

berdir’s picture

@effulgentsia: Both are existing bugs in HEAD. We just found them while testing this and are working on fixing them separately. They are otherwise not related to this issue.

effulgentsia’s picture

I haven't fully grokked all of the changes in this patch yet, and possibly I need to do some manual testing in order to, but this jumped out at me as potentially problematic:

+++ b/core/modules/comment/src/CommentForm.php
@@ -263,16 +257,27 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
+        $comment->setAuthorName($account->getDisplayName());

If getDisplayName() returns a SafeString, then we'd be populating the author name with HTML, but AFAICT, the comment author name is always rendered elsewhere as plain-text. Should we change this to:

$html_display_name = SafeMarkup::format('@name', ['@name' => $account->getDisplayName()]);
$text_display_name = PlainTextOutput::renderFromHtml($html_display_name);
$comment->setAuthorName($text_display_name);

Kind of verbose, but given the explicit flexibility of AccountInterface::getDisplayName() returning either plain-text or SafeString, any other suggestions on how to do this?

effulgentsia’s picture

Hm, maybe #78 isn't a problem, since Comment::getAuthorName() ignores what's in the 'name' field anyway for authenticated users. But that then raises the question of why set it?

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.96 KB
new17.19 KB

@effulgentsia yep you are right - setting the name there makes no sense.

berdir’s picture

More code removed, tests are passing, looks good to me. Nice!

berdir’s picture

Status: Needs review » Reviewed & tested by the community

I meant to do this.

effulgentsia’s picture

Thanks! #80 definitely resolves that concern. I still want some more time with this patch before I can feel comfortable committing it, but I don't object to someone else committing it before me if they're comfortable with it. I'll try to get to this within the next 24 hours if no one beats me to it.

larowlan’s picture

Taking for a manual spin

larowlan’s picture

Screenshots - all looks good.

Confirmed the anonymous name isn't retained if the comment is switched to an authenticated user and then back to anonymous.

Looks good to me - one final question - should we name the field uid instead of admin_select - as that is the base-field we're editing - which would also align with #2227503: Apply formatters and widgets to Comment base fields

stefan.r’s picture

Yay for extra manual testing!

alexpott’s picture

StatusFileSize
new6.98 KB
new17.09 KB

@larowlan good idea - leaving it at rtbc.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new3.94 KB
new19.14 KB

Discussed comment administration wrt comment editing with @effulgentsia. @effulgentsia noticed that in order to set the name when an admin converted a comment form a registered user you would have to edit a comment twice. The patch attached fixes this. It also ensures that the author name only has a default value when dealing with anonymous users.

alexpott’s picture

Also noticed whilst testing that "Edit own comments" is meaningless for anon users - which is a good thing - but potentially confusing.

effulgentsia’s picture

StatusFileSize
new17.34 KB
new3.28 KB

Here's a little cleanup of test code.

effulgentsia’s picture

I'm happy with #89, so as long as bot is happy with #91 and someone RTBC's that interdiff, I can commit.

alexpott’s picture

I've tested the latest changes to comment administration and the #states implementation works nicely - see http://g.recordit.co/am1JyIVSL9.gif

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

The interdiff in #91 looks great.

effulgentsia’s picture

Status: Reviewed & tested by the community » Fixed

Pushed to 8.0.x!

  • effulgentsia committed a9b2470 on 8.0.x
    Issue #2571909 by alexpott, larowlan, stefan.r, Wim Leers, lauriii,...
wim leers’s picture

Status: Fixed » Closed (fixed)

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

andypost’s picture

quietone’s picture