Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
83 lines
2.8 KiB
PHP
83 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Enums\CallStatus;
|
|
use App\Models\Call;
|
|
use App\Models\Page;
|
|
use App\Models\Project;
|
|
use Illuminate\Console\Command;
|
|
|
|
/**
|
|
* Keeps the stored state honest about what the site is actually showing.
|
|
*
|
|
* Most of scheduling needs no command at all: the `published` scopes read the
|
|
* dates, so content appears and disappears on time whether or not anything is
|
|
* running. What a scope cannot do is change what the panel *says*, and a panel
|
|
* that reports "Open" for a call the site stopped offering weeks ago is how a
|
|
* counter stops being read.
|
|
*
|
|
* So this closes what has expired and leaves everything else alone. In
|
|
* particular it does not touch the status of pages or projects: their window
|
|
* already hides them, and rewriting a status would throw away the one somebody
|
|
* chose in order to record something the dates already say.
|
|
*/
|
|
class ScheduleContentCommand extends Command
|
|
{
|
|
protected $signature = 'content:schedule
|
|
{--dry-run : Report what would change without changing it}';
|
|
|
|
protected $description = 'Close calls past their date and report content entering or leaving the site';
|
|
|
|
public function handle(): int
|
|
{
|
|
$expired = Call::query()
|
|
->where('status', CallStatus::Open)
|
|
->whereNotNull('closes_at')
|
|
->where('closes_at', '<', now())
|
|
->get();
|
|
|
|
foreach ($expired as $call) {
|
|
$title = $call->getTranslation('title', (string) config('locales.default'), false);
|
|
|
|
$this->components->twoColumnDetail(
|
|
$title ?: "#{$call->id}",
|
|
'<fg=gray>'.__('console.schedule.closed').'</>',
|
|
);
|
|
|
|
if (! $this->option('dry-run')) {
|
|
$call->update(['status' => CallStatus::Closed]);
|
|
}
|
|
}
|
|
|
|
$this->report();
|
|
|
|
$this->components->info(
|
|
trans_choice('console.schedule.summary', $expired->count(), ['count' => $expired->count()])
|
|
);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* What the dates are about to do on their own. Nothing here needs acting
|
|
* on; it is here so that a scheduled release is visible in the logs before
|
|
* it happens rather than only afterwards.
|
|
*/
|
|
protected function report(): void
|
|
{
|
|
$pending = Page::query()->scheduled()->count() + Project::query()->scheduled()->count();
|
|
$expiring = Page::query()->expired()->count() + Project::query()->expired()->count();
|
|
|
|
if ($pending > 0) {
|
|
$this->components->twoColumnDetail(__('console.schedule.pending'), (string) $pending);
|
|
}
|
|
|
|
if ($expiring > 0) {
|
|
$this->components->twoColumnDetail(__('console.schedule.off_site'), (string) $expiring);
|
|
}
|
|
}
|
|
}
|