Files
SkinbaseNova/app/Console/Commands/PublishScheduledArtworksCommand.php
2026-04-18 17:02:56 +02:00

88 lines
2.8 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Services\Artworks\ArtworkPublicationService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
/**
* PublishScheduledArtworksCommand
*
* Runs every minute (via Kernel schedule).
* Finds artworks with:
* - artwork_status = 'scheduled'
* - publish_at <= now() (UTC)
* - is_approved = true (respect moderation gate)
*
* Publishes each one:
* - sets is_public = true
* - sets published_at = now()
* - sets artwork_status = 'published'
* - dispatches Meilisearch reindex (via Scout)
* - records activity event
*
* Safe to run concurrently (DB row lock prevents double-publish).
*/
class PublishScheduledArtworksCommand extends Command
{
protected $signature = 'artworks:publish-scheduled
{--dry-run : List candidate artworks without publishing}
{--limit=100 : Max artworks to process per run}';
protected $description = 'Publish scheduled artworks whose publish_at datetime has passed.';
public function __construct(
private readonly ArtworkPublicationService $publicationService,
) {
parent::__construct();
}
public function handle(): int
{
$dryRun = (bool) $this->option('dry-run');
$limit = (int) $this->option('limit');
$now = now()->utc();
$result = $this->publicationService->publishDueScheduled($limit, $now);
$candidates = $result['candidates'];
if ($candidates->isEmpty()) {
$this->line('No scheduled artworks due for publishing.');
return self::SUCCESS;
}
$this->info("Found {$candidates->count()} artwork(s) to publish." . ($dryRun ? ' [DRY RUN]' : ''));
$published = 0;
$errors = 0;
foreach ($candidates as $candidate) {
if ($dryRun) {
$this->line(" [dry-run] Would publish artwork #{$candidate->id}: \"{$candidate->title}\"");
continue;
}
try {
$artwork = $this->publicationService->publishIfDue($candidate, $now);
if ($artwork->artwork_status === 'published') {
$published++;
$this->line(" Published artwork #{$artwork->id}: \"{$artwork->title}\"");
}
} catch (\Throwable $e) {
$errors++;
Log::error("PublishScheduledArtworksCommand: failed to publish artwork #{$candidate->id}: {$e->getMessage()}");
$this->error(" Failed to publish #{$candidate->id}: {$e->getMessage()}");
}
}
if (! $dryRun) {
$this->info("Done. Published: {$published}, Errors: {$errors}.");
}
return $errors > 0 ? self::FAILURE : self::SUCCESS;
}
}