Darstellung
Conditional logic
Phase 7 evaluates the same show/hide and action rules on the server (ConditionEngine) and in the browser (assets/frontend/js/form.js).
Disabled or empty groups are always true: the field stays visible and the action runs.
Group shape
Field and action conditions is an object, not a list:
json
{
"enabled": false,
"effect": "show",
"logic": "all",
"rules": [
{
"id": "rule_a1b2c3d4",
"field": "kind",
"operator": "is",
"value": "business"
}
]
}effect:show|hide— fields only. Actions ignoreeffect;matches()means “run this action”.logic:all|any- Rule IDs are stable (
rule_+ 8 hex) - A legacy list of
{field, operator, value}rules is normalized to an enabledshow/allgroup
Operators
| ID | Needs value |
|---|---|
is | yes |
is_not | yes |
contains | yes |
not_contains | yes |
starts_with | yes |
ends_with | yes |
is_empty | no |
is_not_empty | no |
greater_than | yes |
less_than | yes |
String compares are case-insensitive. greater_than / less_than require numeric values. Unknown operators never match. Add-ons can append catalogue entries with ad_form_condition_operators.
Evaluation
- Fields are walked in definition order.
- Rules whose
fieldequals the current field key are skipped (no self-reference). - Hidden fields count as empty for later rules (cascade).
- Submit fields are always visible.
- Hidden fields skip required validation and are omitted from the stored payload and
submission_meta. ActionRunnerskips an action whenmatches()is false (debug log, not a failure).
Frontend
Enabled groups are serialized on the wrap as data-conditions. Required fields keep data-required="1" even when hidden so JS can restore required after they become visible.
Hidden wraps get class is-conditionally-hidden and the hidden attribute. Controls are disabled so classic POST drops them. AJAX collectValues(form, true) skips hidden wraps.
PHP
Dingfelder\AdForm\Conditions\ConditionEngineInterfaceDingfelder\AdForm\Conditions\ConditionEngineDingfelder\AdForm\REST\ConditionsController
SubmitService, ActionRunner and FormRenderer take an optional ConditionEngineInterface (constructor signatures stay compatible). The container injects the engine.
REST catalogue: GET /wp-json/ad-form/v1/conditions (capability edit_ad_form_forms).