Pro Edition
Vergleich
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“NextPDF\Pro\Diff vergleicht zwei PDF-Dokumente und meldet, was sich geändert
hat. Der schnelle Pfad erzeugt einen seitenausgerichteten Text-Diff; der
strukturierte Pfad ergänzt Bild- und Metadatenänderungserkennung und
formatiert das Ergebnis als JSON oder HTML.
Verfügbarkeit & Lizenzierung
Abschnitt betitelt „Verfügbarkeit & Lizenzierung“Diese Funktion wird in NextPDF Pro (nextpdf/pro) ausgeliefert und wird
mit einer Lizenz-Envelope der Pro-Stufe aktiviert. Eine Bereitstellung ohne
diese Berechtigung lädt die Klassen der Funktion nicht. Editionen vergleichen
und Lizenz erwerben.
Kein Laufzeit-Fähigkeits-Flag schaltet die Diff-Klassen; sie sind vorhanden, sobald das Pro-Paket installiert ist.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/pro:^3Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“PdfDiffer::compare() extrahiert den Text je Seite aus jedem Dokument, teilt
ihn in Zeilen auf und führt je Seitenpaar einen Myers-Zeilen-Diff aus, der
hinzugefügte, entfernte und geänderte Regionen erzeugt. Die Textextraktion
parst die textanzeigenden Operatoren von ISO 32000-2:2020 §9.4 (Tj, TJ,
').
StructuredDiffer baut darauf auf: Es gruppiert Textregionen zu Änderungen
auf Absatzebene, vergleicht eingebettete Bilder, vergleicht Metadaten und
erzeugt ein StructuredDiffResult mit einer aggregierten Zusammenfassung.
DiffFormatter serialisiert dieses Ergebnis zu einem JSON-String oder einem
HTML-Bericht-Fragment.
Wenn der optionale Artisan-PDF-Reader installiert ist, verwendet die Textextraktion ihn für seitengenauen Inhalt; andernfalls scannt eine begrenzte Rückfalloption auf Byteebene die Content-Streams direkt.
Warum es so funktioniert
Abschnitt betitelt „Warum es so funktioniert“Der Differ vergleicht extrahierten Text und Struktur, nicht gerenderte Pixel.
Ein struktureller Vergleich ist deterministisch, günstig und bildet die
redaktionellen Änderungen ab, die einem Prüfer wichtig sind. Ein Pixel-Diff
würde stattdessen Antialiasing- und Font-Hinting-Rauschen als Inhalt
kennzeichnen. Da ein PDF Glyphen und Positionierung speichert und keine
lesefertigen Zeichen, rekonstruiert jeder Vergleich zunächst den Text aus dem
Content-Stream. Dieser Extraktionsschritt ist der Grund, warum der
Artisan-Reader die Genauigkeit schärft, warum die begrenzte
FlateDecode-Rückfalloption Abdeckung gegen Sicherheit eintauscht und warum
gescannte Seiten kaum diffen. Die Seitenausrichtung bleibt zur Vorhersehbarkeit
indexbasiert, sodass eine eingefügte Seite als deutliche nachgelagerte
Verschiebung erscheint.
Design-Hintergrund: Warum der Text in einem PDF nicht wirklich Text ist.
Verhaltensvertrag
Abschnitt betitelt „Verhaltensvertrag“- Eingabe. Rohe PDF-Bytes für Quelle und Ziel. Ein Puffer, der nicht mit
%PDFbeginnt, löstInvalidArgumentExceptionaus. - Ausgabe (schneller Pfad).
DiffResultmit den Regionslistenadded,removed,modifiedplusisIdentical(),hasDifferences(),totalChanges(). - Ausgabe (strukturierter Pfad).
StructuredDiffResultmit Absatz-Diffs, Bild-Diffs, Metadatenänderungen und einerDiffSummary. - Bericht-Ausgabe.
DiffFormattergibt einen JSON-String oder ein HTML-Fragment aus. Es erzeugt kein visuelles, nebeneinanderliegendes Redline-PDF. - Ressourcengrenzen. Die dekomprimierte Content-Stream-Größe ist begrenzt, um vor Dekomprimierungsbomben zu schützen; der Byteebenen-Scanner vermeidet katastrophales Regex-Backtracking bei manipulierter Eingabe.
- Determinismus. Für identische Eingaben sind die Diff-Regionen und die formatierte Ausgabe stabil.
Öffentliche API-Oberfläche
Abschnitt betitelt „Öffentliche API-Oberfläche“| Typ | Art | Zentrale Mitglieder |
|---|---|---|
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, Absätze, Bilder, Metadatenänderungen, Zusammenfassung |
NextPDF\Pro\Diff\DiffType | enum | Added, Removed, Modified, Unchanged |
Codebeispiel — Schnellstart
Abschnitt betitelt „Codebeispiel — Schnellstart“<?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";}Codebeispiel — Produktion
Abschnitt betitelt „Codebeispiel — Produktion“<?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);}Randfälle & Fallstricke
Abschnitt betitelt „Randfälle & Fallstricke“- Der Diff ist nach Index seitenausgerichtet. Das Einfügen einer Seite weiter vorne verschiebt alle späteren Seiten und meldet große nachgelagerte Änderungen — das ist für einen indexausgerichteten Vergleich zu erwarten.
- Der Bildvergleich erkennt hinzugefügte, entfernte und geänderte eingebettete Bilder; er ist kein perzeptueller visueller Diff und rendert keine Seiten pixelweise.
- Gescannte reine Bild-PDFs erzeugen wenig oder keinen Text-Diff, weil kein OCR durchgeführt wird.
- Ohne den optionalen Artisan-Reader verwendet die Extraktion die begrenzte Rückfalloption; stark komprimierte Dokumente können eine verringerte Textabdeckung liefern.
Performance
Abschnitt betitelt „Performance“Die Textextraktion ist linear in den Dokumentbytes; der Myers-Diff ist
nahezu linear für ähnliche Dokumente und im schlimmsten Fall quadratisch je
Seitenpaar. Die Dekomprimierungsgrenze begrenzt den Speicher. Siehe
performance_budget.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“Die Byteebenen-Rückfalloption verwendet strpos-basiertes Scannen statt
unbegrenzter Regex, um katastrophales Backtracking bei manipulierten PDFs zu
vermeiden, und begrenzt die Dekomprimierungsausgabe. Das Diffing führt keine
eingebetteten Skripte aus. Siehe das Core-Sicherheitsmodell.
Konformität
Abschnitt betitelt „Konformität“| Aussage | Spec-Klausel | Status |
|---|---|---|
Tj-Textoperator zur Extraktion geparst | ISO 32000-2:2020 §9.4 | Verifiziert (Unit-Suite) |
TJ-Array-Textoperator zur Extraktion geparst | ISO 32000-2:2020 §9.4 | Verifiziert (Unit-Suite) |
| Visuelle nebeneinanderliegende Redline-PDF-Ausgabe | — | Nicht unterstützt (nur JSON/HTML) |
Core-Rückfalloption / Alternative
Abschnitt betitelt „Core-Rückfalloption / Alternative“Für den Dokumentvergleich existiert kein Core-Äquivalent. Der optionale Artisan-Reader verbessert die Extraktionsgenauigkeit, wenn er installiert ist, ist aber nicht erforderlich.
Hinweis zur Enterprise-Abgrenzung
Abschnitt betitelt „Hinweis zur Enterprise-Abgrenzung“Dies ist ein Inhaltsänderungs-Detektor. Er ist kein forensischer Differenzanalysator und erzeugt keine beweis- oder manipulationszuordnenden Berichte; diese Anliegen liegen außerhalb des Geltungsbereichs dieses Moduls.
Publikationsgrenze
Abschnitt betitelt „Publikationsgrenze“Diese Seite dokumentiert ausschließlich extern beobachtbares Verhalten und die unterstützte öffentliche API-Oberfläche. Interne Namespace-Pfade, Hilfsklassen, Mechanismustabellen, Runbook-Dateinamen und Ticket-Präfixe liegen außerhalb des Geltungsbereichs.