You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reviewing files that changed from the base of the PR and between e3a2cf6 and 21c4d4b.
📒 Files selected for processing (6)
classes/controllers/FrmFieldsController.php
classes/views/frm-forms/form.php
js/formidable_admin.js
js/src/admin/admin.js
js/src/admin/fieldPlaceholders.js
tests/phpunit/fields/test_FrmFieldsController.php
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
📝 Walkthrough
Walkthrough
AJAX-loaded builder fields now use indexed placeholders and a JSON manifest to carry field metadata. Client-side code restores that metadata and updates placeholder spinner visibility based on viewport position.
Changes
Builder field placeholders
Layer / File(s)
Summary
Manifest generation and placeholder rendering classes/views/frm-forms/form.php, classes/controllers/FrmFieldsController.php, tests/phpunit/fields/test_FrmFieldsController.php
The form view initializes and emits a JSON manifest for AJAX loads. The controller records field IDs and deduplicated definition indexes while rendering indexed placeholders. Tests cover AJAX placeholders, manifest contents, and normal rendering for initial-load and non-AJAX fields.
Client-side hydration and spinner lifecycle js/src/admin/fieldPlaceholders.js, js/src/admin/admin.js
Client-side code restores field metadata from the manifest at module load and during builder initialization. The spinner observer removes spinners when placeholders leave the viewport, continues observing placeholders after entry, and stops observing a placeholder when its field load fails.
sequenceDiagram
participant FrmFieldsController
participant FormView
participant AdminJS
participant FieldPlaceholders
FrmFieldsController->>FormView: Record placeholder fields and definitions
FormView->>AdminJS: Emit indexed placeholders and JSON manifest
AdminJS->>FieldPlaceholders: Call hydrateFieldPlaceholders
FieldPlaceholders->>FieldPlaceholders: Restore field metadata and remove manifest
Loading
Suggested reviewers:truongwp
Merge Risk:⚪ Minimal · up to 21c4d
AJAX-loaded builder fields now use indexed placeholders with a JSON manifest, and spinners follow viewport visibility. No concrete merge-blocking issue was identified in the supplied changes.
Security Architecture Review
Security architecture risk:🔵 Low · up to 21c4d
The inspected change preserves existing access checks and does not establish a new privilege or data-exposure path. Remaining uncertainty concerns coordinated delivery of the updated page and browser code, and recovery from incomplete or corrupted loading.
Retained concerns
No architecture-level concerns identified.
Security review details
Security Blast Radius
inferred — The inspected change affects placeholder presentation and loading within the selected form-builder page. Existing field retrieval remains scoped to the requested form, so client metadata manipulation alone does not establish access to arbitrary fields or additional authority.
Trust Boundaries and Controls
observed — The inspected loading and creation endpoints retain the frm_edit_forms capability check and frm_ajax nonce verification. Loading resolves fields through the requested form and skips IDs outside that result. These controls predate the PR and are not moved into the browser.
Resilience and Maintainability Implications
observed — The normal loading lifecycle preserves failure containment: fields are claimed before requests, completion releases queue capacity, deleted placeholders are skipped, and successful replacement removes observation of the old node. Failed placeholders remain claimed and now stop spinner observation before displaying an error; viewport re-entry does not duplicate existing spinner content.
Hardening Proposals
proposed — Deliver and roll back the manifest-producing PHP and compatible browser assets together, avoiding mixed versions that leave indexed placeholders undiscoverable by the loading queue.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name
Status
Explanation
Resolution
Docstring Coverage
⚠️ Warning
Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 5 files.
Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name
Status
Explanation
Linked Issues check
✅ Passed
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
✅ Passed
Check skipped because no linked issues were found for this pull request.
Description Check
✅ Passed
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
✅ Passed
The title accurately summarizes the two main changes: building field placeholders with JavaScript and optimizing spinner animations.
Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
Commit to this branch
Create a new PR
🛠️ Fix failing CI checks 💡
Commit to this branch
Create a new PR
🧪 Generate unit tests (beta)
Commit to this branch
Create a new PR
Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Autopilot is currently an internal CodeRabbit preview.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
We reviewed changes in e3a2cf6...21c4d4b on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
The reason will be displayed to describe this comment to others. Learn more.
Call to an undefined method test_FrmFieldsController::assertSame()
The method you are trying to call is not defined, which can result in a fatal error.
Crabcyborg
changed the title
Build placeholders with JS and opimtize spinner animations
Build placeholders with JS and optimize spinner animations
Oct 2, 2026
The reason will be displayed to describe this comment to others. Learn more.
Approving. The PR also reads as an equivalent replacement for the old placeholder template, with nothing dropped.
Live-verified on this branch (preview env, 36-field form with "Load and save form builder page with AJAX" on):
The raw builder HTML has 27 data-frm-placeholder<li>s plus the frm-field-placeholders JSON script. After load the manifest is gone, all 27 are frm_field_loading with id/data-fid/data-formid/data-ftype restored, and all load to real fields. No console errors.
With field requests held, nothing is in view on landing and 0 spinners are added. Scrolled down, 7 of the 8 in-view placeholders had spinners (the 8th was probably just entering view) and 0 sat outside the viewport. Scrolled back up, 0 spinners remain. So spinners are added on entry and removed on exit, as described. Scrolled-to state:
Dropping root: postBodyContent behaves the same in practice, because the observer is still clipped by the scroll container.
Source checks: manifest JSON uses JSON_HEX_* and is applied with className/dataset (no HTML injection). The ajax_this_field guard excludes dividers, so using form_id instead of the old form_select branch is never reached. Existing nonce/capability checks are untouched. PHPUnit and all four Cypress shards pass. DeepSource's red PHP check is assertSame() flagged as undefined in the test file, which is a false positive.
The reason will be displayed to describe this comment to others. Learn more.
Non-blocking: this second call looks redundant. formidable_admin is registered with in_footer = true, so it always runs after the builder markup, and the call at the top of this file already hydrates and removes the manifest. By the time buildInit() runs, this just does a getElementById that finds nothing. One call site makes it clearer which one guarantees hydration before observeFieldPlaceholders().
The reason will be displayed to describe this comment to others. Learn more.
Non-blocking: the call at the top of admin.js runs this at module load with no guard. If the manifest script is ever empty or mangled (a CSP/minifier plugin, or wp_json_encode() returning false), JSON.parse throws and no later code in the bundle runs, including frmAdminBuildJS. Before this PR a bad placeholder only affected that one field. A try { ... } catch ( e ) { return; } around the parse would keep the failure contained. It only takes a malformed manifest to trigger, so it is a robustness nicety rather than a defect.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by CodeRabbit