fedi-feed-router/app/Actions/PublishRouteArticleAction.php

107 lines
3.6 KiB
PHP

<?php
namespace App\Actions;
use App\Enums\LogLevelEnum;
use App\Enums\NotificationSeverityEnum;
use App\Enums\NotificationTypeEnum;
use App\Enums\PublishStatusEnum;
use App\Events\ActionPerformed;
use App\Exceptions\PublishException;
use App\Models\RouteArticle;
use App\Services\Article\ArticleFetcher;
use App\Services\Notification\NotificationService;
use App\Services\Publishing\ArticlePublishingService;
use App\Services\Publishing\PublishOutcome;
use Exception;
class PublishRouteArticleAction
{
public function __construct(
private ArticleFetcher $articleFetcher,
private ArticlePublishingService $publishingService,
private NotificationService $notificationService,
) {}
/**
* @throws PublishException
*/
public function execute(RouteArticle $routeArticle): PublishOutcome
{
$article = $routeArticle->article;
$routeArticle->update(['publish_status' => PublishStatusEnum::PUBLISHING]);
try {
$extractedData = $this->articleFetcher->fetchArticleData($article);
$outcome = $this->publishingService->publishRouteArticle($routeArticle, $extractedData);
} catch (Exception $e) {
$routeArticle->update(['publish_status' => PublishStatusEnum::ERROR]);
ActionPerformed::dispatch('Failed to publish article', LogLevelEnum::ERROR, [
'article_id' => $article->id,
'error' => $e->getMessage(),
]);
$this->notificationService->send(
NotificationTypeEnum::PUBLISH_FAILED,
NotificationSeverityEnum::ERROR,
"Publish failed: {$article->title}",
$e->getMessage(),
$article,
);
throw $e;
}
match (true) {
$outcome->succeeded() => $this->recordPublished($routeArticle),
$outcome->wasSkipped() => $this->recordSkipped($routeArticle, $outcome),
default => $this->recordFailed($routeArticle, $outcome),
};
return $outcome;
}
private function recordPublished(RouteArticle $routeArticle): void
{
$routeArticle->update(['publish_status' => PublishStatusEnum::PUBLISHED]);
ActionPerformed::dispatch('Published article', LogLevelEnum::INFO, [
'article_id' => $routeArticle->article->id,
'title' => $routeArticle->article->title,
]);
}
private function recordSkipped(RouteArticle $routeArticle, PublishOutcome $outcome): void
{
$routeArticle->update(['publish_status' => PublishStatusEnum::SKIPPED]);
ActionPerformed::dispatch('Skipped publishing article', LogLevelEnum::INFO, [
'article_id' => $routeArticle->article->id,
'title' => $routeArticle->article->title,
'reason' => $outcome->reason,
]);
}
private function recordFailed(RouteArticle $routeArticle, PublishOutcome $outcome): void
{
$article = $routeArticle->article;
$routeArticle->update(['publish_status' => PublishStatusEnum::ERROR]);
ActionPerformed::dispatch('No publication created for article', LogLevelEnum::WARNING, [
'article_id' => $article->id,
'title' => $article->title,
'reason' => $outcome->reason,
]);
$this->notificationService->send(
NotificationTypeEnum::PUBLISH_FAILED,
NotificationSeverityEnum::WARNING,
"Publish failed: {$article->title}",
$outcome->reason ?? 'No publication was created for this article.',
$article,
);
}
}