›
byrcsc/laravel-comments · 1.x
Choose the initial moderation status for each new comment.
Every comment lands in some status the moment it is written. Which one is resolved in a fixed, short order:
initialCommentStatus() hook, when it implements
DecidesCommentStatus.comments.default_status for a model-authored comment, or
comments.guest_status for a guest one.'default_status' => 'approved',
'guest_status' => 'pending',Guests are read from their own key on purpose. Raising default_status never
drags anonymous content along with it, approving content nobody can be held to
is a decision the package will not make for you. Set guest_status yourself
when you mean it.
Both accept pending, approved, rejected, or spam. Anything else throws
an InvalidConfigurationException when the package boots.
Hold everything for review by lowering the default:
'default_status' => 'pending',Implement the contract on the commentable when config cannot express the rule. Examples include holding a new user's first comment, approving comments on a closed internal board, or holding every comment on a locked thread.
use ByRcsc\LaravelComments\Contracts\DecidesCommentStatus;
use ByRcsc\LaravelComments\Enums\CommentStatus;
use ByRcsc\LaravelComments\Models\Comment;
class Post extends Model implements DecidesCommentStatus
{
use HasComments;
public function initialCommentStatus(Comment $comment): ?CommentStatus
{
if ($this->comments_locked) {
return CommentStatus::Pending;
}
return null;
}
}The comment handed to the hook is unsaved and fully populated: its commentator, guest identity, parent, and body are all readable, and nothing it says has been trusted yet.
Returning null hands the decision back to the configured defaults, so a hook
only has to answer the cases it cares about. The hook is asked about replies as
well as thread starters.
Two things the hook is deliberately not:
It is not an authorization check. Returning pending holds a comment; it
does not refuse one. Refusing a write belongs in the
policy or your controller.
It is not consulted when a status was named. A factory, a seeder, or an import restoring an export already knows what it meant:
$post->comments()->create(['body' => 'Imported', 'status' => CommentStatus::Approved]);Resolution is only for the writes that said nothing.
The commentable is loaded for the hook only when its class implements the
contract, so a model that does not pays nothing. On the ordinary write path the
commentable is already in hand, $post->comment(...) hands the model over
rather than re-reading the row, so implementing the hook costs no extra query
either. Writing through the Comment model directly, without the commentable
loaded, costs one read.
Comment::factory() sets no status, so factory-built comments resolve theirs
exactly as written ones do, a guest lands pending, which is what a test of a
moderation queue should be seeing. Name one with status() or its shortcuts
when the test is about a particular status:
Comment::factory()->forCommentable($post)->pending()->create();See testing.