Zum Inhalt springen

Cli: Befehls-Handler und Adapter für externe Validatoren

Das Cli-Modul ist die Befehlsoberfläche hinter den Diagnose- und Konformitätswerkzeugen der Engine. Es besteht aus einer Reihe von Befehls-Handlern — benchmark, diff, init, verify, capabilities. Außerdem umfasst es Adapter, die externe PDF-Validatoren (veraPDF, das Arlington PDF Model) hinter einer einzigen Schnittstelle kapseln. Ein einziger verify-Befehl kann jeden von ihnen ansteuern.

Terminal-Fenster
composer require nextpdf/core:^3

Jeder Befehl ist eine Handler-Klasse mit einer execute()-Methode, die einen Prozess-Exit-Code zurückgibt. BenchmarkHandler führt die Benchmark-Szenarien aus. DiffHandler vergleicht Dokumente. InitHandler erstellt das Grundgerüst eines Projekts. VerifyHandler führt die Konformitätsprüfung durch. CapabilitiesHandler meldet, was die Laufzeitumgebung unterstützt. CliOutput ist der schlanke stdout/stderr-Writer, den sich die Handler teilen, sodass die Ausgabe testbar bleibt und nicht an Globals gekoppelt ist. BinaryFinder löst den Pfad zu einem externen Werkzeug auf dem Host auf (@since 2.5.0).

Die Validierungsoberfläche ist der architektonische Kernpunkt. AlternateValidatorAdapter ist die Schnittstelle, die ein externer Validator implementiert. validate() nimmt einen PDF-Pfad und ein ComplianceFlavour entgegen und gibt ein ComplianceValidationResult zurück. isAvailable() meldet, ob das zugrunde liegende Werkzeug installiert ist. toolIdentifier() benennt es. VeraPdfCliAdapter, ArlingtonValidatorAdapter und AsyncValidatorAdapter implementieren diese Schnittstelle. Das bedeutet, dass die Engine Drittanbieter-Validatoren nicht neu implementiert. Sie führt die Referenzwerkzeuge aus und normalisiert deren Verdikt. Ist ein Validator nicht installiert, meldet er isAvailable() === false, statt den Lauf scheitern zu lassen, sodass die Prüfung explizit herabgestuft wird. Die Adapter sind @since 3.0.0; die Core-Handler sind @since 2.3.0@since 2.5.0.

KlasseWichtige MemberRolle
BenchmarkHandlerexecute(string $format = 'pretty', ?string $scenario = null): intFührt Benchmark-Szenarien aus (@since 2.4.0)
VerifyHandlerexecute(): intSteuert die Konformitätsprüfung
DiffHandler / InitHandlerexecute(): intDokument-Diff / Projekt-Grundgerüst
CapabilitiesHandlerexecute(string $format = 'pretty'): intMeldet Laufzeit-Fähigkeiten (@since 2.3.0)
AlternateValidatorAdapter (Schnittstelle)validate(), isAvailable(), toolIdentifier()Vertrag für externe Validatoren (@since 3.0.0)
VeraPdfCliAdapterimplementiert den AdapterKapselt die veraPDF-CLI (@since 3.0.0)
ArlingtonValidatorAdapterimplementiert den AdapterKapselt das Arlington PDF Model (@since 3.0.0)
AsyncValidatorAdapterimplementiert den AdapterAsync-fähiger Validator-Wrapper (@since 3.0.0)
CliOutputwrite(), writeln(), error()Testbarer stdout/stderr-Writer (@since 2.3.0)
BinaryFinderPfadauflösung für externe WerkzeugeLokalisiert Host-Werkzeuge (@since 2.5.0)

Führen Sie composer docs:generate-api-php -- --module=Cli aus, um die vollständige PHPDoc-Tabelle zu erhalten.

Quelle: examples/33-validate-conformance.php. Auswahl eines Validator-Adapters und Prüfung der Verfügbarkeit vor der Verwendung:

<?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";

Führen Sie die Prüfung genau mit den Validatoren aus, die vorhanden sind, und behandeln Sie ein fehlendes Werkzeug als übersprungene Prüfung statt als Fehlschlag.

<?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;
}
}
  • Ein nicht verfügbarer Validator gibt isAvailable() === false zurück. Er wirft keine Ausnahme. „Kein Validator verfügbar“ gilt nicht als bestanden — behandeln Sie diesen Fall eigenständig, so wie es das Produktionsbeispiel tut.
  • Die Adapter führen externe Binärdateien aus. Ihr Verdikt ist das normalisierte Verdikt des externen Werkzeugs — keine eigenständige Neuimplementierung. Halten Sie die Werkzeuge aktuell.
  • Die Methode execute() eines Handlers gibt einen Prozess-Exit-Code zurück. Ein Wert ungleich null ist ein Fehlschlag. Geben Sie ihn aus Ihrem Wrapper weiter, statt ihn zu verwerfen.
  • BinaryFinder löst einen Werkzeugpfad auf dem Host auf. Ein anderer Host kann eine andere Werkzeugversion auflösen. Fixieren Sie die Umgebung für reproduzierbare Prüfungen.
  • Das Reproduzierbarkeitsprofil ist structural: Ein Prüfbericht enthält Zeitstempel und Werkzeugversionen, sodass sich zwei Läufe in diesen Feldern unterscheiden.

Der Overhead der Handler ist vernachlässigbar. Der Aufwand wird vom Prozess des externen Validators dominiert, der bei einem großen Dokument langsam sein kann. AsyncValidatorAdapter existiert, um diese Latenz zu überdecken. Das performance_budget von 1500 ms Wall-Zeit / 64 MB Spitze ist die Engine-Referenz, keine Schranke für einen externen Validator. Die Benchmark-Ausgabe ist strukturell deterministisch, enthält aber naturgemäß Zeitmessdaten.

Die Adapter starten externe Prozesse für einen PDF-Pfad. Behandeln Sie die PDF-Datei als nicht vertrauenswürdige Eingabe. Führen Sie die Prüfung in einer eingeschränkten Umgebung aus. Die externen Validatoren parsen bösartige Daten. Validieren und kanonisieren Sie jeden Dateipfad, bevor Sie ihn an einen Handler übergeben, damit Path-Traversal nicht zu einer unbeabsichtigten Datei führt. Übergeben Sie keine nicht bereinigte Benutzereingabe als Befehlsargumente. Die Adapter erzeugen Prozessargumente, keine Shell-Strings. Die Eingabedatei selbst ist nach wie vor angreiferkontrolliert. Siehe das Bedrohungsmodell der Engine in /modules/core/security/.

Dieses Modul stellt keine eigenen normativen Aussagen zur PDF-Spezifikation auf. Es orchestriert die Konformitätsprüfung, indem es an Referenzvalidatoren delegiert (veraPDF für PDF/A und PDF/UA, das Arlington PDF Model für die strukturellen Regeln von ISO 32000-2). Das maßgebliche Konformitätsverdikt ist das des externen Werkzeugs. Dieses Modul normalisiert und meldet es. End-to-End-Konformität und die Golden-Baselines sind in /modules/core/conformance/ beschrieben.