Aller au contenu

Cli : gestionnaires de commandes et adaptateurs pour validateurs externes

Le module Cli fournit l’interface de commande utilisée par les outils de diagnostic et de conformité du moteur. Il regroupe des gestionnaires de commandes — benchmark, diff, init, verify, capabilities — ainsi que des adaptateurs qui encapsulent des validateurs PDF externes (veraPDF, le modèle Arlington PDF) derrière une interface unique. Une seule commande verify peut piloter n’importe lequel de ces validateurs.

Fenêtre de terminal
composer require nextpdf/core:^3

Chaque commande est portée par une classe gestionnaire dotée d’une méthode execute() qui renvoie un code de sortie de processus. BenchmarkHandler exécute les scénarios de benchmark. DiffHandler compare des documents. InitHandler échafaude un projet. VerifyHandler exécute la vérification de conformité. CapabilitiesHandler indique ce que le runtime prend en charge. CliOutput est la fine abstraction d’écriture stdout/stderr partagée par les gestionnaires, ce qui garde la sortie testable plutôt que couplée à des variables globales. BinaryFinder résout le chemin d’un outil externe sur l’hôte (@since 2.5.0).

La surface de validation constitue le point d’architecture central. AlternateValidatorAdapter est l’interface qu’implémente un validateur externe. validate() reçoit un chemin de PDF et un ComplianceFlavour, puis renvoie un ComplianceValidationResult. isAvailable() indique si l’outil sous-jacent est installé. toolIdentifier() renvoie son nom. VeraPdfCliAdapter, ArlingtonValidatorAdapter et AsyncValidatorAdapter l’implémentent. Cela signifie que le moteur ne réimplémente pas les validateurs tiers : il exécute les outils de référence et normalise leur verdict. Un validateur qui n’est pas installé renvoie isAvailable() === false au lieu de faire échouer l’exécution, de sorte que la vérification signale explicitement cette dégradation. Les adaptateurs sont @since 3.0.0 ; les gestionnaires du cœur sont @since 2.3.0@since 2.5.0.

ClasseMembres clésRôle
BenchmarkHandlerexecute(string $format = 'pretty', ?string $scenario = null): intExécute les scénarios de benchmark (@since 2.4.0)
VerifyHandlerexecute(): intPilote la vérification de conformité
DiffHandler / InitHandlerexecute(): intDiff de document / échafaudage de projet
CapabilitiesHandlerexecute(string $format = 'pretty'): intIndique les capacités du runtime (@since 2.3.0)
AlternateValidatorAdapter (interface)validate(), isAvailable(), toolIdentifier()Contrat de validateur externe (@since 3.0.0)
VeraPdfCliAdapterimplémente l’adaptateurEncapsule la CLI veraPDF (@since 3.0.0)
ArlingtonValidatorAdapterimplémente l’adaptateurEncapsule le modèle Arlington PDF (@since 3.0.0)
AsyncValidatorAdapterimplémente l’adaptateurWrapper de validateur capable de fonctionner de façon asynchrone (@since 3.0.0)
CliOutputwrite(), writeln(), error()Abstraction stdout/stderr testable (@since 2.3.0)
BinaryFinderrésolution de chemin d’outil externeLocalise les outils sur l’hôte (@since 2.5.0)

Exécute composer docs:generate-api-php -- --module=Cli pour obtenir le tableau PHPDoc complet.

Source : examples/33-validate-conformance.php. Sélectionne un adaptateur de validateur et vérifie sa disponibilité avant usage :

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

Exécute la vérification avec les validateurs disponibles, en traitant un outil absent comme une vérification ignorée plutôt que comme un échec.

<?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;
}
}
  • Un validateur indisponible renvoie isAvailable() === false. Il ne lève pas d’exception. « Aucun validateur disponible » n’est pas une réussite — traite ce cas à part, comme le fait l’exemple de production.
  • Les adaptateurs exécutent des binaires externes. Leur verdict est celui de l’outil externe, normalisé — pas une réimplémentation indépendante. Garde les outils à jour.
  • La méthode execute() d’un gestionnaire renvoie un code de sortie de processus. Un code non nul indique un échec. Propage-le depuis ton wrapper plutôt que de l’ignorer.
  • BinaryFinder résout le chemin d’un outil sur l’hôte. Un hôte différent peut résoudre une version d’outil différente. Fige l’environnement pour une vérification reproductible.
  • Le profil de reproductibilité est structural : un rapport de vérification inclut des horodatages et des versions d’outils, de sorte que deux exécutions diffèrent sur ces champs.

La surcharge des gestionnaires est négligeable. Le coût est dominé par le processus du validateur externe, qui peut être lent sur un document volumineux. AsyncValidatorAdapter sert à masquer cette latence. Le performance_budget de 1500 ms wall / 64 Mo de pic est la référence du moteur, pas une limite imposée à un validateur externe. La sortie du benchmark est déterministe dans sa structure, mais contient par nature des données de chronométrage.

Les adaptateurs lancent des processus externes à partir d’un chemin de PDF. Traite le PDF comme une entrée non fiable. Exécute la vérification dans un environnement contraint. Les validateurs externes analysent des données hostiles. Valide et canonicalise tout chemin de fichier avant de le passer à un gestionnaire, afin d’éviter une traversée de chemin vers un fichier inattendu. Ne passe pas d’entrée utilisateur non assainie comme arguments de commande. Les adaptateurs construisent des arguments de processus, pas des chaînes shell. Le fichier d’entrée lui-même reste contrôlé par l’attaquant. Consulte le modèle de menace du moteur dans /modules/core/security/.

Ce module ne formule aucune revendication normative propre relative à la spécification PDF. Il orchestre la vérification de conformité en déléguant à des validateurs de référence (veraPDF pour PDF/A et PDF/UA, le modèle Arlington PDF pour les règles structurelles ISO 32000-2). Le verdict de conformité faisant autorité est celui de l’outil externe. Ce module le normalise et le restitue. La conformité de bout en bout et les baselines de référence sont décrites dans /modules/core/conformance/.