Form Builder Plugin for SynaptikCMS
Custom form builder: create forms with text, long text, email, phone, number, dropdown, and checkbox fields through a drag-and-drop admin editor. Every form gets its own shortcode. Submissions are always saved on the server and can optionally be emailed as a PDF recap.
The PDF generator is fully self-contained — no third-party library (Dompdf, TCPDF, etc.) is bundled or required. It writes a valid PDF 1.4 document directly using the standard Helvetica base font, which every PDF viewer already has built in.
Features
- Field types: short text, long text (textarea), email, phone, number, dropdown (with custom options), and checkbox.
- Per-field settings: label, internal key (used in the PDF and as the form field name), required/optional toggle. Checkbox fields are always optional — an unchecked box already carries meaning.
- Drag-and-drop field reordering in the editor — grab the handle on the left of a field row and drop it above or below another row. No need to delete and recreate fields to insert one in the middle.
- One shortcode per form:
[form id="your-form-id"], insertable in any article, page, or project, and reusable across as many pages as needed. - Every submission is saved on the server, regardless of email settings — browsable and searchable from the admin's Submissions tab, filterable by form.
- Optional email notification per form — a checkbox on the form editor ("Receive submissions by email") controls whether a notification is sent at all. When enabled, each submission is emailed as a PDF recap to either a per-form recipient address or the site's default contact email.
- PDF recap — title (form name), submission date, and every field as a "Label: value" block, with automatic word-wrap and pagination for long forms. Re-downloadable at any time from the Submissions tab, even for submissions to forms where email notification is off.
- Custom success message per form, shown inline once the visitor submits (no page reload — the form is replaced with the message and its fields are cleared).
- Security: honeypot field, minimum-delay check, same-origin referrer check, CSRF token (2-hour TTL), and per-IP rate limiting (5 submissions/hour) — all independent from the core contact form's own state.
Using it day to day
Creating a form
- Form Builder → Forms tab → New form.
- Give it a name (shown in the admin list and used as the PDF title and email subject).
- Receive submissions by email — checked by default. Uncheck it if you only want submissions archived on the server without any email going out (e.g. a form you check manually from time to time).
- Recipient email (only relevant while the checkbox above is on) — leave empty to send to the site's default contact email (Settings → Contact in the core admin), or set a specific address for this form.
- Success message — shown to the visitor once they submit. Leave empty to use the default "Thank you, your submission has been received."
- Fields — click Add field for each field you need:
- Label — shown to visitors.
- Key — internal identifier (lowercase letters, numbers, underscores). Used as the PDF row label fallback and the submitted form field name. Two fields can't share the same key — a duplicate is silently dropped on save.
- Type — Text, Long text, Email, Phone, Number, Dropdown, or Checkbox.
- Dropdown options — only shown for the Dropdown type, one option per line.
- Required — disabled automatically for Checkbox fields.
- Drag the handle (⠿) on the left of a row to reorder it.
- Save form. You'll land back on the Forms list, where the new shortcode is shown — click it to copy.
Publishing the form
Paste [form id="your-form-id"] anywhere in an article, page, or project's content. The form renders automatically at that spot on the public page — CSS and JS are only loaded on pages that actually contain the shortcode.
Reviewing submissions
Form Builder → Submissions tab:
- Filter by form using the dropdown, or view all forms at once.
- Each row shows the date, form name, and a short summary (first two text values).
- Download PDF regenerates and downloads the recap on demand — the PDF itself is never stored on disk, only the raw submitted values are, so this works even for a form with email notification turned off.
- Delete permanently removes a submission's stored record. This does not affect any email already sent.
Editing or deleting a form
Form Builder → Forms tab → Edit to change name, recipient, fields, or field order at any time — existing submissions already on disk keep their original recorded values regardless of later field changes. Delete removes the form definition itself; past submissions to that form are kept and remain browsable from the Submissions tab (filterable by selecting "All forms" once the form itself no longer appears in the per-form filter).
Deleting the plugin
From Extensions, a plugin can only be deleted while inactive — deactivate it first. Deleting removes /plugins/formbuilder/ entirely, including every form definition, every stored submission, and secrets. This is permanent; there is no undo.
PDF generation without a third-party library
formbuilder-pdf.php writes the PDF byte structure by hand: catalog, page tree, font resources (standard Helvetica, no font file needed), one content stream per page, cross-reference table, and trailer. Scope is deliberately narrow — a title, a submission date, and a list of label/value rows with word-wrap and automatic pagination. This is enough for a form recap; it is not a general-purpose PDF layout engine, and there is no support for images, tables, or custom fonts.
Maintenance notes
- Field keys should stay stable once a form is live. The
keyis what a submission's storedvaluesobject is keyed by, and what appears as the label fallback in the PDF. Renaming the label is always safe; changing the key only affects future submissions — past ones keep the old key in their stored record. notify_by_emailis opt-out, not opt-in, for backward compatibility. A form saved before this setting existed has no such key in its stored JSON;fb_notify_submission()treats a missing key as "send" so no existing form silently stops notifying after an update.- Rate limiting and CSRF are independent from the core contact form. 5 submissions per IP per hour, 2-hour CSRF token TTL, stored separately in
plugins/formbuilder/private/— never shared with the core's own contact-form state. - Adding a language: copy
lang/en.json→lang/{locale}.jsonandlang/admin/en.json→lang/admin/{locale}.json, translate the values. The plugin automatically follows the core'sactive_language(front) andadmin_language(admin) settings — no extra configuration needed. - Distribution. This plugin is excluded from the core CMS's public release export (
export-release.shexcludes/plugins/andplugins.json) — it ships and updates independently of core releases.
