Pro edition
Document
At a glance
Section titled “At a glance”The Document module splits a PDF into segments by page range and assembles PDF Portfolios (Collections) with sortable schema columns. Both operations are bounded against hostile input.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Document is part of the Pro edition, with no separate per-feature license flag. Compare editions and get a license.
Install
Section titled “Install”composer require nextpdf/pro:^3The code lives under the NextPDF\Pro\Document namespace.
Conceptual overview
Section titled “Conceptual overview”Two capabilities are provided:
PdfSplitterextracts page ranges into standalone PDF segments. It detects pages by scanning for page objects in the raw input and wraps the selected pages in a minimal catalog and page tree. It supports range-based splitting, fixed-size splitting (splitEvery), and single-range extraction (extractPages).PdfPortfoliobuilds a PDF Collection dictionary that aggregates file attachments with a defined schema. It supports tile, detail, and hidden view modes and emits a dictionary suitable for inclusion in the document catalog.
Why it works this way
Section titled “Why it works this way”Splitting a PDF is not a byte slice. A page object refers to shared resources, fonts, and content streams by indirect reference. It also inherits /MediaBox and /Resources from its page-tree ancestors. So the splitter reconstructs each segment as a self-contained object graph: it walks the transitive reference closure of the selected pages, materialises the inherited attributes, renumbers into a fresh id space, and writes a cross-reference table with byte-accurate offsets. The closure walk is bounded, because a hostile fan-out graph could otherwise pull unbounded work into one segment. The result opens as a valid standalone PDF, not a fragment with dangling references.
Design background: The anatomy of a PDF file.
Behavior contract
Section titled “Behavior contract”PdfSplitter::split($pdfData, $ranges, $maxBytes = 100_000_000, $maxRanges = 1000)enforces an input-size limit and a range-count limit, and rejects input that does not begin with the PDF header.splitEvery($pdfData, $pagesPerSegment)rejects a segment size below 1; the final segment may contain fewer pages.PdfPortfoliorejects any view mode other than tile, detail, or hidden at construction time.addSchema()andaddEntry()return the portfolio for fluent chaining;generateCollectionDictionary()returns the Collection dictionary string.- Schema field names are sanitized for use as PDF name objects; string values are escaped for PDF literal strings.
Code sample — Quick start
Section titled “Code sample — Quick start”The following reflects the documented public API. The repository does not ship a runnable example for this module.
use NextPDF\Pro\Document\PdfSplitter;use NextPDF\Document\PageRange;
$result = (new PdfSplitter())->split($pdfBytes, [new PageRange(1, 5)]);Code sample — Production
Section titled “Code sample — Production”use NextPDF\Pro\Document\PdfSplitter;use NextPDF\Document\PageRange;
$splitter = new PdfSplitter();
try { $result = $splitter->split( $pdfBytes, [new PageRange(1, 10), new PageRange(11, 20)], maxBytes: 50_000_000, maxRanges: 100, );} catch (\InvalidArgumentException $e) { // Input rejected (not a PDF, or limits exceeded).}Edge cases & gotchas
Section titled “Edge cases & gotchas”- The splitter reconstructs each segment as a fresh object graph with a real, byte-accurate cross-reference table; segments are valid standalone PDFs. It renumbers into a new id space rather than preserving the source byte layout, so hand segment bytes to the Writer module for incremental-update or signing workflows.
- A range that matches no pages yields a minimal one-page segment rather than an error.
- Portfolio sorting defaults to the first schema field, ascending.
Performance
Section titled “Performance”Splitting and portfolio assembly are linear in input size and entry count. The default input ceiling is 100 MB and the default range ceiling is 1000; both are caller-tunable downward. Measure with representative documents.
Security notes
Section titled “Security notes”Treat input as untrusted. Size and count guards bound resource use. The module sanitizes field names and escapes string values before they reach the output dictionary. It logs no document content.
Conformance
Section titled “Conformance”The Portfolio dictionary follows the PDF Collections model and the splitter follows the page-object model defined by ISO 32000-2; the source annotates the relevant clauses.
Enterprise boundary note
Section titled “Enterprise boundary note”Enterprise does not change Document behavior. Enterprise adds higher-tier archival and compliance features documented separately; they are not required for splitting or Portfolio assembly.
Core fallback / alternative
Section titled “Core fallback / alternative”Without Pro, use NextPDF Core’s base document primitives; page-range splitting and Portfolio assembly are Pro additions. See /modules/document/.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.