Blog and Comment Hooks

310 visualizzazioni Markdown

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

gateclient.blog_comment_moderate
ClientBlog the request, not the result

Runs before a comment is moderated.

Parameters 5
$cidintThe comment id.
$actionstringThe operation requested: approve, spam or pin. ? Pinning is a toggle request: whether it ends as pinning or unpinning depends on the current state. This value states the request, not the result.
$actor_idintThe id of the administrator doing it.
$author_idintThe author of the comment. It is zero on a guest comment: test before doing anything tied to a member.
$owner_idintThe article the comment belongs to.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
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

actionclient.blog_comment_moderated
ClientBlog the result, not the request

Runs after the moderation is applied. Unlike the gate, the value here is the operation that actually happened.

Parameters 5
$cidintThe comment id.
$actionstringThe operation that happened: approved, spam, pinned or unpinned. Against the three values in the gate there are four here: the toggle request has split into two separate results.
$actor_idintThe administrator who did it.
$author_idintThe author of the comment. It is zero on a guest comment: test before doing anything tied to a member.
$owner_idintThe article the comment belongs to.
Return 1
voidThe return is ignored.
Listener
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

actionclient.blog_comment_edited
ClientBlog the body is encoded

Runs after a comment is edited by an administrator.

Parameters 5
$cidintThe comment id.
$actor_idintThe administrator who edited it.
$author_idintThe author of the comment. It is zero on a guest comment: test before doing anything tied to a member.
$oldstringThe body before the edit. Both arrive encoded: showing them directly turns markup into visible text.
$newstringThe body after the edit, as saved.
Return 1
voidThe return is ignored.
Listener
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

actionclient.blog_comment_deleted
ClientBlog the replies go too

Runs after a comment is deleted.

Parameters 5
$cidintThe id of the deleted comment; the record is gone.
$actor_idintThe administrator who deleted it.
$author_idintThe author of the comment. It is zero on a guest comment: test before doing anything tied to a member.
$owner_idintThe article the comment belongs to.
$parent_idintThe comment replied to. ? A zero means a root comment went, and its replies went with it — with no separate call for them. Clear the whole branch in your own store.
Return 1
voidThe return is ignored.
Listener
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

actionclient.blog_comment_voted
ClientBlog a toggle

Runs when a comment is marked helpful or the mark is taken back.

Parameters 4
$cidintThe comment voted on.
$viewer_idintThe member voting. This flow is members only, so the value is always filled.
$activeboolThe direction: true for a vote, false for taking it back.
$countintThe current total after the vote.
Return 1
voidThe return is ignored.
Listener
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

filterclient.blog_comment_message
ClientBlog raw text

Runs before a comment is saved. The place to put a filter of your own.

Parameters 2
$messagestringby linkThe comment body, raw and not yet encoded. What you write over it is saved.
$ctxarrayby linkContext: the article, the comment replied to, the member id and whether it is a guest. The member id is zero for a guest.
Return 1
voidThe return is ignored; you write over the data.
Listener
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

filterclient.blog_comment_list
ClientBlog an admin sees more

Runs before the comments reach the screen. It runs separately for reply lists too.

Parameters 2
$itemsarrayby linkThe comments to show, with their formatted fields.
$ctxarrayby linkContext: whether this is a reply list, which article, and whether an administrator is looking. ? When an administrator looks, comments awaiting approval are in the list too. A listener ignoring that counts or exports unpublished content.
Return 1
voidThe return is ignored; you write over the data.
Listener
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

The gate states the request, the event the result

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.

Deleting a root comment takes its replies

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.

Ti è stato utile?

Grazie per il tuo feedback!

Hai ancora bisogno di aiuto?

Il nostro team di assistenza è disponibile 24 ore su 24 per aiutarti a trovare le risposte che cerchi.