Pular para o conteúdo

Criação de extensões: visão geral da SPI pública

O NextPDF expõe um conjunto pequeno e intencional de contratos públicos nos namespaces NextPDF\Contracts e NextPDF\Event. Implemente esses contratos para adicionar fontes, interceptar texto, observar o ciclo de vida do documento ou fornecer seu próprio back end de assinatura sem fazer fork do engine.

Terminal window
composer require nextpdf/core:^3

O NextPDF separa a interface pública de provedor de serviço (SPI) do código interno. A SPI é o conjunto de tipos que você pode implementar ou observar. Todo o resto é privado e pode mudar sem aviso prévio.

A SPI pública tem três formas:

  • Contratos de registro. Serviços com duração de processo que você configura antes de criar documentos; FontRegistryInterface e ImageRegistryInterface são os principais exemplos. Registre os recursos; o engine os lê.
  • Contratos de estratégia. Hooks de responsabilidade única que o engine chama durante uma renderização. O TextPreprocessorInterface trata da interceptação de texto em tempo de layout, e o HtmlSecurityPolicyInterface controla recursos de Hypertext Markup Language (HTML). Você fornece o comportamento, e o engine o invoca.
  • Contratos de assinatura. Back ends criptográficos. SignerInterface, HsmSignerInterface e DeferredSignerInterface permitem que você forneça a custódia da chave e a produção da assinatura. O engine constrói a estrutura Cryptographic Message Syntax (CMS), e o seu código mantém a chave.

Um sistema de eventos separado em NextPDF\Event, compatível com a PHP Standard Recommendation 14 (PSR-14), cuida da observação. Os eventos de ciclo de vida permitem que você reaja à criação de documentos, a novas páginas, ao carregamento de fontes, à assinatura e à gravação. Eles não alteram o comportamento do engine.

Cada contrato traz uma tag @stability no PHPDoc de seu código-fonte: stable, experimental ou deprecated. A tag e a promessa de compatibilidade retroativa de cada contrato indicam o nível de mudança esperado. Consulte Regras de estabilidade da SPI para conhecer a política completa.

RecursoContrato públicoEstabilidade
Registro e busca de fontesNextPDF\Contracts\FontRegistryInterfacestable (desde 1.7.0)
Cache e decodificação de imagensNextPDF\Contracts\ImageRegistryInterfacestable (desde 2.0.0)
Interceptação de texto em tempo de layoutNextPDF\Contracts\TextPreprocessorInterfacestable (desde 1.9.0)
Controle de recursos de HTMLNextPDF\Contracts\HtmlSecurityPolicyInterfacestable (desde 3.1.0)
Conexão da fábrica de documentosNextPDF\Contracts\DocumentFactoryInterfacestable (desde 1.7.0)
Assinatura síncronaNextPDF\Contracts\SignerInterfacestable (desde 1.0.0)
Assinatura com suporte de hardwareNextPDF\Contracts\HsmSignerInterfacestable (desde 1.0.0)
Assinatura diferida e em loteNextPDF\Contracts\DeferredSignerInterfaceexperimental (desde 3.0.0)
Carimbo de tempo RFC 3161NextPDF\Contracts\TimestampProviderInterfaceexperimental (desde 3.0.0)
Observação do ciclo de vidaNextPDF\Event\* (compatível com PSR-14)dispatcher stable; payloads experimental

Os tipos a seguir são internos. Não os importe, não os herde nem dependa deles:

  • Qualquer classe fora dos namespaces NextPDF\Contracts e NextPDF\Event, a menos que o PHPDoc dela traga uma tag @stability.
  • O código concreto do engine, incluindo o parser de HTML, o writer, o pipeline de layout e o subsetter de fontes.
  • Os pacotes NextPDF Pro e NextPDF Enterprise. As classes internas deles não fazem parte da superfície de código aberto. Quando uma edição paga fornece uma implementação de SPI, consuma o contrato público, não o tipo interno dela.

O mapa de contratos gerado é a fonte de autoridade e é reconstruído a partir do código-fonte a cada release. Trate a tag PHPDoc @stability em cada arquivo de interface como a única fonte da verdade. Use a tabela acima como apoio de leitura.

Registre uma fonte e, em seguida, observe seu carregamento. As duas etapas usam apenas tipos públicos.

<?php
declare(strict_types=1);
use NextPDF\Contracts\FontRegistryInterface;
use NextPDF\Event\Content\FontLoadedEvent;
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
/** @var FontRegistryInterface $fonts */
$fonts->register('/srv/fonts/Inter-Regular.ttf', 'Inter');
$listeners = new ListenerProvider();
$listeners->addListener(
FontLoadedEvent::class,
static function (FontLoadedEvent $event): void {
\error_log("Font loaded: {$event->family} {$event->style}");
},
);
$dispatcher = new EventDispatcher($listeners);

Em um worker de longa duração, crie os registries uma única vez na inicialização, bloqueie-os e injete um dispatcher compartilhado por meio da fábrica de documentos.

<?php
declare(strict_types=1);
use NextPDF\Contracts\DocumentFactoryInterface;
use NextPDF\Contracts\FontRegistryInterface;
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
use Psr\Log\LoggerInterface;
final class DocumentBootstrap
{
public function __construct(
private readonly FontRegistryInterface $fonts,
private readonly DocumentFactoryInterface $factory,
private readonly LoggerInterface $logger,
) {}
public function warmup(): EventDispatcher
{
$this->fonts->warmup([
'/srv/fonts/Inter-Regular.ttf',
'/srv/fonts/Inter-Bold.ttf',
]);
$this->fonts->lock();
$listeners = new ListenerProvider();
$listeners->addListener(
\NextPDF\Event\Security\SignatureAppliedEvent::class,
fn (object $event): mixed => $this->logger->info('Signature applied'),
);
return new EventDispatcher($listeners);
}
}
  • Bloqueio do registry. Após FontRegistryInterface::lock(), os métodos que alteram o estado lançam LogicException. Bloqueie somente depois que o warmup terminar.
  • Incompatibilidade de estabilidade. Um contrato experimental pode mudar em um release menor. Verifique a estabilidade declarada antes de depender do contrato em produção.
  • Disciplina de namespace. Um tipo fora de NextPDF\Contracts ou NextPDF\Event sem tag @stability é interno, mesmo que seja tecnicamente public.

A SPI tem custo zero quando não é usada. Se nenhum listener estiver registrado para uma classe de evento, o dispatcher de eventos retorna imediatamente após uma única verificação hasListeners(). Os registries guardam dados PHP puros e oferecem suporte a warmup na inicialização para diluir a latência da primeira requisição.

Os contratos de assinatura são a superfície sensível à segurança. O HsmSignerInterface exige que a chave privada nunca saia do limite do hardware. A implementação deve respeitar esse requisito. Consulte o contrato de provedor do sistema de gerenciamento de chaves (KMS) para conhecer o contrato de back end de assinatura de terceiros e o respectivo modelo de ameaças.

Nenhuma afirmação normativa é feita nesta página de visão geral. A conformidade de cada contrato, incluindo PDF Advanced Electronic Signatures (PAdES) e gerenciamento de chaves, está documentada nas páginas de SPI correspondentes.

O NextPDF Pro e o NextPDF Enterprise fornecem implementações de produção para vários contratos de assinatura e validação, incluindo assinatura com suporte de sistema de gerenciamento de chaves. Você depende do contrato público enquanto a edição fornece a implementação, de modo que o código permanece portável entre as edições.

O glossário define SPI, ponto de extensão, tag de estabilidade e promessa de compatibilidade retroativa; consulte o glossário publicado para cada definição canônica.