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;
 | 
						|
    }
 | 
						|
} |