Files
Gnuboard7/app/Console/Helpers/ConsoleConfirm.php
T
2026-05-11 11:29:41 +09:00

107 lines
3.0 KiB
PHP

<?php
namespace App\Console\Helpers;
/**
* 콘솔 yes/no 프롬프트 표준 헬퍼.
*
* Symfony Console 비의존(fgets 기반) — Laravel Command 외부, upgrade step,
* 단순 PHP 스크립트 어디서나 호출 가능하다. 입력 처리 규칙:
*
* 1. 입력을 trim 후 소문자 정규화한다
* 2. empty 입력은 default 값으로 처리한다
* 3. yes / y → true, no / n → false
* 4. 위 외 입력은 안내 메시지 출력 후 다시 질문한다 (재질문 루프)
* 5. STDIN 미연결(非TTY) 또는 EOF 시 default 를 즉시 반환한다 (CI/spawn 안전망)
*/
final class ConsoleConfirm
{
/**
* 표준 yes/no 프롬프트.
*
* @param string $question 질문 메시지 (말미 안내/콜론은 자동 부여)
* @param bool $default 기본값 (true=[yes], false=[no])
* @param resource|null $stdin 테스트용 STDIN 주입. null 이면 STDIN 사용
* @param callable|null $writer 테스트용 출력 콜백. null 이면 echo 사용
*/
public static function ask(
string $question,
bool $default = false,
$stdin = null,
?callable $writer = null,
): bool {
$writer ??= static fn (string $text) => print $text;
$useStdin = $stdin !== null;
if (! $useStdin && ! self::isTty()) {
return $default;
}
$hint = $default ? '[yes]' : '[no]';
$stream = $useStdin ? $stdin : (defined('STDIN') ? STDIN : null);
if ($stream === null) {
return $default;
}
while (true) {
$writer("{$question} (yes/no) {$hint}: ");
$raw = fgets($stream);
if ($raw === false) {
return $default;
}
$parsed = self::parse($raw, $default);
if ($parsed !== null) {
return $parsed;
}
$writer(" yes, y, no, n 중 하나로 입력해 주세요.\n");
}
}
/**
* 입력 문자열을 yes/no/null 로 정규화한다.
*
* @param string $raw 사용자 입력 원문 (개행 포함 가능)
* @param bool $default empty 입력 시 반환할 값
* @return bool|null true=yes, false=no, null=재질문 필요
*/
public static function parse(string $raw, bool $default): ?bool
{
$answer = strtolower(trim($raw));
if ($answer === '') {
return $default;
}
if ($answer === 'yes' || $answer === 'y') {
return true;
}
if ($answer === 'no' || $answer === 'n') {
return false;
}
return null;
}
/**
* STDIN 이 TTY 인지 검사한다.
*/
private static function isTty(): bool
{
if (! defined('STDIN')) {
return false;
}
if (function_exists('stream_isatty')) {
return @stream_isatty(STDIN);
}
if (function_exists('posix_isatty')) {
return @posix_isatty(STDIN);
}
return false;
}
}