Skip to content

Commit 9a1e078

Browse files
committed
MAGETWO-63226: Impossible to perform mass update on product with 60+ attributes in system
1 parent a9c765c commit 9a1e078

File tree

2 files changed

+172
-11
lines changed

2 files changed

+172
-11
lines changed

app/code/Magento/Eav/Model/ResourceModel/Entity/Attribute/Collection.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,19 @@ public function setAttributeSetsFilter(array $setIds)
205205
*/
206206
public function setInAllAttributeSetsFilter(array $setIds)
207207
{
208-
foreach ($setIds as $setId) {
209-
$setId = (int)$setId;
210-
if (!$setId) {
211-
continue;
212-
}
213-
$alias = sprintf('entity_attribute_%d', $setId);
214-
$joinCondition = $this->getConnection()->quoteInto(
215-
"{$alias}.attribute_id = main_table.attribute_id AND {$alias}.attribute_set_id =?",
216-
$setId
217-
);
218-
$this->join([$alias => 'eav_entity_attribute'], $joinCondition, 'attribute_id');
208+
if (!empty($setIds)) {
209+
$this->getSelect()
210+
->join(
211+
['entity_attribute' => $this->getTable('eav_entity_attribute')],
212+
'entity_attribute.attribute_id = main_table.attribute_id',
213+
['count' => new \Zend_Db_Expr('COUNT(*)')]
214+
)
215+
->where(
216+
'entity_attribute.attribute_set_id IN (?)',
217+
$setIds
218+
)
219+
->group('entity_attribute.attribute_id')
220+
->having('count = ' . count($setIds));
219221
}
220222

221223
//$this->getSelect()->distinct(true);
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Eav\Test\Unit\Model\ResourceModel\Entity\Attribute;
9+
10+
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
11+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
12+
13+
/**
14+
* Test for \Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection class.
15+
*
16+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
17+
*/
18+
class CollectionTest extends \PHPUnit_Framework_TestCase
19+
{
20+
/**
21+
* @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection
22+
*/
23+
private $model;
24+
25+
/**
26+
* @var \Magento\Framework\Data\Collection\EntityFactory|\PHPUnit_Framework_MockObject_MockObject
27+
*/
28+
private $entityFactoryMock;
29+
30+
/**
31+
* @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
32+
*/
33+
private $loggerMock;
34+
35+
/**
36+
* @var \Magento\Framework\Data\Collection\Db\FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject
37+
*/
38+
private $fetchStrategyMock;
39+
40+
/**
41+
* @var \Magento\Framework\Data\Collection\EntityFactory|\PHPUnit_Framework_MockObject_MockObject
42+
*/
43+
private $eventManagerMock;
44+
45+
/**
46+
* @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
47+
*/
48+
private $eavConfigMock;
49+
50+
/**
51+
* @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
52+
*/
53+
private $storeManagerMock;
54+
55+
/**
56+
* @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
57+
*/
58+
private $connectionMock;
59+
60+
/**
61+
* @var \Magento\Framework\Model\ResourceModel\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject
62+
*/
63+
private $resourceMock;
64+
65+
/**
66+
* @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
67+
*/
68+
private $selectMock;
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
protected function setUp()
74+
{
75+
$this->entityFactoryMock = $this->getMockBuilder(\Magento\Framework\Data\Collection\EntityFactory::class)
76+
->disableOriginalConstructor()
77+
->getMock();
78+
79+
$this->loggerMock = $this->getMockBuilder(\Psr\Log\LoggerInterface::class)
80+
->disableOriginalConstructor()
81+
->getMock();
82+
83+
$this->fetchStrategyMock = $this->getMockBuilder(FetchStrategyInterface::class)
84+
->disableOriginalConstructor()
85+
->getMock();
86+
87+
$this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
88+
->disableOriginalConstructor()
89+
->getMock();
90+
91+
$this->eavConfigMock = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
92+
->disableOriginalConstructor()
93+
->getMock();
94+
95+
$this->connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class)
96+
->disableOriginalConstructor()
97+
->getMock();
98+
99+
$this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
100+
->disableOriginalConstructor()
101+
->getMock();
102+
103+
$this->resourceMock = $this->getMockBuilder(\Magento\Framework\Model\ResourceModel\Db\AbstractDb::class)
104+
->setMethods(['__wakeup', 'getConnection', 'getMainTable', 'getTable'])
105+
->disableOriginalConstructor()
106+
->getMockForAbstractClass();
107+
108+
$this->resourceMock->expects($this->any())->method('getConnection')->willReturn($this->connectionMock);
109+
$this->resourceMock->expects($this->any())->method('getMainTable')->willReturn('eav_entity_attribute');
110+
111+
$this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
112+
->disableOriginalConstructor()
113+
->getMock();
114+
115+
$this->connectionMock->expects($this->any())->method('select')->willReturn($this->selectMock);
116+
117+
$objectManager = new ObjectManager($this);
118+
$this->model = $objectManager->getObject(
119+
\Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection::class,
120+
[
121+
'entityFactory' => $this->entityFactoryMock,
122+
'logger' => $this->loggerMock,
123+
'fetchStrategy' => $this->fetchStrategyMock,
124+
'eventManager' => $this->eventManagerMock,
125+
'eavConfig' => $this->eavConfigMock,
126+
'connection' => $this->connectionMock,
127+
'resource' => $this->resourceMock,
128+
]
129+
);
130+
}
131+
132+
/**
133+
* Test method \Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection::setInAllAttributeSetsFilter
134+
*
135+
* @return void
136+
*/
137+
public function testSetInAllAttributeSetsFilter()
138+
{
139+
$setIds = [1, 2, 3];
140+
141+
$this->selectMock->expects($this->atLeastOnce())
142+
->method('where')
143+
->with('entity_attribute.attribute_set_id IN (?)', $setIds)
144+
->willReturnSelf();
145+
$this->selectMock->expects($this->atLeastOnce())->method('join')->with(
146+
['entity_attribute' => $this->model->getTable('eav_entity_attribute')],
147+
'entity_attribute.attribute_id = main_table.attribute_id',
148+
['count' => new \Zend_Db_Expr('COUNT(*)')]
149+
)->willReturnSelf();
150+
151+
$this->selectMock->expects($this->atLeastOnce())->method('group')->with('entity_attribute.attribute_id')
152+
->willReturnSelf();
153+
154+
$this->selectMock->expects($this->atLeastOnce())->method('having')->with('count = ' . count($setIds))
155+
->willReturnSelf();
156+
157+
$this->model->setInAllAttributeSetsFilter($setIds);
158+
}
159+
}

0 commit comments

Comments
 (0)