diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/API/DataTableGenericFilter.php | 2 | ||||
-rw-r--r-- | core/API/DataTableManipulator/LabelFilter.php | 7 | ||||
-rw-r--r-- | core/API/DataTableManipulator/ReportTotalsCalculator.php | 117 | ||||
-rw-r--r-- | core/API/DataTablePostProcessor.php | 4 | ||||
-rw-r--r-- | core/ArchiveProcessor.php | 42 | ||||
-rw-r--r-- | core/DataTable.php | 35 | ||||
-rw-r--r-- | core/DataTable/Filter/AddSegmentByLabel.php | 10 | ||||
-rw-r--r-- | core/DataTable/Filter/ColumnCallbackAddMetadata.php | 11 | ||||
-rw-r--r-- | core/DataTable/Filter/ColumnCallbackReplace.php | 5 | ||||
-rwxr-xr-x | core/DataTable/Filter/GroupBy.php | 10 | ||||
-rw-r--r-- | core/DataTable/Filter/MetadataCallbackAddMetadata.php | 10 | ||||
-rw-r--r-- | core/DataTable/Filter/ReplaceSummaryRowLabel.php | 14 | ||||
-rw-r--r-- | core/DataTable/Filter/Sort.php | 36 | ||||
-rw-r--r-- | core/DataTable/Filter/Truncate.php | 10 | ||||
-rw-r--r-- | core/Plugin/Report.php | 22 |
15 files changed, 211 insertions, 124 deletions
diff --git a/core/API/DataTableGenericFilter.php b/core/API/DataTableGenericFilter.php index ff49491642..1554703910 100644 --- a/core/API/DataTableGenericFilter.php +++ b/core/API/DataTableGenericFilter.php @@ -11,6 +11,7 @@ namespace Piwik\API; use Exception; use Piwik\Common; use Piwik\DataTable; +use Piwik\Plugin; use Piwik\Plugin\ProcessedMetric; use Piwik\Plugin\Report; @@ -120,6 +121,7 @@ class DataTableGenericFilter foreach ($filters as $index => $filter) { if ($filter[0] === 'Sort') { $filters[$index][1]['filter_sort_column'] = array('string', $this->report->getDefaultSortColumn()); + $filters[$index][1]['filter_sort_order'] = array('string', $this->report->getDefaultSortOrder()); } } } diff --git a/core/API/DataTableManipulator/LabelFilter.php b/core/API/DataTableManipulator/LabelFilter.php index 0d4e11772a..c691398a40 100644 --- a/core/API/DataTableManipulator/LabelFilter.php +++ b/core/API/DataTableManipulator/LabelFilter.php @@ -64,6 +64,10 @@ class LabelFilter extends DataTableManipulator */ private function doFilterRecursiveDescend($labelParts, $dataTable) { + // we need to make sure to rebuild the index as some filters change the label column directly via + // $row->setColumn('label', '') which would not be noticed in the label index otherwise. + $dataTable->rebuildIndex(); + // search for the first part of the tree search $labelPart = array_shift($labelParts); @@ -102,6 +106,9 @@ class LabelFilter extends DataTableManipulator protected function manipulateSubtableRequest($request) { unset($request['label']); + unset($request['flat']); + $request['totals'] = 0; + $request['filter_sort_column'] = ''; // do not sort, we only want to find a matching column return $request; } diff --git a/core/API/DataTableManipulator/ReportTotalsCalculator.php b/core/API/DataTableManipulator/ReportTotalsCalculator.php index 4703c36c7d..2631b43d5a 100644 --- a/core/API/DataTableManipulator/ReportTotalsCalculator.php +++ b/core/API/DataTableManipulator/ReportTotalsCalculator.php @@ -23,6 +23,31 @@ use Piwik\Plugin\Report; class ReportTotalsCalculator extends DataTableManipulator { /** + * Array [readableMetric] => [summed value] + * @var array + */ + private $totals = array(); + + /** + * @var Report + */ + private $report; + + /** + * Constructor + * + * @param bool $apiModule + * @param bool $apiMethod + * @param array $request + * @param Report $report + */ + public function __construct($apiModule = false, $apiMethod = false, $request = array(), $report = null) + { + parent::__construct($apiModule, $apiMethod, $request); + $this->report = $report; + } + + /** * @param DataTable $table * @return \Piwik\DataTable|\Piwik\DataTable\Map */ @@ -53,66 +78,32 @@ class ReportTotalsCalculator extends DataTableManipulator */ protected function manipulateDataTable($dataTable) { - $report = $this->findCurrentReport(); - - if (!empty($report) && !$report->getDimension() && !$this->isReportAllMetricsReport($report)) { + if (!empty($this->report) && !$this->report->getDimension() && !$this->isAllMetricsReport()) { // we currently do not calculate the total value for reports having no dimension return $dataTable; } - // Array [readableMetric] => [summed value] - $totalValues = array(); - + $this->totals = array(); $firstLevelTable = $this->makeSureToWorkOnFirstLevelDataTable($dataTable); $metricsToCalculate = Metrics::getMetricIdsToProcessReportTotal(); - $realMetricNames = array(); + $metricNames = array(); foreach ($metricsToCalculate as $metricId) { - $metricName = Metrics::getReadableColumnName($metricId); - $realMetricName = $this->hasDataTableMetric($firstLevelTable, $metricId, $metricName); - if (!empty($realMetricName)) { - $realMetricNames[$metricName] = $realMetricName; - } + $metricNames[$metricId] = Metrics::getReadableColumnName($metricId);; } foreach ($firstLevelTable->getRows() as $row) { $columns = $row->getColumns(); - foreach ($realMetricNames as $metricName => $realMetricName) { - $totalValues = $this->sumColumnValueToTotal($columns, $metricName, $realMetricName, $totalValues); + foreach ($metricNames as $metricId => $metricName) { + $this->sumColumnValueToTotal($columns, $metricId, $metricName); } } - $dataTable->setMetadata('totals', $totalValues); + $dataTable->setMetadata('totals', $this->totals); return $dataTable; } - private function hasDataTableMetric(DataTable $dataTable, $metricId, $readableColumnName) - { - $firstRow = $dataTable->getFirstRow(); - - if (empty($firstRow)) { - return false; - } - - $columnAlternatives = array( - $metricId, - $readableColumnName, - // TODO: this and below is a hack to get report totals to work correctly w/ MultiSites.getAll. can be corrected - // when all metrics are described by Metadata classes & internal naming quirks are handled by core system. - 'Goal_' . $readableColumnName, - 'Actions_' . $readableColumnName - ); - - foreach ($columnAlternatives as $column) { - if ($firstRow->getColumn($column) !== false) { - return $column; - } - } - - return false; - } - private function makeSureToWorkOnFirstLevelDataTable($table) { if (!array_key_exists('idSubtable', $this->request)) { @@ -155,25 +146,40 @@ class ReportTotalsCalculator extends DataTableManipulator return $table; } - private function sumColumnValueToTotal($columns, $metricName, $realMetricId, $totalValues) + private function sumColumnValueToTotal($columns, $metricId, $metricName) { $value = false; - if (array_key_exists($realMetricId, $columns)) { - $value = $columns[$realMetricId]; - } - - if (false === $value) { + if (array_key_exists($metricId, $columns)) { + $value = $columns[$metricId]; + } + + if ($value === false) { + // we do not add $metricId to $possibleMetricNames for a small performance improvement since in most cases + // $metricId should be present in $columns so we avoid this foreach loop + $possibleMetricNames = array( + $metricName, + // TODO: this and below is a hack to get report totals to work correctly w/ MultiSites.getAll. can be corrected + // when all metrics are described by Metadata classes & internal naming quirks are handled by core system. + 'Goal_' . $metricName, + 'Actions_' . $metricName + ); + foreach ($possibleMetricNames as $possibleMetricName) { + if (array_key_exists($possibleMetricName, $columns)) { + $value = $columns[$possibleMetricName]; + break; + } + } - return $totalValues; + if ($value === false) { + return; + } } - if (array_key_exists($metricName, $totalValues)) { - $totalValues[$metricName] += $value; + if (array_key_exists($metricName, $this->totals)) { + $this->totals[$metricName] += $value; } else { - $totalValues[$metricName] = $value; + $this->totals[$metricName] = $value; } - - return $totalValues; } /** @@ -188,6 +194,7 @@ class ReportTotalsCalculator extends DataTableManipulator $request['expanded'] = 0; $request['filter_limit'] = -1; $request['filter_offset'] = 0; + $request['filter_sort_column'] = ''; $parametersToRemove = array('flat'); @@ -221,8 +228,8 @@ class ReportTotalsCalculator extends DataTableManipulator return null; } - private function isReportAllMetricsReport(Report $report) + private function isAllMetricsReport() { - return $report->getModule() == 'API' && $report->getAction() == 'get'; + return $this->report->getModule() == 'API' && $this->report->getAction() == 'get'; } } diff --git a/core/API/DataTablePostProcessor.php b/core/API/DataTablePostProcessor.php index 8d936e6779..24d8cf8b6c 100644 --- a/core/API/DataTablePostProcessor.php +++ b/core/API/DataTablePostProcessor.php @@ -191,8 +191,8 @@ class DataTablePostProcessor public function applyTotalsCalculator($dataTable) { if (1 == Common::getRequestVar('totals', '1', 'integer', $this->request)) { - $reportTotalsCalculator = new ReportTotalsCalculator($this->apiModule, $this->apiMethod, $this->request); - $dataTable = $reportTotalsCalculator->calculate($dataTable); + $calculator = new ReportTotalsCalculator($this->apiModule, $this->apiMethod, $this->request, $this->report); + $dataTable = $calculator->calculate($dataTable); } return $dataTable; } diff --git a/core/ArchiveProcessor.php b/core/ArchiveProcessor.php index cb24d83367..81ac213344 100644 --- a/core/ArchiveProcessor.php +++ b/core/ArchiveProcessor.php @@ -9,6 +9,7 @@ namespace Piwik; use Exception; +use Piwik\Archive\DataTableFactory; use Piwik\ArchiveProcessor\Parameters; use Piwik\ArchiveProcessor\Rules; use Piwik\DataAccess\ArchiveWriter; @@ -351,7 +352,18 @@ class ArchiveProcessor // see https://github.com/piwik/piwik/issues/4377 $self = $this; $dataTable->filter(function ($table) use ($self, $columnsToRenameAfterAggregation) { - $self->renameColumnsAfterAggregation($table, $columnsToRenameAfterAggregation); + + if ($self->areColumnsNotAlreadyRenamed($table)) { + /** + * This makes archiving and range dates a lot faster. Imagine we archive a week, then we will + * rename all columns of each 7 day archives. Afterwards we know the columns will be replaced in a + * week archive. When generating month archives, which uses mostly week archives, we do not have + * to replace those columns for the week archives again since we can be sure they were already + * replaced. Same when aggregating year and range archives. This can save up 10% or more when + * aggregating Month, Year and Range archives. + */ + $self->renameColumnsAfterAggregation($table, $columnsToRenameAfterAggregation); + } }); } @@ -360,10 +372,23 @@ class ArchiveProcessor if (!$columnsRenamed) { $this->renameColumnsAfterAggregation($dataTable, $columnsToRenameAfterAggregation); } - + return $dataTable; } + /** + * Note: public only for use in closure in PHP 5.3. + * + * @param $table + * @return \Piwik\Period + */ + public function areColumnsNotAlreadyRenamed($table) + { + $period = $table->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX); + + return !$period || $period->getLabel() === 'day'; + } + protected function getOperationForColumns($columns, $defaultOperation) { $operationForColumn = array(); @@ -499,8 +524,15 @@ class ArchiveProcessor $columnsToRenameAfterAggregation = self::$columnsToRenameAfterAggregation; } - foreach ($columnsToRenameAfterAggregation as $oldName => $newName) { - $table->renameColumn($oldName, $newName); + foreach ($table->getRows() as $row) { + foreach ($columnsToRenameAfterAggregation as $oldName => $newName) { + $row->renameColumn($oldName, $newName); + } + + $subTable = $row->getSubtable(); + if ($subTable) { + $this->renameColumnsAfterAggregation($subTable, $columnsToRenameAfterAggregation); + } } } @@ -524,7 +556,7 @@ class ArchiveProcessor $rowMetrics = new Row; } $this->enrichWithUniqueVisitorsMetric($rowMetrics); - $this->renameColumnsAfterAggregation($results); + $this->renameColumnsAfterAggregation($results, self::$columnsToRenameAfterAggregation); $metrics = $rowMetrics->getColumns(); diff --git a/core/DataTable.php b/core/DataTable.php index 48f4c1426b..96f136a158 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -332,15 +332,23 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess && isset($this->rows) ) { $depth++; - foreach ($this->getRows() as $row) { + foreach ($this->rows as $row) { Common::destroy($row); } + if (!is_null($this->summaryRow)) { + Common::destroy($this->summaryRow); + } unset($this->rows); Manager::getInstance()->setTableDeleted($this->getId()); $depth--; } } + public function setLabelsHaveChanged() + { + $this->indexNotUpToDate = true; + } + /** * @ignore * does not update the summary row! @@ -564,8 +572,9 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess $row = $tableToSum->getFirstRow(); $this->aggregateRowFromSimpleTable($row); } else { + $columnAggregationOps = $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME); foreach ($tableToSum->getRows() as $row) { - $this->aggregateRowWithLabel($row); + $this->aggregateRowWithLabel($row, $columnAggregationOps); } } } @@ -607,7 +616,6 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess */ public function getRowIdFromLabel($label) { - $this->rebuildIndexContinuously = true; if ($this->indexNotUpToDate) { $this->rebuildIndex(); } @@ -643,9 +651,12 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess /** * Rebuilds the index used to lookup a row by label + * @internal */ - private function rebuildIndex() + public function rebuildIndex() { + $this->rebuildIndexContinuously = true; + foreach ($this->getRows() as $id => $row) { $label = $row->getColumn('label'); if ($label !== false) { @@ -987,7 +998,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess */ public function renameColumn($oldName, $newName) { - foreach ($this->getRows() as $row) { + foreach ($this->rows as $row) { $row->renameColumn($oldName, $newName); $subTable = $row->getSubtable(); @@ -1008,7 +1019,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess */ public function deleteColumns($names, $deleteRecursiveInSubtables = false) { - foreach ($this->getRows() as $row) { + foreach ($this->rows as $row) { foreach ($names as $name) { $row->deleteColumn($name); } @@ -1118,8 +1129,6 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess */ public static function isEqual(DataTable $table1, DataTable $table2) { - $rows1 = $table1->getRows(); - $table1->rebuildIndex(); $table2->rebuildIndex(); @@ -1127,6 +1136,8 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess return false; } + $rows1 = $table1->getRows(); + foreach ($rows1 as $row1) { $row2 = $table2->getRowFromLabel($row1->getColumn('label')); if ($row2 === false @@ -1670,9 +1681,10 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess * $row must have a column "label". The $row will be summed to this table's row with the same label. * * @param $row + * @params null|array $columnAggregationOps * @throws \Exception */ - protected function aggregateRowWithLabel(Row $row) + protected function aggregateRowWithLabel(Row $row, $columnAggregationOps) { $labelToLookFor = $row->getColumn('label'); if ($labelToLookFor === false) { @@ -1686,7 +1698,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess $this->addRow($row); } } else { - $rowFound->sumRow($row, $copyMeta = true, $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME)); + $rowFound->sumRow($row, $copyMeta = true, $columnAggregationOps); // if the row to add has a subtable whereas the current row doesn't // we simply add it (cloning the subtable) @@ -1694,8 +1706,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess // then we have to recursively sum the subtables $subTable = $row->getSubtable(); if ($subTable) { - $subTable->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME] - = $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME); + $subTable->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME] = $columnAggregationOps; $rowFound->sumSubtable($subTable); } } diff --git a/core/DataTable/Filter/AddSegmentByLabel.php b/core/DataTable/Filter/AddSegmentByLabel.php index 2e9fd693d1..d13eef97c5 100644 --- a/core/DataTable/Filter/AddSegmentByLabel.php +++ b/core/DataTable/Filter/AddSegmentByLabel.php @@ -63,10 +63,7 @@ class AddSegmentByLabel extends BaseFilter if (count($this->segments) === 1) { $segment = reset($this->segments); - foreach ($table->getRows() as $key => $row) { - if ($key == DataTable::ID_SUMMARY_ROW) { - continue; - } + foreach ($table->getRowsWithoutSummaryRow() as $key => $row) { $label = $row->getColumn('label'); @@ -78,10 +75,7 @@ class AddSegmentByLabel extends BaseFilter $numSegments = count($this->segments); $conditionAnd = ';'; - foreach ($table->getRows() as $key => $row) { - if ($key == DataTable::ID_SUMMARY_ROW) { - continue; - } + foreach ($table->getRowsWithoutSummaryRow() as $key => $row) { $label = $row->getColumn('label'); if (!empty($label)) { diff --git a/core/DataTable/Filter/ColumnCallbackAddMetadata.php b/core/DataTable/Filter/ColumnCallbackAddMetadata.php index c7945839cb..805a5db5ab 100644 --- a/core/DataTable/Filter/ColumnCallbackAddMetadata.php +++ b/core/DataTable/Filter/ColumnCallbackAddMetadata.php @@ -63,10 +63,13 @@ class ColumnCallbackAddMetadata extends BaseFilter */ public function filter($table) { - foreach ($table->getRows() as $key => $row) { - if (!$this->applyToSummaryRow && $key == DataTable::ID_SUMMARY_ROW) { - continue; - } + if ($this->applyToSummaryRow) { + $rows = $table->getRows(); + } else { + $rows = $table->getRowsWithoutSummaryRow(); + } + + foreach ($rows as $key => $row) { $parameters = array(); foreach ($this->columnsToRead as $columnsToRead) { diff --git a/core/DataTable/Filter/ColumnCallbackReplace.php b/core/DataTable/Filter/ColumnCallbackReplace.php index 4d78831e88..84397d7a2c 100644 --- a/core/DataTable/Filter/ColumnCallbackReplace.php +++ b/core/DataTable/Filter/ColumnCallbackReplace.php @@ -99,6 +99,11 @@ class ColumnCallbackReplace extends BaseFilter $this->filterSubTable($row); } } + + if (in_array('label', $this->columnsToFilter)) { + // we need to force rebuilding the index + $table->setLabelsHaveChanged(); + } } /** diff --git a/core/DataTable/Filter/GroupBy.php b/core/DataTable/Filter/GroupBy.php index 2ac79a6de9..07597fe6b5 100755 --- a/core/DataTable/Filter/GroupBy.php +++ b/core/DataTable/Filter/GroupBy.php @@ -76,11 +76,7 @@ class GroupBy extends BaseFilter $groupByRows = array(); $nonGroupByRowIds = array(); - foreach ($table->getRows() as $rowId => $row) { - // skip the summary row - if ($rowId == DataTable::ID_SUMMARY_ROW) { - continue; - } + foreach ($table->getRowsWithoutSummaryRow() as $rowId => $row) { $groupByColumnValue = $row->getColumn($this->groupByColumn); $groupByValue = $groupByColumnValue; @@ -104,6 +100,10 @@ class GroupBy extends BaseFilter } } + if ($this->groupByColumn === 'label') { + $table->setLabelsHaveChanged(); + } + // delete the unneeded rows. $table->deleteRows($nonGroupByRowIds); } diff --git a/core/DataTable/Filter/MetadataCallbackAddMetadata.php b/core/DataTable/Filter/MetadataCallbackAddMetadata.php index 7f6aaef123..414f939183 100644 --- a/core/DataTable/Filter/MetadataCallbackAddMetadata.php +++ b/core/DataTable/Filter/MetadataCallbackAddMetadata.php @@ -62,11 +62,13 @@ class MetadataCallbackAddMetadata extends BaseFilter */ public function filter($table) { - foreach ($table->getRows() as $key => $row) { - if (!$this->applyToSummaryRow && $key == DataTable::ID_SUMMARY_ROW) { - continue; - } + if ($this->applyToSummaryRow) { + $rows = $table->getRows(); + } else { + $rows = $table->getRowsWithoutSummaryRow(); + } + foreach ($rows as $key => $row) { $params = array(); foreach ($this->metadataToRead as $name) { $params[] = $row->getMetadata($name); diff --git a/core/DataTable/Filter/ReplaceSummaryRowLabel.php b/core/DataTable/Filter/ReplaceSummaryRowLabel.php index 1e550f6e3f..168794d097 100644 --- a/core/DataTable/Filter/ReplaceSummaryRowLabel.php +++ b/core/DataTable/Filter/ReplaceSummaryRowLabel.php @@ -53,18 +53,18 @@ class ReplaceSummaryRowLabel extends BaseFilter */ public function filter($table) { - $rows = $table->getRows(); - foreach ($rows as $id => $row) { - if ($row->getColumn('label') == DataTable::LABEL_SUMMARY_ROW - || $id == DataTable::ID_SUMMARY_ROW - ) { + $row = $table->getRowFromId(DataTable::ID_SUMMARY_ROW); + if ($row) { + $row->setColumn('label', $this->newLabel); + } else { + $row = $table->getRowFromLabel(DataTable::LABEL_SUMMARY_ROW); + if ($row) { $row->setColumn('label', $this->newLabel); - break; } } // recurse - foreach ($rows as $row) { + foreach ($table->getRowsWithoutSummaryRow() as $row) { $subTable = $row->getSubtable(); if ($subTable) { $this->filter($subTable); diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php index 7e91bb338d..3b11ec370c 100644 --- a/core/DataTable/Filter/Sort.php +++ b/core/DataTable/Filter/Sort.php @@ -21,11 +21,14 @@ use Piwik\Metrics; * * @api */ -class -Sort extends BaseFilter +class Sort extends BaseFilter { protected $columnToSort; protected $order; + protected $sign; + + const ORDER_DESC = 'desc'; + const ORDER_ASC = 'asc'; /** * Constructor. @@ -36,7 +39,7 @@ Sort extends BaseFilter * @param bool $naturalSort Whether to use a natural sort or not (see {@link http://php.net/natsort}). * @param bool $recursiveSort Whether to sort all subtables or not. */ - public function __construct($table, $columnToSort, $order = 'desc', $naturalSort = true, $recursiveSort = false) + public function __construct($table, $columnToSort, $order = 'desc', $naturalSort = true, $recursiveSort = true) { parent::__construct($table); @@ -68,8 +71,8 @@ Sort extends BaseFilter /** * Sorting method used for sorting numbers * - * @param Row $a - * @param Row $b + * @param array $rowA array[0 => value of column to sort, 1 => label] + * @param array $rowB array[0 => value of column to sort, 1 => label] * @return int */ public function numberSort($rowA, $rowB) @@ -80,20 +83,20 @@ Sort extends BaseFilter } else { return -1 * $this->sign * strnatcasecmp($rowA[1], $rowB[1]); } - } elseif (!isset($rowB[0])) { - return -1; + } elseif (!isset($rowB[0]) && !isset($rowA[0])) { + return -1 * $this->sign * strnatcasecmp($rowA[1], $rowB[1]); } elseif (!isset($rowA[0])) { return 1; } - return 0; + return -1; } /** * Sorting method used for sorting values natural * - * @param mixed $a - * @param mixed $b + * @param array $rowA array[0 => value of column to sort, 1 => label] + * @param array $rowB array[0 => value of column to sort, 1 => label] * @return int */ function naturalSort($rowA, $rowB) @@ -119,8 +122,8 @@ Sort extends BaseFilter /** * Sorting method used for sorting values * - * @param mixed $a - * @param mixed $b + * @param array $rowA array[0 => value of column to sort, 1 => label] + * @param array $rowB array[0 => value of column to sort, 1 => label] * @return int */ function sortString($rowA, $rowB) @@ -208,12 +211,11 @@ Sort extends BaseFilter return; } - $rows = $table->getRows(); - if (count($rows) == 0) { + if (!$table->getRowsCount()) { return; } - $row = current($rows); + $row = $table->getFirstRow(); if ($row === false) { return; } @@ -268,10 +270,10 @@ Sort extends BaseFilter $sortedRows = array(); foreach ($values as $key => $value) { - $sortedRows[$key] = $rows[$key]; + $sortedRows[] = $rows[$key]; } - $table->setRows(array_values($sortedRows)); + $table->setRows($sortedRows); unset($rows); unset($sortedRows); diff --git a/core/DataTable/Filter/Truncate.php b/core/DataTable/Filter/Truncate.php index a8fa0bd08f..04b4cef2a8 100644 --- a/core/DataTable/Filter/Truncate.php +++ b/core/DataTable/Filter/Truncate.php @@ -90,16 +90,18 @@ class Truncate extends BaseFilter */ private function addSummaryRow($table) { - $table->filter('Sort', array($this->columnToSortByBeforeTruncating, 'desc')); - if ($table->getRowsCount() <= $this->truncateAfter + 1) { return; } + $table->filter('Sort', array($this->columnToSortByBeforeTruncating, 'desc', $naturalSort = true, $recursiveSort = false)); + $rows = array_values($table->getRows()); $count = $table->getRowsCount(); $newRow = new Row(array(Row::COLUMNS => array('label' => DataTable::LABEL_SUMMARY_ROW))); + $aggregationOps = $table->getMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME); + for ($i = $this->truncateAfter; $i < $count; $i++) { if (!isset($rows[$i])) { // case when the last row is a summary row, it is not indexed by $cout but by DataTable::ID_SUMMARY_ROW @@ -107,10 +109,10 @@ class Truncate extends BaseFilter //FIXME: I'm not sure why it could return false, but it was reported in: http://forum.piwik.org/read.php?2,89324,page=1#msg-89442 if ($summaryRow) { - $newRow->sumRow($summaryRow, $enableCopyMetadata = false, $table->getMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME)); + $newRow->sumRow($summaryRow, $enableCopyMetadata = false, $aggregationOps); } } else { - $newRow->sumRow($rows[$i], $enableCopyMetadata = false, $table->getMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME)); + $newRow->sumRow($rows[$i], $enableCopyMetadata = false, $aggregationOps); } } diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index dfbe6e50cf..c69792ba9c 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -14,6 +14,7 @@ use Piwik\Cache; use Piwik\CacheId; use Piwik\Columns\Dimension; use Piwik\DataTable; +use Piwik\DataTable\Filter\Sort; use Piwik\Menu\MenuReporting; use Piwik\Metrics; use Piwik\Cache as PiwikCache; @@ -193,7 +194,14 @@ class Report * * @var string|int */ - protected $defaultSortColumn = ''; + protected $defaultSortColumn = 'nb_visits'; + + /** + * Default sort desc. If true will sort by default desc, if false will sort by default asc + * + * @var bool + */ + protected $defaultSortOrderDesc = true; /** * @var array @@ -594,6 +602,18 @@ class Report } /** + * @ignore + */ + public function getDefaultSortOrder() + { + if ($this->defaultSortOrderDesc) { + return Sort::ORDER_DESC; + } + + return Sort::ORDER_ASC; + } + + /** * Get the list of related reports if there are any. They will be displayed for instance below a report as a * recommended related report. * |