콘텐츠로 이동

Cli: 명령 핸들러와 외부 검증기 어댑터

Cli 모듈은 엔진의 진단 및 적합성 도구를 뒷받침하는 명령 인터페이스입니다. benchmark, diff, init, verify, capabilities로 구성된 명령 핸들러 모음입니다. 또한 외부 PDF 검증기(veraPDF, Arlington PDF 모델)를 하나의 인터페이스 뒤에 감싸는 어댑터 모음이기도 합니다. 단일 verify 명령으로 그중 어느 검증기든 구동할 수 있습니다.

Terminal window
composer require nextpdf/core:^3

각 명령은 프로세스 종료 코드를 반환하는 execute() 메서드를 가진 핸들러 클래스입니다. BenchmarkHandler는 벤치마크 시나리오를 실행합니다. DiffHandler는 문서를 비교합니다. InitHandler는 프로젝트를 스캐폴딩합니다. VerifyHandler는 적합성 검증을 실행합니다. CapabilitiesHandler는 런타임이 지원하는 기능을 보고합니다. CliOutput은 핸들러가 공유하는 가벼운 stdout/stderr 작성기이므로, 출력을 전역 상태에 결합하지 않고 테스트할 수 있습니다. BinaryFinder는 호스트에서 외부 도구 경로를 해석합니다(@since 2.5.0).

검증 인터페이스가 이 아키텍처의 핵심입니다. AlternateValidatorAdapter는 외부 검증기가 구현하는 인터페이스입니다. validate()는 PDF 경로와 ComplianceFlavour를 받아 ComplianceValidationResult를 반환합니다. isAvailable()는 백엔드 도구가 설치되어 있는지 보고합니다. toolIdentifier()는 해당 도구를 식별합니다. VeraPdfCliAdapter, ArlingtonValidatorAdapter, AsyncValidatorAdapter가 이를 구현합니다. 즉, 엔진은 서드파티 검증기를 다시 구현하지 않습니다. 엔진은 참조 도구를 실행하고 그 판정을 정규화합니다. 설치되지 않은 검증기는 실행을 실패시키지 않고 isAvailable() === false를 보고하므로, 검증은 명시적으로 단계적 축소로 처리됩니다. 어댑터는 @since 3.0.0이며, 코어 핸들러는 @since 2.3.0@since 2.5.0입니다.

클래스주요 멤버역할
BenchmarkHandlerexecute(string $format = 'pretty', ?string $scenario = null): int벤치마크 시나리오를 실행합니다(@since 2.4.0)
VerifyHandlerexecute(): int적합성 검증을 구동합니다
DiffHandler / InitHandlerexecute(): int문서 diff / 프로젝트 스캐폴딩
CapabilitiesHandlerexecute(string $format = 'pretty'): int런타임 기능을 보고합니다(@since 2.3.0)
AlternateValidatorAdapter (인터페이스)validate(), isAvailable(), toolIdentifier()외부 검증기 계약(@since 3.0.0)
VeraPdfCliAdapter어댑터를 구현합니다veraPDF CLI를 감쌉니다(@since 3.0.0)
ArlingtonValidatorAdapter어댑터를 구현합니다Arlington PDF 모델을 감쌉니다(@since 3.0.0)
AsyncValidatorAdapter어댑터를 구현합니다비동기 처리를 지원하는 검증기 래퍼(@since 3.0.0)
CliOutputwrite(), writeln(), error()테스트 가능한 stdout/stderr 출력 작성기(@since 2.3.0)
BinaryFinder외부 도구 경로 해석호스트의 도구를 찾습니다(@since 2.5.0)

전체 PHPDoc 표는 composer docs:generate-api-php -- --module=Cli를 실행해 확인하십시오.

출처: examples/33-validate-conformance.php. 검증기 어댑터를 선택한 뒤, 사용하기 전에 가용성을 확인합니다:

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Cli\VeraPdfCliAdapter;
use NextPDF\Compliance\ComplianceFlavour;
$validator = new VeraPdfCliAdapter(/* binary path / process factory */);
if (!$validator->isAvailable()) {
fwrite(STDERR, "veraPDF is not installed; conformance verification skipped.\n");
exit(2);
}
$result = $validator->validate('/srv/out/report.pdf', ComplianceFlavour::PdfA4);
echo $result->isCompliant() ? "PASS\n" : "FAIL\n";

사용 가능한 검증기로 검증을 실행하되, 없는 도구는 실패가 아닌 건너뛴 검사로 취급합니다.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Cli\AlternateValidatorAdapter;
use NextPDF\Compliance\ComplianceFlavour;
use Psr\Log\LoggerInterface;
final readonly class ConformanceGate
{
/** @param list<AlternateValidatorAdapter> $validators */
public function __construct(
private array $validators,
private LoggerInterface $logger,
) {}
public function verify(string $pdfPath, ComplianceFlavour $flavour): bool
{
$ran = false;
foreach ($this->validators as $validator) {
if (!$validator->isAvailable()) {
$this->logger->info('Validator absent; skipped.', ['tool' => $validator->toolIdentifier()]);
continue;
}
$ran = true;
if (!$validator->validate($pdfPath, $flavour)->isCompliant()) {
$this->logger->error('Conformance failed.', ['tool' => $validator->toolIdentifier()]);
return false;
}
}
// No validator available is not a pass — surface it.
return $ran;
}
}
  • 사용할 수 없는 검증기는 isAvailable() === false를 반환합니다. 예외를 던지지 않습니다. “사용 가능한 검증기 없음”은 통과가 아닙니다 — 프로덕션 샘플처럼 이를 별도로 처리하십시오.
  • 어댑터는 외부 바이너리를 실행합니다. 그 판정은 외부 도구의 판정을 정규화한 것이며, 독립적으로 다시 구현한 판정이 아닙니다. 도구를 최신 상태로 유지하십시오.
  • 핸들러 execute()는 프로세스 종료 코드를 반환합니다. 0이 아닌 값은 실패입니다. 무시하지 말고 래퍼에서 이를 전파하십시오.
  • BinaryFinder는 호스트에서 도구 경로를 해석합니다. 다른 호스트에서는 다른 도구 버전으로 해석될 수 있습니다. 재현 가능한 검증을 위해 환경을 고정하십시오.
  • 재현성 프로필은 structural입니다. 검증 보고서에는 타임스탬프와 도구 버전이 포함되므로, 두 번의 실행은 해당 필드에서 달라집니다.

핸들러 오버헤드는 무시할 수 있는 수준입니다. 비용의 대부분은 외부 검증기 프로세스에서 발생하며, 큰 문서에서는 느릴 수 있습니다. AsyncValidatorAdapter는 그 지연 시간을 겹쳐 처리하기 위해 제공됩니다. 1500 ms 벽시계 시간 / 64 MB 최대 메모리의 performance_budget는 엔진 기준값이며, 외부 검증기에 적용되는 한계가 아닙니다. 벤치마크 출력은 구조상 결정론적이지만, 본질적으로 타이밍 데이터를 담고 있습니다.

어댑터는 PDF 경로를 대상으로 외부 프로세스를 시작합니다. PDF를 신뢰할 수 없는 입력으로 취급하십시오. 제한된 환경에서 검증을 실행하십시오. 외부 검증기는 적대적인 데이터를 파싱합니다. 의도하지 않은 파일로 이어지는 경로 순회를 방지하려면, 파일 경로를 핸들러에 전달하기 전에 검증하고 정규화하십시오. 검증되지 않은 사용자 입력을 명령 인수로 전달하지 마십시오. 어댑터는 셸 문자열이 아니라 프로세스 인수를 구성합니다. 입력 파일 자체는 여전히 공격자가 제어합니다. 엔진의 위협 모델은 /modules/core/security/를 참조하십시오.

이 모듈은 자체적으로 어떤 PDF 사양에 대해서도 규범적 주장을 하지 않습니다. 이 모듈은 참조 검증기(PDF/A 및 PDF/UA에 대한 veraPDF, ISO 32000-2 구조 규칙에 대한 Arlington PDF 모델)에 위임함으로써 적합성 검증을 오케스트레이션합니다. 권위 있는 적합성 판정은 외부 도구의 것입니다. 이 모듈은 이를 정규화하고 보고합니다. 엔드 투 엔드 적합성과 골든 베이스라인은 /modules/core/conformance/에 설명되어 있습니다.