Darstellung
Hooks and filters
Text domain: ad-form. All hook names are prefixed ad_form_.
Constants live in Dingfelder\AdForm\Core\Hooks.
Actions
| Hook | When |
|---|---|
ad_form_register_services | After core bindings, before boot() |
ad_form_loaded | Plugin fully booted |
ad_form_register_fields | Register field types on FieldRegistry |
ad_form_rest_routes | After core REST routes |
ad_form_elementor_register | After core hooked the Elementor widget/category |
ad_form_gutenberg_register | After core attempted to register ad-form/form |
ad_form_before_form_save | Before insert/update |
ad_form_after_form_save | After insert/update |
ad_form_after_form_delete | After form delete |
ad_form_before_form_render | Before frontend HTML is built |
ad_form_after_form_render | After frontend HTML is built |
ad_form_before_submission | Before a submission is stored |
ad_form_after_submission | After a submission is stored (Submission, Form). Not fired for honeypot hits. |
ad_form_after_entry_status | After an entry is read/spam/trashed/starred |
ad_form_after_entry_delete | After an entry is permanently deleted |
ad_form_before_validation | Before submitted values are sanitized and validated (Form, raw values) |
ad_form_after_validation | After validation (Form, sanitized visible values, field errors) |
ad_form_before_action | Before a submit action runs (type, settings, ActionContext). Not fired for an action the plan does not include |
ad_form_after_action | After a submit action ran (type, ActionResultInterface, ActionContext) |
ad_form_license_activated | After a licence was connected (plan, state) |
ad_form_license_deactivated | After a licence was released from this installation |
ad_form_license_changed | After a manual licence refresh (state) |
ad_form_register_features | Register add-on features on FeatureRegistry. Core keys cannot be redefined |
ad_form_register_gated_modules | Declare a module's required entitlements on ModuleGate |
ad_form_feature_denied | A feature was refused (feature, required_plan). Observation only |
Filters
| Hook | Purpose |
|---|---|
ad_form_service_providers | Add/replace service providers |
ad_form_capabilities | Extra capability names |
ad_form_form_definition | Sanitized form definition JSON |
ad_form_form_query | Form list query |
ad_form_form_rest_item | Serialized REST form |
ad_form_submission_query | Entry list query |
ad_form_submission_rest_item | Serialized REST entry |
ad_form_fields | Registered field type map (type => FieldInterface) |
ad_form_actions | Registered submit action map (type => ActionInterface) |
ad_form_merge_tags | Merge tag map (tag => replacement) for email templates |
ad_form_condition_operators | Condition operator catalogue (id, label, needs_value) |
ad_form_validation_rules | Extra rules (later) |
ad_form_integrations | Integration modules (later) |
ad_form_settings | Settings array |
ad_form_log_context | Sanitize log context |
ad_form_rendered_html | Final frontend HTML |
ad_form_license_api_base | Licence API base URL. For staging. Grants nothing: payloads still need a valid signature |
ad_form_license_dashboard_url | Dashboard base URL |
ad_form_license_timeout | Licence HTTP timeout, clamped to 1–30 seconds |
ad_form_upgrade_url | Upgrade destination |
ad_form_billing_url | Billing destination |
Licensing has no escape hatch
Every licensing hook above is an action, and the five licensing filters are presentational. There is deliberately no filter that can rewrite entitlements, the feature registry or the licence state: each would be a documented one-line bypass. FeatureRegistry::register() refuses any key that is already a core key, and ModuleGate::register() refuses to redefine a core module id.
See docs/ENTITLEMENTS.md and docs/adr/0004-feature-gating.md.
Capabilities
Granted to administrator on activation:
manage_ad_form_formscreate_ad_form_formsedit_ad_form_formsdelete_ad_form_formsview_ad_form_submissionsedit_ad_form_submissionsdelete_ad_form_submissionsmanage_ad_form_settings
PHP interfaces for add-ons
Dingfelder\AdForm\Forms\FormRepositoryInterfaceDingfelder\AdForm\Fields\FieldInterfaceDingfelder\AdForm\Actions\ActionInterfaceDingfelder\AdForm\Integrations\IntegrationInterfaceDingfelder\AdForm\Payments\PaymentGatewayInterfaceDingfelder\AdForm\Conditions\ConditionEngineInterfaceDingfelder\AdForm\Calculations\CalculationEngineInterfaceDingfelder\AdForm\Templates\FormRendererInterfaceDingfelder\AdForm\Support\ValidationRuleInterfaceDingfelder\AdForm\Core\ModuleInterfaceDingfelder\AdForm\Licensing\ApiTransportInterface
Declaring entitlements on your own types
required_entitlements() is declared on AbstractField and AbstractAction, not on the interfaces, so an add-on implementing FieldInterface or ActionInterface directly keeps working and simply declares no requirements.
php
final class SignatureField extends \Dingfelder\AdForm\Fields\AbstractField {
public function type(): string {
return 'signature';
}
/**
* All of these must be granted before the field can be saved or rendered.
*
* @return list<string>
*/
public function required_entitlements(): array {
return array( 'fields.advanced', 'fields.signature' );
}
}Declaring it once is enough: the registry, the definition scanner, the save gate, the builder palette and the REST catalogue all read the same method.