Aller au contenu

Formulaire : champs interactifs AcroForm et aplatissement

Le module Form construit un formulaire PDF interactif. Il crée des champs texte, des cases à cocher, des boutons radio, des champs de choix (liste ou liste déroulante), des boutons et des champs de signature. Il les organise dans une hiérarchie parent/enfant. Il les sérialise sous forme d’objets PDF avec des flux d’apparence. Il peut aplatir le formulaire en contenu de page statique.

Fenêtre de terminal
composer require nextpdf/core:^3

Dans un PDF, le formulaire interactif est l’AcroForm : une hiérarchie de champs à l’échelle du document, dont les champs terminaux sont associés à des annotations de widget sur les pages. ISO 32000-2 §12.7 définit ce formulaire et ses dictionnaires de champ, y compris la racine AcroForm et la hiérarchie de champs. Ce module en fournit l’encodeur au sein du moteur.

FormFieldManager est la surface principale. Il expose les constructeurs textField(), checkBox(), radioButton(), button() et signatureField(), assure le suivi des champs et les sérialise avec writeFields(). Il émet, pour chaque widget, un flux d’apparence Form XObject (/Subtype /Form, /BBox) comme l’exige le §8.10. FormField est l’objet-valeur qui représente le champ. FormFieldDictionaryBuilder transforme un champ en son dictionnaire PDF et applique les entrées et bits d’indicateur propres au type (texte, case à cocher, choix, bouton). Le gestionnaire et FormField sont @since 1.0.0. Le constructeur de dictionnaire est @since 1.1.0.

FormFieldHierarchy modélise l’arbre de champs parent/enfant : addChild(), getRootFieldNames(), getChildren(), getParent(), et un visiteur walkDepthFirst(). Un nom de champ pleinement qualifié correspond au chemin en notation pointée dans cette hiérarchie, soit le modèle que le §12.7 spécifie pour les champs imbriqués.

FormFlattener rend le formulaire en contenu de page statique — flatten() renvoie un FlattenResult — afin qu’un formulaire rempli puisse être figé à des fins d’archivage. FieldMDP et FieldMdpAction modélisent la transformation de verrouillage de champ. Un document signé peut verrouiller un ensemble nommé de champs contre toute modification ultérieure. FieldMdpAction énumère la portée du verrouillage. Sa méthode requiresFieldList() indique quand une liste explicite de champs est obligatoire. FieldMDP est @since 2.0.0.

ClasseMembres clésRôle
FormFieldManagertextField(), checkBox(), radioButton(), button(), signatureField(), addChildField(), getHierarchy(), writeFields()Constructeur de champ + sérialiseur (@since 1.0.0)
FormFieldobjet-valeur de champUn champ AcroForm (@since 1.0.0)
FormFieldDictionaryBuilderbuildFieldDictionary(), applyTextFieldOptions(), applyCheckBoxOptions(), applyChoiceFieldOptions(), applyButtonOptions()Constructeur champ-vers-dictionnaire (@since 1.1.0)
FormFieldHierarchyaddChild(), getRootFieldNames(), getChildren(), getParent(), walkDepthFirst()Arbre de champs parent/enfant (@since 2.0.0)
FormFlattenerflatten(array $fields, array $pages): FlattenResultAplatit le formulaire en contenu statique (@since 1.0.0)
FieldMDPtoTransformParams()Transformation de verrouillage de champ (FieldMDP) (@since 2.0.0)
FieldMdpAction (enum)requiresFieldList()Portée du verrouillage de champ (@since 2.0.0)

Exécute composer docs:generate-api-php -- --module=Form pour générer la table PHPDoc complète.

Source : 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.

Construis un ensemble de champs pour un document signé et verrouille les champs signés avec 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.
  • Un nom de champ est un chemin en notation pointée pleinement qualifié dans FormFieldHierarchy. Deux champs terminaux portant le même nom pleinement qualifié correspondent au même champ logique dans une visionneuse : l’unicité relève de la responsabilité de l’appelant.
  • FieldMdpAction::requiresFieldList() t’indique quand une liste de champs est obligatoire. Une action Include/Exclude sans la liste requise produit un verrouillage malformé ; vérifie l’indicateur.
  • FormFlattener::flatten() détruit l’interactivité par conception : le résultat est du contenu statique. Conserve la source interactive si tu en as besoin par la suite.
  • Les flux d’apparence sont émis par widget. Sans apparence, un champ s’affiche de façon incohérente d’une visionneuse à l’autre ; laisse le gestionnaire générer l’apparence plutôt que de l’omettre.
  • signatureField() ne crée que l’emplacement réservé du champ. La production de la signature réelle relève de la couche de sécurité/signature, pas de ce module.

La création et la sérialisation des champs sont en O(n) selon le nombre de champs, avec un flux d’apparence Form XObject par widget. Le coût de l’aplatissement dépend du contenu rendu, pas du nombre de champs. La charge de travail de référence par défaut tient dans le budget de 1500 ms en temps réel / 64 Mo de pic. Le profil de reproductibilité est structural : les numéros d’objet et le /ID du trailer varient d’une exécution à l’autre. Deux documents portant le même formulaire sont structurellement équivalents, mais pas identiques octet pour octet.

Les valeurs des champs de formulaire sont des entrées utilisateur. Le module échappe les valeurs de chaîne pour la sérialisation PDF (PdfStringEscaper) afin qu’une valeur de champ ne puisse pas sortir de sa chaîne PDF ni injecter de structure. Quand un formulaire est chiffré, le contenu des champs est couvert par le chiffrement AES-256 du document. FieldMDP est un contrôle de sécurité : il verrouille les champs nommés contre toute modification post-signature. Un verrouillage de champ qui ne correspond pas à l’ensemble des champs signés affaiblit ce contrôle : définis délibérément la portée du verrouillage. Traite toute valeur extraite d’un formulaire rempli comme une entrée non fiable. Consulte le modèle de sécurité du moteur dans /modules/core/security/.

Les structures de formulaire émises par ce module suivent le modèle de formulaire interactif d’ISO 32000-2 §12.7 : la racine AcroForm, les dictionnaires de champ et la hiérarchie de champs du document. Les apparences par widget sont émises sous forme de Form XObjects selon le §8.10, avec une documentation en ligne dans src/Form/. Il s’agit de faits d’implémentation vérifiés par tests/Unit/Form/. Ils ne constituent pas une affirmation de conformité PDF 2.0 de bout en bout. La conformité du document complet est validée par l’oracle et les suites golden dans /modules/core/conformance/.