Перейти к содержимому

CLI: обработчики команд и адаптеры внешних валидаторов

Модуль командной строки (CLI) предоставляет набор команд движка для диагностики и проверки соответствия. В него входят обработчики команд benchmark, diff, init, verify и capabilities, а также адаптеры, которые объединяют под одним интерфейсом внешние валидаторы Portable Document Format (PDF), включая veraPDF и модель Arlington PDF. Команда verify может запускать любой из этих адаптеров.

Окно терминала
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Сравнение документов / каркас проекта
CapabilitiesHandlerexecute(string $format = 'pretty'): intСообщает о возможностях среды выполнения (@since 2.3.0)
AlternateValidatorAdapter (интерфейс)validate(), isAvailable(), toolIdentifier()Контракт внешнего валидатора (@since 3.0.0)
VeraPdfCliAdapterреализует адаптерОборачивает интерфейс командной строки veraPDF (@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() возвращает код завершения процесса. Ненулевой код означает сбой. Передавайте его из своей обёртки дальше, а не отбрасывайте.
  • BinaryFinder определяет путь к инструменту на хосте. На другом хосте может найтись другая версия инструмента. Зафиксируйте окружение для воспроизводимой проверки.
  • Профиль воспроизводимости — structural: отчёты о проверке включают временны́е метки и версии инструментов, поэтому эти поля различаются между запусками.

Накладные расходы обработчика пренебрежимо малы. Основная нагрузка приходится на процессы внешних валидаторов, а обработка больших документов может быть медленной. AsyncValidatorAdapter позволяет совмещать эту задержку с другими операциями. Значение performance_budget в 1500 мс времени / 64 МБ пикового потребления — это ориентир для движка, а не ограничение для внешнего валидатора. Вывод теста производительности имеет детерминированную структуру, но неизбежно включает данные о времени.

Адаптеры запускают внешние процессы с путём к PDF. Рассматривайте PDF как недоверенные входные данные и запускайте проверку в ограниченном окружении. Внешние валидаторы разбирают враждебные данные. Проверяйте и приводите к каноническому виду любой путь к файлу перед передачей обработчику, чтобы обход каталогов не давал доступ к непредусмотренному файлу. Не передавайте неочищенный пользовательский ввод в качестве аргументов команды. Адаптеры формируют аргументы процесса, а не строки оболочки. Сам входной файл остаётся под контролем злоумышленника. См. модель угроз движка в /modules/core/security/.

Этот модуль не формулирует собственных нормативных заявлений о спецификации PDF. Он координирует проверку соответствия, делегируя её эталонным валидаторам: veraPDF для PDF/A и PDF/UA, а также модели Arlington PDF для структурных правил ISO 32000-2. Внешний инструмент выдаёт авторитетный вердикт о соответствии. Модуль нормализует этот вердикт и сообщает о нём. Сквозное соответствие и эталонные базовые наборы описаны в /modules/core/conformance/.