Skip to content

Commit 2d705c8

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-l3/magento2ce into 2.4-develop
2 parents 0d9fc3b + a96f0f7 commit 2d705c8

File tree

87 files changed

+4282
-293
lines changed

Some content is hidden

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

87 files changed

+4282
-293
lines changed

app/code/Magento/Authorization/Model/Acl/Loader/Rule.php

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\Authorization\Model\Acl\Loader;
99

10+
use Magento\Framework\Acl;
1011
use Magento\Framework\Acl\Data\CacheInterface;
1112
use Magento\Framework\Acl\LoaderInterface;
1213
use Magento\Framework\Acl\RootResource;
@@ -21,7 +22,12 @@ class Rule implements LoaderInterface
2122
/**
2223
* Rules array cache key
2324
*/
24-
const ACL_RULE_CACHE_KEY = 'authorization_rule_cached_data';
25+
public const ACL_RULE_CACHE_KEY = 'authorization_rule_cached_data';
26+
27+
/**
28+
* Allow everything resource id
29+
*/
30+
private const ALLOW_EVERYTHING = 'Magento_Backend::all';
2531

2632
/**
2733
* @var ResourceConnection
@@ -75,27 +81,74 @@ public function __construct(
7581
/**
7682
* Populate ACL with rules from external storage
7783
*
78-
* @param \Magento\Framework\Acl $acl
84+
* @param Acl $acl
7985
* @return void
8086
*/
81-
public function populateAcl(\Magento\Framework\Acl $acl)
87+
public function populateAcl(Acl $acl)
8288
{
89+
$result = $this->applyPermissionsAccordingToRules($acl);
90+
$this->applyDenyPermissionsForMissingRules($acl, ...$result);
91+
}
92+
93+
/**
94+
* Apply ACL with rules
95+
*
96+
* @param Acl $acl
97+
* @return array[]
98+
*/
99+
private function applyPermissionsAccordingToRules(Acl $acl): array
100+
{
101+
$foundResources = $foundDeniedRoles = [];
83102
foreach ($this->getRulesArray() as $rule) {
84103
$role = $rule['role_id'];
85104
$resource = $rule['resource_id'];
86105
$privileges = !empty($rule['privileges']) ? explode(',', $rule['privileges']) : null;
87106

88107
if ($acl->has($resource)) {
108+
$foundResources[$resource] = $resource;
89109
if ($rule['permission'] == 'allow') {
90110
if ($resource === $this->_rootResource->getId()) {
91111
$acl->allow($role, null, $privileges);
92112
}
93113
$acl->allow($role, $resource, $privileges);
94114
} elseif ($rule['permission'] == 'deny') {
115+
$foundDeniedRoles[$role] = $role;
95116
$acl->deny($role, $resource, $privileges);
96117
}
97118
}
98119
}
120+
return [$foundResources, $foundDeniedRoles];
121+
}
122+
123+
/**
124+
* Apply deny permissions for missing rules
125+
*
126+
* For all rules that were not regenerated in authorization_rule table,
127+
* when adding a new module and without re-saving all roles,
128+
* consider not present rules with deny permissions
129+
*
130+
* @param Acl $acl
131+
* @param array $resources
132+
* @param array $deniedRoles
133+
* @return void
134+
*/
135+
private function applyDenyPermissionsForMissingRules(
136+
Acl $acl,
137+
array $resources,
138+
array $deniedRoles
139+
) {
140+
if (count($resources) && count($deniedRoles)
141+
//ignore denying missing permission if all are allowed
142+
&& !(count($resources) === 1 && isset($resources[static::ALLOW_EVERYTHING]))
143+
) {
144+
foreach ($acl->getResources() as $resource) {
145+
if (!isset($resources[$resource])) {
146+
foreach ($deniedRoles as $role) {
147+
$acl->deny($role, $resource, null);
148+
}
149+
}
150+
}
151+
}
99152
}
100153

101154
/**

app/code/Magento/Authorization/Test/Unit/Model/Acl/Loader/RuleTest.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ static function ($value) {
9797
*/
9898
public function testPopulateAclFromCache(): void
9999
{
100+
$rules = [
101+
['role_id' => 1, 'resource_id' => 'Magento_Backend::all', 'permission' => 'allow'],
102+
['role_id' => 2, 'resource_id' => 1, 'permission' => 'allow'],
103+
['role_id' => 3, 'resource_id' => 1, 'permission' => 'deny']
104+
];
100105
$this->resourceMock->expects($this->never())->method('getTable');
101106
$this->resourceMock->expects($this->never())
102107
->method('getConnection');
@@ -105,13 +110,7 @@ public function testPopulateAclFromCache(): void
105110
->method('load')
106111
->with(Rule::ACL_RULE_CACHE_KEY)
107112
->willReturn(
108-
json_encode(
109-
[
110-
['role_id' => 1, 'resource_id' => 'Magento_Backend::all', 'permission' => 'allow'],
111-
['role_id' => 2, 'resource_id' => 1, 'permission' => 'allow'],
112-
['role_id' => 3, 'resource_id' => 1, 'permission' => 'deny']
113-
]
114-
)
113+
json_encode($rules)
115114
);
116115

117116
$aclMock = $this->createMock(Acl::class);
@@ -123,9 +122,21 @@ public function testPopulateAclFromCache(): void
123122
['1', 'Magento_Backend::all', null],
124123
['2', 1, null]
125124
);
125+
126126
$aclMock
127127
->method('deny')
128-
->with('3', 1, null);
128+
->withConsecutive(
129+
['3', 1, null]
130+
);
131+
132+
$aclMock
133+
->method('getResources')
134+
->willReturn([
135+
'Magento_Backend::all',
136+
'Magento_Backend::admin',
137+
'Vendor_MyModule::menu',
138+
'Vendor_MyModule::index'
139+
]);
129140

130141
$this->model->populateAcl($aclMock);
131142
}

app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,17 @@ private function applyBundlePrice($priceTable): void
822822
]
823823
);
824824

825-
$this->tableMaintainer->insertFromSelect($select, $priceTable->getTableName(), []);
825+
$this->tableMaintainer->insertFromSelect($select, $priceTable->getTableName(), [
826+
"entity_id",
827+
"customer_group_id",
828+
"website_id",
829+
"tax_class_id",
830+
"price",
831+
"final_price",
832+
"min_price",
833+
"max_price",
834+
"tier_price",
835+
]);
826836
}
827837

828838
/**

app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price/DisabledProductOptionPriceModifier.php

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,22 @@ class DisabledProductOptionPriceModifier implements PriceModifierInterface
3434
/**
3535
* @var array
3636
*/
37-
private $isBundle = [];
37+
private $websiteIdsOfProduct = [];
3838

3939
/**
40-
* @var array
40+
* @var BundleSelection
4141
*/
42-
private $websiteIdsOfProduct = [];
42+
private BundleSelection $bundleSelection;
43+
44+
/**
45+
* @var Config
46+
*/
47+
private Config $config;
48+
49+
/**
50+
* @var MetadataPool
51+
*/
52+
private MetadataPool $metadataPool;
4353

4454
/**
4555
* @param ResourceConnection $resourceConnection
@@ -72,11 +82,8 @@ public function __construct(
7282
*/
7383
public function modifyPrice(IndexTableStructure $priceTable, array $entityIds = []) : void
7484
{
75-
foreach ($entityIds as $entityId) {
85+
foreach ($this->getBundleIds($entityIds) as $entityId) {
7686
$entityId = (int) $entityId;
77-
if (!$this->isBundle($entityId)) {
78-
continue;
79-
}
8087
foreach ($this->getWebsiteIdsOfProduct($entityId) as $websiteId) {
8188
$productIdsDisabledRequired = $this->selectionProductsDisabledRequired
8289
->getChildProductIds($entityId, (int)$websiteId);
@@ -118,24 +125,24 @@ private function getWebsiteIdsOfProduct(int $entityId): array
118125
}
119126

120127
/**
121-
* Is product bundle
128+
* Get Bundle Ids
122129
*
123-
* @param int $entityId
124-
* @return bool
130+
* @param array $entityIds
131+
* @return \Traversable
125132
*/
126-
private function isBundle(int $entityId): bool
133+
private function getBundleIds(array $entityIds): \Traversable
127134
{
128-
if (isset($this->isBundle[$entityId])) {
129-
return $this->isBundle[$entityId];
130-
}
131135
$connection = $this->resourceConnection->getConnection('indexer');
132136
$select = $connection->select();
133137
$select->from(
134138
['cpe' => $this->resourceConnection->getTableName('catalog_product_entity')],
135-
['type_id']
136-
)->where('cpe.entity_id = ?', $entityId);
137-
$typeId = $connection->fetchOne($select);
138-
$this->isBundle[$entityId] = $typeId === Type::TYPE_BUNDLE;
139-
return $this->isBundle[$entityId];
139+
['entity_id']
140+
)->where('cpe.entity_id in ( ? )', !empty($entityIds) ? $entityIds : [0], \Zend_Db::INT_TYPE)
141+
->where('type_id = ?', Type::TYPE_BUNDLE);
142+
143+
$statement = $select->query();
144+
while ($id = $statement->fetchColumn()) {
145+
yield $id;
146+
}
140147
}
141148
}

app/code/Magento/Bundle/Model/ResourceModel/Selection/Collection/FilterApplier.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Magento\Bundle\Model\ResourceModel\Selection\Collection;
77

88
use Magento\Bundle\Model\ResourceModel\Selection\Collection;
9+
use Zend_Db_Select_Exception;
910

1011
/**
1112
* An applier of additional filters to a selection collection.
@@ -32,16 +33,17 @@ class FilterApplier
3233
* @param string $conditionType
3334
*
3435
* @return void
36+
* @throws Zend_Db_Select_Exception
3537
*/
36-
public function apply(Collection $collection, $field, $value, $conditionType = 'eq')
38+
public function apply(Collection $collection, string $field, $value, string $conditionType = 'eq')
3739
{
3840
foreach ($collection->getSelect()->getPart('from') as $tableAlias => $data) {
3941
if ($data['tableName'] == $collection->getTable('catalog_product_bundle_selection')) {
4042
$field = $tableAlias . '.' . $field;
4143
}
4244
}
4345

44-
$collection->getSelect()
46+
$collection->getSelect()->distinct(true)
4547
->where($field . $this->conditionTypesMap[$conditionType], $value);
4648
}
4749
}

app/code/Magento/Bundle/Test/Unit/Model/ResourceModel/Selection/Collection/FilterApplierTest.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
namespace Magento\Bundle\Test\Unit\Model\ResourceModel\Selection\Collection;
99

10+
use Magento\Bundle\Model\ResourceModel\Selection\Collection;
1011
use Magento\Bundle\Model\ResourceModel\Selection\Collection\FilterApplier;
1112
use Magento\Framework\DB\Select;
1213
use PHPUnit\Framework\TestCase;
14+
use Zend_Db_Select_Exception;
1315

1416
/**
1517
* Test selection collection filter applier
@@ -37,12 +39,13 @@ protected function setUp(): void
3739
* @param $expectedCondition
3840
* @param $expectedValue
3941
* @dataProvider applyDataProvider
42+
* @throws Zend_Db_Select_Exception
4043
*/
4144
public function testApply($field, $value, $conditionType, $expectedCondition, $expectedValue): void
4245
{
4346
$tableName = 'catalog_product_bundle_selection';
4447
$select = $this->createMock(Select::class);
45-
$collection = $this->createMock(\Magento\Bundle\Model\ResourceModel\Selection\Collection::class);
48+
$collection = $this->createMock(Collection::class);
4649
$collection->method('getSelect')
4750
->willReturn($select);
4851
$collection->method('getTable')
@@ -60,6 +63,10 @@ public function testApply($field, $value, $conditionType, $expectedCondition, $e
6063
]
6164
]
6265
);
66+
$select->expects($this->once())
67+
->method('distinct')
68+
->with(true)
69+
->willReturnSelf();
6370
$select->expects($this->once())
6471
->method('where')
6572
->with($expectedCondition, $expectedValue);

app/code/Magento/Catalog/Model/Indexer/Product/Price/AbstractAction.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ abstract class AbstractAction
6161
protected $_storeManager;
6262

6363
/**
64-
* Currency factory
6564
*
6665
* @var CurrencyFactory
6766
*/
@@ -83,7 +82,6 @@ abstract class AbstractAction
8382
protected $_catalogProductType;
8483

8584
/**
86-
* Indexer price factory
8785
*
8886
* @var Factory
8987
*/
@@ -343,16 +341,15 @@ protected function _getIndexer($productTypeId)
343341
*/
344342
protected function _insertFromTable($sourceTable, $destTable, $where = null)
345343
{
346-
$sourceColumns = array_keys($this->getConnection()->describeTable($sourceTable));
347-
$targetColumns = array_keys($this->getConnection()->describeTable($destTable));
348-
$select = $this->getConnection()->select()->from($sourceTable, $sourceColumns);
344+
$columns = array_keys($this->getConnection()->describeTable($destTable));
345+
$select = $this->getConnection()->select()->from($sourceTable, $columns);
349346
if ($where) {
350347
$select->where($where);
351348
}
352349
$query = $this->getConnection()->insertFromSelect(
353350
$select,
354351
$destTable,
355-
$targetColumns,
352+
$columns,
356353
AdapterInterface::INSERT_ON_DUPLICATE
357354
);
358355
$this->getConnection()->query($query);

0 commit comments

Comments
 (0)