Pro edizione
Diff
In breve
Sezione intitolata “In breve”NextPDF\Pro\Diff confronta due documenti PDF e segnala ciò che è cambiato. Il
percorso rapido produce un diff del testo allineato per pagina; il percorso
strutturato aggiunge il rilevamento delle modifiche a immagini e metadati e
formatta il risultato come JSON o HTML.
Disponibilità e licenza
Sezione intitolata “Disponibilità e licenza”Questa funzionalità è inclusa in NextPDF Pro (nextpdf/pro) e si attiva con
un envelope di licenza di tier Pro. Un deployment privo di tale entitlement non
carica le classi della funzionalità. Confrontare le edizioni e ottenere una
licenza.
Nessun flag di capacità a runtime governa le classi del Diff; sono presenti ogni volta che il pacchetto Pro è installato.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/pro:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”PdfDiffer::compare() estrae il testo per pagina da ciascun documento, lo
suddivide in righe ed esegue un Myers line diff per ciascuna coppia di pagine,
producendo regioni aggiunte, rimosse e modificate. L’estrazione del testo
analizza gli operatori di visualizzazione del testo di ISO 32000-2:2020 §9.4
(Tj, TJ, ').
StructuredDiffer si basa su questo: raggruppa le regioni di testo in modifiche
a livello di paragrafo, confronta le immagini incorporate, confronta i metadati
e produce uno StructuredDiffResult con un riepilogo aggregato. DiffFormatter
serializza tale risultato in una stringa JSON o in un frammento di report HTML.
Quando è installato il reader PDF Artisan opzionale, l’estrazione del testo lo usa per un contenuto accurato per pagina; altrimenti un fallback delimitato a livello di byte scansiona direttamente i content stream.
Perché funziona così
Sezione intitolata “Perché funziona così”Il differ confronta il testo e la struttura estratti, non i pixel renderizzati.
Un confronto strutturale è deterministico, economico e mappa alle modifiche
editoriali che interessano a un revisore. Un pixel diff segnalerebbe invece
l’antialiasing e il rumore dell’hinting dei font come contenuto. Poiché un PDF
memorizza glifi e posizionamento, non caratteri pronti da leggere, ogni confronto
ricostruisce prima il testo dal content stream. Quel passo di estrazione è il
motivo per cui il reader Artisan affina l’accuratezza, il motivo per cui il
fallback delimitato FlateDecode scambia la copertura con la sicurezza e il
motivo per cui le pagine acquisite tramite scanner producono un diff minimo.
L’allineamento delle pagine resta basato sull’indice per prevedibilità, così una
pagina inserita si legge come un chiaro spostamento a valle.
Contesto di progettazione: Perché il testo in un PDF non è davvero testo.
Contratto di comportamento
Sezione intitolata “Contratto di comportamento”- Input. Byte PDF grezzi per sorgente e destinazione. Un buffer che non
inizia con
%PDFsollevaInvalidArgumentException. - Output (percorso rapido).
DiffResultcon elenchi di regioniadded,removed,modifiedoltre aisIdentical(),hasDifferences(),totalChanges(). - Output (percorso strutturato).
StructuredDiffResultcon diff dei paragrafi, diff delle immagini, modifiche ai metadati e unDiffSummary. - Output del report.
DiffFormatteremette una stringa JSON o un frammento HTML. Non produce un PDF redline visivo affiancato. - Limiti delle risorse. La dimensione decompressa del content stream è limitata per difendersi dalle decompression bomb; lo scanner a livello di byte evita il backtracking catastrofico delle regex su input costruito ad arte.
- Determinismo. Per input identici, le regioni del diff e l’output formattato sono stabili.
Superficie API pubblica
Sezione intitolata “Superficie API pubblica”| Type | Kind | Key members |
|---|---|---|
NextPDF\Pro\Diff\PdfDiffer | final class | static compare(string $sourcePdf, string $targetPdf): DiffResult, static compareTexts(array $sourcePages, array $targetPages): DiffResult, static extractText(string $contentStream): string |
NextPDF\Pro\Diff\StructuredDiffer | final class | __construct(?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null), compare(string $sourcePdf, string $targetPdf): StructuredDiffResult |
NextPDF\Pro\Diff\DiffFormatter | final class | toJson(StructuredDiffResult $result): string, toHtml(StructuredDiffResult $result): string |
NextPDF\Pro\Diff\DiffResult | final readonly class | array $added, array $removed, array $modified, isIdentical(): bool, hasDifferences(): bool, totalChanges(): int |
NextPDF\Pro\Diff\StructuredDiffResult | final readonly class | text diff, paragraphs, images, metadata changes, summary |
NextPDF\Pro\Diff\DiffType | enum | Added, Removed, Modified, Unchanged |
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\PdfDiffer;
$diff = PdfDiffer::compare( file_get_contents('v1.pdf'), file_get_contents('v2.pdf'),);
if ($diff->hasDifferences()) { echo $diff->totalChanges(), " text changes detected\n";}Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\DiffFormatter;use NextPDF\Pro\Diff\StructuredDiffer;
function reviewReport(string $oldPdf, string $newPdf): string{ $result = (new StructuredDiffer())->compare($oldPdf, $newPdf);
// JSON for machine consumption; toHtml() for a review UI fragment. return (new DiffFormatter())->toJson($result);}Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Il diff è allineato per pagina in base all’indice. L’inserimento di una pagina in anticipo sposta tutte le pagine successive e segnala ampie modifiche a valle — questo è il comportamento atteso per un confronto allineato per indice.
- Il confronto delle immagini rileva immagini incorporate aggiunte, rimosse e modificate; non è un diff visivo percettivo e non esegue il rendering pixel delle pagine.
- I PDF acquisiti tramite scanner e composti da sole immagini producono un diff del testo scarso o nullo perché non viene eseguito alcun OCR.
- Senza il reader Artisan opzionale, l’estrazione usa il fallback delimitato; i documenti fortemente compressi potrebbero produrre una copertura del testo ridotta.
Prestazioni
Sezione intitolata “Prestazioni”L’estrazione del testo è lineare rispetto ai byte del documento; il Myers diff è
quasi lineare per documenti simili e quadratico nel caso peggiore per ciascuna
coppia di pagine. Il limite di decompressione delimita la memoria. Vedere
performance_budget.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”Il fallback a livello di byte usa una scansione basata su strpos anziché regex
non delimitate per evitare il backtracking catastrofico su PDF costruiti ad arte,
e delimita l’output della decompressione. L’operazione di diff non esegue script
incorporati. Vedere il modello di sicurezza del Core.
Conformità
Sezione intitolata “Conformità”| Claim | Spec clause | Status |
|---|---|---|
Tj text operator parsed for extraction | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
TJ array text operator parsed for extraction | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
| Visual side-by-side redline PDF output | — | Not supported (JSON/HTML only) |
Core fallback / alternativa
Sezione intitolata “Core fallback / alternativa”Non esiste alcun equivalente Core per il confronto dei documenti. Il reader Artisan opzionale migliora l’accuratezza dell’estrazione quando installato, ma non è richiesto.
Nota sul confine Enterprise
Sezione intitolata “Nota sul confine Enterprise”Questo è un rilevatore di modifiche al contenuto. Non è un analizzatore forense delle differenze e non produce report probatori o di attribuzione delle manomissioni; tali temi sono fuori ambito per questo modulo.
Confine di pubblicazione
Sezione intitolata “Confine di pubblicazione”Questa pagina documenta solo il comportamento osservabile dall’esterno e la superficie pubblica dell’API supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi dei file dei runbook e i prefissi dei ticket sono fuori ambito.