5.9 KiB
Hooks and integration
What Nolimit Cache offers to other code, and what it listens to. Written for developers who want to extend the plugin or sit next to it; nothing here is needed to use it.
Hooks prefixed nlcac_ are this plugin's own and are stable: a rename is a
breaking change and will be called out in the release notes. Hooks prefixed
wpmgr_ are shared by name with the other Nolimit plugins (see section 2).
A note on the words: for a filter, add_filter() is how you answer it, by
supplying a value. The headings below describe the mechanism, who calls
apply_filters() and who calls add_filter(), because that cannot be misread.
1. Extension points this plugin OFFERS — nlcac_*
apply_filters() / do_action() in our code: we run everyone's callbacks.
| Hook | Type | Signature | Fired from |
|---|---|---|---|
nlcac_reason_not_to_cache |
filter | ( string $reason, … ) — return a non-empty string to refuse to cache this request |
page cache |
nlcac_page_cached |
action | ( string $path ) — a page was just written to disk |
page cache |
nlcac_purge_urls_for_post |
filter | ( array $urls, int $post_id ) — the URLs about to be purged for a post |
purging |
nlcac_preload_urls |
filter | ( array $urls ) — the queue the preloader will walk |
preloader |
nlcac_exclude_script |
filter | ( bool $exclude, string $handle ) — keep a script out of defer |
optimiser |
nlcac_ai_payload |
filter | ( array $payload ) — what the assistant is about to send |
assistant |
nlcac_images_skip |
filter | ( bool $skip, string $img_tag ) — return true to keep one <img> out of the WebP/AVIF rewrite |
images |
If this plugin is absent, none of these fire. A consumer must not assume
its callback ever runs; has_filter() is not a substitute for the plugin
being active.
A consumer must not do slow or networked work in
nlcac_reason_not_to_cache. It runs on every request, before WordPress, in
the drop-in — which is the whole reason the cache is fast.
2. The family's shared hooks — wpmgr_*
Shared by name across the Nolimit plugins, so load order decides who wins for anything that declares itself once.
Offered here — we call apply_filters() / do_action()
| Hook | Type | Notes |
|---|---|---|
wpmgr_cache_cleared |
action | ( int $removed ). Fired when the page cache is emptied, so a sibling holding derived state can drop it in the same click. Our own object cache listens to it and only calls wp_cache_flush(), so there is no path back into purge. |
wpmgr_dashboard_cards |
filter | Provided by the shared menu file, which every Nolimit plugin carries identically. |
wpmgr_menu_title |
filter | Same. |
wpmgr_menu_glyph |
filter | Same. It exists so the glyph can be overridden. |
Answered here — we register a callback with add_filter() / add_action()
| Hook | Type | What we do | If nobody offers it |
|---|---|---|---|
wpmgr_dashboard_cards |
filter | Add this plugin's card | The card is not drawn; nothing breaks |
wpmgr_menu_title |
filter | Answer the shared menu's title | Shared file's default |
wpmgr_cache_cleared |
action | Flush our object cache | — (we also fire it) |
wpmgr_signals |
filter | Supply this plugin's health signals to a family-wide collection. We answer it; we never read it | Only Nolimit Assistant applies this filter. With it absent or inactive, our signals are contributed to nothing and no error is raised. |
wpmgr_setup_recommendations |
filter | Offer three setup items to the Assistant's Setup screen: turn the page cache on, warm it in the background, keep the basket rule on. Every done is read from the stored setting, never measured. |
Nothing is offered and nothing breaks. Only Nolimit Assistant applies this filter, so without it these items are shown nowhere |
3. WordPress and WooCommerce core
The plugin also attaches to WordPress and WooCommerce core hooks. They are listed by area rather than one row each, because none of them is a contract anyone else needs to honour: they are how the plugin attaches to WordPress.
| Area | Hooks |
|---|---|
| Boot | init, plugins_loaded |
| Admin | admin_init, admin_menu, admin_notices, admin_head, admin_footer, admin_bar_menu, admin_enqueue_scripts, plugin_action_links_{file} |
| Purging | transition_post_status, post_updated, deleted_post, edit_term, delete_term, comment_post, transition_comment_status, update_option_sidebars_widgets, shutdown |
| Front end | template_redirect, wp_head, wp_enqueue_scripts, script_loader_tag, script_loader_src, style_loader_src, the_content, wp_get_attachment_url, wp_calculate_image_srcset, embed_oembed_discover, tiny_mce_plugins |
| Updates | site_transient_update_plugins, plugins_api, upgrader_process_complete |
| Media | wp_update_attachment_metadata, wp_delete_file |
| Settings | update_option_nlcac_settings |
| Scheduling | cron_schedules |
| REST | rest_api_init |
| WooCommerce | woocommerce_new_product, woocommerce_update_product, woocommerce_order_status_changed, woocommerce_product_set_stock, woocommerce_product_set_stock_status, woocommerce_variation_set_stock, woocommerce_variation_set_stock_status, wc_after_products_starting_sales, wc_after_products_ending_sales |
🔴 site_transient_update_plugins is the dangerous one. The filter name
is built from the update host, so every plugin updating from
gitea.nolimit.dk lands on the same one and WordPress runs every callback for
every plugin. Answering unconditionally offers our zip to a sibling. The
guard is two halves and both are required — register with 3 arguments,
and return $update untouched unless $plugin_file is ours. Registering
with 2 leaves the argument unset and the guard silently does nothing, which
is the same shape of bug it exists to fix.
If you write a plugin that updates from the same host, apply the same guard.