JetEngine Listings callback

SkillMedia

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.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the JetEngine Listings callback skill

What this skill tells your AI

The instructions your AI receives, as published by lonsdale201/wp-agent-skills in jet-engine/je-listings-callback/SKILL.md and read by ahel’s review.

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-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:

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-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 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

Signals

GitHub stars
22
Forks
2
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
je-listings-callback
Source
github.com/lonsdale201/wp-agent-skills