Pular para o conteúdo

Form: campos AcroForm interativos e achatamento

O módulo Form cria formulários interativos para documentos Portable Document Format (PDF). Ele constrói campos de texto, checkbox, radio, choice (list/combo), botão e assinatura, organiza esses campos em uma hierarquia parent/child, grava-os como objetos PDF com appearance streams e pode achatar o formulário em conteúdo de página estático.

Terminal window
composer require nextpdf/core:^3

Um formulário PDF interativo é o AcroForm: uma hierarquia de campos no nível do documento cujos campos terminais são associados a widget annotations nas páginas. A ISO 32000-2 §12.7 define esse formulário, seus dicionários de campos, a raiz do AcroForm e a hierarquia de campos. Este módulo codifica essas estruturas para o engine.

FormFieldManager é a superfície principal. Ela expõe os builders textField(), checkBox(), radioButton(), button() e signatureField(), rastreia os campos e os serializa com writeFields(). Ela emite um appearance stream de Form XObject para cada widget (/Subtype /Form, /BBox), conforme exige a §8.10. FormField é o objeto de valor do campo. FormFieldDictionaryBuilder converte um campo em seu dicionário PDF e aplica entradas específicas de tipo e bits de flag a campos de texto, checkbox, choice e botão. O manager e FormField são @since 1.0.0. O dictionary builder é @since 1.1.0.

FormFieldHierarchy modela a árvore de campos parent/child com addChild(), getRootFieldNames(), getChildren(), getParent() e o visitor walkDepthFirst(). Um nome de campo totalmente qualificado é o caminho com pontos nessa hierarquia, correspondendo ao modelo de campos aninhados da §12.7.

FormFlattener renderiza o formulário como conteúdo de página estático. flatten() retorna um FlattenResult; assim, você pode congelar um formulário preenchido para arquivamento. FieldMDP e FieldMdpAction modelam a transform de bloqueio de campo. Um documento assinado pode bloquear um conjunto nomeado de campos contra modificações posteriores. FieldMdpAction enumera o escopo do bloqueio, e requiresFieldList() indica quando uma lista explícita de campos é obrigatória. FieldMDP é @since 2.0.0.

ClasseMembros principaisFunção
FormFieldManagertextField(), checkBox(), radioButton(), button(), signatureField(), addChildField(), getHierarchy(), writeFields()Builder de campos + serializador (@since 1.0.0)
FormFieldobjeto de valor do campoUm campo do AcroForm (@since 1.0.0)
FormFieldDictionaryBuilderbuildFieldDictionary(), applyTextFieldOptions(), applyCheckBoxOptions(), applyChoiceFieldOptions(), applyButtonOptions()Builder de campo para dicionário (@since 1.1.0)
FormFieldHierarchyaddChild(), getRootFieldNames(), getChildren(), getParent(), walkDepthFirst()Árvore de campos parent/child (@since 2.0.0)
FormFlattenerflatten(array $fields, array $pages): FlattenResultAchata o formulário em conteúdo estático (@since 1.0.0)
FieldMDPtoTransformParams()Transform de bloqueio de campo (FieldMDP) (@since 2.0.0)
FieldMdpAction (enum)requiresFieldList()Escopo do bloqueio de campo (@since 2.0.0)

Execute composer docs:generate-api-php -- --module=Form para gerar a tabela completa de PHPDoc.

Fonte: examples/30-form-fields.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Form\FormFieldManager;
$form = new FormFieldManager();
$form->textField(name: 'applicant_name', x: 50, y: 700, w: 200, h: 18);
$form->checkBox(name: 'agree_terms', x: 50, y: 660, size: 12);
$form->radioButton(name: 'plan', x: 50, y: 620, size: 12 /* + option set */);
// The Writer invokes $form->writeFields(...) during document serialization.

Construa um conjunto de campos para um documento assinado e, em seguida, bloqueie os campos assinados com FieldMDP.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Form\FieldMDP;
use NextPDF\Form\FieldMdpAction;
use NextPDF\Form\FormFieldManager;
$form = new FormFieldManager();
$form->textField(name: 'contract_value', x: 50, y: 700, w: 160, h: 18);
$form->signatureField(name: 'approver_sig', x: 50, y: 600, w: 200, h: 60);
// Lock only the named fields after signing.
$lock = new FieldMDP(
action: FieldMdpAction::Include,
fields: ['contract_value'],
);
$transformParams = $lock->toTransformParams();
// $transformParams is attached to the signature's transform method by the signing layer.
  • Um nome de campo é um caminho com pontos totalmente qualificado em FormFieldHierarchy. Em um visualizador, dois campos terminais com o mesmo nome totalmente qualificado representam o mesmo campo lógico. Você é responsável pela unicidade.
  • FieldMdpAction::requiresFieldList() informa quando uma lista de campos é obrigatória. Uma ação Include/Exclude sem a lista exigida cria um bloqueio malformado; verifique a flag.
  • FormFlattener::flatten() remove deliberadamente a interatividade. O resultado é conteúdo estático. Mantenha a fonte interativa caso precise dela mais tarde.
  • Appearance streams são emitidos por widget. Um campo sem appearance pode renderizar de forma inconsistente entre visualizadores; deixe o manager gerar o appearance em vez de omiti-lo.
  • signatureField() cria apenas o placeholder do campo. A camada de Security/assinatura produz a assinatura propriamente dita; este módulo não.

A criação e a serialização de campos são O(n) em relação à contagem de campos, mais um appearance stream de Form XObject por widget. O custo do achatamento escala com o conteúdo renderizado, não com a contagem de campos. A carga de trabalho de referência padrão permanece dentro do orçamento de 1500 ms de tempo total / 64 MB de pico. O perfil de reprodutibilidade é structural: os números dos objetos e o /ID do trailer variam entre execuções. Dois documentos com o mesmo formulário são estruturalmente iguais, mas não idênticos byte a byte.

Os valores dos campos de formulário são entrada do usuário. O módulo faz escape dos valores de string para a serialização PDF com PdfStringEscaper, de modo que um valor de campo não consiga escapar da sua string PDF e injetar estrutura. Quando um formulário é criptografado, a criptografia AES-256 do documento abrange o conteúdo dos campos. FieldMDP é um controle de segurança: ele bloqueia campos nomeados contra modificações após a assinatura. Um bloqueio de campo que não corresponde ao conjunto de campos assinados compromete esse controle; defina o escopo do bloqueio de forma deliberada. Trate qualquer valor extraído de um formulário preenchido como entrada não confiável. Consulte o modelo de segurança do engine em /modules/core/security/.

As estruturas de formulário emitidas por este módulo seguem o modelo de formulário interativo da ISO 32000-2 §12.7: a raiz do AcroForm, os dicionários de campos e a hierarquia de campos do documento. As appearances por widget são emitidas como Form XObjects conforme a §8.10 e documentadas inline em src/Form/. tests/Unit/Form/ exercita esses fatos de implementação. Eles não constituem uma declaração de conformidade PDF 2.0 de ponta a ponta. A conformidade do documento completo é validada pelas suítes oracle e golden em /modules/core/conformance/.