Newer
Older
mattpiwik
a validé
<?php
/**
* Piwik - Open source web analytics
mattpiwik
a validé
* @link http://piwik.org
mattpiwik
a validé
*/
/**
* This class is used to load (from the API) and customize the output of a given DataTable.
* The main() method will create an object implementing Piwik_View_Interface
mattpiwik
a validé
* You can customize the dataTable using the disable* methods.
benakamoorthi
a validé
* You can also customize the dataTable rendering using row metadata:
* - 'html_label_prefix': If this metadata is present on a row, it's contents will be prepended
* the label in the HTML output.
* - 'html_label_suffix': If this metadata is present on a row, it's contents will be appended
* after the label in the HTML output.
mattpiwik
a validé
* Example:
* In the Controller of the plugin VisitorInterest
* <pre>
* function getNumberOfVisitsPerVisitDuration( $fetch = false)
mattpiwik
a validé
* {
* $view = Piwik_ViewDataTable::factory( 'cloud' );
* $view->init( $this->pluginName, __FUNCTION__, 'VisitorInterest.getNumberOfVisitsPerVisitDuration' );
* $view->setColumnsToDisplay( array('label','nb_visits') );
* $view->disableSort();
* $view->disableExcludeLowPopulation();
* $view->disableOffsetInformation();
* return $this->renderView($view, $fetch);
* }
mattpiwik
a validé
* </pre>
mattpiwik
a validé
* @see factory() for all the available output (cloud tags, html table, pie chart, vertical bar chart)
mattpiwik
a validé
*/
abstract class Piwik_ViewDataTable
{
Benaka Moorthi
a validé
/**
* Cache for getAllReportDisplayProperties result.
*
* @var array
*/
public static $reportPropertiesCache = null;
/**
* Template file that will be loaded for this view.
* Usually set in the Piwik_ViewDataTable_*
*
* @var string eg. 'CoreHome/templates/cloud.twig'
*/
protected $dataTableTemplate = null;
/**
* Flag used to make sure the main() is only executed once
*
* @var bool
*/
protected $mainAlreadyExecuted = false;
/**
* Array of properties that are available in the view
* Used to store UI properties, eg. "show_footer", "show_search", etc.
*
* @var array
*/
protected $viewProperties = array();
Benaka Moorthi
a validé
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
/**
* If the current dataTable refers to a subDataTable (eg. keywordsBySearchEngineId for id=X) this variable is set to the Id
*
* @var bool|int
*/
protected $idSubtable = false;
/**
* DataTable loaded from the API for this ViewDataTable.
*
* @var Piwik_DataTable
*/
protected $dataTable = null;
/**
* List of filters to apply after the data has been loaded from the API
*
* @var array
*/
protected $queuedFilters = array();
/**
* List of filter to apply just before the 'Generic' filters
* These filters should delete rows from the table
* @var array
*/
protected $queuedFiltersPriority = array();
/**
* @see init()
* @var string
*/
protected $currentControllerAction;
/**
* @see init()
* @var string
*/
protected $currentControllerName;
/**
* This view should be an implementation of the Interface Piwik_View_Interface
* The $view object should be created in the main() method.
*
* @var Piwik_View_Interface
*/
protected $view = null;
Benaka Moorthi
a validé
Benaka Moorthi
a validé
* Default constructor.
Benaka Moorthi
a validé
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
public function __construct()
{
$this->viewProperties['show_goals'] = false;
$this->viewProperties['show_ecommerce'] = false;
$this->viewProperties['show_search'] = true;
$this->viewProperties['show_table'] = true;
$this->viewProperties['show_table_all_columns'] = true;
$this->viewProperties['show_all_views_icons'] = true;
$this->viewProperties['hide_all_views_icons'] = false;
$this->viewProperties['hide_annotations_view'] = true;
$this->viewProperties['show_bar_chart'] = true;
$this->viewProperties['show_pie_chart'] = true;
$this->viewProperties['show_tag_cloud'] = true;
$this->viewProperties['show_export_as_image_icon'] = false;
$this->viewProperties['show_export_as_rss_feed'] = true;
$this->viewProperties['show_exclude_low_population'] = true;
$this->viewProperties['show_offset_information'] = true;
$this->viewProperties['show_pagination_control'] = true;
$this->viewProperties['show_limit_control'] = false;
$this->viewProperties['show_footer'] = true;
$this->viewProperties['show_related_reports'] = true;
$this->viewProperties['exportLimit'] = Piwik_Config::getInstance()->General['API_datatable_default_limit'];
$this->viewProperties['highlight_summary_row'] = false;
$this->viewProperties['metadata'] = array();
$this->viewProperties['relatedReports'] = array();
$this->viewProperties['title'] = 'unknown';
$this->viewProperties['tooltip_metadata_name'] = false;
$this->viewProperties['enable_sort'] = true;
$this->viewProperties['disable_generic_filters'] = false;
$this->viewProperties['disable_queued_filters'] = false;
$this->viewProperties['keep_summary_row'] = false;
$this->viewProperties['filter_excludelowpop'] = false;
$this->viewProperties['filter_excludelowpop_value'] = false;
$this->viewProperties['filter_pattern'] = false;
$this->viewProperties['filter_column'] = false;
$this->viewProperties['filter_limit'] = false;
$this->viewProperties['filter_sort_column'] = false;
$this->viewProperties['filter_sort_order'] = false;
$this->viewProperties['custom_parameters'] = array();
$this->viewProperties['translations'] = array_merge(
Piwik_Metrics::getDefaultMetrics(),
Piwik_Metrics::getDefaultProcessedMetrics()
);
Benaka Moorthi
a validé
$this->viewProperties['request_parameters_to_modify'] = array();
Benaka Moorthi
a validé
$this->viewProperties['documentation'] = false;
$this->viewProperties['subtable_controller_action'] = false;
$this->viewProperties['datatable_css_class'] = $this->getDefaultDataTableCssClass();
$this->viewProperties['columns_to_display'] = array();
Benaka Moorthi
a validé
$columns = Piwik_Common::getRequestVar('columns', false);
if ($columns !== false) {
$this->viewProperties['columns_to_display'] = Piwik::getArrayFromApiParameter($columns);
array_unshift($this->viewProperties['columns_to_display'], 'label');
Benaka Moorthi
a validé
}
}
/**
* Method to be implemented by the ViewDataTable_*.
* This method should create and initialize a $this->view object @see Piwik_View_Interface
*
* @return mixed either prints the result or returns the output string
*/
abstract public function main();
/**
* Unique string ID that defines the format of the dataTable, eg. "pieChart", "table", etc.
*
* @return string
*/
abstract protected function getViewDataTableId();
/**
* Returns a Piwik_ViewDataTable_* object.
* By default it will return a ViewDataTable_Html
* If there is a viewDataTable parameter in the URL, a ViewDataTable of this 'viewDataTable' type will be returned.
* If defaultType is specified and if there is no 'viewDataTable' in the URL, a ViewDataTable of this $defaultType will be returned.
* If force is set to true, a ViewDataTable of the $defaultType will be returned in all cases.
*
* @param string $defaultType Any of these: table, cloud, graphPie, graphVerticalBar, graphEvolution, sparkline, generateDataChart*
* @return Piwik_ViewDataTable
*/
Benaka Moorthi
a validé
static public function factory($defaultType = null, $action = false)
Benaka Moorthi
a validé
if ($action !== false) {
$defaultProperties = self::getDefaultPropertiesForReport($action);
if (isset($defaultProperties['default_view_type'])) {
$defaultType = $defaultProperties['default_view_type'];
}
}
if ($defaultType === null) {
$defaultType = 'table';
}
Benaka Moorthi
a validé
$type = Piwik_Common::getRequestVar('viewDataTable', $defaultType, 'string');
switch ($type) {
case 'cloud':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_Cloud();
break;
case 'graphPie':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartPie();
break;
case 'graphVerticalBar':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartVerticalBar();
break;
case 'graphEvolution':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution();
break;
case 'sparkline':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_Sparkline();
break;
case 'tableAllColumns':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_HtmlTable_AllColumns();
break;
case 'tableGoals':
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_HtmlTable_Goals();
break;
case 'table':
default:
Benaka Moorthi
a validé
$result = new Piwik_ViewDataTable_HtmlTable();
break;
}
Benaka Moorthi
a validé
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
if ($action !== false) {
list($plugin, $controllerAction) = explode('.', $action);
$subtableAction = $controllerAction;
if (isset($defaultProperties['subtable_action'])) {
$subtableAction = $defaultProperties['subtable_action'];
}
$result->init($plugin, $controllerAction, $action, $subtableAction, $defaultProperties);
}
return $result;
}
/**
* Returns the list of view properties that can be overridden by query parameters.
*
* @return array
*/
public function getOverridableProperties()
{
return array(
'show_search',
'show_table',
'show_table_all_columns',
'show_all_views_icons',
'hide_all_views_icons',
'hide_annotations_view',
'show_barchart',
'show_piechart',
'show_tag_cloud',
'show_export_as_image_icon',
'show_export_as_rss_feed',
'show_exclude_low_population',
'show_offset_information',
'show_pagination_control',
'show_footer',
'show_related_reports',
'columns'
);
}
/**
* Returns the list of view properties that should be sent with the HTML response
* as JSON. These properties can be manipulated via the ViewDataTable UI.
*
* @return array
*/
public function getJavaScriptProperties()
{
return array(
'enable_sort',
'disable_generic_filters',
'disable_queued_filters',
'keep_summary_row',
'filter_excludelowpop',
'filter_excludelowpop_value',
'filter_pattern',
'filter_column',
'filter_limit',
'filter_sort_column',
'filter_sort_order',
);
}
/**
* Inits the object given the $currentControllerName, $currentControllerAction of
* the calling controller action, eg. 'Referers' 'getLongListOfKeywords'.
* The initialization also requires the $apiMethodToRequestDataTable of the API method
* to call in order to get the DataTable, eg. 'Referers.getKeywords'.
* The optional $controllerActionCalledWhenRequestSubTable defines the method name of the API to call when there is a idSubtable.
* This value would be used by the javascript code building the GET request to the API.
*
* Example:
* For the keywords listing, a click on the row loads the subTable of the Search Engines for this row.
* In this case $controllerActionCalledWhenRequestSubTable = 'getSearchEnginesFromKeywordId'.
* The GET request will hit 'Referers.getSearchEnginesFromKeywordId'.
*
* @param string $currentControllerName eg. 'Referers'
* @param string $currentControllerAction eg. 'getKeywords'
* @param string $apiMethodToRequestDataTable eg. 'Referers.getKeywords'
* @param string $controllerActionCalledWhenRequestSubTable eg. 'getSearchEnginesFromKeywordId'
*/
public function init($currentControllerName,
$currentControllerAction,
$apiMethodToRequestDataTable,
Benaka Moorthi
a validé
$controllerActionCalledWhenRequestSubTable = null,
$defaultProperties = array())
{
$this->currentControllerName = $currentControllerName;
$this->currentControllerAction = $currentControllerAction;
Benaka Moorthi
a validé
$this->viewProperties['subtable_controller_action'] = $controllerActionCalledWhenRequestSubTable;
$this->idSubtable = Piwik_Common::getRequestVar('idSubtable', false, 'int');
Benaka Moorthi
a validé
foreach ($defaultProperties as $name => $value) {
$this->setViewProperty($name, $value);
}
$queryParams = Piwik_Url::getArrayFromCurrentQueryString();
foreach ($this->getOverridableProperties() as $name) {
if (isset($queryParams[$name])) {
$this->setViewProperty($name, $queryParams[$name]);
}
}
$this->viewProperties['show_footer_icons'] = ($this->idSubtable == false);
Benaka Moorthi
a validé
$this->viewProperties['apiMethodToRequestDataTable'] = $apiMethodToRequestDataTable;
$this->viewProperties['report_id'] = $currentControllerName . '.' . $currentControllerAction;
$this->viewProperties['self_url'] = $this->getBaseReportUrl($currentControllerName, $currentControllerAction);
Benaka Moorthi
a validé
if (!Piwik_PluginsManager::getInstance()->isPluginActivated('Goals')) {
$this->viewProperties['show_goals'] = false;
}
// the exclude low population threshold value is sometimes obtained by requesting data.
// to avoid issuing unecessary requests when display properties are determined by metadata,
// we allow it to be a closure.
if (isset($this->viewProperties['filter_excludelowpop_value'])
&& $this->viewProperties['filter_excludelowpop_value'] instanceof Closure
) {
$function = $this->viewProperties['filter_excludelowpop_value'];
$this->viewProperties['filter_excludelowpop_value'] = $function();
}
Benaka Moorthi
a validé
$this->loadDocumentation();
Benaka Moorthi
a validé
/**
* Forces the View to use a given template.
* Usually the template to use is set in the specific ViewDataTable_*
* But some users may want to force this template to some other value
*
* @param string $tpl eg .'@MyPlugin/templateToUse'
*/
public function setTemplate($tpl)
{
$this->dataTableTemplate = $tpl;
}
/**
* Returns the View_Interface.
* You can then call render() on this object.
*
* @return Piwik_View_Interface
* @throws exception if the view object was not created
*/
public function getView()
{
if (is_null($this->view)) {
throw new Exception('The $this->view object has not been created.
mattpiwik
a validé
It should be created in the main() method of the Piwik_ViewDataTable_* subclass you are using.');
}
return $this->view;
}
public function getCurrentControllerAction()
{
return $this->currentControllerAction;
}
public function getCurrentControllerName()
{
return $this->currentControllerName;
}
public function getApiMethodToRequestDataTable()
{
Benaka Moorthi
a validé
return $this->viewProperties['apiMethodToRequestDataTable'];
}
public function getControllerActionCalledWhenRequestSubTable()
{
Benaka Moorthi
a validé
return $this->viewProperties['subtable_controller_action'];
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
}
/**
* Returns the DataTable loaded from the API
*
* @return Piwik_DataTable
* @throws exception if not yet defined
*/
public function getDataTable()
{
if (is_null($this->dataTable)) {
throw new Exception("The DataTable object has not yet been created");
}
return $this->dataTable;
}
/**
* To prevent calling an API multiple times, the DataTable can be set directly.
* It won't be loaded again from the API in this case
*
* @param $dataTable
* @return void $dataTable Piwik_DataTable
*/
public function setDataTable($dataTable)
{
$this->dataTable = $dataTable;
}
Benaka Moorthi
a validé
/**
* Returns the defaut view properties for a report, if any.
Benaka Moorthi
a validé
* Plugins can associate callbacks with the ViewDataTable.getReportDisplayProperties
* event to set the default properties of reports.
Benaka Moorthi
a validé
* @return array
*/
private static function getDefaultPropertiesForReport($apiAction)
{
Benaka Moorthi
a validé
$reportDisplayProperties = self::getAllReportDisplayProperties();
return isset($reportDisplayProperties[$apiAction]) ? $reportDisplayProperties[$apiAction] : array();
}
/**
* Returns the list of display properties for all available reports.
*
* @return array
*/
private static function getAllReportDisplayProperties()
{
if (self::$reportPropertiesCache === null) {
self::$reportPropertiesCache = array();
Piwik_PostEvent('ViewDataTable.getReportDisplayProperties', array(&self::$reportPropertiesCache));
}
return self::$reportPropertiesCache;
Benaka Moorthi
a validé
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
}
/**
* Sets a view property by name. This function handles special view properties
* like 'translations' & 'relatedReports' that store arrays.
*
* @param string $name
* @param mixed $value For array properties, $value can be a comma separated string.
*/
private function setViewProperty($name, $value)
{
if (isset($this->viewProperties[$name])
&& is_array($this->viewProperties[$name])
&& is_string($value)
) {
$value = Piwik::getArrayFromApiParameter($value);
}
if ($name == 'translations') {
$this->viewProperties[$name] = array_merge($this->viewProperties[$name], $value);
} else if ($name == 'relatedReports') {
$this->addRelatedReports($reportTitle = false, $value);
} else if ($name == 'filters') {
foreach ($value as $filterInfo) {
if (!is_array($filterInfo)) {
$this->queueFilter($filterInfo);
} else {
@list($filter, $params, $isPriority) = $filterInfo;
$this->queueFilter($filter, $params, $isPriority);
}
}
} else {
$this->viewProperties[$name] = $value;
}
}
/**
* Function called by the ViewDataTable objects in order to fetch data from the API.
* The function init() must have been called before, so that the object knows which API module and action to call.
* It builds the API request string and uses Piwik_API_Request to call the API.
* The requested Piwik_DataTable object is stored in $this->dataTable.
*/
protected function loadDataTableFromAPI()
{
if (!is_null($this->dataTable)) {
// data table is already there
// this happens when setDataTable has been used
return;
}
Benaka Moorthi
a validé
// we build the request (URL) to call the API
$requestArray = $this->getRequestArray();
// we make the request to the API
Benaka Moorthi
a validé
$request = new Piwik_API_Request($requestArray);
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
// and get the DataTable structure
$dataTable = $request->process();
$this->dataTable = $dataTable;
}
/**
* Checks that the API returned a normal DataTable (as opposed to DataTable_Array)
* @throws Exception
* @return void
*/
protected function checkStandardDataTable()
{
Piwik::checkObjectTypeIs($this->dataTable, array('Piwik_DataTable'));
}
/**
* Hook called after the dataTable has been loaded from the API
* Can be used to add, delete or modify the data freshly loaded
*
* @return bool
*/
protected function postDataTableLoadedFromAPI()
{
if (empty($this->dataTable)) {
return false;
}
// deal w/ table metadata
if ($this->dataTable instanceof Piwik_DataTable) {
$this->viewProperties['metadata'] = $this->dataTable->getAllTableMetadata();
if (isset($this->viewProperties['metadata'][Piwik_DataTable::ARCHIVED_DATE_METADATA_NAME])) {
$this->viewProperties['metadata'][Piwik_DataTable::ARCHIVED_DATE_METADATA_NAME] =
$this->makePrettyArchivedOnText();
}
}
// First, filters that delete rows
foreach ($this->queuedFiltersPriority as $filter) {
$filterName = $filter[0];
$filterParameters = $filter[1];
$this->dataTable->filter($filterName, $filterParameters);
}
if (!$this->areGenericFiltersDisabled()) {
// Second, generic filters (Sort, Limit, Replace Column Names, etc.)
Benaka Moorthi
a validé
$requestArray = $this->getRequestArray();
$request = Piwik_API_Request::getRequestArrayFromString($requestArray);
if ($this->viewProperties['enable_sort'] === false) {
$request['filter_sort_column'] = $request['filter_sort_order'] = '';
}
$genericFilter = new Piwik_API_DataTableGenericFilter($request);
$genericFilter->filter($this->dataTable);
}
if (!$this->areQueuedFiltersDisabled()) {
// Finally, apply datatable filters that were queued (should be 'presentation' filters that
// do not affect the number of rows)
foreach ($this->queuedFilters as $filter) {
$filterName = $filter[0];
$filterParameters = $filter[1];
$this->dataTable->filter($filterName, $filterParameters);
}
}
// default columns_to_display to label, nb_uniq_visitors/nb_visits if those columns exist in the
Benaka Moorthi
a validé
// dataset. otherwise, default to all columns in dataset.
if ($this->dataTable instanceof Piwik_DataTable) {
$columns = $this->dataTable->getColumns();
Benaka Moorthi
a validé
if (empty($this->viewProperties['columns_to_display'])) {
if ($this->dataTableColumnsContains($columns, array('nb_visits', 'nb_uniq_visitors'))) {
$columnsToDisplay = array('label');
// if unique visitors data is available, show it, otherwise just visits
if ($this->dataTableColumnsContains($columns, 'nb_uniq_visitors')) {
$columnsToDisplay[] = 'nb_uniq_visitors';
} else {
$columnsToDisplay[] = 'nb_visits';
}
} else {
Benaka Moorthi
a validé
$columnsToDisplay = $columns;
}
Benaka Moorthi
a validé
$this->viewProperties['columns_to_display'] = array_filter($columnsToDisplay);
}
Benaka Moorthi
a validé
$this->removeEmptyColumnsFromDisplay();
}
Benaka Moorthi
a validé
return true;
}
/**
* Returns true if generic filters have been disabled, false if otherwise.
*
* @return bool
*/
private function areGenericFiltersDisabled()
{
// if disable_generic_filters query param is set to '1', generic filters are disabled
if (Piwik_Common::getRequestVar('disable_generic_filters', '0', 'string') == 1) {
return true;
}
// if $this->disableGenericFilters() was called, generic filters are disabled
Benaka Moorthi
a validé
if (isset($this->viewProperties['disable_generic_filters'])
&& $this->viewProperties['disable_generic_filters'] === true
) {
return true;
}
return false;
}
/**
* Returns true if queued filters have been disabled, false if otherwise.
*
* @return bool
*/
private function areQueuedFiltersDisabled()
{
Benaka Moorthi
a validé
return isset($this->viewProperties['disable_queued_filters'])
&& $this->viewProperties['disable_queued_filters'];
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
}
/**
* Returns prettified and translated text that describes when a report was last updated.
*
* @return string
*/
private function makePrettyArchivedOnText()
{
$dateText = $this->viewProperties['metadata'][Piwik_DataTable::ARCHIVED_DATE_METADATA_NAME];
$date = Piwik_Date::factory($dateText);
$today = mktime(0, 0, 0);
if ($date->getTimestamp() > $today) {
$elapsedSeconds = time() - $date->getTimestamp();
$timeAgo = Piwik::getPrettyTimeFromSeconds($elapsedSeconds);
return Piwik_Translate('CoreHome_ReportGeneratedXAgo', $timeAgo);
}
$prettyDate = $date->getLocalized("%longYear%, %longMonth% %day%") . $date->toString('S');
return Piwik_Translate('CoreHome_ReportGeneratedOn', $prettyDate);
}
/**
* @return string URL to call the API, eg. "method=Referers.getKeywords&period=day&date=yesterday"...
*/
Benaka Moorthi
a validé
protected function getRequestArray()
Benaka Moorthi
a validé
// we prepare the array 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
Benaka Moorthi
a validé
$requestArray = array(
'method' => $this->viewProperties['apiMethodToRequestDataTable'],
'format' => 'original',
'disable_generic_filters' => Piwik_Common::getRequestVar('disable_generic_filters', 1, 'int')
);
$toSetEventually = array(
'filter_limit',
'keep_summary_row',
'filter_sort_column',
'filter_sort_order',
'filter_excludelowpop',
'filter_excludelowpop_value',
'filter_column',
'filter_pattern',
'disable_queued_filters',
);
foreach ($toSetEventually as $varToSet) {
$value = $this->getDefaultOrCurrent($varToSet);
if (false !== $value) {
Benaka Moorthi
a validé
$requestArray[$varToSet] = $value;
}
}
Benaka Moorthi
a validé
$segment = $this->getRawSegmentFromRequest();
if(!empty($segment)) {
Benaka Moorthi
a validé
$requestArray['segment'] = $segment;
Benaka Moorthi
a validé
Benaka Moorthi
a validé
$requestArray = array_merge($requestArray, $this->viewProperties['request_parameters_to_modify']);
Benaka Moorthi
a validé
Benaka Moorthi
a validé
return $requestArray;
/**
* @return array|bool
*/
static public function getRawSegmentFromRequest()
{
// we need the URL encoded segment parameter, we fetch it from _SERVER['QUERY_STRING'] instead of default URL decoded _GET
$segment = Piwik_Common::getRequestVar('segment', '', 'string');
if (!empty($segment)) {
if(!empty($request['segment'])) {
$segmentRaw = $request['segment'];
}
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
}
/**
* For convenience, the client code can call methods that are defined in a specific children class
* without testing the children class type, which would trigger an error with a different children class.
*
* Example:
* ViewDataTable/Html.php defines a setColumnsToDisplay(). The client code calls this methods even if
* the ViewDataTable object is a ViewDataTable_Cloud instance (he doesn't know because of the factory()).
* But ViewDataTable_Cloud doesn't define the setColumnsToDisplay() method.
* Because we don't want to force users to test for the object type we simply catch these
* calls when they are not defined in the child and do nothing.
*
* @param string $function
* @param array $args
*/
public function __call($function, $args)
{
}
/**
* Returns array of properties, eg. "show_footer", "show_search", etc.
*
* @return array of boolean
*/
protected function getViewProperties()
{
return $this->viewProperties;
}
/**
* This functions reads the customization values for the DataTable and returns an array (name,value) to be printed in Javascript.
* This array defines things such as:
* - name of the module & action to call to request data for this table
* - optional filters information, eg. filter_limit and filter_offset
* - etc.
*
* The values are loaded:
* - from the generic filters that are applied by default @see Piwik_API_DataTableGenericFilter.php::getGenericFiltersInformation()
* - from the values already available in the GET array
* - from the values set using methods from this class (eg. setSearchPattern(), setLimit(), etc.)
*
* @return array eg. array('show_offset_information' => 0, 'show_...
*/
protected function getJavascriptVariablesToSet()
{
// build javascript variables to set
$javascriptVariablesToSet = array();
$genericFilters = Piwik_API_DataTableGenericFilter::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;
}
}
}
}
Benaka Moorthi
a validé
foreach ($this->viewProperties['custom_parameters'] as $name => $value) {
$javascriptVariablesToSet[$name] = $value;
}
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
Benaka Moorthi
a validé
// we go through all the $this->viewProperties array and set the variables not set yet
foreach ($this->getJavaScriptProperties() as $name) {
if (!isset($javascriptVariablesToSet[$name])
&& !empty($this->viewProperties[$name])
) {
$javascriptVariablesToSet[$name] = $this->viewProperties[$name];
}
}
if ($this->dataTable instanceof Piwik_DataTable) {
// we override the filter_sort_column with the column used for sorting,
// which can be different from the one specified (eg. if the column doesn't exist)
$javascriptVariablesToSet['filter_sort_column'] = $this->dataTable->getSortedByColumnName();
// datatable can return "2" but we want to write "nb_visits" in the js
mattab
a validé
if (isset(Piwik_Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']])) {
$javascriptVariablesToSet['filter_sort_column'] = Piwik_Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']];
}
}
$javascriptVariablesToSet['module'] = $this->currentControllerName;
$javascriptVariablesToSet['action'] = $this->currentControllerAction;
if (!isset($javascriptVariablesToSet['viewDataTable'])) {
$javascriptVariablesToSet['viewDataTable'] = $this->getViewDataTableId();
}
Benaka Moorthi
a validé
$javascriptVariablesToSet['controllerActionCalledWhenRequestSubTable'] = $this->viewProperties['subtable_controller_action'];
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
if ($this->dataTable &&
// Piwik_DataTable_Array doesn't have the method
!($this->dataTable instanceof Piwik_DataTable_Array)
&& empty($javascriptVariablesToSet['totalRows'])
) {
$javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter();
}
// we escape the values that will be displayed in the javascript footer of each datatable
// to make sure there is no malicious code injected (the value are already htmlspecialchar'ed as they
// are loaded with Piwik_Common::getRequestVar()
foreach ($javascriptVariablesToSet as &$value) {
if (is_array($value)) {
$value = array_map('addslashes', $value);
} else {
$value = addslashes($value);
}
}
$deleteFromJavascriptVariables = array(
'filter_excludelowpop',
'filter_excludelowpop_value',
);
foreach ($deleteFromJavascriptVariables as $name) {
if (isset($javascriptVariablesToSet[$name])) {
unset($javascriptVariablesToSet[$name]);
}
}
if(!empty($rawSegment)) {
$javascriptVariablesToSet['segment'] = $rawSegment;
}
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
return $javascriptVariablesToSet;
}
/**
* Returns, for a given parameter, the value of this parameter in the REQUEST array.
* If not set, returns the default value for this parameter @see getDefault()
*
* @param string $nameVar
* @return string|mixed Value of this parameter
*/
protected function getDefaultOrCurrent($nameVar)
{
if (isset($_GET[$nameVar])) {
return Piwik_Common::sanitizeInputValue($_GET[$nameVar]);
}
$default = $this->getDefault($nameVar);
return $default;
}
/**
* Returns the default value for a given parameter.
* For example, these default values can be set using the disable* methods.
*
* @param string $nameVar
* @return mixed
*/
protected function getDefault($nameVar)
{
Benaka Moorthi
a validé
if (!isset($this->viewProperties[$nameVar])) {
return false;
}
Benaka Moorthi
a validé
return $this->viewProperties[$nameVar];
Benaka Moorthi
a validé
/**
Benaka Moorthi
a validé
* Sets a set of extra request query parameters to be used when querying API data.
Benaka Moorthi
a validé
*
Benaka Moorthi
a validé
* @param array $params
Benaka Moorthi
a validé
*/
Benaka Moorthi
a validé
public function setRequestParametersToModify($params)
Benaka Moorthi
a validé
{
$this->viewProperties['request_parameters_to_modify'] += $params;
Benaka Moorthi
a validé
}
/**
* The generic filters (limit, offset, sort by visit desc) will not be applied to this datatable.
*/
public function disableGenericFilters()
{
Benaka Moorthi
a validé
$this->viewProperties['disable_generic_filters'] = true;
}
/**
* The queued filters (replace column names, enhance column with percentage signs, add logo metadata information, etc.)
* will not be applied to this datatable. They can be manually applied by calling applyQueuedFilters on the datatable.
*/
public function disableQueuedFilters()
{
Benaka Moorthi
a validé
$this->viewProperties['disable_queued_filters'] = true;
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
}
/**
* The "X-Y of Z" and the "< Previous / Next >"-Buttons won't be displayed under this table
*/
public function disableOffsetInformationAndPaginationControls()
{
$this->viewProperties['show_offset_information'] = false;
$this->viewProperties['show_pagination_control'] = false;
}
/**
* The "< Previous / Next >"-Buttons won't be displayed under this table
*/
public function disableShowPaginationControl()
{
$this->viewProperties['show_pagination_control'] = false;
}
/**
* Ensures the limit dropdown will always be shown, even if pagination is disabled.
*/
public function alwaysShowLimitDropdown()
{
$this->viewProperties['show_limit_control'] = true;
}
/**
* The "X-Y of Z" won't be displayed under this table
*/
public function disableOffsetInformation()
{
$this->viewProperties['show_offset_information'] = false;
}
/**
* The search box won't be displayed under this table
*/
public function disableSearchBox()
{
$this->viewProperties['show_search'] = false;
}
/**
* Do not sort this table, leave it as it comes out of the API
*/
public function disableSort()
{
$this->viewProperties['enable_sort'] = false;
}
/**
* Do not show the footer icons (show all columns icon, "plus" icon)
*/
public function disableFooterIcons()
{
$this->viewProperties['show_footer_icons'] = false;
}
/**
* When this method is called, the output will not include the template datatable_footer
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
*/
public function disableFooter()
{
$this->viewProperties['show_footer'] = false;
}
/**
* The "Include low population" link won't be displayed under this table
*/
public function disableExcludeLowPopulation()
{
$this->viewProperties['show_exclude_low_population'] = false;
}
/**
* Whether or not to show the "View table" icon
*/
public function disableShowTable()
{
$this->viewProperties['show_table'] = false;
}
/**
* Whether or not to show the "View more data" icon
*/
public function disableShowAllColumns()
{
$this->viewProperties['show_table_all_columns'] = false;
}
/**
* Whether or not to show the tag cloud, pie charts, bar chart icons
*/
public function disableShowAllViewsIcons()
{
$this->viewProperties['show_all_views_icons'] = false;
}
/**
* Whether or not to hide view icons altogether.
* The difference to disableShowAllViewsIcons is that not even the single icon
* will be shown. This icon might cause trouble because it reloads the graph on click.
*/
public function hideAllViewsIcons()
{
$this->viewProperties['show_all_views_icons'] = false;
$this->viewProperties['hide_all_views_icons'] = true;
}
/**
* Whether or not to show the annotations view. This method has no effect if
* the Annotations plugin is not loaded.
*/
public function showAnnotationsView()
{
if (!Piwik_PluginsManager::getInstance()->isPluginLoaded('Annotations')) {
return;
}
$this->viewProperties['hide_annotations_view'] = false;
}
/**
* Whether or not to show the bar chart icon.
*/
public function disableShowBarChart()
{
$this->viewProperties['show_bar_chart'] = false;
}
/**
* Whether or not to show the pie chart icon.
*/
public function disableShowPieChart()
{
$this->viewProperties['show_pie_chart'] = false;
}
/**
* Whether or not to show the tag cloud icon.
*/
public function disableTagCloud()
{
$this->viewProperties['show_tag_cloud'] = false;
}
/**
* Whether or not to show related reports in the footer
*/
public function disableShowRelatedReports()
{
$this->viewProperties['show_related_reports'] = false;
}
/**
* Whether or not to show the export to RSS feed icon
*/
public function disableShowExportAsRssFeed()
{
$this->viewProperties['show_export_as_rss_feed'] = false;
}
/**
* Whether or not to show the "goal" icon
*/
public function enableShowGoals()
{
if (Piwik_PluginsManager::getInstance()->isPluginActivated('Goals')) {
$this->viewProperties['show_goals'] = true;
}
}
/**
* Whether or not to show the "Ecommerce orders/cart" icons
*/
public function enableShowEcommerce()
{
$this->viewProperties['show_ecommerce'] = true;
}
/**
* Whether or not to show the summary row on every page of results. The default behavior
* is to treat the summary row like any other row.
*/
public function alwaysShowSummaryRow()
{
Benaka Moorthi
a validé
$this->viewProperties['keep_summary_row'] = true;
}
/**
* Sets the value to use for the Exclude low population filter.
*
* @param int|float If a row value is less than this value, it will be removed from the dataTable
* @param string The name of the column for which we compare the value to $minValue
*/
public function setExcludeLowPopulation($columnName = null, $minValue = null)
{
if (is_null($columnName)) {
$columnName = 'nb_visits';
}
Benaka Moorthi
a validé
$this->viewProperties['filter_excludelowpop'] = $columnName;
$this->viewProperties['filter_excludelowpop_value'] = $minValue;
}
/**
* Sets the pattern to look for in the table (only rows matching the pattern will be kept)
*
* @param string $pattern to look for
* @param string $column to compare the pattern to
*/
public function setSearchPattern($pattern, $column)
{
Benaka Moorthi
a validé
$this->viewProperties['filter_pattern'] = $pattern;
$this->viewProperties['filter_column'] = $column;
}
/**
* Sets the maximum number of rows of the table
*
* @param int $limit
*/
public function setLimit($limit)
{
if ($limit !== 0) {
Benaka Moorthi
a validé
$this->viewProperties['filter_limit'] = $limit;
}
}
/**
* Will display a message in the DataTable footer.
*
* @param string $message Message
*/
public function setFooterMessage($message)
{
$this->viewProperties['show_footer_message'] = $message;
}
/**
* Sets the dataTable column to sort by. This sorting will be applied before applying the (offset, limit) filter.
*
mattab
a validé
* @param int|string $columnId eg. 'nb_visits' for some tables, or Piwik_Metrics::INDEX_NB_VISITS for others
* @param string $order desc or asc
*/
public function setSortedColumn($columnId, $order = 'desc')
{
Benaka Moorthi
a validé
$this->viewProperties['filter_sort_column'] = $columnId;
$this->viewProperties['filter_sort_order'] = $order;
}
/**
* Returns the column name on which the table will be sorted
*
* @return string
*/
public function getSortedColumn()
{
Benaka Moorthi
a validé
return isset($this->viewProperties['filter_sort_column']) ? $this->viewProperties['filter_sort_column'] : false;
}
/**
* Sets translation string for given column
*
* @param string $columnName column name
* @param string $columnTranslation column name translation
* @throws Exception
*/
public function setColumnTranslation($columnName, $columnTranslation)
{
Benaka Moorthi
a validé
$this->viewProperties['translations'][$columnName] = $columnTranslation;
}
/**
* Returns column translation if available, in other case given column name
*
* @param string $columnName column name
* @return string
*/
public function getColumnTranslation($columnName)
{
Benaka Moorthi
a validé
if (isset($this->viewProperties['translations'][$columnName])) {
return $this->viewProperties['translations'][$columnName];
}
return $columnName;
}
/**
* Set the documentation of a metric used in the report.
* Please note, that the default way of doing this is by using
* getReportMetadata. Only use this method, if you have a good
* reason to do so.
*
* @param string $metricIdentifier The idenentifier string of
* the metric
* @param string $documentation The metric documentation as a
* translated string
*/
public function setMetricDocumentation($metricIdentifier, $documentation)
{
Benaka Moorthi
a validé
$this->viewProperties['metrics_documentation'][$metricIdentifier] = $documentation;
}
/**
* Returns metric documentation, or false
*
* @param string $columnName column name
* @return bool
*/
public function getMetricDocumentation($columnName)
{
Benaka Moorthi
a validé
if (empty($this->viewProperties['metrics_documentation'])) {
$this->loadDocumentation();
}
Benaka Moorthi
a validé
if (!empty($this->viewProperties['metrics_documentation'][$columnName])) {
return $this->viewProperties['metrics_documentation'][$columnName];
}
return false;
}
/**
* Set the documentation of the report.
* Please note, that the default way of doing this is by using
* getReportMetadata. Only use this method, if you have a good
* reason to do so.
*
* @param string $documentation The report documentation as a
* translated string
*/
public function setReportDocumentation($documentation)
{
Benaka Moorthi
a validé
$this->viewProperties['documentation'] = $documentation;
}
/**
* Returns report documentation, or false
* @return array|bool
*/
public function getReportDocumentation()
{
Benaka Moorthi
a validé
return $this->viewProperties['documentation'];
}
/** Load documentation from the API */
private function loadDocumentation()
{
Benaka Moorthi
a validé
$this->viewProperties['metrics_documentation'] = array();
$report = Piwik_API_API::getInstance()->getMetadata(0, $this->currentControllerName, $this->currentControllerAction);
$report = $report[0];
if (isset($report['metricsDocumentation'])) {
Benaka Moorthi
a validé
$this->viewProperties['metrics_documentation'] = $report['metricsDocumentation'];
}
if (isset($report['documentation'])) {
Benaka Moorthi
a validé
$this->viewProperties['documentation'] = $report['documentation'];
}
}
/**
* Sets the columns that will be displayed in the HTML output
* By default all columns are displayed ($columnsNames = array() will display all columns)
*
* @param array $columnsNames Array of column names eg. array('nb_visits','nb_hits')
*/
public function setColumnsToDisplay($columnsNames)
{
if (!is_array($columnsNames)) {
if (strpos($columnsNames, ',') !== false) {
// array values are comma separated
$columnsNames = explode(',', $columnsNames);
} else {
$columnsNames = array($columnsNames);
}
}
Benaka Moorthi
a validé
$this->viewProperties['columns_to_display'] = array_filter($columnsNames);
}
/**
* Returns columns names to display, in order.
* If no columns were specified to be displayed, return all columns found in the first row.
* If the data table has empty_columns meta data set, those columns will be removed.
* @param array PHP array conversion of the data table
* @return array
*/
public function getColumnsToDisplay()
{
Benaka Moorthi
a validé
if (empty($this->viewProperties['columns_to_display'])) {
$row = $this->dataTable->getFirstRow();
if (empty($row)) {
return array();
}
return array_keys($row->getColumns());
}
Benaka Moorthi
a validé
$this->viewProperties['columns_to_display'] = array_filter($this->viewProperties['columns_to_display']);
$this->removeEmptyColumnsFromDisplay();
Benaka Moorthi
a validé
return $this->viewProperties['columns_to_display'];
}
private function removeEmptyColumnsFromDisplay()
{
if ($this->dataTable instanceof Piwik_DataTable_Array) {
$emptyColumns = $this->dataTable->getMetadataIntersectArray(Piwik_DataTable::EMPTY_COLUMNS_METADATA_NAME);
} else {
$emptyColumns = $this->dataTable->getMetadata(Piwik_DataTable::EMPTY_COLUMNS_METADATA_NAME);
}
if (is_array($emptyColumns)) {
foreach ($emptyColumns as $emptyColumn) {
Benaka Moorthi
a validé
$key = array_search($emptyColumn, $this->viewProperties['columns_to_display']);
if ($key !== false) {
Benaka Moorthi
a validé
unset($this->viewProperties['columns_to_display'][$key]);
}
}
Benaka Moorthi
a validé
$this->viewProperties['columns_to_display'] = array_values($this->viewProperties['columns_to_display']);
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
}
}
/**
* Set whether to highlight the summary row or not. If not highlighted, it will
* look like every other row.
*/
public function setHighlightSummaryRow($highlightSummaryRow)
{
$this->viewProperties['highlight_summary_row'] = $highlightSummaryRow;
}
/**
* Sets the name of the metadata to use for a custom tooltip.
*/
public function setTooltipMetadataName($metadataName)
{
$this->viewProperties['tooltip_metadata_name'] = $metadataName;
}
/**
* Sets columns translations array.
*
* @param array $columnsTranslations An associative array indexed by column names, eg. array('nb_visit'=>"Numer of visits")
*/
public function setColumnsTranslations($columnsTranslations)
{
Benaka Moorthi
a validé
$this->viewProperties['translations'] += $columnsTranslations;
}
/**
* Sets a custom parameter, that will be printed in the javascript array associated with each datatable
*
* @param string $parameter name
* @param mixed $value
* @throws Exception
*/
public function setCustomParameter($parameter, $value)
{
Benaka Moorthi
a validé
if (isset($this->viewProperties['custom_parameters'][$parameter])) {
throw new Exception("$parameter is already defined for this DataTable.");
}
Benaka Moorthi
a validé
$this->viewProperties['custom_parameters'][$parameter] = $value;
}
/**
* Queues a Datatable filter, that will be applied once the datatable is loaded from the API.
* Useful when the controller needs to add columns, or decorate existing columns, when these filters don't
* necessarily make sense directly in the API.
*
* @param string $filterName
* @param mixed $parameters
* @param bool $runBeforeGenericFilters Set to true if the filter will delete rows from the table,
* and should therefore be ran before Sort, Limit, etc.
* @return void
*/
public function queueFilter($filterName, $parameters = array(), $runBeforeGenericFilters = false)
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
{
if ($runBeforeGenericFilters) {
$this->queuedFiltersPriority[] = array($filterName, $parameters);
} else {
$this->queuedFilters[] = array($filterName, $parameters);
}
}
/**
* Adds one report to the set of reports that are related to this one. Related reports
* are displayed in the footer as links. When they are clicked, the report will change to
* the related report.
*
* Make sure to call setReportTitle so this report will be displayed correctly.
*
* @param string $module The report's controller name, ie, 'UserSettings'.
* @param string $action The report's controller action, ie, 'getBrowser'.
* @param string $title The text used to describe the related report.
* @param array $queryParams Any specific query params to use when loading the report.
* This can be used to, for example, make a goal report a related
* report (by adding an idGoal parameter).
*/
public function addRelatedReport($module, $action, $title, $queryParams = array())
{
// don't add the related report if it references this report
if ($this->currentControllerName == $module && $this->currentControllerAction == $action) {
return;
}
$url = $this->getBaseReportUrl($module, $action, $queryParams);
$this->viewProperties['relatedReports'][$url] = $title;
}
/**
* Adds a set of reports that are related to this one. Related reports are displayed in
* the footer as links. When they are clicked, the report will change to the related report.
*
* If you need to associate specific query params with a report, use the addRelatedReport
* method instead of this one.
*
* @param string $thisReportTitle The title of this report.
* @param array $relatedReports An array mapping report IDs ('Controller.methodName') with
* display text.
*/
public function addRelatedReports($thisReportTitle, $relatedReports)
{
Benaka Moorthi
a validé
if (!empty($thisReportTitle)) {
$this->setReportTitle($thisReportTitle);
}
foreach ($relatedReports as $report => $title) {
list($module, $action) = explode('.', $report);
$this->addRelatedReport($module, $action, $title);
}
}
/**
* Sets the title of this report.
*
* @param string $title
*/
public function setReportTitle($title)
{
$this->viewProperties['title'] = $title;
}
/**
* Sets a custom URL to use to reference this report.
*
* @param string $module
* @param string $action
* @param array $queryParams
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
*/
public function setReportUrl($module, $action, $queryParams = array())
{
$this->viewProperties['self_url'] = $this->getBaseReportUrl($module, $action, $queryParams);
}
/**
* Returns true if it is likely that the data for this report has been purged and if the
* user should be told about that.
*
* In order for this function to return true, the following must also be true:
* - The data table for this report must either be empty or not have been fetched.
* - The period of this report is not a multiple period.
* - The date of this report must be older than the delete_reports_older_than config option.
* @return bool
*/
public function hasReportBeenPurged()
{
$strPeriod = Piwik_Common::getRequestVar('period', false);
$strDate = Piwik_Common::getRequestVar('date', false);
if ($strPeriod !== false
&& $strDate !== false
&& (is_null($this->dataTable) || $this->dataTable->getRowsCount() == 0)
) {
// if range, only look at the first date
if ($strPeriod == 'range') {
$idSite = Piwik_Common::getRequestVar('idSite', '');
if (intval($idSite) != 0) {
$site = new Piwik_Site($idSite);
$timezone = $site->getTimezone();
} else {
$timezone = 'UTC';
}
$period = new Piwik_Period_Range('range', $strDate, $timezone);
$reportDate = $period->getDateStart();
} // if a multiple period, this function is irrelevant
else if (Piwik_Period::isMultiplePeriod($strDate, $strPeriod)) {
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
return false;
} // otherwise, use the date as given
else {
$reportDate = Piwik_Date::factory($strDate);
}
$reportYear = $reportDate->toString('Y');
$reportMonth = $reportDate->toString('m');
if (class_exists('Piwik_PrivacyManager')
&& Piwik_PrivacyManager::shouldReportBePurged($reportYear, $reportMonth)
) {
return true;
}
}
return false;
}
/**
* Returns URL for this report w/o any filter parameters.
*
* @param string $module
* @param string $action
* @param array $queryParams
*/
private function getBaseReportUrl($module, $action, $queryParams = array())
{
$params = array_merge($queryParams, array('module' => $module, 'action' => $action));
Benaka Moorthi
a validé
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
return Piwik_API_Request::getCurrentUrlWithoutGenericFilters($params);
}
/**
* Convenience method that creates and renders a ViewDataTable for a API method.
*
* @param string $pluginName The name of the plugin (eg, UserSettings).
* @param string $apiAction The name of the API action (eg, getResolution).
* @param bool $fetch If true, the result is returned, if false it is echo'd.
* @return string|null See $fetch.
*/
static public function render($pluginName, $apiAction, $fetch = true)
{
$apiClassName = 'Piwik_'.$pluginName.'_API';
if (!method_exists($apiClassName::getInstance(), $apiAction)) {
throw new Exception("Invalid action name '$apiAction' for '$pluginName' plugin.");
}
$view = self::factory(null, $pluginName.'.'.$apiAction);
$view->main();
$rendered = $view->getView()->render();
if ($fetch) {
return $rendered;
} else {
echo $rendered;
}
}
/**
* Returns whether the DataTable result will have to be expanded for the
* current request before rendering.
*
* @return bool
*/
public static function shouldLoadExpanded()
{
// if filter_column_recursive & filter_pattern_recursive are supplied, and flat isn't supplied
// we have to load all the child subtables.
return Piwik_Common::getRequestVar('filter_column_recursive', false) !== false
&& Piwik_Common::getRequestVar('filter_pattern_recursive', false) !== false
&& Piwik_Common::getRequestVar('flat', false) === false;
}
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
/**
* Returns true if the first array contains one or more of the specified
* column names or their associated integer INDEX_ value.
*
* @param array $columns Piwik_DataTable_Row columns.
* @param array|string $columnsToCheckFor eg, array('nb_visits', 'nb_uniq_visitors')
* @return bool
*/
private function dataTableColumnsContains($columns, $columnsToCheckFor)
{
if (!is_array($columnsToCheckFor)) {
$columnsToCheckFor = array($columnsToCheckFor);
}
foreach ($columnsToCheckFor as $columnToCheckFor) {
foreach ($columns as $column) {
// check for the column name and its associated integer INDEX_ value
if ($column == $columnToCheckFor
|| (isset(Piwik_Metrics::$mappingFromNameToId[$columnToCheckFor])
&& $column == Piwik_Metrics::$mappingFromNameToId[$columnToCheckFor])
) {
return true;
}
}
}
return false;
}
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
protected function buildView($visualization, $template = false)
{
if ($template === false) {
$template = $this->dataTableTemplate;
}
$view = new Piwik_View($template);
if (!empty($this->loadingError)) {
$view->error = $this->loadingError;
}
$view->visualization = $visualization;
if (!$this->isDataAvailable) {
$view->dataTable = null;
} else {
$view->dataTable = $this->dataTable;
// if it's likely that the report data for this data table has been purged,
// set whether we should display a message to that effect.
$view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged();
$view->deleteReportsOlderThan = Piwik_GetOption('delete_reports_older_than');
}
$view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet();
$view->properties = $this->getViewProperties();
return $view;
}
public function getDefaultDataTableCssClass()
{
return false;
}