A WHMCS-style hook system. Register callbacks against named hook points;
core code fires them at the right moments. A throwing callback is logged and
skipped — a broken hook can never break billing or provisioning. Hook names are
case-insensitive.
Differences from WHMCS
Many hook names are the WHMCS ones, and several points fire under both a PNLCS name and the
WHMCS alias, but this is not a drop-in copy of WHMCS:
Parameters are PNLCS model objects ($vars['invoice'] is an App\Models\Invoice), not the
WHMCS arrays of ids and fields.
Only the points listed on this page fire. There is no InvoiceRefunded (use RefundIssued),
AcceptQuote (use QuoteAccepted), TicketUserReply or TicketAdminReply (use
TicketReplied and its isStaffReply).
Each file simply calls add_hook(...) at top level. Files are loaded once per
request during application boot. A file that throws while loading is logged and skipped.
Points marked "event" are fired from a Laravel event in app/Events/; the event's public
properties are the parameters, and every name in the first column fires.
a customer opened an account: the sign-up page, sign-up at checkout, Google or GitHub sign-in, or the API addclient with a password. Not for clients created by staff in the admin area, or by addclient without a password
UserLogin / ClientLogin (event)
user, method, ipAddress, newDevice
a client-area user signed in (method: password, google or github; newDevice: first sign-in from this device for a user seen before)
ClientEdit
client, userid, changes, olddata
a client's own details changed (not the balance or login stamps)
ClientDelete
client, userid
a client is about to be deleted
TicketOpened / TicketOpen (event)
ticket, isAdmin
ticket opened (isAdmin: opened by staff)
TicketReplied (event)
ticket, replyMessage, isStaffReply
ticket reply added
TicketClosed / TicketClose (event)
ticket, byClient
ticket closed by staff, by the customer (byClient) or by the auto-close task
a mail is about to leave (to: list of addresses, message: the Symfony Email); return ['abortsend' => true] to stop it
DownloadRequested
download, clientId, user
a customer asks for a download, after the access check; return ['abort' => 'reason'] to refuse (403) or ['path' => '/absolute/file', 'name' => 'file.zip'] to hand over that file instead
app(\App\Services\HookManager::class)->registered(); // point => callback countapp(\App\Services\HookManager::class)->firedLog(); // fired this request