protected function assertColumnValues($rowsWithValues) { $index = 0; foreach ($this->table->getRows() as $row) { $rowToCheck = $rowsWithValues[$index]; foreach ($rowToCheck as $columnToCheck => $expectedValue) { $actualValue = $row->getColumn($columnToCheck); $this->assertEquals($expectedValue, $actualValue, "{$columnToCheck} in row {$index} does not match assumed {$actualValue} is {$expectedValue}"); } $index++; } $this->assertEquals(count($rowsWithValues), $this->table->getRowsCount()); }
/** * See {@link PatternRecursive}. * * @param DataTable $table * @return int The number of deleted rows. */ public function filter($table) { $rows = $table->getRows(); foreach ($rows as $key => $row) { // A row is deleted if // 1 - its label doesnt contain the pattern // AND 2 - the label is not found in the children $patternNotFoundInChildren = false; try { $idSubTable = $row->getIdSubDataTable(); $subTable = Manager::getInstance()->getTable($idSubTable); // we delete the row if we couldn't find the pattern in any row in the // children hierarchy if ($this->filter($subTable) == 0) { $patternNotFoundInChildren = true; } } catch (Exception $e) { // there is no subtable loaded for example $patternNotFoundInChildren = true; } if ($patternNotFoundInChildren && !Pattern::match($this->patternToSearchQuoted, $row->getColumn($this->columnToFilter), $invertedMatch = false)) { $table->deleteRow($key); } } return $table->getRowsCount(); }
/** * @param DataTable $table */ private function addSummaryRow($table) { 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 $summaryRow = $table->getRowFromId(DataTable::ID_SUMMARY_ROW); //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, $aggregationOps); } } else { $newRow->sumRow($rows[$i], $enableCopyMetadata = false, $aggregationOps); } } $table->filter('Limit', array(0, $this->truncateAfter)); $table->addSummaryRow($newRow); unset($rows); }
/** * Generates JSON graph data and returns it. * * @param DataTable|DataTable\Map $dataTable * @return string */ public function generate($dataTable) { $visualization = new Chart(); if ($dataTable->getRowsCount() > 0) { // if addTotalRow was called in GenerateGraphHTML, add a row containing totals of // different metrics if ($this->properties['add_total_row']) { $dataTable->queueFilter('AddSummaryRow', Piwik::translate('General_Total')); } $dataTable->applyQueuedFilters(); $this->initChartObjectData($dataTable, $visualization); } return $visualization->render(); }
/** * See {@link Limit}. * * @param DataTable $table */ public function filter($table) { $table->setMetadata(DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME, $table->getRowsCount()); if ($this->keepSummaryRow) { $summaryRow = $table->getRowFromId(DataTable::ID_SUMMARY_ROW); } // we delete from 0 to offset if ($this->offset > 0) { $table->deleteRowsOffset(0, $this->offset); } // at this point the array has offset less elements. We delete from limit to the end if ($this->limit >= 0) { $table->deleteRowsOffset($this->limit); } if ($this->keepSummaryRow && !empty($summaryRow)) { $table->addSummaryRow($summaryRow); } }
/** * See {@link AddSegmentBySegmentValue}. * * @param DataTable $table * @return int The number of deleted rows. */ public function filter($table) { if (empty($this->report) || !$table->getRowsCount()) { return; } $dimension = $this->report->getDimension(); if (empty($dimension)) { return; } $segments = $dimension->getSegments(); if (empty($segments)) { return; } /** @var \Piwik\Plugin\Segment $segment */ $segment = reset($segments); $segmentName = $segment->getSegment(); foreach ($table->getRows() as $row) { $value = $row->getMetadata('segmentValue'); $filter = $row->getMetadata('segment'); if ($value !== false && $filter === false) { $row->setMetadata('segment', sprintf('%s==%s', $segmentName, urlencode($value))); } } }
/** * See {@link PatternRecursive}. * * @param DataTable $table * @return int The number of deleted rows. */ public function filter($table) { $rows = $table->getRows(); foreach ($rows as $key => $row) { // A row is deleted if // 1 - its label doesnt contain the pattern // AND 2 - the label is not found in the children $patternNotFoundInChildren = false; $subTable = $row->getSubtable(); if (!$subTable) { $patternNotFoundInChildren = true; } else { // we delete the row if we couldn't find the pattern in any row in the // children hierarchy if ($this->filter($subTable) == 0) { $patternNotFoundInChildren = true; } } if ($patternNotFoundInChildren && !Pattern::match($this->patternToSearchQuoted, $row->getColumn($this->columnToFilter), $invertedMatch = false)) { $table->deleteRow($key); } } return $table->getRowsCount(); }
/** * Returns true if both DataTable instances are exactly the same. * * DataTables are equal if they have the same number of rows, if * each row has a label that exists in the other table, and if each row * is equal to the row in the other table with the same label. The order * of rows is not important. * * @param \Piwik\DataTable $table1 * @param \Piwik\DataTable $table2 * @return bool */ public static function isEqual(DataTable $table1, DataTable $table2) { $table1->rebuildIndex(); $table2->rebuildIndex(); if ($table1->getRowsCount() != $table2->getRowsCount()) { return false; } $rows1 = $table1->getRows(); foreach ($rows1 as $row1) { $row2 = $table2->getRowFromLabel($row1->getColumn('label')); if ($row2 === false || !Row::isEqual($row1, $row2)) { return false; } } return true; }
/** * @param DataTable $table * @param int $idSite * @param string $period * @param string $date * @return mixed */ protected function removeHoursInFuture($table, $idSite, $period, $date) { $site = new Site($idSite); if ($period == 'day' && ($date == 'today' || $date == Date::factory('now', $site->getTimezone())->toString())) { $currentHour = Date::factory('now', $site->getTimezone())->toString('G'); // If no data for today, this is an exception to the API output rule, as we normally return nothing: // we shall return all hours of the day, with nb_visits = 0 if ($table->getRowsCount() == 0) { for ($hour = 0; $hour <= $currentHour; $hour++) { $table->addRowFromSimpleArray(array('label' => $hour, 'nb_visits' => 0)); } return $table; } $idsToDelete = array(); foreach ($table->getRows() as $id => $row) { $hour = $row->getColumn('label'); if ($hour > $currentHour) { $idsToDelete[] = $id; } } $table->deleteRows($idsToDelete); } return $table; }
/** * General tests that tries to test the normal behaviour of DataTable * * We create some tables, add rows, some of the rows link to sub tables * * Then we serialize everything, and we check that the unserialize give the same object back */ public function testGeneral() { /* * create some fake tables to make sure that the serialized array of the first TABLE * does not take in consideration those tables */ $useless1 = $this->createDataTable(array(array(13))); /* * end fake tables */ /* * MAIN TABLE */ $table = new DataTable(); $subtable = new DataTable(); $idtable = $table->getId(); /* * create some fake tables to make sure that the serialized array of the first TABLE * does not take in consideration those tables * -> we check that the DataTable_Manager is not impacting DataTable */ $useless1->addRowFromArray(array(Row::COLUMNS => array(8487))); $useless3 = $this->createDataTable(array(array(8487))); /* * end fake tables */ $row = array(Row::COLUMNS => array(0 => 1554, 1 => 42, 2 => 657, 3 => 155744), Row::METADATA => array('logo' => 'test.png')); $row = new Row($row); $table->addRow($row); $table->addRowFromArray(array(Row::COLUMNS => array(0 => 1554, 1 => 42), Row::METADATA => array('url' => 'piwik.org'))); $table->addRowFromArray(array(Row::COLUMNS => array(0 => 787877888787), Row::METADATA => array('url' => 'OUPLA ADDED'), Row::DATATABLE_ASSOCIATED => $subtable)); /* * SUB TABLE */ $row = array(Row::COLUMNS => array(0 => 1554), Row::METADATA => array('searchengine' => 'google')); $subtable->addRowFromArray($row); $row = array(Row::COLUMNS => array(0 => 84894), Row::METADATA => array('searchengine' => 'yahoo')); $subtable->addRowFromArray($row); $row = array(Row::COLUMNS => array(0 => 4898978989), Row::METADATA => array('searchengine' => 'ask')); $subtable->addRowFromArray($row); /* * SUB SUB TABLE */ $subsubtable = new DataTable(); $subsubtable->addRowFromArray(array(Row::COLUMNS => array(245), Row::METADATA => array('yes' => 'subsubmetadata1'))); $subsubtable->addRowFromArray(array(Row::COLUMNS => array(13), Row::METADATA => array('yes' => 'subsubmetadata2'))); $row = array(Row::COLUMNS => array(0 => 666666666666666), Row::METADATA => array('url' => 'NEW ROW ADDED'), Row::DATATABLE_ASSOCIATED => $subsubtable); $subtable->addRowFromArray($row); $idsubsubtable = $subsubtable->getId(); $serialized = $table->getSerialized(); $this->assertEquals(array_keys($serialized), array(2, 1, 0)); // subtableIds are now consecutive // In the next test we compare an unserialized datatable with its original instance. // The unserialized datatable rows will have positive DATATABLE_ASSOCIATED ids. // Positive DATATABLE_ASSOCIATED ids mean that the associated sub-datatables are not loaded in memory. // In this case, this is NOT true: we know that the sub-datatable is loaded in memory. // HOWEVER, because of datatable id conflicts happening in the datatable manager, it is not yet // possible to know, after unserializing a datatable, if its sub-datatables are loaded in memory. $expectedTableRows = array(); $i = 0; foreach ($table->getRows() as $currentRow) { $expectedTableRow = clone $currentRow; $currentRowAssociatedDatatableId = $currentRow->subtableId; if ($currentRowAssociatedDatatableId != null) { $expectedTableRow->setNonLoadedSubtableId(++$i); // subtableIds are consecutive } $expectedTableRows[] = $expectedTableRow; } $tableAfter = new DataTable(); $tableAfter->addRowsFromSerializedArray($serialized[0]); $this->assertEquals($expectedTableRows, $tableAfter->getRows()); $subsubtableAfter = new DataTable(); $subsubtableAfter->addRowsFromSerializedArray($serialized[$consecutiveSubtableId = 2]); $this->assertEquals($subsubtable->getRows(), $subsubtableAfter->getRows()); $this->assertEquals($subsubtable->getRows(), DataTable::fromSerializedArray($serialized[$consecutiveSubtableId = 2])->getRows()); $this->assertTrue($subsubtable->getRowsCount() > 0); $this->assertEquals($table, Manager::getInstance()->getTable($idtable)); $this->assertEquals($subsubtable, Manager::getInstance()->getTable($idsubsubtable)); }
private function assertRows($expectedLabels, DataTable $dataTable) { $this->assertEquals($expectedLabels, $dataTable->getColumn('label')); $this->assertEquals(count($expectedLabels), $dataTable->getRowsCount()); }
public function test_filter_shouldNotFail_IfDataTableHasNoRows() { $table = new DataTable(); $table->filter($this->filter, array($this->report)); $this->assertSame(0, $table->getRowsCount()); }
/** * See {@link Sort}. * * @param DataTable $table * @return mixed */ public function filter($table) { if ($table instanceof Simple) { return; } if (empty($this->columnToSort)) { return; } if (!$table->getRowsCount()) { return; } $row = $table->getFirstRow(); if ($row === false) { return; } $this->columnToSort = $this->selectColumnToSort($row); $value = $this->getFirstValueFromDataTable($table); if (is_numeric($value) && $this->columnToSort !== 'label') { $methodToUse = "numberSort"; } else { if ($this->naturalSort) { $methodToUse = "naturalSort"; } else { $methodToUse = "sortString"; } } $this->sort($table, $methodToUse); }
public function setSitesTable(DataTable $sites) { $this->numSites = $sites->getRowsCount(); $this->sitesByGroup = $this->moveSitesHavingAGroupIntoSubtables($sites); }
private function assertOrder(DataTable $table, $expectedOrder) { $this->assertEquals($expectedOrder, $table->getColumn('label')); $this->assertEquals(count($expectedOrder), $table->getRowsCount()); }
/** * Extends an already generated insight report by adding a column "isMoverAndShaker" whether a row is also a * "Mover and Shaker" or not. * * Avoids the need to fetch all reports again when we already have the currentReport/lastReport */ public function markMoversAndShakers(DataTable $insight, $currentReport, $lastReport, $totalValue, $lastTotalValue) { if (!$insight->getRowsCount()) { return; } $limitIncreaser = max($insight->getRowsCount(), 3); $limitDecreaser = max($insight->getRowsCount(), 3); $lastDate = $insight->getMetadata('lastDate'); $date = $insight->getMetadata('date'); $period = $insight->getMetadata('period'); $metric = $insight->getMetadata('metric'); $orderBy = $insight->getMetadata('orderBy'); $reportMetadata = $insight->getMetadata('report'); $shakers = $this->generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser); foreach ($insight->getRows() as $row) { $label = $row->getColumn('label'); if ($shakers->getRowFromLabel($label)) { $row->setColumn('isMoverAndShaker', true); } else { $row->setColumn('isMoverAndShaker', false); } } $this->addMoversAndShakersMetadata($insight, $totalValue, $lastTotalValue); }
/** * @param DataTable $table * * @return string */ protected function renderDataTable($table) { if ($table->getRowsCount() == 0) { return "<strong><em>Empty table</em></strong><br />\n"; } $i = 1; $tableStructure = array(); /* * table = array * ROW1 = col1 | col2 | col3 | metadata | idSubTable * ROW2 = col1 | col2 (no value but appears) | col3 | metadata | idSubTable * subtable here */ $allColumns = array(); foreach ($table->getRows() as $row) { foreach ($row->getColumns() as $column => $value) { // for example, goals data is array: not supported in export RSS // in the future we shall reuse ViewDataTable for html exports in RSS anyway if (is_array($value)) { continue; } $allColumns[$column] = true; $tableStructure[$i][$column] = $value; } $i++; } $html = "\n"; $html .= "<table border=1 width=70%>"; $html .= "\n<tr>"; foreach ($allColumns as $name => $toDisplay) { if ($toDisplay !== false) { if ($this->translateColumnNames) { $name = $this->translateColumnName($name); } $html .= "\n\t<td><strong>{$name}</strong></td>"; } } $html .= "\n</tr>"; foreach ($tableStructure as $row) { $html .= "\n\n<tr>"; foreach ($allColumns as $columnName => $toDisplay) { if ($toDisplay !== false) { $value = "-"; if (isset($row[$columnName])) { $value = urldecode($row[$columnName]); } $html .= "\n\t<td>{$value}</td>"; } } $html .= "</tr>"; } $html .= "\n\n</table>"; return $html; }