Service Lifecycle Hooks

2 views Markdown

The 97 hooks opened across a sold service's life: setting up, suspending, cancelling, renewing, changing plan, and talking to the provider module.

Overview

A service is the thing a customer bought: a hosting package, a server, a software licence. The hooks here follow its life. Most come in pairs: a gate in front of an action and an event behind it.

Another part is about the module actually providing the service. The code opening an account on a server, suspending it or changing a password lives there. These hooks let you touch that call's input and output.

Reference

Life events

action:service.created A service was opened. The return value is ignored.
action:service.status_changed Its status changed. The return value is ignored.
action:service.suspended It was suspended. The return value is ignored.
action:service.terminated It was terminated. The return value is ignored.
action:service.cancelled It was cancelled. The return value is ignored.
action:service.deleted Its record was deleted. The return value is ignored.
action:service.renewed It was renewed. The return value is ignored.
action:service.updowngrade.applied A plan change was applied. The return value is ignored.

Gates

Eighteen gates. Two of them split one job in two. A module action called from the panel passes one gate, and the same action from the customer panel passes another. Where your rule holds for both, bind to both.

gate:service.suspend Suspending.
gate:service.cancel Cancelling.
gate:service.delete Deleting.
gate:service.upgrade Upgrading the plan.
gate:service.manual_renew Renewing by hand.
gate:service.status_change Changing the status.
gate:service.module_action A module action from the panel.
gate:service.client_tool A module action from the customer panel.
gate:service.transfer_request A transfer request.
gate:service.autorenew_toggle Switching auto-renewal on and off.

The provider module

action:service.module_ran An action ran on the provider module.
filter:service.module_result What the module returned.
filter:service.build_options The options going to the module while a service is built. The array changes by reference and the changed array is what gets written; the return value is not used.
filter:service.config_fields The service's configuration fields.
filter:service.module_username The username used on the module.
action:service.password_changed The service password changed.

The detail screen's data

filter:service.detail_data The data behind a service detail.
filter:service.dashboard.cards The cards on a service dashboard.
filter:service.dashboard.tools The tools on a service dashboard.
filter:service.detail_tabs_capabilities Which capabilities the detail tabs show.
filter:service.upgrade_products The products offered for an upgrade.

A gate and an event together

coremio/hooks/acme-service.php
// A GATE: do not suspend a service under review (ask us first).
Hook::add('gate:service.suspend', 10, function ($service) {
    if (Acme::onHold((int) ($service['id'] ?? 0)))
        return 'This service is under review; the suspend was stopped.';
    return null;
});

// AN EVENT: tell the outside once it was suspended.
Hook::add('action:service.suspended', 10, function ($id, $service) {
    Crm::suspended((int) $id);
});

Pitfalls

Automatic actions pass these hooks too

Suspending, terminating and renewing also run from scheduled tasks. A gate saying "the operator should not do this" also lands on the job running overnight, and the system cannot do its own work. Write a gate thinking about who it stops.

The event does not prove the work landed on the server

The status hook runs when our record changes. Whether the provider module truly closed the account on the server is a separate question, and the record can change even where the module call failed. Where the server side matters, read the filter carrying the module result.

The panel and customer paths are separate gates

Module actions pass two separate gates: one for the operator in the panel, one for the customer in theirs. Binding to only one means your rule can be walked around by the other path. The customer path is also narrower: only the methods a module openly allows can be called.

A renewal can show up twice

A renewal can come from an invoice being paid or from a manual action, and a subscription collection takes the same path. Writing work that follows a renewal, be ready to run twice for one period and weed out the repeat on your side.

  • Order Flow Hooks
  • Invoice and Payment Hooks
  • Module Lifecycle Hooks
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.