Pro édition
Writer — Référence détaillée
En un coup d’œil
Section intitulée « En un coup d’œil »Le module Writer écrit des révisions PDF par mise à jour incrémentale et regroupe les petits objets dans des Object Streams. Le writer incrémental applique une règle d’ajout seul en fail-closed : chaque octet que le tampon contenait avant une révision doit rester inchangé après celle-ci. Le constructeur d’Object Stream regroupe les objets éligibles dans un seul objet /Type /ObjStm compressé en FlateDecode, sous une taille bornée.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette capacité est fournie dans NextPDF Pro (nextpdf/pro) et s’active avec une enveloppe de licence de niveau Pro. Un déploiement sans ce droit ne charge pas les classes de la capacité. Compare les éditions et obtiens une licence. Il n’existe pas d’indicateur de licence par fonctionnalité ; le code est livré avec l’édition Pro.
Surface de l’API publique
Section intitulée « Surface de l’API publique »Le module réside dans l’espace de noms NextPDF\Pro\Writer. Tous les symboles publics sont listés ci-dessous. Les objets valeur sont des classes final readonly immuables.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
IncrementalUpdateWriter::writeRevision | BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId | Statique. Réécrit le catalogue avec les entrées fusionnées, ajoute une table de références croisées traditionnelle pour les objets nouveaux et modifiés, et écrit un trailer avec /Size, /Root, /Prev et /ID. Vérifie ensuite que le préfixe d’avant la révision est identique octet pour octet. | int — décalage en octets de la nouvelle table de références croisées | \NextPDF\Exception\WriterException lorsque la vérification du préfixe en ajout seul échoue ; getWriterState() renvoie dss-append-only-invariant | Point d’entrée statique. Aucune sortie exploitable en cas de violation. |
ObjectStreamWriter::addObject | int $objectNumber, string $content | Ajoute un objet au flux en attente après une vérification de taille. | void | OverflowException lorsque l’index combiné plus le corps dépasseraient 65,536 octets | $content exclut les encadrants N 0 obj / endobj. |
ObjectStreamWriter::canAccept | string $content | Estime le surcoût d’index et teste le total courant par rapport au maximum. | bool | Ne lève pas d’exception | Prédicat pur ; aucun changement d’état. |
ObjectStreamWriter::build | aucun | Construit l’index, concatène les corps, compresse avec FlateDecode et encapsule le dictionnaire /Type /ObjStm. | string — contenu brut de l’Object Stream | ObjectStreamWriteException lorsqu’aucun objet n’a été ajouté, ou en cas d’échec de compression zlib | L’appelant attribue le numéro d’objet et ajoute les marqueurs. |
ObjectStreamWriter::getEntries | aucun | Recalcule les décalages relatifs au corps pour les objets accumulés. | list<ObjectStreamEntry> | Ne lève pas d’exception | Les décalages sont relatifs à la section du corps. |
ObjectStreamWriter::count | aucun | Indique le nombre d’objets accumulés. | int | Ne lève pas d’exception | — |
ObjStmCompressor::__construct | int $maxStreamSize = 65536, int $maxObjectsPerStream = 200 | Stocke les limites de taille et de nombre d’objets utilisées pour le regroupement. | — | Ne lève pas d’exception | Les valeurs par défaut correspondent au réglage Object Stream du module. |
ObjStmCompressor::groupObjects | list<array{number: int, generation?: int, content: string}> $objects | Filtre les objets non éligibles, puis regroupe le reste dans des writers en respectant les limites de taille et de nombre. | list<ObjectStreamWriter> | Ne lève pas d’exception ; les objets non éligibles sont ignorés | Les objets de génération non nulle passent à la sérialisation normale. |
ObjStmCompressor::isEligible | string $content, int $generation = 0 | Rejette les objets flux, /Encrypt, /XRef, /Catalog et toute génération non nulle. | bool | Ne lève pas d’exception | La correspondance /Type tolère les espaces et les échappements #xx. |
ObjStmCompressor::writeToBuffer | list<ObjectStreamWriter> $streams, BinaryBuffer $buffer, ObjectRegistry $registry | Alloue un objet porteur par flux, enregistre les entrées compressées de type 2 et écrit chaque bloc ObjStm. | list<int> — numéros des objets porteurs | Propage ObjectStreamWriteException depuis build() en cas d’échec rare de compression | À exécuter après l’écriture des objets non éligibles et avant l’émission des références croisées. |
ObjStmCompressor::estimateSavings | list<ObjectStreamWriter> $streams, int $originalSize | Construit chaque flux pour mesurer la taille compressée par rapport à l’originale. | ObjStmCompressionResult | Propage ObjectStreamWriteException depuis build() en cas d’échec rare de compression | Utilitaire de mesure en lecture seule. |
ObjectStreamEntry::__construct | int $objectNumber, string $content, int $offset | Enregistrement immuable d’un objet regroupé et de son décalage dans le corps. | — | Ne lève pas d’exception | final readonly ; propriétés publiques. |
ObjStmCompressionResult::__construct | int $originalObjectCount, int $streamCount, int $estimatedOriginalSize, int $estimatedCompressedSize | Conteneur de métriques immuable. | — | Ne lève pas d’exception | final readonly ; propriétés publiques. |
ObjStmCompressionResult::savedBytes | aucun | Renvoie la taille originale moins la taille compressée. | int | Ne lève pas d’exception | Peut être négatif lorsque le regroupement a augmenté la taille des données. |
ObjStmCompressionResult::savedPercent | aucun | Renvoie la réduction en pourcentage. | float | Ne lève pas d’exception | Renvoie 0.0 lorsque la taille originale est nulle. |
ObjStmCompressionResult::compressionRatio | aucun | Renvoie la taille compressée divisée par l’originale. | float | Ne lève pas d’exception | Renvoie 1.0 lorsque la taille originale est nulle. |
ObjectStreamWriteException | — | Signale un échec de construction d’Object Stream. | — | Étend RuntimeException | Levée par build() ; interceptable via RuntimeException pour la rétrocompatibilité. |
Signatures des points d’entrée
Section intitulée « Signatures des points d’entrée »final class IncrementalUpdateWriter{ public static function writeRevision( BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId, ): int;}final class ObjectStreamWriter{ public function addObject(int $objectNumber, string $content): void; public function canAccept(string $content): bool; public function build(): string; /** @return list<ObjectStreamEntry> */ public function getEntries(): array; public function count(): int;}final class ObjStmCompressor{ public function __construct( int $maxStreamSize = 65536, int $maxObjectsPerStream = 200, );
/** * @param list<array{number: int, generation?: int, content: string}> $objects * @return list<ObjectStreamWriter> */ public function groupObjects(array $objects): array;
public function isEligible(string $content, int $generation = 0): bool;
/** * @param list<ObjectStreamWriter> $streams * @return list<int> */ public function writeToBuffer(array $streams, BinaryBuffer $buffer, ObjectRegistry $registry): array;
/** @param list<ObjectStreamWriter> $streams */ public function estimateSavings(array $streams, int $originalSize): ObjStmCompressionResult;}Contrat de comportement
Section intitulée « Contrat de comportement »writeRevision écrit une révision par mise à jour incrémentale. Il prend un instantané du préfixe existant du tampon avant l’écriture. Il réécrit le catalogue avec les entrées fusionnées, enregistre les décalages des nouveaux objets, écrit une table de références croisées traditionnelle regroupée en sous-sections contiguës, et écrit un trailer avec /Size, /Root, /Prev et /ID. Après l’écriture, il compare de nouveau le préfixe. Si un octet antérieur a changé, il lève WriterException portant l’état de violation d’ajout seul et ne renvoie aucune sortie exploitable. En cas de succès, il renvoie le décalage en octets de la nouvelle table de références croisées pour enchaîner d’autres révisions. Le mélange de tables et de flux de références croisées d’une révision à l’autre est autorisé.
ObjectStreamWriter accumule des objets. addObject lève une erreur de dépassement lorsque l’index combiné et le corps dépasseraient le maximum de 65,536 octets non compressés. build lève une erreur sur un flux vide ; sinon, il compresse l’index plus le corps et renvoie le contenu de l’Object Stream avec les entrées /Type /ObjStm, /N, /First, /Length et /Filter /FlateDecode. L’appelant attribue le numéro d’objet et ajoute les marqueurs N 0 obj / endobj.
ObjStmCompressor décide quels objets regrouper. Il exclut les objets flux, les dictionnaires de chiffrement, les flux de références croisées, le catalogue du document et tout objet dont le numéro de génération est non nul. writeToBuffer alloue un objet porteur par flux, enregistre chaque objet regroupé comme une entrée de références croisées compressée de type 2, et écrit le bloc ObjStm au décalage courant du tampon. estimateSavings construit chaque flux pour calculer les métriques de taille sans modifier le tampon.
Cas limites et modes de défaillance
Section intitulée « Cas limites et modes de défaillance »- La vérification d’ajout seul copie le préfixe existant. Son coût croît avec la taille du document déjà écrit. Ce coût est intentionnel et protège les octets signés.
- La limite de l’Object Stream s’applique à l’index plus le corps non compressés. Place le dictionnaire de chiffrement et les autres types d’objets exclus en tant qu’objets indirects directs.
- L’exclusion
/Typetolère les espaces arbitraires entre jetons et l’échappement hexadécimal#xx. Des formes telles que/Type /Encrypt,/Type\n/Encryptet/Type /#45ncryptsont toutes rejetées, pas seulement l’orthographe littérale canonique. - Tout objet portant un numéro de génération non nul est considéré comme non éligible et passe à la sérialisation normale
N G obj … endobj, car la génération d’un objet compressé est implicitement nulle. writeToBufferdoit s’exécuter après l’écriture de tous les objets non éligibles et avant l’émission des références croisées. Les objets regroupés ne doivent pas être aussi sérialisés séparément.
Comportement en mode FIPS
Section intitulée « Comportement en mode FIPS »Le module Writer n’effectue aucune opération cryptographique. Il protège les octets signés en refusant d’émettre lorsqu’un octet antérieur changerait, ce qui est un test d’égalité octet pour octet plutôt qu’un test cryptographique. La sélection des algorithmes FIPS pour la signature et le hachage est régie par le module de signature, et non par ce writer. Activer ou désactiver le mode FIPS ne change le comportement d’aucune méthode de Writer.
Conformité
Section intitulée « Conformité »NextPDF implémente le module conformément à ISO 32000-2:2020. Le writer incrémental suit la grammaire de mise à jour incrémentale du §7.5.6 : chaque révision ajoute une section de références croisées couvrant uniquement les objets nouveaux, modifiés ou supprimés, et un trailer dont l’entrée /Prev donne le décalage des références croisées précédentes. Le constructeur d’Object Stream suit le modèle d’object stream du §7.5.7 : un index de paires numéro d’objet / décalage, dont les décalages sont mesurés à partir de l’entrée /First par ordre croissant, précède les corps des objets regroupés. Les deux références de clause ont été vérifiées par rapport au corpus ISO 32000-2:2020. L’enchaînement des révisions pour les workflows PAdES B-LT et B-LTA suit ETSI EN 319 142-1 §5.4, comme annoté dans le code source. La prise en charge d’une clause est une déclaration de capacité d’ingénierie, pas une certification ; NextPDF ne détient aucune certification de conformité formelle.
Notes de développement
Section intitulée « Notes de développement »- Installe le paquet avec
composer require nextpdf/pro:^3. Les classes se résolvent sousNextPDF\Pro\Writer. IncrementalUpdateWriter::writeRevisionest un point d’entrée statique ; il ne conserve aucun état d’instance entre les révisions.ObjectStreamEntry,ObjStmCompressionResult,IncrementalUpdateWriteret le compresseur forment ensemble la surface publique du module ; le dépôt ne fournit aucun exemple exécutable pour celui-ci.- Une
WriterExceptionprovenant dewriteRevisionindique une violation d’ajout seul. Traite-la comme un échec bloquant et abandonne le tampon. - Les objets porteurs d’Object Stream sont des objets indirects ; l’appelant attribue leurs numéros d’objet via le registre.
Limite de publication
Section intitulée « Limite de publication »Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins d’espaces de noms internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sont hors périmètre.