Initial commit: Pireon Admin — headless admin panel and public API

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>
This commit is contained in:
2026-08-19 17:55:27 +02:00
commit 3897113313
534 changed files with 64050 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Models\Media;
use App\Services\Media\ImageProcessor;
use Illuminate\Console\Command;
/**
* The safety net, and the way back from a change of settings.
*
* Uploads queue their own processing, but a queue that is not running would
* leave images without dimensions and nobody would notice until the page
* reflowed. The scheduler runs this every ten minutes so a stalled worker
* costs a delay rather than a permanently half-done image.
*
* `--all` reprocesses everything, which is what you want after changing the
* widths or adding a format: the media table is derived, so it can always be
* rebuilt from the files themselves.
*/
class ProcessMediaCommand extends Command
{
protected $signature = 'media:process
{--all : Reprocess every image, not only the pending ones}
{--limit=100 : Maximum number of images to handle in one run}';
protected $description = 'Derive dimensions, responsive versions and placeholders for uploaded images';
public function handle(ImageProcessor $processor): int
{
$media = Media::query()
->unless($this->option('all'), fn ($q) => $q->pending())
->orderBy('id')
->limit(max(1, (int) $this->option('limit')))
->get();
if ($media->isEmpty()) {
$this->components->info('Nothing to process.');
return self::SUCCESS;
}
$failed = 0;
foreach ($media as $item) {
$processor->process($item->refresh());
if ($item->refresh()->error) {
$failed++;
$this->components->error("{$item->path} — {$item->error}");
continue;
}
$this->components->twoColumnDetail(
$item->path,
$item->width ? "{$item->width}×{$item->height} · ".count($item->variants ?? []).' versions' : 'no dimensions',
);
}
$this->newLine();
$this->components->info("Processed {$media->count()} images, {$failed} failed.");
// A failure here is usually a missing file, which is worth a non-zero
// exit in a deploy script.
return $failed > 0 ? self::FAILURE : self::SUCCESS;
}
}