Blog and Comment Hooks
The seven hooks over blog comments: moderation, editing, deletion, votes and the list.
Overview
The path of a blog comment lives here: it is written, filtered, listed, moderated and if need be deleted.
Two distinctions to hold from the start. On a guest comment the author id is zero. And the moderation gate hands you the request while the event hands you the result: because pinning is a toggle, the two are not the same.
Reference
Stopping a comment moderation
Runs before a comment is moderated.
Hook::add('gate:client.blog_comment_moderate', 10,
function ($cid, $action, $actor_id, $author_id, $owner_id) {
// 'pin' is a TOGGLE request: you cannot tell the result from here.
if ($action === 'spam' && Acme::protectedAuthor($author_id))
return 'Comments from this author cannot be marked as spam.';
return null;
});Following a comment moderation
Runs after the moderation is applied. Unlike the gate, the value here is the operation that actually happened.
Hook::add('action:client.blog_comment_moderated', 10,
function ($cid, $action, $actor_id, $author_id, $owner_id) {
// FOUR values here: the toggle has split in two.
if ($action === 'approved' && $author_id) Acme::thankAuthor($author_id);
});Following a comment being edited
Runs after a comment is edited by an administrator.
Hook::add('action:client.blog_comment_edited', 10,
function ($cid, $actor_id, $author_id, $old, $new) {
// Both bodies arrive ENCODED.
Acme::auditEdit($cid, $actor_id, html_entity_decode($old), html_entity_decode($new));
});Following a comment being deleted
Runs after a comment is deleted.
Hook::add('action:client.blog_comment_deleted', 10,
function ($cid, $actor_id, $author_id, $owner_id, $parent_id) {
// On a root comment the replies went too, with no separate call.
if ($parent_id === 0) Acme::dropBranch($cid);
else Acme::dropComment($cid);
});Following a comment vote
Runs when a comment is marked helpful or the mark is taken back.
Hook::add('action:client.blog_comment_voted', 10,
function ($cid, $viewer_id, $active, $count) {
if ($active && $count >= 10) Acme::promoteComment($cid);
});Changing a comment body before it is saved
Runs before a comment is saved. The place to put a filter of your own.
Hook::add('filter:client.blog_comment_message', 10, function (&$message, &$ctx) {
// The body is RAW: encoding happens afterwards.
$message = Acme::stripLinks($message);
});Changing the comment list
Runs before the comments reach the screen. It runs separately for reply lists too.
Hook::add('filter:client.blog_comment_list', 10, function (&$items, &$ctx) {
// When an administrator looks, pending comments are in the list too.
if ($ctx['is_admin'] ?? false) return;
$items = Acme::hideFlagged($items);
});Pitfalls
In the moderation gate pinning is a toggle request: you cannot tell from there whether it ends as pinning or unpinning. In the event the value arrives already split in two. A rule assuming the result at the gate misjudges an unpinning.
A zero parent id in the delete event means a root comment went and every reply beneath it went too. But no separate call arrives for those replies: you must clear the whole branch on your side, or orphan records remain.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.