Skip to content

Hooks and filters ​

Text domain: ad-form. All hook names are prefixed ad_form_.

Constants live in Dingfelder\AdForm\Core\Hooks.

Actions ​

HookWhen
ad_form_register_servicesAfter core bindings, before boot()
ad_form_loadedPlugin fully booted
ad_form_register_fieldsRegister field types on FieldRegistry
ad_form_rest_routesAfter core REST routes
ad_form_elementor_registerAfter core hooked the Elementor widget/category
ad_form_gutenberg_registerAfter core attempted to register ad-form/form
ad_form_before_form_saveBefore insert/update
ad_form_after_form_saveAfter insert/update
ad_form_after_form_deleteAfter form delete
ad_form_before_form_renderBefore frontend HTML is built
ad_form_after_form_renderAfter frontend HTML is built
ad_form_before_submissionBefore a submission is stored
ad_form_after_submissionAfter a submission is stored (Submission, Form). Not fired for honeypot hits.
ad_form_after_entry_statusAfter an entry is read/spam/trashed/starred
ad_form_after_entry_deleteAfter an entry is permanently deleted
ad_form_before_validationBefore submitted values are sanitized and validated (Form, raw values)
ad_form_after_validationAfter validation (Form, sanitized visible values, field errors)
ad_form_before_actionBefore a submit action runs (type, settings, ActionContext). Not fired for an action the plan does not include
ad_form_after_actionAfter a submit action ran (type, ActionResultInterface, ActionContext)
ad_form_license_activatedAfter a licence was connected (plan, state)
ad_form_license_deactivatedAfter a licence was released from this installation
ad_form_license_changedAfter a manual licence refresh (state)
ad_form_register_featuresRegister add-on features on FeatureRegistry. Core keys cannot be redefined
ad_form_register_gated_modulesDeclare a module's required entitlements on ModuleGate
ad_form_feature_deniedA feature was refused (feature, required_plan). Observation only

Filters ​

HookPurpose
ad_form_service_providersAdd/replace service providers
ad_form_capabilitiesExtra capability names
ad_form_form_definitionSanitized form definition JSON
ad_form_form_queryForm list query
ad_form_form_rest_itemSerialized REST form
ad_form_submission_queryEntry list query
ad_form_submission_rest_itemSerialized REST entry
ad_form_fieldsRegistered field type map (type => FieldInterface)
ad_form_actionsRegistered submit action map (type => ActionInterface)
ad_form_merge_tagsMerge tag map (tag => replacement) for email templates
ad_form_condition_operatorsCondition operator catalogue (id, label, needs_value)
ad_form_validation_rulesExtra rules (later)
ad_form_integrationsIntegration modules (later)
ad_form_settingsSettings array
ad_form_log_contextSanitize log context
ad_form_rendered_htmlFinal frontend HTML
ad_form_license_api_baseLicence API base URL. For staging. Grants nothing: payloads still need a valid signature
ad_form_license_dashboard_urlDashboard base URL
ad_form_license_timeoutLicence HTTP timeout, clamped to 1–30 seconds
ad_form_upgrade_urlUpgrade destination
ad_form_billing_urlBilling 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_forms
  • create_ad_form_forms
  • edit_ad_form_forms
  • delete_ad_form_forms
  • view_ad_form_submissions
  • edit_ad_form_submissions
  • delete_ad_form_submissions
  • manage_ad_form_settings

PHP interfaces for add-ons ​

  • Dingfelder\AdForm\Forms\FormRepositoryInterface
  • Dingfelder\AdForm\Fields\FieldInterface
  • Dingfelder\AdForm\Actions\ActionInterface
  • Dingfelder\AdForm\Integrations\IntegrationInterface
  • Dingfelder\AdForm\Payments\PaymentGatewayInterface
  • Dingfelder\AdForm\Conditions\ConditionEngineInterface
  • Dingfelder\AdForm\Calculations\CalculationEngineInterface
  • Dingfelder\AdForm\Templates\FormRendererInterface
  • Dingfelder\AdForm\Support\ValidationRuleInterface
  • Dingfelder\AdForm\Core\ModuleInterface
  • Dingfelder\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.

Digitale Lösungen. Persönlich. Zukunftssicher.