Lewati ke konten

Pemicu aksi dan pendengar peristiwa

NextPDF memicu peristiwa siklus hidup melalui sistem dalam NextPDF\Event yang kompatibel dengan PHP Standards Recommendation 14 (PSR-14). Daftarkan pendengar, tetapkan prioritas, dan tanggapi saat dokumen dibuat, halaman ditambahkan, fon dimuat, penandatanganan atau enkripsi berjalan, bita ditulis, atau keluaran dimulai. Hentikan rantai hanya saat benar-benar diperlukan.

Terminal window
composer require nextpdf/core:^3

Sistem peristiwa memiliki dua komponen publik. ListenerProvider memetakan setiap kelas peristiwa ke daftar pendengar callable yang sudah diurutkan. EventDispatcher menelusuri daftar tersebut dan memanggil tiap pendengar menurut urutan prioritas. Kedua kelas bersifat final, jadi perluas perilakunya melalui komposisi, bukan subkelas.

Kedua kelas sesuai dengan PSR-14 melalui duck typing. EventDispatcher::dispatch() menggunakan signature dispatch() PSR-14 dan mengembalikan peristiwa setelah setiap pendengar berjalan. ListenerProvider::getListenersForEvent() menggunakan signature provider PSR-14. NextPDF tidak memerlukan paket PSR-14. Jika proyek Anda memasangnya, antarmukanya tetap selaras.

Dua perilaku penting bagi penulis ekstensi:

  • Pendengar wildcard. Saat menyelesaikan daftar pendengar, provider menelusuri kelas induk dan antarmuka peristiwa. Pasangkan pendengar ke kelas dasar AbstractEvent untuk mengamati setiap peristiwa siklus hidup. Pasangkan satu pendengar ke antarmuka untuk menangkap satu keluarga.
  • Prioritas dan propagasi. Prioritas yang lebih tinggi berjalan lebih dulu. Prioritas yang sama mempertahankan urutan pendaftaran. Setiap peristiwa yang memperluas AbstractEvent dapat dihentikan. Pendengar dapat memanggil stopPropagation(), lalu dispatcher melewati pendengar yang tersisa.

Dispatcher memiliki jalur cepat tanpa overhead. Ketika tidak ada pendengar yang terikat ke suatu kelas peristiwa atau kelas induk mana pun, dispatch() langsung kembali setelah satu pemeriksaan hasListeners().

PeristiwaRuang namaDipicu saatStabilitas
DocumentCreatedEventNextPDF\Event\DocumentKonstruksi dokumen telah selesaieksperimental
PageAddedEventNextPDF\Event\DocumentHalaman selesai diinisialisasi sepenuhnyaeksperimental
ContentRenderedEventNextPDF\Event\ContentKonten dirender ke halamaneksperimental
FontLoadedEventNextPDF\Event\ContentKeluarga dan gaya fon dimuat untuk pertama kalieksperimental
SignatureAppliedEventNextPDF\Event\SecurityBita tanda tangan disematkaneksperimental
EncryptionAppliedEventNextPDF\Event\SecurityEnkripsi dikonfigurasieksperimental
PdfSerializedEventNextPDF\Event\WriterSerialisasi selesaieksperimental
DocumentOutputEventNextPDF\Event\DocumentPengiriman keluaran akan segera dimulaieksperimental

Dispatcher, provider, antarmuka penanda, dan kelas dasar bersifat stable (sejak 3.0.0). Muatan peristiwa bersifat experimental. Argumen konstruktor dan properti readonly-nya dapat berubah dalam rilis minor. Rilis tambalan hanya bersifat menambahkan. Saat mengikat ke nama properti muatan, pertimbangkan batasan tersebut.

NextPDF\Event\ListenerProvider (stabil, final):

MetodeMengembalikanTujuan
addListener(string $eventClass, callable $listener, int $priority = 0)voidDaftarkan pendengar; prioritas yang lebih tinggi berjalan lebih dulu. Melempar InvalidConfigException ketika kelasnya kosong.
getListenersForEvent(EventInterface $event)list<callable>Menyelesaikan daftar pendengar, termasuk pendaftaran pada induk dan antarmuka.
hasListeners(string $eventClass)boolPeriksa hierarki kelas tanpa overhead.
getListenerCount(string $eventClass)intHanya menghitung pendaftaran langsung.
clearListeners()voidAtur ulang provider.

NextPDF\Event\EventDispatcher (stabil, final):

MetodeMengembalikanTujuan
dispatch(EventInterface $event)EventInterfaceMemanggil pendengar menurut urutan prioritas, menghormati penghentian propagasi, dan mengembalikan peristiwa.
getListenerProvider()ListenerProviderAkses provider untuk menambahkan pendengar saat runtime.

Dokumen yang memicu peristiwa menggunakan NextPDF\Event\EventAwareDocumentTrait. Metode setEventDispatcher()-nya menghubungkan dispatcher ke satu dokumen. Tanpa dispatcher, setiap helper dispatch tidak melakukan apa pun.

<?php
declare(strict_types=1);
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
use NextPDF\Event\Security\SignatureAppliedEvent;
$listeners = new ListenerProvider();
$listeners->addListener(
SignatureAppliedEvent::class,
static function (SignatureAppliedEvent $event): void {
\error_log("Signed at level {$event->signatureLevel} by {$event->signerName}");
},
priority: 100,
);
$dispatcher = new EventDispatcher($listeners);

Pendengar audit produksi ini memakai prioritas tinggi agar berjalan lebih dulu, menulis log terstruktur, dan menambahkan pendengar penangkap-semua pada kelas dasar demi kelengkapan.

<?php
declare(strict_types=1);
use NextPDF\Event\AbstractEvent;
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
use NextPDF\Event\Security\EncryptionAppliedEvent;
use NextPDF\Event\Security\SignatureAppliedEvent;
use Psr\Log\LoggerInterface;
final class SecurityAuditSubscriber
{
public function __construct(private readonly LoggerInterface $logger) {}
public function register(ListenerProvider $listeners): EventDispatcher
{
$listeners->addListener(
SignatureAppliedEvent::class,
function (SignatureAppliedEvent $event): void {
$this->logger->info('signature.applied', [
'level' => $event->signatureLevel,
'signer' => $event->signerName,
]);
},
priority: 1000,
);
$listeners->addListener(
EncryptionAppliedEvent::class,
function (EncryptionAppliedEvent $event): void {
$this->logger->info('encryption.applied', [
'algorithm' => $event->algorithm,
]);
},
priority: 1000,
);
// Catch-all: observe every lifecycle event for trace completeness.
$listeners->addListener(
AbstractEvent::class,
fn (AbstractEvent $event): mixed
=> $this->logger->debug('lifecycle', ['event' => $event->getEventName()]),
priority: -1000,
);
return new EventDispatcher($listeners);
}
}
  • Kelas final. EventDispatcher dan ListenerProvider bersifat final. Gunakan keduanya melalui komposisi; jangan membuat subkelasnya.
  • Kelas peristiwa kosong melempar. addListener('', ...) melempar InvalidConfigException. Selalu berikan konstanta class-string.
  • Biaya wildcard. Pendengar pada AbstractEvent dipicu untuk setiap peristiwa. Beri pendengar penangkap-semua prioritas rendah, dan jaga agar tetap ringan.
  • Mutasi keluaran. DocumentOutputEvent membawa bita Portable Document Format (PDF). Mesin membacanya kembali setelah dispatch. Jika Anda mengubah bita tersebut, Anda memperoleh kendali yang besar sekaligus risiko yang besar. Offset bita yang salah merusak PDF dan dapat memutus tanda tangan. Sebaiknya hanya mengamati, kecuali Anda sepenuhnya mengendalikan hasilnya demi determinisme dan tanda tangan.
  • Tanpa dispatcher, tanpa peristiwa. Dokumen yang tidak memiliki dispatcher yang diatur melalui EventAwareDocumentTrait tidak memicu peristiwa apa pun. Ini adalah jalur tanpa overhead yang disengaja, bukan kesalahan penyiapan.

Jalur cepatnya adalah satu pemeriksaan rantai induk hasListeners(). Tanpa pendengar, dispatch nyaris gratis. Provider menyimpan cache daftar pendengar yang terurut per kelas peristiwa dan menghapus cache itu hanya ketika pendengar berubah. Jaga agar pendengar tidak melakukan operasi yang memblokir karena semuanya berjalan inline pada jalur rendering.

SignatureAppliedEvent dan EncryptionAppliedEvent adalah jangkar audit. Daftarkan pendengar berprioritas tinggi untuk mencatat penandatanganan dan enkripsi ke penyimpanan yang dapat memperlihatkan upaya pengubahan. Jangan menghentikan rantai pada peristiwa keamanan kecuali Anda berniat membungkam pendengar berikutnya. Menghentikannya dapat secara diam-diam menonaktifkan kait audit yang berjalan setelahnya.

Halaman ini tidak membuat klaim normatif apa pun di luar kompatibilitas PSR-14. Kompatibilitas itu berbasis duck typing dan tidak memerlukan paket PSR-14.

NextPDF Enterprise menyertakan pendengar yang telah diaudit untuk peristiwa tanda tangan dan enkripsi yang memasok log audit yang dapat memperlihatkan upaya pengubahan. Karena kontrak pendengar adalah application programming interface (API) peristiwa publik, pendengar Anda sendiri dapat berdampingan dengan pendengar Enterprise pada provider yang sama.

Glosarium mendefinisikan istilah pendengar peristiwa, dispatcher peristiwa, listener provider, dan peristiwa yang dapat dihentikan yang digunakan pada halaman ini. Lihat glosarium yang diterbitkan untuk definisi kanonis.