Customising WiseCP without touching the core: first steps with hooks

Semih2 min read

Modules, themes, hooks and the API explained, plus practical examples with action, filter and gate hooks, so your WiseCP extensions survive every update.

What a hosting company wants from WiseCP is usually small: “Tell accounting when an order comes in”, “Stop the payment step in this case”, “Send an SMS when an invoice is created”. The biggest trap with small requests is opening a core file and adding two lines there. Two lines do the job, right up until the next update overwrites that file.

Four doors

There are four supported ways to extend WiseCP:

Door What it’s for
Module A capability the platform doesn’t have: a new panel, payment provider, registrar, SMS service
Theme The entire website and client area
Hook Reacting to existing behaviour, changing a value, stopping an operation
API An outside system reading and writing clients, orders and services

Most real work uses more than one door. But for “do something that already exists a little differently”, the answer is usually a hook.

Hook families

Hook names tell you what they do with their prefix:

  • action: something happened, just so you know. The return value is ignored.
  • filter: you’re allowed to change a value.
  • gate: you can stop the operation. Return a non-empty string and the operation stops, showing that text to the user.
  • ui: you can print HTML at a specific spot on the page.

Example 1: notify on every new invoice

The listener file goes in the coremio/hooks folder or in a module’s hooks.php.

<?php
// coremio/hooks/invoice-notify.php
Hook::add('action:invoice.created.any', 10, function ($invoice_id, $data) {
    // If the write failed the id arrives as 0; check that first.
    if (!$invoice_id) return;

    // For example, send a short notice to the accounting system.
});

Example 2: add a rule at checkout

gate:order.checkout runs as the customer moves to the payment step. Returning a non-empty string stops it:

<?php
// coremio/hooks/cart-limit.php
Hook::add('gate:order.checkout', 10, function ($member, $cart) {
    if (count($cart) > 20) {
        return 'You can order at most 20 items at once.';
    }
    return null;
});

The docs carry an important warning: at this point the cart lines are not priced yet. If your rule depends on an amount, you have to work out the prices yourself or use the filter at the summary stage. Details like this are why reading a hook’s documentation before writing it is a must.

Three golden rules

  1. Don’t edit the core. An update brings its own core; your work should live in theme, module and hook files.
  2. Don’t do slow work in a hook. If you call an outside service, keep the timeout short; a user may be waiting.
  3. Log everything. When something goes wrong, the hook’s log is the first place you’ll look.

If you need themes and addons for WiseCP, the WiseCP service page covers what can be built.

More from the rulebook

  1. 3 min read

    WHMCS or WiseCP? 6 questions to ask when a hosting company picks a panel

    What to look at when a company selling hosting and domains chooses between WHMCS and WiseCP. There's no winner, only the right questions.

  2. 2 min read

    Making a WHMCS theme update-safe: child themes and hooks

    A child theme structure, the template markup you must keep, and hook-based customisation without touching the core, so your custom theme survives WHMCS updates.

Chance

Got a project in mind? Let’s open the box: tell me what you want to build and I’ll prepare a proposal with the scope and a roadmap.