Skip to content

Be more explicit with who can save and clear issues for a given post - #1202

Closed
pattonwebz wants to merge 13 commits into
developfrom
william/no-ticket/enhance-capability-checking
Closed

Be more explicit with who can save and clear issues for a given post#1202
pattonwebz wants to merge 13 commits into
developfrom
william/no-ticket/enhance-capability-checking

Conversation

@pattonwebz

@pattonwebz pattonwebz commented Aug 19, 2025

Copy link
Copy Markdown
Member

This pull request improves permission handling for REST API endpoints and frontend UI elements to ensure that only users with the appropriate capabilities can perform actions related to post accessibility scans. It introduces a more granular permission check for editing posts, updates the frontend logic to match these checks, and adds comprehensive tests to verify correct behavior.

Permission handling improvements

  • Replaced generic edit_posts capability checks in REST API endpoint registration with a new method, user_can_edit_passed_post_id, which checks if the current user can edit the specific post ID provided in the request. This change is applied to both the post scan results and clear issues endpoints in class-rest-api.php. [1] [2] [3]
  • Added the userCanEdit property to the frontend highlighter app's initialization data, ensuring the UI can accurately reflect the user's ability to edit the current post.

Frontend UI logic updates

  • Updated the frontend highlighter panel logic in index.js to show the "Clear Issues" and "Rescan This Page" buttons only to users who can both edit the post and are logged in, aligning the UI with the new permission checks. [1] [2]

Testing

  • Added a new test class, RestApiEndpointsTest, to verify that only users with edit permissions for a specific post can save scan results or clear issues via the REST API. This includes tests for both admin and limited users.

Checklist

  • PR is linked to the main issue in the repo
  • Tests are added that cover changes

Summary by CodeRabbit

  • New Features

    • Frontend now receives a combined permission flag (logged-in + per-post edit) and UI buttons (Clear Issues, Rescan) respect it.
  • Bug Fixes

    • REST endpoints enforce per-post edit permissions; missing/invalid post id returns 400 and unauthorized requests are blocked.
  • Refactor

    • REST permission checks consolidated to use per-post validation.
  • Tests

    • Added automated tests validating per-post permission behavior for REST endpoints.
  • Chores

    • Admin "Update Counts" button now shown only to users with publish capability.

…ighter

This is used alongside the other logged in check to determine if we show a button to rescan or clear issues to a given user
Copilot AI review requested due to automatic review settings August 19, 2025 12:52
@coderabbitai

coderabbitai Bot commented Aug 19, 2025

Copy link
Copy Markdown
Contributor

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a frontend localization flag userCanEdit (from current_user_can('edit_post', $post_id)), enforces per-post edit permissions for REST routes via user_can_edit_passed_post_id(), updates the frontend highlighter to gate controls on userCanEdit && loggedIn, and adds PHPUnit tests for REST permission behavior.

Changes

Cohort / File(s) Summary
Frontend localization data
includes/classes/class-enqueue-frontend.php
Adds userCanEdit to edacFrontendHighlighterApp via wp_localize_script, set from current_user_can('edit_post', $post_id).
REST API permission model
includes/classes/class-rest-api.php
Adds public function user_can_edit_passed_post_id( $request ); routes with (?P<id>\d+) now validate/sanitize id and use the new permission callback performing current_user_can('edit_post', $id) (returns WP_Error 400 if id missing).
Frontend UI gating
src/frontendHighlighterApp/index.js
Replaces isLoggedInUser gating with userCanEdit && loggedIn for Clear Issues/Rescan visibility and updates related markup/classes.
REST endpoint tests
tests/phpunit/includes/classes/RestApiEndpointsTest.php
Adds tests asserting per-post permission behavior for /post-scan-results/{id} and /clear-issues/{id} (admin vs limited user; limited user managing own post).
Admin UI visibility tweak
admin/class-welcome-page.php
Renders "Update Counts" button only for users with publish_posts capability (wrapped in current_user_can('publish_posts')).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Browser as User (Browser)
  participant FE as Frontend Highlighter
  participant WP as WP REST Router
  participant API as REST_Api
  participant Cap as current_user_can

  rect rgba(230,240,255,0.6)
  note right of FE: Uses localized edacFrontendHighlighterApp.userCanEdit & loggedIn
  Browser->>FE: Load page
  FE->>FE: Read edacFrontendHighlighterApp.userCanEdit & loggedIn
  alt userCanEdit && loggedIn
    FE->>Browser: Show "Clear Issues" / "Rescan"
  else
    FE->>Browser: Hide controls
  end
  end

  rect rgba(240,255,230,0.6)
  note right of WP: REST request flow with per-post permission check
  Browser->>WP: POST /post-scan-results/{id}
  WP->>API: permission_callback($request)
  API->>API: Ensure id present (400 if missing)
  API->>Cap: current_user_can('edit_post', id)
  Cap-->>API: true / false
  API-->>WP: allow / deny
  alt Allowed
    WP-->>Browser: 200 OK
  else Denied
    WP-->>Browser: 403 or 400
  end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • pattonwebz

Poem

I’m a rabbit in the code, twitching my small nose,
I ask “who may edit?” where the permission goes.
Buttons bloom when allowed, hidden where they’re not,
I hop, I guard, I mark the gate — a tiny access spot. 🐇✨

Tip

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

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

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch william/no-ticket/enhance-capability-checking

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Status, Documentation and Community

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Summary of Changes

Hello @pattonwebz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the permission system for accessibility scan features, ensuring that only users with explicit editing rights for a specific post can save scan results or clear issues. It updates both backend REST API endpoints and frontend UI elements to enforce more granular access control, enhancing security and data integrity.

Highlights

  • Enhanced REST API Permissions: Replaced broad 'edit_posts' capability checks with a new, specific 'user_can_edit_passed_post_id' method for accessibility scan-related REST API endpoints, ensuring users can only modify posts they are authorized to edit.
  • Dynamic Frontend UI Control: Updated the frontend highlighter panel to conditionally display 'Clear Issues' and 'Rescan This Page' buttons, making them visible only to users who are logged in and possess the specific capability to edit the current post.
  • Comprehensive Permission Testing: Introduced a new PHPUnit test class, 'RestApiEndpointsTest', to rigorously verify that the updated REST API permission checks function correctly for both administrative and limited users, preventing unauthorized actions.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

This comment was marked as outdated.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request does a great job of improving permission handling for the REST API endpoints and frontend UI. The change to use a more granular permission check for editing specific posts is a solid improvement for security and correctness. The new tests are comprehensive and verify the behavior correctly.

I have one suggestion for improvement in class-rest-api.php regarding the implementation of the new permission callback function. The current implementation returns a WP_REST_Response object on failure, which is not standard for permission callbacks. It should return a WP_Error object to be more robust and compliant with WordPress REST API standards. Other than that, the changes look excellent.

Comment thread includes/classes/class-rest-api.php

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
src/frontendHighlighterApp/index.js (1)

397-405: Simplify boolean gating expression (minor)

Optional chaining already guards access. Coerce to a strict boolean to avoid accidental truthy values.

Apply:

-const userCanEdit = edacFrontendHighlighterApp && edacFrontendHighlighterApp?.userCanEdit && edacFrontendHighlighterApp?.loggedIn;
+const userCanEdit = Boolean( edacFrontendHighlighterApp?.userCanEdit && edacFrontendHighlighterApp?.loggedIn );
tests/phpunit/includes/classes/RestApiEndpointsTest.php (1)

138-162: Add a positive case for limited users editing their own posts (optional)

To fully prove per-post semantics, add a test where the limited user creates a post and is allowed to save/clear for that post.

Example:

public function test_limited_user_can_manage_own_post() {
	wp_set_current_user( self::$limited_id );
	$own_post_id = self::factory()->post->create( [
		'post_type'   => 'post',
		'post_status' => 'publish',
		'post_author' => self::$limited_id,
	] );

	// Save scan results.
	$req1 = new WP_REST_Request( 'POST', '/accessibility-checker/v1/post-scan-results/' . $own_post_id );
	$req1->set_param( 'id', $own_post_id );
	$req1->set_param( 'violations', [ [ 'ruleId' => 'image-alt', 'html' => '<img>' ] ] );
	$resp1 = $this->server->dispatch( $req1 );
	$this->assertSame( 200, $resp1->get_status() );

	// Clear issues.
	$req2 = new WP_REST_Request( 'POST', '/accessibility-checker/v1/clear-issues/' . $own_post_id );
	$req2->set_param( 'id', $own_post_id );
	$req2->set_body( wp_json_encode( [ 'flush' => true ] ) );
	$req2->set_header( 'Content-Type', 'application/json' );
	$resp2 = $this->server->dispatch( $req2 );
	$this->assertSame( 200, $resp2->get_status() );
}
📜 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 ac718c5 and 52487c4.

📒 Files selected for processing (4)
  • includes/classes/class-enqueue-frontend.php (1 hunks)
  • includes/classes/class-rest-api.php (3 hunks)
  • src/frontendHighlighterApp/index.js (2 hunks)
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress coding standards (WPCS) in all PHP files
Use PSR-4 autoloading with EqualizeDigital\AccessibilityChecker namespace for new classes
Use WordPress hooks and filters appropriately
Use edac_ prefix for custom hooks and filters
Minimum PHP 7.4 compatibility
Use type hints where appropriate in PHP code
Follow WordPress security best practices (sanitization, validation, nonces)
Use WordPress database API (wpdb) for database operations
Prefix all functions and classes with edac_ when in global namespace
Use WordPress hooks (actions/filters) for extensibility
Use WordPress transients for caching
Sanitize all user inputs
Validate and escape all outputs
Use WordPress nonces for form submissions
Implement proper capability checks
Provide appropriate hooks for extensibility when adding new functionality
Use descriptive hook names with edac_ prefix
Document all custom hooks in docblocks
Document custom hooks and filters with clear descriptions and parameter types
Use PHPDoc for all public classes, methods, and properties
Escape all output, especially in admin screens and user-generated content
Use WordPress error handling functions (e.g., WP_Error) for PHP errors

Files:

  • includes/classes/class-enqueue-frontend.php
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
  • includes/classes/class-rest-api.php
**/class-*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/class-*.php: Legacy files are autoloaded using EDAC namespace
Legacy class names use WordPress style (Class_Name_Convention)
Legacy file names use class-class-name.php (WordPress style)
Legacy Classes: class-class-name.php
Deprecate legacy code with clear docblocks and migration notes

Files:

  • includes/classes/class-enqueue-frontend.php
  • includes/classes/class-rest-api.php
**/*.{php,js}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{php,js}: Follow WordPress internationalization (i18n) practices and use accessibility-checker text domain
All user-facing text must be translatable
Add inline comments for complex accessibility logic or non-obvious code
Use semantic HTML structure
ARIA attributes used correctly
Keyboard navigation supported
Images have descriptive alt text
Heading hierarchy logical
Screen reader compatibility
Forms are accessible and labeled

Files:

  • includes/classes/class-enqueue-frontend.php
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
  • src/frontendHighlighterApp/index.js
  • includes/classes/class-rest-api.php
includes/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

includes/**/*.php: Validate all AJAX requests and REST endpoints with nonces and capability checks
Avoid blocking queries in PHP, especially during scans

Files:

  • includes/classes/class-enqueue-frontend.php
  • includes/classes/class-rest-api.php
**/[A-Z]*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/[A-Z]*.php: Class names use CamelCase (ClassNameConvention) for new classes
File names use ClassNameConvention.php for new classes (CamelCase)
Classes: ClassName.php

Files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
tests/phpunit/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

tests/phpunit/**/*.php: Write unit tests for new PHP functions and classes
Add integration tests for major features and accessibility rules

Files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
**/*.js

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.js: Strings in JavaScript also need translation support using wp.i18n functions
Gracefully handle JavaScript errors to avoid breaking accessibility features

Files:

  • src/frontendHighlighterApp/index.js
**/*.{css,js}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

Support RTL languages where applicable

Files:

  • src/frontendHighlighterApp/index.js
src/**/*.js

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

src/**/*.js: Focus management implemented
Minimize DOM operations in JavaScript for frontend scanning

Files:

  • src/frontendHighlighterApp/index.js
**/[a-z]*.js

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

JavaScript Utilities: utilityName.js

Files:

  • src/frontendHighlighterApp/index.js
🧠 Learnings (1)
📚 Learning: 2025-08-04T16:46:23.515Z
Learnt from: CR
PR: equalizedigital/accessibility-checker#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-04T16:46:23.515Z
Learning: Applies to tests/phpunit/**/*.php : Add integration tests for major features and accessibility rules

Applied to files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
🧬 Code Graph Analysis (2)
tests/phpunit/includes/classes/RestApiEndpointsTest.php (2)
admin/class-admin.php (1)
  • Admin (20-99)
admin/class-update-database.php (2)
  • Update_Database (16-82)
  • edac_update_database (36-81)
src/frontendHighlighterApp/index.js (1)
src/editorApp/index.js (1)
  • rescanButton (83-83)
🔇 Additional comments (5)
includes/classes/class-enqueue-frontend.php (1)

104-104: LGTM: userCanEdit is correctly derived from per-post capability

Using current_user_can('edit_post', $post_id) aligns frontend gating with REST enforcement. No issues spotted.

src/frontendHighlighterApp/index.js (1)

419-419: UI container class logic reads cleaner after gating change

Switching to !userCanEdit for single_button styling matches the new permission concept. Looks good.

includes/classes/class-rest-api.php (2)

87-89: Correctly passes request to permission_callback

Handing the WP_REST_Request into the permission check enables per-post evaluation. Nice.


179-181: Correctly reuses permission helper for clear-issues

Permission callback parity between endpoints is good; keeps logic centralized.

tests/phpunit/includes/classes/RestApiEndpointsTest.php (1)

101-131: Good coverage: validates per-post permissions for saving scan results

The admin/limited user scenarios accurately exercise the new permission_callback behavior on POST /post-scan-results/{id}.

Comment thread includes/classes/class-rest-api.php
This test verifies that a limited user can save scan results and clear issues for their own post.

[PRO-165]
Enhance the API by ensuring that the 'id' argument is required and properly sanitized.
@pattonwebz
pattonwebz requested a review from Copilot August 19, 2025 13:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances permission handling for REST API endpoints to ensure only users who can edit specific posts are allowed to save scan results or clear issues. The implementation moves from generic edit_posts capability checks to post-specific edit_post checks.

Key changes:

  • Replaced generic permission callbacks with a new user_can_edit_passed_post_id method that validates edit permissions for the specific post ID
  • Updated frontend UI to show action buttons only to users who can edit the current post
  • Added comprehensive test coverage for the new permission logic

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
includes/classes/class-rest-api.php Implements post-specific permission checks and adds new validation method
includes/classes/class-enqueue-frontend.php Adds userCanEdit property to frontend app data
src/frontendHighlighterApp/index.js Updates UI logic to respect post-specific edit permissions
tests/phpunit/includes/classes/RestApiEndpointsTest.php Adds comprehensive test coverage for permission enforcement

Comment thread includes/classes/class-rest-api.php Outdated
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
return is_numeric( $param ); },

Copilot AI Aug 19, 2025

Copy link

Choose a reason for hiding this comment

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

The validate callback function should be properly formatted on separate lines for better readability and consistency with WordPress coding standards.

Copilot uses AI. Check for mistakes.
Comment thread includes/classes/class-rest-api.php Outdated
'validate_callback' => function ( $param ) {
return is_numeric( $param );
},
return is_numeric( $param ); },

Copilot AI Aug 19, 2025

Copy link

Choose a reason for hiding this comment

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

The validate callback function should be properly formatted on separate lines for better readability and consistency with WordPress coding standards.

Copilot uses AI. Check for mistakes.
'post_type' => 'post',
'post_status' => 'draft',
'post_author' => self::$limited_id,
]

Copilot AI Aug 19, 2025

Copy link

Choose a reason for hiding this comment

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

Trailing whitespace after the closing bracket should be removed.

Suggested change
]
]

Copilot uses AI. Check for mistakes.
'ruleId' => 'image-alt',
'html' => '<img>',
],
]

Copilot AI Aug 19, 2025

Copy link

Choose a reason for hiding this comment

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

Trailing whitespace after the closing bracket should be removed.

Suggested change
]
]

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
includes/classes/class-rest-api.php (1)

208-225: Type-hint the request and use a more standard error code for missing params.

PHPDoc is correct, but the method parameter isn’t type-hinted. Also, WordPress commonly uses rest_missing_callback_param for missing required params.

- public function user_can_edit_passed_post_id( $request ) {
-   if ( ! isset( $request['id'] ) ) {
-     return new \WP_Error( 'rest_post_invalid_id', __( 'A required parameter is missing.', 'accessibility-checker' ), [ 'status' => 400 ] );
-   }
+ public function user_can_edit_passed_post_id( \WP_REST_Request $request ) {
+   if ( ! isset( $request['id'] ) ) {
+     return new \WP_Error(
+       'rest_missing_callback_param',
+       __( 'A required parameter is missing: id.', 'accessibility-checker' ),
+       [ 'status' => 400 ]
+     );
+   }
   $post_id = (int) $request['id'];
   return current_user_can( 'edit_post', $post_id ); // able to edit the post.
 }
🧹 Nitpick comments (8)
includes/classes/class-rest-api.php (5)

82-86: Nit: simplify validate callback (and it's redundant with the regex route param).

Given the route already uses (?P<id>\d+), validate_callback is redundant. If you keep it, prefer a simple callable for readability.

Apply:

 'args'                => [
   'id' => [
     'required'          => true,
-    'validate_callback' => function ( $param ) {
-      return is_numeric( $param ); },
+    'validate_callback' => 'is_numeric',
     'sanitize_callback' => 'absint',
   ],
 ],

88-90: Use method reference for permission callback to reduce closure noise.

Directly referencing the method is cleaner and avoids an unnecessary closure.

- 'permission_callback' => function ( $request ) {
-   return $this->user_can_edit_passed_post_id( $request );
- },
+ 'permission_callback' => [ $this, 'user_can_edit_passed_post_id' ],

175-179: Nit: duplicate id arg schema — consider a small helper.

The schema for id is duplicated across endpoints. Extracting it into a helper improves maintainability.

If you keep the inline schema, same readability tweak applies as above:

 'args'                => [
   'id' => [
     'required'          => true,
-    'validate_callback' => function ( $param ) {
-      return is_numeric( $param ); },
+    'validate_callback' => 'is_numeric',
     'sanitize_callback' => 'absint',
   ],
 ],

Optionally, add this helper to the class (outside the shown range):

private function id_arg_schema(): array {
	return [
		'required'          => true,
		'validate_callback' => 'is_numeric',
		'sanitize_callback' => 'absint',
	];
}

Then use it:

'args' => [ 'id' => $this->id_arg_schema() ],

181-183: Use method reference for permission callback (same as other endpoint).

Keep it consistent and concise.

- 'permission_callback' => function ( $request ) {
-   return $this->user_can_edit_passed_post_id( $request );
- },
+ 'permission_callback' => [ $this, 'user_can_edit_passed_post_id' ],

230-236: Type-hint the request param for consistency with other handlers.

Other handlers (e.g., get_site_summary) type-hint \WP_REST_Request. Mirror that here.

- public function clear_issues_for_post( $request ) {
+ public function clear_issues_for_post( \WP_REST_Request $request ) {
tests/phpunit/includes/classes/RestApiEndpointsTest.php (3)

101-131: Strengthen assertions to validate response payload.

You already assert status; also assert payload structure/values to catch regressions.

   $response = $this->server->dispatch( $request );
   $this->assertSame( 200, $response->get_status(), 'Admin should be allowed to save scan results.' );
   $data = $response->get_data();
   $this->assertIsArray( $data );
+  $this->assertArrayHasKey( 'success', $data );
+  $this->assertTrue( $data['success'] );
+  $this->assertArrayHasKey( 'id', $data );
+  $this->assertSame( self::$post_id, $data['id'] );

138-162: Add assertions for response body fields on success and keep a small check for 403 payload.

Validating id and flushed helps ensure the endpoint semantics don’t drift.

   $resp1 = $this->server->dispatch( $r1 );
   $this->assertSame( 200, $resp1->get_status(), 'Admin should be allowed to clear issues.' );
   $body1 = $resp1->get_data();
   $this->assertIsArray( $body1 );
   $this->assertArrayHasKey( 'success', $body1 );
   $this->assertTrue( $body1['success'] );
+  $this->assertArrayHasKey( 'id', $body1 );
+  $this->assertSame( self::$post_id, $body1['id'] );
+  $this->assertArrayHasKey( 'flushed', $body1 );
+  $this->assertTrue( $body1['flushed'] );

169-201: Optionally assert payload structure for “own post” success paths.

Minor, but helps ensure both endpoints return the expected success envelope for non-admins acting on their own content.

   $resp1 = $this->server->dispatch( $req1 );
   $this->assertSame( 200, $resp1->get_status() );
+  $data1 = $resp1->get_data();
+  $this->assertIsArray( $data1 );
+  $this->assertArrayHasKey( 'success', $data1 );
+  $this->assertTrue( $data1['success'] );

   // Clear issues.
   $req2 = new WP_REST_Request( 'POST', '/accessibility-checker/v1/clear-issues/' . $own_post_id );
   $req2->set_param( 'id', $own_post_id );
   $req2->set_body( wp_json_encode( [ 'flush' => true ] ) );
   $req2->set_header( 'Content-Type', 'application/json' );
   $resp2 = $this->server->dispatch( $req2 );
   $this->assertSame( 200, $resp2->get_status() );
+  $data2 = $resp2->get_data();
+  $this->assertIsArray( $data2 );
+  $this->assertArrayHasKey( 'success', $data2 );
+  $this->assertTrue( $data2['success'] );
📜 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 52487c4 and fa863b0.

📒 Files selected for processing (2)
  • includes/classes/class-rest-api.php (3 hunks)
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress coding standards (WPCS) in all PHP files
Use PSR-4 autoloading with EqualizeDigital\AccessibilityChecker namespace for new classes
Use WordPress hooks and filters appropriately
Use edac_ prefix for custom hooks and filters
Minimum PHP 7.4 compatibility
Use type hints where appropriate in PHP code
Follow WordPress security best practices (sanitization, validation, nonces)
Use WordPress database API (wpdb) for database operations
Prefix all functions and classes with edac_ when in global namespace
Use WordPress hooks (actions/filters) for extensibility
Use WordPress transients for caching
Sanitize all user inputs
Validate and escape all outputs
Use WordPress nonces for form submissions
Implement proper capability checks
Provide appropriate hooks for extensibility when adding new functionality
Use descriptive hook names with edac_ prefix
Document all custom hooks in docblocks
Document custom hooks and filters with clear descriptions and parameter types
Use PHPDoc for all public classes, methods, and properties
Escape all output, especially in admin screens and user-generated content
Use WordPress error handling functions (e.g., WP_Error) for PHP errors

Files:

  • includes/classes/class-rest-api.php
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
**/class-*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/class-*.php: Legacy files are autoloaded using EDAC namespace
Legacy class names use WordPress style (Class_Name_Convention)
Legacy file names use class-class-name.php (WordPress style)
Legacy Classes: class-class-name.php
Deprecate legacy code with clear docblocks and migration notes

Files:

  • includes/classes/class-rest-api.php
**/*.{php,js}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{php,js}: Follow WordPress internationalization (i18n) practices and use accessibility-checker text domain
All user-facing text must be translatable
Add inline comments for complex accessibility logic or non-obvious code
Use semantic HTML structure
ARIA attributes used correctly
Keyboard navigation supported
Images have descriptive alt text
Heading hierarchy logical
Screen reader compatibility
Forms are accessible and labeled

Files:

  • includes/classes/class-rest-api.php
  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
includes/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

includes/**/*.php: Validate all AJAX requests and REST endpoints with nonces and capability checks
Avoid blocking queries in PHP, especially during scans

Files:

  • includes/classes/class-rest-api.php
**/[A-Z]*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/[A-Z]*.php: Class names use CamelCase (ClassNameConvention) for new classes
File names use ClassNameConvention.php for new classes (CamelCase)
Classes: ClassName.php

Files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
tests/phpunit/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

tests/phpunit/**/*.php: Write unit tests for new PHP functions and classes
Add integration tests for major features and accessibility rules

Files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
🧠 Learnings (1)
📚 Learning: 2025-08-04T16:46:23.515Z
Learnt from: CR
PR: equalizedigital/accessibility-checker#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-04T16:46:23.515Z
Learning: Applies to tests/phpunit/**/*.php : Add integration tests for major features and accessibility rules

Applied to files:

  • tests/phpunit/includes/classes/RestApiEndpointsTest.php
🧬 Code Graph Analysis (1)
tests/phpunit/includes/classes/RestApiEndpointsTest.php (1)
admin/class-update-database.php (2)
  • Update_Database (16-82)
  • edac_update_database (36-81)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Integration Test: PHP 8.2 | WP latest (+ ms)
  • GitHub Check: Integration Test: PHP 8.1 | WP latest
  • GitHub Check: Integration Test: PHP 8.1 | WP latest (+ ms)
  • GitHub Check: Integration Test: PHP 8.1 | WP 6.2
  • GitHub Check: Integration Test: PHP 8.2 | WP latest (+ ms)
🔇 Additional comments (3)
tests/phpunit/includes/classes/RestApiEndpointsTest.php (3)

47-53: LGTM: route init and server bootstrap are handled correctly.

Triggering init and rest_api_init then caching rest_get_server() makes the tests deterministic across runs.


72-78: Ensure the Update_Database class is autoloaded in the test environment.

If the plugin’s autoloader isn’t active in the test bootstrap, this direct instantiation could fatal. Confirm the test bootstrap loads the plugin (and autoloader) before this runs.

If needed, add a guard:

if ( class_exists( '\EDAC\Admin\Update_Database' ) ) {
	( new \EDAC\Admin\Update_Database() )->edac_update_database();
}

13-20: Nice coverage: admin vs limited user vs own-post.

The matrix of permission scenarios is well covered and aligns with the new per-post capability checks.

pattonwebz and others added 5 commits August 19, 2025 14:54
Ensure consistent code style by aligning closing braces for validation callbacks in the REST API.
Added assertions to check for 'success', 'id', and 'flushed' keys in the API response data for various test cases.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
includes/classes/class-rest-api.php (4)

80-91: Per-post permission callback and arg schema: good; consider validating ID > 0

Nice move to gate /post-scan-results/{id} on a per-post capability and to add arg schema. Minor nit: validate that the ID is a positive integer to avoid 0 (which won’t map to a real post). Note that in WP REST, permission_callback runs before arg validation/sanitization, so your explicit (int) cast inside the callback is still the source of truth.

Apply:

 'args'                => [
   'id' => [
-    'required'          => true,
-    'validate_callback' => function ( $param ) {
-      return is_numeric( $param );
-    },
+    'required'          => true,
+    'validate_callback' => function ( $param ) {
+      return is_numeric( $param ) && (int) $param > 0;
+    },
     'sanitize_callback' => 'absint',
   ],
 ],
 'permission_callback' => function ( $request ) {
   return $this->user_can_edit_passed_post_id( $request );
 },

107-108: Centralize capability for stats endpoints behind a filter

All four stats endpoints are guarded with edit_posts. That’s reasonable, but sites often want a different cap (e.g., manage_options) or a custom role. Recommend introducing an edac_ filter so integrators can override without code edits. Same filter can be reused across these endpoints.

Apply:

 'permission_callback' => function () {
-  return current_user_can( 'edit_posts' );
+  $cap = apply_filters( 'edac_required_capability_for_scans_stats', 'edit_posts' );
+  return current_user_can( $cap );
 },

Repeat the same change for:

  • scans-stats (Lines 107-108)
  • clear-cached-scans-stats (Lines 124-125)
  • scans-stats-by-post-type (Lines 141-142)
  • scans-stats-by-post-types (Lines 158-159)

Please also add a short PHPDoc for the new filter, following WPCS and your guidelines (text domain accessibility-checker).

Also applies to: 124-125, 141-142, 158-159


174-185: Clear-issues route aligns with per-post capability; also validate ID > 0

Good parity with the save route. Same small nit: ensure the ID is positive.

Apply:

 'args'                => [
   'id' => [
-    'required'          => true,
-    'validate_callback' => function ( $param ) {
-      return is_numeric( $param );
-    },
+    'required'          => true,
+    'validate_callback' => function ( $param ) {
+      return is_numeric( $param ) && (int) $param > 0;
+    },
     'sanitize_callback' => 'absint',
   ],
 ],
 'permission_callback' => function ( $request ) {
   return $this->user_can_edit_passed_post_id( $request );
 },

210-227: Permission callback helper: add param type-hint; refine error code/message

Great fix returning WP_Error instead of WP_REST_Response, and docblock looks good. Two small improvements:

  • Add a parameter type-hint for WP_REST_Request (7.4-safe).
  • Use the core-style code for missing params: rest_missing_callback_param and specify which param is missing.

Apply:

-/**
- * Check if the user can edit a post.
- *
- * This is a permission callback to replace several places where we check if the user can edit a post.
- *
- * @since 1.31.0
- *
- * @param \WP_REST_Request $request The request object passed from the REST call. This should contain the 'id' of the post to check permissions for.
- *
- * @return bool|\WP_Error
- */
-public function user_can_edit_passed_post_id( $request ) {
-  if ( ! isset( $request['id'] ) ) {
-    return new \WP_Error( 'rest_post_invalid_id', __( 'A required parameter is missing.', 'accessibility-checker' ), [ 'status' => 400 ] );
-  }
-  $post_id = (int) $request['id'];
-  return current_user_can( 'edit_post', $post_id ); // able to edit the post.
-}
+/**
+ * Check if the user can edit a post.
+ *
+ * Permission callback used where per-post edit checks are required.
+ *
+ * @since 1.31.0
+ *
+ * @param \WP_REST_Request $request The request object. Must contain 'id' of the post to check.
+ * @return bool|\WP_Error
+ */
+public function user_can_edit_passed_post_id( \WP_REST_Request $request ) {
+  if ( ! isset( $request['id'] ) ) {
+    return new \WP_Error(
+      'rest_missing_callback_param',
+      __( 'A required parameter is missing: id.', 'accessibility-checker' ),
+      [ 'status' => 400 ]
+    );
+  }
+  $post_id = (int) $request['id'];
+  return current_user_can( 'edit_post', $post_id );
+}
📜 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 35227d5 and 3e32884.

📒 Files selected for processing (1)
  • includes/classes/class-rest-api.php (7 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress coding standards (WPCS) in all PHP files
Use PSR-4 autoloading with EqualizeDigital\AccessibilityChecker namespace for new classes
Use WordPress hooks and filters appropriately
Use edac_ prefix for custom hooks and filters
Minimum PHP 7.4 compatibility
Use type hints where appropriate in PHP code
Follow WordPress security best practices (sanitization, validation, nonces)
Use WordPress database API (wpdb) for database operations
Prefix all functions and classes with edac_ when in global namespace
Use WordPress hooks (actions/filters) for extensibility
Use WordPress transients for caching
Sanitize all user inputs
Validate and escape all outputs
Use WordPress nonces for form submissions
Implement proper capability checks
Provide appropriate hooks for extensibility when adding new functionality
Use descriptive hook names with edac_ prefix
Document all custom hooks in docblocks
Document custom hooks and filters with clear descriptions and parameter types
Use PHPDoc for all public classes, methods, and properties
Escape all output, especially in admin screens and user-generated content
Use WordPress error handling functions (e.g., WP_Error) for PHP errors

Files:

  • includes/classes/class-rest-api.php
**/class-*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/class-*.php: Legacy files are autoloaded using EDAC namespace
Legacy class names use WordPress style (Class_Name_Convention)
Legacy file names use class-class-name.php (WordPress style)
Legacy Classes: class-class-name.php
Deprecate legacy code with clear docblocks and migration notes

Files:

  • includes/classes/class-rest-api.php
**/*.{php,js}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{php,js}: Follow WordPress internationalization (i18n) practices and use accessibility-checker text domain
All user-facing text must be translatable
Add inline comments for complex accessibility logic or non-obvious code
Use semantic HTML structure
ARIA attributes used correctly
Keyboard navigation supported
Images have descriptive alt text
Heading hierarchy logical
Screen reader compatibility
Forms are accessible and labeled

Files:

  • includes/classes/class-rest-api.php
includes/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

includes/**/*.php: Validate all AJAX requests and REST endpoints with nonces and capability checks
Avoid blocking queries in PHP, especially during scans

Files:

  • includes/classes/class-rest-api.php
🔇 Additional comments (1)
includes/classes/class-rest-api.php (1)

232-232: Docblock param type corrected

Docblock now uses \WP_REST_Request for the request param. Looks good.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
admin/class-welcome-page.php (1)

269-273: Consider conditioning the explanatory copy when the button is hidden.

For users without publish_posts, the text says they can click “Update Counts” but the button won’t be visible. Either wrap this paragraph in the same capability check or adjust the copy for non-privileged users.

Example:

<?php if ( current_user_can( 'publish_posts' ) ) : ?>
	<p><?php esc_html_e( 'This summary is automatically updated every 24 hours, or any time a full site scan is completed. You can also manually update these results by clicking the Update Counts button.', 'accessibility-checker' ); ?></p>
<?php else : ?>
	<p><?php esc_html_e( 'This summary is automatically updated every 24 hours, or any time a full site scan is completed.', 'accessibility-checker' ); ?></p>
<?php endif; ?>
includes/classes/class-rest-api.php (4)

81-91: Minor cleanup: use direct callback and native validator (no closures).

Trim some boilerplate for readability and consistency.

Apply:

   'args'                => [
     'id' => [
-       'required'          => true,
-       'validate_callback' => function ( $param ) {
-         return is_numeric( $param );
-       },
+       'required'          => true,
+       'validate_callback' => 'is_numeric',
        'sanitize_callback' => 'absint',
     ],
   ],
-  'permission_callback' => function ( $request ) {
-    return $this->user_can_edit_passed_post_id( $request );
-  },
+  'permission_callback' => [ $this, 'user_can_edit_passed_post_id' ],

138-143: Permission hardening is fine; optionally add explicit args for slug.

While you’re touching this route, consider declaring and sanitizing the slug param explicitly for clarity (the path regex already constrains it).

Example:

'args' => [
    'slug' => [
        'required'           => true,
        'sanitize_callback'  => 'sanitize_key',
        'validate_callback'  => function( $param ) {
            return (bool) preg_match( '/^[a-zA-Z0-9_-]+$/', $param );
        },
    ],
],

176-185: Minor cleanup: remove closures as above.

Mirror the simplifications suggested for post-scan-results.

Apply:

   'args'                => [
     'id' => [
-       'required'          => true,
-       'validate_callback' => function ( $param ) {
-         return is_numeric( $param );
-       },
+       'required'          => true,
+       'validate_callback' => 'is_numeric',
        'sanitize_callback' => 'absint',
     ],
   ],
-  'permission_callback' => function ( $request ) {
-    return $this->user_can_edit_passed_post_id( $request );
-  },
+  'permission_callback' => [ $this, 'user_can_edit_passed_post_id' ],

210-227: Type-hint the request parameter and prefer a core error code.

  • Add a \WP_REST_Request type-hint to the helper (PHP 7.4-safe).
  • Use rest_missing_callback_param to align with core error semantics (optional).

Apply:

-	public function user_can_edit_passed_post_id( $request ) {
-		if ( ! isset( $request['id'] ) ) {
-			return new \WP_Error( 'rest_post_invalid_id', __( 'A required parameter is missing.', 'accessibility-checker' ), [ 'status' => 400 ] );
-		}
+	public function user_can_edit_passed_post_id( \WP_REST_Request $request ) {
+		if ( ! isset( $request['id'] ) ) {
+			return new \WP_Error(
+				'rest_missing_callback_param',
+				__( 'A required parameter is missing.', 'accessibility-checker' ),
+				[ 'status' => 400 ]
+			);
+		}
 		$post_id = (int) $request['id'];
 		return current_user_can( 'edit_post', $post_id ); // able to edit the post.
 	}
📜 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 3e32884 and 44983e0.

📒 Files selected for processing (2)
  • admin/class-welcome-page.php (1 hunks)
  • includes/classes/class-rest-api.php (7 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.php: Follow WordPress coding standards (WPCS) in all PHP files
Use PSR-4 autoloading with EqualizeDigital\AccessibilityChecker namespace for new classes
Use WordPress hooks and filters appropriately
Use edac_ prefix for custom hooks and filters
Minimum PHP 7.4 compatibility
Use type hints where appropriate in PHP code
Follow WordPress security best practices (sanitization, validation, nonces)
Use WordPress database API (wpdb) for database operations
Prefix all functions and classes with edac_ when in global namespace
Use WordPress hooks (actions/filters) for extensibility
Use WordPress transients for caching
Sanitize all user inputs
Validate and escape all outputs
Use WordPress nonces for form submissions
Implement proper capability checks
Provide appropriate hooks for extensibility when adding new functionality
Use descriptive hook names with edac_ prefix
Document all custom hooks in docblocks
Document custom hooks and filters with clear descriptions and parameter types
Use PHPDoc for all public classes, methods, and properties
Escape all output, especially in admin screens and user-generated content
Use WordPress error handling functions (e.g., WP_Error) for PHP errors

Files:

  • admin/class-welcome-page.php
  • includes/classes/class-rest-api.php
**/class-*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/class-*.php: Legacy files are autoloaded using EDAC namespace
Legacy class names use WordPress style (Class_Name_Convention)
Legacy file names use class-class-name.php (WordPress style)
Legacy Classes: class-class-name.php
Deprecate legacy code with clear docblocks and migration notes

Files:

  • admin/class-welcome-page.php
  • includes/classes/class-rest-api.php
**/*.{php,js}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.{php,js}: Follow WordPress internationalization (i18n) practices and use accessibility-checker text domain
All user-facing text must be translatable
Add inline comments for complex accessibility logic or non-obvious code
Use semantic HTML structure
ARIA attributes used correctly
Keyboard navigation supported
Images have descriptive alt text
Heading hierarchy logical
Screen reader compatibility
Forms are accessible and labeled

Files:

  • admin/class-welcome-page.php
  • includes/classes/class-rest-api.php
includes/**/*.php

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

includes/**/*.php: Validate all AJAX requests and REST endpoints with nonces and capability checks
Avoid blocking queries in PHP, especially during scans

Files:

  • includes/classes/class-rest-api.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Integration Test: PHP 8.2 | WP latest (+ ms)
  • GitHub Check: Integration Test: PHP 8.1 | WP latest (+ ms)
🔇 Additional comments (6)
admin/class-welcome-page.php (1)

43-47: Gating “Update Counts” behind publish_posts is correct and aligned with REST permission.

Matches the /clear-cached-scans-stats permission_callback (publish_posts) and prevents exposing the control to users who can’t perform the action anyway. LGTM.

includes/classes/class-rest-api.php (5)

81-91: Per-post ID args + permission callback are solid.

  • args: id is required, validated, and sanitized (absint).
  • permission: moves from blanket edit_posts to per-post edit via helper.

This is exactly the right tightening for write operations.


106-108: Restricting scans-stats to edit_posts looks good.

These admin-focused stats shouldn’t be exposed to general readers. LGTM.


124-125: Correct capability for cache clearing.

Requiring publish_posts for POST /clear-cached-scans-stats aligns with the admin UI and the state-changing nature of the action.


158-159: LGTM – consistent permissioning.

edit_posts for the multi-type stats endpoint matches the other stats routes.


176-185: ID arg handling + per-post permission for clear-issues is correct.

Good combination of required+sanitized route param and a permission check bound to that post.

@pattonwebz

Copy link
Copy Markdown
Member Author

A rebased version of this was merged into main.

@pattonwebz pattonwebz closed this Aug 21, 2025
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.

3 participants