Transformations
A transformation changes a source value before it is checked and saved. A mapping can have several; they run in order, and a Collection column can have its own.
Built in
Name (name) |
In the screen | Does | Options |
|---|---|---|---|
trim |
Remove spaces around the text | " Villa " → "Villa" |
- |
number |
Number | "1.250,50" → 1250.5; not a number → error |
decimal_separator: . or , |
boolean |
Yes / no | 1, true, yes, y, on, ja, oui, si, x → true, else false |
- |
date |
Date from another format | "29/09/2026" with d/m/Y → 2026-09-29 (Date), 2026-09-29 00:00:00 (Date and Time, publish date), H:i:s for Time |
format: a PHP date format, or timestamp |
split |
Split text into a list | "a, b, c" → ["a","b","c"] |
separator (default ,; \n for lines) |
map_values |
Replace values | 1=available / 0=sold |
pairs (one old=new per line); unmatched: keep, leave empty, or error |
default_value |
Use a value when empty | empty → the value | value |
strip_html |
Remove HTML | <b>Hi</b> → Hi |
- |
json |
Read JSON text | '[1,2]' → [1,2] |
- |
first_item |
First item of a list | [5,6] → 5 |
- |
Lookups (one query per batch)
| Name | In the screen | Turns into an ID | Options |
|---|---|---|---|
imported_object |
Old ID → imported post, term or user | the object another migration imported from that record | source_key (empty: this migration), object_type |
attachment |
Media library item by ID, URL or file path | an attachment | - |
post |
Post by slug or ID | an existing post | post_type, by |
term |
Term by slug, name or ID | an existing term (never created) | taxonomy, by |
user |
User by e-mail, username or ID | an existing user (never created) | by |
Every lookup has When nothing is found: Report an error (default; the record is
not imported) or Leave it out and report a warning. Lists stay lists: [3, 4] → two
IDs.
Your own
use Cybo\AdvancedFieldEngine\Connector\Transform\TransformFailed;
add_action( 'cafe_register_migration_transformers', function () {
cafe_register_migration_transformer(
'price_cents',
'Cents → euros',
function ( $value, array $options, $context ) {
if ( ! is_numeric( $value ) ) {
throw new TransformFailed( "“{$value}” is not a number of cents." );
}
return round( $value / 100, 2 );
}
);
} );
$value: the value so far (after the earlier transformations).$options: what the administrator filled in (declare controls with the fourth argument:[ [ 'name' => 'factor', 'label' => 'Factor', 'type' => 'text' ] ]).$context->record: the whole source record ($context->record->get( 'currency' )),$context->rowinside a Collection column,$context->field(the target CAFE field ornull),$context->target,$context->migration,$context->dry_run, and$context->warnings->add( 'text' )for a warning that does not stop the record.
Throw TransformFailed (or return a WP_Error) to refuse a value: the record is
reported and not written. Any other exception is reported as "The transformation … failed"
without internal details. Keep messages free of secrets.
Lookups of your own
A transformation that queries something should implement
Cybo\AdvancedFieldEngine\Connector\Transform\BatchTransformerInterface: its prime( $values, $options )
receives all values of a batch before transform() is called, so it can load them with
one query. Extending Cybo\AdvancedFieldEngine\Connector\Transform\Lookup\AbstractLookup gives you that
plus the When nothing is found option; implement lookup( $keys, $options, $context )
and not_found_message( $key ), and register an instance with
cafe_register_migration_transformer( new My_Lookup() ).