1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
<?php
/**
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\DataTable\Filter;
use Piwik\DataTable\BaseFilter;
use Piwik\DataTable\Simple;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Piwik;
use Piwik\Tracker\GoalManager;
/**
* Replaces column names in each row of a table using an array that maps old column
* names new ones.
*
* If no mapping is provided, this column will use one that maps index metric names
* (which are integers) with their string column names. In the database, reports are
* stored with integer metric names because it results in blobs that take up less space.
* When loading the reports, the column names must be replaced, which is handled by this
* class. (See {@link Piwik\Metrics} for more information about integer metric names.)
*
* **Basic example**
*
* // filter use in a plugin's API method
* public function getMyReport($idSite, $period, $date, $segment = false, $expanded = false)
* {
* $dataTable = Archive::getDataTableFromArchive('MyPlugin_MyReport', $idSite, $period, $date, $segment, $expanded);
* $dataTable->queueFilter('ReplaceColumnNames');
* return $dataTable;
* }
*
* @api
*/
class ReplaceColumnNames extends BaseFilter
{
protected $mappingToApply;
/**
* Constructor.
*
* @param DataTable $table The table that will be eventually filtered.
* @param array|null $mappingToApply The name mapping to apply. Must map old column names
* with new ones, eg,
*
* array('OLD_COLUMN_NAME' => 'NEW_COLUMN NAME',
* 'OLD_COLUMN_NAME2' => 'NEW_COLUMN NAME2')
*
* If null, {@link Piwik\Metrics::$mappingFromIdToName} is used.
*/
public function __construct($table, $mappingToApply = null)
{
parent::__construct($table);
$this->mappingToApply = Metrics::$mappingFromIdToName;
if (!is_null($mappingToApply)) {
$this->mappingToApply = $mappingToApply;
}
}
/**
* See {@link ReplaceColumnNames}.
*
* @param DataTable $table
*/
public function filter($table)
{
if ($table instanceof Simple) {
$this->filterSimple($table);
} else {
$this->filterTable($table);
}
}
/**
* @param DataTable $table
*/
protected function filterTable($table)
{
foreach ($table->getRows() as $key => $row) {
$oldColumns = $row->getColumns();
$newColumns = $this->getRenamedColumns($oldColumns);
$row->setColumns($newColumns);
$this->filterSubTable($row);
}
}
/**
* @param Simple $table
*/
protected function filterSimple(Simple $table)
{
foreach ($table->getRows() as $row) {
$columns = array_keys($row->getColumns());
foreach ($columns as $column) {
$newName = $this->getRenamedColumn($column);
if ($newName) {
$row->renameColumn($column, $newName);
}
}
}
}
protected function getRenamedColumn($column)
{
$newName = false;
if (isset($this->mappingToApply[$column])
&& $this->mappingToApply[$column] != $column
) {
$newName = $this->mappingToApply[$column];
}
return $newName;
}
/**
* Checks the given columns and renames them if required
*
* @param array $columns
* @return array
*/
protected function getRenamedColumns($columns)
{
$newColumns = array();
foreach ($columns as $columnName => $columnValue) {
$renamedColumn = $this->getRenamedColumn($columnName);
if ($renamedColumn) {
if ($renamedColumn == 'goals') {
$columnValue = $this->flattenGoalColumns($columnValue);
}
// If we happen to rename a column to a name that already exists,
// sum both values in the column. This should really not happen, but
// we introduced in 1.1 a new dataTable indexing scheme for Actions table, and
// could end up with both strings and their int indexes counterpart in a monthly/yearly dataTable
// built from DataTable with both formats
if (isset($newColumns[$renamedColumn])) {
$columnValue += $newColumns[$renamedColumn];
}
$columnName = $renamedColumn;
}
$newColumns[$columnName] = $columnValue;
}
return $newColumns;
}
/**
* @param $columnValue
* @return array
*/
protected function flattenGoalColumns($columnValue)
{
$newSubColumns = array();
foreach ($columnValue as $idGoal => $goalValues) {
$mapping = Metrics::$mappingFromIdToNameGoal;
if ($idGoal == GoalManager::IDGOAL_CART) {
$idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART;
} elseif ($idGoal == GoalManager::IDGOAL_ORDER) {
$idGoal = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER;
}
foreach ($goalValues as $id => $goalValue) {
$subColumnName = $mapping[$id];
$newSubColumns['idgoal=' . $idGoal][$subColumnName] = $goalValue;
}
}
return $newSubColumns;
}
}
|