Skip to content

Conversation

@sapayth
Copy link
Member

@sapayth sapayth commented Sep 1, 2025

fixes #1086

Introduces a new 'AI Settings' section in the settings options, allowing selection of AI provider, model, and API key. Adds dynamic filtering of AI models in the admin UI based on the selected provider. Removes unnecessary debug console logs from admin posting scripts and makes a minor formatting fix in the frontend render form.

Summary by CodeRabbit

  • New Features

    • Admin AI Settings to choose provider, model, and API key.
    • Model dropdown auto-filters by provider, preserves valid selections, adds a default "Select AI Model", and reflects pre-selected provider on load.
    • Provider/model lists are dynamically loaded so available models update when provider changes.
  • Chores

    • Removed debug console logs from admin metabox scripts.
  • Style

    • New admin UI styles and utilities for forms, chat components, dropdowns, and responsive layouts.
  • Documentation

    • Added localization entries and UI strings for AI features.

Introduces a new 'AI Settings' section in the settings options, allowing selection of AI provider, model, and API key. Adds dynamic filtering of AI models in the admin UI based on the selected provider. Removes unnecessary debug console logs from admin posting scripts and makes a minor formatting fix in the frontend render form.
@coderabbitai
Copy link

coderabbitai bot commented Sep 1, 2025

Walkthrough

Adds AI configuration UI and backend: new settings (AI Provider, AI Model, API Key), provider/model helper functions and AJAX endpoint, admin JS to filter models by provider, AJAX action registration, many new admin CSS utilities, localization strings, and removal of a few admin debug console logs plus a trivial whitespace tweak.

Changes

Cohort / File(s) Summary
Settings: AI options
includes/functions/settings-options.php
Adds wpuf_ai settings section and fields: ai_provider, ai_model, ai_api_key.
AI provider/model APIs & AJAX
wpuf-functions.php
Adds wpuf_get_ai_provider_configs(), wpuf_get_ai_provider_options(), wpuf_get_ai_model_options(), and wpuf_get_ai_provider_configs_ajax() (with nonce & capability checks) and exposes provider configs via filters.
Admin JS: model filtering
assets/js/wpuf-admin.js
Adds client-side handler to cache model options, request provider configs via AJAX (wpuf_get_ai_provider_configs), and repopulate the AI model select on provider change and on page load.
Admin AJAX registration
includes/Ajax.php
Registers AJAX action wpuf_get_ai_provider_configs for authenticated users.
Admin metabox logging
includes/Admin/Posting.php
Removes console.log debug statements related to WPUF_Field_Initializer; keeps initializer invocation and control flow.
Frontend tiny formatting
includes/class-frontend-render-form.php
Whitespace-only change in render_featured_field (sprintf( spacing).
Styles: UI utilities & components
assets/css/admin/form-builder.css
Adds a broad set of new .wpuf-* utility and component CSS classes (form inputs, chat UI, collapse/dropdown, responsive utilities, colors, animations, sizing, spacing, etc.).
Localization: POT entries
languages/wp-user-frontend.pot
Adds numerous AI-related msgids and updates source references for new UI strings and AI workflows.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

needs: dev review

Poem

I twitch my whiskers and sort the rows, 🐇
Providers and models in tidy rows,
I nudge a dropdown, hush a log,
I stitch new styles through day and fog,
Settings set — I hop where code now goes. ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The linked issue #1086 addresses a bug where "gmap required validation doesn't work when multiple maps are on the same form." However, the code changes in this pull request introduce entirely new AI-related functionality: an AI Settings section with provider/model selection, dynamic filtering logic via AJAX, CSS utilities for AI components, and supporting functions. There are no changes to gmap validation logic, field initialization, or any bug fixes related to the linked issue. The PR does not meet the primary objective or requirements specified in the linked issue. Either the incorrect issue was linked to this pull request, or the PR scope has shifted. Verify that issue #1086 is the intended target or re-link the appropriate issue(s) that document the AI settings feature requirements. If the gmap validation fix is intended to be part of this PR, it must be implemented and added to the changeset.
Out of Scope Changes Check ⚠️ Warning The linked issue #1086 concerns gmap validation behavior with multiple map fields. All changes in this PR are exclusively focused on AI functionality: new AI Settings section in settings UI, AJAX handler for provider configurations, JavaScript for dynamic model filtering based on provider selection, CSS utilities for AI UI components, and helper functions for provider/model data. There are no changes addressing gmap field initialization, validation logic, or any related concerns from the linked issue, meaning the entire changeset falls outside the scope defined by the linked issue. Clarify the relationship between this PR and issue #1086. If this PR is intended to address the gmap validation issue, implement the necessary gmap-related fixes. If this PR is solely for AI settings feature development, link it to the appropriate feature issue(s) or create a new tracking issue that reflects the actual scope of these changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Add AI settings section" accurately and clearly describes the primary change in the code. The changeset introduces a new AI Settings section with provider and model selection controls, alongside supporting UI elements and AJAX functionality. The title is concise, specific, and directly conveys the main purpose of the changes without vague terms or unnecessary noise.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 1

🧹 Nitpick comments (4)
assets/js/wpuf-admin.js (2)

239-257: Avoid filtering by provider via display text; add a provider attribute.

Relying on option text containing “(OpenAI)/(Anthropic)/...” is brittle (customizations, filters, localization). Prefer a data attribute (e.g., data-provider) or a value prefix to classify options.

Example minimal client-side indexing (no PHP changes), then filter on the indexed attribute:

-        // Filter and add relevant options based on provider
-        aiModelSelect.data('all-options').each(function() {
+        // Index provider once from trailing "(Provider)" if not already set
+        if (!aiModelSelect.data('provider-indexed')) {
+            aiModelSelect.data('all-options').each(function () {
+                var $opt = $(this);
+                var m = $opt.text().match(/\(([^)]+)\)\s*$/);
+                if (m) { $opt.attr('data-provider', m[1].toLowerCase()); }
+            });
+            aiModelSelect.data('provider-indexed', true);
+        }
+        // Filter and add relevant options based on provider
+        aiModelSelect.data('all-options').each(function() {
             var option = $(this);
-            var optionText = option.text();
-            var optionValue = option.val();
+            var optionValue = option.val();
             // Skip empty value option
             if (!optionValue) return;
-            // Check if option belongs to selected provider
-            if (selectedProvider === 'openai' && optionText.includes('(OpenAI)')) {
-                aiModelSelect.append(option.clone());
-            } else if (selectedProvider === 'anthropic' && optionText.includes('(Anthropic)')) {
-                aiModelSelect.append(option.clone());
-            } else if (selectedProvider === 'google' && optionText.includes('(Google)')) {
-                aiModelSelect.append(option.clone());
-            } else if (selectedProvider === 'others' && optionText.includes('(Others)')) {
-                aiModelSelect.append(option.clone());
-            }
+            if (option.attr('data-provider') === selectedProvider) {
+                aiModelSelect.append(option.clone());
+            }
         });

263-276: Guard defaults and prefer localized placeholder text.

  • Ensure the default model exists before selecting; otherwise pick the first real option.
  • “Select AI Model” should be localized (use wp_localize_script or wp.i18n).

Apply:

-        aiModelSelect.append('<option value="">Select AI Model</option>');
+        aiModelSelect.append('<option value="">' + (window.wpuf_admin_i18n?.select_ai_model || 'Select AI Model') + '</option>');
@@
-        } else if (defaultModels[selectedProvider]) {
-            // Fall back to default model for the provider
-            aiModelSelect.val(defaultModels[selectedProvider]);
+        } else if (defaultModels[selectedProvider] && aiModelSelect.find('option[value="' + defaultModels[selectedProvider] + '"]').length) {
+            aiModelSelect.val(defaultModels[selectedProvider]);
+        } else {
+            // Fallback: select first available provider-specific model if present
+            var $first = aiModelSelect.find('option[value!=""]').first();
+            if ($first.length) { aiModelSelect.val($first.val()); }
         }

(Expose wpuf_admin_i18n.select_ai_model via wp_localize_script where this file is enqueued.)

includes/functions/settings-options.php (2)

640-707: Use password field for API key and consider stronger storage/handling.

Displaying/storing API keys in plain text is risky in shared-admin contexts. Use a password-type field to mask input, and (optionally) avoid echoing the saved value back verbatim.

-            [
-                'name'    => 'ai_api_key',
-                'label'   => __( 'API Key', 'wp-user-frontend' ),
-                'desc'    => __( 'Enter your AI service API key. Keep this secure and never share it publicly.', 'wp-user-frontend' ),
-                'type'    => 'text',
-                'default' => '',
-            ],
+            [
+                'name'    => 'ai_api_key',
+                'label'   => __( 'API Key', 'wp-user-frontend' ),
+                'desc'    => __( 'Enter your AI service API key. Keep this secure and never share it publicly.', 'wp-user-frontend' ),
+                'type'    => 'password',
+                'default' => '',
+            ],

If feasible, add a sanitize callback to trim and store, and render a placeholder (e.g., ••••) when a key exists.


656-704: Facilitate robust provider filtering from JS.

Since the admin JS needs to filter models by provider, expose a machine-readable provider key per option (e.g., value prefix openai:gpt-4o or data-provider attribute rendered by the settings API). This avoids parsing human labels.

If altering values is acceptable:

- 'gpt-4o' => 'GPT-4o (OpenAI)',
+ 'openai:gpt-4o' => 'GPT-4o (OpenAI)',

Then update JS to split on : and match provider reliably.

📜 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 aab3cf7 and f91ca2e.

📒 Files selected for processing (4)
  • assets/js/wpuf-admin.js (1 hunks)
  • includes/Admin/Posting.php (1 hunks)
  • includes/class-frontend-render-form.php (1 hunks)
  • includes/functions/settings-options.php (2 hunks)
🔇 Additional comments (4)
includes/Admin/Posting.php (2)

688-695: Good removal of noisy console log.

Swapping the console.log for a comment keeps admin console clean while preserving the initializer guard.


688-695: Confirm gmap “required” fix is actually in the PR.

The PR description says it fixes issue #1086 (“gmap required” with multiple maps), but this file only removes a log. Please point to the commit/file that implements the validation fix, or add it to this PR.

includes/functions/settings-options.php (2)

52-56: AI Settings section inclusion looks good.

Section id, title, and icon are consistent with existing sections.


656-704: Verify model identifiers and future-proof the list.

Some slugs look hypothetical or umbrella (e.g., gpt-5, gpt-4.5, embeddings, tts). Please confirm identifiers you intend to support, and consider sourcing this list via a provider API or filter-only to avoid drift.

Would you like a small adapter that maps providers to models via a filterable registry, so the UI auto-populates from a single source?

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix fatal sprintf/escaping misuse and broken selector for counter.

  • wp_kses_post() is called with extra args (PHP ArgumentCountError). Also, sprintf args are passed to wp_kses_post instead of sprintf.
  • The counter selector in JS looks for .wpuf-message-box, but the span has class="wpuf-items-table-containermessage-box" → the live counter won’t update.

Apply this diff to fix both issues and harden types:

-                         <span class="wpuf-items-table-containermessage-box" id="remaining-feature-item"> <?php echo sprintf(
-                            // translators: %1$s is Post type and %2$s is total feature item
-                            wp_kses_post(__( 'Mark the %1$s as featured (remaining %2$d)', 'wp-user-frontend' ), esc_html ($this->form_settings['post_type'] ), esc_html( $user_sub['total_feature_item'] ) )); ?></span>
+                         <span class="wpuf-message-box" id="remaining-feature-item">
+                             <?php
+                             // translators: %1$s is Post type and %2$d is total feature item
+                             printf(
+                                 esc_html__( 'Mark the %1$s as featured (remaining %2$d)', 'wp-user-frontend' ),
+                                 esc_html( $this->form_settings['post_type'] ),
+                                 absint( $user_sub['total_feature_item'] )
+                             );
+                             ?>
+                         </span>
📝 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
<input type="checkbox" class="wpuf_is_featured" name="is_featured_item" value="1" <?php echo $is_featured ? 'checked' : ''; ?> >
<span class="wpuf-items-table-containermessage-box" id="remaining-feature-item"> <?php echo sprintf(
<span class="wpuf-items-table-containermessage-box" id="remaining-feature-item"> <?php echo sprintf(
// translators: %1$s is Post type and %2$s is total feature item
wp_kses_post(__( 'Mark the %1$s as featured (remaining %2$d)', 'wp-user-frontend' ), esc_html ($this->form_settings['post_type'] ), esc_html( $user_sub['total_feature_item'] ) )); ?></span>
</label>
<input
type="checkbox"
class="wpuf_is_featured"
name="is_featured_item"
value="1"
<?php echo $is_featured ? 'checked' : ''; ?>
>
<span class="wpuf-message-box" id="remaining-feature-item">
<?php
// translators: %1$s is Post type and %2$d is total feature item
printf(
esc_html__( 'Mark the %1$s as featured (remaining %2$d)', 'wp-user-frontend' ),
esc_html( $this->form_settings['post_type'] ),
absint( $user_sub['total_feature_item'] )
);
?>
</span>
</label>

@Rubaiyat-E-Mohammad Rubaiyat-E-Mohammad added QA Approved This PR is approved by the QA team and removed needs: testing labels Sep 3, 2025
Introduces AJAX-based loading of AI models for selected providers in the admin UI. Adds a new AJAX endpoint for fetching provider configurations, updates the settings options to use dynamic provider/model lists, and enhances the form-builder CSS with new utility classes.
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: 5

🧹 Nitpick comments (5)
wpuf-functions.php (1)

5796-5796: Remove unused variable.

The variable $provider_key is defined in the foreach loop but never used. Remove it to clean up the code.

Apply this diff:

-    foreach ( $configs as $provider_key => $config ) {
+    foreach ( $configs as $config ) {
         foreach ( $config['models'] as $model_key => $model_name ) {

Based on learnings (static analysis hint).

assets/css/admin/form-builder.css (4)

1203-1214: Combine transition declarations to avoid overriding earlier one

Second transition overrides the first; visibility no longer transitions. Combine into one.

Apply this diff:

 .wpuf-collapse-content {
-  visibility: hidden;
-  grid-column-start: 1;
-  grid-row-start: 2;
-  min-height: 0px;
-  transition: visibility 0.2s;
-  transition: padding 0.2s ease-out,
-    background-color 0.2s ease-out;
+  visibility: hidden;
+  grid-column-start: 1;
+  grid-row-start: 2;
+  min-height: 0px;
+  transition: visibility 0.2s, padding 0.2s ease-out, background-color 0.2s ease-out;
   padding-left: 1rem;
   padding-right: 1rem;
   cursor: unset;
 }

2692-2730: Remove duplicated transition-timing-function/duration lines

Multiple identical transition-timing-function and transition-duration declarations bloat CSS without effect.

Apply this diff to keep a single set per block:

 .wpuf-collapse-arrow > .wpuf-collapse-title:after {
-  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
   position: absolute;
   display: block;
   height: 0.5rem;
   width: 0.5rem;
   --tw-translate-y: -100%;
   --tw-rotate: 45deg;
   transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
-  transition-property: all;
-  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
-  transition-duration: 150ms;
-  transition-duration: 0.2s;
+  transition-property: all;
+  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  transition-duration: 0.2s;
   top: 1.9rem;
   inset-inline-end: 1.4rem;
   content: "";
   transform-origin: 75% 75%;
   box-shadow: 2px 2px;
   pointer-events: none;
 }

 .wpuf-collapse-plus > .wpuf-collapse-title:after {
-  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
   position: absolute;
   display: block;
   height: 0.5rem;
   width: 0.5rem;
-  transition-property: all;
-  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-  transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
-  transition-duration: 300ms;
+  transition-property: all;
+  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+  transition-duration: 300ms;
   top: 0.9rem;
   inset-inline-end: 1.4rem;
   content: "+";
   pointer-events: none;
 }

1331-1416: Excessively duplicated .wpuf-btn:hover blocks inflate CSS

Same hover rule appears multiple times. Prefer dedupe at build time (e.g., cssnano mergeRules or Tailwind/DaisyUI config to avoid re-emission).


7071-7109: Use theme tokens instead of hardcoded “green” for range inputs

Align with the design system and ensure contrast/dark-mode consistency.

Apply this diff:

 input[type="range"] {
   -webkit-appearance: none;
   width: 100%;
   height: 5px;
-  background: green;
+  background-color: var(--fallback-su, oklch(var(--su)/1));
   outline: none;
   transition: background 0.3s;
   border-radius: 10px
 }
 
 input[type="range"]::-webkit-slider-thumb {
   -webkit-appearance: none;
   appearance: none;
   width: 20px;
   height: 20px;
-  background: green;
+  background-color: var(--fallback-su, oklch(var(--su)/1));
   cursor: pointer;
   border-radius: 10px;
 }
 
 input[type="range"]::-moz-range-thumb {
   width: 20px;
   height: 20px;
-  background: green;
+  background-color: var(--fallback-su, oklch(var(--su)/1));
   cursor: pointer;
   border-radius: 10px;
 }
 
 input[type="range"]:hover,
 input[type="range"]:active {
-  background: green;
+  background-color: var(--fallback-su, oklch(var(--su)/1));
 }
 
 input[type="range"]::-webkit-slider-thumb:hover,
 input[type="range"]::-webkit-slider-thumb:active,
 input[type="range"]::-moz-range-thumb:hover,
 input[type="range"]::-moz-range-thumb:active {
-  background: green;
+  background-color: var(--fallback-su, oklch(var(--su)/1));
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f91ca2e and 51d5ce4.

📒 Files selected for processing (7)
  • assets/css/admin/form-builder.css (67 hunks)
  • assets/js/wpuf-admin.js (1 hunks)
  • includes/Admin/Posting.php (1 hunks)
  • includes/Ajax.php (1 hunks)
  • includes/functions/settings-options.php (2 hunks)
  • languages/wp-user-frontend.pot (27 hunks)
  • wpuf-functions.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • includes/Admin/Posting.php
  • assets/js/wpuf-admin.js
🧰 Additional context used
🧬 Code graph analysis (1)
includes/functions/settings-options.php (1)
wpuf-functions.php (2)
  • wpuf_get_ai_provider_options (5776-5785)
  • wpuf_get_ai_model_options (5793-5803)
🪛 Biome (2.1.2)
assets/css/admin/form-builder.css

[error] 1077-1077: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1209-1209: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1234-1234: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

min-height is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 2694-2694: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 2717-2717: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🪛 PHPMD (2.15.0)
wpuf-functions.php

5796-5796: Avoid unused local variables such as '$provider_key'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (5)
assets/css/admin/form-builder.css (5)

822-879: Namespaced form control styles look good

Consistent with base input styling and scoped under wpuf-*. No issues.


1056-1167: Chat UI utility block is coherent

Semantic grid rows, bubble tail masks, and RTL variants are well-structured. No issues.


1222-1235: Verify :has() usage against supported browsers

Collapse open state relies on :has(). Confirm this aligns with the plugin’s browser support baseline for WP admin.


4989-5007: Custom keyframes and animation utilities are fine

Scoped, simple, and consistent with Tailwind patterns.

Also applies to: 5005-5007


5611-5668: Color utility additions align with palette

Emerald/blue/purple variants consistent with existing tokens.

Also applies to: 5660-5673

Comment on lines +3899 to +3901
.wpuf-collapse {
visibility: collapse;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove visibility: collapse on .wpuf-collapse (can hide panels unexpectedly)

This conflicts with earlier visibility management and may cause collapses to be invisible depending on specificity/cascade. Remove it.

Apply this diff:

-.wpuf-collapse {
-  visibility: collapse;
-}
📝 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
.wpuf-collapse {
visibility: collapse;
}
🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 3899 to 3901, the
.wpuf-collapse rule sets "visibility: collapse" which can unintentionally hide
panels due to cascade/specificity; remove the "visibility: collapse" declaration
from that selector (delete the property line) so visibility is controlled only
by the earlier/intentional rules; if a hidden state is still needed, use a more
specific class or explicit display/visibility rule in the component-specific
stylesheet instead of this global collapse rule.

Comment on lines +5709 to +5822

/**
* Get AI provider configurations
*
* @since WPUF_SINCE
*
* @return array
*/
function wpuf_get_ai_provider_configs() {
$provider_configs = [
'openai' => [
'name' => 'OpenAI',
'endpoint' => 'https://api.openai.com/v1/chat/completions',
'models' => [
'gpt-4o' => 'GPT-4o - Most Capable Multimodal',
'gpt-4o-mini' => 'GPT-4o Mini - Efficient & Fast',
'gpt-4-turbo' => 'GPT-4 Turbo - High Performance',
'gpt-4' => 'GPT-4 - Advanced Reasoning',
'gpt-3.5-turbo' => 'GPT-3.5 Turbo - Fast & Affordable',
],
'requires_key' => true,
],
'anthropic' => [
'name' => 'Anthropic Claude',
'endpoint' => 'https://api.anthropic.com/v1/messages',
'models' => [
'claude-4.1-opus' => 'Claude 4.1 Opus - Most Capable',
'claude-4-opus' => 'Claude 4 Opus - Best Coding Model',
'claude-4-sonnet' => 'Claude 4 Sonnet - Advanced Reasoning',
'claude-3.7-sonnet' => 'Claude 3.7 Sonnet - Hybrid Reasoning',
'claude-3-5-sonnet-20241022' => 'Claude 3.5 Sonnet Latest',
'claude-3-5-sonnet-20240620' => 'Claude 3.5 Sonnet',
'claude-3-5-haiku-20241022' => 'Claude 3.5 Haiku',
'claude-3-opus-20240229' => 'Claude 3 Opus',
'claude-3-sonnet-20240229' => 'Claude 3 Sonnet',
'claude-3-haiku-20240307' => 'Claude 3 Haiku',
],
'requires_key' => true,
],
'google' => [
'name' => 'Google Gemini',
'endpoint' => 'https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent',
'models' => [
'gemini-2.0-flash-exp' => 'Gemini 2.0 Flash Experimental - Latest',
'gemini-2.0-flash' => 'Gemini 2.0 Flash - Stable',
'gemini-2.0-flash-001' => 'Gemini 2.0 Flash 001 - Stable Version',
'gemini-2.0-flash-lite-001' => 'Gemini 2.0 Flash-Lite 001 - Lightweight',
'gemini-2.0-flash-lite' => 'Gemini 2.0 Flash-Lite - Lightweight',
'gemini-2.5-flash' => 'Gemini 2.5 Flash - Latest Stable',
'gemini-2.5-pro' => 'Gemini 2.5 Pro - Most Capable',
'gemini-2.5-flash-lite' => 'Gemini 2.5 Flash-Lite - Efficient',
'gemini-flash-latest' => 'Gemini Flash Latest - Auto-Updated',
'gemini-pro-latest' => 'Gemini Pro Latest - Auto-Updated',
],
'requires_key' => true,
],
];
return apply_filters( 'wpuf_ai_provider_configs', $provider_configs );
}

/**
* Get AI provider options for settings
*
* @since WPUF_SINCE
*
* @return array
*/
function wpuf_get_ai_provider_options() {
$configs = wpuf_get_ai_provider_configs();
$options = [];

foreach ( $configs as $key => $config ) {
$options[ $key ] = $config['name'];
}

return $options;
}

/**
* Get AI model options for settings
*
* @since WPUF_SINCE
* @return array
*/
function wpuf_get_ai_model_options() {
$configs = wpuf_get_ai_provider_configs();
$all_models = [];
foreach ( $configs as $provider_key => $config ) {
foreach ( $config['models'] as $model_key => $model_name ) {
$all_models[ $model_key ] = $model_name;
}
}

return apply_filters( 'wpuf_ai_model_options', $all_models );
}

/**
* AJAX handler to get AI provider configurations
*
* @since WPUF_SINCE
*/
function wpuf_get_ai_provider_configs_ajax() {
// Verify nonce for security
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
wp_send_json_error( 'Invalid nonce' );
}
// Check user capabilities
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'Insufficient permissions' );
}
// Get AI provider configurations
$configs = wpuf_get_ai_provider_configs();
wp_send_json_success( $configs );
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

** PR objectives mention unrelated issue #1086.**

The PR objectives state "Fixes issue #1086" which concerns Google Maps required validation on forms with multiple map fields. However, all code changes in this file relate to AI Settings functionality (provider configuration, model selection, AJAX handlers). This is a significant discrepancy that should be clarified.

Please verify:

🧰 Tools
🪛 PHPMD (2.15.0)

5796-5796: Avoid unused local variables such as '$provider_key'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
In wpuf-functions.php around lines 5709 to 5822 the PR description references
"Fixes issue #1086" (Google Maps validation) but the changes in this file are
only AI settings (provider/model configs and AJAX handler); update the PR so it
accurately reflects what is changed: either remove/replace the issue reference
with the correct issue (or no issue) or add the missing files/commits that
implement the Google Maps validation fix; if the Google Maps fix exists
elsewhere in the branch, list those files/commits in the PR description and
ensure they are included in this PR, otherwise open a separate issue/PR for
#1086 and remove the incorrect fix reference here.

Comment on lines +5810 to +5822
function wpuf_get_ai_provider_configs_ajax() {
// Verify nonce for security
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
wp_send_json_error( 'Invalid nonce' );
}
// Check user capabilities
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'Insufficient permissions' );
}
// Get AI provider configurations
$configs = wpuf_get_ai_provider_configs();
wp_send_json_success( $configs );
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify AJAX action registration and nonce action name.

Please confirm:

  1. Is the AJAX action wpuf_get_ai_provider_configs properly registered in includes/Ajax.php or another file?
  2. Is 'wpuf_nonce' the correct nonce action for this endpoint? Typically, nonce actions are more specific (e.g., 'wpuf_get_ai_provider_configs').

Run this script to verify the AJAX registration:


🏁 Script executed:

#!/bin/bash
# Search for AJAX action registration
echo "Searching for AJAX action registration..."
rg -n "add_action.*wpuf_get_ai_provider_configs" --type=php

echo -e "\nSearching for nonce generation with 'wpuf_nonce'..."
rg -n "wp_create_nonce.*wpuf_nonce" --type=php -A2 -B2

Length of output: 5955


Please verify the AJAX registration with:


🏁 Script executed:

#!/bin/bash
echo "Searching for AJAX action handlers for wpuf_get_ai_provider_configs..."
rg -n "add_action\\(\s*['\"]wp_ajax(_nopriv)?_wpuf_get_ai_provider_configs['\"]" --type=php

Length of output: 70


Register the AJAX handler & tighten the nonce
No add_action('wp_ajax[_nopriv]_wpuf_get_ai_provider_configs', …) exists—add:

add_action('wp_ajax_wpuf_get_ai_provider_configs', 'wpuf_get_ai_provider_configs_ajax');
add_action('wp_ajax_nopriv_wpuf_get_ai_provider_configs', 'wpuf_get_ai_provider_configs_ajax');

And replace the generic 'wpuf_nonce' with a specific action (e.g. 'wpuf_get_ai_provider_configs') in both wp_create_nonce() and wp_verify_nonce().

🤖 Prompt for AI Agents
In wpuf-functions.php around lines 5810 to 5822, the AJAX handler is not
registered and the nonce action is too generic; register the handler by adding
both add_action('wp_ajax_wpuf_get_ai_provider_configs',
'wpuf_get_ai_provider_configs_ajax') and
add_action('wp_ajax_nopriv_wpuf_get_ai_provider_configs',
'wpuf_get_ai_provider_configs_ajax') (place these in the plugin’s initialization
area or where other AJAX actions are registered), and tighten nonce usage by
replacing the generic 'wpuf_nonce' with a specific action name such as
'wpuf_get_ai_provider_configs' in both the wp_create_nonce() call that generates
the nonce and the wp_verify_nonce() call that verifies it in this function.

⚠️ Potential issue | 🟠 Major

Add request method check and internationalize error messages.

The AJAX handler should verify it's handling a POST request, and error messages should be translatable for internationalization.

Apply this diff:

 function wpuf_get_ai_provider_configs_ajax() {
+    // Verify this is a POST request
+    if ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
+        wp_send_json_error( __( 'Invalid request method', 'wp-user-frontend' ) );
+    }
+
     // Verify nonce for security
-    if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
-        wp_send_json_error( 'Invalid nonce' );
+    $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
+    if ( ! wp_verify_nonce( $nonce, 'wpuf_nonce' ) ) {
+        wp_send_json_error( __( 'Invalid nonce', 'wp-user-frontend' ) );
     }
     // Check user capabilities
     if ( ! current_user_can( 'manage_options' ) ) {
-        wp_send_json_error( 'Insufficient permissions' );
+        wp_send_json_error( __( 'Insufficient permissions', 'wp-user-frontend' ) );
     }
📝 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
function wpuf_get_ai_provider_configs_ajax() {
// Verify nonce for security
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
wp_send_json_error( 'Invalid nonce' );
}
// Check user capabilities
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'Insufficient permissions' );
}
// Get AI provider configurations
$configs = wpuf_get_ai_provider_configs();
wp_send_json_success( $configs );
}
function wpuf_get_ai_provider_configs_ajax() {
// Verify this is a POST request
if ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
wp_send_json_error( __( 'Invalid request method', 'wp-user-frontend' ) );
}
// Verify nonce for security
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
if ( ! wp_verify_nonce( $nonce, 'wpuf_nonce' ) ) {
wp_send_json_error( __( 'Invalid nonce', 'wp-user-frontend' ) );
}
// Check user capabilities
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( __( 'Insufficient permissions', 'wp-user-frontend' ) );
}
// Get AI provider configurations
$configs = wpuf_get_ai_provider_configs();
wp_send_json_success( $configs );
}

Comment on lines +5812 to +5814
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
wp_send_json_error( 'Invalid nonce' );
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Sanitize nonce before verification.

The nonce value from $_POST['nonce'] is used directly in wp_verify_nonce() without sanitization. While wp_verify_nonce() is generally safe, it's a WordPress best practice to sanitize all user input before use.

Apply this diff:

-    if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'wpuf_nonce' ) ) {
+    $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
+    if ( ! wp_verify_nonce( $nonce, 'wpuf_nonce' ) ) {
         wp_send_json_error( 'Invalid nonce' );
     }
🤖 Prompt for AI Agents
In wpuf-functions.php around lines 5812 to 5814, the POSTed nonce is passed
directly to wp_verify_nonce; sanitize it first (e.g. read $_POST['nonce'] into a
variable and run sanitize_text_field or equivalent on it, defaulting to an empty
string if not set), then pass the sanitized value to wp_verify_nonce and keep
the existing wp_send_json_error for failures.

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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
languages/wp-user-frontend.pot (1)

2900-2902: Fix confirmed typos and grammar issues in source files, then regenerate POT.

All mentioned issues have been verified as present in the codebase:

  • Spelling errors: "Registraton", "email adress", "Chose", "Minimun", "Twillo" (×3), "neccessery", "Subcription" (×2)
  • Grammar errors: "has been" → "have been" (3 instances), "Could not deleted"
  • Phrasing issues: "get the these key", "Go to Setting", "Please add some more character"
  • Formatting: trailing spaces in "Address Line 1 " and "Address Line 2 ", extra space before "?" in "subscription ?"

The POT file at languages/wp-user-frontend.pot contains these errors. Correct all instances in their source files, then regenerate the POT file.

♻️ Duplicate comments (2)
wpuf-functions.php (1)

5810-5822: Previously identified security and i18n issues remain unaddressed.

The issues flagged in previous reviews for this AJAX handler have not been resolved:

  1. ⚠️ Critical: AJAX action registration is still missing (no add_action for wp_ajax_wpuf_get_ai_provider_configs)
  2. ⚠️ Critical: Nonce is not sanitized before verification (line 5812)
  3. ⚠️ Major: No POST request method verification
  4. ⚠️ Major: Error messages are not internationalized (lines 5813, 5817)
  5. ⚠️ Major: Generic nonce action name 'wpuf_nonce' should be more specific

Please refer to the detailed fixes already provided in the previous review comments.

assets/css/admin/form-builder.css (1)

2838-2840: [DUPLICATE] Remove visibility: collapse from .wpuf-collapse (critical visibility regression).

This is the same issue flagged in the prior review. The visibility: collapse property at lines 2838-2840 directly conflicts with line 1111 which sets visibility: visible on the same selector, and can cause panels/collapses to become invisible due to CSS cascade. Remove the visibility: collapse declaration entirely.

-.wpuf-collapse {
-  visibility: collapse;
-}
🧹 Nitpick comments (7)
languages/wp-user-frontend.pot (6)

1972-2079: New AI strings read clearly; add brief translator context where helpful.

The AI errors/status (“Rate limit exceeded…”, “Form created successfully”, “Test Connection”, etc.) look good. Consider adding short translator notes (meaning/where shown) for “Test Connection”, “Update Form” button labels to reduce ambiguity across locales. Then regenerate the POT.


85-99: Add translator comments for curly‑brace placeholders to avoid breakage.

Strings contain placeholders like {login}, {register}, {link}, {sitename}, {siteurl}, {post_title}, etc., but no “translators:” notes. Add comments such as “translators: keep {login} and {register} placeholders unchanged” so locales don’t alter tokens, then regenerate the POT.

Also applies to: 111-120, 126-137


36-37: Normalize “Select” placeholder styling for consistency.

Three variants exist: “- Select -”, “— Select —”, and “— Select —”. Pick one style (WP commonly uses an em dash “— Select —”) and standardize across templates, then rebuild the POT.

Also applies to: 552-556, 2312-2315


69-71: Unify postal label terminology.

You’re using “Zip Code”, “Postal Code/ZIP”, and “Postal/ZIP Code”. Choose one convention and reuse it (recommend “Postal/ZIP Code” in UI; “ZIP Code” for US‑specific contexts).

Also applies to: 2784-2789, 8362-8364


547-551: Standardize reCAPTCHA capitalization.

Strings mix “reCaptcha”, “Recaptcha”, and “reCAPTCHA”. Consider normalizing to Google’s “reCAPTCHA” brand while keeping existing keys/IDs intact.

Also applies to: 1768-1775, 5155-5166


569-574: Disambiguate common single‑word labels with contexts.

Labels like “Preview”, “Cancel”, “Update”, “Okay”, and “Select” appear in multiple contexts (button vs. field type). Where feasible, use _x() with a context (e.g., _x( 'Select', 'field type', 'textdomain' )) to help translators choose accurate terms.

Also applies to: 626-635, 799-801, 2929-2931, 2967-2971

wpuf-functions.php (1)

5793-5803: Remove unused loop variable.

The $provider_key variable on line 5796 is not used within the loop body. Consider using an underscore to indicate it's intentionally unused.

Apply this diff:

-    foreach ( $configs as $provider_key => $config ) {
+    foreach ( $configs as $config ) {
         foreach ( $config['models'] as $model_key => $model_name ) {
             $all_models[ $model_key ] = $model_name;
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51d5ce4 and e186cbc.

📒 Files selected for processing (3)
  • assets/css/admin/form-builder.css (70 hunks)
  • languages/wp-user-frontend.pot (20 hunks)
  • wpuf-functions.php (1 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
assets/css/admin/form-builder.css

[error] 1014-1014: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

width is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1146-1146: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1171-1171: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

min-height is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1931-1931: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 1954-1954: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🪛 PHPMD (2.15.0)
wpuf-functions.php

5796-5796: Avoid unused local variables such as '$provider_key'. (undefined)

(UnusedLocalVariable)

🔇 Additional comments (5)
wpuf-functions.php (2)

5717-5767: LGTM! Well-structured provider configuration function.

The provider configuration is well-organized with appropriate model options for each AI provider and includes a filter hook for extensibility.


5776-5785: LGTM! Clean helper function.

The function correctly extracts provider options for use in settings dropdowns.

assets/css/admin/form-builder.css (3)

822-879: New form input utility classes with solid foundation.

The addition of .wpuf-form-input, .wpuf-form-textarea, .wpuf-form-select, and .wpuf-form-multiselect classes (lines 822–879) provides consistent form styling across components. The focus states, placeholder styling, and datetime field handling are well-structured. This aligns well with the AI settings form fields introduced in this PR.


993-1109: Chat UI classes provide comprehensive layout and RTL support.

The .wpuf-chat-* component classes (lines 993–1109) with grid-based layout, bubble styling, directional variants (.wpuf-chat-start, .wpuf-chat-end), and RTL mask-image handling ([dir="rtl"] selectors) are well-engineered for potential AI assistant messaging UI. Bubble arrow positioning and CSS masks are semantic.


862-878: Review comment is incorrect—no width property exists in the specified lines.

The actual code at lines 862–878 contains only padding, min-height, text-align, and display properties. No width declaration is present, so there is no duplicate property to remove. Biome could not have flagged a width property that does not exist in this code section.

Likely an incorrect or invalid review comment.

Comment on lines +1145 to +1147
transition: visibility 0.2s;
transition: padding 0.2s ease-out,
background-color 0.2s ease-out;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate transition property in .wpuf-collapse-content (line ~1146).

Biome detects that transition is defined twice in this rule block. The second definition at line 1146 will override the first, leading to unintended behavior. Consolidate into a single transition declaration covering all properties.

🧰 Tools
🪛 Biome (2.1.2)

[error] 1146-1146: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 1145 to 1147, the
.wpuf-collapse-content rule declares transition twice causing the first to be
overridden; consolidate into a single transition declaration that lists all
properties and timings (e.g., visibility, padding, background-color) so all
intended transitions apply consistently.

Comment on lines +1169 to +1172
visibility: visible;
min-height: -moz-fit-content;
min-height: fit-content;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate min-height property in .wpuf-collapse[open]... selectors (line ~1171).

Biome detects duplicate min-height in the combined selector. Ensure only one min-height: fit-content declaration per selector to avoid override confusion.

🧰 Tools
🪛 Biome (2.1.2)

[error] 1171-1171: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

min-height is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 1169 to 1172, the combined
selector contains duplicate min-height declarations; remove the redundant one so
only a single min-height declaration remains (if you need vendor fallback keep
the -moz-fit-content line followed by a single min-height: fit-content) to avoid
override confusion.

Comment on lines +1929 to +1950
.wpuf-collapse-arrow > .wpuf-collapse-title:after {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
position: absolute;
display: block;
height: 0.5rem;
width: 0.5rem;
--tw-translate-y: -100%;
--tw-rotate: 45deg;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
transition-duration: 150ms;
transition-duration: 0.2s;
top: 1.9rem;
inset-inline-end: 1.4rem;
content: "";
transform-origin: 75% 75%;
box-shadow: 2px 2px;
pointer-events: none;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate transition-timing-function in .wpuf-collapse-arrow > .wpuf-collapse-title:after (line ~1931).

Lines 1930–1931 and 1940–1941 both define transition-timing-function: cubic-bezier(0, 0, 0.2, 1); Consolidate to a single declaration to avoid redundancy and potential cascade issues.

🧰 Tools
🪛 Biome (2.1.2)

[error] 1931-1931: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 1929 to 1950, there are
duplicate transition-timing-function declarations in .wpuf-collapse-arrow >
.wpuf-collapse-title:after; remove the redundant lines and keep a single
transition-timing-function (pick the intended cubic-bezier value) so the rule
has only one timing-function declaration and no conflicting duplicates.

Comment on lines +1952 to +1967
.wpuf-collapse-plus > .wpuf-collapse-title:after {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
position: absolute;
display: block;
height: 0.5rem;
width: 0.5rem;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
transition-duration: 300ms;
top: 0.9rem;
inset-inline-end: 1.4rem;
content: "+";
pointer-events: none;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Duplicate transition-timing-function in .wpuf-collapse-plus > .wpuf-collapse-title:after (line ~1954).

Lines 1953–1954 and 1960–1961 both define transition-timing-function. Consolidate to avoid redundancy and clarify intent.

🧰 Tools
🪛 Biome (2.1.2)

[error] 1954-1954: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

transition-timing-function is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 1952 to 1967, the
.wpuf-collapse-plus > .wpuf-collapse-title:after block declares
transition-timing-function twice in two places (lines ~1953–1954 and
~1960–1961); remove the duplicate entries and keep a single
transition-timing-function with the intended cubic-bezier value (place it
alongside transition-property/transition-duration for clarity), so there is only
one timing-function declaration in that rule.

Comment on lines +7191 to 7193
.lg\:wpuf-p-9 {
padding: 2.25rem;
.lg\:wpuf-grid-cols-3 {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Syntax error: missing closing brace before .lg\:wpuf-grid-cols-3 (line 7193).

Line 7191 declares .lg\:wpuf-p-9 but line 7192 is incomplete (ends with just }) and line 7193 begins a new rule without proper preceding brace closure. Add the missing closing brace and newline.

   .lg\:wpuf-p-9 {
     padding: 2.25rem;
+  }
   .lg\:wpuf-grid-cols-3 {
     grid-template-columns: repeat(3, minmax(0, 1fr));
   }
📝 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
.lg\:wpuf-p-9 {
padding: 2.25rem;
.lg\:wpuf-grid-cols-3 {
.lg\:wpuf-p-9 {
padding: 2.25rem;
}
.lg\:wpuf-grid-cols-3 {
🤖 Prompt for AI Agents
In assets/css/admin/form-builder.css around lines 7191 to 7193, the
.lg\:wpuf-p-9 rule is missing its closing brace which causes the following
.lg\:wpuf-grid-cols-3 selector to be merged incorrectly; add a closing brace (})
and a newline immediately after the .lg\:wpuf-p-9 block so the
.lg\:wpuf-grid-cols-3 rule starts on its own line, preserving proper indentation
and CSS syntax.

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

Labels

QA Approved This PR is approved by the QA team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants