Cybo Advanced Field EngineCyboweb Technologies · Documentation · v1.0.2

Field Groups & Fields

A field group is a named set of fields. A field has a name (used in code), a label (shown to editors) and a type.

Until the visual builder ships, manage the schema in PHP with the schema manager. The same service will power the builder, the REST API and importers, so the rules below will never differ between them.

$schema = cafe()->schema_manager();

All methods return the saved object, true, or a WP_Error explaining the problem.

Field groups

$group = $schema->create_group( [
	'key'         => 'product_information', // Optional. Lowercase letters, digits, underscores.
	'title'       => 'Product Information', // Required.
	'description' => 'Shown on products.',
	'status'      => 'active',              // active | inactive | trash
	'menu_order'  => 0,                     // Lower = higher priority.
	'settings'    => [],
	'location_rules' => [],                 // Where the group appears (see below).
] );

$schema->update_group( $group->id, [ 'title' => 'Product Info' ] ); // Only given keys change.
$schema->delete_group( $group->id ); // Also deletes its fields and ALL their values.

$schema->find_group( $id );
$schema->find_group_by_key( 'product_information' );

Group keys are unique. If you omit the key, one like group_3f9a1c2b7d4e5f is generated.

Fields

$field = $schema->create_field( $group->id, [
	'name'      => 'subtitle',  // Required. Letters, digits, underscores; not starting with a digit.
	'type'      => 'text',      // Required. A registered field type.
	'label'     => 'Subtitle',  // Optional. Defaults to "Subtitle" from the name.
	'key'       => 'field_product_subtitle', // Optional, unique across all groups.
	'required'  => false,
	'settings'  => [ 'max_length' => 120 ],
	'parent_id' => 0,           // ID of the parent field (a Collection, Field Set …); 0 = top level.
] );

$schema->update_field( $field->id, [ 'label' => 'Product subtitle' ] );
$schema->delete_field( $field->id ); // Also deletes nested fields and ALL their values.

$schema->fields_for_group( $group->id );

Rules CAFE enforces

Rule Error code
Group keys are unique cafe_duplicate_group_key
Field keys are unique across all groups cafe_duplicate_field_key
Field names are unique among siblings cafe_duplicate_field_name
The field type must be registered cafe_unknown_field_type
A parent must be a container that accepts the child type cafe_invalid_parent
A field cannot be nested inside itself cafe_invalid_parent
A field cannot move to another group cafe_field_group_immutable
A field with saved values cannot change to a type with different storage cafe_incompatible_type_change
Location rules, conditional logic and settings must be well-formed cafe_invalid_location_rules, cafe_invalid_conditional_logic, cafe_invalid_group_settings
menu_order, sort_order, parent_id must be whole numbers cafe_invalid_menu_order, cafe_invalid_sort_order, cafe_invalid_parent_id
Unreadable stored JSON is not overwritten silently cafe_corrupted_definition

Fields inside tabs and collapsible sections share their parent's names, so seo_title inside a "SEO" tab is still read with cafe_get_field( 'seo_title' ).

Location rules format

A list of OR groups; each group is a list of AND rules:

'location_rules' => [
	[ // Group 1: post type is product AND taxonomy is not 7 …
		[ 'rule' => 'post_type', 'operator' => '==', 'value' => 'product' ],
		[ 'rule' => 'taxonomy',  'operator' => '!=', 'value' => 7 ],
	],
	[ // … OR group 2: the front page.
		[ 'rule' => 'page_type', 'operator' => '==', 'value' => 'front_page' ],
	],
],
  • rule: lowercase letters, digits, underscores.
  • operator: ==, !=, >, <, >=, <=, contains, not_contains, empty, not_empty.
  • value: text (max 1000 characters), number, boolean or null.
  • No other keys are allowed. At most 100 groups and 100 rules per group.

Conditional logic format

A tree of AND/OR groups; conditions reference other fields by key:

'conditional_logic' => [
	'relation'   => 'OR',
	'conditions' => [
		[ 'field' => 'field_button_type', 'operator' => '==', 'value' => 'external' ],
		[
			'relation'   => 'AND',
			'conditions' => [
				[ 'field' => 'field_show_cta', 'operator' => '==', 'value' => true ],
				[ 'field' => 'field_cta_url', 'operator' => 'not_empty' ],
			],
		],
	],
],

Relations are AND / OR (any case, stored uppercase). Operators and values follow the same rules as location rules. Nesting is limited to 5 levels and 100 conditions per group.

Group settings

Group settings must be an object of named settings containing only text, numbers, booleans, null and nested arrays (max 8 levels, 64 KB). Objects and closures are refused. title_translations (the group title per language, e.g. {"nl": "Homepagina"}) must map language codes to plain-text titles of at most 255 characters; see WPML.

show_description (true / false, default false) prints the group description at the top of the group's box on edit screens. The description is plain text.

Edit screen

settings.hidden_elements lists standard parts of the post edit screen to hide while the group is shown (post, page and custom post type screens; term and Settings Page screens are not affected):

title, editor, permalink, featured_image, excerpt, categories, tags, page_attributes, format, author, revisions, discussion, comments, custom_fields

"settings": { "hidden_elements": [ "editor", "discussion", "comments" ] }

Unknown names and duplicates are refused (REST save and import). When several groups match a post, a part is hidden if any of them hides it.

Hiding never changes saved data:

Editor How parts are hidden
Classic CSS only, so every input is still submitted (WordPress would close comments if the Discussion inputs were missing from a save). The matching Screen Options entries are hidden too.
Block The post type supports are switched off for that page load only, and panels without a support (permalink, categories, tags) are removed with removeEditorPanel(), which is not stored as a user preference. The title is hidden with CSS, because without title support new posts are saved as "Auto Draft".
editor hidden The editor support is switched off for that page load, so the post opens on the classic screen with no editor. The content is not submitted and stays exactly as saved, block markup included.

Implementation: src/Admin/EditScreen.php.

Corrupted definitions

If a stored definition contains malformed JSON (for example after a manual database edit), it still loads with safe defaults, and corrupted_columns lists the unreadable columns. update_group() / update_field() return cafe_corrupted_definition until you pass new values for those columns, so broken data is never overwritten silently.

Renaming is safe

Values are linked to the field's internal ID, not its name. Renaming subtitle to tagline keeps every saved value, just update your templates.