addPropertiesThatShouldBeAvailableClientSide(array('columns')); return $config; } public function beforeRender() { if ($this->config->show_goals) { $this->config->translations['nb_conversions'] = Piwik::translate('Goals_ColumnConversions'); $this->config->translations['revenue'] = Piwik::translate('General_TotalRevenue'); } } public function beforeLoadDataTable() { // TODO: this should not be required here. filter_limit should not be a view property, instead HtmlTable should use 'limit' or something, // and manually set request_parameters_to_modify['filter_limit'] based on that. (same for filter_offset). $this->requestConfig->request_parameters_to_modify['filter_limit'] = false; if ($this->config->max_graph_elements) { $this->requestConfig->request_parameters_to_modify['filter_truncate'] = $this->config->max_graph_elements - 1; } $this->requestConfig->request_parameters_to_modify['format_metrics'] = 1; // if addTotalRow was called in GenerateGraphHTML, add a row containing totals of // different metrics if ($this->config->add_total_row) { $this->requestConfig->request_parameters_to_modify['totals'] = 1; $this->requestConfig->request_parameters_to_modify['keep_totals_row'] = 1; $this->requestConfig->request_parameters_to_modify['keep_totals_row_label'] = Piwik::translate('General_Total'); } $this->metricsFormatter = new Numeric(); } /** * Determines what rows are selectable and stores them in the selectable_rows property in * a format the SeriesPicker JavaScript class can use. */ public function determineWhichRowsAreSelectable() { if ($this->config->row_picker_match_rows_by === false) { return; } // collect all selectable rows $self = $this; $this->dataTable->filter(function ($dataTable) use ($self) { /** @var DataTable $dataTable */ foreach ($dataTable->getRows() as $row) { $rowLabel = $row->getColumn('label'); if (false === $rowLabel) { continue; } // build config if (!isset($self->selectableRows[$rowLabel])) { $self->selectableRows[$rowLabel] = array( 'label' => $rowLabel, 'matcher' => $rowLabel, 'displayed' => $self->isRowVisible($rowLabel) ); } } }); } public function isRowVisible($rowLabel) { $isVisible = true; if ('label' == $this->config->row_picker_match_rows_by) { $isVisible = in_array($rowLabel, $this->config->rows_to_display === false ? [] : $this->config->rows_to_display); } return $isVisible; } /** * Defaults the selectable_columns property if it has not been set and then transforms * it into something the SeriesPicker JavaScript class can use. */ public function afterAllFiltersAreApplied() { $this->determineWhichRowsAreSelectable(); // set default selectable columns, if none specified $selectableColumns = $this->config->selectable_columns; if (false === $selectableColumns) { $this->generateSelectableColumns(); } $this->ensureValidColumnsToDisplay(); $this->addTranslations(); $this->config->selectable_rows = array_values($this->selectableRows); } protected function addTranslations() { if ($this->config->add_total_row) { $totalTranslation = Piwik::translate('General_Total'); $this->config->selectable_rows[] = array( 'label' => $totalTranslation, 'matcher' => $totalTranslation, 'displayed' => $this->isRowVisible($totalTranslation) ); } if ($this->config->show_goals) { $this->config->addTranslations(array( 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), 'revenue' => Piwik::translate('General_TotalRevenue') )); } $transformed = array(); foreach ($this->config->selectable_columns as $column) { $transformed[] = array( 'column' => $column, 'translation' => @$this->config->translations[$column], 'displayed' => in_array($column, $this->config->columns_to_display) ); } $this->config->selectable_columns = $transformed; } protected function generateSelectableColumns() { $defaultColumns = $this->getDefaultColumnsToDisplay(); if ($this->config->show_goals) { $goalMetrics = array('nb_conversions', 'revenue'); $defaultColumns = array_merge($defaultColumns, $goalMetrics); } // Use the subset of default columns that are actually present in the datatable $allColumns = $this->getDataTable()->getColumns(); $selectableColumns = array_intersect($defaultColumns, $allColumns); // If there are no default columns, just strip out the 'label' column and use all the others if (empty($selectableColumns)) { $selectableColumns = $this->removeLabelFromArray($allColumns); } $this->config->selectable_columns = $selectableColumns; } private function removeLabelFromArray($theArray) { if (!empty($theArray) && is_array($theArray)) { $key = array_search('label', $theArray); if ($key !== false) { unset($theArray[$key]); $theArray = array_values($theArray); } } return $theArray; } protected function ensureValidColumnsToDisplay() { $columnsToDisplay = $this->config->columns_to_display; // Remove 'label' from columns to display if present $columnsToDisplay = $this->removeLabelFromArray($columnsToDisplay); // Strip out any columns_to_display that are not in the dataset $allColumns = []; if ($this->report) { $allColumns = $this->report->getAllMetrics(); } $allColumns = array_merge($allColumns, $this->getDataTable()->getColumns()); $dataTable = $this->getDataTable(); if ($dataTable instanceof DataTable\Map) { $dataTable = $dataTable->getFirstRow(); } /** @var ProcessedMetric[] $extraProcessedMetrics */ $extraProcessedMetrics = $dataTable->getMetadata(DataTable::EXTRA_PROCESSED_METRICS_METADATA_NAME); if (!empty($extraProcessedMetrics)) { $extraProcessedMetricNames = array_map(function (Metric $m) { return $m->getName(); }, $extraProcessedMetrics); $allColumns = array_merge($allColumns, $extraProcessedMetricNames); } $allColumns = array_unique($allColumns); // If the datatable has no data, use the default columns (there must be data for evolution graphs or else nothing displays) if (empty($allColumns)) { $allColumns = $this->getDefaultColumnsToDisplay(); } $this->config->columns_to_display = array_intersect($columnsToDisplay, $allColumns); } private function getDefaultColumnsToDisplay() { return array( 'nb_visits', 'nb_actions', 'nb_uniq_visitors', 'nb_users' ); } }