mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-26 02:10:19 +08:00
3625f12abe
Creates a new organsied formatting system for webhook data, with interfaces for extending with custom model formatting rules. Allows easy usage & extension of the default bookstack formatting behaviour when customizing webhook events via theme system, and keeps default data customizations organised. This also makes the following webhook data changes: - owned_by/created_by/updated_by user details are loaded for events with Entity details. (POTENTIALLY BREAKING CHANGE). - current_revision details are loaded for page update/create events. Added testing to cover added model formatting rules. For #3279 and #3218
123 lines
3.7 KiB
PHP
123 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace BookStack\Actions;
|
|
|
|
use BookStack\Auth\User;
|
|
use BookStack\Entities\Models\Entity;
|
|
use BookStack\Entities\Models\Page;
|
|
use BookStack\Interfaces\Loggable;
|
|
use BookStack\Model;
|
|
use Illuminate\Support\Carbon;
|
|
|
|
class WebhookFormatter
|
|
{
|
|
protected Webhook $webhook;
|
|
protected string $event;
|
|
protected User $initiator;
|
|
protected int $initiatedTime;
|
|
|
|
/**
|
|
* @var string|Loggable
|
|
*/
|
|
protected $detail;
|
|
|
|
/**
|
|
* @var array{condition: callable(string, Model):bool, format: callable(Model):void}[]
|
|
*/
|
|
protected $modelFormatters = [];
|
|
|
|
public function __construct(string $event, Webhook $webhook, $detail, User $initiator, int $initiatedTime)
|
|
{
|
|
$this->webhook = $webhook;
|
|
$this->event = $event;
|
|
$this->initiator = $initiator;
|
|
$this->initiatedTime = $initiatedTime;
|
|
$this->detail = is_object($detail) ? clone $detail : $detail;
|
|
}
|
|
|
|
public function format(): array
|
|
{
|
|
$data = [
|
|
'event' => $this->event,
|
|
'text' => $this->formatText(),
|
|
'triggered_at' => Carbon::createFromTimestampUTC($this->initiatedTime)->toISOString(),
|
|
'triggered_by' => $this->initiator->attributesToArray(),
|
|
'triggered_by_profile_url' => $this->initiator->getProfileUrl(),
|
|
'webhook_id' => $this->webhook->id,
|
|
'webhook_name' => $this->webhook->name,
|
|
];
|
|
|
|
if (method_exists($this->detail, 'getUrl')) {
|
|
$data['url'] = $this->detail->getUrl();
|
|
}
|
|
|
|
if ($this->detail instanceof Model) {
|
|
$data['related_item'] = $this->formatModel();
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @param callable(string, Model):bool $condition
|
|
* @param callable(Model):void $format
|
|
*/
|
|
public function addModelFormatter(callable $condition, callable $format): void
|
|
{
|
|
$this->modelFormatters[] = [
|
|
'condition' => $condition,
|
|
'format' => $format,
|
|
];
|
|
}
|
|
|
|
public function addDefaultModelFormatters(): void
|
|
{
|
|
// Load entity owner, creator, updater details
|
|
$this->addModelFormatter(
|
|
fn($event, $model) => ($model instanceof Entity),
|
|
fn($model) => $model->load(['ownedBy', 'createdBy', 'updatedBy'])
|
|
);
|
|
|
|
// Load revision detail for page update and create events
|
|
$this->addModelFormatter(
|
|
fn($event, $model) => ($model instanceof Page && ($event === ActivityType::PAGE_CREATE || $event === ActivityType::PAGE_UPDATE)),
|
|
fn($model) => $model->load('currentRevision')
|
|
);
|
|
}
|
|
|
|
protected function formatModel(): array
|
|
{
|
|
/** @var Model $model */
|
|
$model = $this->detail;
|
|
$model->unsetRelations();
|
|
|
|
foreach ($this->modelFormatters as $formatter) {
|
|
if ($formatter['condition']($this->event, $model)) {
|
|
$formatter['format']($model);
|
|
}
|
|
}
|
|
|
|
return $model->toArray();
|
|
}
|
|
|
|
protected function formatText(): string
|
|
{
|
|
$textParts = [
|
|
$this->initiator->name,
|
|
trans('activities.' . $this->event),
|
|
];
|
|
|
|
if ($this->detail instanceof Entity) {
|
|
$textParts[] = '"' . $this->detail->name . '"';
|
|
}
|
|
|
|
return implode(' ', $textParts);
|
|
}
|
|
|
|
public static function getDefault(string $event, Webhook $webhook, $detail, User $initiator, int $initiatedTime): self
|
|
{
|
|
$instance = new static($event, $webhook, $detail, $initiator, $initiatedTime);
|
|
$instance->addDefaultModelFormatters();
|
|
return $instance;
|
|
}
|
|
} |