Pular para o conteúdo

Contracts: 41 interfaces públicas (SPI)

NextPDF\Contracts é a interface pública de provedor de serviços (SPI): 41 interfaces e enums em src/Contracts/ com uma tag @stability explícita e uma promessa de compatibilidade com versões anteriores. Pacotes de extensão, pontes de framework e as edições Pro e Enterprise dependem desses tipos, nunca de classes concretas.

Terminal window
composer require nextpdf/core:^3

O motor expõe duas superfícies. Classes concretas em src/Core/, src/Html/ e src/Writer/ não têm promessa de compatibilidade e podem mudar entre versões menores. O namespace Contracts funciona de outra forma. Ele reúne um conjunto selecionado de tipos com assinaturas congeladas conforme o nível de estabilidade que declaram. Tudo fora do motor depende deste namespace, e de nada mais interno. Isso inclui as pontes para Laravel, Symfony e CodeIgniter, o shim compat-tcpdf, o NextPDF Server e as edições Pro e Enterprise.

Cada contrato declara um de quatro níveis em seu PHPDoc. Um contrato stable não permite nenhuma mudança incompatível em um lançamento menor ou de correção. Novos métodos só chegam com implementações padrão. Um contrato experimental pode mudar em um lançamento menor com um aviso de descontinuação. Um contrato deprecated indica seu substituto. Um pequeno conjunto é apenas contrato, como StreamingWriterInterface e CursorInterface. O tipo é publicado e congelado, mas nenhuma implementação de produção é fornecida ainda.

A lista de níveis autoritativa é docs/extension-points.json (versão do manifesto 3.0.0, 67 pontos publicados entre Contracts e Event). Um teste verificável por máquina, tests/Unit/Contracts/StabilityContractTest.php, lê esse manifesto e falha o build em cinco condições. Primeira, um tipo listado está ausente. Segunda, um tipo obtido por reflexão diverge do manifesto. Terceira, uma tag PHPDoc @stability se desvia do manifesto. Quarta, um contrato em src/Contracts/ está ausente do manifesto. Quinta, um tipo @internal vaza para ele. A superfície de contratos não consegue se desviar sem ser detectada.

Os contratos se dividem em nove domínios, cada um coberto por uma página dedicada: construção de documentos, assinatura, codificação de código de barras, tipografia, política de segurança, extração, observabilidade e streaming. A divisão reflete como você adota o motor. Você depende do contrato de documento para gerar arquivos Portable Document Format (PDF). Você depende dos contratos de assinatura para adicionar uma assinatura. Você depende dos contratos de política de segurança para restringir HTML não confiável.

A resolução opcional de implementações segue um único padrão em todo o motor. O core verifica se uma classe concreta existe com class_exists() e faz o cast para o contrato. LtvManagerInterface e PdfAManagerInterface resolvem suas implementações Pro dessa forma. O core permanece Apache-2.0 sem dependência rígida de código comercial.

ContratoTipoEstabilidadeDesdeDomínio
PdfDocumentInterfaceinterfacestable1.0.0document
DocumentFactoryInterfaceinterfacestable1.7.0document
ResettableServiceinterfacestable1.7.0document
OutputDestinationenumstable1.0.0document
Orientationenumstable1.0.0document
Alignmentenumstable1.0.0document
SignerInterfaceinterfacestable1.0.0signing
HsmSignerInterfaceinterfacestable1.0.0signing
DeferredSignerInterfaceinterfaceexperimental3.0.0signing
TimestampProviderInterfaceinterfaceexperimental3.0.0signing
LtvManagerInterfaceinterfacestable1.10.0signing
CryptoPolicyInterfaceinterfacestable1.9.0signing
Barcode1DEncoderInterfaceinterfacestable1.0.0barcode
Barcode2DEncoderInterfaceinterfacestable1.0.0barcode
BarcodeEncoderInterfaceinterfacestable3.0.0barcode
Gs1DataParserInterfaceinterfacestable1.0.0barcode
FontRegistryInterfaceinterfacestable1.7.0typography
TextPreprocessorInterfaceinterfacestable1.9.0typography
HtmlSecurityPolicyInterfaceinterfacestable3.1.0security-policy
ExternalResourcePolicyInterfaceinterfacestable4.0.0security-policy
InspectorInterfaceinterfaceexperimental2.2.0extraction
EmbeddingServiceInterfaceinterfaceexperimental2.1.0extraction
VectorIndexInterfaceinterfaceexperimental2.1.0extraction
JobNotificationInterfaceinterfaceexperimental2.2.0observability
SpectrumInterfaceinterfaceexperimental2.1.0observability
StreamingWriterInterfaceinterfaceexperimental3.1.0streaming
CursorInterfaceinterfaceexperimental3.1.0streaming

A tabela lista os contratos primários. Os tipos restantes, incluindo objetos de transferência de dados (DTOs) de objetos de valor (TextSegment, TextPreprocessResult), o sub-namespace EInvoice, enums de comportamento (DegradationPolicy, UnderlineStyle) e contratos de importação (ImportedFormObjectInterface, EmbeddedPdfObjectInterface, ChromeRenderResultInterface), estão documentados nas páginas de domínio em Veja também. A lista completa legível por máquina é docs/extension-points.json, espelhada em .ai/contracts-map.md.

examples/01-hello-world.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Hello World');
$doc->addPage();
$doc->setFont('helvetica', '', 24);
$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);
$doc->save(__DIR__ . '/output/01-hello-world.pdf');

Document::createStandalone() retorna um Document concreto que satisfaz PdfDocumentInterface. Use o type-hint da interface em seus serviços para manter os detalhes internos do motor intercambiáveis.

examples/14-worker-factory.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Core\PdfFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
// Created once at process boot in a RoadRunner/Swoole/Octane worker.
$fontRegistry = new FontRegistry();
$imageRegistry = new ImageRegistry(maxCacheBytes: 50 * 1024 * 1024);
$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$factory = PdfFactory::new()
->withCompress(true)
->withDocumentFactory($documentFactory);
for ($request = 1; $request <= 3; $request++) {
$doc = $factory->create();
$doc->setTitle("Worker Request #{$request}");
$doc->addPage();
$doc->setFont('helvetica', 'B', 16);
$doc->cell(0, 12, "Worker Request #{$request}", newLine: true);
$doc->save(__DIR__ . "/output/14-worker-request-{$request}.pdf");
}

DocumentFactory implementa DocumentFactoryInterface. Ele mantém singletons com tempo de vida do processo para FontRegistryInterface e ImageRegistryInterface e os injeta em cada Document descartável, de modo que um worker analise cada fonte uma única vez ao longo de milhares de requisições.

  • Um tipo que é apenas contrato compila, mas não tem suporte em tempo de execução. Uma expressão new contra StreamingWriterInterface ou CursorInterface não pode ter sucesso porque nenhuma classe as implementa ainda. Trate-as como uma interface de programação de aplicações (API) declarada antecipadamente.
  • A tag PHPDoc @stability é a fonte da verdade para um único tipo. docs/extension-points.json é a fonte da verdade para o conjunto. Quando os dois divergem, StabilityContractTest falha. Não esconda a divergência editando apenas um dos lados.
  • experimental não significa instável na prática. Significa que a promessa de compatibilidade é mais fraca. Leia o campo bc_promise de cada contrato em .ai/contracts-map.md antes de depender dele.
  • Uma classe @internal nunca é um contrato, mesmo que outros pacotes possam tecnicamente referenciá-la. O teste de estabilidade rejeita qualquer tipo @internal que apareça no manifesto.
  • Adicionar um método a uma interface stable é uma mudança incompatível para os implementadores, a menos que o método venha com uma implementação padrão. O motor adiciona capacidade por meio de novas interfaces, em vez de ampliar as existentes.

Programar contra Contracts não adiciona custo mensurável em tempo de execução: um type-hint de interface é resolvido em tempo de ligação, não a cada chamada. O performance_budget do exemplo de worker desta página é de 1500 ms de tempo total e 64 MB de pico ao longo de três documentos. A análise de fontes na primeira requisição domina esse orçamento. Requisições posteriores reutilizam o cache do registro e caem para milissegundos de um único dígito no trabalho atribuível a contratos. O modelo de custo é O(1) por despacho de contrato; o trabalho está na implementação concreta, documentada em cada página de domínio.

A SPI também é um limite de segurança. HtmlSecurityPolicyInterface e ExternalResourcePolicyInterface são contratos de negação por padrão que restringem o que o HTML não confiável pode fazer antes de chegar a um renderizador. CryptoPolicyInterface controla a seleção de algoritmo e de força de chave para assinatura e criptografia. Como esses itens são contratos, você pode fornecer uma política mais rigorosa sem criar um fork do motor. Fixe no nível stable qualquer política relevante para a segurança. Contratos de política experimentais podem mudar de forma entre lançamentos menores. As páginas de domínio de assinatura e de política de segurança trazem o modelo de ameaças completo e as referências normativas.

Esta visão geral não faz nenhuma afirmação normativa direta; cada página de domínio renderiza seu próprio bloco citations. Os contratos de assinatura são mapeados para a ISO 32000-2 §12.8 (assinaturas digitais) e a ETSI EN 319 142 (baselines PAdES). O gerenciador de PDF/A é mapeado para a ISO 19005-4. Consulte as páginas de assinatura, política de segurança e extração para ver tabelas de conformidade em nível de cláusula.

As edições Pro e Enterprise fornecem o código de produção por trás de vários contratos do core: LtvManagerInterface (validação de longo prazo), PdfAManagerInterface (imposição de PDF/A), o Módulo de Segurança de Hardware (HSM) e os assinadores diferidos, os codificadores de código de barras e os contratos de embedding e de índice vetorial. O core publica e congela a interface; o pacote Premium fornece a implementação. Isso mantém o motor de código aberto Apache-2.0 e oferece às implantações comerciais uma atualização imediata sem alteração de API.

  • Contracts / Document — contratos de documento PDF, de fábrica e de registro.
  • Contracts / Signing — contratos de assinador, HSM, carimbo de data/hora e validação de longo prazo (LTV).
  • Contracts / Security Policy — contratos de criptografia, HTML e política de recursos.
  • Contracts / Typography — contratos de registro de fontes e de pré-processamento de texto.
  • Contracts / Extraction — contratos de inspetor, PDF/A, embedding e nota fiscal eletrônica.
  • Core — classes concretas que satisfazem esses contratos.
  • Event — a contraparte da SPI de eventos publicada junto com Contracts.