Skip to content

Commit 8f7b9a9

Browse files
authored
Merge pull request #2126 from tleon/Add-cqrs-listing-doc
Add PaginatedList documentation
2 parents 5819a67 + 90b2e32 commit 8f7b9a9

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
Generate developer documentation for a PrestaShop Admin API custom operation class.
2+
3+
**Arguments:** `$0` = operation name, `$1` = PrestaShop core path
4+
5+
Example invocation arguments: `toggle-exchange-rate-automatization-command /home/tleone/Dev/prestashop-develop`
6+
7+
## Task
8+
9+
You are writing documentation for the PrestaShop devdocs site (https://devdocs.prestashop-project.org/9/admin-api/resource_server/api-resources/). The target page is `admin-api/resource_server/api-resources.md` in this repository. Your output will be a new section to add to that file for operation `$0`.
10+
11+
## Steps
12+
13+
### 1. Read the operation class
14+
15+
The PrestaShop core source is at `$1`. Find operation `$0` in `src/PrestaShopBundle/ApiPlatform/Metadata/`. Read it fully to understand:
16+
- What it extends and what interfaces it implements
17+
- Its constructor parameters (especially the custom ones beyond standard API Platform params)
18+
- How it stores extra properties and what defaults it sets
19+
- What provider/processor it enforces
20+
21+
### 2. Find real-world usages
22+
23+
Search for usages of the operation in `modules/ps_apiresources/src/` and `src/PrestaShopBundle/ApiPlatform/Resources/` inside the core repo. Pick 1–2 representative examples that cover the most important parameters.
24+
25+
### 3. Study the existing documentation format
26+
27+
Read `admin-api/resource_server/api-resources.md` in this repository to understand the current format and where the new section should be inserted (after the last existing CQRS operation section, before `## PaginatedList`).
28+
29+
Each custom operation follows this structure:
30+
31+
```
32+
### OperationName
33+
34+
| HTTP Method | Action |
35+
|---|---|
36+
| METHOD | one-line description |
37+
38+
Brief paragraph explaining what the operation does and when to use it over alternatives.
39+
40+
```php
41+
// full realistic example based on actual usages
42+
```
43+
44+
Behavioral notes about provider/processor, response shape, caveats.
45+
46+
#### Custom parameters
47+
48+
| Parameter | Type | Required | Default | Description |
49+
|---|---|---|---|---|
50+
| `paramName` | `string` | Yes || What it does |
51+
```
52+
53+
### 4. Generate the documentation section
54+
55+
Write a documentation section for the operation following the format above. The section must include:
56+
57+
- **Header**: `### OperationName`
58+
- **HTTP method table**
59+
- **Description paragraph**: what problem it solves, when to use it over alternatives
60+
- **PHP code example**: realistic, based on actual usages found in step 2, showing the most important parameters with full namespace/use declarations and class body
61+
- **Behavioral notes**: how the provider/processor works, what the response looks like, any important caveats
62+
- **Custom parameters table**: only list parameters that are unique to this operation (not standard API Platform params). Columns: Parameter, Type, Required, Default, Description
63+
64+
Keep the tone consistent with the existing devdoc pages: technical and direct, no marketing language.
65+
66+
### 5. Insert into the file
67+
68+
Insert the generated section into `admin-api/resource_server/api-resources.md` at the correct location. Then confirm the insertion was successful.

admin-api/resource_server/api-resources.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,85 @@ class ApiClient
285285
}
286286
```
287287

288+
### CQRSPaginate
289+
290+
| HTTP Method | Action |
291+
|-------------|-----------------------------|
292+
| GET | Read a paginated collection |
293+
294+
`CQRSPaginate` is the CQRS-based equivalent of `PaginatedList` for endpoints backed by a CQRS query instead of a `GridDataFactory`. Use it when you have a CQRS query that handles pagination internally and returns a result object containing both an items list and a total count. Use `PaginatedList` instead when you need to reuse an existing grid data factory.
295+
296+
```php
297+
<?php
298+
declare(strict_types=1);
299+
300+
namespace PrestaShop\Module\APIResources\ApiPlatform\Resources\Product;
301+
302+
use ApiPlatform\Metadata\ApiProperty;
303+
use ApiPlatform\Metadata\ApiResource;
304+
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Query\GetEditableCombinationsList;
305+
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductNotFoundException;
306+
use PrestaShop\PrestaShop\Core\Search\Filters\ProductCombinationFilters;
307+
use PrestaShopBundle\ApiPlatform\Metadata\CQRSPaginate;
308+
use Symfony\Component\HttpFoundation\Response;
309+
310+
#[ApiResource(
311+
operations: [
312+
new CQRSPaginate(
313+
uriTemplate: '/products/{productId}/combinations',
314+
CQRSQuery: GetEditableCombinationsList::class,
315+
scopes: [
316+
'product_read',
317+
],
318+
CQRSQueryMapping: [
319+
'[_context][langId]' => '[languageId]',
320+
'[_context][shopConstraint]' => '[shopConstraint]',
321+
],
322+
ApiResourceMapping: [
323+
'[combinationName]' => '[name]',
324+
'[attributesInformation]' => '[attributes]',
325+
'[impactOnPrice]' => '[impactOnPriceTaxExcluded]',
326+
],
327+
filtersClass: ProductCombinationFilters::class,
328+
filtersMapping: [
329+
'[_context][shopId]' => '[shopId]',
330+
],
331+
itemsField: 'combinations',
332+
countField: 'totalCombinationsCount',
333+
),
334+
],
335+
exceptionToStatus: [
336+
ProductNotFoundException::class => Response::HTTP_NOT_FOUND,
337+
],
338+
)]
339+
class CombinationList
340+
{
341+
public int $productId;
342+
public int $combinationId;
343+
public string $name;
344+
public bool $default;
345+
public string $reference;
346+
public array $attributes;
347+
}
348+
```
349+
350+
The provider (`QueryListProvider`) builds a `Filters` object from the request query parameters (`offset`, `limit`, `orderBy`, `sortOrder`, `filters`), executes the CQRS query, and returns a `PaginationElements` object with pagination metadata alongside the items. The default page size is 50 items.
351+
352+
The CQRS query receives pagination parameters plus URI variables and context parameters automatically. The normalized query result must expose the items array and total count as top-level fields, identified by `itemsField` and `countField`.
353+
354+
#### Custom parameters
355+
356+
| Parameter | Type | Required | Default | Description |
357+
|---|---|---|---|---|
358+
| `CQRSQuery` | `string` | Yes | — | Fully qualified class name of the CQRS query to execute. The query must handle pagination internally. |
359+
| `scopes` | `string[]` | No | `[]` | OAuth scopes required to access the endpoint. |
360+
| `CQRSQueryMapping` | `array` | No | `null` | Field mapping applied when denormalizing the query object and normalizing the query result. See [Custom Mapping](#custom-mapping). |
361+
| `ApiResourceMapping` | `array` | No | `null` | Field mapping applied when denormalizing each item from the query result into the API resource DTO. See [Custom Mapping](#custom-mapping). |
362+
| `filtersClass` | `string` | No | `Filters::class` | Fully qualified class name of the `Filters` subclass to use. Specify a custom class to enforce default ordering or filtering constraints. |
363+
| `filtersMapping` | `array` | No | `null` | Maps API field names to the internal names used by the `Filters` class. Applied to `filters` and `orderBy` query parameters. See [Custom Mapping](#custom-mapping). |
364+
| `itemsField` | `string` | No | `'items'` | Name of the field in the normalized CQRS query result that holds the list of items. |
365+
| `countField` | `string` | No | `'count'` | Name of the field in the normalized CQRS query result that holds the total item count. |
366+
288367
## PaginatedList
289368

290369
For listing operations we provided a custom operation based on the core grid system based on two settings:

0 commit comments

Comments
 (0)