Ir al contenido

Support: utilidades compartidas + Clock + Sleeper

El módulo Support contiene las utilidades transversales que el motor usa internamente. También expone una pequeña superficie pública: el reloj de sistema PSR-20, la canalización de recopilación de advertencias y las primitivas de serialización de PDF. La mayor parte del espacio de nombres es infraestructura interna. Esta página documenta las partes en las que puede apoyarse el código externo y señala cuáles son de uso exclusivamente interno.

Ventana de terminal
composer require nextpdf/core:^3

Reloj (PSR-20). SystemClock implementa Psr\Clock\ClockInterface. Su now() devuelve la hora actual como un DateTimeImmutable. El modelo PSR-20 define una interfaz de reloj con una sola operación de lectura. Esa operación devuelve la hora actual como un valor de fecha y hora inmutable (PSR-20 psr_20_clock#2.1). SystemClock es el valor predeterminado. El motor lo usa cuando no se inyecta ningún reloj. Para fijar la hora en pruebas, se debe inyectar en su lugar un reloj congelado. Este debe implementar la misma interfaz. Combinar el reloj con Config::deterministic permite obtener una salida idéntica byte a byte.

Canalización de advertencias. WarningCollector es el transporte principal en memoria para los problemas de renderizado no fatales. El motor añade un Warning por cada degradación determinista. Algunos ejemplos son una columna de tabla comprimida, una fuente sin resolver o un glifo ausente. El código llamador las lee después de la generación a través de Document::getWarnings(). Un Warning es un objeto de valor inmutable. Lleva un WarningCode, una WarningSeverity (warning o degraded), la página, el tipo de elemento, el id de la función, un indicador de paridad degradada, un mensaje, un DegradationImpact y un id de capacidad opcional. WarningCode es un enum respaldado por strings con identificadores estables. Llevan el prefijo NEXTPDF_W_ (por ejemplo NEXTPDF_W_FONT_UNRESOLVED). El prefijo permite compararlos con seguridad en las pruebas. addWithPolicy() aplica la DegradationPolicy activa. Bajo una política estricta, un impacto de cumplimiento, semántico o de bloqueo lanza DegradedException. Bajo una política equilibrada, solo un impacto de bloqueo lanza. Una política permisiva nunca lanza excepciones.

Primitivas de PDF. PdfStringEscaper es la única fuente de verdad para el escapado de strings y nombres de PDF. escapeLiteral() escapa los caracteres que exige un string literal de PDF (barra invertida, paréntesis, CR, LF, HT, BS, FF) y elimina NUL. escapeName() codifica en hexadecimal los bytes fuera del ASCII imprimible y del conjunto de delimitadores de PDF para un objeto de nombre. BinaryBuffer es un acumulador binario optimizado para escritura. Construye objetos y streams de PDF. Su modo de streaming vuelca a un manejador php://temp para documentos grandes. También admite las operaciones de rango de bytes que necesita la incrustación de firmas. PdfOperators contiene los strings de formato de los operadores de stream de contenido (trazado, texto, estado gráfico, fuente). Las capas de dibujo y de análisis los comparten.

BinaryBuffer, PdfOperators y la mayor parte del resto de NextPDF\Support\ son infraestructura interna. Las capas de escritura y de dibujo los consumen. Se documentan aquí por exhaustividad y para facilitar la auditoría. No forman parte de la superficie de API pública con soporte. En su lugar, conviene apoyarse en la fachada Document y en el espacio de nombres Contracts. SystemClock, WarningCollector, Warning, WarningCode, WarningSeverity y DegradationImpact son los miembros expuestos al público.

SímboloTipoVisibilidadMiembros clave
NextPDF\Support\SystemClockclase finalpúblicanow(): DateTimeImmutable (PSR-20 ClockInterface)
NextPDF\Support\WarningCollectorclase finalpúblicaadd(), emit(), addWithPolicy(), getWarnings(), hasWarnings(), hasDegradedParity(), clear()
NextPDF\Support\Warningclase final de solo lecturapública$code, $severity, $page, $elementType, $featureId, $degradedParity, $message, $impact, $capabilityId
NextPDF\Support\WarningCodeenum de stringpúblicaidentificadores NEXTPDF_W_* estables
NextPDF\Support\WarningSeverityenum de stringpúblicaWarning, Degraded
NextPDF\Support\DegradationImpactenum de stringpúblicaCosmetic, LayoutRisk, SemanticLoss, ComplianceRisk, Blocking
NextPDF\Support\PdfStringEscaperclase final de solo lecturainternaescapeLiteral(), escapeName() (estáticos)
NextPDF\Support\BinaryBufferclase finalinternawrite(), writeStream(), replaceAt(), extract(), enableStreaming(), getContents()
NextPDF\Support\PdfOperatorsclase finalinternaconstantes de strings de formato de operadores de stream de contenido

Leer las advertencias recopiladas después de la generación.

<?php
declare(strict_types=1);
use NextPDF\Support\WarningCollector;
$collector = new WarningCollector();
// The engine appends warnings during rendering. After generation:
if ($collector->hasWarnings()) {
foreach ($collector->getWarnings() as $warning) {
\printf(
"[%s] page %d: %s\n",
$warning->code->value,
$warning->page,
$warning->message,
);
}
}

Inyectar un reloj para obtener una hora determinista e interpretar una advertencia de paridad degradada como un fallo de compilación.

<?php
declare(strict_types=1);
use NextPDF\Support\SystemClock;
use NextPDF\Support\WarningCollector;
use Psr\Clock\ClockInterface;
// Production uses the real system clock.
$clock = new SystemClock();
$now = $clock->now(); // DateTimeImmutable
$epoch = $now->getTimestamp(); // int
// In tests, swap in any ClockInterface that returns a fixed instant
// (the parameter is typed to the PSR-20 interface, not SystemClock).
function buildReport(ClockInterface $clock): \DateTimeImmutable
{
return $clock->now();
}
$collector = new WarningCollector();
// ... run generation ...
if ($collector->hasDegradedParity()) {
throw new \RuntimeException('Output parity degraded; failing the build.');
}
  • SystemClock::now() devuelve un nuevo DateTimeImmutable en cada llamada. No asumir que dos llamadas devuelven el mismo instante. Para una hora fija, inyectar un reloj congelado.
  • WarningCollector está en memoria y es por instancia. Es el canal principal. El sidecar JSON y el STDERR de la CLI se emiten en el límite de salida, no por el propio recolector.
  • addWithPolicy() puede lanzar DegradedException a mitad del renderizado bajo una política estricta. Capturarla en el límite de generación si se necesita una salida parcial.
  • WarningCode expone valores que son strings estables: comparar por el caso del enum, no por el texto del mensaje, que es legible por humanos y puede cambiar.
  • BinaryBuffer::getLength() es un alias intencional de getOffset() por paridad con la interfaz de stream. Ambos devuelven el mismo recuento de bytes.
  • Tratar PdfStringEscaper, BinaryBuffer y PdfOperators como internos. No están cubiertos por la promesa de estabilidad de la API pública.

SystemClock::now() es una única construcción de objeto, O(1). Los añadidos de WarningCollector son inserciones en lista O(1) amortizadas. getWarnings() devuelve la lista subyacente. BinaryBuffer en modo de streaming limita la memoria a su umbral maxmemory (predeterminado 2 MB) antes de volcar al disco, lo que mantiene plano el pico de memoria para documentos grandes. El performance_budget predeterminado para esta página de referencia es wall_ms: 1500, peak_mb: 64.

La superficie del reloj permite eliminar el indeterminismo del reloj de pared de la salida firmada y con marca de tiempo al inyectar un reloj fijo junto con Config::deterministic. PdfStringEscaper es el único escapador auditable para la salida de strings y nombres de PDF. Enrutar toda la emisión de strings a través de él evita la inyección de contenido mediante paréntesis o delimitadores sin escapar en texto proporcionado por el usuario. Las advertencias pueden llevar detalles derivados del documento (tipos de elemento, ids de función). Sanear la salida de advertencias antes de reenviarla a un destino de logs de baja confianza.

EspecificaciónCláusulaTema
PSR-20 (PHP-FIG)psr_20_clock#2.1La operación de lectura del reloj devuelve una fecha y hora inmutable
ISO 32000-2:2020§7.3.4.2 / §7.3.5Escapado de strings literales y de objetos de nombre (parafraseado; texto de la norma ISO no citado, sin chunk fijado)

SystemClock implementa la ClockInterface de PSR-20. El escapador sigue las reglas de caracteres de strings literales y de objetos de nombre de PDF. El texto de la norma ISO se parafrasea según la política de citas del sitio y no se fija ningún chunk literal.

  • /modules/core/exception/DegradedException lanzada por addWithPolicy()
  • /modules/core/contracts/DegradationPolicy, Capability
  • /modules/core/observability/ — reenvío de advertencias y métricas
  • /modules/core/config/Config::deterministic se combina con el reloj
  • /modules/core/writer/ — consumidor interno de BinaryBuffer y PdfOperators

Glosario: PSR-20 · política de degradación · objeto de valor