Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 10 additions & 32 deletions extensions/flags/src/AuditIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
namespace Flarum\Flags;

use Flarum\Audit\AuditLogger;
use Flarum\Post\Post;
use Flarum\Flags\Event\Dismissed;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
* Audit log integration for flarum/flags.
*
* Stateful: hooks the Flag model and a HasMany macro to detect flag dismissals. Wired into
* Hooks the Flag model's created event and the Dismissed event. Wired into
* flarum/audit through the Flarum\Audit\Extend\Audit extender's `using()` escape hatch, behind
* an Extend\Conditional so it's only active when flarum-audit is installed.
*/
Expand All @@ -35,36 +34,15 @@ public function __invoke(Container $container): void
// listener isn't bound to the model's static dispatcher.
$container->make(Dispatcher::class)->listen('eloquent.created: '.Flag::class, [$this, 'flagCreated']);

// We don't use the FlagsWillBeDeleted event as extensions might still prevent deletion at that
// point. This macro must stay a closure: it relies on $this being rebound to the HasMany
// instance at call time. It registers on the HasMany class (not a model instance), so it is
// not part of the serialized model graph that tripped the static model-event closures.
HasMany::macro('delete', function () {
/** @var HasMany $this */
$parent = $this->getParent();

// Because flarum/flags calls this every time a post is deleted, we need to check if there were actual flags.
$post = ($parent instanceof Post && $this->getQuery()->getModel() instanceof Flag && $this->getQuery()->count())
? $parent
: null;

// Replicates code from Relation::__call
$result = $this->forwardCallTo($this->getQuery(), 'delete', func_get_args());

if ($post) {
AuditLogger::log('post.dismissed_flags', [
'discussion_id' => $post->discussion->id,
'post_id' => $post->id,
]);
}

// Replicates code from Relation::__call
if ($result === $this->getQuery()) {
return $this;
}
$container->make(Dispatcher::class)->listen(Dismissed::class, [$this, 'flagsDismissed']);
}

return $result;
});
public function flagsDismissed(Dismissed $event): void
{
AuditLogger::log('post.dismissed_flags', [
'discussion_id' => $event->post->discussion->id,
'post_id' => $event->post->id,
]);
}

public function flagCreated(Flag $flag): void
Expand Down
11 changes: 9 additions & 2 deletions extensions/flags/src/Command/DeleteFlagsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Flarum\Flags\Command;

use Flarum\Flags\Event\Deleting;
use Flarum\Flags\Event\Dismissed;
use Flarum\Post\Post;
use Flarum\Post\PostRepository;
use Illuminate\Events\Dispatcher;
Expand All @@ -30,11 +31,17 @@ public function handle(DeleteFlags $command): Post

$actor->assertCan('viewFlags', $post->discussion);

foreach ($post->flags as $flag) {
$flags = $post->flags;

foreach ($flags as $flag) {
$this->events->dispatch(new Deleting($flag, $actor, $command->data));
}

$post->flags()->delete();
$flags->each->delete();

if ($flags->isNotEmpty()) {
$this->events->dispatch(new Dismissed($post, $flags, $actor, $command->data));
}

return $post;
}
Expand Down
29 changes: 29 additions & 0 deletions extensions/flags/src/Event/Dismissed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/

namespace Flarum\Flags\Event;

use Flarum\Flags\Flag;
use Flarum\Post\Post;
use Flarum\User\User;
use Illuminate\Support\Collection;

class Dismissed
{
/**
* @param Collection<int, Flag> $flags
*/
public function __construct(
public Post $post,
public Collection $flags,
public User $actor,
public array $data = []
) {
}
}
Loading