diff --git a/core/API/Request.php b/core/API/Request.php index 838df1610ab..ac066be7c26 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -218,5 +218,26 @@ public static function getRequestParametersGET() $GET = Piwik_Common::getArrayFromQueryString($_SERVER['QUERY_STRING']); return $GET; } + + /** + * Returns the current URL without generic filter query parameters. + * + * @param array $params Query parameter values to override in the new URL. + * @return string + */ + public static function getCurrentUrlWithoutGenericFilters($params) + { + // unset all filter query params so the related report will show up in its default state, + // unless the filter param was in $queryParams + $genericFiltersInfo = Piwik_API_DataTableGenericFilter::getGenericFiltersInformation(); + foreach ($genericFiltersInfo as $filter) { + foreach ($filter as $queryParamName => $queryParamInfo) { + if (!isset($params[$queryParamName])) { + $params[$queryParamName] = null; + } + } + } + return Piwik_Url::getCurrentQueryStringWithParametersModified($params); + } } diff --git a/core/DataTable/Filter/ExcludeLowPopulation.php b/core/DataTable/Filter/ExcludeLowPopulation.php index c5d6369d6c5..9f4d5c723cf 100644 --- a/core/DataTable/Filter/ExcludeLowPopulation.php +++ b/core/DataTable/Filter/ExcludeLowPopulation.php @@ -21,22 +21,29 @@ */ class Piwik_DataTable_Filter_ExcludeLowPopulation extends Piwik_DataTable_Filter { - static public $minimumValue; const MINIMUM_SIGNIFICANT_PERCENTAGE_THRESHOLD = 0.02; + + /** + * The minimum value to enforce in a datatable for a specified column. Rows found with + * a value less than this are removed. + * + * @var number + */ + private $minimumValue; /** * Constructor * * @param Piwik_DataTable $table * @param string $columnToFilter column to filter - * @param number $minimumValue minimum value + * @param number|Closure $minimumValue minimum value * @param bool $minimumPercentageThreshold */ public function __construct($table, $columnToFilter, $minimumValue, $minimumPercentageThreshold = false) { parent::__construct($table); $this->columnToFilter = $columnToFilter; - + if ($minimumValue == 0) { if ($minimumPercentageThreshold === false) { $minimumPercentageThreshold = self::MINIMUM_SIGNIFICANT_PERCENTAGE_THRESHOLD; @@ -45,7 +52,8 @@ public function __construct($table, $columnToFilter, $minimumValue, $minimumPerc $sumValues = array_sum($allValues); $minimumValue = $sumValues * $minimumPercentageThreshold; } - self::$minimumValue = $minimumValue; + + $this->minimumValue = $minimumValue; } /** @@ -53,23 +61,13 @@ public function __construct($table, $columnToFilter, $minimumValue, $minimumPerc * * @param Piwik_DataTable $table */ - function filter($table) - { - $table->filter('ColumnCallbackDeleteRow', - array($this->columnToFilter, - array("Piwik_DataTable_Filter_ExcludeLowPopulation", "excludeLowPopulation") - ) - ); - } - - /** - * Checks whether the given value is below the defined minimum - * - * @param number $value value to check - * @return bool - */ - static public function excludeLowPopulation($value) + public function filter($table) { - return $value >= self::$minimumValue; + $minimumValue = $this->minimumValue; + $isValueHighPopulation = function ($value) use ($minimumValue) { + return $value >= $minimumValue; + }; + + $table->filter('ColumnCallbackDeleteRow', array($this->columnToFilter, $isValueHighPopulation)); } } diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php index a60bdb22082..886082ad24d 100644 --- a/core/ViewDataTable.php +++ b/core/ViewDataTable.php @@ -57,14 +57,6 @@ abstract class Piwik_ViewDataTable */ protected $mainAlreadyExecuted = false; - /** - * Contains the values set for the parameters - * - * @see getJavascriptVariablesToSet() - * @var array - */ - protected $variablesDefault = array(); - /** * Array of properties that are available in the view * Used to store UI properties, eg. "show_footer", "show_search", etc. @@ -72,7 +64,7 @@ abstract class Piwik_ViewDataTable * @var array */ protected $viewProperties = array(); - + /** * If the current dataTable refers to a subDataTable (eg. keywordsBySearchEngineId for id=X) this variable is set to the Id * @@ -87,7 +79,6 @@ abstract class Piwik_ViewDataTable */ protected $dataTable = null; - /** * List of filters to apply after the data has been loaded from the API * @@ -120,12 +111,6 @@ abstract class Piwik_ViewDataTable */ protected $controllerActionCalledWhenRequestSubTable = null; - /** - * @see init() - * @var string - */ - protected $apiMethodToRequestDataTable; - /** * This view should be an implementation of the Interface Piwik_View_Interface * The $view object should be created in the main() method. @@ -134,21 +119,6 @@ abstract class Piwik_ViewDataTable */ protected $view = null; - /** - * Array of columns names translations - * - * @var array - */ - protected $columnsTranslations = array(); - - /** - * Documentation for the metrics used in the current report. - * Received from the Plugin API, used for inline help. - * - * @var array - */ - protected $metricsDocumentation = false; - /** * Documentation for the report. * Received from the Plugin API, used for inline help. @@ -156,13 +126,66 @@ abstract class Piwik_ViewDataTable * @var array */ protected $documentation = false; - + /** - * Array of columns set to display - * - * @var array + * Default constructor. */ - protected $columnsToDisplay = array(); + 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() + ); + + $this->viewProperties['columns_to_display'][] = 'label'; + + $columns = Piwik_Common::getRequestVar('columns', false); + if ($columns !== false) { + $this->viewProperties['columns_to_display'] = array_merge( + $this->viewProperties['columns_to_display'], Piwik::getArrayFromApiParameter($columns)); + } else if (Piwik_Common::getRequestVar('period', false) == 'day') { + $this->viewProperties['columns_to_display'][] = 'nb_uniq_visitors'; + } else { + $this->viewProperties['columns_to_display'][] = 'nb_visits'; + } + } /** * Method to be implemented by the ViewDataTable_*. @@ -187,66 +210,132 @@ abstract protected function getViewDataTableId(); * 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* - * @param bool $force If set to true, returns a ViewDataTable of the $defaultType * @return Piwik_ViewDataTable */ - static public function factory($defaultType = null, $force = false) + static public function factory($defaultType = null, $action = false) { - if (is_null($defaultType)) { + if ($action !== false) { + $defaultProperties = self::getDefaultPropertiesForReport($action); + if (isset($defaultProperties['default_view_type'])) { + $defaultType = $defaultProperties['default_view_type']; + } + } + + if ($defaultType === null) { $defaultType = 'table'; } - if ($force === true) { - $type = $defaultType; - } else { - $type = Piwik_Common::getRequestVar('viewDataTable', $defaultType, 'string'); - } + $type = Piwik_Common::getRequestVar('viewDataTable', $defaultType, 'string'); switch ($type) { case 'cloud': - return new Piwik_ViewDataTable_Cloud(); + $result = new Piwik_ViewDataTable_Cloud(); break; case 'graphPie': - return new Piwik_ViewDataTable_GenerateGraphHTML_ChartPie(); + $result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartPie(); break; case 'graphVerticalBar': - return new Piwik_ViewDataTable_GenerateGraphHTML_ChartVerticalBar(); + $result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartVerticalBar(); break; case 'graphEvolution': - return new Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution(); + $result = new Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution(); break; case 'sparkline': - return new Piwik_ViewDataTable_Sparkline(); + $result = new Piwik_ViewDataTable_Sparkline(); break; case 'generateDataChartVerticalBar': - return new Piwik_ViewDataTable_GenerateGraphData_ChartVerticalBar(); + $result = new Piwik_ViewDataTable_GenerateGraphData_ChartVerticalBar(); break; case 'generateDataChartPie': - return new Piwik_ViewDataTable_GenerateGraphData_ChartPie(); + $result = new Piwik_ViewDataTable_GenerateGraphData_ChartPie(); break; case 'generateDataChartEvolution': - return new Piwik_ViewDataTable_GenerateGraphData_ChartEvolution(); + $result = new Piwik_ViewDataTable_GenerateGraphData_ChartEvolution(); break; case 'tableAllColumns': - return new Piwik_ViewDataTable_HtmlTable_AllColumns(); + $result = new Piwik_ViewDataTable_HtmlTable_AllColumns(); break; case 'tableGoals': - return new Piwik_ViewDataTable_HtmlTable_Goals(); + $result = new Piwik_ViewDataTable_HtmlTable_Goals(); break; case 'table': default: - return new Piwik_ViewDataTable_HtmlTable(); + $result = new Piwik_ViewDataTable_HtmlTable(); break; } + + 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', + ); } /** @@ -270,53 +359,46 @@ static public function factory($defaultType = null, $force = false) public function init($currentControllerName, $currentControllerAction, $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable = null) + $controllerActionCalledWhenRequestSubTable = null, + $defaultProperties = array()) { $this->currentControllerName = $currentControllerName; $this->currentControllerAction = $currentControllerAction; - $this->apiMethodToRequestDataTable = $apiMethodToRequestDataTable; $this->controllerActionCalledWhenRequestSubTable = $controllerActionCalledWhenRequestSubTable; $this->idSubtable = Piwik_Common::getRequestVar('idSubtable', false, 'int'); - - $this->viewProperties['report_id'] = $currentControllerName . '.' . $currentControllerAction; - $this->viewProperties['show_goals'] = false; - $this->viewProperties['show_ecommerce'] = false; - $this->viewProperties['show_search'] = Piwik_Common::getRequestVar('show_search', true); - $this->viewProperties['show_table'] = Piwik_Common::getRequestVar('show_table', true); - $this->viewProperties['show_table_all_columns'] = Piwik_Common::getRequestVar('show_table_all_columns', true); - $this->viewProperties['show_all_views_icons'] = Piwik_Common::getRequestVar('show_all_views_icons', true); - $this->viewProperties['hide_all_views_icons'] = Piwik_Common::getRequestVar('hide_all_views_icons', false); - $this->viewProperties['hide_annotations_view'] = Piwik_Common::getRequestVar('hide_annotations_view', true); - $this->viewProperties['show_bar_chart'] = Piwik_Common::getRequestVar('show_barchart', true); - $this->viewProperties['show_pie_chart'] = Piwik_Common::getRequestVar('show_piechart', true); - $this->viewProperties['show_tag_cloud'] = Piwik_Common::getRequestVar('show_tag_cloud', true); - $this->viewProperties['show_export_as_image_icon'] = Piwik_Common::getRequestVar('show_export_as_image_icon', false); - $this->viewProperties['show_export_as_rss_feed'] = Piwik_Common::getRequestVar('show_export_as_rss_feed', true); - $this->viewProperties['show_exclude_low_population'] = Piwik_Common::getRequestVar('show_exclude_low_population', true); - $this->viewProperties['show_offset_information'] = Piwik_Common::getRequestVar('show_offset_information', true); - $this->viewProperties['show_pagination_control'] = Piwik_Common::getRequestVar('show_pagination_control', true); - $this->viewProperties['show_limit_control'] = false; - $this->viewProperties['show_footer'] = Piwik_Common::getRequestVar('show_footer', true); + + 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); - $this->viewProperties['show_related_reports'] = Piwik_Common::getRequestVar('show_related_reports', true); - $this->viewProperties['apiMethodToRequestDataTable'] = $this->apiMethodToRequestDataTable; - $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['apiMethodToRequestDataTable'] = $apiMethodToRequestDataTable; + + $this->viewProperties['report_id'] = $currentControllerName . '.' . $currentControllerAction; $this->viewProperties['self_url'] = $this->getBaseReportUrl($currentControllerName, $currentControllerAction); - $this->viewProperties['tooltip_metadata_name'] = false; - - $standardColumnNameToTranslation = array_merge( - Piwik_Metrics::getDefaultMetrics(), - Piwik_Metrics::getDefaultProcessedMetrics() - ); - $this->setColumnsTranslations($standardColumnNameToTranslation); + + 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(); + } } - + /** * Forces the View to use a given template. * Usually the template to use is set in the specific ViewDataTable_* @@ -358,7 +440,7 @@ public function getCurrentControllerName() public function getApiMethodToRequestDataTable() { - return $this->apiMethodToRequestDataTable; + return $this->viewProperties['apiMethodToRequestDataTable']; } public function getControllerActionCalledWhenRequestSubTable() @@ -392,6 +474,56 @@ public function setDataTable($dataTable) $this->dataTable = $dataTable; } + /** + * Returns the defaut view properties for a report, if any. + * + * Plugins can associate callbacks with the ViewDataTable.getReportDisplayProperties + * event to set the default properties of reports. + * + * @return array + */ + private static function getDefaultPropertiesForReport($apiAction) + { + $properties = array(); + Piwik_PostEvent('ViewDataTable.getReportDisplayProperties', array(&$properties, $apiAction)); + + return $properties; + } + + /** + * 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. @@ -462,8 +594,8 @@ protected function postDataTableLoadedFromAPI() $requestString = $this->getRequestString(); $request = Piwik_API_Request::getRequestArrayFromString($requestString); - if (!empty($this->variablesDefault['enable_sort']) - && $this->variablesDefault['enable_sort'] === 'false' + if (!empty($this->viewProperties['enable_sort']) + && $this->viewProperties['enable_sort'] === 'false' ) { $request['filter_sort_column'] = $request['filter_sort_order'] = ''; } @@ -497,8 +629,8 @@ private function areGenericFiltersDisabled() } // if $this->disableGenericFilters() was called, generic filters are disabled - if (isset($this->variablesDefault['disable_generic_filters']) - && $this->variablesDefault['disable_generic_filters'] === true + if (isset($this->viewProperties['disable_generic_filters']) + && $this->viewProperties['disable_generic_filters'] === true ) { return true; } @@ -513,8 +645,8 @@ private function areGenericFiltersDisabled() */ private function areQueuedFiltersDisabled() { - return isset($this->variablesDefault['disable_queued_filters']) - && $this->variablesDefault['disable_queued_filters']; + return isset($this->viewProperties['disable_queued_filters']) + && $this->viewProperties['disable_queued_filters']; } /** @@ -547,7 +679,7 @@ protected function getRequestString() // 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->apiMethodToRequestDataTable; + $requestString = 'method=' . $this->viewProperties['apiMethodToRequestDataTable']; $requestString .= '&format=original'; $requestString .= '&disable_generic_filters=' . Piwik_Common::getRequestVar('disable_generic_filters', 1, 'int'); @@ -683,9 +815,17 @@ protected function getJavascriptVariablesToSet() // 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])) { + // 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]; + } + } + + foreach ($this->viewProperties['custom_parameters'] as $name => $value) { + if (!empty($value)) { $javascriptVariablesToSet[$name] = $value; } } @@ -741,7 +881,6 @@ protected function getJavascriptVariablesToSet() $javascriptVariablesToSet['segment'] = $rawSegment; } - return $javascriptVariablesToSet; } @@ -770,10 +909,10 @@ protected function getDefaultOrCurrent($nameVar) */ protected function getDefault($nameVar) { - if (!isset($this->variablesDefault[$nameVar])) { + if (!isset($this->viewProperties[$nameVar])) { return false; } - return $this->variablesDefault[$nameVar]; + return $this->viewProperties[$nameVar]; } /** @@ -791,7 +930,7 @@ public function setRequestStringSuffix($suffix) */ public function disableGenericFilters() { - $this->variablesDefault['disable_generic_filters'] = true; + $this->viewProperties['disable_generic_filters'] = true; } /** @@ -800,7 +939,7 @@ public function disableGenericFilters() */ public function disableQueuedFilters() { - $this->variablesDefault['disable_queued_filters'] = true; + $this->viewProperties['disable_queued_filters'] = true; } /** @@ -849,7 +988,7 @@ public function disableSearchBox() */ public function disableSort() { - $this->variablesDefault['enable_sort'] = 'false'; + $this->viewProperties['enable_sort'] = 'false'; } /** @@ -988,7 +1127,7 @@ public function enableShowEcommerce() */ public function alwaysShowSummaryRow() { - $this->variablesDefault['keep_summary_row'] = true; + $this->viewProperties['keep_summary_row'] = true; } /** @@ -1002,8 +1141,8 @@ public function setExcludeLowPopulation($columnName = null, $minValue = null) if (is_null($columnName)) { $columnName = 'nb_visits'; } - $this->variablesDefault['filter_excludelowpop'] = $columnName; - $this->variablesDefault['filter_excludelowpop_value'] = $minValue; + $this->viewProperties['filter_excludelowpop'] = $columnName; + $this->viewProperties['filter_excludelowpop_value'] = $minValue; } /** @@ -1014,8 +1153,8 @@ public function setExcludeLowPopulation($columnName = null, $minValue = null) */ public function setSearchPattern($pattern, $column) { - $this->variablesDefault['filter_pattern'] = $pattern; - $this->variablesDefault['filter_column'] = $column; + $this->viewProperties['filter_pattern'] = $pattern; + $this->viewProperties['filter_column'] = $column; } /** @@ -1026,7 +1165,7 @@ public function setSearchPattern($pattern, $column) public function setLimit($limit) { if ($limit !== 0) { - $this->variablesDefault['filter_limit'] = $limit; + $this->viewProperties['filter_limit'] = $limit; } } @@ -1048,9 +1187,8 @@ public function setFooterMessage($message) */ public function setSortedColumn($columnId, $order = 'desc') { -// debug_print_backtrace(); - $this->variablesDefault['filter_sort_column'] = $columnId; - $this->variablesDefault['filter_sort_order'] = $order; + $this->viewProperties['filter_sort_column'] = $columnId; + $this->viewProperties['filter_sort_order'] = $order; } /** @@ -1060,7 +1198,7 @@ public function setSortedColumn($columnId, $order = 'desc') */ public function getSortedColumn() { - return isset($this->variablesDefault['filter_sort_column']) ? $this->variablesDefault['filter_sort_column'] : false; + return isset($this->viewProperties['filter_sort_column']) ? $this->viewProperties['filter_sort_column'] : false; } /** @@ -1072,11 +1210,7 @@ public function getSortedColumn() */ public function setColumnTranslation($columnName, $columnTranslation) { - if (empty($columnTranslation)) { - throw new Exception('Unknown column: ' . $columnName); - } - - $this->columnsTranslations[$columnName] = $columnTranslation; + $this->viewProperties['translations'][$columnName] = $columnTranslation; } /** @@ -1087,8 +1221,8 @@ public function setColumnTranslation($columnName, $columnTranslation) */ public function getColumnTranslation($columnName) { - if (isset($this->columnsTranslations[$columnName])) { - return $this->columnsTranslations[$columnName]; + if (isset($this->viewProperties['translations'][$columnName])) { + return $this->viewProperties['translations'][$columnName]; } return $columnName; } @@ -1106,7 +1240,7 @@ public function getColumnTranslation($columnName) */ public function setMetricDocumentation($metricIdentifier, $documentation) { - $this->metricsDocumentation[$metricIdentifier] = $documentation; + $this->viewProperties['metrics_documentation'][$metricIdentifier] = $documentation; } /** @@ -1117,12 +1251,12 @@ public function setMetricDocumentation($metricIdentifier, $documentation) */ public function getMetricDocumentation($columnName) { - if ($this->metricsDocumentation === false) { + if (empty($this->viewProperties['metrics_documentation'])) { $this->loadDocumentation(); } - if (!empty($this->metricsDocumentation[$columnName])) { - return $this->metricsDocumentation[$columnName]; + if (!empty($this->viewProperties['metrics_documentation'][$columnName])) { + return $this->viewProperties['metrics_documentation'][$columnName]; } return false; @@ -1148,7 +1282,7 @@ public function setReportDocumentation($documentation) */ public function getReportDocumentation() { - if ($this->metricsDocumentation === false) { + if ($this->documentation === false) { $this->loadDocumentation(); } @@ -1158,13 +1292,13 @@ public function getReportDocumentation() /** Load documentation from the API */ private function loadDocumentation() { - $this->metricsDocumentation = array(); + $this->viewProperties['metrics_documentation'] = array(); $report = Piwik_API_API::getInstance()->getMetadata(0, $this->currentControllerName, $this->currentControllerAction); $report = $report[0]; if (isset($report['metricsDocumentation'])) { - $this->metricsDocumentation = $report['metricsDocumentation']; + $this->viewProperties['metrics_documentation'] = $report['metricsDocumentation']; } if (isset($report['documentation'])) { @@ -1188,7 +1322,7 @@ public function setColumnsToDisplay($columnsNames) $columnsNames = array($columnsNames); } } - $this->columnsToDisplay = array_filter($columnsNames); + $this->viewProperties['columns_to_display'] = array_filter($columnsNames); } /** @@ -1200,7 +1334,7 @@ public function setColumnsToDisplay($columnsNames) */ public function getColumnsToDisplay() { - if (empty($this->columnsToDisplay)) { + if (empty($this->viewProperties['columns_to_display'])) { $row = $this->dataTable->getFirstRow(); if (empty($row)) { return array(); @@ -1209,11 +1343,11 @@ public function getColumnsToDisplay() return array_keys($row->getColumns()); } - $this->columnsToDisplay = array_filter($this->columnsToDisplay); + $this->viewProperties['columns_to_display'] = array_filter($this->viewProperties['columns_to_display']); $this->removeEmptyColumnsFromDisplay(); - return $this->columnsToDisplay; + return $this->viewProperties['columns_to_display']; } private function removeEmptyColumnsFromDisplay() @@ -1228,12 +1362,12 @@ private function removeEmptyColumnsFromDisplay() } if (is_array($emptyColumns)) { foreach ($emptyColumns as $emptyColumn) { - $key = array_search($emptyColumn, $this->columnsToDisplay); + $key = array_search($emptyColumn, $this->viewProperties['columns_to_display']); if ($key !== false) { - unset($this->columnsToDisplay[$key]); + unset($this->viewProperties['columns_to_display'][$key]); } } - $this->columnsToDisplay = array_values($this->columnsToDisplay); + $this->viewProperties['columns_to_display'] = array_values($this->viewProperties['columns_to_display']); } } @@ -1261,7 +1395,7 @@ public function setTooltipMetadataName($metadataName) */ public function setColumnsTranslations($columnsTranslations) { - $this->columnsTranslations += $columnsTranslations; + $this->viewProperties['translations'] += $columnsTranslations; } /** @@ -1273,10 +1407,10 @@ public function setColumnsTranslations($columnsTranslations) */ public function setCustomParameter($parameter, $value) { - if (isset($this->variablesDefault[$parameter])) { + if (isset($this->viewProperties['custom_parameters'][$parameter])) { throw new Exception("$parameter is already defined for this DataTable."); } - $this->variablesDefault[$parameter] = $value; + $this->viewProperties['custom_parameters'][$parameter] = $value; } /** @@ -1337,7 +1471,10 @@ public function addRelatedReport($module, $action, $title, $queryParams = array( */ public function addRelatedReports($thisReportTitle, $relatedReports) { - $this->setReportTitle($thisReportTitle); + if (!empty($thisReportTitle)) { + $this->setReportTitle($thisReportTitle); + } + foreach ($relatedReports as $report => $title) { list($module, $action) = explode('.', $report); $this->addRelatedReport($module, $action, $title); @@ -1429,21 +1566,33 @@ public function hasReportBeenPurged() private function getBaseReportUrl($module, $action, $queryParams = array()) { $params = array_merge($queryParams, array('module' => $module, 'action' => $action)); - - // unset all filter query params so the related report will show up in its default state, - // unless the filter param was in $queryParams - $genericFiltersInfo = Piwik_API_DataTableGenericFilter::getGenericFiltersInformation(); - foreach ($genericFiltersInfo as $filter) { - foreach ($filter as $queryParamName => $queryParamInfo) { - if (!isset($params[$queryParamName])) { - $params[$queryParamName] = null; - } - } + 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; } - - // add the related report - $url = Piwik_Url::getCurrentQueryStringWithParametersModified($params); - return $url; } /** diff --git a/core/ViewDataTable/Cloud.php b/core/ViewDataTable/Cloud.php index a0f4d48c564..bc2377b4e78 100644 --- a/core/ViewDataTable/Cloud.php +++ b/core/ViewDataTable/Cloud.php @@ -29,23 +29,11 @@ protected function getViewDataTableId() { return 'cloud'; } - - /** - * @see Piwik_ViewDataTable::init() - * @param string $currentControllerName - * @param string $currentControllerAction - * @param string $apiMethodToRequestDataTable - * @param null|string $controllerActionCalledWhenRequestSubTable - */ - function init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable = null) + + public function __construct() { - parent::init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable); + parent::__construct(); + $this->dataTableTemplate = '@CoreHome/_dataTableCloud'; $this->disableOffsetInformation(); $this->disableExcludeLowPopulation(); diff --git a/core/ViewDataTable/GenerateGraphData.php b/core/ViewDataTable/GenerateGraphData.php index ddd8f23f695..e80405cf54b 100644 --- a/core/ViewDataTable/GenerateGraphData.php +++ b/core/ViewDataTable/GenerateGraphData.php @@ -31,16 +31,58 @@ */ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable { - /** - * Number of elements to display in the graph. - * @var int - */ - protected $graphLimit = null; protected $yAxisUnit = ''; // used for the series picker protected $selectableColumns = array(); + public function __construct() + { + parent::__construct(); + $this->viewProperties['graph_limit'] = null; + + $labelIdx = array_search('label', $this->viewProperties['columns_to_display']); + unset($this->viewProperties[$labelIdx]); + } + + public function init($currentControllerName, + $currentControllerAction, + $apiMethodToRequestDataTable, + $controllerActionCalledWhenRequestSubTable = null, + $defaultProperties = array()) + { + parent::init($currentControllerName, + $currentControllerAction, + $apiMethodToRequestDataTable, + $controllerActionCalledWhenRequestSubTable, + $defaultProperties); + + $columns = Piwik_Common::getRequestVar('columns', false); + if ($columns !== false) { + $columns = Piwik::getArrayFromApiParameter($columns); + } else { + $columns = $this->viewProperties['columns_to_display']; + } + + // do not sort if sorted column was initially "label" or eg. it would make "Visits by Server time" not pretty + if ($this->getSortedColumn() != 'label') { + $firstColumn = reset($columns); + if ($firstColumn == 'label') { + $firstColumn = next($columns); + } + + $this->setSortedColumn($firstColumn); + } + + // selectable columns + $selectableColumns = array('nb_visits', 'nb_actions'); + if (Piwik_Common::getRequestVar('period', false) == 'day') { + $selectableColumns[] = 'nb_uniq_visitors'; + } + + $this->setSelectableColumns($selectableColumns); + } + public function setAxisYUnit($unit) { $this->yAxisUnit = $unit; @@ -54,7 +96,7 @@ public function setAxisYUnit($unit) */ public function setGraphLimit($limit) { - $this->graphLimit = $limit; + $this->viewProperties['graph_limit'] = $limit; } /** @@ -64,7 +106,7 @@ public function setGraphLimit($limit) */ public function getGraphLimit() { - return $this->graphLimit; + return $this->viewProperties['graph_limit']; } protected $displayPercentageInTooltip = true; diff --git a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php index cbcf93d7bed..4249d7cca86 100644 --- a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php +++ b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php @@ -35,8 +35,10 @@ protected function getViewDataTableId() return 'generateDataChartEvolution'; } - function __construct() + public function __construct() { + parent::__construct(); + $this->view = new Piwik_Visualization_Chart_Evolution(); } diff --git a/core/ViewDataTable/GenerateGraphData/ChartPie.php b/core/ViewDataTable/GenerateGraphData/ChartPie.php index 6acd8f440ed..5f8d61a2647 100644 --- a/core/ViewDataTable/GenerateGraphData/ChartPie.php +++ b/core/ViewDataTable/GenerateGraphData/ChartPie.php @@ -17,16 +17,17 @@ */ class Piwik_ViewDataTable_GenerateGraphData_ChartPie extends Piwik_ViewDataTable_GenerateGraphData { - protected $graphLimit = 6; - protected function getViewDataTableId() { return 'generateDataChartPie'; } - function __construct() + public function __construct() { + parent::__construct(); + $this->view = new Piwik_Visualization_Chart_Pie(); + $this->viewProperties['graph_limit'] = 6; } /** diff --git a/core/ViewDataTable/GenerateGraphData/ChartVerticalBar.php b/core/ViewDataTable/GenerateGraphData/ChartVerticalBar.php index b4c462b7ba4..ca9dd94bf06 100644 --- a/core/ViewDataTable/GenerateGraphData/ChartVerticalBar.php +++ b/core/ViewDataTable/GenerateGraphData/ChartVerticalBar.php @@ -17,16 +17,17 @@ */ class Piwik_ViewDataTable_GenerateGraphData_ChartVerticalBar extends Piwik_ViewDataTable_GenerateGraphData { - protected $graphLimit = 6; - protected function getViewDataTableId() { return 'generateDataChartVerticalBar'; } - function __construct() + public function __construct() { + parent::__construct(); + $this->view = new Piwik_Visualization_Chart_VerticalBar(); + $this->viewProperties['graph_limit'] = 6; } protected function getUnitsForColumnsToDisplay() diff --git a/core/ViewDataTable/GenerateGraphHTML.php b/core/ViewDataTable/GenerateGraphHTML.php index 8c17e37d8da..2c4da0652c7 100644 --- a/core/ViewDataTable/GenerateGraphHTML.php +++ b/core/ViewDataTable/GenerateGraphHTML.php @@ -24,37 +24,28 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable protected $graphType = 'unknown'; /** - * Parameters to send to GenerateGraphData instance. Parameters are passed - * via the $_GET array. - * - * @var array + * Default constructor. */ - protected $generateGraphDataParams = array(); - - /** - * @see Piwik_ViewDataTable::init() - * @param string $currentControllerName - * @param string $currentControllerAction - * @param string $apiMethodToRequestDataTable - * @param null $controllerActionCalledWhenRequestSubTable - */ - function init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable = null) + public function __construct() { - parent::init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable); - + parent::__construct(); + $this->dataTableTemplate = '@CoreHome/_dataTableGraph'; - $this->disableOffsetInformationAndPaginationControls(); $this->disableExcludeLowPopulation(); $this->disableSearchBox(); $this->enableShowExportAsImageIcon(); - + } + + public function init($currentControllerName, + $currentControllerAction, + $apiMethodToRequestDataTable, + $controllerActionCalledWhenRequestSubTable = null, + $defaultProperties = array()) + { + parent::init($currentControllerName, $currentControllerAction, $apiMethodToRequestDataTable, + $controllerActionCalledWhenRequestSubTable, $defaultProperties); + $this->parametersToModify = array( 'viewDataTable' => $this->getViewDataTableIdToLoad(), // in the case this controller is being executed by another controller @@ -84,13 +75,24 @@ public function setParametersToModify($array) { $this->parametersToModify = array_merge($this->parametersToModify, $array); } + + /** + * Returns the names of the view properties to send to GenerateGraphData instance. + * Properties are passed via the $_GET array. + * + * @return array + */ + public function getViewPropertiesToForward() + { + return array('show_all_ticks', 'add_total_row'); + } /** * Show every x-axis tick instead of just every other one. */ public function showAllTicks() { - $this->generateGraphDataParams['show_all_ticks'] = 1; + $this->viewProperties['show_all_ticks'] = 1; } /** @@ -99,7 +101,7 @@ public function showAllTicks() */ public function addTotalRow() { - $this->generateGraphDataParams['add_total_row'] = 1; + $this->viewProperties['add_total_row'] = 1; } /** @@ -143,8 +145,12 @@ protected function buildView() } // collect data + $jsonParameters = array(); + foreach ($this->getJavaScriptProperties() as $name) { + $jsonParameters[$name] = $this->viewProperties[$name]; + } $this->parametersToModify['action'] = $this->currentControllerAction; - $this->parametersToModify = array_merge($this->variablesDefault, $this->parametersToModify); + $this->parametersToModify = array_merge($jsonParameters, $this->parametersToModify); $this->graphData = $this->getGraphData(); // build view @@ -174,7 +180,7 @@ protected function getGraphData() { $saveGet = $_GET; - $params = array_merge($this->generateGraphDataParams, $this->parametersToModify); + $params = array_merge($this->getGenerateGraphDataParams(), $this->parametersToModify); foreach ($params as $key => $val) { // We do not forward filter data to the graph controller. // This would cause the graph to have filter_limit=5 set by default, @@ -193,4 +199,15 @@ protected function getGraphData() return str_replace(array("\r", "\n"), '', $content); } + + private function getGenerateGraphDataParams() + { + $result = array(); + foreach ($this->getViewPropertiesToForward() as $name) { + if (isset($this->viewProperties[$name])) { + $result[$name] = $this->viewProperties[$name]; + } + } + return $result; + } } diff --git a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php index 4381b758552..73d0f3a1670 100644 --- a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php +++ b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php @@ -43,12 +43,14 @@ protected function getViewDataTableIdToLoad() function init($currentControllerName, $currentControllerAction, $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable = null) + $controllerActionCalledWhenRequestSubTable = null, + $defaultProperties = array()) { parent::init($currentControllerName, $currentControllerAction, $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable); + $controllerActionCalledWhenRequestSubTable, + $defaultProperties); $this->calculateEvolutionDateRange(); $this->disableShowAllViewsIcons(); diff --git a/core/ViewDataTable/HtmlTable.php b/core/ViewDataTable/HtmlTable.php index c8677b9643c..2d6505db852 100644 --- a/core/ViewDataTable/HtmlTable.php +++ b/core/ViewDataTable/HtmlTable.php @@ -25,25 +25,16 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable * @var array */ public $arrayDataTable; // phpArray + + public function __construct() + { + parent::__construct(); - /** - * @see Piwik_ViewDataTable::init() - * @param string $currentControllerName - * @param string $currentControllerAction - * @param string $apiMethodToRequestDataTable - * @param null|string $controllerActionCalledWhenRequestSubTable - */ - function init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable = null) - { - parent::init($currentControllerName, - $currentControllerAction, - $apiMethodToRequestDataTable, - $controllerActionCalledWhenRequestSubTable); $this->dataTableTemplate = '@CoreHome/_dataTable'; - $this->variablesDefault['enable_sort'] = '1'; + $this->viewProperties['enable_sort'] = '1'; + $this->viewProperties['disable_row_evolution'] = false; + $this->viewProperties['disable_row_actions'] = false; + $this->setSortedColumn('nb_visits', 'desc'); $this->setLimit(Piwik_Config::getInstance()->General['datatable_default_limit']); $this->handleLowPopulation(); @@ -51,6 +42,13 @@ function init($currentControllerName, $this->viewProperties['datatable_js_type'] = 'dataTable'; $this->viewProperties['datatable_css_class'] = $this->getDefaultDataTableCssClass(); } + + public function getJavaScriptProperties() + { + $result = parent::getJavaScriptProperties(); + $result[] = 'search_recursive'; + return $result; + } protected function getViewDataTableId() { @@ -190,7 +188,7 @@ protected function getPHPArrayFromDataTable() */ public function addColumnToDisplay($columnName) { - $this->columnsToDisplay[] = $columnName; + $this->viewProperties['columns_to_display'][] = $columnName; } /** @@ -199,7 +197,7 @@ public function addColumnToDisplay($columnName) */ public function setSearchRecursive() { - $this->variablesDefault['search_recursive'] = true; + $this->viewProperties['search_recursive'] = true; } protected function getRequestString() @@ -216,7 +214,7 @@ protected function getRequestString() */ public function disableRowEvolution() { - $this->variablesDefault['disable_row_evolution'] = true; + $this->viewProperties['disable_row_evolution'] = true; } /** @@ -224,7 +222,7 @@ public function disableRowEvolution() */ public function disableRowActions() { - $this->variablesDefault['disable_row_actions'] = true; + $this->viewProperties['disable_row_actions'] = true; } } diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php index 8eec6d2d1b8..6d0b2898b56 100644 --- a/plugins/Actions/API.php +++ b/plugins/Actions/API.php @@ -38,25 +38,6 @@ static public function getInstance() return self::$instance; } - - /** - * Backward compatibility. Fallsback to getPageTitles() instead. - * @deprecated Deprecated since Piwik 0.5 - * @ignore - * - * @param int $idSite - * @param string $period - * @param $date - * @param bool $segment - * @param bool $expanded - * @param bool|int $idSubtable - * @return Piwik_DataTable|Piwik_DataTable_Array - */ - public function getActions($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false) - { - return $this->getPageTitles($idSite, $period, $date, $segment, $expanded, $idSubtable); - } - /** * Returns the list of metrics (pages, downloads, outlinks) * diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php index fdae02efd0c..efbbbb4f91b 100644 --- a/plugins/Actions/Actions.php +++ b/plugins/Actions/Actions.php @@ -18,6 +18,22 @@ */ class Piwik_Actions extends Piwik_Plugin { + const ACTIONS_REPORT_ROWS_DISPLAY = 100; + + private $columnTranslations; + + public function __construct() + { + $this->columnTranslations = array( + 'nb_hits' => Piwik_Translate('General_ColumnPageviews'), + 'nb_visits' => Piwik_Translate('General_ColumnUniquePageviews'), + 'avg_time_on_page' => Piwik_Translate('General_ColumnAverageTimeOnPage'), + 'bounce_rate' => Piwik_Translate('General_ColumnBounceRate'), + 'exit_rate' => Piwik_Translate('General_ColumnExitRate'), + 'avg_time_generation' => Piwik_Translate('General_ColumnAverageGenerationTime'), + ); + } + public function getInformation() { $info = array( @@ -32,16 +48,17 @@ public function getInformation() public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessing_Day.compute' => 'archiveDay', - 'ArchiveProcessing_Period.compute' => 'archivePeriod', - 'WidgetsList.add' => 'addWidgets', - 'Menu.add' => 'addMenus', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenus', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties', ); return $hooks; } - + public function getSegmentsMetadata(&$segments) { $sqlFilter = array($this, 'getIdActionFromSegment'); @@ -605,5 +622,389 @@ protected function guessActionTypeFromSegment($segmentName) throw new Exception(" The segment $segmentName has an unexpected value."); } } + + public function getReportDisplayProperties(&$properties, $apiAction) + { + $reportViewProperties = array( + 'Actions.getPageUrls' => $this->getDisplayPropertiesForPageUrls(), + 'Actions.getEntryPageUrls' => $this->getDisplayPropertiesForEntryPageUrls(), + 'Actions.getExitPageUrls' => $this->getDisplayPropertiesForExitPageUrls(), + 'Actions.getSiteSearchKeywords' => $this->getDisplayPropertiesForSiteSearchKeywords(), + 'Actions.getSiteSearchNoResultKeywords' => $this->getDisplayPropertiesForSiteSearchNoResultKeywords(), + 'Actions.getSiteSearchCategories' => $this->getDisplayPropertiesForSiteSearchCategories(), + 'Actions.getPageUrlsFollowingSiteSearch' => $this->getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch(false), + 'Actions.getPageTitlesFollowingSiteSearch' => $this->getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch(true), + 'Actions.getPageTitles' => $this->getDisplayPropertiesForGetPageTitles(), + 'Actions.getEntryPageTitles' => $this->getDisplayPropertiesForGetEntryPageTitles(), + 'Actions.getExitPageTitles' => $this->getDisplayPropertiesForGetExitPageTitles(), + 'Actions.getDownloads' => $this->getDisplayPropertiesForGetDownloads(), + 'Actions.getOutlinks' => $this->getDisplayPropertiesForGetOutlinks(), + ); + + if (isset($reportViewProperties[$apiAction])) { + $properties = $reportViewProperties[$apiAction]; + } + } + + private function addBaseDisplayProperties(&$result) + { + $result['datatable_css_class'] = 'dataTableActions'; + $result['datatable_js_type'] = 'actionDataTable'; + $result['subtable_template'] = '@CoreHome/_dataTableActions_subDataTable.twig'; + $result['search_recursive'] = true; + $result['show_all_views_icons'] = false; + $result['show_table_all_columns'] = false; + $result['filter_limit'] = self::ACTIONS_REPORT_ROWS_DISPLAY; + + // if the flat parameter is not provided, make sure it is set to 0 in the URL, + // so users can see that they can set it to 1 (see #3365) + $result['custom_parameters'] = array('flat' => 0); + + if (Piwik_ViewDataTable::shouldLoadExpanded()) { + $result['show_expanded'] = true; + + $result['filters'][] = function ($dataTable) { + Piwik_Actions::setDataTableRowLevels($dataTable); + }; + } + + return $result; + } + + public static function setDataTableRowLevels($dataTable, $level = 0) + { + foreach ($dataTable->getRows() as $row) { + $row->setMetadata('css_class', 'level'.$level); + + $subtable = $row->getSubtable(); + if ($subtable) { + self::setDataTableRowLevels($subtable, $level + 1); + } + } + } + + private function addExcludeLowPopDisplayProperties(&$result) + { + if (Piwik_Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') != '0') { + $result['filter_excludelowpop'] = 'nb_hits'; + $result['filter_excludelowpop_value'] = function () { + // computing minimum value to exclude (2 percent of the total number of actions) + $visitsInfo = Piwik_VisitsSummary_Controller::getVisitsSummary()->getFirstRow(); + $nbActions = $visitsInfo->getColumn('nb_actions'); + $nbActionsLowPopulationThreshold = floor(0.02 * $nbActions); + + // we remove 1 to make sure some actions/downloads are displayed in the case we have a very few of them + // and each of them has 1 or 2 hits... + return min($visitsInfo->getColumn('max_actions') - 1, $nbActionsLowPopulationThreshold - 1); + }; + } + } + + private function addPageDisplayProperties(&$result) + { + // add common translations + $result['translations'] += array( + 'nb_hits' => Piwik_Translate('General_ColumnPageviews'), + 'nb_visits' => Piwik_Translate('General_ColumnUniquePageviews'), + 'avg_time_on_page' => Piwik_Translate('General_ColumnAverageTimeOnPage'), + 'bounce_rate' => Piwik_Translate('General_ColumnBounceRate'), + 'exit_rate' => Piwik_Translate('General_ColumnExitRate'), + 'avg_time_generation' => Piwik_Translate('General_ColumnAverageGenerationTime'), + ); + + // prettify avg_time_on_page column + $getPrettyTimeFromSeconds = array('Piwik', 'getPrettyTimeFromSeconds'); + $result['filters'][] = array('ColumnCallbackReplace', array('avg_time_on_page', $getPrettyTimeFromSeconds)); + + // prettify avg_time_generation column + $avgTimeCallback = function ($time) { + return $time ? Piwik::getPrettyTimeFromSeconds($time, true, true, false) : "-"; + }; + $result['filters'][] = array('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback)); + + // add avg_generation_time tooltip + $tooltipCallback = function ($hits, $min, $max) { + if (!$hits) { + return false; + } + + return Piwik_Translate("Actions_AvgGenerationTimeTooltip", array( + $hits, + "
", + Piwik::getPrettyTimeFromSeconds($min), + Piwik::getPrettyTimeFromSeconds($max) + )); + }; + $result['filters'][] = array('ColumnCallbackAddMetadata', + array( + array('nb_hits_with_time_generation', 'min_time_generation', 'max_time_generation'), + 'avg_time_generation_tooltip', + $tooltipCallback + ) + ); + + $this->addExcludeLowPopDisplayProperties($result); + } + + public function getDisplayPropertiesForPageUrls() + { + $result = array( + 'translations' => array('label' => Piwik_Translate('Actions_ColumnPageURL')), + 'columns_to_display' => array('label', 'nb_hits', 'nb_visits', 'bounce_rate', + 'avg_time_on_page', 'exit_rate', 'avg_time_generation'), + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForEntryPageUrls() + { + // link to the page, not just the report, but only if not a widget + $widget = Piwik_Common::getRequestVar('widget', false); + $reportUrl = Piwik_API_Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexEntryPageUrls' : 'getEntryPageUrls' + )); + + $result = array( + 'translations' => array('label' => Piwik_Translate('Actions_ColumnEntryPageURL'), + 'entry_bounce_count' => Piwik_Translate('General_ColumnBounces'), + 'entry_nb_visits' => Piwik_Translate('General_ColumnEntrances')), + 'columns_to_display' => array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'), + 'filter_sort_column' => 'entry_nb_visits', + 'filter_sort_order' => 'desc', + 'title' => Piwik_Translate('Actions_SubmenuPagesEntry'), + 'relatedReports' => array( + 'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles') + ), + 'self_url' => $reportUrl + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForExitPageUrls() + { + // link to the page, not just the report, but only if not a widget + $widget = Piwik_Common::getRequestVar('widget', false); + $reportUrl = Piwik_API_Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexExitPageUrls' : 'getExitPageUrls' + )); + + $result = array( + 'translations' => array('label' => Piwik_Translate('Actions_ColumnExitPageURL'), + 'exit_nb_visits' => Piwik_Translate('General_ColumnExits')), + 'columns_to_display' => array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'), + 'filter_sort_column' => 'exit_nb_visits', + 'filter_sort_order' => 'desc', + 'title' => Piwik_Translate('Actions_SubmenuPagesExit'), + 'relatedReports' => array( + 'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles') + ), + 'self_url' => $reportUrl, + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + private function addSiteSearchDisplayProperties(&$result) + { + $result['translations'] += array( + 'nb_visits' => Piwik_Translate('Actions_ColumnSearches'), + 'exit_rate' => str_replace("% ", "% ", Piwik_Translate('Actions_ColumnSearchExits')), + 'nb_pages_per_search' => Piwik_Translate('Actions_ColumnPagesPerSearch') + ); + $result['show_bar_chart'] = false; + $result['show_table_all_columns'] = false; + } + + public function getDisplayPropertiesForSiteSearchKeywords() + { + $result = array( + 'translations' => array('label' => Piwik_Translate('Actions_ColumnSearchKeyword')), + 'columns_to_display' => array('label', 'nb_visits', 'nb_pages_per_search', 'exit_rate'), + ); + + $this->addSiteSearchDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForSiteSearchNoResultKeywords() + { + $result = array( + 'translations' => array('label', Piwik_Translate('Actions_ColumnNoResultKeyword')), + 'columns_to_display' => array('label', 'nb_visits', 'exit_rate') + ); + + $this->addSiteSearchDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForSiteSearchCategories() + { + return array( + 'translations' => array( + 'label' => Piwik_Translate('Actions_ColumnSearchCategory'), + 'nb_visits' => Piwik_Translate('Actions_ColumnSearches'), + 'nb_pages_per_search' => Piwik_Translate('Actions_ColumnPagesPerSearch') + ), + 'columns_to_display' => array('label', 'nb_visits', 'nb_pages_per_search'), + 'show_table_all_columns' => false, + 'show_bar_chart' => false, + 'disable_row_evolution' => false, + ); + } + + public function getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch($isTitle) + { + $title = $isTitle ? Piwik_Translate('Actions_WidgetPageTitlesFollowingSearch') + : Piwik_Translate('Actions_WidgetPageUrlsFollowingSearch'); + + $relatedReports = array( + 'Actions.getPageTitlesFollowingSiteSearch' => Piwik_Translate('Actions_WidgetPageTitlesFollowingSearch'), + 'Actions.getPageUrlsFollowingSiteSearch' => Piwik_Translate('Actions_WidgetPageUrlsFollowingSearch'), + ); + + $result = array( + 'translations' => array( + 'label' => Piwik_Translate('General_ColumnDestinationPage'), + 'nb_hits_following_search' => Piwik_Translate('General_ColumnViewedAfterSearch'), + 'nb_hits' => Piwik_Translate('General_ColumnTotalPageviews') + ), + 'columns_to_display' => array('label', 'nb_hits_following_search', 'nb_hits'), + 'filter_sort_column' => 'nb_hits_following_search', + 'filter_sort_order' => 'desc', + 'show_exclude_low_population' => false, + 'title' => $title, + 'relatedReports' => $relatedReports + ); + + $this->addExcludeLowPopDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForGetPageTitles() + { + // link to the page, not just the report, but only if not a widget + $widget = Piwik_Common::getRequestVar('widget', false); + $reportUrl = Piwik_API_Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexPageTitles' : 'getPageTitles' + )); + + $result = array( + 'translations' => array('label' => Piwik_Translate('Actions_ColumnPageName')), + 'columns_to_display' => array('label', 'nb_hits', 'nb_visits', 'bounce_rate', + 'avg_time_on_page', 'exit_rate', 'avg_time_generation'), + 'title' => Piwik_Translate('Actions_SubmenuPageTitles'), + 'relatedReports' => array( + 'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles'), + 'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles'), + ), + 'self_url' => $reportUrl + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForGetEntryPageTitles() + { + $entryPageUrlAction = + Piwik_Common::getRequestVar('widget', false) === false ? 'indexEntryPageUrls' : 'getEntryPageUrls'; + + $result = array( + 'translations' => array( + 'label' => Piwik_Translate('Actions_ColumnEntryPageTitle'), + 'entry_bounce_count' => Piwik_Translate('General_ColumnBounces'), + 'entry_nb_visits' => Piwik_Translate('General_ColumnEntrances'), + ), + 'columns_to_display' => array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'), + 'title' => Piwik_Translate('Actions_EntryPageTitles'), + 'relatedReports' => array( + 'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'), + "Actions.$entryPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesEntry') + ), + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForGetExitPageTitles() + { + $exitPageUrlAction = + Piwik_Common::getRequestVar('widget', false) === false ? 'indexExitPageUrls' : 'getExitPageUrls'; + + $result = array( + 'translations' => array( + 'label' => Piwik_Translate('Actions_ColumnExitPageTitle'), + 'exit_nb_visits' => Piwik_Translate('General_ColumnExits'), + ), + 'columns_to_display' => array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'), + 'title' => Piwik_Translate('Actions_ExitPageTitles'), + 'relatedReports' => array( + 'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'), + "Actions.$exitPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesExit'), + ), + ); + + $this->addPageDisplayProperties($result); + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForGetDownloads() + { + $result = array( + 'translations' => array( + 'label' => Piwik_Translate('Actions_ColumnDownloadURL'), + 'nb_visits' => Piwik_Translate('Actions_ColumnUniqueDownloads'), + 'nb_hits' => Piwik_Translate('Actions_ColumnDownloads'), + ), + 'columns_to_display' => array('label', 'nb_visits', 'nb_hits'), + 'show_exclude_low_population' => false + ); + + $this->addBaseDisplayProperties($result); + + return $result; + } + + public function getDisplayPropertiesForGetOutlinks() + { + $result = array( + 'translations' => array( + 'label' => Piwik_Translate('Actions_ColumnClickedURL'), + 'nb_visits' => Piwik_Translate('Actions_ColumnUniqueClicks'), + 'nb_hits' => Piwik_Translate('Actions_ColumnClicks'), + ), + 'columns_to_display' => array('label', 'nb_visits', 'nb_hits'), + 'show_exclude_low_population' => false + ); + + $this->addBaseDisplayProperties($result); + + return $result; + } } diff --git a/plugins/Actions/Controller.php b/plugins/Actions/Controller.php index 16473b60e0e..f7597825e56 100644 --- a/plugins/Actions/Controller.php +++ b/plugins/Actions/Controller.php @@ -16,22 +16,10 @@ */ class Piwik_Actions_Controller extends Piwik_Controller { - const ACTIONS_REPORT_ROWS_DISPLAY = 100; - - protected function getPageUrlsView($currentAction, $controllerActionSubtable, $apiAction) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, $currentAction, $apiAction, $controllerActionSubtable); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnPageURL')); - return $view; - } - - /** - * PAGES - * @param bool $fetch - * @return string - */ - + // + // Actions that render whole pages + // + public function indexPageUrls($fetch = false) { return Piwik_View::singleReport( @@ -39,24 +27,6 @@ public function indexPageUrls($fetch = false) $this->getPageUrls(true), $fetch); } - public function getPageUrls($fetch = false) - { - $view = $this->getPageUrlsView(__FUNCTION__, 'getPageUrls', 'Actions.getPageUrls'); - $this->configureViewPages($view); - $this->configureViewActions($view); - return $this->renderView($view, $fetch); - } - - protected function configureViewPages($view) - { - $view->setColumnsToDisplay(array('label', 'nb_hits', 'nb_visits', 'bounce_rate', 'avg_time_on_page', 'exit_rate', 'avg_time_generation')); - } - - /** - * ENTRY PAGES - * @param bool $fetch - * @return string|void - */ public function indexEntryPageUrls($fetch = false) { return Piwik_View::singleReport( @@ -64,30 +34,6 @@ public function indexEntryPageUrls($fetch = false) $this->getEntryPageUrls(true), $fetch); } - public function getEntryPageUrls($fetch = false) - { - $view = $this->getPageUrlsView(__FUNCTION__, 'getEntryPageUrls', 'Actions.getEntryPageUrls'); - $this->configureViewEntryPageUrls($view); - $this->configureViewActions($view); - return $this->renderView($view, $fetch); - } - - protected function configureViewEntryPageUrls($view) - { - $view->setSortedColumn('entry_nb_visits'); - $view->setColumnsToDisplay(array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate')); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnEntryPageURL')); - $view->setColumnTranslation('entry_bounce_count', Piwik_Translate('General_ColumnBounces')); - $view->setColumnTranslation('entry_nb_visits', Piwik_Translate('General_ColumnEntrances')); - $view->addRelatedReports(Piwik_Translate('Actions_SubmenuPagesEntry'), array( - 'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles') - )); - $view->setReportUrl('Actions', $this->getEntryPageUrlActionForLink()); - } - - /* - * EXIT PAGES - */ public function indexExitPageUrls($fetch = false) { return Piwik_View::singleReport( @@ -95,29 +41,6 @@ public function indexExitPageUrls($fetch = false) $this->getExitPageUrls(true), $fetch); } - public function getExitPageUrls($fetch = false) - { - $view = $this->getPageUrlsView(__FUNCTION__, 'getExitPageUrls', 'Actions.getExitPageUrls'); - $this->configureViewExitPageUrls($view); - $this->configureViewActions($view); - return $this->renderView($view, $fetch); - } - - protected function configureViewExitPageUrls($view) - { - $view->setSortedColumn('exit_nb_visits'); - $view->setColumnsToDisplay(array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate')); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnExitPageURL')); - $view->setColumnTranslation('exit_nb_visits', Piwik_Translate('General_ColumnExits')); - $view->addRelatedReports(Piwik_Translate('Actions_SubmenuPagesExit'), array( - 'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles') - )); - $view->setReportUrl('Actions', $this->getExitPageUrlActionForLink()); - } - - /* - * SITE SEARCH - */ public function indexSiteSearch() { $view = new Piwik_View('@Actions/indexSiteSearch'); @@ -134,87 +57,6 @@ public function indexSiteSearch() echo $view->render(); } - public function getSiteSearchKeywords($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getSiteSearchKeywords'); - $this->configureViewSiteSearchKeywords($view); - return $this->renderView($view, $fetch); - } - - public function getSiteSearchNoResultKeywords($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getSiteSearchNoResultKeywords'); - $this->configureViewSiteSearchKeywords($view); - $view->setColumnsToDisplay(array('label', 'nb_visits', 'exit_rate')); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnNoResultKeyword')); - return $this->renderView($view, $fetch); - } - - public function configureViewSiteSearchKeywords(Piwik_ViewDataTable $view) - { - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnSearchKeyword')); - $view->setColumnsToDisplay(array('label', 'nb_visits', 'nb_pages_per_search', 'exit_rate')); - $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnSearches')); - $view->setColumnTranslation('exit_rate', str_replace("% ", "% ", Piwik_Translate('Actions_ColumnSearchExits'))); - $view->setColumnTranslation('nb_pages_per_search', Piwik_Translate('Actions_ColumnPagesPerSearch')); - $view->disableShowBarChart(); - $view->disableShowAllColumns(); - } - - public function getSiteSearchCategories($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getSiteSearchCategories'); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnSearchCategory')); - $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnSearches')); - $view->setColumnsToDisplay(array('label', 'nb_visits', 'nb_pages_per_search')); - $view->setColumnTranslation('nb_pages_per_search', Piwik_Translate('Actions_ColumnPagesPerSearch')); - $view->disableShowAllColumns(); - $view->disableShowBarChart(); - $view->disableRowEvolution(); - return $this->renderView($view, $fetch); - } - - - public function getPageUrlsFollowingSiteSearch($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getPageUrlsFollowingSiteSearch', 'getPageUrlsFollowingSiteSearch'); - $view->addRelatedReports(Piwik_Translate('Actions_WidgetPageUrlsFollowingSearch'), array( - 'Actions.getPageTitlesFollowingSiteSearch' => Piwik_Translate('Actions_WidgetPageTitlesFollowingSearch'), - )); - $view = $this->configureViewPagesFollowingSiteSearch($view); - return $this->renderView($view, $fetch); - } - - public function getPageTitlesFollowingSiteSearch($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getPageTitlesFollowingSiteSearch', 'getPageTitlesFollowingSiteSearch'); - $view->addRelatedReports(Piwik_Translate('Actions_WidgetPageTitlesFollowingSearch'), array( - 'Actions.getPageUrlsFollowingSiteSearch' => Piwik_Translate('Actions_WidgetPageUrlsFollowingSearch'), - )); - $view = $this->configureViewPagesFollowingSiteSearch($view); - return $this->renderView($view, $fetch); - } - - public function configureViewPagesFollowingSiteSearch($view) - { - $view->setColumnsToDisplay(array('label', 'nb_hits_following_search', 'nb_hits')); - $view->setColumnTranslation('nb_hits_following_search', Piwik_Translate('General_ColumnViewedAfterSearch')); - $view->setColumnTranslation('label', Piwik_Translate('General_ColumnDestinationPage')); - $view->setSortedColumn('nb_hits_following_search'); - $view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnTotalPageviews')); - $view->disableExcludeLowPopulation(); - $view = $this->configureViewActions($view, $doSetTranslations = false); - return $view; - } - - /* - * PAGE TITLES - */ public function indexPageTitles($fetch = false) { return Piwik_View::singleReport( @@ -222,93 +64,6 @@ public function indexPageTitles($fetch = false) $this->getPageTitles(true), $fetch); } - public function getPageTitles($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getPageTitles', - 'getPageTitlesSubDataTable'); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnPageName')); - $view->addRelatedReports(Piwik_Translate('Actions_SubmenuPageTitles'), array( - 'Actions.getEntryPageTitles' => Piwik_Translate('Actions_EntryPageTitles'), - 'Actions.getExitPageTitles' => Piwik_Translate('Actions_ExitPageTitles'), - )); - $view->setReportUrl('Actions', $this->getPageTitlesActionForLink()); - $this->configureViewPages($view); - $this->configureViewActions($view); - return $this->renderView($view, $fetch); - } - - public function getPageTitlesSubDataTable($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getPageTitles', - 'getPageTitlesSubDataTable'); - $this->configureViewPages($view); - $this->configureViewActions($view); - return $this->renderView($view, $fetch); - } - - /** - * Echos or returns a report displaying analytics data for every unique entry - * page title. - * - * @param bool $fetch True to return the view as a string, false to echo it. - * @return string - */ - public function getEntryPageTitles($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getEntryPageTitles', __FUNCTION__); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnEntryPageTitle')); - $view->setColumnTranslation('entry_bounce_count', Piwik_Translate('General_ColumnBounces')); - $view->setColumnTranslation('entry_nb_visits', Piwik_Translate('General_ColumnEntrances')); - $view->setColumnsToDisplay(array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate')); - - $entryPageUrlAction = $this->getEntryPageUrlActionForLink(); - $view->addRelatedReports(Piwik_Translate('Actions_EntryPageTitles'), array( - 'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'), - "Actions.$entryPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesEntry'), - )); - - $this->configureViewActions($view); - - return $this->renderView($view, $fetch); - } - - /** - * Echos or returns a report displaying analytics data for every unique exit - * page title. - * - * @param bool $fetch True to return the view as a string, false to echo it. - * @return string - */ - public function getExitPageTitles($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Actions.getExitPageTitles', __FUNCTION__); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnExitPageTitle')); - $view->setColumnTranslation('exit_nb_visits', Piwik_Translate('General_ColumnExits')); - $view->setColumnsToDisplay(array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate')); - - $exitPageUrlAction = $this->getExitPageUrlActionForLink(); - $view->addRelatedReports(Piwik_Translate('Actions_ExitPageTitles'), array( - 'Actions.getPageTitles' => Piwik_Translate('Actions_SubmenuPageTitles'), - "Actions.$exitPageUrlAction" => Piwik_Translate('Actions_SubmenuPagesExit'), - )); - - $this->configureViewActions($view); - - return $this->renderView($view, $fetch); - } - - /* - * DOWNLOADS - */ - public function indexDownloads($fetch = false) { return Piwik_View::singleReport( @@ -316,202 +71,79 @@ public function indexDownloads($fetch = false) $this->getDownloads(true), $fetch); } - public function getDownloads($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getDownloads', - 'getDownloadsSubDataTable'); - - $this->configureViewDownloads($view); - return $this->renderView($view, $fetch); - } - - public function getDownloadsSubDataTable($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getDownloads', - 'getDownloadsSubDataTable'); - $this->configureViewDownloads($view); - return $this->renderView($view, $fetch); - } - - - /* - * OUTLINKS - */ - public function indexOutlinks($fetch = false) { return Piwik_View::singleReport( Piwik_Translate('Actions_SubmenuOutlinks'), $this->getOutlinks(true), $fetch); } - - public function getOutlinks($fetch = false) + + // + // Actions that render individual reports + // + + public function getPageUrls($fetch = false) { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getOutlinks', - 'getOutlinksSubDataTable'); - $this->configureViewOutlinks($view); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - - public function getOutlinksSubDataTable($fetch = false) + + public function getEntryPageUrls($fetch = false) { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, - __FUNCTION__, - 'Actions.getOutlinks', - 'getOutlinksSubDataTable'); - $this->configureViewOutlinks($view); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /* - * Page titles & Page URLs reports - */ - protected function configureViewActions($view, $doSetTranslations = true) + public function getExitPageUrls($fetch = false) { - if ($doSetTranslations) { - $view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnPageviews')); - $view->setColumnTranslation('nb_visits', Piwik_Translate('General_ColumnUniquePageviews')); - $view->setColumnTranslation('avg_time_on_page', Piwik_Translate('General_ColumnAverageTimeOnPage')); - $view->setColumnTranslation('bounce_rate', Piwik_Translate('General_ColumnBounceRate')); - $view->setColumnTranslation('exit_rate', Piwik_Translate('General_ColumnExitRate')); - $view->setColumnTranslation('avg_time_generation', Piwik_Translate('General_ColumnAverageGenerationTime')); - - $view->queueFilter('ColumnCallbackReplace', array('avg_time_on_page', array('Piwik', 'getPrettyTimeFromSeconds'))); - - $avgTimeCallback = create_function('$time', 'return $time ? Piwik::getPrettyTimeFromSeconds($time, true, true, false) : "-";'); - $view->queueFilter('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback)); - - $tooltipCallback = create_function('$hits, $min, $max', ' - return $hits ? - Piwik_Translate("Actions_AvgGenerationTimeTooltip", array( - $hits, "
", - Piwik::getPrettyTimeFromSeconds($min), - Piwik::getPrettyTimeFromSeconds($max) - )) - : false;'); - $view->queueFilter('ColumnCallbackAddMetadata', array( - array('nb_hits_with_time_generation', 'min_time_generation', 'max_time_generation'), - 'avg_time_generation_tooltip', $tooltipCallback)); - } - - if (Piwik_Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') != '0') { - // computing minimum value to exclude - $visitsInfo = Piwik_VisitsSummary_Controller::getVisitsSummary(); - $visitsInfo = $visitsInfo->getFirstRow(); - $nbActions = $visitsInfo->getColumn('nb_actions'); - $nbActionsLowPopulationThreshold = floor(0.02 * $nbActions); // 2 percent of the total number of actions - // we remove 1 to make sure some actions/downloads are displayed in the case we have a very few of them - // and each of them has 1 or 2 hits... - $nbActionsLowPopulationThreshold = min($visitsInfo->getColumn('max_actions') - 1, $nbActionsLowPopulationThreshold - 1); - - $view->setExcludeLowPopulation('nb_hits', $nbActionsLowPopulationThreshold); - } - - $this->configureGenericViewActions($view); - return $view; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /* - * Downloads report - */ - protected function configureViewDownloads($view) + public function getSiteSearchKeywords($fetch = false) { - $view->setColumnsToDisplay(array('label', 'nb_visits', 'nb_hits')); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnDownloadURL')); - $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueDownloads')); - $view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnDownloads')); - $view->disableExcludeLowPopulation(); - $this->configureGenericViewActions($view); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /* - * Outlinks report - */ - protected function configureViewOutlinks($view) + public function getSiteSearchNoResultKeywords($fetch = false) { - $view->setColumnsToDisplay(array('label', 'nb_visits', 'nb_hits')); - $view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnClickedURL')); - $view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueClicks')); - $view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnClicks')); - $view->disableExcludeLowPopulation(); - $this->configureGenericViewActions($view); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /* - * Common to all Actions reports, how to use the custom Actions Datatable html - */ - protected function configureGenericViewActions($view) + public function getSiteSearchCategories($fetch = false) { - $view->setDataTableCssClass('dataTableActions'); - $view->setJsType('actionDataTable'); - $view->setSubtableTemplate('@CoreHome/_dataTableActions_subDataTable.twig'); - - $view->setSearchRecursive(); - if (Piwik_ViewDataTable::shouldLoadExpanded()) { - $view->showExpanded(); - - // set levelN css class for each row - $self = $this; - $view->queueFilter(function ($dataTable) use ($self) { - $self->setDataTableRowLevels($dataTable); - }); - } - // disable Footer icons - $view->disableShowAllViewsIcons(); - $view->disableShowAllColumns(); - - $view->setLimit(self::ACTIONS_REPORT_ROWS_DISPLAY); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } - // if the flat parameter is not provided, make sure it is set to 0 in the URL, - // so users can see that they can set it to 1 (see #3365) - if (Piwik_Common::getRequestVar('flat', false) === false) { - $view->setCustomParameter('flat', 0); - } + public function getPageUrlsFollowingSiteSearch($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } - $view->main(); + public function getPageTitlesFollowingSiteSearch($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - - public function setDataTableRowLevels($dataTable, $level = 0) + + public function getPageTitles($fetch = false) { - foreach ($dataTable->getRows() as $row) { - $row->setMetadata('css_class', 'level'.$level); - - $subtable = $row->getSubtable(); - if ($subtable) { - $this->setDataTableRowLevels($subtable, $level + 1); - } - } + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** Returns action to use when linking to the exit page URLs report. */ - private function getExitPageUrlActionForLink() + public function getEntryPageTitles($fetch = false) { - // link to the page not, just the report, but only if not a widget - return Piwik_Common::getRequestVar('widget', 0) == 0 ? 'indexExitPageUrls' : 'getExitPageUrls'; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } + public function getExitPageTitles($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } - /** Returns action to use when linking to the entry page URLs report. */ - private function getEntryPageUrlActionForLink() + public function getDownloads($fetch = false) { - // link to the page not, just the report, but only if not a widget - return Piwik_Common::getRequestVar('widget', 0) == 0 ? 'indexEntryPageUrls' : 'getEntryPageUrls'; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** Returns action to use when linking to the page titles report. */ - private function getPageTitlesActionForLink() + public function getOutlinks($fetch = false) { - // link to the page not, just the report, but only if not a widget - return Piwik_Common::getRequestVar('widget', 0) == 0 ? 'indexPageTitles' : 'getPageTitles'; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } } diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php index 47edc746c9e..a95fea8120b 100644 --- a/plugins/Goals/Controller.php +++ b/plugins/Goals/Controller.php @@ -82,74 +82,6 @@ public function ecommerceReport() echo $view->render(); } - protected function getItemsView($fetch, $type, $function, $api, $abandonedCart = false) - { - $label = Piwik_Translate($type); - $abandonedCart = Piwik_Common::getRequestVar('viewDataTable', 'ecommerceOrder', 'string') == 'ecommerceAbandonedCart'; - - // Products in Ecommerce Orders - if ($abandonedCart === false) { - $view = new Piwik_ViewDataTable_HtmlTable(); - $view->setCustomParameter('viewDataTable', Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER); - $columns = Piwik_Goals::getProductReportColumns(); - $view->setMetricDocumentation('revenue', Piwik_Translate('Goals_ColumnRevenueDocumentation', Piwik_Translate('Goals_DocumentationRevenueGeneratedByProductSales'))); - $view->setMetricDocumentation('quantity', Piwik_Translate('Goals_ColumnQuantityDocumentation', $label)); - $view->setMetricDocumentation('orders', Piwik_Translate('Goals_ColumnOrdersDocumentation', $label)); - $view->setMetricDocumentation('avg_price', Piwik_Translate('Goals_ColumnAveragePriceDocumentation', $label)); - $view->setMetricDocumentation('avg_quantity', Piwik_Translate('Goals_ColumnAverageQuantityDocumentation', $label)); - $view->setMetricDocumentation('nb_visits', Piwik_Translate('Goals_ColumnVisitsProductDocumentation', $label)); - $view->setMetricDocumentation('conversion_rate', Piwik_Translate('Goals_ColumnConversionRateProductDocumentation', $label)); - } // Products in Abandoned Carts - else { - $view = new Piwik_ViewDataTable_HtmlTable(); - $view->setCustomParameter('viewDataTable', Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART); - $columns = Piwik_Goals::getProductReportColumns(); - $columns['abandoned_carts'] = Piwik_Translate('General_AbandonedCarts'); - $columns['revenue'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_ProductRevenue')); - $columns['quantity'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_Quantity')); - $columns['avg_quantity'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_AverageQuantity')); - unset($columns['orders']); - unset($columns['conversion_rate']); - $view->setRequestStringSuffix('&abandonedCarts=1'); - } - - $view->init($this->pluginName, $function, $api); - $view->enableShowEcommerce(); - $view->disableShowAllViewsIcons(); - $view->disableShowTable(); - $view->disableExcludeLowPopulation(); - $view->disableShowAllColumns(); - $this->setPeriodVariablesView($view); - $view->setLimit(10); - - $view->setColumnsTranslations(array_merge( - array('label' => $label), - $columns - )); - $columnsToDisplay = array_merge(array('label'), array_keys($columns)); - $view->setColumnsToDisplay($columnsToDisplay); - $view->setSortedColumn('revenue', 'desc'); - foreach (array('revenue', 'avg_price') as $column) { - $view->queueFilter('ColumnCallbackReplace', array($column, array("Piwik", "getPrettyMoney"), array($this->idSite))); - } - return $this->renderView($view, $fetch); - } - - public function getItemsSku($fetch = false) - { - return $this->getItemsView($fetch, 'Goals_ProductSKU', __FUNCTION__, "Goals.getItemsSku"); - } - - public function getItemsName($fetch = false) - { - return $this->getItemsView($fetch, 'Goals_ProductName', __FUNCTION__, "Goals.getItemsName"); - } - - public function getItemsCategory($fetch = false) - { - return $this->getItemsView($fetch, 'Goals_ProductCategory', __FUNCTION__, "Goals.getItemsCategory"); - } - public function getEcommerceLog($fetch = false) { $saveGET = $_GET; @@ -450,48 +382,6 @@ protected function getMetricsForGoal($idGoal) return $return; } - /** - * Gets the 'visits to conversion' report using the requested view type. - */ - public function getVisitsUntilConversion($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Goals.getVisitsUntilConversion', 'getVisitsUntilConversion'); - $view->disableSearchBox(); - $view->disableExcludeLowPopulation(); - $view->disableSubTableWhenShowGoals(); - $view->disableShowAllColumns(); - $view->setColumnsToDisplay(array('label', 'nb_conversions')); - $view->setSortedColumn('label', 'asc'); - $view->setColumnTranslation('label', Piwik_Translate('Goals_VisitsUntilConv')); - $view->setColumnTranslation('nb_conversions', Piwik_Translate('Goals_ColumnConversions')); - $view->setLimit(count(Piwik_Goals_Archiver::$visitCountRanges)); - $view->disableOffsetInformationAndPaginationControls(); - $view->disableShowAllViewsIcons(); - return $this->renderView($view, $fetch); - } - - /** - * Gets the 'days to conversion' report using the requested view type. - */ - public function getDaysToConversion($fetch = false) - { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, 'Goals.getDaysToConversion', 'getDaysToConversion'); - $view->disableSearchBox(); - $view->disableExcludeLowPopulation(); - $view->disableSubTableWhenShowGoals(); - $view->disableShowAllColumns(); - $view->setColumnsToDisplay(array('label', 'nb_conversions')); - $view->setSortedColumn('label', 'asc'); - $view->setColumnTranslation('label', Piwik_Translate('Goals_DaysToConv')); - $view->setColumnTranslation('nb_conversions', Piwik_Translate('Goals_ColumnConversions')); - $view->disableShowAllViewsIcons(); - $view->setLimit(count(Piwik_Goals_Archiver::$daysToConvRanges)); - $view->disableOffsetInformationAndPaginationControls(); - return $this->renderView($view, $fetch); - } - /** * Utility function that returns HTML that displays Goal information for reports. This * is the HTML that is at the bottom of every goals page. @@ -553,4 +443,33 @@ private function getGoalReportsByDimensionTable($conversions, $ecommerce = false return $goalReportsByDimension->render(); } + + // + // Report rendering actions + // + + public function getItemsSku($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } + + public function getItemsName($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } + + public function getItemsCategory($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } + + public function getVisitsUntilConversion($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } + + public function getDaysToConversion($fetch = false) + { + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); + } } diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php index 855adb9e302..146c8a26593 100644 --- a/plugins/Goals/Goals.php +++ b/plugins/Goals/Goals.php @@ -87,6 +87,7 @@ function getListHooksRegistered() 'Menu.add' => 'addMenus', 'SitesManager.deleteSite' => 'deleteSiteGoals', 'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics', + 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties', // TODO: ViewDataTable should get ALL once ); return $hooks; } @@ -494,4 +495,133 @@ public function archivePeriod(Piwik_ArchiveProcessor_Period $archiveProcessor) $archiving->archivePeriod(); } } + + public function getReportDisplayProperties(&$properties, $apiAction) + { + $reportViewProperties = array( + 'Goals.getItemsSku' => $this->getDisplayPropertiesForGetItemsSku(), + 'Goals.getItemsName' => $this->getDisplayPropertiesForGetItemsName(), + 'Goals.getItemsCategory' => $this->getDisplayPropertiesForGetItemsCategory(), + 'Goals.getVisitsUntilConversion' => $this->getDisplayPropertiesForGetVisitsUntilConversion(), + 'Goals.getDaysToConversion' => $this->getDisplayPropertiesForGetDaysToConversion(), + ); + + if (isset($reportViewProperties[$apiAction])) { + $properties = $reportViewProperties[$apiAction]; + } + } + + private function getDisplayPropertiesForGetItemsSku() + { + return $this->getDisplayPropertiesForItemsReport(Piwik_Translate('Goals_ProductSKU')); + } + + private function getDisplayPropertiesForGetItemsName() + { + return $this->getDisplayPropertiesForItemsReport(Piwik_Translate('Goals_ProductName')); + } + + private function getDisplayPropertiesForGetItemsCategory() + { + return $this->getDisplayPropertiesForItemsReport(Piwik_Translate('Goals_ProductCategory')); + } + + private function getDisplayPropertiesForGetVisitsUntilConversion() + { + return array( + 'show_search' => false, + 'show_exclude_low_population' => false, + 'show_table_all_columns' => false, + 'columns_to_display' => array('label', 'nb_conversions'), + 'filter_sort_column' => 'label', + 'filter_sort_order' => 'asc', + 'translations' => array( + 'label' => Piwik_Translate('Goals_VisitsUntilConv'), + 'nb_conversions' => Piwik_Translate('Goals_ColumnConversions'), + ), + 'filter_limit' => count(Piwik_Goals_Archiver::$visitCountRanges), + 'show_offset_information' => false, + 'show_pagination_control' => false, + 'show_all_views_icons' => false + ); + } + + private function getDisplayPropertiesForGetDaysToConversion() + { + return array( + 'show_search' => false, + 'show_exclude_low_population' => false, + 'show_table_all_columns' => false, + 'columns_to_display' => array('label', 'nb_conversions'), + 'filter_sort_column' => 'label', + 'filter_sort_order' => 'asc', + 'translations' => array( + 'label' => Piwik_Translate('Goals_DaysToConv'), + 'nb_conversions' => Piwik_Translate('Goals_ColumnConversions'), + ), + 'filter_limit' => count(Piwik_Goals_Archiver::$daysToConvRanges), + 'show_all_views_icons' => false, + 'show_offset_information' => false, + 'show_pagination_control' => false, + ); + } + + private function getDisplayPropertiesForItemsReport($label) + { + $idSite = Piwik_Common::getRequestVar('idSite'); + + $moneyColumns = array('revenue', 'avg_price'); + $prettifyMoneyColumns = array( + 'ColumnCallbackReplace', array($moneyColumns, array("Piwik", "getPrettyMoney"), array($idSite))); + + $result = array( + 'show_ecommerce' => true, + 'show_all_views_icons' => false, + 'show_table' => false, + 'show_exclude_low_population' => false, + 'show_table_all_columns' => false, + 'filter_limit' => 10, + 'translations' => array('label' => $label), + 'filter_sort_column' => 'revenue', + 'filter_sort_order' => 'desc', + 'filters' => array($prettifyMoneyColumns) + ); + + // set columns/translations which differ based on viewDataTable TODO: shouldn't have to do this check... amount of reports should be dynamic, but metadata should be static + $columns = Piwik_Goals::getProductReportColumns(); + + $abandonedCart = Piwik_Common::getRequestVar('viewDataTable', 'ecommerceOrder', 'string') == 'ecommerceAbandonedCart'; + if ($abandonedCart) { + $columns['abandoned_carts'] = Piwik_Translate('General_AbandonedCarts'); + $columns['revenue'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_ProductRevenue')); + $columns['quantity'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_Quantity')); + $columns['avg_quantity'] = Piwik_Translate('Goals_LeftInCart', Piwik_Translate('General_AverageQuantity')); + unset($columns['orders']); + unset($columns['conversion_rate']); + + $result['request_string_suffix'] = '&abandonedCarts=1'; + } + + $result['translations'] = array_merge(array('label' => $label), $columns); + $result['columns_to_display'] = array_keys($result['translations']); + + // set metrics documentation in normal ecommerce report + if (!$abandonedCart) { + $result['metrics_documentation'] = array( + 'revenue' => Piwik_Translate('Goals_ColumnRevenueDocumentation', + Piwik_Translate('Goals_DocumentationRevenueGeneratedByProductSales')), + 'quantity' => Piwik_Translate('Goals_ColumnQuantityDocumentation', $label), + 'orders' => Piwik_Translate('Goals_ColumnOrdersDocumentation', $label), + 'avg_price' => Piwik_Translate('Goals_ColumnAveragePriceDocumentation', $label), + 'avg_quantity' => Piwik_Translate('Goals_ColumnAverageQuantityDocumentation', $label), + 'nb_visits' => Piwik_Translate('Goals_ColumnVisitsProductDocumentation', $label), + 'conversion_rate' => Piwik_Translate('Goals_ColumnConversionRateProductDocumentation', $label), + ); + } + + $result['custom_parameters']['viewDataTable'] = + $abandonedCart ? Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART : Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER; + + return $result; + } } diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php index f5c78937839..515eacf118d 100644 --- a/plugins/UserSettings/Controller.php +++ b/plugins/UserSettings/Controller.php @@ -15,19 +15,7 @@ */ class Piwik_UserSettings_Controller extends Piwik_Controller { - /** The set of related reports displayed under the 'Operating Systems' header. */ - private $osRelatedReports = null; - - public function __construct() - { - parent::__construct(); - $this->osRelatedReports = array( - 'UserSettings.getOSFamily' => Piwik_Translate('UserSettings_OperatingSystemFamily'), - 'UserSettings.getOS' => Piwik_Translate('UserSettings_OperatingSystems') - ); - } - - function index() + public function index() { $view = new Piwik_View('@UserSettings/index'); @@ -42,172 +30,59 @@ function index() echo $view->render(); } - - function getResolution($fetch = false) + + public function getResolution($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getResolution' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnResolution')); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - - function getConfiguration($fetch = false) + + public function getConfiguration($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getConfiguration' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnConfiguration')); - $view->setLimit(3); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - function getOS($fetch = false) + public function getOS($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getOS' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnOperatingSystem')); - $view->addRelatedReports(Piwik_Translate('UserSettings_OperatingSystems'), $this->osRelatedReports); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** - * Returns or echos a report displaying the number of visits by operating system family. - */ public function getOSFamily($fetch = false) { - $view = $this->getStandardDataTableUserSettings(__FUNCTION__, 'UserSettings.getOSFamily'); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_OperatingSystemFamily')); - $view->addRelatedReports(Piwik_Translate('UserSettings_OperatingSystemFamily'), $this->osRelatedReports); - return $this->renderView($view, $fetch); - } - - function getBrowserVersion($fetch = false) - { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getBrowserVersion' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnBrowserVersion')); - $view->setGraphLimit(7); - $view->addRelatedReports(Piwik_Translate('UserSettings_ColumnBrowserVersion'), array( - 'UserSettings.getBrowser' => Piwik_Translate('UserSettings_Browsers') - )); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** - * Returns or echos a report displaying the number of visits by browser type. The browser - * version is not included in this report. - */ - public function getBrowser($fetch = false) + public function getMobileVsDesktop($fetch = false) { - $view = $this->getStandardDataTableUserSettings(__FUNCTION__, 'UserSettings.getBrowser'); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnBrowser')); - $view->setGraphLimit(7); - $view->addRelatedReports(Piwik_Translate('UserSettings_Browsers'), array( - 'UserSettings.getBrowserVersion' => Piwik_Translate('UserSettings_ColumnBrowserVersion') - )); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - function getBrowserType($fetch = false) + public function getBrowserVersion($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getBrowserType', - 'graphPie' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnBrowserFamily')); - $view->disableOffsetInformationAndPaginationControls(); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - function getWideScreen($fetch = false) + public function getBrowser($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getWideScreen' - ); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnTypeOfScreen')); - $view->disableOffsetInformationAndPaginationControls(); - $view->addRelatedReports(Piwik_Translate('UserSettings_ColumnTypeOfScreen'), array( - 'UserSettings.getMobileVsDesktop' => Piwik_Translate('UserSettings_MobileVsDesktop') - )); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** - * Returns or echos a report displaying the number of visits by device type (Mobile or Desktop). - */ - public function getMobileVsDesktop($fetch = false) + public function getBrowserType($fetch = false) { - $view = $this->getStandardDataTableUserSettings(__FUNCTION__, 'UserSettings.getMobileVsDesktop'); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_MobileVsDesktop')); - $view->addRelatedReports(Piwik_Translate('UserSettings_MobileVsDesktop'), array( - 'UserSettings.getWideScreen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen') - )); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - function getPlugin($fetch = false) + public function getWideScreen($fetch = false) { - $view = $this->getStandardDataTableUserSettings( - __FUNCTION__, - 'UserSettings.getPlugin' - ); - $view->disableShowAllViewsIcons(); - $view->disableShowAllColumns(); - $view->disableOffsetInformationAndPaginationControls(); - $view->setColumnsToDisplay(array('label', 'nb_visits_percentage', 'nb_visits')); - $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnPlugin')); - $view->setColumnTranslation('nb_visits_percentage', Piwik_Metrics::getPercentVisitColumn()); - $view->setSortedColumn('nb_visits_percentage'); - $view->setLimit(10); - $view->setFooterMessage(Piwik_Translate('UserSettings_PluginDetectionDoesNotWorkInIE')); - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - protected function getStandardDataTableUserSettings($currentControllerAction, - $APItoCall, - $defaultDatatableType = null) + public function getPlugin($fetch = false) { - $view = Piwik_ViewDataTable::factory($defaultDatatableType); - $view->init($this->pluginName, $currentControllerAction, $APItoCall); - $view->disableSearchBox(); - $view->disableExcludeLowPopulation(); - $view->setLimit(5); - $view->setGraphLimit(5); - - $this->setPeriodVariablesView($view); - $this->setMetricsVariablesView($view); - - return $view; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } - /** - * Renders datatable for browser language - * - * @param bool $fetch - * - * @return string|void - */ public function getLanguage($fetch = false) { - $view = Piwik_ViewDataTable::factory(); - $view->init($this->pluginName, __FUNCTION__, "UserSettings.getLanguage"); - $view->disableExcludeLowPopulation(); - - $view->setColumnsToDisplay(array('label', 'nb_visits')); - $view->setColumnTranslation('label', Piwik_Translate('General_Language')); - $view->setSortedColumn('nb_visits'); - $view->disableSearchBox(); - $view->setLimit(5); - - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } -} \ No newline at end of file +} diff --git a/plugins/UserSettings/UserSettings.php b/plugins/UserSettings/UserSettings.php index e7a15f9e792..9097213fa72 100644 --- a/plugins/UserSettings/UserSettings.php +++ b/plugins/UserSettings/UserSettings.php @@ -171,15 +171,128 @@ public function getInformation() function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessing_Day.compute' => 'archiveDay', - 'ArchiveProcessing_Period.compute' => 'archivePeriod', - 'WidgetsList.add' => 'addWidgets', - 'Menu.add' => 'addMenu', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties', ); return $hooks; } + + public function getReportDisplayProperties(&$properties, $apiAction) + { + $basicUserSettingsProperties = array('show_search' => false, + 'show_exclude_low_population' => false, + 'filter_limit' => 5, + 'graph_limit' => 5); + + $osRelatedReports = array( + 'UserSettings.getOSFamily' => Piwik_Translate('UserSettings_OperatingSystemFamily'), + 'UserSettings.getOS' => Piwik_Translate('UserSettings_OperatingSystems') + ); + + $browserRelatedReports = array( + 'UserSettings.getBrowser' => Piwik_Translate('UserSettings_Browsers'), + 'UserSettings.getBrowserVersion' => Piwik_Translate('UserSettings_ColumnBrowserVersion') + ); + + $wideScreenDeviceTypeRelatedReports = array( + 'UserSettings.getMobileVsDesktop' => Piwik_Translate('UserSettings_MobileVsDesktop'), + 'UserSettings.getWideScreen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen') + ); + + $reportViewProperties = array( + 'UserSettings.getResolution' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnResolution')) + )), + + 'UserSettings.getConfiguration' => array_merge($basicUserSettingsProperties, array( + 'filter_limit' => 3, + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnConfiguration')) + )), + + 'UserSettings.getOS' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnOperatingSystem')), + 'title' => Piwik_Translate('UserSettings_OperatingSystems'), + 'relatedReports' => $osRelatedReports + )), + + 'UserSettings.getOSFamily' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_OperatingSystemFamily')), + 'title' => Piwik_Translate('UserSettings_OperatingSystemFamily'), + 'relatedReports' => $osRelatedReports + )), + + 'UserSettings.getBrowserVersion' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserVersion')), + 'graph_limit' => 7, + 'title' => Piwik_Translate('UserSettings_ColumnBrowserVersion'), + 'relatedReports' => $browserRelatedReports + )), + + 'UserSettings.getBrowser' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowser')), + 'graph_limit' => 7, + 'title' => Piwik_Translate('UserSettings_Browsers'), + 'relatedReports' => $browserRelatedReports + )), + + 'UserSettings.getBrowserType' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnBrowserFamily')), + 'show_offset_information' => false, + 'show_pagination_control' => false, + 'default_view_type' => 'graphPie', + )), + + 'UserSettings.getWideScreen' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_ColumnTypeOfScreen')), + 'show_offset_information' => false, + 'show_pagination_control' => false, + 'title' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'), + 'relatedReports' => $wideScreenDeviceTypeRelatedReports + )), + + 'UserSettings.getMobileVsDesktop' => array_merge($basicUserSettingsProperties, array( + 'translations' => array('label' => Piwik_Translate('UserSettings_MobileVsDesktop')), + 'title' => Piwik_Translate('UserSettings_MobileVsDesktop'), + 'relatedReports' => $wideScreenDeviceTypeRelatedReports + )), + + 'UserSettings.getPlugin' => array_merge($basicUserSettingsProperties, array( + 'translations' => array( + 'label' => Piwik_Translate('UserSettings_ColumnPlugin'), + 'nb_visits_percentage' => + str_replace(' ', ' ', Piwik_Translate('General_ColumnPercentageVisits')) + ), + 'show_offset_information' => false, + 'show_pagination_control' => false, + 'show_all_views_icons' => false, + 'show_table_all_columns' => false, + 'columns_to_display' => array('label', 'nb_visits_percentage', 'nb_visits'), + 'filter_sort_column' => 'nb_visits_percentage', + 'filter_sort_order' => 'desc', + 'filter_limit' => 10, + 'show_footer_message' => Piwik_Translate('UserSettings_PluginDetectionDoesNotWorkInIE'), + )), + + 'UserSettings.getLanguage' => array( + 'translations' => array('label' => Piwik_Translate('General_Language')), + 'filter_sort_column' => 'nb_visits', + 'filter_sort_order' => 'desc', + 'show_search' => false, + 'filter_limit' => false, + 'columns_to_display' => array('label', 'nb_visits'), + 'show_exclude_low_population' => false, + ), + ); + + if (isset($reportViewProperties[$apiAction])) { + $properties = $reportViewProperties[$apiAction]; + } + } /** * Registers reports metadata diff --git a/plugins/VisitTime/Controller.php b/plugins/VisitTime/Controller.php index 769c1027615..600262625cc 100644 --- a/plugins/VisitTime/Controller.php +++ b/plugins/VisitTime/Controller.php @@ -25,83 +25,16 @@ public function index() public function getVisitInformationPerServerTime($fetch = false) { - $view = $this->getGraph(__FUNCTION__, 'VisitTime.getVisitInformationPerServerTime', - 'VisitTime_ColumnServerTime'); - - $view->setCustomParameter('hideFutureHoursWhenToday', 1); - $view->enableShowGoals(); - - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } public function getVisitInformationPerLocalTime($fetch = false) { - $view = $this->getGraph(__FUNCTION__, 'VisitTime.getVisitInformationPerLocalTime', - 'VisitTime_ColumnLocalTime'); - - // add the visits by day of week as a related report, if the current period is not 'day' - if (Piwik_Common::getRequestVar('period', 'day') != 'day') { - $view->addRelatedReports(Piwik_Translate('VisitTime_LocalTime'), array( - 'VisitTime.getByDayOfWeek' => Piwik_Translate('VisitTime_VisitsByDayOfWeek') - )); - } - - return $this->renderView($view, $fetch); + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } public function getByDayOfWeek($fetch = false) { - $view = $this->getGraph( - __FUNCTION__, 'VisitTime.getByDayOfWeek', 'VisitTime_DayOfWeek', $limit = 7, $sort = false); - $view->disableSort(); - - if ($view instanceof Piwik_ViewDataTable_GenerateGraphHTML) { - $view->showAllTicks(); - } - $dateRange = $this->getRangeDate(); - - $view->setFooterMessage(Piwik_Translate('General_ReportGeneratedFrom', $dateRange)); - - return $this->renderView($view, $fetch); - } - - protected function getRangeDate() - { - // get query params - $idSite = Piwik_Common::getRequestVar('idSite'); - $date = Piwik_Common::getRequestVar('date'); - $period = Piwik_Common::getRequestVar('period'); - - // create a period instance - $oPeriod = Piwik_Period::makePeriodFromQueryParams(Piwik_Site::getTimezoneFor($idSite), $period, $date); - - // set the footer message using the period start & end date - $start = $oPeriod->getDateStart()->toString(); - $end = $oPeriod->getDateEnd()->toString(); - if ($start == $end) { - $dateRange = $start; - } else { - $dateRange = $start . " – " . $end; - } - return $dateRange; - } - - private function getGraph($controllerMethod, $apiMethod, $labelTranslation, $limit = 24) - { - $view = Piwik_ViewDataTable::factory('graphVerticalBar'); - $view->init($this->pluginName, $controllerMethod, $apiMethod); - - - $view->setColumnTranslation('label', Piwik_Translate($labelTranslation)); - $view->setSortedColumn('label', 'asc'); - - $view->setLimit($limit); - $view->setGraphLimit($limit); - $view->disableSearchBox(); - $view->disableExcludeLowPopulation(); - $view->disableOffsetInformationAndPaginationControls(); - $this->setMetricsVariablesView($view); - - return $view; + return Piwik_ViewDataTable::render($this->pluginName, __FUNCTION__, $fetch); } } diff --git a/plugins/VisitTime/VisitTime.php b/plugins/VisitTime/VisitTime.php index 36ecd86f650..39934563e5a 100644 --- a/plugins/VisitTime/VisitTime.php +++ b/plugins/VisitTime/VisitTime.php @@ -29,13 +29,14 @@ public function getInformation() function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessing_Day.compute' => 'archiveDay', - 'ArchiveProcessing_Period.compute' => 'archivePeriod', - 'WidgetsList.add' => 'addWidgets', - 'Menu.add' => 'addMenu', - 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.getReportDisplayProperties' => 'getReportDisplayProperties', ); return $hooks; } @@ -117,6 +118,59 @@ public function getSegmentsMetadata(&$segments) 'acceptedValues' => $acceptedValues ); } + + public function getReportDisplayProperties(&$properties, $apiAction) + { + $commonProperties = array( + 'filter_sort_column' => 'label', + 'filter_sort_order' => 'asc', + 'show_search' => false, + 'show_exclude_low_population' => false, + 'show_offset_information' => false, + 'show_pagination_control' => false, + 'default_view_type' => 'graphVerticalBar' + ); + + $reportViewProperties = array( + 'VisitTime.getVisitInformationPerServerTime' => array_merge($commonProperties, array( + 'filter_limit' => 24, + 'graph_limit' => 24, + 'show_goals' => true, + 'translations' => array('label' => Piwik_Translate('VisitTime_ColumnServerTime')), + + // custom parameter + 'hideFutureHoursWhenToday' => 1, + )), + + 'VisitTime.getVisitInformationPerLocalTime' => array_merge($commonProperties, array( + 'filter_limit' => 24, + 'graph_limit' => 24, + 'title' => Piwik_Translate('VisitTime_ColumnLocalTime'), + 'translations' => array('label' => Piwik_Translate('VisitTime_LocalTime')), + )), + + 'VisitTime.getByDayOfWeek' => array_merge($commonProperties, array( + 'filter_limit' => 7, + 'graph_limit' => 7, + 'enable_sort' => false, + 'show_all_ticks' => true, + 'show_footer_message' => + Piwik_Translate('General_ReportGeneratedFrom', self::getDateRangeForFooterMessage()), + 'translations' => array('label' => Piwik_Translate('VisitTime_DayOfWeek')), + )), + ); + + // add the visits by day of week as a related report, if the current period is not 'day' + if (Piwik_Common::getRequestVar('period', 'day') != 'day') { + $reportViewProperties['VisitTime.getVisitInformationPerLocalTime']['relatedReports'] = array( + 'VisitTime.getByDayOfWeek' => Piwik_Translate('VisitTime_VisitsByDayOfWeek') + ); + } + + if (isset($reportViewProperties[$apiAction])) { + $properties = $reportViewProperties[$apiAction]; + } + } public function archivePeriod(Piwik_ArchiveProcessor_Period $archiveProcessor) { @@ -134,4 +188,25 @@ public function archiveDay(Piwik_ArchiveProcessor_Day $archiveProcessor) $archiving->archiveDay(); } } + + private static function getDateRangeForFooterMessage() + { + // get query params + $idSite = Piwik_Common::getRequestVar('idSite'); + $date = Piwik_Common::getRequestVar('date'); + $period = Piwik_Common::getRequestVar('period'); + + // create a period instance + $oPeriod = Piwik_Period::makePeriodFromQueryParams(Piwik_Site::getTimezoneFor($idSite), $period, $date); + + // set the footer message using the period start & end date + $start = $oPeriod->getDateStart()->toString(); + $end = $oPeriod->getDateEnd()->toString(); + if ($start == $end) { + $dateRange = $start; + } else { + $dateRange = $start . " – " . $end; + } + return $dateRange; + } }