Skip to content

Commit 6159299

Browse files
committed
MAGETWO-63945: Add extension point to sales grid indexer
1 parent 0aff845 commit 6159299

File tree

9 files changed

+405
-3
lines changed

9 files changed

+405
-3
lines changed

app/code/Magento/Sales/Model/ResourceModel/AbstractGrid.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public function purge($value, $field = null)
8989
*
9090
* @param string $default
9191
* @return string
92+
* @deprecated unused
93+
* @see \Magento\Sales\Model\ResourceModel\Provider\UpdatedIdListProvider
9294
*/
9395
protected function getLastUpdatedAtValue($default = '0000-00-00 00:00:00')
9496
{

app/code/Magento/Sales/Model/ResourceModel/Grid.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
*/
66
namespace Magento\Sales\Model\ResourceModel;
77

8+
use Magento\Framework\App\ObjectManager;
89
use Magento\Framework\DB\Adapter\AdapterInterface;
9-
use Magento\Sales\Model\ResourceModel\AbstractGrid;
1010
use Magento\Framework\Model\ResourceModel\Db\Context;
11+
use Magento\Sales\Model\ResourceModel\Provider\IdListProviderInterface;
1112

1213
/**
1314
* Class Grid
@@ -39,6 +40,11 @@ class Grid extends AbstractGrid
3940
*/
4041
protected $columns;
4142

43+
/**
44+
* @var IdListProviderInterface
45+
*/
46+
private $idListProvider;
47+
4248
/**
4349
* @param Context $context
4450
* @param string $mainTableName
@@ -47,6 +53,7 @@ class Grid extends AbstractGrid
4753
* @param array $joins
4854
* @param array $columns
4955
* @param string $connectionName
56+
* @param IdListProviderInterface $idListProvider
5057
*/
5158
public function __construct(
5259
Context $context,
@@ -55,13 +62,15 @@ public function __construct(
5562
$orderIdField,
5663
array $joins = [],
5764
array $columns = [],
58-
$connectionName = null
65+
$connectionName = null,
66+
IdListProviderInterface $idListProvider = null
5967
) {
6068
$this->mainTableName = $mainTableName;
6169
$this->gridTableName = $gridTableName;
6270
$this->orderIdField = $orderIdField;
6371
$this->joins = $joins;
6472
$this->columns = $columns;
73+
$this->idListProvider = $idListProvider ?: ObjectManager::getInstance()->get(IdListProviderInterface::class);
6574
parent::__construct($context, $connectionName);
6675
}
6776

@@ -99,7 +108,10 @@ public function refresh($value, $field = null)
99108
public function refreshBySchedule()
100109
{
101110
$select = $this->getGridOriginSelect()
102-
->where($this->mainTableName . '.updated_at >= ?', $this->getLastUpdatedAtValue());
111+
->where(
112+
$this->mainTableName . '.entity_id IN (?)',
113+
$this->idListProvider->get($this->mainTableName, $this->gridTableName)
114+
);
103115

104116
return $this->getConnection()->query(
105117
$this->getConnection()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Model\ResourceModel\Provider;
7+
8+
use Magento\Framework\ObjectManager\TMapFactory;
9+
10+
/**
11+
* Implements IdListProviderInterface as composite
12+
*/
13+
class IdListProviderComposite implements IdListProviderInterface
14+
{
15+
/**
16+
* @var IdListProviderInterface[]
17+
*/
18+
private $providers;
19+
20+
/**
21+
* @param TMapFactory $tmapFactory
22+
* @param array $providers
23+
*/
24+
public function __construct(
25+
TMapFactory $tmapFactory,
26+
array $providers = []
27+
) {
28+
$this->providers = $tmapFactory->create(
29+
[
30+
'array' => $providers,
31+
'type' => IdListProviderInterface::class
32+
]
33+
);
34+
}
35+
36+
/**
37+
* @inheritDoc
38+
*/
39+
public function get($mainTableName, $gridTableName)
40+
{
41+
$result = [];
42+
foreach ($this->providers as $provider) {
43+
$result = array_merge($result, $provider->get($mainTableName, $gridTableName));
44+
}
45+
46+
return $result;
47+
}
48+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Model\ResourceModel\Provider;
7+
8+
/**
9+
* Interface provides entities ids list that should be updated in grid
10+
*/
11+
interface IdListProviderInterface
12+
{
13+
/**
14+
* Returns id list of entities for adding or updating in grid.
15+
*
16+
* @param string $mainTableName source table name
17+
* @param string $gridTableName grid table name
18+
* @return array
19+
*/
20+
public function get($mainTableName, $gridTableName);
21+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Model\ResourceModel\Provider;
7+
8+
use Magento\Framework\App\ResourceConnection;
9+
10+
/**
11+
* Provides latest updated entities ids list
12+
*/
13+
class UpdatedIdListProvider implements IdListProviderInterface
14+
{
15+
/**
16+
* @var ResourceConnection
17+
*/
18+
private $resourceConnection;
19+
20+
/**
21+
* IdListProvider constructor.
22+
* @param ResourceConnection $resourceConnection
23+
*/
24+
public function __construct(
25+
ResourceConnection $resourceConnection
26+
) {
27+
$this->resourceConnection = $resourceConnection;
28+
}
29+
30+
/**
31+
* @inheritdoc
32+
*/
33+
public function get($mainTableName, $gridTableName)
34+
{
35+
$lastUpdatedAt = $this->getLastUpdatedAtValue($gridTableName);
36+
$select = $this->getConnection()->select()
37+
->from($this->getConnection()->getTableName($mainTableName), ['entity_id'])
38+
->where('updated_at >= ?', $lastUpdatedAt);
39+
40+
return $this->getConnection()->fetchAll($select, [], \Zend_Db::FETCH_COLUMN);
41+
}
42+
43+
/**
44+
* Returns update time of the last row in the grid.
45+
*
46+
* @param string $gridTableName
47+
* @return string
48+
*/
49+
private function getLastUpdatedAtValue($gridTableName)
50+
{
51+
$select = $this->getConnection()->select()
52+
->from($this->getConnection()->getTableName($gridTableName), ['updated_at'])
53+
->order('updated_at DESC')
54+
->limit(1);
55+
$row = $this->getConnection()->fetchRow($select);
56+
57+
return isset($row['updated_at']) ? $row['updated_at'] : '0000-00-00 00:00:00';
58+
}
59+
60+
/**
61+
* @return \Magento\Framework\DB\Adapter\AdapterInterface
62+
*/
63+
private function getConnection()
64+
{
65+
return $this->resourceConnection->getConnection('sales');
66+
}
67+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Test\Unit\Model\ResourceModel\Provider;
7+
8+
use Magento\Framework\ObjectManager\TMap;
9+
use Magento\Framework\ObjectManager\TMapFactory;
10+
use Magento\Sales\Model\ResourceModel\Provider\IdListProviderComposite;
11+
use Magento\Sales\Model\ResourceModel\Provider\IdListProviderInterface;
12+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
13+
14+
/**
15+
* Class IdListProviderCompositeTest
16+
*/
17+
class IdListProviderCompositeTest extends \PHPUnit_Framework_TestCase
18+
{
19+
public function testGetEmpty()
20+
{
21+
/** @var TMapFactory|MockObject $tMapFactory */
22+
$tMapFactory = $this->getMockBuilder(TMapFactory::class)
23+
->disableOriginalConstructor()
24+
->setMethods(['create'])
25+
->getMock();
26+
$tMap = $this->getMockBuilder(TMap::class)
27+
->disableOriginalConstructor()
28+
->getMock();
29+
30+
$tMapFactory->expects(static::once())
31+
->method('create')
32+
->with(
33+
[
34+
'array' => [],
35+
'type' => IdListProviderInterface::class
36+
]
37+
)
38+
->willReturn($tMap);
39+
$tMap->expects(static::once())
40+
->method('getIterator')
41+
->willReturn(new \ArrayIterator([]));
42+
43+
$provider = new IdListProviderComposite($tMapFactory, []);
44+
static::assertEquals([], $provider->get('main_table', 'grid_table'));
45+
}
46+
47+
/**
48+
* @covers \Magento\Sales\Model\ResourceModel\Provider\IdListProviderComposite::get
49+
*/
50+
public function testGet()
51+
{
52+
/** @var TMapFactory|MockObject $tMapFactory */
53+
$tMapFactory = $this->getMockBuilder(TMapFactory::class)
54+
->disableOriginalConstructor()
55+
->setMethods(['create'])
56+
->getMock();
57+
$tMap = $this->getMockBuilder(TMap::class)
58+
->disableOriginalConstructor()
59+
->getMock();
60+
61+
$provider1 = $this->getMockBuilder(IdListProviderInterface::class)
62+
->getMockForAbstractClass();
63+
$provider1->expects(static::once())
64+
->method('get')
65+
->willReturn([1, 2]);
66+
67+
$provider2 = $this->getMockBuilder(IdListProviderInterface::class)
68+
->getMockForAbstractClass();
69+
$provider2->expects(static::once())
70+
->method('get')
71+
->willReturn([3, 4]);
72+
73+
$tMapFactory->expects(static::once())
74+
->method('create')
75+
->with(
76+
[
77+
'array' => [
78+
'provider1' => IdListProviderInterface::class,
79+
'provider2' => IdListProviderInterface::class
80+
],
81+
'type' => IdListProviderInterface::class
82+
]
83+
)
84+
->willReturn($tMap);
85+
$tMap->expects(static::once())
86+
->method('getIterator')
87+
->willReturn(new \ArrayIterator([$provider1, $provider2]));
88+
89+
$provider = new IdListProviderComposite(
90+
$tMapFactory,
91+
[
92+
'provider1' => IdListProviderInterface::class,
93+
'provider2' => IdListProviderInterface::class,
94+
]
95+
);
96+
97+
static::assertEquals([1, 2, 3, 4], $provider->get('main_table', 'grid_table'));
98+
}
99+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@
113113
<preference for="Magento\Sales\Model\Order\Creditmemo\NotifierInterface" type="Magento\Sales\Model\Order\Creditmemo\Notifier"/>
114114
<preference for="Magento\Sales\Api\RefundOrderInterface" type="Magento\Sales\Model\RefundOrder"/>
115115
<preference for="Magento\Sales\Api\RefundInvoiceInterface" type="Magento\Sales\Model\RefundInvoice"/>
116+
<preference for="Magento\Sales\Model\ResourceModel\Provider\IdListProviderInterface" type="Magento\Sales\Model\ResourceModel\Provider\IdListProviderComposite" />
117+
<type name="Magento\Sales\Model\ResourceModel\Provider\IdListProviderComposite">
118+
<arguments>
119+
<argument name="providers" xsi:type="array">
120+
<item name="default" xsi:type="string">Magento\Sales\Model\ResourceModel\Provider\UpdatedIdListProvider</item>
121+
</argument>
122+
</arguments>
123+
</type>
116124
<type name="Magento\Sales\Model\ResourceModel\Report" shared="false"/>
117125
<type name="Magento\Sales\Model\Order\Pdf\Config\Reader">
118126
<arguments>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Model\ResourceModel;
7+
8+
/**
9+
* Class GridTest
10+
*/
11+
class GridTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var \Magento\Sales\Model\ResourceModel\Grid
15+
*/
16+
private $resourceModel;
17+
18+
/**
19+
* @var \Magento\Framework\ObjectManagerInterface
20+
*/
21+
private $objectManager;
22+
23+
protected function setUp()
24+
{
25+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
26+
$this->resourceModel = $this->objectManager->create('Magento\Sales\Model\ResourceModel\Order\Grid');
27+
}
28+
29+
/**
30+
* Tests asynchronous insertion of the new entity into order grid.
31+
*
32+
* @magentoDataFixture Magento/Sales/_files/order_async.php
33+
*/
34+
public function testRefreshByScheduleAsyncModeSuccess()
35+
{
36+
$this->resourceModel->refreshBySchedule();
37+
$this->assertNotEmpty($this->getOrderGridItemList());
38+
}
39+
40+
/**
41+
* Tests failing of asynchronous insertion new entity into order grid.
42+
*
43+
* @magentoDataFixture Magento/Sales/_files/order_async.php
44+
*/
45+
public function testRefreshByScheduleAsyncModeFail()
46+
{
47+
$this->assertEmpty($this->getOrderGridItemList());
48+
}
49+
50+
/**
51+
* Tests synchronous insertion of the new entity into order grid.
52+
*
53+
* @magentoDataFixture Magento/Sales/_files/order.php
54+
*/
55+
public function testRefreshByScheduleSyncModeSuccess()
56+
{
57+
$this->assertNotEmpty($this->getOrderGridItemList());
58+
}
59+
60+
/**
61+
* Returns value of signifyd_guarantee_status column from sales order grid
62+
*
63+
* @return string|null
64+
*/
65+
private function getOrderGridItemList()
66+
{
67+
/** @var \Magento\Sales\Model\ResourceModel\Order\Grid\Collection $orderGridCollection */
68+
$orderGridCollection = $this->objectManager->get(
69+
\Magento\Sales\Model\ResourceModel\Order\Grid\Collection::class
70+
);
71+
72+
return $orderGridCollection->addFilter('increment_id', '100000001')->getItems();
73+
}
74+
}

0 commit comments

Comments
 (0)