Problem/Motivation

hook_comment_publish() and hook_comment_unpublish() are documented to exist. However, they are not really being invoked correctly. See Comment::postSave():

 if ($this->isPublished()) {
    \Drupal::moduleHandler()->invokeAll('comment_publish', array($this));
  }

So the publish hook is being invoked every time a comment is saved and it is currently published (whether or not it was previously published), and as far as I can tell, the unpublish hook is not being invoked at all.

And (see comment #2/Berdir) we probably do not need these hooks anyway, because you can use the generic update hooks and look at the original comment to see if its published status has changed.

Proposed resolution

Remove these two hooks from the comment.api.php file, and from being invoked in the postSave() method.

Alternative proposal: Invoke them as they are documented to be invoked (if the publishing status is being changed to published/unpublished).

Remaining tasks

a) Write a patch, get it reviewed.
b) Write a short change notice describing how to use other hooks to achieve the same purpose.

User interface changes

None.

API changes

No hook_comment_publish() or hook_comment_unpublish().

Original report by jhodgdon

While I was working on #2216535: Replace Node overview topic and Node API topic with Entity Hooks topic, I noticed several problems with the entity hooks:

a) When the entity CRUD hooks are invoked, the generic ones like hook_entity_create() and hook_entity_load() all have the entity type ID passed in. This was not documented in most of the hook documentation in entity.api.php (I'm fixing that).

However, this is not being tested in entity_crud_hook_test.module where it tests all the entity CRUD hooks. I think that should be fixed?

b) Inconsistency: In all cases but one, the EntityStorageBase::invokeHook() method is used to invoke the entity hooks from the storage controller. This makes the type-specific hook run before the generic hook (hook_ENTITY_TYPE_create() before hook_entity_create() for instance).

However, during load it goes in the opposite order. It seems like this should be reversed? See EntityStorageBase::postLoad().

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhodgdon’s picture

More to address:

c) I do not think that hook_comment_publish() and hook_comment_unpublish() are being invoked correctly. See Comment::postSave()
https://api.drupal.org/api/drupal/core!modules!comment!src!Entity!Commen...

It looks like the publish hook is being invoked on every save if the comment is now published, and the unpublish hook is not being invoked???

Berdir’s picture

So we fixed a) in a separate issue by removing that.

b) Yeah, possibly.

c) Not sure why we even have those hooks, it's really not that hard to check it yourself now with $comment->original.

Berdir’s picture

Note that c), unlike a/b is a comment specific problem, should possibly be a separate issue to discuss what to do with them? Agree that they are broken, so maybe just remove them as a "fix"...

jhodgdon’s picture

Title: Inconsistencies with entity hooks » Comment publish/unpublish hooks are not invoked correctly
Component: entity system » comment.module
Issue summary: View changes

Well, it looks like the comment hook is the only real relevant issue left on this one (I'm giving up worrying about the fact that the load() hooks run in backwards order from all other hooks; if you think it's worth pursuing, we can pursue it elsewhere).

So, repurposing this issue.

jhodgdon’s picture

Status: Active » Needs review
FileSize
1.72 KB

Here's the easy patch.

For the change notice, I think we could write this:
------
Title:
hook_comment_publish() and hook_comment_unpublish() have been removed

Body:
hook_comment_publish() and hook_comment_unpublish() have been removed in Drupal 8.x.

You can react to an update that changes the published status of a comment by using hook_entity_update(), or better yet hook_ENTITY_TYPE_update(). This will have $entity->original set to the original entity, before the changes.

Example in Drupal 7:

function mymodule_comment_publish($comment) {
  // The comment has just been published. React accordingly.
}

function mymodule_comment_unpublish($comment) {
  // The comment has just been unpublished. React accordingly.
}

Drupal 8:

function mymodule_comment_update($comment) {
  if ($comment->isPublished() && !$comment->original->isPublished()) {
     // The comment has just been published. React accordingly.
  }
  elseif (!$comment->isPublished() && $comment->original->isPublished()) {
     // The comment has just been unpublished. React accordingly.
  }
}

-------------

Thoughts? I can make a draft change notice, but since I am not sure the approach has been agreed to, I didn't do that yet.

Status: Needs review » Needs work

The last submitted patch, 5: 2294375-comment-hooks.patch, failed testing.

jhodgdon’s picture

It looks like Forum and Tracker modules were relying on the (flawed) hook_comment_publish() invoke. Their hook implementations will need to be updated.

jhodgdon’s picture

Status: Needs work » Needs review
FileSize
5.84 KB
4.12 KB

OK. Turns out node.module also implemented these two hooks, but since it also had a hook_comment_update(), it was pointless to do it again in those two hooks. The forum and tracker hook situation is I think a lot cleaner without these two hooks too, since (again) they were doing pretty much the same thing in the update hooks too.

This is seeming like a better and better idea...

Status: Needs review » Needs work

The last submitted patch, 8: 2294375-comment-hooks-8.patch, failed testing.

jhodgdon’s picture

Status: Needs work » Needs review
FileSize
5.86 KB

Oh, should fix a few docs things... and the non-working patch... interdiff failed...

Status: Needs review » Needs work

The last submitted patch, 10: 2294375-comment-hooks-9.patch, failed testing.

jhodgdon’s picture

OK, I give up. I don't get why using the update hook is failing. Maybe the comment storage class is doing something weird to bypass those hooks.

Anyway, the publish/unpublish hooks are not being invoked as they are documented and *something* needs to be done... I am just not sure what now.

larowlan’s picture

jhodgdon’s picture

Status: Needs work » Closed (duplicate)

Yeah, this issue should be a duplicate of that other one.

jhodgdon’s picture

jhodgdon’s picture

Status: Closed (duplicate) » Needs work

I changed my mind. This issue is also about the publish hook, and the other one is only about unpublish.

jhodgdon’s picture

Status: Needs work » Needs review
FileSize
6.3 KB

One more try on a patch. I think forum/tracker may need hook_comment_insert() done too.

larowlan’s picture

+++ b/core/modules/node/node.module
@@ -1673,23 +1673,3 @@ function node_comment_delete($comment) {
-function node_comment_publish($comment) {
...
-function node_comment_unpublish($comment) {

Should these be replaced with comment_{insert,update} hooks too?

Thanks for working on this!

jhodgdon’s picture

If this works, here's a new proposed change notice:
=============
------
Title:
hook_comment_publish() and hook_comment_unpublish() have been removed

Body:
hook_comment_publish() and hook_comment_unpublish() have been removed in Drupal 8.x.

You can react to an update that changes the published status of a comment by using hook_entity_update(), hook_entity_insert(), or better yet hook_ENTITY_TYPE_update() and hook_ENTITY_TYPE_insert().

The update hooks will have $entity->original set to the original entity, before the changes.

Example in Drupal 7:

function mymodule_comment_publish($comment) {
  // The comment has just been published. React accordingly.
}

function mymodule_comment_unpublish($comment) {
  // The comment has just been unpublished. React accordingly.
}

Drupal 8:

function mymodule_comment_update($comment) {
  if ($comment->isPublished() && !$comment->original->isPublished()) {
     // The comment has just been published for the first time. React accordingly.
  }
  elseif (!$comment->isPublished() && $comment->original->isPublished()) {
     // The comment has just been unpublished for the first time. React accordingly.
  }
}

function mymodule_comment_insert($comment) {
  if ($comment->isPublished()) {
     // A new published comment has just been created. React accordingly.
  }
  else {
    // A new unpublished comment has just been created. React accordingly.
  }
}

===============

jhodgdon’s picture

RE #18 - no, the node module already has insert/update comment hooks in it. No additional publish/unpublish hooks are necessary.

andypost’s picture

+1 to rtbc and removal, confirm #20
we could update https://www.drupal.org/node/2112417 change record for that and others anyway

jhodgdon’s picture

I do not see this as being really related to that other change record. I also think having the hook names in the change record title is important. So I think we should make a separate change record.

The tests passed on the latest patch, so I will go ahead and make a draft change record.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

This looks great, the hooks were used when the mass publish/unpublish did not save comments as whole entities, but that was changed a long time ago.

Nice how the resulting code is actually easier in all cases.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 17: 2294375-comment-hooks-17.patch, failed testing.

Status: Needs work » Needs review
andypost’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed ddaba8b and pushed to 8.x. Thanks!

Status: Fixed » Closed (fixed)

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