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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
|
<?php
// TODO clean this unit should'nt read the requests parameters (via getRequestVar)
class Piwik_View_DataTable
{
protected $dataTableTemplate = null;
protected $currentControllerAction;
protected $moduleNameAndMethod;
protected $actionToLoadTheSubTable;
public $dataTable; // data table
public $arrayDataTable; // phpArray
// do we need all the children of the datatables?
protected $recursiveDataTableLoad = false;
protected $JSsearchBox = true;
protected $JSoffsetInformation = true;
protected $JSexcludeLowPopulation = true;
protected $JSsortEnabled = true;
protected $mainAlreadyExecuted = false;
protected $columnsToDisplay = array();
protected $variablesDefault = array();
const DEFAULT_COLUMN_EXCLUDE_LOW_POPULATION = 2;
static public function factory( $type = null )
{
if(is_null($type))
{
$type = Piwik_Common::getRequestVar('viewDataTable', 'table', 'string');
}
switch($type)
{
case 'cloud':
require_once "View/DataTableCloud.php";
return new Piwik_View_DataTableCloud;
break;
case 'table':
default:
return new Piwik_View_DataTable;
break;
}
}
function __construct()
{
}
function init( $currentControllerAction,
$moduleNameAndMethod,
$actionToLoadTheSubTable = null)
{
$this->currentControllerAction = $currentControllerAction;
$this->moduleNameAndMethod = $moduleNameAndMethod;
$this->actionToLoadTheSubTable = $actionToLoadTheSubTable;
$this->dataTableTemplate = 'UserSettings/templates/datatable.tpl';
$this->idSubtable = Piwik_Common::getRequestVar('idSubtable', false,'int');
$this->method = $moduleNameAndMethod;
$this->variablesDefault['filter_excludelowpop_default'] = 'false';
$this->variablesDefault['filter_excludelowpop_value_default'] = 'false';
}
function getView()
{
return $this->view;
}
public function setTemplate( $tpl )
{
$this->dataTableTemplate = $tpl;
}
public function main()
{
if($this->mainAlreadyExecuted)
{
return;
}
$this->mainAlreadyExecuted = true;
// $i=0;while($i<1500000){ $j=$i*$i;$i++;}
$this->loadDataTableFromAPI();
// We apply a filter to the DataTable, decoding the label column (useful for keywords for example)
$filter = new Piwik_DataTable_Filter_ColumnCallbackReplace(
$this->dataTable,
'label',
'urldecode'
);
$view = new Piwik_View($this->dataTableTemplate);
$view->id = $this->getUniqIdTable();
// We get the PHP array converted from the DataTable
$phpArray = $this->getPHPArrayFromDataTable();
$view->arrayDataTable = $phpArray;
$view->method = $this->method;
$columns = $this->getColumnsToDisplay($phpArray);
$view->dataTableColumns = $columns;
$nbColumns = count($columns);
// case no data in the array we use the number of columns set to be displayed
if($nbColumns == 0)
{
$nbColumns = count($this->columnsToDisplay);
}
$view->nbColumns = $nbColumns;
$view->javascriptVariablesToSet
= $this->getJavascriptVariablesToSet();
$this->view = $view;
}
protected function getUniqIdTable()
{
// the $uniqIdTable variable is used as the DIV ID in the rendered HTML
// we use the current Controller action name as it is supposed to be unique in the rendered page
$uniqIdTable = $this->currentControllerAction;
// if we request a subDataTable the $this->currentControllerAction DIV ID is already there in the page
// we make the DIV ID really unique by appending the ID of the subtable requested
if( $this->idSubtable != false)
{
$uniqIdTable = 'subDataTable_' . $this->idSubtable;
}
return $uniqIdTable;
}
public function setColumnsToDisplay( $arrayIds)
{
$this->columnsToDisplay = $arrayIds;
}
protected function isColumnToDisplay( $idColumn )
{
// we return true
// - we didn't set any column to display (means we display all the columns)
// - the column has been set as to display
if( count($this->columnsToDisplay) == 0
|| in_array($idColumn, $this->columnsToDisplay))
{
return true;
}
return false;
}
protected function getColumnsToDisplay($phpArray)
{
$dataTableColumns = array();
if(count($phpArray) > 0)
{
// build column information
$id = 0;
foreach($phpArray[0]['columns'] as $columnName => $row)
{
if( $this->isColumnToDisplay( $id, $columnName) )
{
$dataTableColumns[] = array('id' => $id, 'name' => $columnName);
}
$id++;
}
}
return $dataTableColumns;
}
protected function getDefaultOrCurrent( $nameVar )
{
if(isset($_REQUEST[$nameVar]))
{
return $_REQUEST[$nameVar];
}
$default = $this->getDefault($nameVar);
return $default;
}
protected function getDefault($nameVar)
{
if(!isset($this->variablesDefault[$nameVar]))
{
return false;
}
return $this->variablesDefault[$nameVar];
}
public function setSearchRecursive()
{
$this->variablesDefault['search_recursive'] = true;
}
public function setRecursiveLoadDataTableIfSearchingForPattern()
{
try{
$requestValue = Piwik_Common::getRequestVar('filter_column_recursive');
$requestValue = Piwik_Common::getRequestVar('filter_pattern_recursive');
// if the 2 variables are set we are searching for something.
// we have to load all the children subtables in this case
$this->recursiveDataTableLoad = true;
return true;
}
catch(Exception $e) {
$this->recursiveDataTableLoad = false;
return false;
}
}
public function setExcludeLowPopulation( $value = 30 )
{
$this->variablesDefault['filter_excludelowpop_default'] = 2;
$this->variablesDefault['filter_excludelowpop_value_default'] = $value;
$this->variablesDefault['filter_excludelowpop'] = 2;
$this->variablesDefault['filter_excludelowpop_value'] = $value;
}
public function setDefaultLimit( $limit )
{
$this->variablesDefault['filter_limit'] = $limit;
}
public function setSortedColumn( $columnId, $order = 'desc')
{
$this->variablesDefault['filter_sort_column']= $columnId;
$this->variablesDefault['filter_sort_order']= $order;
}
public function disableSort()
{
$this->JSsortEnabled = 'false';
}
public function getSort()
{
return $this->JSsortEnabled;
}
public function disableOffsetInformation()
{
$this->JSoffsetInformation = 'false';
}
public function getOffsetInformation()
{
return $this->JSoffsetInformation;
}
public function disableSearchBox()
{
$this->JSsearchBox = 'false';
}
public function getSearchBox()
{
return $this->JSsearchBox;
}
public function disableExcludeLowPopulation()
{
$this->JSexcludeLowPopulation = 'false';
}
public function getExcludeLowPopulation()
{
return $this->JSexcludeLowPopulation;
}
protected function getJavascriptVariablesToSet( )
{
// build javascript variables to set
$javascriptVariablesToSet = array();
$genericFilters = Piwik_API_Request::getGenericFiltersInformation();
foreach($genericFilters as $filter)
{
foreach($filter as $filterVariableName => $filterInfo)
{
// if there is a default value for this filter variable we set it
// so that it is propagated to the javascript
if(isset($filterInfo[1]))
{
$javascriptVariablesToSet[$filterVariableName] = $filterInfo[1];
// we set the default specified column and Order to sort by
// when this javascript variable is not set already
// for example during an AJAX call this variable will be set in the URL
// so this will not be executed ( and the default sorted not be used as the sorted column might have changed in the meanwhile)
if( false !== ($defaultValue = $this->getDefault($filterVariableName)))
{
$javascriptVariablesToSet[$filterVariableName] = $defaultValue;
}
}
}
}
// var_dump($javascriptVariablesToSet);exit;
//TODO check security of printing javascript variables; inject some JS code here??
foreach($_GET as $name => $value)
{
try{
$requestValue = Piwik_Common::getRequestVar($name);
}
catch(Exception $e) {
$requestValue = '';
}
$javascriptVariablesToSet[$name] = $requestValue;
}
// at this point there are some filters values we may have not set,
// case of the filter without default values and parameters set directly in this class
// for example setExcludeLowPopulation
// we go through all the $this->variablesDefault array and set the variables not set yet
foreach($this->variablesDefault as $name => $value)
{
if(!isset($javascriptVariablesToSet[$name] ))
{
$javascriptVariablesToSet[$name] = $value;
}
}
$javascriptVariablesToSet['action'] = $this->currentControllerAction;
if(!is_null($this->actionToLoadTheSubTable))
{
$javascriptVariablesToSet['actionToLoadTheSubTable'] = $this->actionToLoadTheSubTable;
}
// var_dump($this->variablesDefault);
// var_dump($javascriptVariablesToSet); exit;
$javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter();
$javascriptVariablesToSet['show_search'] = $this->getSearchBox();
$javascriptVariablesToSet['show_offset_information'] = $this->getOffsetInformation();
$javascriptVariablesToSet['show_exclude_low_population'] = $this->getExcludeLowPopulation();
$javascriptVariablesToSet['enable_sort'] = $this->getSort();
return $javascriptVariablesToSet;
}
protected function loadDataTableFromAPI( $idSubtable = false)
{
if($idSubtable === false)
{
$idSubtable = $this->idSubtable;
}
// we prepare the string to give to the API Request
// we setup the method and format variable
// - we request the method to call to get this specific DataTable
// - the format = original specifies that we want to get the original DataTable structure itself, not rendered
$requestString = 'method='.$this->moduleNameAndMethod
.'&format=original'
;
if( $this->recursiveDataTableLoad )
{
$requestString .= '&expanded=1';
}
// if a subDataTable is requested we add the variable to the API request string
if( $idSubtable != false)
{
$requestString .= '&this->idSubtable='.$idSubtable;
}
$toSetEventually = array(
'filter_limit',
'filter_sort_column',
'filter_sort_order',
'filter_excludelowpop',
'filter_excludelowpop_value',
);
foreach($toSetEventually as $varToSet)
{
$value = $this->getDefaultOrCurrent($varToSet);
if( false !== $value )
{
$requestString .= '&'.$varToSet.'='.$value;
}
}
// We finally make the request to the API
$request = new Piwik_API_Request($requestString);
// and get the DataTable structure
$dataTable = $request->process();
// echo $dataTable;exit;
$this->dataTable = $dataTable;
}
protected function getPHPArrayFromDataTable( )
{
$renderer = Piwik_DataTable_Renderer::factory('php');
$renderer->setTable($this->dataTable);
$renderer->setSerialize( false );
$phpArray = $renderer->render();
return $phpArray;
}
}
|