Skip to content

Commit 4b67412

Browse files
authored
Merge branch '2.4-develop' into ref-AdminDashboardWithChartsTest
2 parents b5ec75c + 30301a5 commit 4b67412

File tree

72 files changed

+2751
-292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+2751
-292
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AwsS3AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest" extends="AdminImportSimpleAndConfigurableProductsWithAssignedImagesTest">
12+
<annotations>
13+
<features value="AwsS3"/>
14+
<stories value="Import Products"/>
15+
<title value="S3 - Import Configurable Product With Simple Child Products With Images"/>
16+
<description value="Imports a .csv file containing a configurable product with 3 child simple products that
17+
have images. Verifies that products are imported successfully and that the images are attached to the
18+
products as expected."/>
19+
<severity value="MAJOR"/>
20+
<group value="importExport"/>
21+
<group value="remote_storage_aws_s3"/>
22+
<skip>
23+
<issueId value="MC-39280"/>
24+
</skip>
25+
</annotations>
26+
27+
<before>
28+
<!-- Enable AWS S3 Remote Storage -->
29+
<magentoCLI command="setup:config:set {{RemoteStorageAwsS3ConfigData.enable_options}}" stepKey="enableRemoteStorage"/>
30+
</before>
31+
32+
<after>
33+
<!-- Disable AWS S3 Remote Storage -->
34+
<magentoCLI command="setup:config:set {{RemoteStorageAwsS3ConfigData.disable_options}}" stepKey="disableRemoteStorage"/>
35+
</after>
36+
</test>
37+
</tests>

app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,12 @@ public function addWebsiteFilter($websites = null)
916916
}
917917

918918
$this->_productLimitationFilters['website_ids'] = $websites;
919-
$this->_applyProductLimitations();
919+
920+
if ($this->getStoreId() == Store::DEFAULT_STORE_ID) {
921+
$this->_productLimitationJoinWebsite();
922+
} else {
923+
$this->_applyProductLimitations();
924+
}
920925

921926
return $this;
922927
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
-->
7+
8+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
9+
<actionGroup name="StorefrontNavigateToCategoryUrlActionGroup">
10+
<annotations>
11+
<description>Goes to the Storefront Category page for the provided Category URL.</description>
12+
</annotations>
13+
<arguments>
14+
<argument name="categoryUrl" type="string"/>
15+
</arguments>
16+
<amOnPage url="{{StorefrontCategoryPage.url(categoryUrl)}}" stepKey="goToStorefrontCategoryPage"/>
17+
</actionGroup>
18+
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontProductPageSelectDropDownOptionValueActionGroup.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818
</arguments>
1919

2020
<selectOption selector="{{StorefrontProductInfoMainSection.productOptionSelect(attributeLabel)}}" userInput="{{optionLabel}}" stepKey="fillDropDownAttributeOption"/>
21+
<waitForPageLoad stepKey="waitForPageLoad"/>
2122
</actionGroup>
2223
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductImagesSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<element name="imageFileUpload" type="input" selector="#fileupload"/>
1414
<element name="imageUploadButton" type="button" selector="div.image div.fileinput-button"/>
1515
<element name="imageFile" type="text" selector="//*[@id='media_gallery_content']//img[contains(@src, '{{url}}')]" parameterized="true"/>
16+
<element name="imageElement" type="text" selector="#media_gallery_content img"/>
1617
<element name="removeImageButton" type="button" selector=".action-remove"/>
1718
<element name="removeImageButtonForExactImage" type="button" selector="[id='media_gallery_content'] img[src*='{{imageName}}'] + div[class='actions'] button[class='action-remove']" parameterized="true"/>
1819
<element name="modalOkBtn" type="button" selector="button.action-primary.action-accept"/>

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
3939
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
4040
use Magento\Framework\Validator\UniversalFactory;
41+
use Magento\Store\Model\Store;
4142
use Magento\Store\Model\StoreManagerInterface;
4243
use PHPUnit\Framework\MockObject\MockObject;
4344
use PHPUnit\Framework\TestCase;
@@ -93,6 +94,11 @@ class CollectionTest extends TestCase
9394
*/
9495
private $storeManager;
9596

97+
/**
98+
* @var ProductLimitation|MockObject
99+
*/
100+
private $productLimitationMock;
101+
96102
/**
97103
* @var EntityFactory|MockObject
98104
*/
@@ -192,7 +198,7 @@ protected function setUp(): void
192198
$this->entityMock->expects($this->any())->method('getTable')->willReturnArgument(0);
193199
$this->connectionMock->expects($this->atLeastOnce())->method('select')->willReturn($this->selectMock);
194200

195-
$productLimitationMock = $this->createMock(
201+
$this->productLimitationMock = $this->createMock(
196202
ProductLimitation::class
197203
);
198204
$productLimitationFactoryMock = $this->getMockBuilder(
@@ -201,7 +207,7 @@ protected function setUp(): void
201207
->setMethods(['create'])->getMock();
202208

203209
$productLimitationFactoryMock->method('create')
204-
->willReturn($productLimitationMock);
210+
->willReturn($this->productLimitationMock);
205211
$this->collection = $this->objectManager->getObject(
206212
Collection::class,
207213
[
@@ -432,4 +438,44 @@ public function testGetNewEmptyItem()
432438
$secondItem = $this->collection->getNewEmptyItem();
433439
$this->assertEquals($firstItem, $secondItem);
434440
}
441+
442+
/**
443+
* Test to add website filter in admin area
444+
*/
445+
public function testAddWebsiteFilterOnAdminStore(): void
446+
{
447+
$websiteIds = [2];
448+
$websiteTable = 'catalog_product_website';
449+
$joinCondition = 'join condition';
450+
$this->productLimitationMock->expects($this->atLeastOnce())
451+
->method('offsetSet')
452+
->with('website_ids', $websiteIds);
453+
$this->productLimitationMock->method('offsetExists')
454+
->with('website_ids')
455+
->willReturn(true);
456+
$this->productLimitationMock->method('offsetGet')
457+
->with('website_ids')
458+
->willReturn($websiteIds);
459+
$this->connectionMock->expects($this->once())
460+
->method('quoteInto')
461+
->with('product_website.website_id IN(?)', $websiteIds, 'int')
462+
->willReturn($joinCondition);
463+
$this->selectMock->method('getPart')->with(Select::FROM)->willReturn([]);
464+
/** @var AbstractEntity|MockObject $eavEntity */
465+
$eavEntity = $this->createMock(AbstractEntity::class);
466+
$eavEntity->method('getTable')
467+
->with('catalog_product_website')
468+
->willReturn($websiteTable);
469+
$this->selectMock->expects($this->once())
470+
->method('join')
471+
->with(
472+
['product_website' => $websiteTable],
473+
'product_website.product_id = e.entity_id AND ' . $joinCondition,
474+
[]
475+
);
476+
477+
$this->collection->setEntity($eavEntity);
478+
$this->collection->setStoreId(Store::DEFAULT_STORE_ID);
479+
$this->collection->addWebsiteFilter($websiteIds);
480+
}
435481
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Deferred/Product.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private function fetch() : array
132132
$this->searchCriteriaBuilder->create(),
133133
$this->attributeCodes,
134134
false,
135-
true
135+
false
136136
);
137137

138138
/** @var \Magento\Catalog\Model\Product $product */

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/DataProvider/Product.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public function getList(
8989

9090
$this->collectionPreProcessor->process($collection, $searchCriteria, $attributes, $context);
9191

92-
if (!$isChildSearch) {
92+
if ($isChildSearch) {
9393
$visibilityIds = $isSearch
9494
? $this->visibility->getVisibleInSearchIds()
9595
: $this->visibility->getVisibleInCatalogIds();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ private function deleteProductsLinks(
220220
if (!empty($linksToDelete) && Import::BEHAVIOR_APPEND === $importEntity->getBehavior()) {
221221
foreach ($linksToDelete as $linkTypeId => $productIds) {
222222
if (!empty($productIds)) {
223-
$whereLinkId = $importEntity->getConnection()->quoteInto('link_type_id', $linkTypeId);
223+
$whereLinkId = $importEntity->getConnection()->quoteInto('link_type_id = ?', $linkTypeId);
224224
$whereProductId = $importEntity->getConnection()->quoteInto(
225225
'product_id IN (?)',
226226
array_unique($productIds)

app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9-
use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper;
109
use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher;
10+
use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper;
1111
use Magento\CatalogRule\Model\Rule;
1212
use Magento\Framework\App\ResourceConnection;
1313
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
@@ -18,6 +18,8 @@
1818
*/
1919
class ReindexRuleProduct
2020
{
21+
private const ADMIN_WEBSITE_ID = 0;
22+
2123
/**
2224
* @var ResourceConnection
2325
*/
@@ -38,22 +40,30 @@ class ReindexRuleProduct
3840
*/
3941
private $localeDate;
4042

43+
/**
44+
* @var bool
45+
*/
46+
private $useWebsiteTimezone;
47+
4148
/**
4249
* @param ResourceConnection $resource
4350
* @param ActiveTableSwitcher $activeTableSwitcher
4451
* @param TableSwapper $tableSwapper
4552
* @param TimezoneInterface $localeDate
53+
* @param bool $useWebsiteTimezone
4654
*/
4755
public function __construct(
4856
ResourceConnection $resource,
4957
ActiveTableSwitcher $activeTableSwitcher,
5058
TableSwapper $tableSwapper,
51-
TimezoneInterface $localeDate
59+
TimezoneInterface $localeDate,
60+
bool $useWebsiteTimezone = true
5261
) {
5362
$this->resource = $resource;
5463
$this->activeTableSwitcher = $activeTableSwitcher;
5564
$this->tableSwapper = $tableSwapper;
5665
$this->localeDate = $localeDate;
66+
$this->useWebsiteTimezone = $useWebsiteTimezone;
5767
}
5868

5969
/**
@@ -95,18 +105,18 @@ public function execute(Rule $rule, $batchCount, $useAdditionalTable = false)
95105
$actionOperator = $rule->getSimpleAction();
96106
$actionAmount = $rule->getDiscountAmount();
97107
$actionStop = $rule->getStopRulesProcessing();
108+
$fromTimeInAdminTz = $this->parseDateByWebsiteTz((string)$rule->getFromDate(), self::ADMIN_WEBSITE_ID);
109+
$toTimeInAdminTz = $this->parseDateByWebsiteTz((string)$rule->getToDate(), self::ADMIN_WEBSITE_ID);
98110

99111
$rows = [];
100112
foreach ($websiteIds as $websiteId) {
101-
$scopeTz = new \DateTimeZone(
102-
$this->localeDate->getConfigTimezone(ScopeInterface::SCOPE_WEBSITE, $websiteId)
103-
);
104-
$fromTime = $rule->getFromDate()
105-
? (new \DateTime($rule->getFromDate(), $scopeTz))->getTimestamp()
106-
: 0;
107-
$toTime = $rule->getToDate()
108-
? (new \DateTime($rule->getToDate(), $scopeTz))->getTimestamp() + IndexBuilder::SECONDS_IN_DAY - 1
109-
: 0;
113+
$fromTime = $this->useWebsiteTimezone
114+
? $this->parseDateByWebsiteTz((string)$rule->getFromDate(), (int)$websiteId)
115+
: $fromTimeInAdminTz;
116+
$toTime = $this->useWebsiteTimezone
117+
? $this->parseDateByWebsiteTz((string)$rule->getToDate(), (int)$websiteId)
118+
+ ($rule->getToDate() ? IndexBuilder::SECONDS_IN_DAY - 1 : 0)
119+
: $toTimeInAdminTz;
110120

111121
foreach ($productIds as $productId => $validationByWebsite) {
112122
if (empty($validationByWebsite[$websiteId])) {
@@ -140,4 +150,23 @@ public function execute(Rule $rule, $batchCount, $useAdditionalTable = false)
140150

141151
return true;
142152
}
153+
154+
/**
155+
* Parse date value by the timezone of the website
156+
*
157+
* @param string $date
158+
* @param int $websiteId
159+
* @return int
160+
*/
161+
private function parseDateByWebsiteTz(string $date, int $websiteId): int
162+
{
163+
if (empty($date)) {
164+
return 0;
165+
}
166+
167+
$websiteTz = $this->localeDate->getConfigTimezone(ScopeInterface::SCOPE_WEBSITE, $websiteId);
168+
$dateTime = new \DateTime($date, new \DateTimeZone($websiteTz));
169+
170+
return $dateTime->getTimestamp();
171+
}
143172
}

0 commit comments

Comments
 (0)