Extension points, event subscriptions, and preference declarations
The Quote module declares 5 plugins that intercept catalog and tier price operations to keep quote items synchronized.
| Plugin Name | Target | Purpose |
|---|---|---|
| clean_quote_items_after_product_delete | Catalog\Model\ResourceModel\Product | Remove quote items when product is deleted |
| update_quote_items_after_product_save | Catalog\Model\ResourceModel\Product | Mark quotes for recollection on product changes |
| update_quote_items_after_tier_prices_update | Catalog\Api\TierPriceStorageInterface | Recollect quotes when tier prices change |
| quoteProductMassChange | Catalog\Model\Product\Action | Handle mass product status/attribute changes |
Model\Product\Plugin\RemoveQuoteItems
When a product is deleted, this plugin removes all corresponding quote items to prevent orphaned cart items.
public function afterDelete(
ProductResourceModel $subject,
ProductResourceModel $result,
AbstractModel $product
): ProductResourceModel {
$this->quoteItemsCleaner->execute($product);
return $result;
}
Model\Product\Plugin\UpdateQuoteItems
Marks quotes containing the updated product for totals recollection on next access.
public function afterSave(
ProductResourceModel $subject,
ProductResourceModel $result,
AbstractModel $product
): ProductResourceModel {
if ($this->isProductDataChanged($product)) {
$this->markQuotesRecollect->execute([$product->getId()]);
}
return $result;
}
Model\Product\Plugin\MarkQuotesRecollectMassDisabled
Handles mass product actions (bulk disable, attribute updates) by marking affected quotes for recollection.
The Quote module registers 5 observers across global and frontend scopes.
| Observer | Event | Scope | Purpose |
|---|---|---|---|
| CollectTotalsObserver | sales_quote_address_collect_totals_before | global | VAT validation during totals collection |
| SubmitObserver | sales_model_service_quote_submit_success | global | Post-order placement cleanup |
| SendInvoiceEmailObserver | sales_order_invoice_pay | global | Trigger invoice email notification |
Observer\SubmitObserver
Handles post-order submission tasks including quote cleanup and order notifications.
public function execute(Observer $observer): void
{
$quote = $observer->getEvent()->getQuote();
$order = $observer->getEvent()->getOrder();
// Quote is already marked inactive by QuoteManagement
// This observer triggers additional order processing
}
Note: This observer fires after successful order creation. If payment fails, this observer is not called.
Observer\Frontend\Quote\Address\CollectTotalsObserver
Validates customer VAT number during frontend totals collection and adjusts customer group if needed.
// Triggered by: sales_quote_address_collect_totals_before
// Validates VAT for EU customers
// May change customer tax group based on VAT validation result
The Quote module defines 41 interface-to-implementation mappings in di.xml.
CartRepositoryInterface
→
QuoteRepository
CartManagementInterface
→
QuoteManagement
CartItemRepositoryInterface
→
Quote\Item\Repository
CartTotalRepositoryInterface
→
Cart\CartTotalRepository
CartInterface
→
Quote
CartItemInterface
→
Quote\Item
AddressInterface
→
Quote\Address
PaymentInterface
→
Quote\Payment
GuestCartManagementInterface
→
GuestCart\GuestCartManagement
GuestCartRepositoryInterface
→
GuestCart\GuestCartRepository
GuestCouponManagementInterface
→
GuestCart\GuestCouponManagement
MaskedQuoteIdToQuoteIdInterface
→
MaskedQuoteIdToQuoteId
QuoteIdToMaskedQuoteIdInterface
→
QuoteIdToMaskedQuoteId
QuoteMutexInterface
→
QuoteMutex
Add custom fees or discounts via sales.xml collectors, not plugins on collectTotals().
Add custom quote validation via QuoteValidationComposite, not by overriding QuoteValidator.
Never modify quote totals outside the collector system - they will be overwritten on next collectTotals().
Always use QuoteMutex when placing orders to prevent race condition duplicate orders.