Domain Profile Hooks

2 views Markdown

Saved contact profiles, default name servers and the renewal invoice — the last eight hooks of the domain area.

Overview

Most hooks here belong to an account rather than to one domain. Contact profiles and default name servers are templates a customer fills once and uses on every name.

The last two sit on the money side: where a customer renews a domain by hand, a gate stands in front of the invoice and an event behind it.

Reference

Following a profile delete

actiondomain.whois_profile_deleted
ClientDomains a last snapshot

Runs after a saved contact profile was deleted.

Parameters 3
$uidintThe account id. A sub-user's action is recorded against the owner.
$profileIdintThe id of the deleted profile.
$profilearrayThe profile as it was before: id, name, information, detouse. Take what you need from here; the record is gone.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.whois_profile_deleted', 10,
    function ($uid, $profileId, $profile) {
        // The record is gone: everything you need is in the third parameter.
        Acme::dropProfileIndex($uid, $profileId);
    });

Following the default profile

actiondomain.whois_profile_default_set
ClientDomains the record holds the OLD value

Runs after a profile was made the default.

Parameters 3
$uidintThe account id. A sub-user's action is recorded against the owner.
$profileIdintThe id of the profile made default.
$profilearrayThe profile record from before the change. Its default field still holds the old value, so do not read the new state from it.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.whois_profile_default_set', 10,
    function ($uid, $profileId, $profile) {
        // The new default is the SECOND parameter; the third is the old record.
        Acme::defaultProfile($uid, $profileId);
    });

Changing the profile form

filterdomain.whois_profile_data
Hook::runRefs the key names are fixed

Runs before a saved profile is loaded into the form.

Parameters 3
$dataarrayrefThe fields going to the form: id, name, first, last, org, email, phone, address, postal, city, country. Keep the key names; the form fills by them.
$profilearrayThe raw database record. Fields the form leaves out (the state, a second address line) are in here.
$uidintThe account id. A sub-user's action is recorded against the owner.
Return 1
voidThe value changes by reference; the return is not read.
Listener
Hook::add('filter:domain.whois_profile_data', 10,
    function (&$data, $profile, $uid) {
        // A field the form leaves out sits in the raw record: take it from there.
        $data['state'] = $profile['information']['State'] ?? '';
    });

Following the default name servers

actiondomain.default_ns_saved
ClientDomains account-wide

Runs after the customer's default name server set was saved. The set belongs to the whole account, not to one name.

Parameters 2
$uidintThe account id. A sub-user's action is recorded against the owner.
$nsarrayThe saved set: the ns1ns4 keys, filled ones only. At least two are present.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.default_ns_saved', 10, function ($uid, $ns) {
    // This set applies to EVERY new name on the account, not to one.
    Acme::rememberDefaults($uid, $ns);
});

Following provider settings

actiondomain.registrar_settings_saved
AdminProducts an operator setting

Runs after a domain provider's settings were saved.

Parameters 2
$modulestringThe provider module whose settings were saved.
$settingsarrayThe saved settings. They can hold credentials; do not log them.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.registrar_settings_saved', 10, function ($module, $settings) {
    // Record that they changed, never what is inside them.
    Audit::note('registrar-settings', $module, 'updated');
});

Stopping a renewal invoice

gatedomain.renewal_invoice_create
ClientDomains before the invoice

Runs where a customer starts a manual renewal, before the invoice is raised. Stopping it means no invoice and no line is created.

Parameters 5
$servicearrayThe domain service being renewed.
$yearsintThe number of years chosen.
$subtotalfloatThe subtotal without tax. In the service's own currency.
$tldstringThe extension, without a dot and lower case.
$uidintThe account id.
Return 1
stringA non-empty string stops the invoice; the text reaches the customer as the error.
Listener
Hook::add('gate:domain.renewal_invoice_create', 10,
    function ($service, $years, $subtotal, $tld, $uid) {
        // Some extensions take no renewal longer than ten years.
        if ($years > 10) return 'Renewals run to ten years at most.';

        return null;
    });

Following a renewal invoice

actiondomain.renewal_invoice_created
ClientDomains the invoice is unpaid

Runs after the renewal invoice was raised. The invoice is unpaid here and the domain is not renewed yet.

Parameters 5
$servicearrayThe domain service being renewed.
$yearsintThe number of years chosen.
$invoiceIdintThe id of the unpaid invoice.
$subtotalfloatThe subtotal without tax.
$duedateFullstringThe domain's current due date. Not the new one: the renewal lands after payment.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.renewal_invoice_created', 10,
    function ($service, $years, $invoiceId, $subtotal, $duedateFull) {
        // The domain is NOT renewed yet; that follows the payment.
        Crm::pendingRenewal($invoiceId, $service['name'] ?? '', $years);
    });

Following DNS records that were read

actiondomain.dns_records_fetched
AdminServices straight from the provider

Runs after the DNS records came back from the provider.

Parameters 2
$servicearrayThe domain service record.
$recordsarrayThe records that were read, normalised.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:domain.dns_records_fetched', 10, function ($service, $records) {
    Acme::snapshotZone((int) ($service['id'] ?? 0), $records);
});

Following the detail page opening

actiondomain.detail.viewed
website/domains on every opening

Runs when a customer opens the management page of their own domain. Access checks are already behind you: the opener is confirmed as the owner.

Parameters 2
$servicearrayThe domain record: id, name, owner_id, status, duedate and the rest.
$serviceIdintThe id of the domain.
Return 1
voidThe return is ignored. It runs while the page opens, so whatever you do here is added to the customer's wait. Hand a slow call to the queue.
Listener
Hook::add('action:domain.detail.viewed', 10, function ($service, $serviceId) {
    // Keep it light: the customer is waiting for the page.
    Acme::touchLastSeen($serviceId);
});

Pitfalls

The default-profile record holds the OLD state

On the default hook the third parameter is the profile record from before the change: its default field still holds the old value. Which profile is now the default is the second parameter. Reading the record and concluding "this one is not the default" comes from here.

These hooks belong to an account, not a domain

Profiles and default name servers are account-wide templates. The hooks hand you an account id rather than a service record, so a listener reaching for domain details finds nothing. A sub-user's action is recorded against the owner.

The date on the invoice is the old due date

The date field on the renewal invoice hook is the domain's current due date, not the one after renewing. The new date exists only once the payment lands. Using this one as "the new end" shows the customer the wrong day.

Provider settings carry credentials

The settings hook can hand you the keys and passwords used to reach the provider. Recording that they changed is fair; recording what is in them is not. Log which module was updated and nothing more.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.