Merge the Country endpoints into one domain PR - #429
Conversation
Expose GetCountryRequiredFields through GET /countries/{countryId}/required-fields,
in a dedicated resource class (like CustomerDetails / SupplierDetails). The query
returns a small object {stateRequired, dniRequired} mapped by matching field names
(no explicit mapping needed, same as SearchEngine).
Adds an integration test and a scopes entry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds three status/zone mutation endpoints, standalone files to avoid
touching the existing Country.php:
- PUT /countries/{countryId}/toggle-status (ToggleCountryStatusCommand)
- PUT /countries/bulk-toggle-status (BulkToggleCountriesStatusCommand)
- PUT /countries/bulk-update-zone (BulkUpdateCountryZoneCommand)
The three commands were introduced in PS 9.1+/develop and do not exist
at the 9.0.3 tag — the 9.0.3 CI matrix legs will fail until PR PrestaShop#220
(drop 9.0.3 from CI) lands.
Related to PrestaShop/PrestaShop#39630
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consolidates PrestaShop#217, PrestaShop#368 and PrestaShop#394. PrestaShop#217 and PrestaShop#394 both modified CountryEndpointTest.php and conflict on cherry-pick. The status and zone test class is folded into CountryEndpointTest and stops working on fixture data. It used to look its subject up with SELECT id_country FROM ps_country and assert with SELECT active / SELECT id_zone, which meant toggling and re-zoning whatever country the fixtures happened to install first. It now creates the countries it operates on through POST /countries and reads the result back through GET /countries/{countryId}, which already exposes enabled and zoneId. The required-fields assertion also pins the complete key set instead of checking three keys individually. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ToggleCountryStatusCommand, BulkToggleCountriesStatusCommand, BulkUpdateCountryZoneCommand and BulkDeleteCountriesCommand were introduced by the Countries grid migration (PrestaShop/PrestaShop#41495 and #41931), which shipped in 9.2.0. On older cores ApiResourceScopesExtractor::skipCQRSNotFound() drops those operations from the routing, so their endpoints answer 404 instead of 401/200. Declare minVersion 9.2.0 on the four operations, skip their tests below that version, and drop the four protected-endpoint data sets there too. The class_exists() guard on testBulkDeleteCountries is replaced by the same helper.
YE is a real ISO 3166-1 code the fixtures already ship, so the second fixture of testBulkToggleCountriesStatus failed with DuplicateCountryIsoCodeException.
The four operations declare minVersion 9.2.0, so their CQRS classes are legitimately absent on the older cores the matrix still runs.
📋 Summary of changesThis PR adds five new Country-domain endpoints by merging three previously open PRs (#217, #368, #394): a read-only sub-resource ⏱️ Estimated review time30–40 minutes — five new resource classes with straightforward mappings, but the bulk/toggle operations raise questions about exception coverage, response bodies, and missing validation tests. 🎯 Scope
🧱 API Platform / CQRS architecture complianceCountryRequiredFields.php
CountryStatus.php
BulkCountriesStatus.php
BulkCountriesZone.php
BulkDeleteCountries.php
PHPStan neon files
💡 Improvement suggestions
✅ Pre-review checklistURI & routing
Operations & scopes
API Resource properties
CQRS mapping
Forbidden practices (CI-enforced)
Exception handling & validation
Multi-shop
Listing field alignment — not applicable (no list endpoint in this PR) Integration test
|
nicosomb
left a comment
There was a problem hiding this comment.
A few items from the automated pre-review turned out fine after checking Core, no changes needed:
CountryRequiredFields with no QUERY_MAPPING: CountryRequiredFields's isStateRequired()/isDniRequired() match stateRequired/dniRequired exactly, and countryId comes from the URI variable merge rather than the query result. No mapping needed.
BulkCountriesZone with no CQRSCommandMapping: BulkUpdateCountryZoneCommand's constructor parameters (countryIds, newZoneId) match the DTO property names exactly.
The Rector skip-list for toggle-status/required-fields/etc: the Rector Dry Run check is green on this PR, which confirms these keywords are already handled.
| ), | ||
| ], | ||
| exceptionToStatus: [ | ||
| CountryNotFoundException::class => Response::HTTP_NOT_FOUND, |
There was a problem hiding this comment.
Only CountryNotFoundException is mapped. BulkToggleCountriesStatusCommand builds a CountryId per id, whose assertion throws CountryConstraintException on an invalid one, unmapped here so it falls through to 500. BulkCountriesZone in this same PR has CountryException mapped to 422, worth aligning.
| ), | ||
| ], | ||
| exceptionToStatus: [ | ||
| CountryNotFoundException::class => Response::HTTP_NOT_FOUND, |
There was a problem hiding this comment.
Same gap as BulkCountriesStatus: BulkDeleteCountriesCommand builds a CountryId per id the same way, and the resulting CountryConstraintException isn't mapped here either.
| * BulkDeleteCountriesCommand only exists since 9.2.0, so the operation is filtered out of | ||
| * the routing on older cores and the test is skipped there. | ||
| */ | ||
| public function testBulkDeleteCountries(): void |
There was a problem hiding this comment.
None of the four new endpoints here (bulk-delete, toggle-status, bulk-toggle-status, bulk-update-zone) have a testInvalid* counterpart. The existing create/edit tests do use assertValidationErrors, just not extended to these.
What this PR does
Merges #217, #368 and #394 into one PR, following the mutualisation done on the Product domain in #410.
Endpoints added
/countries/{countryId}/required-fieldsGetCountryRequiredFieldscountry_read/countries/{countryId}/toggle-statusToggleCountryStatusCommandcountry_write/countries/bulk-toggle-statusBulkToggleCountriesStatusCommandcountry_write/countries/bulk-update-zoneBulkUpdateCountriesZoneCommandcountry_write/countries/bulk-deleteBulkDeleteCountriesCommandcountry_write#217 and #394 both modified
tests/Integration/ApiPlatform/CountryEndpointTest.phpand conflict on cherry-pick.Tests
CountryStatusZoneEndpointTestis folded intoCountryEndpointTest, and this is where the merge pays off: the status and zone tests were operating on fixture data.They looked their subject up in
ps_countryand asserted withSELECT active/SELECT id_zone— so they toggled and re-zoned whichever country the fixtures happened to install first, and left it that way for the rest of the suite.CountryEndpointTest, in the same domain, was already creating countries throughPOST /countries.The status and zone tests now create the countries they operate on, and read the result back through
GET /countries/{countryId}, which already exposesenabledandzoneId.The required-fields assertion pins the complete key set (
countryId,stateRequired,dniRequired) rather than checking three keys one by one.The status and bulk operations require 9.2.0
ToggleCountryStatusCommand,BulkToggleCountriesStatusCommand,BulkUpdateCountryZoneCommandandBulkDeleteCountriesCommandwere all introduced by the Countries grid migration (PrestaShop/PrestaShop#41495 and PrestaShop/PrestaShop#41931) and only ship from 9.2.0. On 9.0/9.1ApiResourceScopesExtractor::skipCQRSNotFound()drops the operations from the routing entirely, so the endpoints answer 404 — not 401 — and they disappear from the scope registration too.The four operations therefore declare
extraProperties: ['minVersion' => '9.2.0'], their tests callmarkTestSkippedByMinVersion('9.2.0'), andgetProtectedEndpoints()only yields their data sets from 9.2.0 on. This replaces the ad-hocclass_exists(BulkDeleteCountriesCommand::class)gate #394 used for the bulk delete alone.How to test
The four status/bulk endpoints need a 9.2.0+ core; on 9.0/9.1 they are not routed at all.
Covered by
CountryEndpointTest.Supersedes
All three will be closed once the CI is green here.