Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/API/DataTableGenericFilter.php2
-rw-r--r--core/API/DataTableManipulator/LabelFilter.php7
-rw-r--r--core/API/DataTableManipulator/ReportTotalsCalculator.php117
-rw-r--r--core/API/DataTablePostProcessor.php4
-rw-r--r--core/ArchiveProcessor.php42
-rw-r--r--core/DataTable.php35
-rw-r--r--core/DataTable/Filter/AddSegmentByLabel.php10
-rw-r--r--core/DataTable/Filter/ColumnCallbackAddMetadata.php11
-rw-r--r--core/DataTable/Filter/ColumnCallbackReplace.php5
-rwxr-xr-xcore/DataTable/Filter/GroupBy.php10
-rw-r--r--core/DataTable/Filter/MetadataCallbackAddMetadata.php10
-rw-r--r--core/DataTable/Filter/ReplaceSummaryRowLabel.php14
-rw-r--r--core/DataTable/Filter/Sort.php36
-rw-r--r--core/DataTable/Filter/Truncate.php10
-rw-r--r--core/Plugin/Report.php22
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.
*