55 */
66namespace Magento \Checkout \Block \Cart ;
77
8+ use Magento \Framework \App \ObjectManager ;
89use Magento \Quote \Model \Quote ;
10+ use Magento \Checkout \Observer \CatalogRuleSaveAfterObserver ;
911
1012/**
1113 * Shopping cart abstract block
@@ -15,7 +17,12 @@ class AbstractCart extends \Magento\Framework\View\Element\Template
1517 /**
1618 * Block alias fallback
1719 */
18- const DEFAULT_TYPE = 'default ' ;
20+ public const DEFAULT_TYPE = 'default ' ;
21+
22+ /**
23+ * Session key for last time cart totals were recollected (used with catalog rules cache).
24+ */
25+ private const SESSION_KEY_LAST_RECOLLECT_AT = 'last_cart_totals_recollect_at ' ;
1926
2027 /**
2128 * @var Quote|null
@@ -44,21 +51,28 @@ class AbstractCart extends \Magento\Framework\View\Element\Template
4451 */
4552 protected $ _checkoutSession ;
4653
54+ /**
55+ * @var \Magento\Framework\App\CacheInterface
56+ */
57+ private $ cache ;
58+
4759 /**
4860 * @param \Magento\Framework\View\Element\Template\Context $context
4961 * @param \Magento\Customer\Model\Session $customerSession
5062 * @param \Magento\Checkout\Model\Session $checkoutSession
5163 * @param array $data
52- * @codeCoverageIgnore
64+ * @param \Magento\Framework\App\CacheInterface|null $cache
5365 */
5466 public function __construct (
5567 \Magento \Framework \View \Element \Template \Context $ context ,
5668 \Magento \Customer \Model \Session $ customerSession ,
5769 \Magento \Checkout \Model \Session $ checkoutSession ,
58- array $ data = []
70+ array $ data = [],
71+ ?\Magento \Framework \App \CacheInterface $ cache = null
5972 ) {
6073 $ this ->_customerSession = $ customerSession ;
6174 $ this ->_checkoutSession = $ checkoutSession ;
75+ $ this ->cache = $ cache ?? ObjectManager::getInstance ()->get (\Magento \Framework \App \CacheInterface::class);
6276 parent ::__construct ($ context , $ data );
6377 $ this ->_isScopePrivate = true ;
6478 }
@@ -107,15 +121,46 @@ public function getQuote()
107121 {
108122 if (null === $ this ->_quote ) {
109123 $ this ->_quote = $ this ->_checkoutSession ->getQuote ();
124+
125+ if ($ this ->_quote ->getId () && $ this ->shouldRecollectTotals ()) {
126+ $ existingItemsCount = $ this ->_quote ->getItemsCount ();
127+ $ existingItemsQty = $ this ->_quote ->getItemsQty ();
128+ $ existingVirtualItemsQty = $ this ->_quote ->getData ('virtual_items_qty ' );
129+ $ this ->_quote ->setData ('totals_collected_flag ' , false );
130+ $ this ->_quote ->collectTotals ();
131+ $ this ->_quote ->setItemsCount ($ existingItemsCount );
132+ $ this ->_quote ->setItemsQty ($ existingItemsQty );
133+ $ this ->_quote ->setData ('virtual_items_qty ' , $ existingVirtualItemsQty );
134+ $ this ->_checkoutSession ->setData (
135+ self ::SESSION_KEY_LAST_RECOLLECT_AT ,
136+ $ this ->cache ->load (CatalogRuleSaveAfterObserver::CACHE_KEY_CATALOG_RULES_UPDATED_AT )
137+ );
138+ }
110139 }
111140 return $ this ->_quote ;
112141 }
113142
143+ /**
144+ * Whether cart totals should be recollected (only after a catalog price rule was saved).
145+ *
146+ * @return bool
147+ */
148+ private function shouldRecollectTotals (): bool
149+ {
150+ $ rulesUpdatedAt = (int ) ($ this ->cache ->load (
151+ CatalogRuleSaveAfterObserver::CACHE_KEY_CATALOG_RULES_UPDATED_AT
152+ ) ?: 0 );
153+ if ($ rulesUpdatedAt <= 0 ) {
154+ return false ;
155+ }
156+ $ lastRecollectAt = (int ) ($ this ->_checkoutSession ->getData (self ::SESSION_KEY_LAST_RECOLLECT_AT ) ?: 0 );
157+ return $ rulesUpdatedAt > $ lastRecollectAt ;
158+ }
159+
114160 /**
115161 * Get all cart items
116162 *
117163 * @return array
118- * @codeCoverageIgnore
119164 */
120165 public function getItems ()
121166 {
@@ -135,15 +180,18 @@ public function getItemHtml(\Magento\Quote\Model\Quote\Item $item)
135180 }
136181
137182 /**
183+ * Retrieve totals.
184+ *
138185 * @return array
139- * @codeCoverageIgnore
140186 */
141187 public function getTotals ()
142188 {
143189 return $ this ->getTotalsCache ();
144190 }
145191
146192 /**
193+ * Retrieve cached totals.
194+ *
147195 * @return array
148196 */
149197 public function getTotalsCache ()
0 commit comments