Skip to content

Commit a7ef876

Browse files
Fix: Force current currency reload on currency code change
Fixed an issue where calling setCurrentCurrencyCode() multiple times did not update the currency returned by getCurrentCurrency() due to internal caching. The issue occurred because getCurrentCurrency() caches the currency object in the store's data using the 'current_currency' key. When setCurrentCurrencyCode() was called to change the currency code, the cached currency object was not cleared, causing getCurrentCurrency() to return the old currency instead of loading the new one. Solution: - Added unsetData('current_currency') in setCurrentCurrencyCode() to clear the cached currency when the currency code changes - This forces getCurrentCurrency() to reload the currency based on the new currency code on its next call Changes: - Updated Store::setCurrentCurrencyCode() to clear cached currency - Added unit test to verify currency cache is cleared on code change Test coverage: - Added testSetCurrentCurrencyCodeClearsCachedCurrency() unit test - Test verifies unsetData() is called when currency code changes - Test verifies behavior with multiple currency code changes Manual testing: 1. Create store with multiple available currencies (USD, EUR) 2. Call $store->setCurrentCurrencyCode('USD') 3. Verify $store->getCurrentCurrency()->getCode() returns 'USD' 4. Call $store->setCurrentCurrencyCode('EUR') 5. Verify $store->getCurrentCurrency()->getCode() returns 'EUR' 6. Without this fix, step 5 would return 'USD' Fixes: #40333
1 parent 0a3b703 commit a7ef876

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

app/code/Magento/Store/Model/Store.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,9 @@ public function setCurrentCurrencyCode($code)
911911
: $this->_storeManager->getWebsite()->getDefaultStore()->getDefaultCurrency()->getCode();
912912

913913
$this->_httpContext->setValue(Context::CONTEXT_CURRENCY, $code, $defaultCode);
914+
915+
// Force reload of current currency on currency code change
916+
$this->unsetData('current_currency');
914917
}
915918
return $this;
916919
}

app/code/Magento/Store/Test/Unit/Model/StoreTest.php

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,107 @@ public static function currencyCodeDataProvider(): array
819819
];
820820
}
821821

822+
/**
823+
* Test that setCurrentCurrencyCode clears cached currency
824+
*
825+
* @return void
826+
*/
827+
public function testSetCurrentCurrencyCodeClearsCachedCurrency(): void
828+
{
829+
$currencyCodeFirst = 'USD';
830+
$currencyCodeSecond = 'EUR';
831+
832+
$sessionMock = $this->getMockBuilder(SessionManagerInterface::class)
833+
->getMockForAbstractClass();
834+
$sessionMock->expects($this->exactly(2))
835+
->method('setCurrencyCode')
836+
->willReturnCallback(function ($code) use ($currencyCodeFirst, $currencyCodeSecond) {
837+
static $callCount = 0;
838+
$callCount++;
839+
if ($callCount === 1) {
840+
$this->assertEquals($currencyCodeFirst, $code);
841+
} else {
842+
$this->assertEquals($currencyCodeSecond, $code);
843+
}
844+
});
845+
846+
$httpContextMock = $this->getMockBuilder(\Magento\Framework\App\Http\Context::class)
847+
->disableOriginalConstructor()
848+
->getMock();
849+
850+
$currencyFactoryMock = $this->getMockBuilder(CurrencyFactory::class)
851+
->disableOriginalConstructor()
852+
->getMock();
853+
854+
$currencyMockFirst = $this->getMockBuilder(Currency::class)
855+
->disableOriginalConstructor()
856+
->getMock();
857+
$currencyMockFirst->expects($this->any())
858+
->method('getCode')
859+
->willReturn($currencyCodeFirst);
860+
861+
$currencyMockSecond = $this->getMockBuilder(Currency::class)
862+
->disableOriginalConstructor()
863+
->getMock();
864+
$currencyMockSecond->expects($this->any())
865+
->method('getCode')
866+
->willReturn($currencyCodeSecond);
867+
868+
$storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
869+
->getMockForAbstractClass();
870+
$storeManagerMock->expects($this->any())
871+
->method('getStore')
872+
->willReturn(null);
873+
874+
$websiteMock = $this->getMockBuilder(WebsiteInterface::class)
875+
->getMockForAbstractClass();
876+
$websiteMock->expects($this->any())
877+
->method('getDefaultStore')
878+
->willReturnSelf();
879+
$websiteMock->expects($this->any())
880+
->method('getDefaultCurrency')
881+
->willReturn($currencyMockFirst);
882+
883+
$storeManagerMock->expects($this->any())
884+
->method('getWebsite')
885+
->willReturn($websiteMock);
886+
887+
$storeMock = $this->getMockBuilder(Store::class)
888+
->setConstructorArgs([
889+
$this->createMock(\Magento\Framework\Model\Context::class),
890+
$this->createMock(\Magento\Framework\Registry::class),
891+
$this->createMock(\Magento\Framework\App\Cache\Type\Config::class),
892+
$this->createMock(\Magento\Framework\Url::class),
893+
$this->requestMock,
894+
$this->createMock(\Magento\Config\Model\ResourceModel\Config\Data::class),
895+
$this->configMock,
896+
$storeManagerMock,
897+
$this->filesystemMock,
898+
$this->createMock(\Magento\Framework\Url\ModifierInterface::class),
899+
$sessionMock,
900+
$httpContextMock,
901+
$this->createMock(\Magento\Framework\App\Config::class),
902+
$currencyFactoryMock
903+
])
904+
->onlyMethods(['getAvailableCurrencyCodes', 'getData', 'unsetData', 'setData'])
905+
->getMock();
906+
907+
$storeMock->expects($this->any())
908+
->method('getAvailableCurrencyCodes')
909+
->willReturn([$currencyCodeFirst, $currencyCodeSecond]);
910+
911+
// Expect unsetData to be called when currency code changes
912+
$storeMock->expects($this->exactly(2))
913+
->method('unsetData')
914+
->with('current_currency');
915+
916+
// First currency change
917+
$storeMock->setCurrentCurrencyCode($currencyCodeFirst);
918+
919+
// Second currency change - should clear cached currency
920+
$storeMock->setCurrentCurrencyCode($currencyCodeSecond);
921+
}
922+
822923
/**
823924
* @param Store $model
824925
*/

0 commit comments

Comments
 (0)