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
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@gmail.com>2015-02-26 05:23:28 +0300
committerThomas Steur <thomas.steur@gmail.com>2015-03-05 05:31:18 +0300
commit287aad82841f0f0e85406192b2f1f865bc0be67d (patch)
treed9c035a484c3f2727d7fa1cdf14ccd213c308508 /core/DataTable
parenta1cb3695319b321f92bb0a4fd31892a9bc1bdf38 (diff)
Faster flattening for many reports
Diffstat (limited to 'core/DataTable')
-rw-r--r--core/DataTable/Filter/Sort.php101
-rw-r--r--core/DataTable/Filter/Truncate.php2
-rw-r--r--core/DataTable/Map.php33
-rw-r--r--core/DataTable/Row.php44
4 files changed, 102 insertions, 78 deletions
diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php
index 42441c8e30..632da35dc8 100644
--- a/core/DataTable/Filter/Sort.php
+++ b/core/DataTable/Filter/Sort.php
@@ -21,7 +21,8 @@ use Piwik\Metrics;
*
* @api
*/
-class Sort extends BaseFilter
+class
+Sort extends BaseFilter
{
protected $columnToSort;
protected $order;
@@ -71,34 +72,21 @@ class Sort extends BaseFilter
* @param Row $b
* @return int
*/
- public function numberSort($a, $b)
+ public function numberSort($rowA, $rowB)
{
- $valA = $this->getColumnValue($a);
- $valB = $this->getColumnValue($b);
+ if (isset($rowA[0]) && isset($rowB[0])) {
+ if ($rowA[0] != $rowB[0] || !isset($rowA[1])) {
+ return $this->sign * ($rowA[0] < $rowB[0] ? -1 : 1);
+ } else {
+ return -1 * $this->sign * strnatcasecmp($rowA[1], $rowB[1]);
+ }
+ } elseif (!isset($rowB[0])) {
+ return -1;
+ } elseif (!isset($rowA[0])) {
+ return 1;
+ }
- return !isset($valA)
- && !isset($valB)
- ? 0
- : (
- !isset($valA)
- ? 1
- : (
- !isset($valB)
- ? -1
- : (($valA != $valB
- || !isset($a->c[Row::COLUMNS]['label']))
- ? ($this->sign * (
- $valA
- < $valB
- ? -1
- : 1)
- )
- : -1 * $this->sign * strnatcasecmp(
- $a->c[Row::COLUMNS]['label'],
- $b->c[Row::COLUMNS]['label'])
- )
- )
- );
+ return 0;
}
/**
@@ -108,10 +96,10 @@ class Sort extends BaseFilter
* @param mixed $b
* @return int
*/
- function naturalSort($a, $b)
+ function naturalSort($rowA, $rowB)
{
- $valA = $this->getColumnValue($a);
- $valB = $this->getColumnValue($b);
+ $valA = $rowA[0];
+ $valB = $rowB[0];
return !isset($valA)
&& !isset($valB)
@@ -135,10 +123,10 @@ class Sort extends BaseFilter
* @param mixed $b
* @return int
*/
- function sortString($a, $b)
+ function sortString($rowA, $rowB)
{
- $valA = $this->getColumnValue($a);
- $valB = $this->getColumnValue($b);
+ $valA = $rowA[0];
+ $valB = $rowB[0];
return !isset($valA)
&& !isset($valB)
@@ -243,6 +231,51 @@ class Sort extends BaseFilter
}
}
- $table->sort(array($this, $methodToUse), $this->columnToSort);
+ $this->sort($table, $methodToUse);
}
+
+ /**
+ * Sorts the DataTable rows using the supplied callback function.
+ *
+ * @param string $functionCallback A comparison callback compatible with {@link usort}.
+ * @param string $columnSortedBy The column name `$functionCallback` sorts by. This is stored
+ * so we can determine how the DataTable was sorted in the future.
+ */
+ private function sort(DataTable $table, $functionCallback)
+ {
+ $table->setTableSortedBy($this->columnToSort);
+
+ $rows = $table->getRowsWithoutSummaryRow();
+
+ // get column value and label only once for performance tweak
+ $values = array();
+ foreach ($rows as $key => $row) {
+ $values[$key] = array($this->getColumnValue($row), $row->getColumn('label'));
+ }
+
+ uasort($values, array($this, $functionCallback));
+
+ $sortedRows = array();
+ foreach ($values as $key => $value) {
+ $sortedRows[$key] = $rows[$key];
+ }
+
+ $table->setRows(array_values($sortedRows));
+
+ unset($rows);
+ unset($sortedRows);
+
+ if ($table->isSortRecursiveEnabled()) {
+ foreach ($table->getRows() as $row) {
+
+ $subTable = $row->getSubtable();
+ if ($subTable) {
+ $subTable->enableRecursiveSort();
+ $this->sort($subTable, $functionCallback);
+ }
+ }
+ }
+
+ }
+
}
diff --git a/core/DataTable/Filter/Truncate.php b/core/DataTable/Filter/Truncate.php
index 632eb2755e..a8fa0bd08f 100644
--- a/core/DataTable/Filter/Truncate.php
+++ b/core/DataTable/Filter/Truncate.php
@@ -96,7 +96,7 @@ class Truncate extends BaseFilter
return;
}
- $rows = $table->getRows();
+ $rows = array_values($table->getRows());
$count = $table->getRowsCount();
$newRow = new Row(array(Row::COLUMNS => array('label' => DataTable::LABEL_SUMMARY_ROW)));
diff --git a/core/DataTable/Map.php b/core/DataTable/Map.php
index 8795eac134..8787b06404 100644
--- a/core/DataTable/Map.php
+++ b/core/DataTable/Map.php
@@ -110,6 +110,19 @@ class Map implements DataTableInterface
}
/**
+ * Apply a filter to all subtables contained by this instance.
+ *
+ * @param string|Closure $className Name of filter class or a Closure.
+ * @param array $parameters Parameters to pass to the filter.
+ */
+ public function filterSubtables($className, $parameters = array())
+ {
+ foreach ($this->getDataTables() as $table) {
+ $table->filterSubtables($className, $parameters);
+ }
+ }
+
+ /**
* Returns the array of DataTables contained by this class.
*
* @return DataTable[]|Map[]
@@ -185,6 +198,26 @@ class Map implements DataTableInterface
}
/**
+ * @ignore
+ */
+ public function disableRecursiveFilters()
+ {
+ foreach ($this->getDataTables() as $table) {
+ $table->disableRecursiveFilters();
+ }
+ }
+
+ /**
+ * @ignore
+ */
+ public function enableRecursiveFilters()
+ {
+ foreach ($this->getDataTables() as $table) {
+ $table->enableRecursiveFilters();
+ }
+ }
+
+ /**
* Renames the given column in each contained {@link DataTable}.
*
* See {@link DataTable::renameColumn()}.
diff --git a/core/DataTable/Row.php b/core/DataTable/Row.php
index 5f21f3fdec..71dde68031 100644
--- a/core/DataTable/Row.php
+++ b/core/DataTable/Row.php
@@ -209,37 +209,9 @@ class Row implements \ArrayAccess, \IteratorAggregate
return false;
}
- if ($this->isColumnValueCallable($this->c[self::COLUMNS][$name])) {
- $value = $this->resolveCallableColumn($name);
-
- if (!isset($value)) {
- return false;
- }
-
- return $value;
- }
-
return $this->c[self::COLUMNS][$name];
}
- private function isColumnValueCallable($name)
- {
- if (! is_callable($name)) {
- return false;
- }
-
- if (is_object($name) && ($name instanceof \Closure)) {
- return true;
- }
-
- return is_array($name) && isset($name[0]) && is_object($name[0]);
- }
-
- private function resolveCallableColumn($columnName)
- {
- return call_user_func($this->c[self::COLUMNS][$columnName], $this);
- }
-
/**
* Returns the array of all metadata, or one requested metadata value.
*
@@ -287,16 +259,7 @@ class Row implements \ArrayAccess, \IteratorAggregate
*/
public function getColumns()
{
- $values = array();
- foreach ($this->c[self::COLUMNS] as $columnName => $val) {
- if ($this->isColumnValueCallable($val)) {
- $values[$columnName] = $this->resolveCallableColumn($columnName);
- } else {
- $values[$columnName] = $val;
- }
- }
-
- return $values;
+ return $this->c[self::COLUMNS];
}
/**
@@ -517,11 +480,6 @@ class Row implements \ArrayAccess, \IteratorAggregate
continue;
}
- if ($this->isColumnValueCallable($columnToSumValue)) {
- $this->setColumn($columnToSumName, $columnToSumValue);
- continue;
- }
-
$thisColumnValue = $this->getColumn($columnToSumName);
$operation = 'sum';