Skip to content

Commit 4aa21e0

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into AC10721
2 parents 15f6f3f + 3a7c4d1 commit 4aa21e0

File tree

14 files changed

+365
-29
lines changed

14 files changed

+365
-29
lines changed

app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,9 +1912,7 @@ protected function _saveTitles(array $titles)
19121912
if (!isset($existingOptionIds[$optionId]) && count($storeInfo) > 0) {
19131913
$storeInfo = [Store::DEFAULT_STORE_ID => reset($storeInfo)] + $storeInfo;
19141914
}
1915-
//for use default
1916-
$uniqStoreInfo = array_unique($storeInfo);
1917-
foreach ($uniqStoreInfo as $storeId => $title) {
1915+
foreach ($storeInfo as $storeId => $title) {
19181916
$titleRows[] = ['option_id' => $optionId, 'store_id' => $storeId, 'title' => $title];
19191917
}
19201918
}

app/code/Magento/Sales/Plugin/Model/ResourceModel/Order/OrderGridCollectionFilter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function aroundAddFieldToFilter(
5555
}
5656
}
5757

58-
$fieldName = $subject->getConnection()->quoteIdentifier($field);
58+
$fieldName = $subject->getConnection()->quoteIdentifier('main_table.' . $field);
5959
$condition = $subject->getConnection()->prepareSqlCondition($fieldName, $condition);
6060
$subject->getSelect()->where($condition, null, Select::TYPE_CONDITION);
6161

app/code/Magento/Sales/etc/adminhtml/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
</arguments>
5050
<plugin name="orderGridExportFilterColumnPlugin" type="Magento\Sales\Plugin\Model\Export\OrderGridExportFilterColumn"/>
5151
</type>
52-
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult">
52+
<type name="Magento\Sales\Model\ResourceModel\Order\Grid\Collection">
5353
<plugin name="orderGridCollectionFilterPlugin" type="Magento\Sales\Plugin\Model\ResourceModel\Order\OrderGridCollectionFilter"/>
5454
</type>
5555
<type name="Magento\Sales\Block\Adminhtml\Order\Create\Search\Grid\DataProvider\ProductCollection">

app/code/Magento/Wishlist/CustomerData/Wishlist.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Magento\Catalog\Model\Product\Image\NotLoadInfoImageException;
99
use Magento\Customer\CustomerData\SectionSourceInterface;
1010
use Magento\Framework\App\ObjectManager;
11+
use Magento\Store\Model\StoreManagerInterface;
1112

1213
/**
1314
* Wishlist section
@@ -17,7 +18,7 @@ class Wishlist implements SectionSourceInterface
1718
/**
1819
* @var string
1920
*/
20-
const SIDEBAR_ITEMS_NUMBER = 3;
21+
public const SIDEBAR_ITEMS_NUMBER = 3;
2122

2223
/**
2324
* @var \Magento\Wishlist\Helper\Data
@@ -44,19 +45,26 @@ class Wishlist implements SectionSourceInterface
4445
*/
4546
private $itemResolver;
4647

48+
/**
49+
* @var StoreManagerInterface
50+
*/
51+
private $storeManager;
52+
4753
/**
4854
* @param \Magento\Wishlist\Helper\Data $wishlistHelper
4955
* @param \Magento\Wishlist\Block\Customer\Sidebar $block
5056
* @param \Magento\Catalog\Helper\ImageFactory $imageHelperFactory
5157
* @param \Magento\Framework\App\ViewInterface $view
5258
* @param \Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface|null $itemResolver
59+
* @param StoreManagerInterface|null $storeManager
5360
*/
5461
public function __construct(
5562
\Magento\Wishlist\Helper\Data $wishlistHelper,
5663
\Magento\Wishlist\Block\Customer\Sidebar $block,
5764
\Magento\Catalog\Helper\ImageFactory $imageHelperFactory,
5865
\Magento\Framework\App\ViewInterface $view,
59-
\Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface $itemResolver = null
66+
\Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface $itemResolver = null,
67+
StoreManagerInterface $storeManager = null
6068
) {
6169
$this->wishlistHelper = $wishlistHelper;
6270
$this->imageHelperFactory = $imageHelperFactory;
@@ -65,6 +73,7 @@ public function __construct(
6573
$this->itemResolver = $itemResolver ?: ObjectManager::getInstance()->get(
6674
\Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface::class
6775
);
76+
$this->storeManager = $storeManager ?? ObjectManager::getInstance()->get(StoreManagerInterface::class);
6877
}
6978

7079
/**
@@ -76,6 +85,7 @@ public function getSectionData()
7685
return [
7786
'counter' => $counter,
7887
'items' => $counter ? $this->getItems() : [],
88+
'websiteId' => $this->storeManager->getWebsite()->getId()
7989
];
8090
}
8191

app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Magento\Catalog\Model\Product\Type\AbstractType;
1616
use Magento\Framework\App\ViewInterface;
1717
use Magento\Framework\Pricing\Render;
18+
use Magento\Store\Model\StoreManagerInterface;
1819
use Magento\Wishlist\Block\Customer\Sidebar;
1920
use Magento\Wishlist\CustomerData\Wishlist;
2021
use Magento\Wishlist\CustomerData\Wishlist as WishlistModel;
@@ -23,6 +24,7 @@
2324
use Magento\Wishlist\Model\ResourceModel\Item\Collection;
2425
use PHPUnit\Framework\MockObject\MockObject;
2526
use PHPUnit\Framework\TestCase;
27+
use Magento\Store\Api\Data\WebsiteInterface;
2628

2729
/**
2830
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -47,6 +49,15 @@ class WishlistTest extends TestCase
4749
/** @var ImageBuilder|MockObject */
4850
private $itemResolver;
4951

52+
/** @var StoreManagerInterface|MockObject */
53+
private $storeManagerMock;
54+
55+
/** @var WebsiteInterface|MockObject */
56+
private $websiteMock;
57+
58+
/** @var ImageFactory|MockObject */
59+
private $imageHelperFactory;
60+
5061
protected function setUp(): void
5162
{
5263
$this->wishlistHelperMock = $this->getMockBuilder(Data::class)
@@ -61,24 +72,34 @@ protected function setUp(): void
6172
$this->catalogImageHelperMock = $this->getMockBuilder(Image::class)
6273
->disableOriginalConstructor()
6374
->getMock();
64-
$imageHelperFactory = $this->getMockBuilder(ImageFactory::class)
75+
$this->imageHelperFactory = $this->getMockBuilder(ImageFactory::class)
6576
->disableOriginalConstructor()
6677
->onlyMethods(['create'])
6778
->getMock();
68-
$imageHelperFactory->expects($this->any())
79+
$this->imageHelperFactory->expects($this->any())
6980
->method('create')
7081
->willReturn($this->catalogImageHelperMock);
7182

7283
$this->itemResolver = $this->createMock(
7384
ItemResolverInterface::class
7485
);
7586

87+
$this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
88+
->disableOriginalConstructor()
89+
->getMockForAbstractClass();
90+
91+
$this->websiteMock = $this->getMockBuilder(WebsiteInterface::class)
92+
->onlyMethods(['getId',])
93+
->disableOriginalConstructor()
94+
->getMockForAbstractClass();
95+
7696
$this->model = new Wishlist(
7797
$this->wishlistHelperMock,
7898
$this->sidebarMock,
79-
$imageHelperFactory,
99+
$this->imageHelperFactory,
80100
$this->viewMock,
81-
$this->itemResolver
101+
$this->itemResolver,
102+
$this->storeManagerMock
82103
);
83104
}
84105

@@ -102,6 +123,14 @@ public function testGetSectionData()
102123
$itemAddParams = ['add_params'];
103124
$itemRemoveParams = ['remove_params'];
104125

126+
$this->storeManagerMock->expects($this->once())
127+
->method('getWebsite')
128+
->willReturn($this->websiteMock);
129+
130+
$this->websiteMock->expects($this->once())
131+
->method('getId')
132+
->willReturn(1);
133+
105134
$result = [
106135
'counter' => __('1 item'),
107136
'items' => [
@@ -124,6 +153,7 @@ public function testGetSectionData()
124153
'delete_item_params' => $itemRemoveParams,
125154
],
126155
],
156+
'websiteId' => 1
127157
];
128158

129159
/** @var Item|MockObject $itemMock */
@@ -288,6 +318,14 @@ public function testGetSectionDataWithTwoItems()
288318
->getMock();
289319
$items = [$itemMock, $itemMock];
290320

321+
$this->storeManagerMock->expects($this->once())
322+
->method('getWebsite')
323+
->willReturn($this->websiteMock);
324+
325+
$this->websiteMock->expects($this->once())
326+
->method('getId')
327+
->willReturn(1);
328+
291329
$result = [
292330
'counter' => __('%1 items', count($items)),
293331
'items' => [
@@ -328,6 +366,7 @@ public function testGetSectionDataWithTwoItems()
328366
'delete_item_params' => $itemRemoveParams,
329367
],
330368
],
369+
'websiteId' => 1
331370
];
332371

333372
$this->wishlistHelperMock->expects($this->once())
@@ -465,9 +504,18 @@ public function testGetSectionDataWithoutItems()
465504
{
466505
$items = [];
467506

507+
$this->storeManagerMock->expects($this->once())
508+
->method('getWebsite')
509+
->willReturn($this->websiteMock);
510+
511+
$this->websiteMock->expects($this->once())
512+
->method('getId')
513+
->willReturn(null);
514+
468515
$result = [
469516
'counter' => null,
470517
'items' => [],
518+
'websiteId' =>null
471519
];
472520

473521
$this->wishlistHelperMock->expects($this->once())

app/code/Magento/Wishlist/view/frontend/web/js/view/wishlist.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,32 @@
55

66
define([
77
'uiComponent',
8-
'Magento_Customer/js/customer-data'
9-
], function (Component, customerData) {
8+
'Magento_Customer/js/customer-data',
9+
'underscore'
10+
], function (Component, customerData, _) {
1011
'use strict';
1112

13+
var wishlistReloaded = false;
14+
1215
return Component.extend({
1316
/** @inheritdoc */
1417
initialize: function () {
1518
this._super();
16-
1719
this.wishlist = customerData.get('wishlist');
20+
if (!wishlistReloaded
21+
&& !_.isEmpty(this.wishlist())
22+
// Expired section names are reloaded on page load.
23+
&& _.indexOf(customerData.getExpiredSectionNames(), 'wishlist') === -1
24+
&& window.checkout
25+
&& window.checkout.websiteId
26+
&& window.checkout.websiteId !== this.wishlist().websiteId
27+
) {
28+
//set count to 0 to prevent "wishlist" blocks and count to show with wrong count and items
29+
this.wishlist().counter = 0;
30+
customerData.invalidate(['wishlist']);
31+
customerData.reload(['wishlist'], false);
32+
wishlistReloaded = true;
33+
}
1834
}
1935
});
2036
});

dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest/ProductOptionsTest.php

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313
use Magento\Catalog\Helper\Data as CatalogConfig;
1414
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
1515
use Magento\CatalogImportExport\Model\Import\ProductTestBase;
16+
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Exception\NoSuchEntityException;
18+
use Magento\Framework\Exception\StateException;
1619
use Magento\ImportExport\Helper\Data as ImportExportConfig;
1720
use Magento\Store\Model\ScopeInterface;
1821
use Magento\Store\Model\StoreManagerInterface;
1922
use Magento\Store\Test\Fixture\Store as StoreFixture;
2023
use Magento\TestFramework\Fixture\AppIsolation;
2124
use Magento\TestFramework\Fixture\Config;
2225
use Magento\TestFramework\Fixture\DataFixture;
26+
use Magento\TestFramework\Helper\Bootstrap;
2327

2428
/**
2529
* Integration test for \Magento\CatalogImportExport\Model\Import\Product class.
@@ -90,7 +94,7 @@ public function testSaveCustomOptions(string $importFile, string $sku, int $expe
9094
$importModel->importData();
9195

9296
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
93-
$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
97+
$productRepository = Bootstrap::getObjectManager()->create(
9498
\Magento\Catalog\Api\ProductRepositoryInterface::class
9599
);
96100
$product = $productRepository->get($sku);
@@ -187,17 +191,17 @@ public function testSaveCustomOptionsWithMultipleStoreViews(
187191
array $expected
188192
) {
189193
$expected = $this->getFullExpectedOptions($expected);
190-
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
194+
$objectManager = Bootstrap::getObjectManager();
191195
/** @var StoreManagerInterface $storeManager */
192196
$storeManager = $objectManager->get(StoreManagerInterface::class);
193197
$pathToFile = __DIR__ . '/../_files/' . $importFile;
194198
$importModel = $this->createImportModel($pathToFile);
195199
$errors = $importModel->validateData();
196200
$this->assertTrue($errors->getErrorsCount() == 0, 'Import File Validation Failed');
197201
$importModel->importData();
198-
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
202+
/** @var ProductRepositoryInterface $productRepository */
199203
$productRepository = $objectManager->get(
200-
\Magento\Catalog\Api\ProductRepositoryInterface::class
204+
ProductRepositoryInterface::class
201205
);
202206
$actual = [];
203207
foreach ($expected as $sku => $storesData) {
@@ -982,9 +986,9 @@ public function testImportCustomOptions(string $importFile, string $sku1, string
982986
$this->assertTrue($errors->getErrorsCount() == 0);
983987
$importModel->importData();
984988

985-
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
986-
$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
987-
\Magento\Catalog\Api\ProductRepositoryInterface::class
989+
/** @var ProductRepositoryInterface $productRepository */
990+
$productRepository = Bootstrap::getObjectManager()->create(
991+
ProductRepositoryInterface::class
988992
);
989993
$product1 = $productRepository->get($sku1);
990994

@@ -1025,4 +1029,64 @@ public function getCustomOptionDataProvider(): array
10251029
],
10261030
];
10271031
}
1032+
1033+
/**
1034+
* Tests import product custom options with multiple uploads.
1035+
*
1036+
* @dataProvider getProductCustomOptionDataProvider
1037+
* @param string $importFile
1038+
* @param string $sku
1039+
* @param int $uploadCount
1040+
* @throws LocalizedException
1041+
* @throws NoSuchEntityException
1042+
* @throws StateException
1043+
*/
1044+
public function testImportProductCustomOptionsOnMultipleUploads(
1045+
string $importFile,
1046+
string $sku,
1047+
int $uploadCount
1048+
): void {
1049+
$pathToFile = __DIR__ . '/../_files/' . $importFile;
1050+
1051+
for ($count = 0; $count < $uploadCount; $count++) {
1052+
$productImportModel = $this->createImportModel($pathToFile);
1053+
$errors = $productImportModel->validateData();
1054+
$this->assertTrue($errors->getErrorsCount() == 0);
1055+
$productImportModel->importData();
1056+
}
1057+
1058+
/** @var ProductRepositoryInterface $productRepository */
1059+
$productRepository = Bootstrap::getObjectManager()->create(
1060+
ProductRepositoryInterface::class
1061+
);
1062+
$product = $productRepository->get($sku);
1063+
1064+
$this->assertInstanceOf(\Magento\Catalog\Model\Product::class, $product);
1065+
$options = $product->getOptionInstance()->getProductOptions($product);
1066+
1067+
$expectedData = $this->getExpectedOptionsData($pathToFile, 'default');
1068+
$expectedOptions = $expectedData['options'];
1069+
1070+
$this->assertCount(count($expectedOptions), $options);
1071+
1072+
// Cleanup imported products
1073+
try {
1074+
$this->productRepository->delete($product);
1075+
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
1076+
}
1077+
}
1078+
1079+
/**
1080+
* @return array
1081+
*/
1082+
public function getProductCustomOptionDataProvider(): array
1083+
{
1084+
return [
1085+
[
1086+
'importFile' => 'product_with_custom_options_and_multiple_uploads.csv',
1087+
'sku' => 'p1',
1088+
'uploadCount' => 2,
1089+
],
1090+
];
1091+
}
10281092
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
sku,store_view_code,attribute_set_code,product_type,custom_options
2+
p1,default,Default,simple,"name=Option One,type=multiple,required=0,price=2.000000,sku=1,max_characters=0,file_extension=,image_size_x=0,image_size_y=0,price_type=fixed,option_title=One|name=Option One,type=multiple,required=0,price=2.000000,sku=2,max_characters=0,file_extension=,image_size_x=0,image_size_y=0,price_type=fixed,option_title=Two|name=Option Two,type=multiple,required=0,price=3.000000,sku=3,max_characters=0,file_extension=,image_size_x=0,image_size_y=0,price_type=fixed,option_title=Three|name=Option Two,type=multiple,required=0,price=4.000000,sku=4,max_characters=0,file_extension=,image_size_x=0,image_size_y=0,price_type=fixed,option_title=Four"

0 commit comments

Comments
 (0)