Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .claude/document-custom-operation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Generate developer documentation for a PrestaShop Admin API custom operation class.

**Arguments:** `$0` = operation name, `$1` = PrestaShop core path

Example invocation arguments: `toggle-exchange-rate-automatization-command /home/tleone/Dev/prestashop-develop`

## Task

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`.

## Steps

### 1. Read the operation class

The PrestaShop core source is at `$1`. Find operation `$0` in `src/PrestaShopBundle/ApiPlatform/Metadata/`. Read it fully to understand:
- What it extends and what interfaces it implements
- Its constructor parameters (especially the custom ones beyond standard API Platform params)
- How it stores extra properties and what defaults it sets
- What provider/processor it enforces

### 2. Find real-world usages

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.

### 3. Study the existing documentation format

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`).

Each custom operation follows this structure:

```
### OperationName

| HTTP Method | Action |
|---|---|
| METHOD | one-line description |

Brief paragraph explaining what the operation does and when to use it over alternatives.

```php
// full realistic example based on actual usages
```

Behavioral notes about provider/processor, response shape, caveats.

#### Custom parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `paramName` | `string` | Yes | — | What it does |
```

### 4. Generate the documentation section

Write a documentation section for the operation following the format above. The section must include:

- **Header**: `### OperationName`
- **HTTP method table**
- **Description paragraph**: what problem it solves, when to use it over alternatives
- **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
- **Behavioral notes**: how the provider/processor works, what the response looks like, any important caveats
- **Custom parameters table**: only list parameters that are unique to this operation (not standard API Platform params). Columns: Parameter, Type, Required, Default, Description

Keep the tone consistent with the existing devdoc pages: technical and direct, no marketing language.

### 5. Insert into the file

Insert the generated section into `admin-api/resource_server/api-resources.md` at the correct location. Then confirm the insertion was successful.
79 changes: 79 additions & 0 deletions admin-api/resource_server/api-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,85 @@ class ApiClient
}
```

### CQRSPaginate

| HTTP Method | Action |
|-------------|-----------------------------|
| GET | Read a paginated collection |

`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.

```php
<?php
declare(strict_types=1);

namespace PrestaShop\Module\APIResources\ApiPlatform\Resources\Product;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Query\GetEditableCombinationsList;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductNotFoundException;
use PrestaShop\PrestaShop\Core\Search\Filters\ProductCombinationFilters;
use PrestaShopBundle\ApiPlatform\Metadata\CQRSPaginate;
use Symfony\Component\HttpFoundation\Response;

#[ApiResource(
operations: [
new CQRSPaginate(
uriTemplate: '/products/{productId}/combinations',
CQRSQuery: GetEditableCombinationsList::class,
scopes: [
'product_read',
],
CQRSQueryMapping: [
'[_context][langId]' => '[languageId]',
'[_context][shopConstraint]' => '[shopConstraint]',
],
ApiResourceMapping: [
'[combinationName]' => '[name]',
'[attributesInformation]' => '[attributes]',
'[impactOnPrice]' => '[impactOnPriceTaxExcluded]',
],
filtersClass: ProductCombinationFilters::class,
filtersMapping: [
'[_context][shopId]' => '[shopId]',
],
itemsField: 'combinations',
countField: 'totalCombinationsCount',
),
],
exceptionToStatus: [
ProductNotFoundException::class => Response::HTTP_NOT_FOUND,
],
)]
class CombinationList
{
public int $productId;
public int $combinationId;
public string $name;
public bool $default;
public string $reference;
public array $attributes;
}
```

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.

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`.

#### Custom parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `CQRSQuery` | `string` | Yes | — | Fully qualified class name of the CQRS query to execute. The query must handle pagination internally. |
| `scopes` | `string[]` | No | `[]` | OAuth scopes required to access the endpoint. |
| `CQRSQueryMapping` | `array` | No | `null` | Field mapping applied when denormalizing the query object and normalizing the query result. See [Custom Mapping](#custom-mapping). |
| `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). |
| `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. |
| `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). |
| `itemsField` | `string` | No | `'items'` | Name of the field in the normalized CQRS query result that holds the list of items. |
| `countField` | `string` | No | `'count'` | Name of the field in the normalized CQRS query result that holds the total item count. |

## PaginatedList

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