Aller au contenu

Config : configuration immuable du document

Config est l’objet de configuration immuable du document. Chaque changement de paramètre renvoie une nouvelle instance via un wither typé ; la configuration peut donc être partagée en toute sécurité entre documents et workers. NextPdfConfig est une classe statique distincte qui porte les limites de sécurité du parseur CSS à l’échelle du processus.

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

Les deux classes sont incluses dans le package du cœur. Config existe depuis la 1.7.0. NextPdfConfig existe depuis la 2.2.0.

Config est une classe final readonly marquée #[DisallowDynamicProperties]. Elle ne contient que des scalaires et des value objects final readonly ; le graphe entier est donc profondément immuable. Il n’existe pas de setter générique with(string, mixed). Chaque modification passe par son propre wither typé dédié. On en compte 19 — withPageSize(), withMargins(), withCompress(), jusqu’à withOutputColorProfile() — et chacun reconstruit l’objet avec des arguments nommés. La reconstruction par arguments nommés est délibérée : l’ajout d’un paramètre au constructeur ne décale jamais silencieusement un argument positionnel dans un wither existant. Un test de compatibilité fige par réflexion la liste des méthodes publiques et le nombre de paramètres. Toute dérive de signature fait échouer la CI.

Le constructeur expose la surface de configuration avec des valeurs par défaut sûres :

ParamètreTypeValeur par défaut
pageSizePageSizePageSize(595.276, 841.890, 'A4')
marginsMarginMargin(10.0, 10.0, 10.0, 10.0)
compressbooltrue
autoPageBreakbooltrue
breakMarginfloat20.0
langstring (BCP-47)''
fontsDirectorystring''
imageCacheBytesint52_428_800
deterministic?DeterministicSettingsnull
cryptoPolicy?CryptoPolicyInterfacenull
branding?BrandingConfignull
degradationPolicyDegradationPolicyBalanced
degradationOverridesarray<string, DegradationPolicy>[]
cssRenderingModeCssRenderingModeNormal
auditCollector?AuditCollectornull
cssFeatureFlags?CssFeatureFlagsnull
cssLayoutModeCssLayoutModeStreaming
retainedNodeBudgetint50_000
layoutTelemetryCollector?LayoutTelemetryCollectornull
telemetryEnabledboolfalse
outputColorProfileOutputColorProfileDeviceRGB

Trois paramètres sont bornés. retainedNodeBudget accepte la plage fermée [5_000, 100_000] (constantes RETAINED_NODE_BUDGET_MIN, RETAINED_NODE_BUDGET_MAX, défaut RETAINED_NODE_BUDGET_DEFAULT). withRetainedNodeBudget() lève InvalidArgumentException en dehors de cette plage. effectiveRetainedNodeBudget() renvoie 0 en mode streaming. Sinon, elle applique un clamp pour ramener la valeur dans la plage, à titre de vérification de défense en profondeur contre une construction positionnelle directe. validate() impose les invariants inter-champs que les withers par champ ne peuvent pas voir isolément. CssLayoutMode::Auto est réservé et lève NotImplementedException. CssRenderingMode::Safe combiné avec CssLayoutMode::Retained lève IncompatibleRenderingModeException. auditCollector est le collecteur de rapport d’audit fourni par l’appelant. Il n’est consommé que lorsque cssRenderingMode vaut CssRenderingMode::Audit, où il pilote un bloc XMP privé nextpdfAudit ; dans les autres modes de rendu, il est ignoré.

NextPdfConfig répond à un besoin différent. C’est un utilitaire statique non instanciable qui porte les limites du parseur CSS à l’échelle du processus. Ces limites sont le nombre maximal d’octets de feuille de style (512 Ko par défaut) et la profondeur maximale d’imbrication CSS (8 par défaut). Ce sont des garde-fous de sécurité contre l’épuisement des ressources provoqué par une entrée hostile, et non des préférences propres au document. C’est pour cette raison qu’elles sont statiques. Les setters appliquent un clamp avec un plancher (max(1024, …) octets, max(1, …) pour la profondeur). resetDefaults() est marquée @internal et réservée aux tests.

SymboleNatureMembres clés
NextPDF\Core\Configclasse final readonly21 paramètres de constructeur ; 19 withers typés ; validate(), isSafeMode(), isRetainedMode(), effectiveRetainedNodeBudget(), resolveFeatureFlags()
NextPDF\Core\Config::RETAINED_NODE_BUDGET_MINconst int5_000
NextPDF\Core\Config::RETAINED_NODE_BUDGET_MAXconst int100_000
NextPDF\Core\Config::RETAINED_NODE_BUDGET_DEFAULTconst int50_000
NextPDF\Core\NextPdfConfigclasse finalsetMaxCssBytes(), getMaxCssBytes(), setMaxCssNestingDepth(), getMaxCssNestingDepth(), resetDefaults() (@internal)

Withers : withPageSize, withMargins, withCompress, withAutoPageBreak, withLang, withFontsDirectory, withImageCacheBytes, withDeterministic, withCryptoPolicy, withBranding, withDegradationPolicy, withDegradationOverride, withCssRenderingMode, withCssFeatureFlags, withCssLayoutMode, withRetainedNodeBudget, withLayoutTelemetryCollector, withTelemetryEnabled, withOutputColorProfile.

Construis une configuration à partir des valeurs par défaut et ajuste deux paramètres.

<?php
declare(strict_types=1);
use NextPDF\Core\Config;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
$config = (new Config())
->withPageSize(PageSize::Letter())
->withMargins(Margin::uniform(18.0));
// Each wither returns a new instance; the original is unchanged.

Crée une configuration déterministe et validée, puis resserre les limites CSS à l’échelle du processus pour une entrée non fiable.

<?php
declare(strict_types=1);
use NextPDF\Core\Config;
use NextPDF\Core\CssRenderingMode;
use NextPDF\Core\NextPdfConfig;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
$config = (new Config())
->withPageSize(PageSize::A4())
->withMargins(Margin::symmetric(vertical: 20.0, horizontal: 15.0))
->withCompress(true)
->withCssRenderingMode(CssRenderingMode::Safe);
// Reject mutually exclusive modes before generation starts.
$config->validate();
// Process-wide hardening for hostile stylesheet input.
NextPdfConfig::setMaxCssBytes(262_144); // 256 KB
NextPdfConfig::setMaxCssNestingDepth(4);
  • Config n’applique aucune règle inter-champs tant que tu n’appelles pas validate(). Un wither ne peut pas détecter à lui seul un conflit Safe + Retained ; appelle validate() avant la génération.
  • withRetainedNodeBudget() est le seul wither qui peut échouer sur sa seule entrée (InvalidArgumentException en dehors de [5_000, 100_000]).
  • effectiveRetainedNodeBudget() renvoie 0 en mode streaming, ce qui signale « le budget de niveau 1 ne s’applique pas » — et non « aucun nœud autorisé ».
  • withLayoutTelemetryCollector() et withTelemetryEnabled() sont indépendants. Câbler un collecteur sans activer la télémétrie le prépare pour une future canary. Activer la télémétrie sans collecteur est valide et constitue un no-op.
  • NextPdfConfig est statique et s’applique à l’échelle du processus. Un changement affecte tous les documents du processus jusqu’à réinitialisation. C’est un garde-fou de sécurité, pas une préférence propre au document. Garde-le en dehors des chemins de mutation par requête.
  • NextPdfConfig::resetDefaults() est @internal. Ne l’appelle pas dans du code de production.

Un wither alloue un seul nouveau Config et copie les références vers les value objects existants. C’est en O(1) par rapport au nombre de paramètres et cela n’effectue aucune copie profonde, car chaque valeur conservée est elle-même immuable. Les accesseurs de NextPdfConfig sont des lectures de champ statique, en O(1). Le performance_budget par défaut de cette page de référence est wall_ms: 1500, peak_mb: 64.

NextPdfConfig existe pour borner la consommation de ressources du parseur. Le plafond par défaut de 512 Ko pour la feuille de style et la limite de profondeur d’imbrication de 8 protègent contre un déni de service provoqué par du CSS pathologiquement volumineux ou profondément imbriqué. Abaisse les deux limites lorsque la source de la feuille de style n’est pas fiable. Config::cryptoPolicy porte une CryptoPolicyInterface pour l’application de la politique cryptographique (par exemple, un profil FIPS). Elle vaut null par défaut et se définit via withCryptoPolicy(). Config::deterministic contrôle les horodatages et identifiants fixes pour une sortie strictement identique à l’octet près et est requis pour les builds reproductibles.

Ce module relève de la configuration du moteur et ne porte aucune citation de norme normative. Les paramètres qui pilotent un comportement normatif — outputColorProfile (émission d’OutputIntent), cryptoPolicy (FIPS), deterministic (builds reproductibles) — sont documentés au regard de leurs clauses dans les modules qui les émettent.

  • /modules/core/document/ — le consommateur de Config
  • /modules/core/valueobjects/PageSize, Margin utilisés par Config
  • /modules/core/contracts/CryptoPolicyInterface, DegradationPolicy
  • /modules/core/event/Config porté sur DocumentCreatedEvent
  • /modules/core/exception/InvalidConfigException, NotImplementedException

Glossaire : wither typé · politique de dégradation · value object