Skip to content

Commit 53384ce

Browse files
committed
MAGETWO-65420: Update reports definitions for the Advanced Reporting service
1 parent 34f90dd commit 53384ce

File tree

6 files changed

+261
-25
lines changed

6 files changed

+261
-25
lines changed

app/code/Magento/Analytics/ReportXml/DB/ColumnsResolver.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace Magento\Analytics\ReportXml\DB;
88

9+
use Magento\Framework\DB\Sql\JsonSerializableExpression;
10+
911
/**
1012
* Class ColumnsResolver
1113
*
@@ -51,7 +53,7 @@ public function getColumns(SelectBuilder $selectBuilder, $entityConfig)
5153
if (isset($attributeData['distinct']) && $attributeData['distinct'] == true) {
5254
$prefix = ' DISTINCT ';
5355
}
54-
$expression = new \Zend_Db_Expr(
56+
$expression = new JsonSerializableExpression(
5557
strtoupper($attributeData['function']) . '(' . $prefix . $tableAlias . '.' . $columnName . ')'
5658
);
5759
} else {

app/code/Magento/Analytics/ReportXml/SelectHydrator.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Magento\Framework\DB\Select;
1010
use Magento\Framework\App\ResourceConnection;
11+
use Magento\Framework\ObjectManagerInterface;
1112

1213
/**
1314
* Class SelectHydrator
@@ -45,15 +46,22 @@ class SelectHydrator
4546
private $resourceConnection;
4647

4748
/**
48-
* SelectHydrator constructor.
49+
* @var ObjectManagerInterface
50+
*/
51+
private $objectManager;
52+
53+
/**
4954
* @param ResourceConnection $resourceConnection
55+
* @param ObjectManagerInterface $objectManager
5056
* @param array $selectParts
5157
*/
5258
public function __construct(
5359
ResourceConnection $resourceConnection,
60+
ObjectManagerInterface $objectManager,
5461
$selectParts = []
5562
) {
5663
$this->resourceConnection = $resourceConnection;
64+
$this->objectManager = $objectManager;
5765
$this->selectParts = $selectParts;
5866
}
5967

@@ -88,9 +96,48 @@ public function extract(Select $select)
8896
public function recreate(array $selectParts)
8997
{
9098
$select = $this->resourceConnection->getConnection()->select();
99+
100+
$select = $this->processColumns($select, $selectParts);
101+
91102
foreach ($selectParts as $partName => $partValue) {
92103
$select->setPart($partName, $partValue);
93104
}
105+
106+
return $select;
107+
}
108+
109+
/**
110+
* Process COLUMNS part values and add this part into select.
111+
*
112+
* If each column contains information about select expression
113+
* an object with the type of this expression going to be created and assigned to this column.
114+
*
115+
* @param Select $select
116+
* @param array $selectParts
117+
* @return Select
118+
*/
119+
private function processColumns(Select $select, array &$selectParts)
120+
{
121+
if (!empty($selectParts[Select::COLUMNS]) && is_array($selectParts[Select::COLUMNS])) {
122+
$part = [];
123+
124+
foreach ($selectParts[Select::COLUMNS] as $columnEntry) {
125+
list($correlationName, $column, $alias) = $columnEntry;
126+
if (is_array($column) && !empty($column['class'])) {
127+
$expression = $this->objectManager->create(
128+
$column['class'],
129+
isset($column['arguments']) ? $column['arguments'] : []
130+
);
131+
$part[] = [$correlationName, $expression, $alias];
132+
} else {
133+
$part[] = $columnEntry;
134+
}
135+
}
136+
137+
$select->setPart(Select::COLUMNS, $part);
138+
unset($selectParts[Select::COLUMNS]);
139+
}
140+
94141
return $select;
95142
}
96143
}

app/code/Magento/Analytics/Test/Unit/ReportXml/DB/ColumnsResolverTest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Magento\Analytics\ReportXml\DB\NameResolver;
99
use Magento\Analytics\ReportXml\DB\ColumnsResolver;
1010
use Magento\Analytics\ReportXml\DB\SelectBuilder;
11+
use Magento\Framework\DB\Sql\JsonSerializableExpression;
1112

1213
/**
1314
* Class ColumnsResolverTest
@@ -51,12 +52,12 @@ public function testGetColumnsWithoutAttributes()
5152
}
5253

5354
/**
54-
* @dataProvider dataProvider
55+
* @dataProvider getColumnsDataProvider
5556
*/
5657
public function testGetColumns($expression, $attributeData)
5758
{
5859
$columnAlias = 'fn';
59-
$expr = new \Zend_Db_Expr($expression);
60+
$expr = new JsonSerializableExpression($expression);
6061
$expectedResult = [$columnAlias => $expr];
6162
$columns = [$columnAlias => 'name'];
6263
$entityConfig['attribute'] = ['attribute1' => $attributeData];
@@ -91,7 +92,10 @@ public function testGetColumns($expression, $attributeData)
9192
);
9293
}
9394

94-
public function dataProvider()
95+
/**
96+
* @return array
97+
*/
98+
public function getColumnsDataProvider()
9599
{
96100
return [
97101
'TestWithFunction' =>

app/code/Magento/Analytics/Test/Unit/ReportXml/SelectHydratorTest.php

Lines changed: 175 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use Magento\Framework\App\ResourceConnection;
1010
use Magento\Framework\DB\Adapter\AdapterInterface;
1111
use Magento\Framework\DB\Select;
12+
use Magento\Framework\DB\Sql\JsonSerializableExpression;
13+
use Magento\Framework\ObjectManagerInterface;
14+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
1215

1316
class SelectHydratorTest extends \PHPUnit_Framework_TestCase
1417
{
@@ -32,6 +35,21 @@ class SelectHydratorTest extends \PHPUnit_Framework_TestCase
3235
*/
3336
private $selectMock;
3437

38+
/**
39+
* @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
40+
*/
41+
private $objectManagerMock;
42+
43+
/**
44+
* @var JsonSerializableExpression|\PHPUnit_Framework_MockObject_MockObject
45+
*/
46+
private $expressionMock;
47+
48+
/**
49+
* @var ObjectManagerHelper
50+
*/
51+
private $objectManagerHelper;
52+
3553
/**
3654
* @return void
3755
*/
@@ -49,7 +67,19 @@ protected function setUp()
4967
->disableOriginalConstructor()
5068
->getMock();
5169

52-
$this->selectHydrator = new SelectHydrator($this->resourceConnectionMock);
70+
$this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class)
71+
->disableOriginalConstructor()
72+
->getMock();
73+
74+
$this->objectManagerHelper = new ObjectManagerHelper($this);
75+
76+
$this->selectHydrator = $this->objectManagerHelper->getObject(
77+
SelectHydrator::class,
78+
[
79+
'resourceConnection' => $this->resourceConnectionMock,
80+
'objectManager' => $this->objectManagerMock,
81+
]
82+
);
5383
}
5484

5585
public function testExtract()
@@ -79,35 +109,160 @@ public function testExtract()
79109
$this->assertEquals($this->selectHydrator->extract($this->selectMock), $result);
80110
}
81111

82-
public function testRecreate()
112+
/**
113+
* @dataProvider recreateWithoutExpressionDataProvider
114+
* @param array $selectParts
115+
* @param array $parts
116+
* @param array $partValues
117+
*/
118+
public function testRecreateWithoutExpression($selectParts, $parts, $partValues)
83119
{
84120
$this->resourceConnectionMock->expects($this->once())
85121
->method('getConnection')
86122
->willReturn($this->connectionMock);
87123
$this->connectionMock->expects($this->once())
88124
->method('select')
89125
->willReturn($this->selectMock);
90-
$parts =
91-
[
92-
Select::DISTINCT,
93-
Select::COLUMNS,
94-
Select::UNION,
95-
Select::FROM,
96-
Select::WHERE,
97-
Select::GROUP,
98-
Select::HAVING,
99-
Select::ORDER,
100-
Select::LIMIT_COUNT,
101-
Select::LIMIT_OFFSET,
102-
Select::FOR_UPDATE
103-
];
104-
$selectParts = [];
105126
foreach ($parts as $key => $part) {
106127
$this->selectMock->expects($this->at($key))
107128
->method('setPart')
108-
->with($part, 'part' . $key);
109-
$selectParts[$part] = 'part' . $key;
129+
->with($part, $partValues[$key]);
110130
}
111-
$this->selectHydrator->recreate($selectParts);
131+
132+
$this->assertSame($this->selectMock, $this->selectHydrator->recreate($selectParts));
133+
}
134+
135+
/**
136+
* @return array
137+
*/
138+
public function recreateWithoutExpressionDataProvider()
139+
{
140+
return [
141+
'Select without expressions' => [
142+
[
143+
Select::COLUMNS => [
144+
[
145+
'table_name',
146+
'field_name',
147+
'alias',
148+
],
149+
[
150+
'table_name',
151+
'field_name_2',
152+
'alias_2',
153+
],
154+
]
155+
],
156+
[Select::COLUMNS],
157+
[[
158+
[
159+
'table_name',
160+
'field_name',
161+
'alias',
162+
],
163+
[
164+
'table_name',
165+
'field_name_2',
166+
'alias_2',
167+
],
168+
]],
169+
],
170+
];
171+
}
172+
173+
/**
174+
* @dataProvider recreateWithExpressionDataProvider
175+
* @param array $selectParts
176+
* @param array $parts
177+
* @param array $partValues
178+
* @param array $mocks
179+
*/
180+
public function testRecreateWithExpression($selectParts, $parts, $partValues, $mocks = [])
181+
{
182+
/** data provider executes in isolation so all mocks have to be set in the test */
183+
foreach ($mocks as $mockName => $mockObject) {
184+
$this->{$mockName} = $mockObject;
185+
}
186+
187+
$checkClassName = function ($value) {
188+
return is_string($value);
189+
};
190+
191+
$checkArguments = function ($value) {
192+
return is_array($value);
193+
};
194+
195+
$this->objectManagerMock
196+
->expects($this->once())
197+
->method('create')
198+
->with($this->callback($checkClassName), $this->callback($checkArguments))
199+
->willReturn($this->expressionMock);
200+
$this->resourceConnectionMock
201+
->expects($this->once())
202+
->method('getConnection')
203+
->with()
204+
->willReturn($this->connectionMock);
205+
$this->connectionMock
206+
->expects($this->once())
207+
->method('select')
208+
->with()
209+
->willReturn($this->selectMock);
210+
foreach ($parts as $key => $part) {
211+
$this->selectMock->expects($this->at($key))
212+
->method('setPart')
213+
->with($part, $partValues[$key]);
214+
}
215+
216+
$this->assertSame($this->selectMock, $this->selectHydrator->recreate($selectParts));
217+
}
218+
219+
/**
220+
* @return array
221+
*/
222+
public function recreateWithExpressionDataProvider()
223+
{
224+
$expressionMock = $this->getMockBuilder(JsonSerializableExpression::class)
225+
->disableOriginalConstructor()
226+
->getMock();
227+
228+
return [
229+
'Select without expressions' => [
230+
'Parts' => [
231+
Select::COLUMNS => [
232+
[
233+
'table_name',
234+
'field_name',
235+
'alias',
236+
],
237+
[
238+
'table_name',
239+
[
240+
'class' => 'Some_class',
241+
'arguments' => [
242+
'expression' => ['some(expression)']
243+
]
244+
],
245+
'alias_2',
246+
],
247+
]
248+
],
249+
'Parts names' => [Select::COLUMNS],
250+
'Assembled parts' => [[
251+
[
252+
'table_name',
253+
'field_name',
254+
'alias',
255+
],
256+
[
257+
'table_name',
258+
$expressionMock,
259+
'alias_2',
260+
],
261+
]],
262+
'Mocks' => [
263+
'expressionMock' => $expressionMock
264+
]
265+
],
266+
];
112267
}
113268
}

app/code/Magento/Analytics/etc/reports.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
<xs:enumeration value="max" />
7777
<xs:enumeration value="avg" />
7878
<xs:enumeration value="min" />
79+
<xs:enumeration value="sha1" />
7980
</xs:restriction>
8081
</xs:simpleType>
8182
<xs:simpleType name="glueType">

0 commit comments

Comments
 (0)