Skip to content

Conversation

@iftakharul-islam
Copy link
Member

@iftakharul-islam iftakharul-islam commented Oct 29, 2025

Fixes 199

Summary by CodeRabbit

  • New Features
    • Added Helpful Feedback block—a customizable yes/no voting widget for documentation pages with vote counting and duplicate submission prevention
    • Supports anonymous voting, multiple layout variants, and extensive styling customization (colors, typography, spacing, borders)
    • Displays thank-you message and vote summary after user submission with visual feedback

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Warning

Rate limit exceeded

@iftakharul-islam has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 14 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between bd002e6 and f6492fc.

⛔ Files ignored due to path filters (8)
  • assets/build/5f4138884ca3828fa2ff.svg is excluded by !**/*.svg
  • assets/build/fonts/wedocs.0e4fd4b5.ttf is excluded by !**/*.ttf
  • assets/build/fonts/wedocs.29ec52e7.woff is excluded by !**/*.woff
  • assets/build/images/pro-badge.aa003c10.png is excluded by !**/*.png
  • assets/build/images/slider-1.b05d3c91.jpg is excluded by !**/*.jpg
  • assets/build/images/slider-2.f7822c31.jpg is excluded by !**/*.jpg
  • assets/build/images/slider-3.ab3b7f94.jpg is excluded by !**/*.jpg
  • assets/build/images/slider-4.501d8d95.jpg is excluded by !**/*.jpg
📒 Files selected for processing (20)
  • assets/build/block.asset.php
  • assets/build/block.js
  • assets/build/blocks/DocsGrid/block.json
  • assets/build/blocks/DocsGrid/render.php
  • assets/build/editor.asset.php
  • assets/build/editor.js
  • assets/build/frontend.asset.php
  • assets/build/frontend.css
  • assets/build/frontend.js
  • assets/build/icons.asset.php
  • assets/build/icons.js
  • assets/build/index.asset.php
  • assets/build/index.css
  • assets/build/index.js
  • assets/build/print.asset.php
  • assets/build/print.css
  • assets/build/print.js
  • assets/build/store.asset.php
  • assets/build/store.js
  • assets/build/style-block.css

Walkthrough

This PR introduces a new "Helpful Feedback" Gutenberg block that enables users to vote on content helpfulness via Yes/No buttons. The feature includes a server-side renderer, AJAX vote handler, frontend voting UI with state management, comprehensive styling across editor and frontend, and vote tracking via cookies, user metadata, and IP address.

Changes

Cohort / File(s) Summary
Build Output Files
assets/build/block.js, assets/build/index.css, assets/build/style-block.css
JSX runtime wiring reorganization; artboard responsive size definitions; new .wedocs-helpful-feedback CSS component with state/layout variants
Built Block Definition & Renderer
assets/build/blocks/HelpfulFeedback/block.json, assets/build/blocks/HelpfulFeedback/render.php
Gutenberg block manifest with extensive configurable attributes; server-side renderer with vote tracking via cookie/user meta/IP and conditional pre/post-vote UI
Source Block Definition & Components
src/blocks/HelpfulFeedback/block.json, src/blocks/HelpfulFeedback/edit.js, src/blocks/HelpfulFeedback/index.js, src/blocks/HelpfulFeedback/save.js
Block metadata, React editor component with Inspector controls for styling/config, block registration, null save component
Block Rendering & Styling
src/blocks/HelpfulFeedback/render.php, src/blocks/HelpfulFeedback/style.scss
Server-side renderer (duplicate logic with built version); comprehensive SCSS with layout variants, responsive breakpoints, animations, accessibility
Frontend Voting Logic
assets/js/helpful-feedback.js, src/blocks/HelpfulFeedback/view.js
AJAX-driven voting handlers with duplicate submission prevention, error handling, thank-you UI, and custom event emission (duplicate implementations)
Backend AJAX Handler & Registration
includes/Ajax.php, src/blocks/index.js, wedocs.php
New AJAX vote handler with validation, duplicate prevention, vote tracking/storage; block registration in main plugin file

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Add docs grid #203: Modifies the same assets/build/block.js bundle with JSX runtime and module wiring changes that align with this PR's build output updates.

Suggested labels

Needs Review

Suggested reviewers

  • arifulhoque7

Poem

A rabbit hops with glee, 🐰
Voting "Yes!" for clarity,
Feedback flows so free,
Helpful, fair, and merry! ✨
Thumbs up to the spree!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat/helpful feedback block' clearly summarizes the main change: introducing a new helpful feedback block feature to the WeDocs plugin.

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.

@iftakharul-islam iftakharul-islam self-assigned this Oct 29, 2025
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: 7

🧹 Nitpick comments (19)
src/blocks/HelpfulFeedback/save.js (1)

1-1: Remove unused import

The useBlockProps import is not used in this component since it returns null for server-side rendering. Remove the unused import to keep the code clean.

Apply this diff:

-import { useBlockProps } from '@wordpress/block-editor';
-
 const Save = () => {
     return null;
 };
assets/build/blocks/HelpfulFeedback/block.json (1)

1-234: Avoid committing both source and build manifests to prevent drift.

This block.json duplicates src/blocks/HelpfulFeedback/block.json. Prefer a single source of truth (src) and generate build artifacts during build/release. If keeping both, add a CI check to ensure they stay in sync.

includes/Ajax.php (4)

43-46: Hooks look good; add capability/rate‑limit considerations if abuse becomes an issue.

Registration for both priv and nopriv is correct. Consider lightweight rate limiting (per IP) to reduce abuse.


332-336: Harden privacy: use a salted hash for IPs.

Replace md5($user_ip) with wp_hash($user_ip) to avoid reversible hashes and tie to site salts.

-            update_post_meta( $post_id, "wedocs_helpful_vote_ip_" . md5( $user_ip ), $vote );
+            update_post_meta( $post_id, "wedocs_helpful_vote_ip_" . wp_hash( $user_ip ), $vote );

339-343: Set secure cookie attributes (Secure, HttpOnly, SameSite).

Current setcookie lacks security attributes. Prefer the array options form (PHP ≥7.3):

-        setcookie( 'wedocs_response', $cookie_val, time() + WEEK_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
+        setcookie( 'wedocs_response', $cookie_val, [
+            'expires'  => time() + WEEK_IN_SECONDS,
+            'path'     => COOKIEPATH,
+            'domain'   => COOKIE_DOMAIN,
+            'secure'   => is_ssl(),
+            'httponly' => true,
+            'samesite' => 'Lax',
+        ] );

Note: If older PHP versions must be supported, we can fall back to the legacy signature without SameSite; confirm target PHP/WP matrix.


320-330: Non‑atomic vote check/update allows rare double counts under race.

Two rapid requests can both pass the "already voted" checks and increment. Mitigate with a short‑lived per‑user/IP transient lock or move the "mark as voted" write before increment with a unique check (e.g., add_post_meta + unique key) and rollback on failure.

src/blocks/HelpfulFeedback/edit.js (2)

1-16: Drop unused imports to reduce bundle size.

RichText, RangeControl, and BorderControl aren’t used.

-import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
+import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
@@
-    RangeControl,
-    __experimentalBorderControl as BorderControl,
+    // RangeControl,
+    // __experimentalBorderControl as BorderControl,

If these are planned soon, ignore.


104-113: Guard against undefined BoxControl values.

If containerPadding/Margin are ever undefined, template strings will output "undefined". Optionally default them when destructuring:

-        containerPadding,
-        containerMargin,
+        containerPadding = { top:'0', right:'0', bottom:'0', left:'0' },
+        containerMargin = { top:'0', right:'0', bottom:'0', left:'0' },
assets/js/helpful-feedback.js (1)

109-116: Optional: update hidden counts only when present.

Current logic is fine. If you want to suppress layout shift, also hide parentheses when counts are 0 in preview; not required.

assets/build/block.js (2)

1-1: Remove leftover console.log in production bundle

Drop the debug log to avoid console noise in users’ editors.

- console.log("editor panel:",r);
+ // debug log removed

1-1: Exclude built artifacts from linters to prevent false positives

The assets/build/ directory contains bundled artifacts that trigger unnecessary linter warnings (e.g., Biome's "used before declaration"). Create ignore files at the repository root:

+.eslintignore
+assets/build/
+
+.biomeignore
+assets/build/

Both ESLint and Biome will automatically discover and respect these files.

src/blocks/HelpfulFeedback/view.js (4)

32-41: Block repeat votes on already‑voted containers

Avoid unnecessary requests when the UI is already finalized.

-            // Check if already voting
-            if ($container.hasClass('loading')) {
+            // Prevent duplicate or post-vote clicks
+            if ($container.hasClass('loading') || $container.hasClass('has-voted')) {
                 return;
             }

141-155: Encode thank-you message before injecting HTML

Even though PHP escapes the data attribute, encode again before HTML interpolation.

-            const thankYouContent = `
+            const safeThankYou = $('<div>').text(thankYouMessage).html();
+            const thankYouContent = `
                 <div class="wedocs-feedback-thank-you">
                     <div class="wedocs-feedback-title" style="color: #28a745; margin-bottom: 16px;">
-                        ${thankYouMessage}
+                        ${safeThankYou}
                     </div>
                     <div class="wedocs-feedback-result">
 ...
             `;

55-70: Add an AJAX timeout and surface transport errors

Prevent long‑hung requests on flaky networks.

 $.ajax({
     url: wedocsHelpfulFeedback.ajax_url,
     type: 'POST',
     data: ajaxData,
     dataType: 'json',
+    timeout: 10000,

95-107: Internationalize user‑visible strings

Replace hardcoded messages with localized strings (wp.i18n or wp_localize_script). Example using localization:

- let errorMessage = 'An error occurred while voting';
+ let errorMessage = wedocsHelpfulFeedback.i18n_error_generic || 'An error occurred while voting';
...
- errorMessage = 'You are not authorized to vote';
+ errorMessage = wedocsHelpfulFeedback.i18n_error_unauthorized || 'You are not authorized to vote';
...
- errorMessage = 'Too many requests. Please try again later';
+ errorMessage = wedocsHelpfulFeedback.i18n_error_rate_limited || 'Too many requests. Please try again later';

And in PHP where the script is localized:

wp_localize_script(
  'wedocs-helpful-feedback-frontend',
  'wedocsHelpfulFeedback',
  [
    'ajax_url' => admin_url('admin-ajax.php'),
    'nonce'    => wp_create_nonce('wedocs_helpful_feedback_nonce'),
    'i18n_error_generic'      => __('An error occurred while voting','wedocs'),
    'i18n_error_unauthorized' => __('You are not authorized to vote','wedocs'),
    'i18n_error_rate_limited' => __('Too many requests. Please try again later','wedocs'),
  ]
);
src/blocks/HelpfulFeedback/render.php (3)

44-60: Harden cookie handling to numeric IDs

Cast cookie values to integers before comparison.

-    $previous = isset($_COOKIE['wedocs_response']) ? explode(',', $_COOKIE['wedocs_response']) : [];
-    if (in_array($post_id, $previous)) {
+    $previous = isset($_COOKIE['wedocs_response']) ? explode(',', $_COOKIE['wedocs_response']) : [];
+    $previous_ids = array_map('intval', $previous);
+    if (in_array((int) $post_id, $previous_ids, true)) {
         $has_voted = true;
         ...
     }

213-218: Normalize script URL join

Avoid double slashes by removing the leading slash after plugin_dir_url(...).

-wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) . '/assets/js/helpful-feedback.js', ['jquery'], WEDOCS_VERSION, true);
+wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) . 'assets/js/helpful-feedback.js', ['jquery'], WEDOCS_VERSION, true);

115-123: Border widths: honor per-side values

Current inline border uses only the top width for all sides. If you intend per-side widths, emit separate width/style/color.

-        $container_styles[] = sprintf(
-            'border: %s %s %s',
-            esc_attr($border_width['top'] ?? '1px'),
-            esc_attr($attributes['containerBorderStyle']),
-            esc_attr($attributes['containerBorderColor'] ?? '#e0e0e0')
-        );
+        $container_styles[] = sprintf(
+            'border-width: %s %s %s %s; border-style: %s; border-color: %s',
+            esc_attr($border_width['top'] ?? '1px'),
+            esc_attr($border_width['right'] ?? '1px'),
+            esc_attr($border_width['bottom'] ?? '1px'),
+            esc_attr($border_width['left'] ?? '1px'),
+            esc_attr($attributes['containerBorderStyle']),
+            esc_attr($attributes['containerBorderColor'] ?? '#e0e0e0')
+        );
assets/build/blocks/HelpfulFeedback/render.php (1)

44-47: Cast cookie IDs to integers

Same robustness improvement as the src file.

-    $previous = isset($_COOKIE['wedocs_response']) ? explode(',', $_COOKIE['wedocs_response']) : [];
-    if (in_array($post_id, $previous)) {
+    $previous = isset($_COOKIE['wedocs_response']) ? explode(',', $_COOKIE['wedocs_response']) : [];
+    $previous_ids = array_map('intval', $previous);
+    if (in_array((int) $post_id, $previous_ids, true)) {
         $has_voted = true;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51ef3cb and e2f035d.

📒 Files selected for processing (17)
  • assets/build/block.asset.php (1 hunks)
  • assets/build/block.js (1 hunks)
  • assets/build/blocks/HelpfulFeedback/block.json (1 hunks)
  • assets/build/blocks/HelpfulFeedback/render.php (1 hunks)
  • assets/build/index.css (2 hunks)
  • assets/build/style-block.css (1 hunks)
  • assets/js/helpful-feedback.js (1 hunks)
  • includes/Ajax.php (2 hunks)
  • src/blocks/HelpfulFeedback/block.json (1 hunks)
  • src/blocks/HelpfulFeedback/edit.js (1 hunks)
  • src/blocks/HelpfulFeedback/index.js (1 hunks)
  • src/blocks/HelpfulFeedback/render.php (1 hunks)
  • src/blocks/HelpfulFeedback/save.js (1 hunks)
  • src/blocks/HelpfulFeedback/style.scss (1 hunks)
  • src/blocks/HelpfulFeedback/view.js (1 hunks)
  • src/blocks/index.js (1 hunks)
  • wedocs.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/blocks/HelpfulFeedback/view.js (2)
src/utils/menuFix.js (1)
  • $ (2-2)
assets/js/frontend.js (1)
  • data (163-166)
src/blocks/HelpfulFeedback/edit.js (1)
src/blocks/CustomControls/RadioImageControl.js (1)
  • RadioImageControl (3-26)
assets/build/blocks/HelpfulFeedback/render.php (2)
src/blocks/HelpfulFeedback/render.php (1)
  • render_wedocs_helpful_feedback (20-407)
src/blocks/HelpfulFeedback/edit.js (1)
  • attributes (22-69)
src/blocks/HelpfulFeedback/render.php (2)
assets/build/blocks/HelpfulFeedback/render.php (1)
  • render_wedocs_helpful_feedback (20-407)
src/blocks/HelpfulFeedback/edit.js (1)
  • attributes (22-69)
src/blocks/HelpfulFeedback/index.js (2)
src/blocks/HelpfulFeedback/edit.js (1)
  • Edit (19-511)
src/blocks/HelpfulFeedback/save.js (1)
  • Save (3-5)
assets/build/block.js (1)
src/blocks/DocsGrid/edit.js (1)
  • wp (16-16)
🪛 Biome (2.1.2)
assets/build/block.js

[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🔇 Additional comments (13)
assets/build/index.css (1)

3190-3230: Build artifact - auto-generated CSS

This file contains compiled CSS output. The changes include:

  • Minor selector formatting adjustment (line 3190-3192)
  • New responsive artboard utility classes for horizontal phone layouts (lines 3201-3230)

These are expected build artifacts and don't require detailed review.

src/blocks/index.js (1)

3-3: LGTM - Block import follows established pattern

The HelpfulFeedback block import is correctly added alongside existing block imports, maintaining consistency with the codebase structure.

wedocs.php (2)

50-50: LGTM - Render file inclusion follows established pattern

The render file is properly included using the same pattern as the DocsGrid block (line 49), ensuring consistency across block implementations.


187-193: LGTM - Block registration is properly structured

The HelpfulFeedback block registration:

  • Follows the same pattern as DocsGrid (lines 180-185)
  • Uses the correct path to the block directory
  • Specifies the appropriate render callback function
  • Maintains consistency with existing block registration conventions
assets/build/block.asset.php (1)

1-1: Expected build artifact update

The version hash change is an expected result of the build process after adding the new HelpfulFeedback block. Dependencies remain unchanged.

src/blocks/HelpfulFeedback/index.js (1)

1-17: LGTM - Standard Gutenberg block registration

The block registration follows WordPress best practices:

  • Properly imports registerBlockType from @wordpress/blocks
  • Loads Edit and Save components
  • References metadata from block.json
  • Includes stylesheet for proper styling
  • Clean, maintainable structure
assets/build/style-block.css (1)

3-3: Build artifact - compiled CSS

This is the compiled/minified output from src/blocks/HelpfulFeedback/style.scss. The CSS includes comprehensive styling for the Helpful Feedback block with accessibility, responsive design, and print styles. As a build artifact, it doesn't require detailed review.

src/blocks/HelpfulFeedback/style.scss (1)

1-294: Excellent styling implementation with strong accessibility focus

This SCSS file demonstrates best practices:

Accessibility Features:

  • Minimum touch target sizes (44px × 44px) on line 38-39
  • Clear focus indicators with 2px outline (lines 41-44)
  • Proper disabled state handling (lines 46-49)
  • High contrast mode support (lines 253-259)
  • Reduced motion support (lines 262-271)

Responsive Design:

  • Mobile-first approach with appropriate breakpoints
  • Layout adapts at 480px for different screen sizes (lines 165-172, 175-194)
  • Flexible button arrangements

Additional Strengths:

  • Well-organized with clear section comments
  • Two distinct layout variants (layout1: rectangular, layout2: circular)
  • Loading and voted state management
  • Print-optimized styles (lines 274-294)
  • Smooth animations with accessibility fallbacks
src/blocks/HelpfulFeedback/block.json (1)

18-38: Ensure the server derives allowAnonymous from this attribute, not the request.

The AJAX handler should read allowAnonymous from the block config for the given post, otherwise clients can bypass login by posting allow_anonymous=true. See my comment in includes/Ajax.php for a concrete fix using parse_blocks.

assets/js/helpful-feedback.js (1)

47-53: Client may send allow_anonymous, but server must ignore it.

Keep sending it if you need UI parity, but ensure the server derives the setting from the block, not from this value (see Ajax.php fix).

includes/Ajax.php (1)

260-266: Nonce setup verified as correct.

The nonce is properly created with wp_create_nonce('wedocs_helpful_feedback_nonce') and localized to wedocsHelpfulFeedback.nonce at ./src/blocks/HelpfulFeedback/render.php:215-217. The action name matches what's verified in Ajax.php, following standard WordPress security practices.

src/blocks/HelpfulFeedback/view.js (1)

195-201: I need to verify if src/blocks/HelpfulFeedback/view.js is loaded separately or is just a build source file.

The review comment is incorrect—no double initialization risk exists.

The codebase uses a standard WordPress build process where src/blocks/HelpfulFeedback/view.js is a source file that gets compiled to assets/js/helpful-feedback.js. Only one script is enqueued via wp_enqueue_script() with the single handle wedocs-helpful-feedback-frontend, pointing to assets/js/helpful-feedback.js. Since only the built file loads on the frontend, there is no scenario where both files execute or double-bind event handlers.

The identical code in both files confirms the src-to-build relationship—not separate parallel loading.

Likely an incorrect or invalid review comment.

src/blocks/HelpfulFeedback/render.php (1)

20-20: No collision risk exists; the review comment is incorrect.

Only assets/build/blocks/HelpfulFeedback/render.php is loaded at runtime via the registered register_block_type() call in wedocs.php:188. The src/blocks/HelpfulFeedback/render.php file is never executed—it is not independently required anywhere and is not registered as a block. Therefore, both function definitions never coexist in memory, and no fatal redeclaration error can occur. The suggested guard is unnecessary.

Likely an incorrect or invalid review comment.

Comment on lines 1 to 7
<?php
/**
* Server-side rendering for the Helpful Feedback block
*
* @package weDocs
*/

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

Avoid duplicate sources of truth

Having both this built PHP and src/blocks/HelpfulFeedback/render.php risks drift and redeclare fatals. Prefer a single canonical render file (ideally the one co-located with block.json used by register_block_type_from_metadata) and remove or exclude the other from loading.


🏁 Script executed:

#!/bin/bash
rg -n "render.php" assets/build/blocks/HelpfulFeedback src/blocks/HelpfulFeedback -S

Length of output: 155



---

🏁 Script executed:

```shell
#!/bin/bash
# Check if both render.php files exist and compare their contents
echo "=== Checking render.php files ==="
for file in assets/build/blocks/HelpfulFeedback/render.php src/blocks/HelpfulFeedback/render.php; do
  if [ -f "$file" ]; then
    echo "✓ Found: $file"
  else
    echo "✗ Not found: $file"
  fi
done

echo -e "\n=== Content comparison ==="
if [ -f "assets/build/blocks/HelpfulFeedback/render.php" ] && [ -f "src/blocks/HelpfulFeedback/render.php" ]; then
  echo "File sizes:"
  wc -c assets/build/blocks/HelpfulFeedback/render.php src/blocks/HelpfulFeedback/render.php
  echo -e "\nDifference check:"
  diff assets/build/blocks/HelpfulFeedback/render.php src/blocks/HelpfulFeedback/render.php && echo "Files are identical" || echo "Files differ"
fi

# Look for build config files
echo -e "\n=== Build configuration files ==="
fd -n "webpack|rollup|gulp|tsconfig|package\.json" --max-depth 2

Length of output: 906


Remove or regenerate the built render.php file to maintain a single source of truth

The two render.php files differ on line 214—assets/build has hardcoded './assets/js/helpful-feedback.js' and version '1.0.0', while src has /assets/js/helpful-feedback.js and WEDOCS_VERSION. This confirms the built version is stale. Delete assets/build/blocks/HelpfulFeedback/render.php or ensure it's properly generated from the source during your build process to prevent maintenance burden and potential runtime issues.

🤖 Prompt for AI Agents
In assets/build/blocks/HelpfulFeedback/render.php lines 1-7, the built file is
stale (differs at line 214: it uses a hardcoded
'./assets/js/helpful-feedback.js' and version '1.0.0' vs src which uses
'/assets/js/helpful-feedback.js' and WEDOCS_VERSION); remove
assets/build/blocks/HelpfulFeedback/render.php from the repo or regenerate it
from src so the built copy matches the single source of truth, and if
regenerating, run the build task and update the build script to emit the correct
path and WEDOCS_VERSION constant so the generated file stays in sync.

Comment on lines 213 to 218
// Enqueue frontend script and styles
wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) .'./assets/js/helpful-feedback.js', ['jquery'], '1.0.0', true);
wp_localize_script('wedocs-helpful-feedback-frontend', 'wedocsHelpfulFeedback', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wedocs_helpful_feedback_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 | 🟠 Major

Align script enqueue with plugin constants and clean URL

Use the version constant and drop ./ for predictable caching and correct URLs.

-wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) .'./assets/js/helpful-feedback.js', ['jquery'], '1.0.0', true);
+wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) . 'assets/js/helpful-feedback.js', ['jquery'], WEDOCS_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
// Enqueue frontend script and styles
wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) .'./assets/js/helpful-feedback.js', ['jquery'], '1.0.0', true);
wp_localize_script('wedocs-helpful-feedback-frontend', 'wedocsHelpfulFeedback', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wedocs_helpful_feedback_nonce')
]);
// Enqueue frontend script and styles
wp_enqueue_script('wedocs-helpful-feedback-frontend', plugin_dir_url(WEDOCS_FILE) . 'assets/js/helpful-feedback.js', ['jquery'], WEDOCS_VERSION, true);
wp_localize_script('wedocs-helpful-feedback-frontend', 'wedocsHelpfulFeedback', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wedocs_helpful_feedback_nonce')
]);
🤖 Prompt for AI Agents
In assets/build/blocks/HelpfulFeedback/render.php around lines 213 to 218, the
script enqueue uses a hardcoded version and a malformed path with "./"; change
the path to concatenate plugin_dir_url(WEDOCS_FILE) with
'assets/js/helpful-feedback.js' (remove the "./") and replace the hardcoded
'1.0.0' with the plugin version constant (e.g., WEDOCS_VERSION); if there are
matching style enqueues nearby, apply the same path and version constant changes
for consistency and predictable caching.

Comment on lines 388 to 394
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php echo esc_attr($alignment); ?>;
margin-bottom: 10px;
}
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

Fix flex alignment mapping here as well

Mirror the mapping fix from the src version so “right” aligns correctly.

-        justify-content: <?php echo esc_attr($alignment); ?>;
+        justify-content: <?php
+            $justify = 'center';
+            if ( 'left' === $alignment )  { $justify = 'flex-start'; }
+            if ( 'right' === $alignment ) { $justify = 'flex-end'; }
+            echo esc_attr( $justify );
+        ?>;
📝 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
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php echo esc_attr($alignment); ?>;
margin-bottom: 10px;
}
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php
$justify = 'center';
if ( 'left' === $alignment ) { $justify = 'flex-start'; }
if ( 'right' === $alignment ) { $justify = 'flex-end'; }
echo esc_attr( $justify );
?>;
margin-bottom: 10px;
}
🤖 Prompt for AI Agents
In assets/build/blocks/HelpfulFeedback/render.php around lines 388–394, the CSS
is using the raw $alignment value for justify-content which causes "right" to
not align correctly; replace the direct echo of $alignment with a mapped value
(e.g., map 'left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end')
and echo that mapped value with a sensible default fallback (such as
'flex-start') so the built file mirrors the src alignment fix.

Comment on lines +141 to +161
const thankYouContent = `
<div class="wedocs-feedback-thank-you">
<div class="wedocs-feedback-title" style="color: #28a745; margin-bottom: 16px;">
${thankYouMessage}
</div>
<div class="wedocs-feedback-result">
<div class="wedocs-feedback-voted-option voted-${vote}" style="display: flex; align-items: center; gap: 8px; justify-content: ${$container.hasClass('left') ? 'flex-start' : $container.hasClass('right') ? 'flex-end' : 'center'}; margin-bottom: 10px;">
<span class="wedocs-feedback-icon">${voteIcon}</span>
${voteText}
</div>
${voteSummary}
</div>
</div>
`;

// Fade out buttons and fade in thank you message
$buttons.fadeOut(300, function() {
$title.fadeOut(200, function() {
$container.append(thankYouContent);
$container.find('.wedocs-feedback-thank-you').hide().fadeIn(400);
});
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

Escape thankYouMessage to prevent XSS.

thankYouMessage comes from markup attributes; avoid inserting it as HTML. Build DOM with text nodes instead of string HTML.

Apply this change:

-            const thankYouContent = `
-                <div class="wedocs-feedback-thank-you">
-                    <div class="wedocs-feedback-title" style="color: #28a745; margin-bottom: 16px;">
-                        ${thankYouMessage}
-                    </div>
-                    <div class="wedocs-feedback-result">
-                        <div class="wedocs-feedback-voted-option voted-${vote}" style="display: flex; align-items: center; gap: 8px; justify-content: ${$container.hasClass('left') ? 'flex-start' : $container.hasClass('right') ? 'flex-end' : 'center'}; margin-bottom: 10px;">
-                            <span class="wedocs-feedback-icon">${voteIcon}</span>
-                            ${voteText}
-                        </div>
-                        ${voteSummary}
-                    </div>
-                </div>
-            `;
+            const $thankYou = $('<div/>', { class: 'wedocs-feedback-thank-you' });
+            const $titleDiv = $('<div/>', {
+                class: 'wedocs-feedback-title',
+                style: 'color:#28a745;margin-bottom:16px;'
+            }).text(thankYouMessage);
+            const $result = $('<div/>', { class: 'wedocs-feedback-result' });
+            const $voted = $('<div/>', {
+                class: `wedocs-feedback-voted-option voted-${vote}`,
+                style: `display:flex;align-items:center;gap:8px;justify-content:${$container.hasClass('left') ? 'flex-start' : $container.hasClass('right') ? 'flex-end' : 'center'};margin-bottom:10px;`
+            }).append($('<span/>', { class: 'wedocs-feedback-icon', html: voteIcon })).append(document.createTextNode(' ' + voteText));
+            $result.append($voted);
+            if (voteSummary) {
+                $result.append($(voteSummary));
+            }
+            $thankYou.append($titleDiv).append($result);

And below:

-                    $container.append(thankYouContent);
-                    $container.find('.wedocs-feedback-thank-you').hide().fadeIn(400);
+                    $container.append($thankYou.hide());
+                    $thankYou.fadeIn(400);
📝 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
const thankYouContent = `
<div class="wedocs-feedback-thank-you">
<div class="wedocs-feedback-title" style="color: #28a745; margin-bottom: 16px;">
${thankYouMessage}
</div>
<div class="wedocs-feedback-result">
<div class="wedocs-feedback-voted-option voted-${vote}" style="display: flex; align-items: center; gap: 8px; justify-content: ${$container.hasClass('left') ? 'flex-start' : $container.hasClass('right') ? 'flex-end' : 'center'}; margin-bottom: 10px;">
<span class="wedocs-feedback-icon">${voteIcon}</span>
${voteText}
</div>
${voteSummary}
</div>
</div>
`;
// Fade out buttons and fade in thank you message
$buttons.fadeOut(300, function() {
$title.fadeOut(200, function() {
$container.append(thankYouContent);
$container.find('.wedocs-feedback-thank-you').hide().fadeIn(400);
});
const $thankYou = $('<div/>', { class: 'wedocs-feedback-thank-you' });
const $titleDiv = $('<div/>', {
class: 'wedocs-feedback-title',
style: 'color:#28a745;margin-bottom:16px;'
}).text(thankYouMessage);
const $result = $('<div/>', { class: 'wedocs-feedback-result' });
const $voted = $('<div/>', {
class: `wedocs-feedback-voted-option voted-${vote}`,
style: `display:flex;align-items:center;gap:8px;justify-content:${$container.hasClass('left') ? 'flex-start' : $container.hasClass('right') ? 'flex-end' : 'center'};margin-bottom:10px;`
}).append($('<span/>', { class: 'wedocs-feedback-icon', html: voteIcon })).append(document.createTextNode(' ' + voteText));
$result.append($voted);
if (voteSummary) {
$result.append($(voteSummary));
}
$thankYou.append($titleDiv).append($result);
// Fade out buttons and fade in thank you message
$buttons.fadeOut(300, function() {
$title.fadeOut(200, function() {
$container.append($thankYou.hide());
$thankYou.fadeIn(400);
});
🤖 Prompt for AI Agents
In assets/js/helpful-feedback.js around lines 141 to 161, the template string
injects thankYouMessage directly into HTML which risks XSS; replace the
string-concatenation approach with DOM construction so the thankYouMessage is
inserted as a text node (e.g., create the .wedocs-feedback-thank-you and child
elements with jQuery/DOM APIs and use .text() or textContent for
thankYouMessage) instead of embedding it in the HTML string, then append and
fade the constructed nodes as before; ensure any other user-derived strings used
there are likewise inserted via text methods rather than raw HTML.

Comment on lines +268 to +295
$post_id = intval( $_POST['post_id'] ?? 0 );
$vote = sanitize_text_field( $_POST['vote'] ?? '' );
$allow_anonymous = filter_var( $_POST['allow_anonymous'] ?? true, FILTER_VALIDATE_BOOLEAN );

if ( ! $post_id || ! in_array( $vote, [ 'yes', 'no' ] ) ) {
wp_send_json_error( [
'message' => __( 'Invalid voting data.', 'wedocs' )
] );
}

// Verify this is a docs post
if ( get_post_type( $post_id ) !== 'docs' ) {
wp_send_json_error( [
'message' => __( 'Invalid post type.', 'wedocs' )
] );
}

// Get current user ID and IP
$user_id = get_current_user_id();
$user_ip = $_SERVER['REMOTE_ADDR'] ?? '';

// Check if user can vote
if ( ! $user_id && ! $allow_anonymous ) {
wp_send_json_error( [
'message' => __( 'You must be logged in to vote.', 'wedocs' )
] );
}

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

Auth bypass: do not trust client‑provided allow_anonymous.

Clients can set allow_anonymous=true to bypass the login requirement. Derive this from the block configuration for the target post instead of $_POST.

Apply this change and helper:

-        $vote = sanitize_text_field( $_POST['vote'] ?? '' );
-        $allow_anonymous = filter_var( $_POST['allow_anonymous'] ?? true, FILTER_VALIDATE_BOOLEAN );
+        $vote = sanitize_text_field( $_POST['vote'] ?? '' );
+        // Derive from block attributes in post content; default to true if not found.
+        $allow_anonymous = (bool) $this->get_helpful_feedback_setting( $post_id, 'allowAnonymous', true );

Add this helper inside the class (outside any method):

/**
 * Read Helpful Feedback block attribute from post content.
 *
 * @param int    $post_id
 * @param string $key
 * @param mixed  $default
 * @return mixed
 */
private function get_helpful_feedback_setting( $post_id, $key, $default = null ) {
    $post = get_post( $post_id );
    if ( ! $post ) {
        return $default;
    }
    $blocks = parse_blocks( $post->post_content );
    foreach ( $blocks as $block ) {
        if ( isset( $block['blockName'] ) && 'wedocs/helpful-feedback' === $block['blockName'] ) {
            if ( isset( $block['attrs'][ $key ] ) ) {
                return $block['attrs'][ $key ];
            }
        }
    }
    return $default;
}

This prevents clients from toggling auth in transit and honors the editor setting.

🤖 Prompt for AI Agents
In includes/Ajax.php around lines 268 to 295, the current code trusts a
client-supplied $_POST['allow_anonymous'], allowing an auth bypass; replace that
by reading the post's Helpful Feedback block attribute and use it to determine
whether anonymous voting is allowed. Add the provided private helper
get_helpful_feedback_setting($post_id, $key, $default = null) inside the class
(outside any method), then call it for the key that controls anonymous voting
(e.g. 'allowAnonymous' or the actual attribute name used) to set
$allow_anonymous instead of filter_var($_POST['allow_anonymous'] ...), and keep
the existing login check logic unchanged.

Comment on lines +388 to +394
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php echo esc_attr($alignment); ?>;
margin-bottom: 10px;
}
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

Fix invalid flex alignment (justify-content)

justify-content doesn’t accept “left/right”. Map to flex values to render correctly for “right”.

Apply:

-    #<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
+    #<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
         display: flex;
         align-items: center;
         gap: 8px;
-        justify-content: <?php echo esc_attr($alignment); ?>;
+        justify-content: <?php
+            $justify = 'center';
+            if ( 'left' === $alignment )  { $justify = 'flex-start'; }
+            if ( 'right' === $alignment ) { $justify = 'flex-end'; }
+            echo esc_attr( $justify );
+        ?>;
         margin-bottom: 10px;
     }
📝 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
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php echo esc_attr($alignment); ?>;
margin-bottom: 10px;
}
#<?php echo esc_attr($block_id); ?> .wedocs-feedback-voted-option {
display: flex;
align-items: center;
gap: 8px;
justify-content: <?php
$justify = 'center';
if ( 'left' === $alignment ) { $justify = 'flex-start'; }
if ( 'right' === $alignment ) { $justify = 'flex-end'; }
echo esc_attr( $justify );
?>;
margin-bottom: 10px;
}
🤖 Prompt for AI Agents
In src/blocks/HelpfulFeedback/render.php around lines 388 to 394, the CSS uses
justify-content: <?php echo esc_attr($alignment); ?> but justify-content does
not accept "left"/"right"; map those values to valid flex values (use
"flex-start" for "left", "flex-end" for "right", keep "center" as-is) and output
the mapped value instead of the raw $alignment (e.g., compute a safe $justify =
$alignment === 'left' ? 'flex-start' : ($alignment === 'right' ? 'flex-end' :
$alignment) and echo esc_attr($justify)).

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

♻️ Duplicate comments (1)
includes/Ajax.php (1)

262-298: Critical auth bypass: client-controlled allow_anonymous

Line 273 reads allow_anonymous from $_POST, allowing attackers to bypass authentication by simply setting allow_anonymous=true in the request. This security flaw was flagged in previous reviews but remains unaddressed.

Fix: Derive allow_anonymous from the block's saved attributes in the post content rather than trusting client input. The block configuration is stored server-side and cannot be manipulated by clients.

🔎 Recommended fix

Add a helper method to read the block attribute from post content:

/**
 * Read Helpful Feedback block attribute from post content.
 *
 * @param int    $post_id
 * @param string $key
 * @param mixed  $default
 * @return mixed
 */
private function get_helpful_feedback_setting( $post_id, $key, $default = null ) {
    $post = get_post( $post_id );
    if ( ! $post ) {
        return $default;
    }
    $blocks = parse_blocks( $post->post_content );
    foreach ( $blocks as $block ) {
        if ( isset( $block['blockName'] ) && 'wedocs/helpful-feedback' === $block['blockName'] ) {
            if ( isset( $block['attrs'][ $key ] ) ) {
                return $block['attrs'][ $key ];
            }
        }
    }
    return $default;
}

Then replace line 273:

-        $allow_anonymous = filter_var( $_POST['allow_anonymous'] ?? true, FILTER_VALIDATE_BOOLEAN );
+        $allow_anonymous = (bool) $this->get_helpful_feedback_setting( $post_id, 'allowAnonymous', true );

Based on learnings from past review comments.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2f035d and bd002e6.

📒 Files selected for processing (4)
  • assets/build/block.js
  • assets/build/index.css
  • includes/Ajax.php
  • wedocs.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • wedocs.php
🧰 Additional context used
🧬 Code graph analysis (1)
assets/build/block.js (2)
assets/build/editor.js (2)
  • l (1-1)
  • a (1-1)
src/blocks/DocsGrid/edit.js (1)
  • wp (16-16)
🪛 Biome (2.1.2)
assets/build/block.js

[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🔇 Additional comments (3)
assets/build/index.css (1)

2996-2996: LGTM: CSS formatting and responsive artboard additions

The selector formatting fix and new horizontal phone artboard sizes are well-structured and follow consistent patterns. These additions support multi-device responsive layouts for the UI components.

Also applies to: 3007-3036

includes/Ajax.php (1)

264-268: Well-implemented vote handling logic

The nonce verification, input validation, post type checking, duplicate vote prevention, and vote recording logic are well-structured. The extensibility hook at line 352 is a nice touch for future enhancements.

The combination of cookie-based, user meta, and IP-based tracking provides reasonable protection against duplicate votes (acknowledging the IP limitations noted separately).

Also applies to: 275-286, 299-361

assets/build/block.js (1)

1-1: Built file - source review recommended

This is a minified/built JavaScript file. Meaningful code review should be performed on the source files (e.g., src/blocks/HelpfulFeedback/) rather than the compiled output.

The static analysis "used before declaration" errors are false positives common in bundled code due to JavaScript hoisting and the way webpack structures modules.

To properly review the block logic, please examine the source files:

  • src/blocks/HelpfulFeedback/edit.js
  • src/blocks/HelpfulFeedback/save.js
  • src/blocks/HelpfulFeedback/view.js
  • src/blocks/DocsGrid/edit.js

These would provide better context for the actual changes and logic being introduced.

Comment on lines +288 to +321
// Get current user ID and IP
$user_id = get_current_user_id();
$user_ip = $_SERVER['REMOTE_ADDR'] ?? '';

// Check if user can vote
if ( ! $user_id && ! $allow_anonymous ) {
wp_send_json_error( [
'message' => __( 'You must be logged in to vote.', 'wedocs' )
] );
}

// Check if user has already voted
$has_voted = false;

// Check cookie-based tracking (for compatibility with existing system)
$previous = isset( $_COOKIE['wedocs_response'] ) ? explode( ',', $_COOKIE['wedocs_response'] ) : [];
if ( in_array( $post_id, $previous ) ) {
$has_voted = true;
}

// Check user-specific voting records
if ( ! $has_voted && $user_id ) {
// Check by user ID
$user_vote = get_post_meta( $post_id, "wedocs_helpful_vote_user_{$user_id}", true );
if ( $user_vote ) {
$has_voted = true;
}
} elseif ( ! $has_voted && $allow_anonymous && $user_ip ) {
// Check by IP for anonymous users
$ip_vote = get_post_meta( $post_id, "wedocs_helpful_vote_ip_" . md5( $user_ip ), true );
if ( $ip_vote ) {
$has_voted = true;
}
}
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the Ajax.php file
fd "Ajax.php" --type f

Repository: weDevsOfficial/wedocs-plugin

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Read the specific lines mentioned in the review (lines 288-338 to see all mentioned usages)
if [ -f "includes/Ajax.php" ]; then
  wc -l includes/Ajax.php
  echo "--- Lines 288-340 of includes/Ajax.php ---"
  sed -n '288,340p' includes/Ajax.php
fi

Repository: weDevsOfficial/wedocs-plugin

Length of output: 2217


🏁 Script executed:

#!/bin/bash
# Search for all occurrences of REMOTE_ADDR and X-Forwarded-For in the file
echo "=== REMOTE_ADDR occurrences ==="
rg "REMOTE_ADDR" includes/ -n
echo ""
echo "=== X-Forwarded-For occurrences ==="
rg "X_FORWARDED_FOR|X-Forwarded-For" includes/ -n

Repository: weDevsOfficial/wedocs-plugin

Length of output: 689


🏁 Script executed:

#!/bin/bash
# Let me check the functions.php file to see if there's already an IP utility function
echo "--- Lines 360-380 of includes/functions.php (context around X-Forwarded-For) ---"
sed -n '360,380p' includes/functions.php

Repository: weDevsOfficial/wedocs-plugin

Length of output: 922


🏁 Script executed:

#!/bin/bash
# Get a fuller view of the IP handling function in functions.php
echo "--- Search for function definition near the IP handling code ---"
sed -n '350,390p' includes/functions.php

Repository: weDevsOfficial/wedocs-plugin

Length of output: 1179


🏁 Script executed:

#!/bin/bash
# Check if wedocs_get_ip_address() is being used elsewhere in the codebase
echo "=== Usage of wedocs_get_ip_address() function ==="
rg "wedocs_get_ip_address" --type php -n

Repository: weDevsOfficial/wedocs-plugin

Length of output: 326


🏁 Script executed:

#!/bin/bash
# Check if there are other places in Ajax.php that might be using this pattern
echo "=== All IP-related code in Ajax.php ==="
rg "\\\$_SERVER\['REMOTE_ADDR" includes/Ajax.php -B 2 -A 2 -n

Repository: weDevsOfficial/wedocs-plugin

Length of output: 296


🏁 Script executed:

#!/bin/bash
# Check for any IP validation in the existing wedocs_get_ip_address function or surrounding code
echo "=== Full wedocs_get_ip_address function and context ==="
sed -n '355,380p' includes/functions.php

Repository: weDevsOfficial/wedocs-plugin

Length of output: 955


🏁 Script executed:

#!/bin/bash
# Check if there are any other security/validation measures around IP in the codebase
echo "=== Search for filter_var or IP validation patterns ==="
rg "filter_var.*FILTER_VALIDATE_IP" includes/ -n
echo ""
echo "=== Search for IP sanitization ==="
rg "sanitize.*ip|validate.*ip" includes/ -i -n

Repository: weDevsOfficial/wedocs-plugin

Length of output: 337


Use the existing wedocs_get_ip_address() function instead of direct $_SERVER access

Line 290 directly accesses $_SERVER['REMOTE_ADDR'] for IP-based duplicate-vote prevention, but the codebase already has a wedocs_get_ip_address() function (in includes/functions.php) that properly handles multiple proxy headers (HTTP_CLIENT_IP, X-Forwarded-For, etc.).

Replace line 290 with:

$user_ip = wedocs_get_ip_address();

This reuses existing infrastructure instead of duplicating IP detection logic.

Note: The wedocs_get_ip_address() function itself lacks IP validation; consider adding filter_var($ipaddress, FILTER_VALIDATE_IP) checks in that function to reject malformed IPs.

🤖 Prompt for AI Agents
In includes/Ajax.php around lines 288 to 321, replace the direct
$_SERVER['REMOTE_ADDR'] access with a call to the project helper
wedocs_get_ip_address() so IP-based duplicate-vote checks use the centralized
proxy-aware resolver; specifically change the assignment of $user_ip to use
wedocs_get_ip_address() and keep the subsequent md5/post_meta IP check logic
intact, and (optionally) ensure the helper performs FILTER_VALIDATE_IP
validation so malformed values are rejected before storing/checking.

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.

2 participants