Aller au contenu
getnextpdf.com

Pro édition

Merge — Référence détaillée

Cette page est la référence au niveau du contrat pour le module NextPDF Pro Merge, NextPDF\Pro\Merge. SmartMerger assemble plusieurs documents d’entrée en un seul et applique les améliorations Pro : un arbre de signets consolidé à partir des libellés de chaque entrée, une déduplication au niveau du document entier, une sélection de plages de pages par entrée et la détection des liens internes. SemanticSplitter est le point d’entrée compagnon de découpe soucieux de la structure. Cette page énonce l’API publique, le contrat de comportement observable, les bornes de ressources et les modes d’échec. La mise en place orientée tâches et les exemples se trouvent sur la page de capacité Merge.

Cette capacité est livrée 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.

Aucun indicateur de capacité au runtime ne verrouille ce module. Les classes Merge sont utilisables dès que nextpdf/pro est installé et sous licence.

SymboleParamètresComportement par défautRetourneLève ou échoue avecNotes
SmartMerger::__construct()?PdfMerger $coreMerger = null, ?PdfSplitter $splitter = nullAccepte et ignore le merger Core hérité ; un splitter null construit le splitter Pro par défaut$coreMerger conservé uniquement pour une construction rétrocompatible
SmartMerger::merge()list<MergeInput> $inputs, SmartMergeConfig $config = new SmartMergeConfig()Réduit les plages de pages, déduplique les entrées entières, délègue l’assemblage de base, puis injecte les signets et compte les liens selon la configurationSmartMergeResultInvalidArgumentException sur une liste d’entrées vide ; OverflowException lorsque le nombre d’entrées dépasse maxInputs ou qu’une entrée dépasse maxBytesPerInputUnique point d’entrée de fusion
MergeInput::__construct()string $pdfData, list<PageRange> $pageRanges = [], string $label = ''Objet-valeur ; un $pageRanges vide sélectionne toutes les pagesReadonly
MergeInput::hasPageRanges()Vrai lorsque l’entrée porte au moins une plage de pagesbool
SmartMergeConfig::__construct()bool $consolidateBookmarks = true, bool $deduplicatePages = false, bool $rewriteLinks = true, int $maxInputs = 100, int $maxBytesPerInput = 100_000_000Objet-valeur portant les bascules d’amélioration et les bornes de ressourcesReadonly ; la déduplication est en opt-in
SmartMergeConfig::default()Signets et analyse de liens activés, déduplication désactivéeselfFabrique statique
SmartMergeConfig::basic()Toutes les améliorations désactivées ; concaténation de base uniquementselfFabrique statique
SmartMergeResult::__construct()string $pdfData, int $totalPages, int $sourceCount, int $mergedSize, int $bookmarksAdded = 0, int $duplicatesRemoved = 0, int $linksRewritten = 0, list<string> $inputLabels = []Porteur readonly des octets fusionnés et des statistiques de consolidationReadonly
SmartMergeResult::isValid()Vrai lorsque la sortie commence par l’en-tête %PDFboolVérification de l’en-tête uniquement
SmartMergeResult::hasOptimizations()Vrai lorsqu’au moins un doublon a été supprimé ou au moins un lien comptébool
SemanticSplitter::__construct()?PdfSplitter $splitter = nullUn argument null construit le splitter Pro par défautInjection par constructeur pour les tests
SemanticSplitter::splitByStructure()string $pdfData, float $headingFontThreshold = 14.0Détecte les opérateurs Tf de taille de titre comme débuts de section et découpe à ces frontières ; l’absence de structure détectée retourne une seule section couvrant tout le documentSplitResultInvalidArgumentException lorsque le tampon est vide ou dépourvu de l’en-tête %PDF ; OverflowException lorsque l’entrée dépasse 100 MBSe replie sur la découpe par plages de pages de Core
public function __construct(
?PdfMerger $coreMerger = null,
?PdfSplitter $splitter = null,
)
public function merge(
array $inputs,
SmartMergeConfig $config = new SmartMergeConfig(),
): SmartMergeResult
public function __construct(
public string $pdfData,
public array $pageRanges = [],
public string $label = '',
)
public function hasPageRanges(): bool
public function __construct(
public bool $consolidateBookmarks = true,
public bool $deduplicatePages = false,
public bool $rewriteLinks = true,
public int $maxInputs = 100,
public int $maxBytesPerInput = 100_000_000,
)
public static function default(): self
public static function basic(): self
public function isValid(): bool
public function hasOptimizations(): bool
public function __construct(?PdfSplitter $splitter = null)
public function splitByStructure(
string $pdfData,
float $headingFontThreshold = 14.0,
): SplitResult

SmartMerger::merge() exécute un pipeline fixe, observé de l’extérieur comme suit.

  1. Une liste d’entrées vide lève InvalidArgumentException. Le nombre d’entrées est ensuite borné par maxInputs ; un dépassement lève OverflowException.
  2. Chaque entrée est contrôlée en taille par rapport à maxBytesPerInput avant usage. Lorsque l’entrée déclare des plages de pages, elle est d’abord réduite aux pages sélectionnées via le splitter Pro, puis ne contribue que ces pages.
  3. Lorsque deduplicatePages est activé, la chaîne d’octets complète de chaque document d’entrée est empreintée avec la fonction non cryptographique xxh128. Une entrée dont les octets correspondent exactement à une entrée précédente est écartée. La déduplication porte sur le document entier et est exacte à l’octet près.
  4. L’assemblage de base délègue au moteur Pro PdfSplitter::mergeDocuments(), qui renumérote chaque entrée dans un espace d’objets unique et contigu et émet une véritable table de références croisées.
  5. La consolidation des signets est appliquée lorsque consolidateBookmarks est activé et qu’au moins une entrée porte un libellé non vide. Un dictionnaire /Outlines minimal est inséré, lié depuis le catalogue du document, avec une entrée d’outline par entrée dans l’ordre de fusion.
  6. Lorsque rewriteLinks est activé, la sortie fusionnée est analysée à la recherche d’actions /S /GoTo et leur nombre est rapporté.

SmartMergeResult rapporte les octets fusionnés ainsi que des statistiques. totalPages provient de la fusion de base. sourceCount est le nombre d’entrées d’origine, pris avant la déduplication. mergedSize est la longueur en octets de la sortie. bookmarksAdded ne compte que les entrées ayant fourni un libellé non vide. duplicatesRemoved compte les entrées entières écartées. linksRewritten est le nombre de GoTo détectés. inputLabels liste les libellés résolus dans l’ordre de fusion. isValid() vérifie l’en-tête %PDF ; hasOptimizations() est vrai lorsqu’un doublon a été supprimé ou un lien compté.

Chaque entrée d’outline porte le libellé de l’entrée comme /Title, échappé en chaîne littérale PDF conformément à ISO 32000-2:2020 §7.3.4.2. Le reverse solidus est d’abord doublé, les parenthèses sont échappées, les octets de contrôle nommés utilisent leurs séquences définies, et tout octet non imprimable restant devient un échappement octal à trois chiffres. Un libellé hostile ne peut donc pas désynchroniser le délimiteur de chaîne littérale ni injecter de structure d’objet. Les entrées dont le libellé est vide reçoivent un titre de remplacement Document N, indexé à partir de un.

Le PdfMerger::merge() Core hérité est un stub délibérément fail-closed dans cette version ; il n’est jamais invoqué par SmartMerger. La fusion de base passe plutôt par Pro PdfSplitter::mergeDocuments(), de sorte que le fichier fusionné porte une table de références croisées exacte à l’octet près, avec une entrée par objet indirect conformément à ISO 32000-2:2020 §7.5.4. Le déterminisme suit le profil documenté du splitter Pro : des entrées et une configuration identiques produisent un flux d’octets stable.

SemanticSplitter::splitByStructure() analyse les flux de contenu des pages à la recherche d’opérateurs Tf de définition de police dont la taille atteint ou dépasse headingFontThreshold (par défaut 14.0) et traite chacune de ces pages comme un début de section. Les frontières sont converties en plages de pages et déléguées à Pro PdfSplitter::split(). Lorsqu’aucune frontière n’est détectée, tout le document est retourné comme une section unique. L’entrée doit commencer par %PDF et rester dans la borne de 100 MB.

  • Une liste d’entrées vide échoue avec InvalidArgumentException avant tout assemblage.
  • Un nombre d’entrées au-dessus de maxInputs (par défaut 100), ou toute entrée au-dessus de maxBytesPerInput (par défaut 100 MB), échoue avec OverflowException. Les deux bornes sont des rejets fail-closed délibérés, pas des erreurs transitoires.
  • La déduplication porte sur le document entier et est exacte à l’octet près. Deux entrées qui s’affichent de façon identique mais diffèrent d’un seul octet sont toutes deux conservées, et duplicatesRemoved compte les entrées entières écartées, malgré le nom deduplicatePages orienté page.
  • sourceCount reflète le nombre d’entrées d’origine, pas le nombre de documents après déduplication.
  • La consolidation des signets ne se déclenche que lorsqu’au moins une entrée a un libellé non vide. Avec consolidateBookmarks à true mais tous les libellés vides, aucun objet /Outlines n’est écrit.
  • Les entrées d’outline injectées portent des titres et les liens d’arbre /Parent, /Prev, /Next ; elles n’incorporent pas de destinations /Dest explicites dans cette version.
  • La réécriture des liens ne compte que les actions /S /GoTo ; elle ne repointe pas les destinations à travers les objets renumérotés. Traite linksRewritten comme un nombre de détections.
  • La détection de SemanticSplitter est lexicale. Elle s’appuie sur les opérateurs de taille de police Tf, si bien que les pages sans image ou à l’encodage inhabituel ne produisent aucune frontière et retournent une section unique couvrant tout le document.

Aucune opération cryptographique n’a lieu dans ce module, donc aucun comportement spécifique au mode FIPS n’existe. L’empreinte de contenu xxh128 utilisée pour la déduplication est un hachage de détection de changement non cryptographique et ne porte aucun poids d’intégrité ou de preuve.

AffirmationNormeClause
Signets consolidés écrits sous forme de dictionnaire /Outlines lié depuis le catalogue du documentISO 32000-2:2020§7.7.2
La fusion de base émet une table de références croisées exacte à l’octet près pour chaque objet indirectISO 32000-2:2020§7.5.4
Titres des entrées d’outline échappés en chaînes littérales PDF, avec traitement du backslash et des parenthèsesISO 32000-2:2020§7.3.4.2
Ré-résolution complète des liens inter-documentsNon pris en charge (détection GoTo uniquement)
Destinations d’outline explicites par sectionNon émises dans cette version

Toutes les clauses sont paraphrasées ; NextPDF ne reproduit pas le texte normatif. Ce sont des déclarations de capacité, pas des certifications ; NextPDF ne détient aucune certification et n’en accorde aucune.

  • Disponibilité au sein du paquet Pro : SmartMerger, MergeInput, SmartMergeConfig, SmartMergeResult et SemanticSplitter depuis 2.2.0. Tous sont à jour dans nextpdf/pro 3.1.0.
  • La fusion de base délègue à Pro PdfSplitter::mergeDocuments(). Le PdfMerger::merge() Core hérité est un stub fail-closed dans cette version et n’est jamais appelé.
  • N’active deduplicatePages que lorsque les entrées peuvent être des documents entiers identiques à l’octet près ; il ne fusionne pas les copies quasi identiques ou ré-encodées.
  • Utilise SmartMergeConfig::basic() pour une concaténation pure et ::default() pour les signets plus l’analyse de liens.
  • Attrape OverflowException lors de la fusion d’entrées non fiables ; les bornes de nombre et de taille sont des rejets intentionnels.
  • Préfère directement le PdfSplitter Pro pour une simple découpe par plages de pages ; ne recours à SemanticSplitter que lorsqu’un sectionnement piloté par les titres est requis.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins de namespace 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.