Filters
Filters transform a value passing through a named pipeline. Unlike hooks (see Hooks & the Plugin Lifecycle), every filter callback must return the value, modified or unchanged — nothing fires for its side effects alone.
pl_add_filter(string $hook, callable $callback, int $priority = 10): void
pl_apply_filter(string $hook, mixed $value, mixed ...$args): mixed
pl_apply_filter() passes $value through every registered callback on $hook, in priority order, and returns the final result — extra $args are forwarded to each callback after $value. If nothing is registered, $value comes back unchanged.
Core filter points already available
As of 1.4.0, the core itself calls pl_apply_filter() at five real points — register on any of these directly, no core edit required:
| Filter | Fires where | Receives |
|---|---|---|
item_before_save | Just before an item is written to disk | ($item, $type, $fileSlug) |
content_data_array | After sl_build_data_array() assembles $data | ($data) |
menu_tree | After the main menu tree is built | ($tree) |
head_meta_tags | After render_meta_tags() builds its output | ($html, $pageData) |
render_content_html | After the full shortcode/Markdown pipeline runs | ($html, $item) |
pl_add_filter('render_content_html', function (string $html, ?array $item) {
return $html . '<div class="my-plugin-badge">Verified</div>';
});
This is genuinely the most direct way for a plugin to affect front-end content today — it doesn't need the output-buffering trick described in Front-End Integration if a filter point already covers what you need.
Your own filter points
A plugin can also expose filter points for other plugins to hook into. The code producing the value has to explicitly call pl_apply_filter() where it wants to allow modification — if it doesn't, there's nothing to hook into.
// Plugin A
$price = pl_apply_filter('my-plugin/item-price', $rawPrice, $item);
// Plugin B
pl_add_filter('my-plugin/item-price', function (float $price, array $item): float {
return ($item['category'] ?? '') === 'sale' ? $price * 0.90 : $price;
});
When several callbacks register on the same hook, they run in priority order, each receiving the value as modified by the previous one:
pl_add_filter('my-plugin/item-price', fn($price) => $price * 0.90, 10); // 10% off
pl_add_filter('my-plugin/item-price', fn($price) => $price - 5.00, 20); // then €5 off
Namespace filter names as {your-plugin-slug}/{what-is-filtered} to avoid collisions — my-plugin/item-price, my-plugin/email-subject, my-plugin/rendered-html.
