*/ private const EDIT_BLOCKED_STATUSES = [ PostStatus::Published, PostStatus::PartiallyPublished, PostStatus::Failed, PostStatus::Publishing, ]; /** * Statuses where the post can no longer be deleted. * * @var array */ private const DELETE_BLOCKED_STATUSES = [ PostStatus::Publishing, PostStatus::Published, PostStatus::PartiallyPublished, ]; public static function blocksEditing(Post $post): bool { return in_array($post->status, self::EDIT_BLOCKED_STATUSES, true); } public static function blocksDeletion(Post $post): bool { return in_array($post->status, self::DELETE_BLOCKED_STATUSES, true); } public static function editBlockedMessage(): string { return __(self::EDIT_BLOCKED_MESSAGE_KEY); } /** * True when status is scheduled and the post has no future schedule to reuse. */ public static function requiresExplicitSchedule(?Post $post, mixed $status): bool { if ($status !== PostStatus::Scheduled->value) { return false; } $existing = $post?->scheduled_at; return $existing === null || $existing->isPast(); } /** * Validation rules for `scheduled_at` on post update (web, API, MCP). * * @return list */ public static function scheduledAtRules(?Post $post, mixed $status): array { return [ Rule::requiredIf(fn (): bool => self::requiresExplicitSchedule($post, $status)), 'nullable', 'date', Rule::when( $status === PostStatus::Scheduled->value, ['after:now'], ), ]; } }