Added
- Add form group policies for allowed submission statuses, optional per-group field palettes, and new-form default profiles (stencil, templates, form defaults). Group policies inherit from global settings; allowed submission statuses are enforced at the group level. (#2717, #2209, #863)
- Add
FormGroupPolicyservice as the single entry point for global → group → form policy resolution. - Add custom variable sources via
Variables::EVENT_REGISTER_VARIABLES, exposing registered tokens in the variable picker and resolving them server-side when references are parsed. (#898) - Add group-scoped form and submission permissions using stable form group handles, with optional per-form dedicated permissions via a new Use Dedicated Permissions form setting. (#1426, #1356, #2489, Discussion #1696)
- Add
formie-importFormsandformie-exportFormspermissions, replacing the temporary admin-only import/export gate. - Add
formie-accessIntegrationspermission for the top-level Integrations control panel section, separate from Access settings. - Add nested settings page permissions under Access settings, with CP navigation and controller enforcement per page.
- Add
formie_captcha_providerstable and migrate captcha provider credentials out of plugin settings, with site/project scope support and project config export for project-scoped providers. - Add
formie_spam_settingstable and migrate spam handling settings out of plugin settings, with site/project scope support and project config export for project-scoped defaults. - Add built-in submission guards (honeypot, minimum submit time, replay protection) via a
RunSubmissionGuardsTaskscreen-stage workflow task and Settings → Spam Protection controls. - Add global email rules (blocked domains, block free providers), form submit expiration guard, and align
RunSpamChecksTaskwithSpamHelperfor documented keyword and IP matching. - Add suspicious text detection, maximum links screening, global submission throttling, and per-IP submission throttling under Settings → Spam Protection. (#1332, #1154, #1099)
- Add a suspicious text detector focused on keyboard spam, low-quality filler text, and configurable allowed terms.
- Add a
Permissionsservice as the single ACL entry point for forms, submissions, sent notifications, and import/export checks. - Add Field Error Announcement plugin setting (Settings → Forms) to control how front-end validation and submit errors are announced to screen readers (
polite,assertive, oroff). Live validation while typing always uses polite announcements. (#2505) - Add optional per-form reCAPTCHA Action and Minimum Score settings for score-based modes, inheriting global Spam Protection defaults when left blank. (#2167, #2804)
- Add scoped Submission Limits per form: cap all submissions for a form (closes the form when reached), submissions per IP address, or submissions per logged-in user, over configurable periods. Discussion #1939
- Add Reports control panel section for saved analytical views over submissions: filters, summary counts, charts, column configuration, and on-demand export (CSV, Excel, JSON, XML, text) with configurable filename tokens. (#647)
- Add Scheduled Reports to email a summary and export attachment from a saved report on daily or weekly schedules, with configurable file type, optional email template, recipients, and user group delivery. (#692, #2184)
- Add
formie-accessReports,formie-manageReports, andformie-manageScheduledReportspermissions. - Add
craft formie/reports/run-scheduledconsole command for cron-driven scheduled report delivery. - Add Report Async Export Row Threshold setting (Settings → Submissions) to queue large report exports in the background (default 1000 rows). (#2259)
- Add queued report exports with CP polling, email notification, and signed download links for interactive exports.
- Add
formie_report_exportstable,craft formie/gc/prune-report-exportsconsole command, and automatic expiry during Craft garbage collection. - Add report export download settings: interactive/scheduled link expiry (hours), and single-use download links (default on).
Changed
- Apply single-use report export download limits to signed email links only; authenticated control panel downloads remain available until expiry.
- Improve queued report export feedback in the control panel with a dismissible inline notice when the queue starts, instead of a delayed Craft toast about email delivery.
- Improve report viewer load performance by skipping redundant overview refreshes on initial page load and aggregating summary counts in a single query per report instead of three counts per form.
- Improve Submission Limits form settings UX (Apply Limit To, consolidated messaging) and clarify the distinction from global Submission Throttling abuse controls. Add Submission Limits author documentation. Discussion #1939
- Remove built-in CSV export actions from the submissions element index; use Reports for export and scheduled delivery instead.
- Align
FormelementcanView(),canSave(),canDuplicate(), and delete behaviour with controller permissions instead of broad allow-all checks. - Auto-grant creators scoped group (or dedicated per-form) manage permissions when they can create forms but lack broader access.
- Filter CP form and submission element sources and indexes to forms the current user can view or manage.
- Filter the settings sidebar and default settings landing page to the first settings page a user can access.
- Unify Settings → Spam Protection as the single CP page for spam handling, keyword rules, and captcha provider credentials. Legacy
spamandcaptchasroutes redirect to the new page. - Deprecate captcha and spam keys in
plugins.formie.settings; legacy plugin settings values are stripped on save and seeded into runtime stores via the compatibility layer. - Removed chart on Submissions element index in favour of dedicated Reports charting.
- Stream CSV/text report exports row-by-row to disk for memory-safe large datasets (#2497).
- Scheduled reports attach exports when under the email attachment limit; otherwise include a signed download link in the summary email instead of silently omitting the file.
- Store report export download tokens as SHA-256 hashes; scheduled export links default to 48-hour expiry.
Fixed
- Fix report export email links returning “Export not found” after a control panel auto-download by serving CP polling downloads from an authenticated route that does not consume single-use signed links.
- Fix report export downloads failing with Craft’s “Invalid token” error by using a
downloadTokenquery param instead oftoken, which Craft 5.9+ reserves for route tokens. - Hash legacy report export download tokens in PHP during migration for MySQL/MariaDB/PostgreSQL compatibility instead of MySQL-only
SHA2(). - Kick Craft’s queue when polling queued report exports in the control panel, so large async exports progress instead of staying
pendingindefinitely on single-page report views. - Align spam keyword screening in
RunSpamChecksTaskwithSpamHelper, restoring[match:]/[ip:]rule support and field/global reference resolution in the submission workflow. - Skip client-side validation for fields disabled by conditional logic, and disable conditionally hidden submit buttons so Enter no longer triggers hidden submit/next actions. (#2727, #1136, Discussion #1628)
- Apply spam behaviour (success/message) without attempting to persist discarded spam submissions when Save spam submissions is disabled, avoiding failed saves under bot load. (#2818)
- Bound spam keyword scanning and spam log payloads so very large field values cannot stall PHP workers during spam handling. (#2065)
- Initialise captcha placeholders immediately when multipage forms change page via tabs or Ajax Next, so Friendly Captcha and other providers mount on the visible page before submit. (#1893)
- Tear down Cloudflare Turnstile widgets with
remove()during remounts and apply CSP nonces to dynamically loaded captcha scripts where available, reducing console noise on strict CSP hosts. (#2535) - Wait for reCAPTCHA Enterprise readiness before executing score/policy challenges on multipage navigation. (#2224)