diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php
index 629500ca91cdc..053d7d6e97826 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Filter/DateTimeTest.php
@@ -10,6 +10,7 @@
use Magento\Catalog\Model\Product\Filter\DateTime;
use Magento\Framework\Locale\Resolver;
use Magento\Framework\Locale\ResolverInterface;
+use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory;
use Magento\Framework\Stdlib\DateTime\Timezone;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\TestCase;
@@ -43,7 +44,7 @@ function () {
);
$timezone = $objectManager->getObject(
Timezone::class,
- ['localeResolver' => $localeResolver]
+ ['localeResolver' => $localeResolver, 'dateFormatterFactory' => new DateFormatterFactory()]
);
$stdlibDateTimeFilter = $objectManager->getObject(
\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class,
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
index 264c55ba43390..bebf6ce5302d6 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
@@ -35,7 +35,7 @@
-
+
diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml
new file mode 100644
index 0000000000000..c4c70cef81b0b
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Mftf/Test/CheckoutDifferentDefaultCountryPerStoreTest.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCountry
+ {{DE_Address_Berlin_Not_Default_Address.country_id}}
+
+
+
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
index a857d89a72b14..d1adb27353e1c 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
@@ -79,7 +79,13 @@ define(
if (!quote.isVirtual()) {
checkoutProvider.on('shippingAddress', function (shippingAddressData) {
- checkoutData.setShippingAddressFromData(shippingAddressData);
+ //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
+ if (quote.shippingAddress().countryId !== shippingAddressData.country_id ||
+ (shippingAddressData.postcode || shippingAddressData.region_id)
+ ) {
+ checkoutData.setShippingAddressFromData(shippingAddressData);
+ }
+ //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
});
} else {
checkoutProvider.on('shippingAddress', function (shippingAddressData) {
diff --git a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php
index 39071f25ea18c..70232e955a86d 100644
--- a/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Block/Widget/DobTest.php
@@ -19,6 +19,7 @@
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Locale\Resolver;
use Magento\Framework\Locale\ResolverInterface;
+use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory;
use Magento\Framework\Stdlib\DateTime\Timezone;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\View\Element\Html\Date;
@@ -50,7 +51,7 @@ class DobTest extends TestCase
const YEAR = '2014';
// Value of date('Y', strtotime(self::DATE))
- const DATE_FORMAT = 'M/d/Y';
+ const DATE_FORMAT = 'M/d/y';
/** Constants used by Dob::setDateInput($code, $html) */
const DAY_HTML =
@@ -119,7 +120,7 @@ function () {
);
$timezone = $objectManager->getObject(
Timezone::class,
- ['localeResolver' => $localeResolver]
+ ['localeResolver' => $localeResolver, 'dateFormatterFactory' => new DateFormatterFactory()]
);
$this->_locale = Resolver::DEFAULT_LOCALE;
@@ -357,7 +358,8 @@ public function getDateFormatDataProvider(): array
preg_replace(
'/[^MmDdYy\/\.\-]/',
'',
- (new \IntlDateFormatter('ar_SA', \IntlDateFormatter::SHORT, \IntlDateFormatter::NONE))
+ (new DateFormatterFactory())
+ ->create('ar_SA', \IntlDateFormatter::SHORT, \IntlDateFormatter::NONE)
->getPattern()
)
],
diff --git a/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php
new file mode 100644
index 0000000000000..0bb102f34dd2d
--- /dev/null
+++ b/app/code/Magento/GroupedProduct/Model/Inventory/ParentItemProcessor.php
@@ -0,0 +1,173 @@
+groupedType = $groupedType;
+ $this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
+ $this->stockConfiguration = $stockConfiguration;
+ $this->stockItemRepository = $stockItemRepository;
+ $this->resource = $resource;
+ $this->metadataPool = $metadataPool;
+ }
+
+ /**
+ * Process parent products
+ *
+ * @param Product $product
+ * @return void
+ */
+ public function process(Product $product)
+ {
+ $parentIds = $this->getParentEntityIdsByChild($product->getId());
+ foreach ($parentIds as $productId) {
+ $this->processStockForParent((int)$productId);
+ }
+ }
+
+ /**
+ * Change stock item for parent product depending on children stock items
+ *
+ * @param int $productId
+ * @return void
+ */
+ private function processStockForParent(int $productId)
+ {
+ $criteria = $this->criteriaInterfaceFactory->create();
+ $criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
+ $criteria->setProductsFilter($productId);
+ $stockItemCollection = $this->stockItemRepository->getList($criteria);
+ $allItems = $stockItemCollection->getItems();
+ if (empty($allItems)) {
+ return;
+ }
+ $parentStockItem = array_shift($allItems);
+ $groupedChildrenIds = $this->groupedType->getChildrenIds($productId);
+ $criteria->setProductsFilter($groupedChildrenIds);
+ $stockItemCollection = $this->stockItemRepository->getList($criteria);
+ $allItems = $stockItemCollection->getItems();
+
+ $groupedChildrenIsInStock = false;
+
+ foreach ($allItems as $childItem) {
+ if ($childItem->getIsInStock() === true) {
+ $groupedChildrenIsInStock = true;
+ break;
+ }
+ }
+
+ if ($this->isNeedToUpdateParent($parentStockItem, $groupedChildrenIsInStock)) {
+ $parentStockItem->setIsInStock($groupedChildrenIsInStock);
+ $parentStockItem->setStockStatusChangedAuto(1);
+ $this->stockItemRepository->save($parentStockItem);
+ }
+ }
+
+ /**
+ * Check is parent item should be updated
+ *
+ * @param StockItemInterface $parentStockItem
+ * @param bool $childrenIsInStock
+ * @return bool
+ */
+ private function isNeedToUpdateParent(StockItemInterface $parentStockItem, bool $childrenIsInStock): bool
+ {
+ return $parentStockItem->getIsInStock() !== $childrenIsInStock &&
+ ($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto());
+ }
+
+ /**
+ * Retrieve parent ids array by child id
+ *
+ * @param int $childId
+ * @return string[]
+ */
+ private function getParentEntityIdsByChild($childId)
+ {
+ $select = $this->resource->getConnection()
+ ->select()
+ ->from(['l' => $this->resource->getTableName('catalog_product_link')], [])
+ ->join(
+ ['e' => $this->resource->getTableName('catalog_product_entity')],
+ 'e.' .
+ $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField() . ' = l.product_id',
+ ['e.entity_id']
+ )
+ ->where('l.linked_product_id = ?', $childId)
+ ->where(
+ 'link_type_id = ?',
+ Link::LINK_TYPE_GROUPED
+ );
+
+ return $this->resource->getConnection()->fetchCol($select);
+ }
+}
diff --git a/app/code/Magento/GroupedProduct/etc/di.xml b/app/code/Magento/GroupedProduct/etc/di.xml
index 43678d0ad7a82..d9534c6d3fe7d 100644
--- a/app/code/Magento/GroupedProduct/etc/di.xml
+++ b/app/code/Magento/GroupedProduct/etc/di.xml
@@ -105,4 +105,11 @@
+
+
+
+ - Magento\GroupedProduct\Model\Inventory\ParentItemProcessor
+
+
+
diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
index 55992c92226af..87cd4cf346288 100644
--- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
+++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php
@@ -226,6 +226,7 @@ protected function _prepareForm()
'title' => __('Select File to Import'),
'required' => true,
'class' => 'input-file',
+ 'onchange' => 'varienImport.refreshLoadedFileLastModified(this);',
'note' => __(
'File must be saved in UTF-8 encoding for proper import'
),
@@ -282,7 +283,7 @@ protected function getDownloadSampleFileHtml()
private function getImportBehaviorTooltip()
{
$html = '
';
diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv
index a4943fe72826f..a91a76612fd9f 100644
--- a/app/code/Magento/ImportExport/i18n/en_US.csv
+++ b/app/code/Magento/ImportExport/i18n/en_US.csv
@@ -127,3 +127,4 @@ Summary,Summary
"File %1 deleted","File %1 deleted"
"Please provide valid export file name","Please provide valid export file name"
"%1 is not a valid file","%1 is not a valid file"
+"Content of uploaded file was changed, please re-upload the file","Content of uploaded file was changed, please re-upload the file"
diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml
index 69779baba381d..d512ce8182ede 100644
--- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml
+++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml
@@ -7,6 +7,10 @@
escapeHtml(
+ __('Content of uploaded file was changed, please re-upload the file')
+);
?>
escapeJs($block->getUrl('*/*/download/', ['filename' => 'entity-name']))}',
+ /**
+ * Loaded file last modified
+ * @type {int|null}
+ */
+ loadedFileLastModified: null,
+
/**
* Reset selected index
* @param {string} elementId
@@ -162,11 +172,50 @@ require([
}
},
+ /**
+ * Refresh loaded file last modified
+ */
+ refreshLoadedFileLastModified: function(e) {
+ if (jQuery(e)[0].files.length > 0) {
+ this.loadedFileLastModified = jQuery(e)[0].files[0].lastModified;
+ } else {
+ this.loadedFileLastModified = null;
+ }
+ },
+
/**
* Post form data to dynamic iframe.
* @param {string} newActionUrl OPTIONAL Change form action to this if specified
*/
postToFrame: function(newActionUrl) {
+ var fileUploader = document.getElementById('{$fieldNameSourceFile}');
+
+ if (fileUploader.files.length > 0) {
+ var file = fileUploader.files[0],
+ ifrElName = this.ifrElemName,
+ reader = new FileReader();
+
+ reader.readAsText(file, "UTF-8");
+
+ reader.onerror = function () {
+ jQuery('body').loader('hide');
+ alert({
+ content: '{$uploaderErrorMessage}'
+ });
+ fileUploader.value = null;
+ jQuery('iframe#' + ifrElName).remove();
+ return;
+ }
+
+ if (file.lastModified !== this.loadedFileLastModified) {
+ alert({
+ content: '{$uploaderErrorMessage}'
+ });
+ fileUploader.value = null;
+ return;
+ }
+ }
+
if (!jQuery('[name="' + this.ifrElemName + '"]').length) {
jQuery('body').append('');
jQuery('iframe#' + this.ifrElemName).attr('display', 'none');
diff --git a/app/code/Magento/Persistent/Model/QuoteManager.php b/app/code/Magento/Persistent/Model/QuoteManager.php
index b6504d528fbe4..35b07ebdb7c44 100644
--- a/app/code/Magento/Persistent/Model/QuoteManager.php
+++ b/app/code/Magento/Persistent/Model/QuoteManager.php
@@ -5,6 +5,7 @@
*/
namespace Magento\Persistent\Model;
+use Magento\Customer\Api\Data\CustomerInterfaceFactory;
use Magento\Customer\Api\Data\GroupInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Persistent\Helper\Data;
@@ -64,6 +65,11 @@ class QuoteManager
*/
private $cartExtensionFactory;
+ /**
+ * @var CustomerInterfaceFactory
+ */
+ private $customerDataFactory;
+
/**
* @param \Magento\Persistent\Helper\Session $persistentSession
* @param Data $persistentData
@@ -71,6 +77,7 @@ class QuoteManager
* @param CartRepositoryInterface $quoteRepository
* @param CartExtensionFactory|null $cartExtensionFactory
* @param ShippingAssignmentProcessor|null $shippingAssignmentProcessor
+ * @param CustomerInterfaceFactory|null $customerDataFactory
*/
public function __construct(
\Magento\Persistent\Helper\Session $persistentSession,
@@ -78,7 +85,8 @@ public function __construct(
\Magento\Checkout\Model\Session $checkoutSession,
CartRepositoryInterface $quoteRepository,
?CartExtensionFactory $cartExtensionFactory = null,
- ?ShippingAssignmentProcessor $shippingAssignmentProcessor = null
+ ?ShippingAssignmentProcessor $shippingAssignmentProcessor = null,
+ ?CustomerInterfaceFactory $customerDataFactory = null
) {
$this->persistentSession = $persistentSession;
$this->persistentData = $persistentData;
@@ -88,6 +96,8 @@ public function __construct(
?? ObjectManager::getInstance()->get(CartExtensionFactory::class);
$this->shippingAssignmentProcessor = $shippingAssignmentProcessor
?? ObjectManager::getInstance()->get(ShippingAssignmentProcessor::class);
+ $this->customerDataFactory = $customerDataFactory
+ ?? ObjectManager::getInstance()->get(CustomerInterfaceFactory::class);
}
/**
@@ -109,14 +119,11 @@ public function setGuest($checkQuote = false)
$quote->getPaymentsCollection()->walk('delete');
$quote->getAddressesCollection()->walk('delete');
$this->_setQuotePersistent = false;
+ $this->cleanCustomerData($quote);
$quote->setIsActive(true)
- ->setCustomerId(null)
- ->setCustomerEmail(null)
- ->setCustomerFirstname(null)
- ->setCustomerLastname(null)
- ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID)
->setIsPersistent(false)
->removeAllAddresses();
+
//Create guest addresses
$quote->getShippingAddress();
$quote->getBillingAddress();
@@ -129,6 +136,27 @@ public function setGuest($checkQuote = false)
$this->persistentSession->setSession(null);
}
+ /**
+ * Clear customer data in quote
+ *
+ * @param Quote $quote
+ */
+ private function cleanCustomerData($quote)
+ {
+ /**
+ * Set empty customer object in quote to avoid restore customer id
+ * @see Quote::beforeSave()
+ */
+ if ($quote->getCustomerId()) {
+ $quote->setCustomer($this->customerDataFactory->create());
+ }
+ $quote->setCustomerId(null)
+ ->setCustomerEmail(null)
+ ->setCustomerFirstname(null)
+ ->setCustomerLastname(null)
+ ->setCustomerGroupId(GroupInterface::NOT_LOGGED_IN_ID);
+ }
+
/**
* Emulate guest cart with persistent cart
*
diff --git a/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php b/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php
index f2f9b96fa82e4..98c9c3df27852 100644
--- a/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php
+++ b/app/code/Magento/Persistent/Observer/MakePersistentQuoteGuestObserver.php
@@ -1,16 +1,14 @@
_persistentSession = $persistentSession;
$this->_persistentData = $persistentData;
$this->_customerSession = $customerSession;
- $this->quoteManager = $quoteManager;
+ $this->checkoutSession = $checkoutSession;
}
/**
@@ -74,7 +72,7 @@ public function execute(\Magento\Framework\Event\Observer $observer)
if (($this->_persistentSession->isPersistent() && !$this->_customerSession->isLoggedIn())
|| $this->_persistentData->isShoppingCartPersist()
) {
- $this->quoteManager->setGuest(true);
+ $this->checkoutSession->clearQuote()->clearStorage();
}
}
}
diff --git a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php
index fe754711c910b..efc9ecd4c1a59 100644
--- a/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php
+++ b/app/code/Magento/Persistent/Observer/RemoveGuestPersistenceOnEmptyCartObserver.php
@@ -10,6 +10,8 @@
/**
* Observer to remove persistent session if guest empties persistent cart previously created and added to by customer.
+ *
+ * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
*/
class RemoveGuestPersistenceOnEmptyCartObserver implements ObserverInterface
{
@@ -96,6 +98,8 @@ public function execute(\Magento\Framework\Event\Observer $observer)
}
if (!$cart || $cart->getItemsCount() == 0) {
+ $this->customerSession->setCustomerId(null)
+ ->setCustomerGroupId(null);
$this->quoteManager->setGuest();
}
}
diff --git a/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php b/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php
index 0c183084edca2..03d6ab02beb3c 100644
--- a/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php
+++ b/app/code/Magento/Persistent/Test/Unit/Model/QuoteManagerTest.php
@@ -9,6 +9,8 @@
namespace Magento\Persistent\Test\Unit\Model;
use Magento\Checkout\Model\Session;
+use Magento\Customer\Api\Data\CustomerInterface;
+use Magento\Customer\Api\Data\CustomerInterfaceFactory;
use Magento\Customer\Model\GroupManagement;
use Magento\Eav\Model\Entity\Collection\AbstractCollection;
use Magento\Persistent\Helper\Data;
@@ -78,6 +80,11 @@ class QuoteManagerTest extends TestCase
*/
private $shippingAssignmentProcessor;
+ /**
+ * @var CustomerInterfaceFactory|MockObject
+ */
+ private $customerDataFactory;
+
protected function setUp(): void
{
$this->persistentSessionMock = $this->createMock(\Magento\Persistent\Helper\Session::class);
@@ -124,13 +131,15 @@ protected function setUp(): void
'getItemsQty',
'getExtensionAttributes',
'setExtensionAttributes',
- '__wakeup'
+ '__wakeup',
+ 'setCustomer'
])
->disableOriginalConstructor()
->getMock();
$this->cartExtensionFactory = $this->createPartialMock(CartExtensionFactory::class, ['create']);
$this->shippingAssignmentProcessor = $this->createPartialMock(ShippingAssignmentProcessor::class, ['create']);
+ $this->customerDataFactory = $this->createMock(CustomerInterfaceFactory::class);
$this->model = new QuoteManager(
$this->persistentSessionMock,
@@ -138,7 +147,8 @@ protected function setUp(): void
$this->checkoutSessionMock,
$this->quoteRepositoryMock,
$this->cartExtensionFactory,
- $this->shippingAssignmentProcessor
+ $this->shippingAssignmentProcessor,
+ $this->customerDataFactory
);
}
@@ -189,6 +199,7 @@ public function testSetGuestWhenShoppingCartAndQuoteAreNotPersistent()
public function testSetGuest()
{
+ $customerId = 22;
$this->checkoutSessionMock->expects($this->once())
->method('getQuote')->willReturn($this->quoteMock);
$this->quoteMock->expects($this->once())->method('getId')->willReturn(11);
@@ -220,6 +231,7 @@ public function testSetGuest()
->method('getShippingAddress')->willReturn($quoteAddressMock);
$this->quoteMock->expects($this->once())
->method('getBillingAddress')->willReturn($quoteAddressMock);
+ $this->quoteMock->method('getCustomerId')->willReturn($customerId);
$this->quoteMock->expects($this->once())->method('collectTotals')->willReturn($this->quoteMock);
$this->quoteRepositoryMock->expects($this->once())->method('save')->with($this->quoteMock);
$this->persistentSessionMock->expects($this->once())
@@ -229,7 +241,6 @@ public function testSetGuest()
$this->quoteMock->expects($this->once())->method('isVirtual')->willReturn(false);
$this->quoteMock->expects($this->once())->method('getItemsQty')->willReturn(1);
$extensionAttributes = $this->getMockBuilder(CartExtensionInterface::class)
- ->addMethods(['getShippingAssignments', 'setShippingAssignments'])
->getMockForAbstractClass();
$shippingAssignment = $this->createMock(ShippingAssignmentInterface::class);
$extensionAttributes->expects($this->once())
@@ -248,6 +259,11 @@ public function testSetGuest()
$this->quoteMock->expects($this->once())
->method('setExtensionAttributes')
->with($extensionAttributes);
+ $customerMock = $this->createMock(CustomerInterface::class);
+ $this->customerDataFactory->method('create')->willReturn($customerMock);
+ $this->quoteMock->expects($this->once())
+ ->method('setCustomer')
+ ->with($customerMock);
$this->model->setGuest(false);
}
diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php
index 3622fe66099a4..bb78447cf852f 100644
--- a/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php
+++ b/app/code/Magento/Persistent/Test/Unit/Observer/MakePersistentQuoteGuestObserverTest.php
@@ -1,6 +1,5 @@
actionMock = $this->createMock(Index::class);
@@ -67,7 +69,7 @@ protected function setUp(): void
$this->sessionHelperMock = $this->createMock(Session::class);
$this->helperMock = $this->createMock(Data::class);
$this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class);
- $this->quoteManagerMock = $this->createMock(QuoteManager::class);
+ $this->checkoutSession = $this->createMock(CheckoutSession::class);
$this->eventManagerMock =
$this->getMockBuilder(Event::class)
->addMethods(['getControllerAction'])
@@ -81,7 +83,7 @@ protected function setUp(): void
$this->sessionHelperMock,
$this->helperMock,
$this->customerSessionMock,
- $this->quoteManagerMock
+ $this->checkoutSession
);
}
@@ -94,7 +96,8 @@ public function testExecute()
$this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true);
$this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(false);
$this->helperMock->expects($this->never())->method('isShoppingCartPersist');
- $this->quoteManagerMock->expects($this->once())->method('setGuest')->with(true);
+ $this->checkoutSession->expects($this->once())->method('clearQuote')->willReturnSelf();
+ $this->checkoutSession->expects($this->once())->method('clearStorage')->willReturnSelf();
$this->model->execute($this->observerMock);
}
@@ -107,7 +110,8 @@ public function testExecuteWhenShoppingCartIsPersist()
$this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true);
$this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(true);
$this->helperMock->expects($this->once())->method('isShoppingCartPersist')->willReturn(true);
- $this->quoteManagerMock->expects($this->once())->method('setGuest')->with(true);
+ $this->checkoutSession->expects($this->once())->method('clearQuote')->willReturnSelf();
+ $this->checkoutSession->expects($this->once())->method('clearStorage')->willReturnSelf();
$this->model->execute($this->observerMock);
}
@@ -120,7 +124,8 @@ public function testExecuteWhenShoppingCartIsNotPersist()
$this->sessionHelperMock->expects($this->once())->method('isPersistent')->willReturn(true);
$this->customerSessionMock->expects($this->once())->method('isLoggedIn')->willReturn(true);
$this->helperMock->expects($this->once())->method('isShoppingCartPersist')->willReturn(false);
- $this->quoteManagerMock->expects($this->never())->method('setGuest');
+ $this->checkoutSession->expects($this->never())->method('clearQuote')->willReturnSelf();
+ $this->checkoutSession->expects($this->never())->method('clearStorage')->willReturnSelf();
$this->model->execute($this->observerMock);
}
}
diff --git a/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php b/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php
index 4adc806fed415..7bef8feaaacc5 100644
--- a/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php
+++ b/app/code/Magento/Persistent/Test/Unit/Observer/RemoveGuestPersistenceOnEmptyCartObserverTest.php
@@ -137,6 +137,13 @@ public function testExecuteWithEmptyCart()
->with($customerId)
->willReturn($quoteMock);
$quoteMock->expects($this->once())->method('getItemsCount')->willReturn($emptyCount);
+ $this->customerSessionMock->expects($this->once())
+ ->method('setCustomerId')
+ ->with(null)
+ ->willReturnSelf();
+ $this->customerSessionMock->expects($this->once())
+ ->method('setCustomerGroupId')
+ ->with(null);
$this->quoteManagerMock->expects($this->once())->method('setGuest');
$this->model->execute($this->observerMock);
@@ -160,6 +167,13 @@ public function testExecuteWithNonexistentCart()
->method('getActiveForCustomer')
->with($customerId)
->willThrowException($exception);
+ $this->customerSessionMock->expects($this->once())
+ ->method('setCustomerId')
+ ->with(null)
+ ->willReturnSelf();
+ $this->customerSessionMock->expects($this->once())
+ ->method('setCustomerGroupId')
+ ->with(null);
$this->quoteManagerMock->expects($this->once())->method('setGuest');
$this->model->execute($this->observerMock);
diff --git a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml
index eaebc7fdaf74a..fc17bc7f0f10a 100644
--- a/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml
+++ b/app/code/Magento/Store/Test/Mftf/Test/StorefrontAddStoreCodeInUrlTest.xml
@@ -21,6 +21,9 @@
+
+
+
diff --git a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php
index ef2df77e7daff..3600992011ed6 100644
--- a/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php
+++ b/app/code/Magento/Ui/Component/Form/Element/DataType/Date.php
@@ -111,7 +111,7 @@ public function getComponentName()
public function convertDate($date, $hour = 0, $minute = 0, $second = 0, $setUtcTimeZone = true)
{
try {
- $dateObj = $this->localeDate->date($date, $this->getLocale(), false);
+ $dateObj = $this->localeDate->date($date, $this->getLocale(), false, false);
$dateObj->setTime($hour, $minute, $second);
//convert store date to default date in UTC timezone without DST
if ($setUtcTimeZone) {
diff --git a/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php b/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php
new file mode 100644
index 0000000000000..4b430e7a71886
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/GroupedProduct/Model/Inventory/ParentItemProcessorTest.php
@@ -0,0 +1,59 @@
+objectManager = Bootstrap::getObjectManager();
+ }
+
+ /**
+ * Test stock status parent product if children are out of stock
+ *
+ * @magentoDataFixture Magento/GroupedProduct/_files/product_grouped_with_simple_out_of_stock.php
+ *
+ * @return void
+ */
+ public function testOutOfStockParentProduct(): void
+ {
+ $productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
+ /** @var Product $product */
+ $product = $productRepository->get('simple_100000001');
+ $product->setStockData(['qty' => 0, 'is_in_stock' => 0]);
+ $productRepository->save($product);
+ /** @var StockItemRepository $stockItemRepository */
+ $stockItemRepository = $this->objectManager->create(StockItemRepository::class);
+ /** @var StockRegistryInterface $stockRegistry */
+ $stockRegistry = $this->objectManager->create(StockRegistryInterface::class);
+ $stockItem = $stockRegistry->getStockItemBySku('grouped');
+ $stockItem = $stockItemRepository->get($stockItem->getItemId());
+
+ $this->assertEquals(false, $stockItem->getIsInStock());
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php
index 3aadad7e9ebec..de6501ee78986 100644
--- a/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php
+++ b/dev/tests/integration/testsuite/Magento/Quote/Model/Product/Plugin/UpdateQuoteItemsTest.php
@@ -9,6 +9,7 @@
use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\DB\Adapter\AdapterInterface;
+use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\Quote\Model\GetQuoteByReservedOrderId;
use PHPUnit\Framework\TestCase;
@@ -60,11 +61,13 @@ public function testMarkQuoteRecollectAfterChangeProductPrice(): void
$product->setPrice((float)$product->getPrice() + 10);
$this->productRepository->save($product);
+ /** @var QuoteResource $quoteResource */
+ $quoteResource = $quote->getResource();
/** @var AdapterInterface $connection */
- $connection = $quote->getResource()->getConnection();
+ $connection = $quoteResource->getConnection();
$select = $connection->select()
->from(
- $connection->getTableName('quote'),
+ $quoteResource->getTable('quote'),
['updated_at', 'trigger_recollect']
)->where(
"reserved_order_id = 'test_order_with_simple_product_without_address'"
diff --git a/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php
new file mode 100644
index 0000000000000..42a381535b8b9
--- /dev/null
+++ b/lib/internal/Magento/Framework/Stdlib/DateTime/Intl/DateFormatterFactory.php
@@ -0,0 +1,104 @@
+ [
+ \IntlDateFormatter::SHORT => 'd/MM/y',
+ ]
+ ];
+
+ /**
+ * Create Intl Date formatter
+ *
+ * The Intl Date formatter gives date formats by ICU standard.
+ * http://userguide.icu-project.org/formatparse/datetime
+ *
+ * @param string $locale
+ * @param int $dateStyle
+ * @param int $timeStyle
+ * @param string|null $timeZone
+ * @param bool $useFourDigitsForYear
+ * @return \IntlDateFormatter
+ */
+ public function create(
+ string $locale,
+ int $dateStyle,
+ int $timeStyle,
+ ?string $timeZone = null,
+ bool $useFourDigitsForYear = true
+ ): \IntlDateFormatter {
+ $formatter = new \IntlDateFormatter(
+ $locale,
+ $dateStyle,
+ $timeStyle,
+ $timeZone
+ );
+ /**
+ * Process custom date formats
+ */
+ $customDateFormat = $this->getCustomDateFormat($locale, $dateStyle, $timeStyle);
+ if ($customDateFormat !== null) {
+ $formatter->setPattern($customDateFormat);
+ } elseif ($dateStyle === \IntlDateFormatter::SHORT && $useFourDigitsForYear) {
+ /**
+ * Gives 4 places for year value in short style
+ */
+ $longYearPattern = $this->setFourYearPlaces((string)$formatter->getPattern());
+ $formatter->setPattern($longYearPattern);
+ }
+
+ return $formatter;
+ }
+
+ /**
+ * Get custom date format if it exists
+ *
+ * @param string $locale
+ * @param int $dateStyle
+ * @param int $timeStyle
+ * @return string
+ */
+ private function getCustomDateFormat(string $locale, int $dateStyle, int $timeStyle): ?string
+ {
+ $customDateFormat = null;
+ if ($dateStyle !== \IntlDateFormatter::NONE && isset(self::CUSTOM_DATE_FORMATS[$locale][$dateStyle])) {
+ $customDateFormat = self::CUSTOM_DATE_FORMATS[$locale][$dateStyle];
+ if ($timeStyle !== \IntlDateFormatter::NONE) {
+ $timeFormat = (new \IntlDateFormatter($locale, \IntlDateFormatter::NONE, $timeStyle))
+ ->getPattern();
+ $customDateFormat .= ' ' . $timeFormat;
+ }
+ }
+
+ return $customDateFormat;
+ }
+
+ /**
+ * Set 4 places for year value in format string
+ *
+ * @param string $format
+ * @return string
+ */
+ private function setFourYearPlaces(string $format): string
+ {
+ return preg_replace(
+ '/(?_scopeResolver = $scopeResolver;
$this->_localeResolver = $localeResolver;
@@ -87,6 +90,7 @@ public function __construct(
$this->_defaultTimezonePath = $defaultTimezonePath;
$this->_scopeConfig = $scopeConfig;
$this->_scopeType = $scopeType;
+ $this->dateFormatterFactory = $dateFormatterFactory;
}
/**
@@ -122,11 +126,15 @@ public function getConfigTimezone($scopeType = null, $scopeCode = null)
*/
public function getDateFormat($type = \IntlDateFormatter::SHORT)
{
- return (new \IntlDateFormatter(
- $this->_localeResolver->getLocale(),
- $type,
- \IntlDateFormatter::NONE
- ))->getPattern();
+ $formatter = $this->dateFormatterFactory->create(
+ (string)$this->_localeResolver->getLocale(),
+ (int)$type,
+ \IntlDateFormatter::NONE,
+ null,
+ false
+ );
+
+ return $formatter->getPattern();
}
/**
@@ -134,11 +142,13 @@ public function getDateFormat($type = \IntlDateFormatter::SHORT)
*/
public function getDateFormatWithLongYear()
{
- return preg_replace(
- '/(?getDateFormat()
+ $formatter = $this->dateFormatterFactory->create(
+ (string)$this->_localeResolver->getLocale(),
+ \IntlDateFormatter::SHORT,
+ \IntlDateFormatter::NONE
);
+
+ return $formatter->getPattern();
}
/**
@@ -146,11 +156,13 @@ public function getDateFormatWithLongYear()
*/
public function getTimeFormat($type = \IntlDateFormatter::SHORT)
{
- return (new \IntlDateFormatter(
- $this->_localeResolver->getLocale(),
+ $formatter = $this->dateFormatterFactory->create(
+ (string)$this->_localeResolver->getLocale(),
\IntlDateFormatter::NONE,
- $type
- ))->getPattern();
+ (int)$type
+ );
+
+ return $formatter->getPattern();
}
/**
@@ -166,10 +178,8 @@ public function getDateTimeFormat($type)
*/
public function date($date = null, $locale = null, $useTimezone = true, $includeTime = true)
{
- $locale = $locale ?: $this->_localeResolver->getLocale();
- $timezone = $useTimezone
- ? $this->getConfigTimezone()
- : date_default_timezone_get();
+ $locale = (string)($locale ?: $this->_localeResolver->getLocale());
+ $timezone = (string)($useTimezone ? $this->getConfigTimezone() : date_default_timezone_get());
switch (true) {
case (empty($date)):
@@ -179,9 +189,14 @@ public function date($date = null, $locale = null, $useTimezone = true, $include
case ($date instanceof \DateTimeImmutable):
return new \DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone());
case (!is_numeric($date)):
- $date = $this->appendTimeIfNeeded($date, $includeTime, $timezone, $locale);
- $date = $this->parseLocaleDate($date, $locale, $timezone, $includeTime)
- ?: (new \DateTime($date))->getTimestamp();
+ $date = $this->appendTimeIfNeeded((string)$date, (bool)$includeTime, $timezone, $locale);
+ $formatter = $this->dateFormatterFactory->create(
+ $locale,
+ \IntlDateFormatter::SHORT,
+ $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE,
+ $timezone
+ );
+ $date = $formatter->parse($date) ?: (new \DateTime($date))->getTimestamp();
break;
}
@@ -279,7 +294,6 @@ public function formatDateTime(
if (!($date instanceof \DateTimeInterface)) {
$date = new \DateTime($date);
}
-
if ($timezone === null) {
if ($date->getTimezone() == null || $date->getTimezone()->getName() == 'UTC'
|| $date->getTimezone()->getName() == '+00:00'
@@ -290,14 +304,20 @@ public function formatDateTime(
}
}
- $formatter = new \IntlDateFormatter(
- $locale ?: $this->_localeResolver->getLocale(),
- $dateType,
- $timeType,
- $timezone,
+ $formatter = $this->dateFormatterFactory->create(
+ (string)($locale ?: $this->_localeResolver->getLocale()),
+ (int)($dateType ?? \IntlDateFormatter::SHORT),
+ (int)($timeType ?? \IntlDateFormatter::SHORT),
null,
- $pattern
+ false
);
+ if ($timezone) {
+ $formatter->setTimeZone($timezone);
+ }
+ if ($pattern) {
+ $formatter->setPattern($pattern);
+ }
+
return $formatter->format($date);
}
@@ -338,11 +358,17 @@ public function convertConfigTimeToUtc($date, $format = 'Y-m-d H:i:s')
* @return string
* @throws LocalizedException
*/
- private function appendTimeIfNeeded($date, $includeTime, $timezone, $locale)
+ private function appendTimeIfNeeded(string $date, bool $includeTime, string $timezone, string $locale)
{
if ($includeTime && !preg_match('/\d{1}:\d{2}/', $date)) {
- $convertedDate = $this->parseLocaleDate($date, $locale, $timezone, false);
- if (!$convertedDate) {
+ $formatter = $this->dateFormatterFactory->create(
+ $locale,
+ \IntlDateFormatter::SHORT,
+ \IntlDateFormatter::NONE,
+ $timezone
+ );
+ $timestamp = $formatter->parse($date);
+ if (!$timestamp) {
throw new LocalizedException(
new Phrase(
'Could not append time to DateTime'
@@ -350,68 +376,15 @@ private function appendTimeIfNeeded($date, $includeTime, $timezone, $locale)
);
}
- $formatterWithHour = $this->getDateFormatter(
+ $formatterWithHour = $this->dateFormatterFactory->create(
$locale,
- $timezone,
- \IntlDateFormatter::MEDIUM,
- \IntlDateFormatter::SHORT
+ \IntlDateFormatter::SHORT,
+ \IntlDateFormatter::SHORT,
+ $timezone
);
- $date = $formatterWithHour->format($convertedDate);
- }
- return $date;
- }
-
- /**
- * Parse date by locale format through IntlDateFormatter
- *
- * @param string $date
- * @param string $locale
- * @param string $timeZone
- * @param bool $includeTime
- * @return int|null Timestamp of date
- */
- private function parseLocaleDate(string $date, string $locale, string $timeZone, bool $includeTime): ?int
- {
- $allowedStyles = [\IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT];
- $timeStyle = $includeTime ? \IntlDateFormatter::SHORT : \IntlDateFormatter::NONE;
-
- /**
- * Try to parse date with different styles
- */
- foreach ($allowedStyles as $style) {
- $formatter = $this->getDateFormatter($locale, $timeZone, $style, $timeStyle);
- $timeStamp = $formatter->parse($date);
- if ($timeStamp) {
- return $timeStamp;
- }
+ $date = $formatterWithHour->format($timestamp);
}
- return null;
- }
-
- /**
- * Get date formatter for locale
- *
- * @param string $locale
- * @param string $timeZone
- * @param int $style
- * @param int $timeStyle
- * @return \IntlDateFormatter
- */
- private function getDateFormatter(string $locale, string $timeZone, int $style, int $timeStyle): \IntlDateFormatter
- {
- $cacheKey = "{$locale}_{$timeZone}_{$style}_{$timeStyle}";
- if (isset($this->dateFormatterCache[$cacheKey])) {
- return $this->dateFormatterCache[$cacheKey];
- }
-
- $this->dateFormatterCache[$cacheKey] = new \IntlDateFormatter(
- $locale,
- $style,
- $timeStyle,
- new \DateTimeZone($timeZone)
- );
-
- return $this->dateFormatterCache[$cacheKey];
+ return $date;
}
}
diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php
index 2e8110316ec29..38a62f006adbc 100644
--- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php
+++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/DateTime/TimezoneTest.php
@@ -12,6 +12,7 @@
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Locale\ResolverInterface;
use Magento\Framework\Stdlib\DateTime;
+use Magento\Framework\Stdlib\DateTime\Intl\DateFormatterFactory;
use Magento\Framework\Stdlib\DateTime\Timezone;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\MockObject\MockObject;
@@ -90,22 +91,23 @@ protected function tearDown(): void
* @param string $date
* @param string $locale
* @param bool $includeTime
- * @param int $expectedTimestamp
+ * @param int|string $expectedTime
+ * @param string|null $timeZone
* @dataProvider dateIncludeTimeDataProvider
*/
- public function testDateIncludeTime($date, $locale, $includeTime, $expectedTimestamp)
+ public function testDateIncludeTime($date, $locale, $includeTime, $expectedTime, $timeZone = 'America/Chicago')
{
- $this->scopeConfig->method('getValue')->willReturn('America/Chicago');
- /** @var Timezone $timezone */
- $timezone = $this->objectManager->getObject(Timezone::class, ['scopeConfig' => $this->scopeConfig]);
+ if ($timeZone !== null) {
+ $this->scopeConfig->method('getValue')->willReturn($timeZone);
+ }
/** @var \DateTime $dateTime */
- $dateTime = $timezone->date($date, $locale, true, $includeTime);
- if (is_numeric($expectedTimestamp)) {
- $this->assertEquals($expectedTimestamp, $dateTime->getTimestamp());
+ $dateTime = $this->getTimezone()->date($date, $locale, $timeZone !== null, $includeTime);
+ if (is_numeric($expectedTime)) {
+ $this->assertEquals($expectedTime, $dateTime->getTimestamp());
} else {
$format = $includeTime ? DateTime::DATETIME_PHP_FORMAT : DateTime::DATE_PHP_FORMAT;
- $this->assertEquals($expectedTimestamp, date($format, $dateTime->getTimestamp()));
+ $this->assertEquals($expectedTime, date($format, $dateTime->getTimestamp()));
}
}
@@ -158,16 +160,30 @@ public function dateIncludeTimeDataProvider(): array
1635570000 // expected timestamp
],
'Parse Saudi Arabia date without time' => [
- '31/8/2020 02020',
+ '4/09/2020',
'ar_SA',
false,
- '2020-08-31'
+ '2020-09-04'
+ ],
+ 'Parse Saudi Arabia date with time' => [
+ '4/09/2020 10:10 مساء',
+ 'ar_SA',
+ true,
+ '2020-09-04 22:10:00',
+ null
+ ],
+ 'Parse Saudi Arabia date with zero time' => [
+ '4/09/2020',
+ 'ar_SA',
+ true,
+ '2020-09-04 00:00:00',
+ null
],
'Parse date in short style with long year 1999' => [
- '9/11/1999',
+ '8/11/1999',
'en_US',
false,
- '1999-09-11'
+ '1999-08-11'
],
'Parse date in short style with long year 2099' => [
'9/2/2099',
@@ -175,6 +191,59 @@ public function dateIncludeTimeDataProvider(): array
false,
'2099-09-02'
],
+ 'Parse date in short style with short year 1999' => [
+ '8/11/99',
+ 'en_US',
+ false,
+ '1999-08-11'
+ ],
+ ];
+ }
+
+ /**
+ * @param string $locale
+ * @param int $style
+ * @param string $expectedFormat
+ * @dataProvider getDatetimeFormatDataProvider
+ */
+ public function testGetDatetimeFormat(string $locale, int $style, string $expectedFormat): void
+ {
+ /** @var Timezone $timezone */
+ $this->localeResolver->method('getLocale')->willReturn($locale);
+ $this->assertEquals($expectedFormat, $this->getTimezone()->getDateTimeFormat($style));
+ }
+
+ /**
+ * @return array
+ */
+ public function getDatetimeFormatDataProvider(): array
+ {
+ return [
+ ['en_US', \IntlDateFormatter::SHORT, 'M/d/yy h:mm a'],
+ ['ar_SA', \IntlDateFormatter::SHORT, 'd/MM/y h:mm a']
+ ];
+ }
+
+ /**
+ * @param string $locale
+ * @param int $style
+ * @param string $expectedFormat
+ * @dataProvider getDateFormatWithLongYearDataProvider
+ */
+ public function testGetDateFormatWithLongYear(string $locale, string $expectedFormat): void
+ {
+ /** @var Timezone $timezone */
+ $this->localeResolver->method('getLocale')->willReturn($locale);
+ $this->assertEquals($expectedFormat, $this->getTimezone()->getDateFormatWithLongYear());
+ }
+
+ /**
+ * @return array
+ */
+ public function getDateFormatWithLongYearDataProvider(): array
+ {
+ return [
+ ['en_US', 'M/d/y'],
];
}
@@ -320,7 +389,8 @@ private function getTimezone()
$this->createMock(DateTime::class),
$this->scopeConfig,
$this->scopeType,
- $this->defaultTimezonePath
+ $this->defaultTimezonePath,
+ new DateFormatterFactory()
);
}