Issue #3609619: Match order constraints by pluggable order attributes (OrderContext + OrderAttributeMatcher)
Implements pluggable order-attribute matching for order constraint policies (issue #3609619).
What
Order constraints no longer hardcode the customer email as the dimension a limit counts by. Each policy now carries a match_by setting naming one or more order attribute matchers, the dimensions two orders must share to count together. The default is the customer email, so existing behavior is unchanged.
New building blocks
OrderContext: the assembled runtime picture of an order (the order plus what tagged builders resolve from it).OrderContextBuilderInterface+OrderContextFactory: taggedyoyaku_order.order_context_builderservices enrich the context per source module, keeping the core decoupled.OrderAttributeMatcherplugin type (attribute, interface, base, manager):value(OrderContext): ?stringreports the order's value on a dimension (null skips an incomplete identity);match(QueryInterface, OrderContext): voidnarrows the count query.- Shipped matchers:
email(yoyaku_order) andcard_token(yoyaku_payment, resolved from the stored payment token so a fresh email cannot slip past a per-customer limit).
Composing several matchers counts two orders together only when they match on all of them (AND); "same email or same card" is two separate policies.
Tests
Kernel coverage for the email default, explicit match_by, incomplete-identity skip, unknown-matcher fail-open (yoyaku_order), and the card-token dimension (yoyaku_payment). Docs and the French translation are updated.