Plugin lifecycle hooks

Available in:Free

These hooks tell your code when HappenBoard and HappenBoard Pro can be used, and when they are being deleted. Use them to start a companion plugin at the right moment and to remove its data along with HappenBoard’s. Three Pro filters also change how Pro reaches its store for licences and updates. If you are new to the reference, start with Extending HappenBoard with hooks.

Load order on each request

  1. WordPress loads the main file of every active plugin. Your add_action( 'happenboard_loaded', ... ) line runs here.
  2. On plugins_loaded, HappenBoard attaches the hooks of all its services, then fires happenboard_loaded.
  3. HappenBoard Pro answers that action at priority 10. If the free plugin is version 0.2.0 or newer, Pro attaches its own services, then fires happenboard_pro_loaded.
  4. On init, HappenBoard registers its post types, taxonomies and blocks. Both plugins add new capabilities at priority 1 and update their tables at priority 2.

So inside happenboard_loaded you can use HappenBoard’s classes and filters, but its content types do not exist yet.

Uninstalling needs a constant

Deleting HappenBoard from the Plugins screen keeps all its data unless wp-config.php contains define( 'HAPPENBOARD_UNINSTALL', true );. HappenBoard Pro has its own constant, HAPPENBOARD_PRO_UNINSTALL. Each uninstall action fires only when its constant is set. Each plugin also removes only its own data: Pro’s options, its tables and the meta it keeps on WooCommerce products and orders wait for Pro’s own uninstall. The guide GDPR, personal data and uninstalling explains this to site owners.

Pro licence and updates

HappenBoard Pro activates its licence and gets its updates from the HappenBoard store (see Installing HappenBoard Pro). Its licence client and updater start on plugins_loaded on their own, outside happenboard_loaded. That way a site whose free plugin is missing or too old still receives the Pro update that fixes it. Add the three store filters from your plugin’s main file, not from a happenboard_pro_loaded callback, which does not run in that case.

happenboard_loaded

Action Free src/Plugin.php

Fires at the end of HappenBoard’s boot, on plugins_loaded, once every service of the free plugin has attached its hooks. Start a companion plugin here: your code then runs only when HappenBoard is active.

Signature

do_action( 'happenboard_loaded' )

Example

// my-happenboard-addon.php, the main file of your own plugin.
add_action(
    'happenboard_loaded',
    function (): void {
        // HappenBoard is active: its classes and filters can be used.
        add_filter( 'happenboard_schema_event', 'my_addon_schema', 10, 2 );

        // Post types and blocks are registered later, on init.
        add_action( 'init', 'my_addon_register_meta' );
    }
);

Notes

  • Use it instead of plugins_loaded. Your callback never runs when HappenBoard is inactive, so you need no class_exists() check. To test elsewhere, in a theme for example, use did_action( 'happenboard_loaded' ).
  • It fires before init. HappenBoard’s post types, taxonomies, meta fields and blocks are registered on init, and its REST routes on rest_api_init. Defer that kind of work to an init callback.
  • HappenBoard Pro boots from this action at priority 10. Use a higher priority, or happenboard_pro_loaded, to run after Pro’s services.
  • A theme’s functions.php loads after this action has fired, so hooking it from a theme does nothing. In a theme, add your filters directly.

happenboard_pro_loaded

Action Pro src/Plugin.php

Fires at the end of HappenBoard Pro’s boot, once every Pro service has attached its hooks. Use it for add-ons that extend Pro features.

Signature

do_action( 'happenboard_pro_loaded' )

Example

add_action(
    'happenboard_pro_loaded',
    function (): void {
        // HappenBoard and HappenBoard Pro are both active and booted.
        add_filter( 'happenboard_pro_wc_pay_later_methods', 'my_addon_pay_later', 10, 2 );

        // Pro adds its capabilities and tables on init (priorities 1 and 2):
        // read its tables from priority 3 on.
        add_action( 'init', 'my_addon_load_ticket_stats', 5 );
    }
);

Notes

  • It runs inside happenboard_loaded, so also during plugins_loaded and before init. It never fires when the free plugin is inactive.
  • It does not fire when the installed HappenBoard is older than 0.2.0: Pro then stays off and says why in an admin notice. HAPPENBOARD_PRO_VERSION is defined even then, so test this action, not the constant, to know Pro is running.
  • Pro adds new capabilities on init priority 1 and creates or updates its tables on priority 2. Read Pro’s tables from priority 3 on.
  • Every filter Pro adds during its boot is already attached. Hooking the same filter here at priority 10 runs your callback after Pro’s.

happenboard_pro_store_url

Filter Pro src/Service/Licensing/LicenceApi.php

Filters the address of the store HappenBoard Pro uses for its licence and updates. Licence and update calls go to {store}/?wc-api=wc-am-api, and the lookup of a key’s product to {store}/wp-json/license/v1/find.

Signature

apply_filters( 'happenboard_pro_store_url', string $store )

Parameters

$store string
The HAPPENBOARD_PRO_STORE_URL constant when it is defined, otherwise https://happenboard.com/.

Return value

string The store URL. Only an absolute https URL is used, with a trailing slash added. Any other value, an empty string included, switches licensing and updates off.

Example

add_filter(
    'happenboard_pro_store_url',
    function ( $store ) {
        // The staging site talks to the staging store.
        if ( 'staging' === wp_get_environment_type() ) {
            return 'https://staging-store.example.com/';
        }

        return $store;
    }
);

Notes

  • For a fixed address, define HAPPENBOARD_PRO_STORE_URL in wp-config.php instead. No code is needed.
  • A value that is not https switches the licence off rather than raising an error. Every licence action then fails with a message saying the licence server address is not a valid https URL, and no update is offered.
  • The licence key travels in these requests, sent with wp_safe_remote_post(). A store on a local or private address is refused unless you also allow it with core’s http_request_host_is_external filter.
  • Update packages must come from the store’s host or one of its subdomains. If your store serves downloads from another host, add it with happenboard_pro_update_package_hosts.

happenboard_pro_licence_request_args

Filter Pro src/Service/Licensing/LicenceApi.php

Filters the arguments of each request HappenBoard Pro sends to its store, just before wp_safe_remote_post() runs. It covers licence calls, update checks and the product lookup.

Signature

apply_filters( 'happenboard_pro_licence_request_args', array $args, string $action, string $url )

Parameters

$args array<string,mixed>
timeout 15, redirection 2, a HappenBoard-Pro/{version} user agent and an Accept: application/json header. The product lookup also has a body.
$action string
find for the product lookup, otherwise the store action: activate, deactivate, status, update or plugininformation.
$url string
The request URL. Except for find, it carries the licence key and the site’s instance ID in its query string.

Return value

array<string,mixed> The request arguments. A value that is not an array is replaced with an empty array, which drops the timeout and the headers.

Example

add_filter(
    'happenboard_pro_licence_request_args',
    function ( $args, $action, $url ) {
        // Behind a slow outgoing proxy: give the store more time.
        $args['timeout'] = 30;

        return $args;
    },
    10,
    3
);

Notes

  • Three arguments: add_filter( ..., 10, 3 ).
  • Never log $url as it is: its api_key parameter is the licence key. The find request sends the key in its body instead.
  • wp_safe_remote_post() always sets reject_unsafe_urls, so turning it off here has no effect.
  • Requests go out only when someone clicks Activate, Deactivate on this site or Check now under HappenBoard → Settings → Licence. The daily licence check and WordPress update checks also send them, once a key is active.

happenboard_pro_update_package_hosts

Filter Pro src/Service/Updates/Updater.php

Filters the hosts allowed to serve HappenBoard Pro update packages. WordPress receives the package URL the store names only if it uses https, has no user name, password or port, and sits on one of these hosts or a subdomain.

Signature

apply_filters( 'happenboard_pro_update_package_hosts', array $hosts, string $url )

Parameters

$hosts array<int,string>
The store’s host (happenboard.com by default), or an empty array when the store is switched off.
$url string
The package URL being checked.

Return value

array<int,string> The allowed hosts. Each one also allows its subdomains, compared without regard to case. A value that is not an array allows nothing.

Example

add_filter(
    'happenboard_pro_update_package_hosts',
    function ( $hosts, $url ) {
        // The store serves its downloads from a CDN.
        $hosts[] = 'downloads.example-cdn.com';

        return $hosts;
    },
    10,
    2
);

Notes

  • Two arguments: add_filter( ..., 10, 2 ) to receive $url.
  • A package on any other host, or over plain http, makes Pro reject the whole answer and offer no update. The failure is cached for an hour, a good answer for 12 hours. After adding a host, click Check again under Dashboard → Updates: Pro then asks the store again.
  • It runs only while a licence is active on the site, and never on a source checkout whose version is still the {VERSION} placeholder.
  • WordPress downloads and installs Pro from every host you add. Add only hosts your store really serves packages from.

happenboard_uninstall

Action Free uninstall.php

Fires when WordPress deletes the free HappenBoard plugin with HAPPENBOARD_UNINSTALL set, once per site, before HappenBoard removes any of its own data. Hook it to delete your add-on’s options, tables, scheduled events and capabilities in the same pass.

Signature

do_action( 'happenboard_uninstall' )

Example

// In your plugin's main file, outside any HappenBoard hook.
add_action(
    'happenboard_uninstall',
    function (): void {
        global $wpdb;

        // HappenBoard has deleted nothing yet: its events are still readable.
        delete_option( 'my_addon_settings' );
        $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}my_addon_log" );
        wp_clear_scheduled_hook( 'my_addon_cron' );

        foreach ( wp_roles()->role_objects as $role ) {
            $role->remove_cap( 'my_addon_manage' );
        }
    }
);

Notes

  • Nothing happens without the opt-in. Unless define( 'HAPPENBOARD_UNINSTALL', true ); is in wp-config.php, the uninstaller stops at once, this action never fires and every event, attendee and setting stays.
  • Add it from your plugin’s main file, not from a happenboard_loaded callback. HappenBoard is inactive when WordPress runs its uninstall.php, so happenboard_loaded does not fire in that request. Your plugin must still be active.
  • After your callback, HappenBoard deletes its posts, terms, transients, five tables, scheduled events, capabilities and user meta, and every option whose name starts with happenboard_ or widget_happenboard_. HappenBoard Pro’s happenboard_pro_ options and transients stay. Give your own options another prefix, or they go too.
  • On multisite it fires once for each site of the network, inside switch_to_blog(), so $wpdb->prefix already points at that site.

happenboard_pro_uninstall

Action Pro uninstall.php

Fires when WordPress deletes HappenBoard Pro with HAPPENBOARD_PRO_UNINSTALL set, once per site, before Pro removes any of its own data. Pro add-ons hook it to clean up in the same pass.

Signature

do_action( 'happenboard_pro_uninstall' )

Example

// In your add-on's main file, outside any HappenBoard hook.
add_action(
    'happenboard_pro_uninstall',
    function (): void {
        global $wpdb;

        // Runs once per site on multisite, with $wpdb->prefix set for that site.
        delete_option( 'my_addon_ticket_report' );
        $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}my_addon_sales" );

        foreach ( wp_roles()->role_objects as $role ) {
            $role->remove_cap( 'my_addon_view_sales' );
        }
    }
);

Notes

  • It needs Pro’s own opt-in, define( 'HAPPENBOARD_PRO_UNINSTALL', true ); in wp-config.php. Without it, the action never fires and no Pro data is removed, apart from the ticket PDFs older versions left in uploads/happenboard-tickets/, which are always deleted.
  • Add it from your plugin’s main file, not from a happenboard_pro_loaded callback: Pro is inactive in the uninstall request, so that action does not fire.
  • After your callback, Pro deletes every option and transient whose name starts with happenboard_pro_, its Stripe webhook transients, thirteen tables, six capabilities, scheduled events and post meta. It also sets its WooCommerce ticket products back to draft, and deletes the licence once, after the loop over sites.
  • On multisite it fires once per site, with $wpdb pointed at that site. It never touches the free plugin’s data, which happenboard_uninstall covers.

Next steps