跳转到内容

Cli:命令处理器和外部验证器适配器

Cli 模块是引擎诊断和符合性工具背后的命令接口。它包含一组命令处理器——benchmark、diff、init、verify、capabilities。同时,它也提供一组适配器,在统一接口后封装外部 PDF 验证器(veraPDF、Arlington PDF model)。单个 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,并返回一个 ComplianceValidationResultisAvailable() 报告后端工具是否已安装。toolIdentifier() 为该工具命名。VeraPdfCliAdapterArlingtonValidatorAdapterAsyncValidatorAdapter 都实现了该接口。这意味着引擎不会重新实现第三方验证器,而是执行参考工具并将其判定结果规范化。尚未安装的验证器会报告 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 CLI(@since 3.0.0
ArlingtonValidatorAdapter实现此适配器包装 Arlington PDF model(@since 3.0.0
AsyncValidatorAdapter实现此适配器支持异步的验证器包装(@since 3.0.0
CliOutputwrite()writeln()error()可供测试的 stdout/stderr 写入器(@since 2.3.0
BinaryFinder外部工具路径解析定位主机工具(@since 2.5.0

运行 composer docs:generate-api-php -- --module=Cli 可获取完整的 PHPDoc 表格。

来源: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 的作用就是重叠这段延迟。1500 ms 挂钟时间 / 64 MB 峰值的 performance_budget 是引擎参考值,并非对外部验证器的限制。基准测试输出在结构上具有确定性,但按其性质本身就包含计时数据。

这些适配器会针对一个 PDF 路径启动外部进程。请将该 PDF 视为不受信任的输入。请在受限环境中执行验证。这些外部验证器会解析恶意数据。在将任何文件路径传给处理器之前,请先验证并规范化它,以避免路径遍历到非预期文件。请勿将未经净化的用户输入作为命令参数传入。这些适配器构建的是进程参数,而非 shell 字符串。输入文件本身仍由攻击者控制。请参阅 /modules/core/security/ 中的引擎威胁模型。

本模块本身不主张任何 PDF 规格层面的规范性声明。它通过委派给参考验证器(由 veraPDF 处理 PDF/A 与 PDF/UA,由 Arlington PDF model 处理 ISO 32000-2 结构规则)来协调符合性验证。权威的符合性判定来自外部工具。本模块负责将其规范化并报告。端到端符合性与黄金基准描述于 /modules/core/conformance/ 中。