Skip to content

Commit 301ad68

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into Hammer_Bugfix_Delivery_02022022
2 parents fbbbba0 + 1a0a0a6 commit 301ad68

File tree

65 files changed

+4657
-454
lines changed

Some content is hidden

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

65 files changed

+4657
-454
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Eav/Decimal.php

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
namespace Magento\Catalog\Model\ResourceModel\Product\Indexer\Eav;
77

88
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Framework\DB\Select;
10+
use Magento\Store\Model\Store;
11+
use Zend_Db;
912

1013
/**
1114
* Catalog Product Eav Decimal Attributes Indexer resource model
@@ -46,37 +49,72 @@ protected function _prepareIndex($entityIds = null, $attributeId = null)
4649
return $this;
4750
}
4851

49-
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
50-
$productValueExpression = $connection->getCheckSql('pds.value_id > 0', 'pds.value', 'pdd.value');
52+
$select = $connection->select()
53+
->union(
54+
[
55+
$this->getSelect($attrIds, $entityIds),
56+
$this->getSelect($attrIds, $entityIds, true)
57+
]
58+
);
5159

52-
$select = $connection->select()->from(
53-
['pdd' => $this->getTable('catalog_product_entity_decimal')],
54-
[]
55-
)->join(
56-
['cs' => $this->getTable('store')],
57-
'',
58-
[]
59-
)->joinLeft(
60-
['pds' => $this->getTable('catalog_product_entity_decimal')],
61-
sprintf(
62-
'pds.%s = pdd.%s AND pds.attribute_id = pdd.attribute_id'.' AND pds.store_id=cs.store_id',
63-
$productIdField,
64-
$productIdField
65-
),
66-
[]
67-
)->joinLeft(
60+
$query = $select->insertFromSelect($idxTable);
61+
$connection->query($query);
62+
63+
return $this;
64+
}
65+
66+
/**
67+
* Generate select with attribute values
68+
*
69+
* @param array $attributeIds
70+
* @param array|null $entityIds
71+
* @param bool $storeValuesOnly
72+
* @return Select
73+
* @throws \Exception
74+
*/
75+
private function getSelect(array $attributeIds, ?array $entityIds, bool $storeValuesOnly = false): Select
76+
{
77+
$productIdField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
78+
$connection = $this->getConnection();
79+
$select = $connection->select()
80+
->from(
81+
['cs' => $this->getTable('store')],
82+
[]
83+
);
84+
if ($storeValuesOnly) {
85+
$select->join(
86+
['pdd' => $this->getTable('catalog_product_entity_decimal')],
87+
'pdd.store_id = cs.store_id',
88+
[]
89+
);
90+
$productValueExpression = 'pdd.value';
91+
} else {
92+
$select->join(
93+
['pdd' => $this->getTable('catalog_product_entity_decimal')],
94+
'pdd.store_id=' . Store::DEFAULT_STORE_ID,
95+
[]
96+
)->joinLeft(
97+
['pds' => $this->getTable('catalog_product_entity_decimal')],
98+
sprintf(
99+
'pds.%s = pdd.%s AND pds.attribute_id = pdd.attribute_id' . ' AND pds.store_id=cs.store_id',
100+
$productIdField,
101+
$productIdField
102+
),
103+
[]
104+
);
105+
$productValueExpression = $connection->getCheckSql('pds.value_id > 0', 'pds.value', 'pdd.value');
106+
}
107+
$select->joinLeft(
68108
['cpe' => $this->getTable('catalog_product_entity')],
69109
"cpe.{$productIdField} = pdd.{$productIdField}",
70110
[]
71-
)->where(
72-
'pdd.store_id=?',
73-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
74111
)->where(
75112
'cs.store_id!=?',
76-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
113+
Store::DEFAULT_STORE_ID
77114
)->where(
78115
'pdd.attribute_id IN(?)',
79-
$attrIds
116+
$attributeIds,
117+
Zend_Db::INT_TYPE
80118
)->where(
81119
"{$productValueExpression} IS NOT NULL"
82120
)->columns(
@@ -105,7 +143,11 @@ protected function _prepareIndex($entityIds = null, $attributeId = null)
105143
);
106144

107145
if ($entityIds !== null) {
108-
$select->where('cpe.entity_id IN(?)', $entityIds);
146+
$select->where(
147+
'cpe.entity_id IN(?)',
148+
$entityIds,
149+
Zend_Db::INT_TYPE
150+
);
109151
}
110152

111153
/**
@@ -121,10 +163,7 @@ protected function _prepareIndex($entityIds = null, $attributeId = null)
121163
]
122164
);
123165

124-
$query = $select->insertFromSelect($idxTable);
125-
$connection->query($query);
126-
127-
return $this;
166+
return $select;
128167
}
129168

130169
/**
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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="AdminProductGridSwitchViewBookmarkTest">
12+
<annotations>
13+
<features value="Catalog"/>
14+
<stories value="Switch views in product grid"/>
15+
<title value="Verify that newly created view on product grid and switching between default view is correct"/>
16+
<description value="Verify that newly created view on product grid and switching between default view is correct"/>
17+
<severity value="MAJOR"/>
18+
<testCaseId value="ACP2E-258"/>
19+
<group value="product"/>
20+
</annotations>
21+
22+
<before>
23+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
24+
<actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndex"/>
25+
</before>
26+
27+
<after>
28+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logoutOfAdmin"/>
29+
</after>
30+
31+
<waitForElementVisible selector="{{AdminGridColumnsControls.columns}}" stepKey="waitForAdminGridColumnControlsColumn"/>
32+
<click selector="{{AdminGridColumnsControls.columns}}" stepKey="clickAdminGridColumnControlsColumn"/>
33+
<waitForElementVisible selector="{{AdminDataGridHeaderSection.columnCheckbox('Special Price')}}" stepKey="verifyAdminGridColumnControlsForSelectedColumnVisible"/>
34+
<click selector="{{AdminDataGridHeaderSection.columnCheckbox('Special Price')}}" stepKey="clickForAdminGridControlForSelectedColumn"/>
35+
<waitForElementVisible selector="{{AdminGridHeaders.headerByName('Special Price')}}" stepKey="waitForAdminGridColumnHeaderForSelectedColumn"/>
36+
<click selector="{{AdminGridColumnsControls.columns}}" stepKey="closeAdminGridColumnControls"/>
37+
<waitForElementNotVisible selector="{{AdminGridColumnsControls.columnName('Special Price')}}" stepKey="verifyAdminGridColumnControlsForSelectedColumnNotVisible"/>
38+
39+
<click selector="{{AdminDataGridHeaderSection.bookmarkToggle}}" stepKey="openViewBookmarks"/>
40+
<waitForElementVisible selector="{{AdminGridDefaultViewControls.saveViewAs}}" stepKey="waitForSaveViewButton"/>
41+
<click selector="{{AdminGridDefaultViewControls.saveViewAs}}" stepKey="saveView"/>
42+
<waitForElementVisible selector="{{AdminGridDefaultViewControls.viewName}}" stepKey="waitForViewNameInput"/>
43+
<fillField selector="{{AdminGridDefaultViewControls.viewName}}" userInput="{{NewGridView.name}}" stepKey="inputViewName"/>
44+
<pressKey selector="{{AdminGridDefaultViewControls.viewName}}" parameterArray="[\Facebook\WebDriver\WebDriverKeys::ENTER]" stepKey="pressEnterKey"/>
45+
<waitForElementNotVisible selector="{{AdminGridDefaultViewControls.viewName}}" stepKey="waitForViewNameInputGone"/>
46+
47+
<waitForPageLoad stepKey="waitForGridLoad" time="10"/>
48+
49+
<grabTextFrom selector="{{AdminGridHeaders.headerByName('Special Price')}}" stepKey="grabCustomViewHeaderColumn"/>
50+
<assertEquals message="ExpectedSpecialPriceHeader" stepKey="assertExpectedSpecialPriceHeader">
51+
<actualResult type="variable">$grabCustomViewHeaderColumn</actualResult>
52+
<expectedResult type="string">Special Price</expectedResult>
53+
</assertEquals>
54+
55+
<click selector="{{AdminGridDefaultViewControls.viewByName('Default View')}}" stepKey="clickOnViewButton"/>
56+
<waitForPageLoad stepKey="waitForGridReset"/>
57+
58+
<waitForElementNotVisible selector="{{AdminGridHeaders.headerByName('Special Price')}}" stepKey="verifyAdminGridHeaderForSelectedViewNotVisible"/>
59+
60+
<click selector="{{AdminDataGridHeaderSection.bookmarkToggle}}" stepKey="openViewBookmarksForDeletion"/>
61+
<click selector="{{AdminGridDefaultViewControls.viewByName(NewGridView.name)}}{{AdminEnhancedMediaGalleryActionsSection.editViewButtonPartial}}" stepKey="clickEditButton"/>
62+
<seeElement selector="{{AdminEnhancedMediaGalleryActionsSection.deleteViewButton}}" stepKey="seeDeleteButton"/>
63+
<click selector="{{AdminEnhancedMediaGalleryActionsSection.deleteViewButton}}" stepKey="clickDeleteButton"/>
64+
<waitForPageLoad stepKey="waitForDeletion" time="10"/>
65+
</test>
66+
</tests>

app/code/Magento/CatalogInventory/Model/ResourceModel/StockStatusFilter.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
1111
use Magento\CatalogInventory\Api\StockConfigurationInterface;
1212
use Magento\CatalogInventory\Model\Stock;
13+
use Magento\CatalogInventory\Model\StockStatusApplierInterface;
1314
use Magento\Framework\App\ResourceConnection;
1415
use Magento\Framework\DB\Select;
16+
use Magento\Framework\App\ObjectManager;
1517

1618
/**
1719
* Generic in-stock status filter
1820
*/
1921
class StockStatusFilter implements StockStatusFilterInterface
2022
{
2123
private const TABLE_NAME = 'cataloginventory_stock_status';
24+
2225
/**
2326
* @var ResourceConnection
2427
*/
@@ -29,16 +32,25 @@ class StockStatusFilter implements StockStatusFilterInterface
2932
*/
3033
private $stockConfiguration;
3134

35+
/**
36+
* @var StockStatusApplierInterface
37+
*/
38+
private $stockStatusApplier;
39+
3240
/**
3341
* @param ResourceConnection $resource
3442
* @param StockConfigurationInterface $stockConfiguration
43+
* @param StockStatusApplierInterface|null $stockStatusApplier
3544
*/
3645
public function __construct(
3746
ResourceConnection $resource,
38-
StockConfigurationInterface $stockConfiguration
47+
StockConfigurationInterface $stockConfiguration,
48+
?StockStatusApplierInterface $stockStatusApplier = null
3949
) {
4050
$this->resource = $resource;
4151
$this->stockConfiguration = $stockConfiguration;
52+
$this->stockStatusApplier = $stockStatusApplier
53+
?? ObjectManager::getInstance()->get(StockStatusApplierInterface::class);
4254
}
4355

4456
/**
@@ -67,7 +79,12 @@ public function execute(
6779
implode(' AND ', $joinCondition),
6880
[]
6981
);
70-
$select->where("{$stockStatusTableAlias}.stock_status = ?", StockStatusInterface::STATUS_IN_STOCK);
82+
83+
if ($this->stockStatusApplier->hasSearchResultApplier()) {
84+
$select->columns(["{$stockStatusTableAlias}.stock_status AS is_salable"]);
85+
} else {
86+
$select->where("{$stockStatusTableAlias}.stock_status = ?", StockStatusInterface::STATUS_IN_STOCK);
87+
}
7188

7289
return $select;
7390
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model;
9+
10+
/**
11+
* Search Result Applier getters and setters
12+
*/
13+
class StockStatusApplier implements StockStatusApplierInterface
14+
{
15+
/**
16+
* Storefront search result applier flag
17+
*
18+
* @var bool
19+
*/
20+
private $searchResultApplier = false;
21+
22+
/**
23+
* Set flag, if the request is originated from SearchResultApplier
24+
*
25+
* @param bool $status
26+
*/
27+
public function setSearchResultApplier(bool $status): void
28+
{
29+
$this->searchResultApplier = $status;
30+
}
31+
32+
/**
33+
* Get flag, if the request is originated from SearchResultApplier
34+
*
35+
* @return bool
36+
*/
37+
public function hasSearchResultApplier() : bool
38+
{
39+
return $this->searchResultApplier;
40+
}
41+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model;
9+
10+
/**
11+
* Search Result Applier interface.
12+
*/
13+
interface StockStatusApplierInterface
14+
{
15+
16+
/**
17+
* Set flag, if the request is originated from SearchResultApplier
18+
*
19+
* @param bool $status
20+
*/
21+
public function setSearchResultApplier(bool $status): void;
22+
23+
/**
24+
* Get flag, if the request is originated from SearchResultApplier
25+
*
26+
* @return bool
27+
*/
28+
public function hasSearchResultApplier() : bool;
29+
}

app/code/Magento/CatalogInventory/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
<preference for="Magento\CatalogInventory\Model\ResourceModel\QtyCounterInterface" type="Magento\CatalogInventory\Model\ResourceModel\Stock" />
3535
<preference for="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilterInterface" type="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilter" />
36+
<preference for="Magento\CatalogInventory\Model\StockStatusApplierInterface" type="Magento\CatalogInventory\Model\StockStatusApplier" />
3637
<type name="Magento\Catalog\Model\Product\Attribute\Repository">
3738
<plugin name="filterCustomAttribute" type="Magento\CatalogInventory\Model\Plugin\FilterCustomAttribute" />
3839
</type>

app/code/Magento/Config/Test/Mftf/Section/AdminConfigSection.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@
2323
<element name="collapsibleSectionByTitle" type="text" selector="//form[@id='config-edit-form']//div[@class='section-config'][contains(.,'{{sectionTitle}}')]" parameterized="true" />
2424
<element name="expandedSectionByTitle" type="text" selector="//form[@id='config-edit-form']//div[@class='section-config active'][contains(.,'{{sectionTitle}}')]" parameterized="true" />
2525
<element name="errorElement" type="text" selector="#{{inputId}}-error" parameterized="true" />
26+
<element name="defaultCurrency" type="select" selector="#currency_options_default" />
27+
<element name="allowedCurrencies" type="multiselect" selector="#currency_options_allow" />
28+
<element name="defaultCurrencyCheckbox" type="checkbox" selector="#currency_options_default_inherit"/>
29+
<element name="allowedCurrencyCheckbox" type="checkbox" selector="#currency_options_allow_inherit"/>
2630
</section>
2731
</sections>

app/code/Magento/Customer/Block/Account/AuthenticationPopup.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public function __construct(
4242
}
4343

4444
/**
45+
* Returns serialize jsLayout
46+
*
4547
* @return string
4648
*/
4749
public function getJsLayout()
@@ -60,7 +62,8 @@ public function getConfig()
6062
'autocomplete' => $this->escapeHtml($this->isAutocompleteEnabled()),
6163
'customerRegisterUrl' => $this->escapeUrl($this->getCustomerRegisterUrlUrl()),
6264
'customerForgotPasswordUrl' => $this->escapeUrl($this->getCustomerForgotPasswordUrl()),
63-
'baseUrl' => $this->escapeUrl($this->getBaseUrl())
65+
'baseUrl' => $this->escapeUrl($this->getBaseUrl()),
66+
'customerLoginUrl' => $this->getUrl('customer/ajax/login'),
6467
];
6568
}
6669

app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@
332332
<data key="telephone">333-33-333-33</data>
333333
<data key="country">Germany</data>
334334
<data key="state">Berlin</data>
335-
<data key="vatNumber">DE265675123</data>
335+
<data key="vatNumber">DE257486969</data>
336336
</entity>
337337
<entity name="US_Address_California">
338338
<data key="firstname">John</data>

0 commit comments

Comments
 (0)