fn_b/app/Console/Commands/EditorialRelease.php

41 lines
1.8 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Services\Editorial\ReleaseRunner;
use Illuminate\Console\Command;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
final class EditorialRelease extends Command
{
protected $signature = 'editorial:release';
protected $description = 'Run a resumable editorial API operation from JSON on stdin, on this application server';
public function handle(): int
{
try {
abort_unless(PHP_SAPI === 'cli', 403);
if (! app()->environment('testing')) {
abort_unless(app()->environment('production')
&& realpath(base_path()) === '/www/wwwroot/clashfreenode-new.com'
&& rtrim(config('editorial.base_url'), '/') === 'https://clashfreenode.com'
&& function_exists('posix_geteuid') && posix_getpwuid(posix_geteuid())['name'] === 'nginx', 403, 'Server binding mismatch');
}
$raw = stream_get_contents(STDIN, 48 * 1024 * 1024 + 1);
abort_unless(strlen($raw) <= 48 * 1024 * 1024, 413);
$input = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
abort_unless(is_array($input), 422);
$result = app(ReleaseRunner::class)->run($input);
$this->line(json_encode(['ok' => true, 'data' => $result], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR));
return ($result['phase'] ?? '') === 'published_pending' ? 2 : 0;
} catch (\Throwable $e) {
$status = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500;
$this->line(json_encode(['ok' => false, 'status' => $status, 'error' => 'Release operation failed; use the same release_id to inspect or resume. No credential details are exposed.']));
return 1;
}
}
}