Skip to content

fix: align service pagination and endpoint behavior#3

Merged
soulevilx merged 1 commit into
developfrom
fix/service-pagination-and-endpoints
May 16, 2026
Merged

fix: align service pagination and endpoint behavior#3
soulevilx merged 1 commit into
developfrom
fix/service-pagination-and-endpoints

Conversation

@soulevilx
Copy link
Copy Markdown
Contributor

@soulevilx soulevilx commented May 16, 2026

What changed

Aligned service pagination and endpoint behavior.

Why

Consistency and correctness in service responses.

How

Updated pagination logic and endpoint handlers.

Files/areas touched

Service classes and endpoints.

Validation commands and results

composer test, composer lint, composer security, composer quality all passed.

Dependency on other PRs

None.

Risk/impact

Low-impact fix for existing services.

Summary by CodeRabbit

  • Bug Fixes

    • Improved block rendering by ensuring the editor context is properly set when rendering blocks.
    • Enhanced plugin path handling to ensure consistent encoding across operations.
  • Chores

    • Removed extraneous comments from service implementations for improved code clarity.
    • Added PHPMD suppression annotations to improve code quality standards.
    • Expanded test coverage with comprehensive unit tests for pagination, endpoint paths, and query parameter mapping across multiple services.

Review Change Stack

@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

This PR enhances the WordPress SDK with optional parameter defaults, refines service implementations for WordPress endpoint handling, and adds extensive test coverage validating data model construction, pagination behavior, and endpoint path generation across multiple services.

Changes

SDK Data Models, Service Enhancements, and Test Coverage

Layer / File(s) Summary
Data Model Defaults and Constructor Tests
src/Data/Page.php, src/Data/Status.php, tests/Unit/Data/DataModelsTest.php, tests/Unit/Data/Query/ListQueryTest.php
Status constructor parameters ($public, $protected, $private, $queryable, $show_in_list) become optional with false defaults. Page receives PHPMD suppression annotations. New test methods verify constructor defaulting behavior for Page, Status, Comment, Taxonomy, PostType, SearchResult, and query parameter mapping for ListMediaQuery, ListTermsQuery, and ListUsersQuery.
Service Method Implementations and Cleanups
src/Http/AbstractService.php, src/Services/BlockRendererService.php, src/Services/PluginsService.php, tests/Unit/Services/BlockRendererServiceTest.php
BlockRendererService adds context='edit' query parameter by default. PluginsService introduces pluginPath() helper to normalize multi-segment plugin paths by trimming slashes, encoding each segment via segment(), and rejoining with /. AbstractService removes extraneous comments while preserving HTTP request/response logic. BlockRendererServiceTest assertion updated to verify context parameter.
Pagination Helper Verification
tests/Unit/Services/AbstractTermServiceTest.php, tests/Unit/Services/CommentsServiceTest.php, tests/Unit/Services/MediaServiceTest.php, tests/Unit/Services/PagesServiceTest.php, tests/Unit/Services/SearchServiceTest.php, tests/Unit/Services/UsersServiceTest.php, tests/Unit/Services/SchemaServicesTest.php
Comprehensive test coverage for auto-pagination helpers (all(), cursor(), each()) across service layer; verifies correct item aggregation across pages, page query parameter advancement, proper cursor iteration, and early termination when callback returns false. SchemaServicesTest extended with lastOptions tracking to capture query parameters.
Endpoint Path Test Infrastructure and Service Verification
tests/Unit/Services/EndpointPathServicesTest.php, tests/Unit/Services/BlockTypesServiceTest.php, tests/Unit/Services/BlocksServiceTest.php, tests/Unit/Services/GlobalStylesServiceTest.php, tests/Unit/Services/MenuLocationsServiceTest.php, tests/Unit/Services/NavMenusServiceTest.php, tests/Unit/Services/PluginsServiceTest.php, tests/Unit/Services/RawEndpointServiceTest.php, tests/Unit/Services/SidebarsServiceTest.php, tests/Unit/Services/SiteHealthServiceTest.php, tests/Unit/Services/TemplatesServiceTest.php, tests/Unit/Services/ThemesServiceTest.php, tests/Unit/Services/WidgetTypesServiceTest.php
Introduces EndpointPathServicesTest with RecordsServiceRequests trait to record request method, URI, and options; provides test service stubs extending production services and NullHttpClient for isolated testing; verifies endpoint URI and query parameter construction for BlockRenderer, BlockTypes, Blocks, GlobalStyles, MenuLocations, NavMenus, Plugins, RawEndpoint, Sidebars, SiteHealth, Templates, Themes, and WidgetTypes services.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 With flexible defaults and pagination tested true,
Plugin paths now handle their segments with care—
Context set to edit, endpoints shining bright,
A web of services, rigorously right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: aligning service pagination and endpoint behavior across multiple service classes, which is the primary focus of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/service-pagination-and-endpoints

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/Services/BlockRendererService.php (1)

17-17: ⚡ Quick win

Replace inline context literal with a class constant.

Line 17 hardcodes 'edit'; extract it to a named constant so the value is centralized and less error-prone.

Suggested diff
 class BlockRendererService extends RawEndpointService
 {
+    private const CONTEXT_EDIT = 'edit';
+
     /**
      * `@param` array<string, mixed> $attributes
      * `@return` array<mixed>
      */
     public function render(string $name, array $attributes = [], ?int $postId = null): array
     {
-        $query = ['context' => 'edit'];
+        $query = ['context' => self::CONTEXT_EDIT];
         if ($attributes !== []) {
             $query['attributes'] = $attributes;
         }
As per coding guidelines, "Avoid hidden domain strings when enums or constants are clearer".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/BlockRendererService.php` at line 17, Replace the hardcoded
context string by adding a class constant on BlockRendererService (e.g., private
const CONTEXT_EDIT = 'edit') and update the $query assignment to use that
constant (self::CONTEXT_EDIT) instead of the literal; also search for any other
occurrences of the literal 'edit' in BlockRendererService and switch them to the
same constant so the domain value is centralized and less error-prone.
tests/Unit/Services/RawEndpointServiceTest.php (1)

19-22: ⚡ Quick win

Remove this non-invariant docblock from the anonymous test helper.

This comment is type-only and does not capture why, tradeoffs, or invariants.

Suggested diff
-            /**
-             * `@param` array<string, mixed> $payload
-             * `@return` array<mixed>
-             */
             public function exposedPutRaw(string $path, array $payload): array
             {
                 return $this->putRaw($path, $payload);
             }
As per coding guidelines, "Keep comments for why, tradeoffs, or invariants only".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/Services/RawEndpointServiceTest.php` around lines 19 - 22, Remove
the non-informative docblock on the anonymous test helper that only repeats
types (the block containing "`@param` array<string, mixed> $payload" and "`@return`
array<mixed>"); delete this comment so the test helper remains uncluttered (rely
on actual type hints or PHPStan/phpdoc where meaningful), leaving the anonymous
function itself untouched.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Services/PluginsService.php`:
- Around line 52-57: pluginPath currently builds a path from explode('/'...)
without filtering empty segments which allows inputs like '' or 'a//b' to
produce malformed endpoints; update pluginPath to first
explode(trim($plugin,'/')) then array_filter the segments to remove empty
strings, throw an InvalidArgumentException (or other appropriate exception) if
the resulting segments array is empty (fail fast), and finally map each
remaining segment through $this->segment(...) and implode with '/' to produce
the normalized path (refer to function pluginPath and method segment).

---

Nitpick comments:
In `@src/Services/BlockRendererService.php`:
- Line 17: Replace the hardcoded context string by adding a class constant on
BlockRendererService (e.g., private const CONTEXT_EDIT = 'edit') and update the
$query assignment to use that constant (self::CONTEXT_EDIT) instead of the
literal; also search for any other occurrences of the literal 'edit' in
BlockRendererService and switch them to the same constant so the domain value is
centralized and less error-prone.

In `@tests/Unit/Services/RawEndpointServiceTest.php`:
- Around line 19-22: Remove the non-informative docblock on the anonymous test
helper that only repeats types (the block containing "`@param` array<string,
mixed> $payload" and "`@return` array<mixed>"); delete this comment so the test
helper remains uncluttered (rely on actual type hints or PHPStan/phpdoc where
meaningful), leaving the anonymous function itself untouched.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71c6b530-c89c-4b90-9d15-db4496296c82

📥 Commits

Reviewing files that changed from the base of the PR and between 57267a1 and 721d1fe.

📒 Files selected for processing (28)
  • src/Data/Page.php
  • src/Data/Status.php
  • src/Http/AbstractService.php
  • src/Services/BlockRendererService.php
  • src/Services/PluginsService.php
  • tests/Unit/Data/DataModelsTest.php
  • tests/Unit/Data/Query/ListQueryTest.php
  • tests/Unit/Services/AbstractTermServiceTest.php
  • tests/Unit/Services/BlockRendererServiceTest.php
  • tests/Unit/Services/BlockTypesServiceTest.php
  • tests/Unit/Services/BlocksServiceTest.php
  • tests/Unit/Services/CommentsServiceTest.php
  • tests/Unit/Services/EndpointPathServicesTest.php
  • tests/Unit/Services/GlobalStylesServiceTest.php
  • tests/Unit/Services/MediaServiceTest.php
  • tests/Unit/Services/MenuLocationsServiceTest.php
  • tests/Unit/Services/NavMenusServiceTest.php
  • tests/Unit/Services/PagesServiceTest.php
  • tests/Unit/Services/PluginsServiceTest.php
  • tests/Unit/Services/RawEndpointServiceTest.php
  • tests/Unit/Services/SchemaServicesTest.php
  • tests/Unit/Services/SearchServiceTest.php
  • tests/Unit/Services/SidebarsServiceTest.php
  • tests/Unit/Services/SiteHealthServiceTest.php
  • tests/Unit/Services/TemplatesServiceTest.php
  • tests/Unit/Services/ThemesServiceTest.php
  • tests/Unit/Services/UsersServiceTest.php
  • tests/Unit/Services/WidgetTypesServiceTest.php
💤 Files with no reviewable changes (1)
  • src/Http/AbstractService.php

Comment on lines +52 to +57
private function pluginPath(string $plugin): string
{
return implode('/', array_map(
fn (string $segment): string => $this->segment($segment),
explode('/', trim($plugin, '/'))
));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate and normalize empty plugin segments before URI construction.

Lines 52-57 currently allow '', '/', or double-slash input ('a//b'), which can generate malformed plugin endpoints. Filter empty segments and fail fast when no valid segment remains.

Suggested diff
     private function pluginPath(string $plugin): string
     {
-        return implode('/', array_map(
+        $segments = array_values(array_filter(
+            explode('/', trim($plugin, '/')),
+            static fn (string $segment): bool => $segment !== ''
+        ));
+
+        if ($segments === []) {
+            throw new \InvalidArgumentException('Plugin path must not be empty.');
+        }
+
+        return implode('/', array_map(
             fn (string $segment): string => $this->segment($segment),
-            explode('/', trim($plugin, '/'))
+            $segments
         ));
     }
📝 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
private function pluginPath(string $plugin): string
{
return implode('/', array_map(
fn (string $segment): string => $this->segment($segment),
explode('/', trim($plugin, '/'))
));
private function pluginPath(string $plugin): string
{
$segments = array_values(array_filter(
explode('/', trim($plugin, '/')),
static fn (string $segment): bool => $segment !== ''
));
if ($segments === []) {
throw new \InvalidArgumentException('Plugin path must not be empty.');
}
return implode('/', array_map(
fn (string $segment): string => $this->segment($segment),
$segments
));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Services/PluginsService.php` around lines 52 - 57, pluginPath currently
builds a path from explode('/'...) without filtering empty segments which allows
inputs like '' or 'a//b' to produce malformed endpoints; update pluginPath to
first explode(trim($plugin,'/')) then array_filter the segments to remove empty
strings, throw an InvalidArgumentException (or other appropriate exception) if
the resulting segments array is empty (fail fast), and finally map each
remaining segment through $this->segment(...) and implode with '/' to produce
the normalized path (refer to function pluginPath and method segment).

@soulevilx soulevilx merged commit 1ef7a40 into develop May 16, 2026
5 checks passed
@soulevilx soulevilx deleted the fix/service-pagination-and-endpoints branch May 16, 2026 14:06
Copy link
Copy Markdown

Copilot AI left a comment

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 aligns WordPress service endpoint/path handling and pagination helper behavior across multiple services, and expands unit test coverage to lock in the expected request URIs/options and DTO/query mapping.

Changes:

  • Adjusted service behaviors for endpoint path construction (notably plugin path handling) and block rendering context defaults.
  • Expanded/added unit tests to validate endpoint paths, request options, and auto-pagination helpers across many services.
  • Improved DTO ergonomics for WordPress-shaped responses (e.g., Status defaults, Page post-field defaults) and added query mapping tests.

Reviewed changes

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

Show a summary per file
File Description
tests/Unit/Services/WidgetTypesServiceTest.php Adds coverage for widget-types list/get request paths and options.
tests/Unit/Services/UsersServiceTest.php Adds coverage for auto-pagination helpers behavior (all, cursor, each).
tests/Unit/Services/ThemesServiceTest.php Adds coverage for themes list path and query mapping.
tests/Unit/Services/TemplatesServiceTest.php Adds coverage for templates list/create paths and request bodies.
tests/Unit/Services/SiteHealthServiceTest.php Adds coverage for additional site health check helper methods and paths.
tests/Unit/Services/SidebarsServiceTest.php Adds coverage for sidebars list/get paths and query usage.
tests/Unit/Services/SearchServiceTest.php Adds coverage for auto-pagination helpers on search endpoint.
tests/Unit/Services/SchemaServicesTest.php Adds auto-pagination coverage for schema-backed services and captures last request options.
tests/Unit/Services/RawEndpointServiceTest.php New test validating putRaw request body construction and request recording.
tests/Unit/Services/PluginsServiceTest.php Updates/expands tests to reflect new plugin path handling and CRUD request building.
tests/Unit/Services/PagesServiceTest.php Adds coverage for auto-pagination helpers on pages endpoint.
tests/Unit/Services/NavMenusServiceTest.php Adds coverage for menu get/delete paths and force query.
tests/Unit/Services/MenuLocationsServiceTest.php Adds coverage for menu locations list path behavior.
tests/Unit/Services/MediaServiceTest.php Adds coverage for auto-pagination helpers on media endpoint.
tests/Unit/Services/GlobalStylesServiceTest.php Adds coverage for global styles CRUD paths and request bodies.
tests/Unit/Services/EndpointPathServicesTest.php New consolidated path regression tests across multiple endpoint services (also introduces local test helpers).
tests/Unit/Services/CommentsServiceTest.php Adds coverage for auto-pagination helpers on comments endpoint.
tests/Unit/Services/BlockTypesServiceTest.php Adds coverage for block-types list path variants and query mapping.
tests/Unit/Services/BlocksServiceTest.php Adds coverage for blocks CRUD path building and request body mapping.
tests/Unit/Services/BlockRendererServiceTest.php Updates assertions to require context=edit in block renderer queries.
tests/Unit/Data/Query/ListQueryTest.php Adds tests for media/terms/users list query-to-querystring mapping and null filtering.
tests/Unit/Data/DataModelsTest.php Adds DTO constructor coverage for Page, Status, and other WP response shapes.
src/Services/PluginsService.php Changes plugin path construction to encode segments while keeping / separators.
src/Services/BlockRendererService.php Defaults render requests to context=edit.
src/Http/AbstractService.php Removes extraneous inline comments (no functional change in diff shown).
src/Data/Status.php Provides default false values for optional WordPress boolean fields.
src/Data/Page.php Adds Page constructor supplying defaults for post-only fields not present in typical page responses.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +259 to +263
class NullHttpClient implements HttpClientInterface
{
public function get(string $uri, array $options = []): ResponseWrapperInterface
{
throw new \RuntimeException('Not used');
Comment on lines +142 to +146
trait RecordsServiceRequests
{
public ?string $lastMethod = null;
public ?string $lastUri = null;
public array $lastOptions = [];
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