Skip to content

fix(checkout): handle partial entities in the express checkout listing subscriber - #796

Merged
Max Stegmeyer (mstegmeyer) merged 3 commits into
trunkfrom
fix/ecs-listing-partial-entities
Aug 31, 2026
Merged

fix(checkout): handle partial entities in the express checkout listing subscriber#796
Max Stegmeyer (mstegmeyer) merged 3 commits into
trunkfrom
fix/ecs-listing-partial-entities

Conversation

@mstegmeyer

Copy link
Copy Markdown
Contributor

1. Why is this change necessary?

ExpressCheckoutSubscriber::addExcludedProductsToSearchResult() listens to
sales_channel.product.search.result.loaded, which is dispatched for every sales-channel product
search — including those that narrow the loaded fields with Criteria::addFields(). Such reads hydrate
PartialEntity instances, which carry no typed getters, so $product->getParentId() is a fatal error.
The @param …<ProductCollection> docblock is what kept this hidden: the runtime collection is never a
ProductCollection.

Third-party plugins are not the only trigger — core's store-api.product.purchase-limit route, used by
the storefront quantity selector on closeout products, reads products with addFields() and without
parentId.

2. What does this change do, exactly?

The handler no longer assumes a typed product entity: ids are read through Entity::has() /
Entity::get(), the way core's ProductSubscriber handles possibly-partial products, and the event's
generic becomes EntityCollection<Entity> so static analysis stops offering getters that may not exist.

One consequence is deliberate. When a partial read does not request parentId, an exclusion inherited
from the parent product can no longer be detected and the product is not tagged; resolving that would
mean an extra query on every partial product read, defeating the reason callers use addFields().
Exclusions by a product's own id keep working, because the primary key is always loaded.

The two existing tests labelled "related to the ExpressCheckoutSubscriber" never reached the handler —
no credentials, no active payment method, listing disabled — and their assertion compared a UUID against
an ids-collection name. Repairing them is what makes the new regression tests bite.

3. Describe each step to reproduce the issue or behaviour.

  1. Configure PayPal credentials and enable "PayPal Checkout on listing pages".
  2. Trigger a sales-channel product search that uses Criteria::addFields() — for instance change the
    quantity on the detail page of a closeout product, which calls the purchase-limit route.
  3. Before this change: Call to undefined method PartialEntity::getParentId().

The new tests in ExcludedProductValidatorTest reproduce this through a plain
sales_channel.product.repository search.

4. Please link to the relevant issues (if any).

closes #554

5. Checklist

  • I have written tests and verified that they fail without my change
  • I have created an entry in the CHANGELOG.md files with all necessary user information about my changes
  • This change has comments for package types, values, functions, and non-obvious lines of code
  • I have read the contribution requirements and fulfill them.

@mstegmeyer
Max Stegmeyer (mstegmeyer) added this pull request to the merge queue Aug 31, 2026
Merged via the queue into trunk with commit c90c6ac Aug 31, 2026
27 checks passed
@mstegmeyer
Max Stegmeyer (mstegmeyer) deleted the fix/ecs-listing-partial-entities branch August 31, 2026 14:49
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.

Problem with partial entities

3 participants