Pro edition
Interop — Deep Reference
At a glance
Section titled “At a glance”This page is the contract-level reference for NextPDF\Pro\Interop\V1. The module contains fourteen public symbols: one serialization contract (InteropResultInterface), one CI integrity guard (SchemaLock), three top-level result DTOs (ExtractedText, DocumentSegmentation, FormData), and nine supporting value objects and enums. Every DTO is an immutable, JSON-serializable view of one analysis result. The wire shape is versioned and locked; nothing on this surface re-runs analysis. The task-oriented view lives on the capability page.
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. Compare editions and get a license.
No runtime capability flag gates this module. The classes are available whenever nextpdf/pro is installed and licensed.
Public API surface
Section titled “Public API surface”| Symbol | Parameters | Default behavior | Returns | Throws or fails with | Notes |
|---|---|---|---|---|---|
InteropResultInterface | — | Contract for top-level result DTOs; extends JsonSerializable | — | Does not throw | SCHEMA_VERSION is the string '1.0'. |
InteropResultInterface::toArray() | none | Serializes to a JSON-safe array that always carries schema_version | array<string, mixed> | Does not throw | Implementations also emit a type discriminator. |
InteropResultInterface::toJson() | int $flags = 0 | Encodes the toArray() output; JSON_THROW_ON_ERROR is always OR-ed in | string | JsonException on non-encodable data | Pass flags such as JSON_PRETTY_PRINT. |
SchemaLock::verify() | none | Hashes the on-disk V1 schema.json and compares it against the locked SHA-256 | bool | Does not throw | false when the schema file is missing, unreadable, or modified. |
SchemaLock::expectedHash() | none | Returns the locked hash | string | Does not throw | Diagnostic output for CI failure triage. |
SchemaLock::actualHash() | none | Returns the hash of the current schema file | string | Does not throw | Sentinel strings FILE_NOT_FOUND / READ_FAILED replace the hash on I/O failure. |
BoundingBox | float $x, float $y, float $width, float $height | Immutable box in PDF user-space points, origin at the bottom-left | — | Does not throw | area(), overlaps(), toArray(), fromArray(). |
DocumentInfo | int $pageCount plus six optional metadata fields | Immutable document metadata | — | Does not throw | fromArray() type-guards every field; absent fields fall back to defaults. |
PageInfo | int $pageNumber, float $width, float $height, int $rotation = 0 | Immutable page metadata | — | Does not throw | isLandscape(); fromArray() coerces numeric strings and floats. |
ExtractedText | list<ExtractedPage> $pages, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | Whole-document text-extraction result | — | JsonException from toJson() only | page(), totalBlockCount(), plainText(), fromArray(). |
ExtractedPage | PageInfo $pageInfo, list<TextBlock> $textBlocks | Per-page container of text blocks in reading order | — | Does not throw | plainText() joins block content with single spaces. |
TextBlock | string $content, BoundingBox $boundingBox, int $pageNumber, string $fontName = '', float $fontSize = 0.0 | Positioned contiguous text run | — | Does not throw | Font name and size are best-effort (dominant font in the block). |
DocumentSegmentation | list<Segment> $segments, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | Layout-aware segmentation result | — | JsonException from toJson() only | segmentCount(), ofType(), onPage(), contentSegments(), fromArray(). |
Segment | SegmentType $type, string $content, BoundingBox $boundingBox, int $pageNumber, float $confidence = 1.0, list<Segment> $children = [] | Classified page region; children nest recursively | — | Does not throw | isHighConfidence() threshold is 0.8; descendantCount() is recursive. |
SegmentType | string-backed enum | Twelve cases, heading through unknown | — | Does not throw | isContent() and isStructural() partition the cases. |
FormData | list<FormField> $fields, DocumentInfo $documentInfo, float $processingTimeMs = 0.0 | Whole-document form-extraction result | — | JsonException from toJson() only | field(), dataFields(), filledCount(), toKeyValueMap(), fromArray(). |
FormField | string $name, FormFieldType $type, plus six optional fields | Single extracted form field | — | Does not throw | isFilled() is value !== ''. |
FormFieldType | string-backed enum | Eight cases, text through button | — | Does not throw | isDataField() is false for button and signature. |
interface InteropResultInterface extends JsonSerializable
public const SCHEMA_VERSION = '1.0';
public function toArray(): array;
public function toJson(int $flags = 0): string;final class SchemaLock
public static function verify(): bool
public static function expectedHash(): string
public static function actualHash(): stringfinal readonly class ExtractedText implements InteropResultInterface
public function __construct( public array $pages, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function page(int $pageNumber): ?ExtractedPage
public function totalBlockCount(): int
public function plainText(): string
public static function fromArray(array $data): selffinal readonly class DocumentSegmentation implements InteropResultInterface
public function __construct( public array $segments, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function ofType(SegmentType $type): array
public function onPage(int $pageNumber): array
public function contentSegments(): array
public static function fromArray(array $data): selffinal readonly class FormData implements InteropResultInterface
public function __construct( public array $fields, public DocumentInfo $documentInfo, public float $processingTimeMs = 0.0,)
public function field(string $name): ?FormField
public function dataFields(): array
public function toKeyValueMap(): array
public static function fromArray(array $data): selfBehavior contract
Section titled “Behavior contract”- Versioned envelope. Every top-level DTO (
ExtractedText,DocumentSegmentation,FormData) implementsInteropResultInterface. ItstoArray()output always carriesschema_version('1.0') and atypediscriminator:extracted_text,document_segmentation, orform_data. - JSON encoding.
toJson()delegates tojson_encodewithJSON_THROW_ON_ERROROR-ed into the caller’s flags.jsonSerialize()delegates totoArray(), sojson_encode($dto)produces the same shape. - Deterministic serialization. Key order and shape are fixed by the DTO.
Segment::toArray()omits thechildrenkey when empty;FormField::toArray()omitsbounding_boxwhen it isnull. Consumers must treat both keys as optional. - Round trip. Each DTO exposes a static
fromArray()that accepts a decoded JSON object. Fields are type-guarded at this cross-process boundary: absent or mistyped values fall back to documented defaults instead of throwing. - Enum fallbacks. An unrecognized
typestring maps toSegmentType::UnknowninSegment::fromArray()and toFormFieldType::TextinFormField::fromArray(). - Coordinates.
BoundingBoxcoordinates are PDF user-space units (points, 1/72 inch) with the origin at the bottom-left corner of the page. Page numbers are one-based throughout. - Plain-text joins.
ExtractedPage::plainText()joins block content with single spaces.ExtractedText::plainText()joins pages with blank lines ("\n\n"). - Segmentation queries.
ofType(),onPage(), andcontentSegments()filter top-level segments only and return re-indexed lists.contentSegments()selects the types whereSegmentType::isContent()istrue:heading,sub_heading,paragraph,table,list,code. - Form queries.
FormData::dataFields()andtoKeyValueMap()exclude non-data field types (button,signature).filledCount()counts fields whose value is a non-empty string. - Schema lock.
SchemaLock::verify()reads the V1schema.jsonshipped with the package, normalizes CRLF to LF, hashes with SHA-256, and compares against the locked constant in constant time. CI uses it to block silent schema drift; the lock value changes only with a deliberate versioned schema change. - Versioning policy. The V1 surface is an explicit public contract. Additive changes bump the schema version; breaking changes require a new major version.
Edge cases & failure modes
Section titled “Edge cases & failure modes”- The only throwing member on this surface is
toJson():JsonExceptionwhen the array is not encodable, for example invalid UTF-8 in extracted content. SchemaLock::verify()returnsfalse— never throws — when the schema file is missing, unreadable, or modified. CompareexpectedHash()withactualHash()to distinguish drift from I/O failure.fromArray()fallbacks are silent by design. A mistypedpage_numberbecomes1; a mistypedconfidencebecomes the default. Validate upstream when fabricated defaults are unacceptable.- Numeric-string coercion is asymmetric.
PageInfo::fromArray()accepts numeric strings for its int and float fields;SegmentandTextBlockaccept only int or float forconfidenceandfont_size. BoundingBox::fromArray()requires all four keys per its documented array shape. The DTOs that embed it substitute a zero box (ornullforFormField) when the wrapper key is absent.ExtractedPage::fromArray()substitutes a fallbackpage_infoof page 1 at 595 × 842 points when the key is missing or mistyped.FormField::fromArray()accepts only strict booleans forrequiredandread_only; truthy strings and integers map tofalse.Segmentchildren recurse without a depth limit. Extremely deep nesting is bounded only by PHP’s memory and stack limits.- No cryptographic key or signature operation occurs in this module.
SchemaLockuses SHA-256 solely as a file-integrity checksum, so there is no FIPS-mode-specific behavior.
Conformance
Section titled “Conformance”Interop V1 is a NextPDF-owned, versioned wire contract. It does not implement an external standard, so there is no normative citation table. BoundingBox semantics align with the PDF user-space coordinate model that the producing Core subsystems use.
Development notes
Section titled “Development notes”- Branch on
schema_versionin consumers. Treat additive keys as compatible; reject unknown major versions explicitly. - Run
SchemaLock::verify()in CI. On failure, logexpectedHash()andactualHash()and require a deliberate versioned schema change, never an in-place edit. - For cross-process round trips, decode with associative arrays (
json_decode($json, true)) and feed the result to the matchingfromArray(). - All DTOs are
finalandreadonly. Extend by composition; derive new views from the public fields. toKeyValueMap()flattens data-bearing fields only. Readsignaturefields directly fromFormData::$fieldswhen their presence matters.- Reuse is safe: the DTOs hold no mutable state and no resources, so they can be cached, shared across requests, and serialized repeatedly.
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.