Skip to content

Extending dynamic data ​

Add a modifier ​

A modifier transforms a tag's value. This one turns "Blue Bottle Coffee" into "BBC":

php
use VxFramework\Modules\Dynamic_Data\Modifiers\Base_Modifier;
use VxFramework\Modules\Dynamic_Data\Runtime\Value_Cast;

final class My_Initials_Modifier extends Base_Modifier {
    public function key(): string   { return 'initials'; }
    public function label(): string { return __( 'Initials', 'my-plugin' ); }
    public function group(): string { return 'text'; }

    public function apply( $value, array $args, array $context ) {
        $words = preg_split( '/\s+/', trim( Value_Cast::to_string( $value ) ) );
        return strtoupper( implode( '', array_map( fn( $w ) => mb_substr( $w, 0, 1 ), array_filter( $words ) ) ) );
    }
}

add_filter( 'vxframework/dynamic-data/modifiers', function ( array $modifiers ) {
    $modifiers['initials'] = new My_Initials_Modifier();   // keyed by key()
    return $modifiers;
} );

Use it as @post(title).initials(). It appears in the Advanced editor's modifier list and autocomplete.

Useful optional methods:

  • args(): describe arguments, as [ [ 'key' => 'length', 'label' => 'Length', 'type' => 'number', 'default' => 10 ] ], so the editor can offer inputs.
  • applies_to(): which value types the modifier is offered for (string, number, url, date, boolean, list).
  • client_resolvable(): return false if the editor can't run your modifier in the browser. Custom modifiers always run on the server; previews wait for it.

Add a tag group ​

A group adds a new @group(...) root, for data VX doesn't know about:

php
use VxFramework\Modules\Dynamic_Data\Runtime\Groups\Base_Group;
use VxFramework\Modules\Dynamic_Data\Runtime\Resolved_Value;

final class My_Weather_Group extends Base_Group {
    public function get_key(): string   { return 'weather'; }
    public function get_label(): string { return 'Weather'; }

    public function resolve( array $path, array $context ): ?Resolved_Value {
        $data = my_weather_lookup();                     // e.g. [ 'current' => [ 'temp' => 21 ] ]
        foreach ( $path as $segment ) {
            if ( ! is_array( $data ) || ! array_key_exists( $segment, $data ) ) {
                return null;                             // unknown path renders empty
            }
            $data = $data[ $segment ];
        }
        return new Resolved_Value( $data, is_numeric( $data ) ? 'number' : 'string' );
    }
}

add_filter( 'vxframework/dynamic-data/groups', function ( array $groups ) {
    $groups['weather'] = new My_Weather_Group();
    return $groups;
} );

Then write Currently @weather(current.temp)° in the Advanced editor. Custom groups resolve on the server.

Add a builtin ​

Builtins compute values and start with #, like #math. Register them through vxframework/dynamic-data/builtins, the same way as modifiers (keyed by name). Look at #query_var in VX's source for the shape.

Render expressions from PHP ​

php
use VxFramework\Modules\Dynamic_Data\Expression;

echo esc_html( Expression::render( 'Rated @post(rating) of 5', [ 'post_id' => get_the_ID() ] ) );
$tagline = Expression::render_nullable( '@post(tagline)', [ 'post_id' => $id ] ); // null when empty

Pass post_id (for @post and @author), term_id and taxonomy (for @term), and user_id (for @user).

Change which blocks can be bound ​

vxframework/dynamic-data/supported-blocks filters the final map of bindable blocks and attributes, and vxframework/dynamic-data/block-overrides adds per-block allow, deny or restrict entries. Custom blocks with attributes that have the content role are picked up automatically.

Technical details for LLMs
  • Base_Modifier (VxFramework\Modules\Dynamic_Data\Modifiers): abstract key(), label(), apply( $value, array $args, array $context ); optional group() (default general), applies_to() (constants APPLIES_TO_SCALAR, APPLIES_TO_STRING), args(), client_resolvable() (default true; set false unless a JS twin exists), passes() for conditional modifiers. The filter map must be keyed by the modifier key; non-string keys and non-Base_Modifier values are discarded.
  • default is registered as an alias of fallback.
  • Base_Group (…\Runtime\Groups): get_key(), get_label(), resolve( array $path, array $context ): ?Resolved_Value. Stateless; context carries the entity. Map keyed by group key.
  • Builtins: vxframework/dynamic-data/builtins map keyed by name (math, query_var built in).
  • Context keys for Expression::render: post_id, term_id, taxonomy, user_id, plus meta_overlay / core_overlay (unsaved values, used by editor previews).
  • Custom groups aren't guaranteed to appear in the tag picker catalog; vx-framework/get-dynamic-data-catalog reflects VX's built-in groups.

Documentation for the VX Framework.