Перейти к содержимому
getnextpdf.com

Pro редакция

AST — глубокий справочник

Эта страница — глубокий справочник по модулю Pro AST. Она охватывает публичные поверхности построения, кэширования, мутации, записи и эмиссии, их контракты поведения и режимы сбоев. Модуль разбирает загруженный PDF в неизменяемое дерево AstDocument, применяет журналируемые мутации в памяти и записывает инкрементные обновления на основе наложений. AstDocument и AstNode — типы-значения Core в пространстве имён NextPDF\Ast; этот модуль их производит и потребляет.

Эта возможность поставляется в NextPDF Pro (nextpdf/pro) и активируется лицензионным конвертом уровня Pro. Развёртывание без этого права не загружает классы этой возможности. Сравнить редакции и получить лицензию.

Пофункционального лицензионного флага нет. Это возможность редакции Pro. Поведение построения полностью определяется AstBuildOptions.

СимволПараметрыПоведение по умолчаниюВозвращаетВыбрасывает или завершается ошибкойПримечания
AstBuilder::__constructPdfReader $reader, AstBuildOptions $options, ?AstCache $cache = nullПривязывает загруженный reader к опциям построения; кэширование необязательноAstBuilderЗначение null для cache означает, что каждый вызов build() перестраивает дерево.
AstBuilder::buildstring $sourceHash (полный шестнадцатеричный SHA-256 байтов PDF)Поиск в кэше, отклонение шифрования, путь дерева структуры, резервный путь без тегов, прикрепление ограничивающих рамок, сохранение в кэшAstDocumentAstUnsupportedEncryptionException, AstBuildLimitException, AstBuildTimeoutExceptionПопадание в кэш возвращает результат без повторного разбора.
AstBuildOptions::__construct?int $pageRangeStart = null, ?int $pageRangeEnd = null, int $maxNodes = 100_000, int $maxDepth = 200, ?int $estimatedTokenBudget = null, int $maxMemoryBytes = 268435456, float $timeoutSeconds = 30.0, bool $useHeuristic = falseНеизменяемый объект-значение конфигурацииAstBuildOptionsestimatedTokenBudget — информационная подсказка; не применяется принудительно.
AstBuildOptions::pageRangeContainsint $pageIndexИстина, когда индекс с отсчётом от 0 попадает в настроенный диапазонboolГраницы null не ограничены; обе null означают все страницы.
AstBuildOptions::hashСтабильный SHA-256 по всем значениям опцийstringРавные значения дают равные хеши между экземплярами; используется как сегмент ключа кэша.
AstCache::__constructCacheInterface $backendОборачивает любой PSR-16 бэкендAstCache
AstCache::buildKeystring $sourceHash, AstBuildOptions $optionsКлюч = nextpdf_ast_v1_ + первые 32 hex хеша источника + _ + первые 16 hex хеша опцийstringИзменения опций автоматически аннулируют кэшированные результаты.
AstCache::getstring $cacheKeyДекодирует JSON-полезную нагрузку через строгую проверку по каждому полю?AstDocumentНикогда не выбрасывает; при сбое возвращает nullНекорректные или подделанные полезные нагрузки безопасно завершаются как промах кэша.
AstCache::setstring $cacheKey, AstDocument $documentСохраняет JSON с TTL 24 часа, затем проверяет немедленным обратным чтениемvoidAstWriteVerificationException (пространство имён Exception)Сбой записи в бэкенд или неудачный round-trip приводит к исключению.
AstCache::deletestring $cacheKeyУдаление по мере возможностиvoidНикогда не выбрасываетСбои удаления в бэкенде проглатываются.
AstCache::hasstring $cacheKeyПроверка существования по мере возможностиboolНикогда не выбрасывает; при сбое возвращает false
AstMutator::updateNodeAstDocument $document, string $nodeId, array $updatesЗаменяет text_content, записывает запись UpdatedAstDocument (новый экземпляр)InvalidArgumentExceptionПрименяется только ключ text_content; неизвестные ключи игнорируются.
AstMutator::deleteNodeAstDocument $document, string $nodeIdУдаляет узел из дерева в памяти, записывает запись DeletedAstDocument (новый экземпляр)InvalidArgumentExceptionУдаление только в памяти; см. оговорку о скрытии данных ниже.
AstMutator::getMutationLogВозвращает общий экземпляр журналаMutationLogПередайте тот же журнал в AstWriter.
AstMutator::resetLogОтбрасывает все записанные мутацииvoidНачинает новый журнал.
MutationLogrecord, all, isEmpty, count, forNode, mutatedNodeIdsЖурнал в памяти только для добавления, порядок вставки сохраняетсяпо методуforNode возвращает самую последнюю запись для узла; побеждает последняя запись.
MutationEntry::__constructstring $nodeId, MutationType $type, ?AstNode $originalNode, ?AstNode $mutatedNode, DateTimeImmutable $timestampНеизменяемая запись одной мутацииMutationEntryoriginalNode равен null для Inserted; mutatedNode равен null для Deleted.
MutationTypeварианты enum Updated, Inserted, DeletedКлассификация на основе строкDeleted в режиме OVERLAY скрывает содержимое; не стирает байты.
AstWriter::writestring $originalPdfBytes, MutationLog $logДобавляет инкрементное обновление, потоки наложения которого покрывают изменённые ограничивающие рамкиstring (изменённые байты PDF)AstWriteExceptionПустой журнал возвращает вход без изменений. Записи Inserted и записи без ограничивающей рамки пропускаются.
AstWriter::writeAndVerifystring $originalPdfBytes, MutationLog $logВыполняет write(), затем структурную проверку выводаstring (проверенные байты PDF)AstWriteException, AstWriteVerificationException (пространство имён Writer)Проверка структурная, не семантическая.
AstPdfEmitter::emitAstNode $root, BinaryBuffer $buffer, ObjectRegistry $registry, array $pageObjectsЗаписывает StructTreeRoot, цепочку StructElem и ParentTree для переданного дереваEmitResultAstEmitExceptionКорень должен быть узлом Document с потомками. Round-trip эмиттер для проверки дерева структуры.
EmitResult::__constructint $structTreeRootObject, int $rootElementObject, int $parentTreeObject, int $elementObjectCount, int $parentTreeNextKeyНеизменяемая запись идентификаторов эмитированных объектовEmitResult
public function build(string $sourceHash): AstDocument
public function updateNode(AstDocument $document, string $nodeId, array $updates): AstDocument
public function deleteNode(AstDocument $document, string $nodeId): AstDocument
public function write(string $originalPdfBytes, MutationLog $log): string
public function writeAndVerify(string $originalPdfBytes, MutationLog $log): string
  • NextPDF\Pro\Ast\Exception\AstException расширяет RuntimeException — базовый класс иерархии построения.
  • AstBuildLimitException расширяет AstException — превышен потолок узлов, глубины или памяти.
  • AstBuildTimeoutException расширяет AstBuildLimitException — истёк тайм-аут построения по реальному времени.
  • AstNoStructTreeException расширяет AstException — дерево структуры отсутствует. AstBuilder::build() перехватывает его внутренне и переключается на резервный путь; вызывающие build() его не наблюдают.
  • AstUnsupportedEncryptionException расширяет AstException — входной PDF зашифрован.
  • NextPDF\Pro\Ast\Exception\AstWriteVerificationException расширяет AstException — проверка записи в кэш не удалась.
  • NextPDF\Pro\Ast\Writer\AstWriteException расширяет RuntimeException — сбой входных данных или структуры писателя.
  • NextPDF\Pro\Ast\Writer\AstWriteVerificationException расширяет AstWriteException — структурная проверка после записи не удалась.

Существуют два разных класса AstWriteVerificationException в разных пространствах имён. AstCache::set() выбрасывает класс из пространства имён Exception; AstWriter::writeAndVerify() выбрасывает класс из пространства имён Writer. Сопоставляйте пространство имён в блоках catch.

AstBuilder::build($sourceHash) требует полный шестнадцатеричный SHA-256 исходных байтов. Конвейер таков: необязательный поиск в кэше, отклонение шифрования, путь дерева структуры, резервный путь без тегов, прикрепление ограничивающих рамок, необязательное сохранение в кэш.

Ключ кэша объединяет хеш источника с хешем AstBuildOptions. Хеш опций стабилен между экземплярами с одинаковыми значениями, поэтому идентичные входы и опции возвращают одно и то же дерево. Когда кэш не предоставлен, каждый вызов перестраивает дерево. Кэшируемые полезные нагрузки — это JSON, никогда не нативная сериализация PHP: путь чтения проверяет каждое поле и инстанцирует только типы-значения AST, поэтому отравленная запись кэша не может вызвать инъекцию объектов и деградирует до промаха кэша.

Путь дерева структуры выполняется, когда дерево структуры присутствует. Потолки ресурсов — количество узлов, глубина, дельта памяти и реальное время — применяются во время чтения дерева структуры и выбрасывают AstBuildLimitException или AstBuildTimeoutException. Если средство чтения сообщает об отсутствии дерева структуры, построитель переключается на путь без тегов: эвристический построитель, когда useHeuristic истинно, иначе простой резервный построитель. Ограничивающие рамки прикрепляются путём анализа потока содержимого каждой страницы в диапазоне; страница, поток содержимого которой не удаётся разобрать, пропускается и оставляет остальную часть дерева нетронутой.

AstNode неизменяем. Обновления дерева перестраивают затронутые узлы снизу вверх; неизменённые поддеревья возвращаются по идентичности. AstMutator следует тому же контракту: каждая мутация возвращает новый AstDocument, перестраивает только путь от корня до цели и записывает MutationEntry в общий MutationLog.

AstWriter применяет MutationLog в режиме OVERLAY как инкрементное обновление только для добавления: новые потоки содержимого наложения, обновлённые объекты страниц, секция перекрёстных ссылок, охватывающая только новые объекты, и трейлер, чей /Prev указывает на предыдущий startxref. Исходные байты остаются нетронутыми согласно модели инкрементного обновления ISO 32000-2:2020, 7.5.6. Замещающий текст, отрисовываемый для записей Updated, экранирует \, ( и ) в литеральных строках согласно ISO 32000-2:2020, 7.3.4.2.

AstPdfEmitter::emit() — симметричная обратная операция к чтению дерева структуры: деревья, произведённые средством чтения, при round-trip дают структурно эквивалентные деревья с точностью до перенумерации идентификаторов узлов и документированных классов канонизации. MCID, присутствующие на узлах, повторно эмитируются дословно и никогда не перевыделяются.

  • Зашифрованный вход отклоняется до какой-либо работы с деревом; для зашифрованных PDF нет результата с частичным деревом. Сначала расшифруйте.
  • Потолки ресурсов: максимум узлов (по умолчанию 100,000), максимальная глубина (по умолчанию 200), максимальная память (по умолчанию 256 MiB), тайм-аут по реальному времени (по умолчанию 30 s). Превышение потолка выбрасывает AstBuildLimitException; тайм-аут выбрасывает AstBuildTimeoutException, подкласс.
  • Диапазон страниц отсчитывается от 0 и включителен; границы null означают все страницы.
  • Страница, поток содержимого которой не удаётся разобрать, пропускается во время прикрепления ограничивающих рамок; остальная часть дерева не затрагивается.
  • AstCache::get() никогда не выбрасывает: некорректные, подделанные или нестроковые полезные нагрузки возвращают null и вынуждают перестроение. AstCache::set() завершается с явной ошибкой, когда запись в бэкенд или немедленное обратное чтение не удаётся.
  • AstMutator выбрасывает InvalidArgumentException, когда идентификатор узла не найден. Неизвестные ключи обновления молча игнорируются; применяется только text_content.
  • AstWriter::write() выбрасывает AstWriteException, когда во входных данных отсутствует заголовок %PDF- или обнаружимый startxref. Записи без ограничивающей рамки молча пропускаются. Страницы, которые не удаётся найти сканированием объектов — например, при сжатых потоках перекрёстных ссылок, — пропускаются; если наложение применить нельзя, входные байты возвращаются без изменений.
  • Вывод OVERLAY — это не скрытие данных (redaction). Белый прямоугольник и перерисованный текст добавляются; исходные байты содержимого остаются в файле и восстанавливаются прямым извлечением. Не используйте это для удаления по GDPR ст. 17 или юридического скрытия данных. Писатель режима reconstruct существует в дереве исходного кода, но помечен как внутренний, не готов к production и находится вне поддерживаемой поверхности API.
  • Геометрия наложения предполагает A4 в книжной ориентации (595 x 842 pt), поскольку писатель не читает MediaBox страницы. На страницах, отличных от A4, наложение может быть слегка смещено; вывод остаётся структурно валидным.
  • writeAndVerify() проверяет только структуру: заголовок, завершающий %%EOF и рост вывода. Он не выполняет семантического повторного разбора изменённого документа.
  • AstPdfEmitter::emit() выбрасывает AstEmitException, когда корень не является узлом Document или не имеет потомков. Сопутствующие записи OBJR (аннотации) в этом выпуске не эмитируются.
  • Этот модуль не выполняет криптографических операций и не определяет поведения, специфичного для FIPS. SHA-256 используется только как адресация по содержимому для ключей кэша.

Путь дерева структуры читает средства логической структуры тегированного PDF, определённые ISO 32000-2; корпус RAG, доступный на момент написания, не включает пункты о логической структуре, поэтому это утверждение обосновано продуктом на основе аннотаций источника. Компоновка инкрементного обновления писателя следует ISO 32000-2:2020, 7.5.6 (цитируется ниже), а экранирование литеральных строк следует ISO 32000-2:2020, 7.3.4.2 (цитируется ниже).

Эти утверждения описывают возможности относительно цитируемых пунктов. NextPDF не имеет сертификации соответствия, и поддержка пункта не является заявлением о сертификации.

  • Создавайте один AstBuilder на каждый загруженный PdfReader. Переиспользуйте AstCache между построениями, чтобы амортизировать разбор; конструкция ключа делает изменения опций самоаннулирующимися.
  • Разделяйте один MutationLog между AstMutator и AstWriter, чтобы писатель применял ровно записанную сессию. Вызывайте resetLog() между независимыми сессиями редактирования.
  • Устанавливайте useHeuristic в true для документов без тегов, когда группировка на основе макета предпочтительнее простого резервного дерева.
  • Построения детерминированы для одинаковых байтов и опций; полагайтесь на это для тестов в стиле snapshot.
  • Перехватывайте сбои построения через иерархию NextPDF\Pro\Ast\Exception, а сбои записи — через иерархию NextPDF\Pro\Ast\Writer; у них нет общего базового класса ниже RuntimeException.

Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов runbook и префиксы тикетов находятся вне области рассмотрения.