Skip to content

Conversation

@zackkatz
Copy link
Member

@zackkatz zackkatz commented Aug 29, 2025

This implements #2450.

Summary

Refactors the lightbox provider's script enqueuing to resolve conflicts with DataTables rendering and follow WordPress best practices.

Problem

The lightbox provider was using outdated patterns that caused:

  • DataTables to fail rendering in certain situations
  • JavaScript conflicts due to improper script loading order
  • Potential duplicate script enqueuing
  • Direct HTML output instead of WordPress APIs

Solution

1. ✅ Proper WordPress Enqueuing Pattern

  • Separated registration from enqueuing phases
  • Scripts registered early, enqueued only when needed
  • Added validation to prevent double-enqueuing

2. ✅ Modern WordPress APIs

  • Replaced direct <script>/<style> tags with wp_add_inline_script/style()
  • Proper script dependency management
  • Better integration with WordPress script loader

3. ✅ Enhanced Security & Validation

  • Added esc_js() and esc_attr() for dynamic content
  • JSON encoding validation with error handling
  • Array type checking before processing
  • Sanitized gallery ID generation

4. ✅ Backward Compatibility

  • Deprecated print_scripts() properly with _deprecated_function()
  • New method add_inline_scripts_and_styles() for clarity
  • Existing implementations continue to work

Testing Checklist

  • DataTables render correctly with lightbox enabled
  • Multiple Views on same page work properly
  • No JavaScript console errors
  • FancyBox lightbox functionality works
  • AJAX-loaded content with DataTables works
  • Tested with Divi theme (z-index: 100000)
  • Backward compatibility verified

Files Changed

  • includes/extensions/lightbox/class-gravityview-lightbox-provider.php
  • includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php

Performance Impact

  • 🟢 Prevents duplicate resource loading
  • 🟢 Reduces unnecessary function calls
  • 🟢 Optimizes conditional loading

Security Improvements

  • Proper output escaping
  • Input validation
  • Safe JSON encoding

Fixes #2450

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Multi-file uploads now open as grouped galleries in the lightbox.
    • PDFs and SVGs are detected and displayed correctly in the lightbox.
  • Improvements

    • More reliable loading of lightbox assets across pages and views.
    • Better compatibility with caching, themes, and other plugins.
    • Inline initialization ensures consistent Fancybox behavior.
  • Bug Fixes

    • Resolved z-index and admin bar overlap issues for the lightbox.
    • Prevented duplicate loading of lightbox assets.

💾 Build file (c6996c4).

- Replace direct wp_print_scripts() with proper register/enqueue pattern
- Use wp_add_inline_script/style instead of direct HTML output
- Add validation to prevent double-enqueuing of scripts/styles
- Deprecate print_scripts() in favor of add_inline_scripts_and_styles()
- Improve security with proper escaping (esc_js, esc_attr)
- Add error handling for JSON encoding and script registration
- Enhance FancyBox gallery ID generation with sanitization

This resolves DataTables rendering failures caused by improper script
loading order and timing conflicts. The refactoring follows WordPress
best practices and maintains full backward compatibility.

Fixes #2450

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Aug 29, 2025

Walkthrough

Transitioned lightbox assets from direct printing to a register-then-enqueue lifecycle. Added register_scripts/register_styles hooks, introduced add_inline_scripts_and_styles for inline assets, deprecated print_scripts, and updated FancyBox provider and entry-link flow to enqueue assets with duplicate checks and WordPress inline APIs.

Changes

Cohort / File(s) Summary
Core Lightbox Provider
includes/extensions/lightbox/class-gravityview-lightbox-provider.php
Switched hooks to register scripts/styles; enqueue now called at render time; added add_inline_scripts_and_styles() hook; deprecated print_scripts(); added duplicate-enqueue safeguards; updated call sites to enqueue instead of print.
Fancybox Provider
includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php
Implemented inline init via add_inline_scripts_and_styles() using WP inline APIs; added JSON-encoded settings and safety checks; updated attribute logic for file links and galleries; deprecated print_scripts() wrapper; renamed enqueue_* to register_* methods.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant WP as WordPress Hooks
  participant View as GravityView Render
  participant LB as Lightbox Provider (Base)
  participant FB as FancyBox Provider

  WP->>LB: add_hooks()<br/>register_scripts()/register_styles()
  Note over LB: Assets are registered only

  View->>LB: filter_entry_link_output()
  LB->>LB: enqueue_styles()/enqueue_scripts()<br/>[skip if already enqueued]
  LB->>FB: add_inline_scripts_and_styles()<br/>[inline JS/CSS after enqueue]
  Note over FB: Binds Fancybox & sets z-index/admin-bar CSS

  View-->>User: Rendered links with data-fancybox attributes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Use proper register-then-enqueue pattern instead of enqueuing during registration (#2450)
Replace direct HTML/script/style output with WP inline APIs (#2450)
Add checks to prevent duplicate enqueues (#2450)
Adjust timing to avoid conflicts with DataTables initialization (#2450)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation

Possibly related PRs

Suggested reviewers

  • mrcasual

Poem

I hop between hooks with feather-light feet,
No scripts out of order, no styles that compete.
From print to enqueue, I tidy the queue,
Fancy lights glimmer—DataTables debut! ✨
Thump-thump, says my heart, as races subdue.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue/2450-script-printing

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
includes/extensions/lightbox/class-gravityview-lightbox-provider.php (2)

69-70: Register assets earlier in the queue.

Registering on wp_enqueue_scripts at default priority (10) is fine, but setting a lower priority helps guarantee handles exist before any downstream inline additions or conditional enqueues run.

Apply:

- add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
- add_action( 'wp_enqueue_scripts', array( $this, 'register_styles' ) );
+ add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ), 1 );
+ add_action( 'wp_enqueue_scripts', array( $this, 'register_styles' ), 1 );

229-237: Docblock wording nit.

These methods “register” assets (not “enqueue”). Minor doc tweak will reduce confusion.

Apply:

- * Enqueue scripts for the lightbox
+ * Register scripts for the lightbox

and

- * Enqueue styles for the lightbox
+ * Register styles for the lightbox
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a36c691 and c6996c4.

📒 Files selected for processing (2)
  • includes/extensions/lightbox/class-gravityview-lightbox-provider.php (5 hunks)
  • includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php (3)
future/includes/class-gv-utils.php (1)
  • Utils (12-193)
includes/helper-functions.php (1)
  • gravityview_sanitize_html_class (140-156)
future/includes/class-gv-entry.php (1)
  • get_slug (225-246)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test_and_package
🔇 Additional comments (16)
includes/extensions/lightbox/class-gravityview-lightbox-provider.php (6)

95-107: Good deprecation path.

Deprecation notice is explicit and points to the replacement hook.


109-119: Solid extension point.

Empty base hook for inline assets keeps child providers clean and focused.


167-168: Hooks cleanup looks correct.

Removes the new registration hooks as expected.


239-260: Guarded, idempotent enqueue is good.

Slug checks and avoiding double-enqueue look correct. Inline injection after a fresh enqueue is the right spot.


267-278: Style enqueue guard looks good.

Avoids duplicates and no-ops on empty handles.


363-366: On-demand enqueue aligns with objectives.

Enqueuing when rendering links prevents unnecessary loads. Combined with early registration, this should resolve order conflicts with DataTables.

Please confirm FancyBox CSS reliably outputs when enqueued during content render across common themes. If any theme doesn’t print late styles, we may need a fallback (e.g., ensuring style is enqueued earlier when the provider is active).

includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php (10)

52-61: Registered-before-inline guard is sensible.

Bailing when handles aren’t registered prevents orphaned inline assets.


64-69: Safe JSON encoding path.

wp_json_encode() check avoids malformed inline JS.


70-77: Inline init: ensure footer-friendly loading.

Binding after the library load is correct. To guarantee the script prints when enqueued post-head, the handle should be registered for the footer (see suggestion below).


78-86: Inline CSS is fine; watch late-style printing.

Inline styles attach to the handle correctly. If any theme fails to print late-enqueued styles, consider enqueuing the stylesheet earlier or adding a small runtime <style> as a fallback.


89-98: Back-compat method handled well.

Clear deprecation plus delegation to the new flow.


148-150: Style registration looks good.

Versioning and handle naming are consistent.


178-198: Defensive checks are solid; minor nit on early returns.

Validations (lightbox enabled, details array, non-empty file_path) prevent noise. Converting non-array $link_atts is helpful.


200-202: Class merge and sanitation look good.

gravityview_sanitize_html_class prevents unsafe class injections.


204-212: Gallery grouping logic: sanitize and uniqueness LGTM.

Using form_id, field_id, and entry slug yields stable group IDs. esc_attr on parts is appropriate.


222-226: Verify FancyBox “pdf” data-type.

Setting data-type to 'pdf' for SVGs and gv-iframe URLs may be FancyBox-version-specific. Many versions expect 'iframe' for PDFs and similar. Please confirm your bundled FancyBox supports 'pdf'; otherwise switch to 'iframe'.

Apply if needed:

- $link_atts['data-type'] = 'pdf';
+ $link_atts['data-type'] = 'iframe';

Comment on lines +91 to 92
$this->enqueue_scripts();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Styles aren’t enqueued when the provider is active (script only).

print_scripts_if_active() enqueues scripts, but not styles. On pages where no individual link triggers filter_entry_link_output(), styles may never be queued (e.g., AJAX-only content). Enqueue both here.

Apply:

- $this->enqueue_scripts();
+ $this->enqueue_scripts();
+ $this->enqueue_styles();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$this->enqueue_scripts();
}
$this->enqueue_scripts();
$this->enqueue_styles();
}
🤖 Prompt for AI Agents
In includes/extensions/lightbox/class-gravityview-lightbox-provider.php around
lines 91-92, print_scripts_if_active() currently only calls
$this->enqueue_scripts(), so styles are never enqueued when the provider is
active (script-only). Modify the method to also call $this->enqueue_styles() (or
the appropriate style enqueue helper) so both scripts and styles are
registered/queued when the provider is active; if enqueue_styles() doesn't exist
yet, add a matching method that registers/enqueues the required CSS and ensure
calls are idempotent and only run when the provider is active.

Comment on lines +141 to 143
public function register_scripts() {
wp_register_script( self::$script_slug, plugins_url( 'assets/lib/fancybox/dist/fancybox.umd.js', GRAVITYVIEW_FILE ), array(), GV_PLUGIN_VERSION );
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Register FancyBox script in the footer to support late enqueue.

Without $in_footer = true, enqueuing after wp_head risks the script never printing. This is the main cause of “works sometimes” symptoms.

Apply:

- wp_register_script( self::$script_slug, plugins_url( 'assets/lib/fancybox/dist/fancybox.umd.js', GRAVITYVIEW_FILE ), array(), GV_PLUGIN_VERSION );
+ wp_register_script( self::$script_slug, plugins_url( 'assets/lib/fancybox/dist/fancybox.umd.js', GRAVITYVIEW_FILE ), array(), GV_PLUGIN_VERSION, true );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function register_scripts() {
wp_register_script( self::$script_slug, plugins_url( 'assets/lib/fancybox/dist/fancybox.umd.js', GRAVITYVIEW_FILE ), array(), GV_PLUGIN_VERSION );
}
public function register_scripts() {
wp_register_script( self::$script_slug, plugins_url( 'assets/lib/fancybox/dist/fancybox.umd.js', GRAVITYVIEW_FILE ), array(), GV_PLUGIN_VERSION, true );
}
🤖 Prompt for AI Agents
In
includes/extensions/lightbox/fancybox/class-gravityview-lightbox-provider-fancybox.php
around lines 141 to 143, wp_register_script is called without the $in_footer
flag which can prevent the script from printing when enqueued late; update the
wp_register_script call to pass the $in_footer parameter as true (i.e. set the
5th argument to true while keeping the existing dependencies and version) so the
FancyBox script is registered to load in the footer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix: Lightbox script enqueuing conflicts causing DataTables rendering failures

2 participants