Forms & Submissions
Pragma CMS treats forms as a full lifecycle engine: from a drag-and-drop schema definition to secure database storage and third-party API integrations. The entire system is designed to be atomic (using strict SQL transactions) and extensible (via a comprehensive hook registry).
Form Configuration & Routing
When creating a form, you have granular control over what happens after a user submits it:
Submit Actions & Redirects
Instead of just showing a basic success message, you can dynamically route users:
- Message: Displays a rich-text success message (parsed via Summernote).
- Redirect to a Collection Entry: Automatically redirects to a specific article, product, or dynamic page. If the entry's slug changes, the redirect updates automatically.
- Redirect to a System Page: Redirects to a fixed route (e.g.,
/blog,/contact). - Custom URL: Redirects to an external website.
Conditional Email Routing
Instead of sending all submissions to a single admin email, Pragma CMS allows Conditional Routing. You can route emails to different addresses based on what the user selected in the form.
- Example: If the field
departmentequalssales, send to[email protected]. If it equalssupport, send to[email protected].
User Notifications (Auto-responders)
You can easily enable and customize a confirmation email (Subject and Body) that will automatically be sent to the user who filled out the form (provided the form contains an email field).
Form Builder Schema & Field Architecture
The drag-and-drop Administration interface is a visual wrapper that generates a strict relational and JSON-based schema in the database (forms and form_fields tables).
Supported Field Types
The builder supports a wide range of native fields, categorized by complexity:
- Basic: Text, Email, Telephone (with international validation format), Number (with min/max/step).
- Choice: Select, Radio, Checkbox.
- Advanced:
- File: Secure file uploads with MIME-type validation, size limits, and drag-and-drop preview support.
- Composite (Group): A key architectural feature. Allows developers to group sub-fields (e.g., an "Address" group containing Street, City, Zip Code). These are stored internally as a structured JSON object within the
options_valuescolumn and rendered recursively. - Date / Time / DateTime: Native HTML5 selectors.
- HTML / Separator: Allows injecting rich-text blocks (WYSIWYG) between fields to structure complex forms.
- Hidden Field: Crucial for passing contextual backend data (e.g., UTM parameters, Lead Sources, Product IDs) silently during submission.
Configuration & Validation Engine
Every field possesses granular backend configurations:
- Handle: Automatically generated or custom-defined, acting as the exact JSON key when data is submitted.
- Grid Width: Responsive layout definitions (100%, 50%, 33%, 25%).
- Validation Rules: Visual UI rules (Min Length, Max Value, Data Type) are compiled into a strict validation string (e.g.,
email|min:5|max:255) stored in thevalidation_rulesdatabase column and enforced by the PHP controller upon submission.
Conditional Logic Data Model
The form builder allows administrators to define conditional rules that control field visibility based on another field’s value.
Each conditional rule is composed of the following elements:
- Activation: Enabled via an “Enable Conditional Logic” checkbox in the field settings.
- Target Field: The field whose value is evaluated.
- Operator: Defines the condition to apply. Supported operators include:
equalsnot_equalscontainsnot_containsgreater_thanless_thanstarts_with
- Comparison Value: The value against which the target field is compared.
- Effect: The field containing the conditional logic is displayed only if the condition is satisfied.
Instead of hardcoding JavaScript logic, all rules are stored server-side as structured JSON in the conditional_logic column of the form_fields table.
During rendering, FormManager::renderForm() injects this configuration into data-conditional-logic attributes. The core JavaScript engine then parses these attributes to dynamically update the DOM in real time.
Displaying a Form
Pragma CMS provides two main ways to display a built form on the front-end:
1. No-Code Method (Page Builder)
Recommended for content editors:
- Go to Pages.
- Edit a page using the Builder content type.
- Add a new block, select Form, and choose your form from the dropdown.
2. Developer Method (Templates)
For custom Twig templates or PHP views, you can inject a form using its unique handle. The core takes care of the CSRF tokens and required HTML markup.
In Twig:
{{ renderForm('YOUR_FORM_HANDLE', {'ajax': true}) }}
In PHP:
<?= FormManager::renderForm('YOUR_FORM_HANDLE', ["ajax" => true]); ?>
/form/{handle}), the CMS will dynamically retrieve the form schema and render it inside the default
base.phplayout.
When renderForm() is called, the CMS does more than just output HTML inputs. It natively handles both asynchronous submission and built-in security layers:
- AJAX Mode: When enabled, the form is submitted without a page reload. A success message is displayed dynamically or a redirect can be triggered.
- Security Layer: The system automatically injects multiple protections:
- CSRF Protection: Embeds the current session's CSRF token (
$_SESSION['csrf_token']). - Honeypot Field: Injects a visually hidden input (
aria-hidden="true",tabindex="-1"). If a spam bot fills this field, the backend silently rejects the submission. - reCAPTCHA v3 Integration: If enabled in the global settings, the form button is annotated with
data-recaptcha-enabled, allowing the JS engine to silently negotiate a token before POSTing to the API.
- CSRF Protection: Embeds the current session's CSRF token (
Managing Submissions
All form submissions are securely stored in the database. From the Admin panel, you can:
- View the submitted data (JSON decoded natively).
- Download attached files (securely linked to the submission).
- See the exact submission date and status (Read/Unread).
- Direct Reply: If the submission contains an email, the UI provides a quick "Reply" button that triggers a
mailto:link with the form's subject.
The HTTP POST Pipeline & Storage
When a form is submitted, the API processes the payload through a strict, sequential pipeline defined in the core form.php controller. This guarantees security, extensibility, and data integrity.
1. Security & Anti-Spam
Before any data is read, the payload must pass three automated security gates:
- Honeypot: If the visually hidden field is filled by a bot, the CMS fakes a success response (
200 OK) to fool the bot, logs the IP address, and aborts the script. - CSRF Validation: The submission must contain a valid session token (
$_SESSION['csrf_token']). - Server-Side reCAPTCHA v3: If enabled, the CMS initiates a server-to-server request to the Google API to verify the user's score.
2. Pre-Validation Hook
Hook::FORM_BEFORE_VALIDATION: Developers can intercept the raw$_POSTdata here. This is extremely useful for sanitizing inputs or formatting data (e.g., stripping spaces from phone numbers).
3. Dynamic Validation & File Processing
- The CMS iterates through the form's schema and enforces the specific validation rules (Regex, length, type).
- Custom Errors: Using
Hook::FORM_CUSTOM_VALIDATION, developers can inject custom business logic (e.g., query the database to return an error if an email is already registered). - File Uploads: If files are attached, the CMS strictly validates MIME types, creates dynamic time-based directories (
uploads/YYYY/MM/), and safely resolves naming collisions.
4. Atomic Database Storage
Submissions use a hybrid storage model:
- The entire saving process is wrapped in a
Database::beginTransaction(). form_submissions: Stores metadata (IP, Date) and encodes the dynamic form payload as a single JSON object in thedatacolumn.form_submission_files: Relational table linking uploaded files to the submission ID.- Integrity: If file uploading fails or a database query throws an error, the CMS triggers
Database::rollBack(). No orphaned files or partial data will ever be stored.
5. Post-Submission Hook (External Integrations)
Hook::FORM_AFTER_SUBMISSION: Once data is committed to the database, this action hook receives thesubmissionId, the cleandataarray, and thefilesarray. It is the perfect place to push data to CRMs (HubSpot, Salesforce), sync to Mailchimp, or trigger webhooks.
6. Dynamic Notification Engine (resolveRecipients)
Once the data is securely stored, the system fires notifications.
- Admin Routing: The
FormManager::resolveRecipients()method decodes therouting_rulesJSON associated with the form. It merges the default static admin emails with dynamically triggered emails based on the user's payload (e.g., routing to[email protected]if$submissionData['department'] === 'sales'). - Auto-reply Sniffing: The CMS scans the submission payload for any field containing the word
emailthat validates as a proper email address. If found, and if the feature is enabled, a branded Auto-reply (User Notification) is generated using the Core Email Templating engine and sent directly to the submitter's email address. - The Email Engine: All notifications are dispatched via the global
send_email()helper. This function leveragesPHPMailerand the site's SMTP configuration to handle HTML/Text multipart rendering and secure attachments delivery.
send_email()function manually in your own controllers or to customize email templates, please refer to the Emailing & Communication section.
7. PRG (Post/Redirect/Get) Response
Finally, the controller prepares the UI response:
- It securely saves the submission summary in
$_SESSION['recap']for frontend display. - If the form action is set to Redirect, it resolves the dynamic URL (e.g., translating a Collection Entry ID into a public URL) and returns the redirect directive to the JS handler. Otherwise, it returns the rich-text success message.
Hooks
Pragma CMS provides a robust set of hooks to intercept and modify every stage of the form lifecycle, from modifying the admin palette to routing submission data to external CRMs like Salesforce, HubSpot, or Mailchimp.
FORM_AFTER_SUBMISSIONor
FORM_CUSTOM_VALIDATION), please see the Hooks & Extensibility Reference.