Developers
How Flavonto Forms works
Storage, form versions, the submission pipeline, background jobs and where to extend.
Storage
Forms, versions, entries and everything around them live in the plugin's own tables (prefix {$wpdb->prefix}flvf_): forms, revisions, entries, entry_values, entry_labels, entry_label_map, entry_notes, events, jobs, uploads, drafts, payments, payment_events, rate_limits, exports and parts. On multisite each site has its own set.
A form's design is a JSON document (see The form document). The builder edits a draft revision; publishing creates an immutable published revision. Each entry stores the id of the revision it was sent with, so changing a form never changes how older entries are shown, exported or emailed.
Answers are stored one row per field in entry_values, as JSON, with a searchable text column. Fields marked Encrypt when stored are encrypted (libsodium secretbox) and their text column is left empty. Files are stored in the private folder (see flvf_private_dir) under random names, encrypted when the folder cannot be shown to be private.
The submission pipeline
Flavonto\Forms\Submit\Pipeline::run() handles the submit route and submissions without JavaScript in this order:
- Form found, active, within its schedule and limits.
- Spam checks before reading answers: trap field, security token (signed, bound to the form, page and user), timing, rate limit.
- Idempotency: a repeated request with the same submission id returns the first result.
- Answers collected and normalised per field type; uploads claimed.
- Conditional logic evaluated on the server with the same engine the browser uses; hidden answers dropped.
- Validation per field (
flvf_validate_field) and for the form (flvf_validate_form); calculations recomputed. - Spam checks on the content (
flvf_is_spam, Akismet, blocked words, links). - Payment amount decided from the server's calculation.
- The entry is stored. Everything after this point can fail without losing it.
- Emails, integrations, purges and payment checks are queued as jobs with unique side effect keys, then run after the response is sent.
- The confirmation is chosen and returned (
flvf_submission_response).
Background jobs
Jobs run right after the response (when the host allows it) and through WP-Cron every minute (flvf_run_jobs). Failures are retried with growing waits up to each job's maximum attempts; every attempt is logged in the entry timeline. Job types are registered with flvf_job_handlers; a handler receives the job row and returns a Flavonto\Forms\Jobs\Result (done(), retry( $error ) or failed( $error )).
Front end
The visitor runtime is plain JavaScript, in a small core plus feature modules that load only when a form uses them (logic, dates, uploads, signatures, repeaters, rich text, address suggestions, challenges, drafts). See JavaScript events.
Where to extend
| You want to | Use |
|---|---|
| Validate an answer your own way | flvf_validate_field, flvf_validate_form |
| Add a merge tag | flvf_merge_tag |
| Fill options from your own data | flvf_field_options |
| Prefill a field | flvf_dynamic_value or flvf_dynamic_value_{parameter} |
| Change an email before sending | flvf_notification_mail, flvf_email_html |
| Act on a new entry | flvf_entry_created, flvf_after_submission |
| Add an integration | flvf_integrations with a class extending Flavonto\Forms\Integrations\Adapter |
| Add a field type | flvf_field_types (definition, settings and rendering through flvf_field_html) |
| Decide spam | flvf_is_spam |
| Change payment requests | flvf_stripe_session_params, flvf_paypal_order_params |
The complete list is in Actions and filters.