je-listings-callback
Registers or audits a JetEngine Listings callback used by Dynamic Field rendering through jet-engine/callbacks/register or the legacy callback filters. Covers callable identifiers, positional control arguments, multi-callback chains, zero-value defaults, serialized/non-scalar inp
Install
npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/jet-engine/je-listings-callback
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
git clone https://github.com/Lonsdale201/wp-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
JetEngine Listings callback
Add a Dynamic Field transform through JetEngine's allowlist. Treat the callback as render code: make it deterministic, cheap, and explicit about whether it returns plain text or already-safe HTML.
When to use this skill
- Add a formatter to Dynamic Field's Filter field output control.
- Add callback-specific controls and positional PHP arguments.
- Diagnose a selected callback that yields blank or malformed output.
- Process serialized arrays, chained callbacks, HTML, or zero-valued settings.
- Audit output escaping or N+1 work in Listing Grids.
Preferred registration
Register on jet-engine/callbacks/register. The identifier must pass
is_callable() and JetEngine's allowed-callback gate. Use a global function or
a fully qualified static callable string.
final class My_Plugin_JE_Callbacks {
public static function format_distance($value, $decimals = 1, $unit = 'km') {
if (! is_numeric($value)) {
return '';
}
$decimals = max(0, min(6, (int) $decimals));
$unit = in_array($unit, array('km', 'mi'), true) ? $unit : 'km';
return number_format_i18n((float) $value, $decimals) . ' ' . $unit;
}
}
add_action(
'jet-engine/callbacks/register',
static function($manager): void {
$manager->register_callback(
'My_Plugin_JE_Callbacks::format_distance',
__('Format distance', 'my-plugin'),
array(
'my_plugin_decimals' => array(
'label' => __('Decimals', 'my-plugin'),
'type' => 'number',
'default' => 1,
),
'my_plugin_unit' => array(
'label' => __('Unit', 'my-plugin'),
'type' => 'select',
'default' => 'km',
'options' => array(
'km' => 'km',
'mi' => 'mi',
),
),
)
);
}
);
JetEngine calls the function as:
callback(field value, my_plugin_decimals, my_plugin_unit)
Control declaration order is argument order. Prefix every control key. The modern registration adds its own UI conditions; do not duplicate them.
Critical argument edge
In 3.8.14, modern argument extraction uses ! empty($settings[$key]). Saved
0, '0', false, and '' therefore fall back to the declared default. The
default is read with ! empty() too, so a declared default of 0 becomes an
empty string. If zero is valid:
- choose a non-ambiguous UI representation and normalize it in the callback; or
- use the legacy
jet-engine/listing/dynamic-field/callback-argsfilter andarray_key_exists()for that argument.
Do not promise that a numeric control can pass literal zero through the modern helper unchanged.
Input and output contract
- The first argument is the current field result.
- Multiple
filter_callbacksrun sequentially; each output becomes the next callback's input. - Return
string, number,null, orWP_Errorintentionally. Raw arrays and objects produce a visible JetEngine error with available child keys; they are not silently stringified. - Return an empty string for unsupported input only when hiding the value is the
desired behavior. Otherwise return a
WP_Errorduring development. - Bound database/remote work. A Listing Grid may invoke the callback once per field, per item, and per callback in the chain.
Serialized and array-backed values
JetEngine only safely unserializes input for callbacks listed by
jet-engine/listings/non-scalar-callbacks. Add a custom callback only when its
source field is documented to store arrays:
add_filter(
'jet-engine/listings/non-scalar-callbacks',
static function(array $callbacks): array {
$callbacks['My_Plugin_JE_Callbacks::join_labels'] = true;
return $callbacks;
}
);
Do not call unrestricted unserialize() in a callback. Validate the resulting
shape and convert it to a scalar before returning.
Output security
Custom callback output is not automatically escaped by default. The filter
jet-engine/listings/dynamic-field/kses-output defaults to false at the final
render point.
- For plain text, return
esc_html($text)if the callback owns final HTML rendering, or return a raw scalar only when the consuming format escapes it. - For URLs/attributes, escape at the final attribute context; do not use
esc_html()as a universal sanitizer. - For intentional limited HTML, return
wp_kses_post($html)or enable final KSES for the exact field settings. - Never pass user-controlled shortcode or arbitrary callable names through.
add_filter(
'jet-engine/listings/dynamic-field/kses-output',
static function($use_kses, $settings) {
return 'My_Plugin_JE_Callbacks::safe_badge'
=== ($settings['filter_callback'] ?? '') ? true : $use_kses;
},
10,
2
);
Legacy route
Use the three legacy filters only for compatibility or zero-sensitive argument handling:
jet-engine/listings/allowed-callbacksjet-engine/listings/allowed-callbacks-argsjet-engine/listing/dynamic-field/callback-args
Keep the same fully callable identifier in all three. Read callback-contracts.md before implementing the legacy path or chained/non-scalar behavior.
Verification
Test direct is_callable(), allowlist presence, argument order, omitted values,
literal zero, empty input, malicious HTML, array/object output, a multi-callback
chain, and a multi-item Listing Grid. Confirm the actual rendered DOM and count
queries, not only the callback's direct return value.
References
- Official documentation: https://crocoblock.com/knowledge-base/plugins/jetengine/
- Crocoblock developer documentation: https://github.com/Crocoblock/developer-documentation/tree/main/01-jet-engine
- Verified source paths:
wp-content/plugins/jet-engine/includes/components/listings/callbacks.phpwp-content/plugins/jet-engine/includes/components/listings/manager.phpwp-content/plugins/jet-engine/includes/components/listings/render/dynamic-field.phpwp-content/plugins/jet-engine/includes/core/functions.php
Files (wp-agent-skills)
-
agents
-
openai.yaml 255 B
interface: display_name: "JetEngine Listings Callback" short_description: "Build safe Dynamic Field callbacks" default_prompt: "Use $je-listings-callback to implement or audit this JetEngine Dynamic Field callback, arguments, output, and escaping."
-
-
references
-
callback-contracts.md 3.1 KB
# Listings callback contracts Load this reference for legacy registration, zero-sensitive controls, chained callbacks, or array-backed field data. ## Gate sequence JetEngine executes a callback only when both conditions hold: 1. the identifier is present in `jet-engine/listings/allowed-callbacks`; 2. PHP `is_callable($identifier)` returns true. Valid examples: ```php 'my_plugin_global_formatter' 'My_Plugin_JE_Callbacks::format_distance' 'Vendor\\Package\\Formatter::format' ``` A bare alias such as `format_distance` is invalid unless a global function with that exact name exists. Registering a label does not create a callable. ## Legacy registration ```php $id = 'My_Plugin_JE_Callbacks::format_distance'; add_filter('jet-engine/listings/allowed-callbacks', static function($items) use ($id) { $items[$id] = __('Format distance', 'my-plugin'); return $items; }); add_filter('jet-engine/listings/allowed-callbacks-args', static function($args) use ($id) { $args['my_plugin_decimals'] = array( 'label' => __('Decimals', 'my-plugin'), 'type' => 'number', 'default' => 1, 'condition' => array( 'dynamic_field_filter' => 'yes', 'filter_callback' => array($id), ), ); return $args; }); add_filter( 'jet-engine/listing/dynamic-field/callback-args', static function($runtime, $callback, $settings) use ($id) { if ($id !== $callback) { return $runtime; } $runtime[] = array_key_exists('my_plugin_decimals', $settings) ? $settings['my_plugin_decimals'] : 1; return $runtime; }, 10, 3 ); ``` The runtime array already contains the field value. Append arguments in the same order as the callable signature. ## Multiple callbacks When `filter_callbacks` is populated, JetEngine ignores the singular `filter_callback` path and applies each row in order. A formatter must accept the previous formatter's output, not only the original database shape. Test chains such as: ```text stored ID -> title lookup -> HTML badge stored array -> join -> uppercase missing value -> fallback-aware formatter ``` ## Non-scalar input The non-scalar allowlist tells JetEngine that the callback expects safely decoded array-backed data. It does not validate element types for the callback. After decoding: ```php public static function join_labels($value, $separator = ', ') { if (! is_array($value)) { return ''; } $labels = array_filter($value, 'is_scalar'); $labels = array_map('sanitize_text_field', array_map('strval', $labels)); return implode((string) $separator, $labels); } ``` Do not mark a scalar callback as non-scalar merely to make malformed data work. ## Performance checklist - Preload related objects with one query where possible. - Use request-local memoization keyed by input and every control argument. - Do not cache personalized output under a global key. - Put timeouts and failure handling around remote services; preferably hydrate remote data before render time. - Benchmark a realistic Listing Grid with all configured callback chains.
-
-
SKILL.md 7 KB
--- name: je-listings-callback description: >- Registers or audits a JetEngine Listings callback used by Dynamic Field rendering through jet-engine/callbacks/register or the legacy callback filters. Covers callable identifiers, positional control arguments, multi-callback chains, zero-value defaults, serialized/non-scalar input, scalar output, escaping, and render-time performance. Use when adding a field formatter, callback controls, array-aware transforms, or diagnosing blank, unsafe, incorrectly ordered, or unexpectedly defaulted Dynamic Field output. metadata: wp-skills-author: "Soczó Kristóf" wp-skills-contact: "mailto:lonsdale201@hotmail.com" wp-skills-plugin: "jet-engine" wp-skills-plugin-version-tested: "3.8.14" wp-skills-wp-version-tested: "7.0.4" wp-skills-php-min: "7.4" wp-skills-last-updated: "2026-08-17" --- # JetEngine Listings callback Add a Dynamic Field transform through JetEngine's allowlist. Treat the callback as render code: make it deterministic, cheap, and explicit about whether it returns plain text or already-safe HTML. ## When to use this skill - Add a formatter to Dynamic Field's Filter field output control. - Add callback-specific controls and positional PHP arguments. - Diagnose a selected callback that yields blank or malformed output. - Process serialized arrays, chained callbacks, HTML, or zero-valued settings. - Audit output escaping or N+1 work in Listing Grids. ## Preferred registration Register on `jet-engine/callbacks/register`. The identifier must pass `is_callable()` and JetEngine's allowed-callback gate. Use a global function or a fully qualified static callable string. ```php final class My_Plugin_JE_Callbacks { public static function format_distance($value, $decimals = 1, $unit = 'km') { if (! is_numeric($value)) { return ''; } $decimals = max(0, min(6, (int) $decimals)); $unit = in_array($unit, array('km', 'mi'), true) ? $unit : 'km'; return number_format_i18n((float) $value, $decimals) . ' ' . $unit; } } add_action( 'jet-engine/callbacks/register', static function($manager): void { $manager->register_callback( 'My_Plugin_JE_Callbacks::format_distance', __('Format distance', 'my-plugin'), array( 'my_plugin_decimals' => array( 'label' => __('Decimals', 'my-plugin'), 'type' => 'number', 'default' => 1, ), 'my_plugin_unit' => array( 'label' => __('Unit', 'my-plugin'), 'type' => 'select', 'default' => 'km', 'options' => array( 'km' => 'km', 'mi' => 'mi', ), ), ) ); } ); ``` JetEngine calls the function as: ```text callback(field value, my_plugin_decimals, my_plugin_unit) ``` Control declaration order is argument order. Prefix every control key. The modern registration adds its own UI conditions; do not duplicate them. ## Critical argument edge In 3.8.14, modern argument extraction uses `! empty($settings[$key])`. Saved `0`, `'0'`, `false`, and `''` therefore fall back to the declared default. The default is read with `! empty()` too, so a declared default of `0` becomes an empty string. If zero is valid: - choose a non-ambiguous UI representation and normalize it in the callback; or - use the legacy `jet-engine/listing/dynamic-field/callback-args` filter and `array_key_exists()` for that argument. Do not promise that a numeric control can pass literal zero through the modern helper unchanged. ## Input and output contract - The first argument is the current field result. - Multiple `filter_callbacks` run sequentially; each output becomes the next callback's input. - Return `string`, number, `null`, or `WP_Error` intentionally. Raw arrays and objects produce a visible JetEngine error with available child keys; they are not silently stringified. - Return an empty string for unsupported input only when hiding the value is the desired behavior. Otherwise return a `WP_Error` during development. - Bound database/remote work. A Listing Grid may invoke the callback once per field, per item, and per callback in the chain. ## Serialized and array-backed values JetEngine only safely unserializes input for callbacks listed by `jet-engine/listings/non-scalar-callbacks`. Add a custom callback only when its source field is documented to store arrays: ```php add_filter( 'jet-engine/listings/non-scalar-callbacks', static function(array $callbacks): array { $callbacks['My_Plugin_JE_Callbacks::join_labels'] = true; return $callbacks; } ); ``` Do not call unrestricted `unserialize()` in a callback. Validate the resulting shape and convert it to a scalar before returning. ## Output security Custom callback output is not automatically escaped by default. The filter `jet-engine/listings/dynamic-field/kses-output` defaults to `false` at the final render point. - For plain text, return `esc_html($text)` if the callback owns final HTML rendering, or return a raw scalar only when the consuming format escapes it. - For URLs/attributes, escape at the final attribute context; do not use `esc_html()` as a universal sanitizer. - For intentional limited HTML, return `wp_kses_post($html)` or enable final KSES for the exact field settings. - Never pass user-controlled shortcode or arbitrary callable names through. ```php add_filter( 'jet-engine/listings/dynamic-field/kses-output', static function($use_kses, $settings) { return 'My_Plugin_JE_Callbacks::safe_badge' === ($settings['filter_callback'] ?? '') ? true : $use_kses; }, 10, 2 ); ``` ## Legacy route Use the three legacy filters only for compatibility or zero-sensitive argument handling: - `jet-engine/listings/allowed-callbacks` - `jet-engine/listings/allowed-callbacks-args` - `jet-engine/listing/dynamic-field/callback-args` Keep the same fully callable identifier in all three. Read [callback-contracts.md](references/callback-contracts.md) before implementing the legacy path or chained/non-scalar behavior. ## Verification Test direct `is_callable()`, allowlist presence, argument order, omitted values, literal zero, empty input, malicious HTML, array/object output, a multi-callback chain, and a multi-item Listing Grid. Confirm the actual rendered DOM and count queries, not only the callback's direct return value. ## References - Official documentation: <https://crocoblock.com/knowledge-base/plugins/jetengine/> - Crocoblock developer documentation: <https://github.com/Crocoblock/developer-documentation/tree/main/01-jet-engine> - Verified source paths: - `wp-content/plugins/jet-engine/includes/components/listings/callbacks.php` - `wp-content/plugins/jet-engine/includes/components/listings/manager.php` - `wp-content/plugins/jet-engine/includes/components/listings/render/dynamic-field.php` - `wp-content/plugins/jet-engine/includes/core/functions.php`
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.