public function setUp() { parent::setUp(); Piwik::createConfigObject(); Piwik_Config::getInstance()->setTestEnvironment(); Piwik_DataTable_Manager::getInstance()->deleteAll(); }
/** * Returns instance * * @return Piwik_DataTable_Manager */ public static function getInstance() { if (self::$instance == null) { self::$instance = new self(); } return self::$instance; }
protected function filter($table = null) { if (is_null($table)) { $table = $this->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 = Piwik_DataTable_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 && !Piwik_DataTable_Filter_Pattern::match($this->patternToSearch, $this->patternToSearchQuoted, $row->getColumn($this->columnToFilter))) { $table->deleteRow($key); } } return $table->getRowsCount(); }
/** * Returns instance * * @return Piwik_DataTable_Manager */ public static function getInstance() { if (self::$instance == null) { $c = __CLASS__; self::$instance = new $c(); } return self::$instance; }
/** * Reset this row to an empty one and sum the associated subtable again. */ public function recalculate() { $id = $this->getIdSubDataTable(); if ($id !== null) { $subtable = Piwik_DataTable_Manager::getInstance()->getTable($id); $this->sumTable($subtable); } }
/** * Filters a subtable * * @param Piwik_DataTable_Row $row * @return mixed */ public function filterSubTable(Piwik_DataTable_Row $row) { if (!$this->enableRecursive) { return; } if ($row->isSubtableLoaded()) { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()); $this->filter($subTable); } }
public function tearDown() { parent::tearDown(); Piwik_DataTable_Manager::getInstance()->deleteAll(); Piwik_Option::getInstance()->clearCache(); Piwik_Common::deleteTrackerCache(); Piwik_Site::clearCache(); Piwik::truncateAllTables(); Piwik_TablePartitioning::$tablesAlreadyInstalled = null; }
public function tearDown() { parent::tearDown(); Piwik_DataTable_Manager::getInstance()->deleteAll(); Piwik_Option::getInstance()->clearCache(); Piwik_Site::clearCache(); Piwik_Common::deleteTrackerCache(); Piwik_TablePartitioning::$tablesAlreadyInstalled = null; $tempTableName = Piwik_Common::prefixTable(Piwik_PrivacyManager_LogDataPurger::TEMP_TABLE_NAME); Piwik_Query("DROP TABLE IF EXISTS " . $tempTableName); }
public function filterSubTable(Piwik_DataTable_Row $row) { if (!$this->enableRecursive) { return; } try { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()); $this->filter($subTable); } catch (Exception $e) { // case idSubTable == null, or if the table is not loaded in memory } }
protected function filterTable($table) { foreach ($table->getRows() as $key => $row) { $this->renameColumns($row); try { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()); $this->filterTable($subTable); } catch (Exception $e) { // case idSubTable == null, or if the table is not loaded in memory } } }
/** * Truncates the table after X rows and adds a summary row * * @param Piwik_DataTable $table */ public function filter($table) { $table->filter('AddSummaryRow', array($this->truncateAfter)); $table->filter('ReplaceSummaryRowLabel'); foreach ($table->getRows() as $row) { if ($row->isSubtableLoaded()) { $idSubTable = $row->getIdSubDataTable(); $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); $subTable->filter('Truncate', array($this->truncateAfter)); } } }
public function filter($table) { $table->filter('AddSummaryRow', array($this->truncateAfter)); $table->filter('ReplaceSummaryRowLabel'); foreach ($table->getRows() as $row) { try { $idSubTable = $row->getIdSubDataTable(); $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); $subTable->filter('Truncate', array($this->truncateAfter)); } catch (Exception $e) { // there is no subtable loaded for example } } }
protected function renderTable($table) { if ($table instanceof Piwik_DataTable_Array) { $output = ''; $output .= "Piwik_DataTable_Array<hr>"; foreach ($table->getArray() as $descTable => $table) { $output .= "<b>" . $descTable . "</b><br>"; $output .= $table; $output .= "<hr>"; } return $output; } if ($table->getRowsCount() == 0) { return "Empty table <br>\n"; } static $depth = 0; $output = ''; $i = 1; foreach ($table->getRows() as $row) { $columns = array(); foreach ($row->getColumns() as $column => $value) { if (is_string($value)) { $value = "'{$value}'"; } $columns[] = "'{$column}' => {$value}"; } $columns = implode(", ", $columns); $details = array(); foreach ($row->getDetails() as $detail => $value) { if (is_string($value)) { $value = "'{$value}'"; } $details[] = "'{$detail}' => {$value}"; } $details = implode(", ", $details); $output .= str_repeat($this->prefixRows, $depth) . "- {$i} [" . $columns . "] [" . $details . "] [idsubtable = " . $row->getIdSubDataTable() . "]<br>\n"; if ($row->getIdSubDataTable() !== null) { $depth++; try { $output .= $this->renderTable(Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable())); } catch (Exception $e) { $output .= "-- Sub DataTable not loaded<br>\n"; } $depth--; } $i++; } return $output; }
protected function filterTable($table) { foreach ($table->getRows() as $key => $row) { $oldColumns = $row->getColumns(); $newColumns = $this->getRenamedColumns($oldColumns); $row->setColumns($newColumns); if ($this->applyFilterRecursively) { try { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()); $this->filterTable($subTable); } catch (Exception $e) { // case idSubTable == null, or if the table is not loaded in memory } } } }
/** * Updates the summary row label * * @param Piwik_DataTable $table */ public function filter($table) { $rows = $table->getRows(); foreach ($rows as $row) { if ($row->getColumn('label') == Piwik_DataTable::LABEL_SUMMARY_ROW) { $row->setColumn('label', $this->newLabel); break; } } // recurse foreach ($rows as $row) { if ($row->isSubtableLoaded()) { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()); $this->filter($subTable); } } }
/** * Resets all caches and drops the database */ public function tearDown() { parent::tearDown(); try { $plugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins(); foreach ($plugins as $plugin) { $plugin->uninstall(); } Piwik_PluginsManager::getInstance()->unloadPlugins(); } catch (Exception $e) { } Piwik::dropDatabase(); Piwik_DataTable_Manager::getInstance()->deleteAll(); Piwik_Option::getInstance()->clearCache(); Piwik_Site::clearCache(); Piwik_Common::deleteTrackerCache(); Piwik_Config::getInstance()->clear(); Piwik_TablePartitioning::$tablesAlreadyInstalled = null; Zend_Registry::_unsetInstance(); }
public static function tearDownAfterClass() { try { $plugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins(); foreach ($plugins as $plugin) { $plugin->uninstall(); } Piwik_PluginsManager::getInstance()->unloadPlugins(); } catch (Exception $e) { } Piwik::dropDatabase(); Piwik_DataTable_Manager::getInstance()->deleteAll(); Piwik_Option::getInstance()->clearCache(); Piwik_Site::clearCache(); Piwik_Common::deleteTrackerCache(); Piwik_Config::getInstance()->clear(); Piwik_TablePartitioning::$tablesAlreadyInstalled = null; Zend_Registry::_unsetInstance(); $_GET = $_REQUEST = array(); Piwik_Translate::getInstance()->unloadEnglishTranslation(); // re-enable tag cloud shuffling Piwik_Visualization_Cloud::$debugDisableShuffle = true; }
/** * The serialization returns a one dimension array containing all the * serialized DataTable contained in this DataTable. * We save DataTable in serialized format in the Database. * Each row of this returned PHP array will be a row in the DB table. * At the end of the method execution, the dataTable may be truncated (if $maximum* parameters are set). * * The keys of the array are very important as they are used to define the DataTable * * IMPORTANT: The main table (level 0, parent of all tables) will always be indexed by 0 * even it was created after some other tables. * It also means that all the parent tables (level 0) will be indexed with 0 in their respective * serialized arrays. You should never lookup a parent table using the getTable( $id = 0) as it * won't work. * * @throws Exception if an infinite recursion is found (a table row's has a subtable that is one of its parent table) * @param int If not null, defines the number of rows maximum of the serialized dataTable * If $addSummaryRowAfterNRows is less than the size of the table, a SummaryRow will be added at the end of the table, that * is the sum of the values of all the rows after the Nth row. All the rows after the Nth row will be deleted. * * @return array Serialized arrays * array( // Datatable level0 * 0 => 'eghuighahgaueytae78yaet7yaetae', * * // first Datatable level1 * 1 => 'gaegae gh gwrh guiwh uigwhuige', * * //second Datatable level1 * 2 => 'gqegJHUIGHEQjkgneqjgnqeugUGEQHGUHQE', * * //first Datatable level3 (child of second Datatable level1 for example) * 3 => 'eghuighahgaueytae78yaet7yaetaeGRQWUBGUIQGH&QE', * ); */ public function getSerialized($maximumRowsInDataTable = null, $maximumRowsInSubDataTable = null, $columnToSortByBeforeTruncation = null) { static $depth = 0; if ($depth > self::MAXIMUM_DEPTH_LEVEL_ALLOWED) { $depth = 0; throw new Exception("Maximum recursion level of " . self::MAXIMUM_DEPTH_LEVEL_ALLOWED . " reached. You have probably set a DataTable_Row with an associated DataTable which belongs already to its parent hierarchy."); } if (!is_null($maximumRowsInDataTable)) { $this->filter('AddSummaryRow', array($maximumRowsInDataTable - 1, Piwik_DataTable::LABEL_SUMMARY_ROW, $columnToSortByBeforeTruncation)); } // For each row, get the serialized row // If it is associated to a sub table, get the serialized table recursively ; // but returns all serialized tables and subtable in an array of 1 dimension $aSerializedDataTable = array(); foreach ($this->rows as $row) { if (($idSubTable = $row->getIdSubDataTable()) !== null) { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); $depth++; $aSerializedDataTable = $aSerializedDataTable + $subTable->getSerialized($maximumRowsInSubDataTable, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation); $depth--; } } // we load the current Id of the DataTable $forcedId = $this->getId(); // if the datatable is the parent we force the Id at 0 (this is part of the specification) if ($depth == 0) { $forcedId = 0; } // we then serialize the rows and store them in the serialized dataTable $addToRows = array(self::ID_SUMMARY_ROW => $this->summaryRow); if ($this->parents && Zend_Registry::get('config')->General->enable_archive_parents_of_datatable) { $addToRows[self::ID_PARENTS] = $this->parents; } $aSerializedDataTable[$forcedId] = serialize($this->rows + $addToRows); return $aSerializedDataTable; }
/** * Helper function to test if two rows are equal. * * Two rows are equal * - if they have exactly the same columns / details * - if they have a subDataTable associated, then we check that both of them are the same. * * @param Piwik_DataTable_Row row1 to compare * @param Piwik_DataTable_Row row2 to compare * * @return bool */ public static function isEqual(Piwik_DataTable_Row $row1, Piwik_DataTable_Row $row2) { //same columns $cols1 = $row1->getColumns(); $cols2 = $row2->getColumns(); uksort($cols1, 'strnatcasecmp'); uksort($cols2, 'strnatcasecmp'); if ($cols1 != $cols2) { return false; } $dets1 = $row1->getDetails(); $dets2 = $row2->getDetails(); ksort($dets1); ksort($dets2); // same details if ($dets1 != $dets2) { return false; } // either both are null // or both have a value if (!(is_null($row1->getIdSubDataTable()) && is_null($row2->getIdSubDataTable()))) { $subtable1 = Piwik_DataTable_Manager::getInstance()->getTable($row1->getIdSubDataTable()); $subtable2 = Piwik_DataTable_Manager::getInstance()->getTable($row2->getIdSubDataTable()); if (!Piwik_DataTable::isEqual($subtable1, $subtable2)) { return false; } } return true; }
/** * Post processing called at the end of the main archive processing. * Makes sure the new archive is marked as "successful" in the DB * * We also try to delete some stuff from memory but really there is still a lot... */ protected function postCompute() { // delete the first done = ERROR Piwik_Query("/* SHARDING_ID_SITE = " . $this->idsite . " */ \n\t\t\t\t\t\t\tDELETE FROM " . $this->tableArchiveNumeric->getTableName() . " \n\t\t\t\t\t\t\tWHERE idarchive = ? AND name = 'done'", array($this->idArchive)); $this->insertNumericRecord('done', Piwik_ArchiveProcessing::DONE_OK); Piwik_DataTable_Manager::getInstance()->deleteAll(); }
/** * This method will compute the sum of DataTables over the period for the given fields $aRecordName. * The resulting DataTable will be then added to queue of data to be recorded in the database. * It will usually be called in a plugin that listens to the hook 'ArchiveProcessing_Period.compute' * * For example if $aRecordName = 'UserCountry_country' the method will select all UserCountry_country DataTable for the period * (eg. the 31 dataTable of the last month), sum them, then record it in the DB * * * This method works on recursive dataTable. For example for the 'Actions' it will select all subtables of all dataTable of all the sub periods * and get the sum. * * It returns an array that gives information about the "final" DataTable. The array gives for every field name, the number of rows in the * final DataTable (ie. the number of distinct LABEL over the period) (eg. the number of distinct keywords over the last month) * * @param string|array $aRecordName Field name(s) of DataTable to select so we can get the sum * @param array $invalidSummedColumnNameToRenamedName (current_column_name => new_column_name) for columns that must change names when summed * (eg. unique visitors go from nb_uniq_visitors to sum_daily_nb_uniq_visitors) * @param int $maximumRowsInDataTableLevelZero Max row count of parent datatable to archive * @param int $maximumRowsInSubDataTable Max row count of children datatable(s) to archive * @param string $columnToSortByBeforeTruncation Column name to sort by, before truncating rows (ie. if there are more rows than the specified max row count) * * @return array array ( * nameTable1 => number of rows, * nameTable2 => number of rows, * ) */ public function archiveDataTable($aRecordName, $invalidSummedColumnNameToRenamedName = null, $maximumRowsInDataTableLevelZero = null, $maximumRowsInSubDataTable = null, $columnToSortByBeforeTruncation = null) { // We clean up below all tables created during this function call (and recursive calls) $latestUsedTableId = Piwik_DataTable_Manager::getInstance()->getMostRecentTableId(); $this->loadSubPeriods(); if (!is_array($aRecordName)) { $aRecordName = array($aRecordName); } $nameToCount = array(); foreach ($aRecordName as $recordName) { $table = $this->getRecordDataTableSum($recordName, $invalidSummedColumnNameToRenamedName); $nameToCount[$recordName]['level0'] = $table->getRowsCount(); $nameToCount[$recordName]['recursive'] = $table->getRowsCountRecursive(); $blob = $table->getSerialized($maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation); destroy($table); $this->insertBlobRecord($recordName, $blob); } Piwik_DataTable_Manager::getInstance()->deleteAll($latestUsedTableId); return $nameToCount; }
/** * Computes the given dataTable output and returns the string/binary * * @param Piwik_DataTable $table data table to render * @param string $prefix prefix to output before table data * @return string */ protected function renderTable($table, $prefix = "") { if ($table instanceof Piwik_DataTable_Array) { return $this->renderDataTableArray($table, $prefix); } if ($table->getRowsCount() == 0) { return "Empty table<br />\n"; } static $depth = 0; $output = ''; $i = 1; foreach ($table->getRows() as $row) { $dataTableArrayBreak = false; $columns = array(); foreach ($row->getColumns() as $column => $value) { if ($value instanceof Piwik_DataTable_Array) { $output .= $this->renderDataTableArray($value, $prefix); $dataTableArrayBreak = true; break; } if (is_string($value)) { $value = "'{$value}'"; } elseif (is_array($value)) { $value = var_export($value, true); } $columns[] = "'{$column}' => {$value}"; } if ($dataTableArrayBreak === true) { continue; } $columns = implode(", ", $columns); $metadata = array(); foreach ($row->getMetadata() as $name => $value) { if (is_string($value)) { $value = "'{$value}'"; } elseif (is_array($value)) { $value = var_export($value, true); } $metadata[] = "'{$name}' => {$value}"; } $metadata = implode(", ", $metadata); $output .= str_repeat($this->prefixRows, $depth) . "- {$i} [" . $columns . "] [" . $metadata . "] [idsubtable = " . $row->getIdSubDataTable() . "]<br />\n"; if (!is_null($row->getIdSubDataTable())) { if ($row->isSubtableLoaded()) { $depth++; $output .= $this->renderTable(Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable()), $prefix . ' '); $depth--; } else { $output .= "-- Sub DataTable not loaded<br />\n"; } } $i++; } return $output; }
public function setUp() { parent::setUp(); Piwik_DataTable_Manager::getInstance()->deleteAll(); }
protected function deleteInvalidSummedColumnsFromDataTable($dataTable) { foreach ($dataTable->getRows() as $row) { if (($idSubtable = $row->getIdSubDataTable()) !== null) { foreach (self::$invalidSummedColumnNameToDeleteFromDayArchive as $name) { $row->deleteColumn($name); } $this->deleteInvalidSummedColumnsFromDataTable(Piwik_DataTable_Manager::getInstance()->getTable($idSubtable)); } } }
/** * 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 * * @group Core * @group DataTable */ 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 = new Piwik_DataTable(); $useless1->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(13))); /* * end fake tables */ /* * MAIN TABLE */ $table = new Piwik_DataTable(); $subtable = new Piwik_DataTable(); $idtable = $table->getId(); $idsubtable = $subtable->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 */ $useless2 = new Piwik_DataTable(); $useless1->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(8487))); $useless3 = new Piwik_DataTable(); $useless3->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(8487))); /* * end fake tables */ $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554, 1 => 42, 2 => 657, 3 => 155744), Piwik_DataTable_Row::METADATA => array('logo' => 'test.png')); $row = new Piwik_DataTable_Row($row); $table->addRow($row); $table->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554, 1 => 42), Piwik_DataTable_Row::METADATA => array('url' => 'piwik.org'))); $table->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(0 => 787877888787.0), Piwik_DataTable_Row::METADATA => array('url' => 'OUPLA ADDED'), Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subtable)); /* * SUB TABLE */ $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554), Piwik_DataTable_Row::METADATA => array('searchengine' => 'google')); $subtable->addRowFromArray($row); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 84894), Piwik_DataTable_Row::METADATA => array('searchengine' => 'yahoo')); $subtable->addRowFromArray($row); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 4898978989.0), Piwik_DataTable_Row::METADATA => array('searchengine' => 'ask')); $subtable->addRowFromArray($row); /* * SUB SUB TABLE */ $subsubtable = new Piwik_DataTable(); $subsubtable->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(245), Piwik_DataTable_Row::METADATA => array('yes' => 'subsubmetadata1'))); $subsubtable->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(13), Piwik_DataTable_Row::METADATA => array('yes' => 'subsubmetadata2'))); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 666666666666666.0), Piwik_DataTable_Row::METADATA => array('url' => 'NEW ROW ADDED'), Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subsubtable); $subtable->addRowFromArray($row); $idsubsubtable = $subsubtable->getId(); $serialized = $table->getSerialized(); $this->assertEquals(array_keys($serialized), array($idsubsubtable, $idsubtable, 0)); // 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(); foreach ($table->getRows() as $currentRow) { $expectedTableRow = clone $currentRow; $currentRowAssociatedDatatableId = $currentRow->c[Piwik_DataTable_Row::DATATABLE_ASSOCIATED]; if ($currentRowAssociatedDatatableId != null) { // making DATATABLE_ASSOCIATED ids positive $expectedTableRow->c[Piwik_DataTable_Row::DATATABLE_ASSOCIATED] = -1 * $currentRowAssociatedDatatableId; } $expectedTableRows[] = $expectedTableRow; } $tableAfter = new Piwik_DataTable(); $tableAfter->addRowsFromSerializedArray($serialized[0]); $this->assertEquals($expectedTableRows, $tableAfter->getRows()); $subsubtableAfter = new Piwik_DataTable(); $subsubtableAfter->addRowsFromSerializedArray($serialized[$idsubsubtable]); $this->assertEquals($subsubtable->getRows(), $subsubtableAfter->getRows()); $this->assertEquals($table, Piwik_DataTable_Manager::getInstance()->getTable($idtable)); $this->assertEquals($subsubtable, Piwik_DataTable_Manager::getInstance()->getTable($idsubsubtable)); }
/** * The serialization returns a one dimension array containing all the * serialized DataTable contained in this DataTable. * We save DataTable in serialized format in the Database. * Each row of this returned PHP array will be a row in the DB table. * At the end of the method execution, the dataTable may be truncated (if $maximum* parameters are set). * * The keys of the array are very important as they are used to define the DataTable * * IMPORTANT: The main table (level 0, parent of all tables) will always be indexed by 0 * even it was created after some other tables. * It also means that all the parent tables (level 0) will be indexed with 0 in their respective * serialized arrays. You should never lookup a parent table using the getTable( $id = 0) as it * won't work. * * @throws Exception if an infinite recursion is found (a table row's has a subtable that is one of its parent table) * @param int $maximumRowsInDataTable If not null, defines the number of rows maximum of the serialized dataTable * @param int $maximumRowsInSubDataTable If not null, defines the number of rows maximum of the serialized subDataTable * @param string $columnToSortByBeforeTruncation Column to sort by before truncation * @return array Serialized arrays * array( // Datatable level0 * 0 => 'eghuighahgaueytae78yaet7yaetae', * * // first Datatable level1 * 1 => 'gaegae gh gwrh guiwh uigwhuige', * * //second Datatable level1 * 2 => 'gqegJHUIGHEQjkgneqjgnqeugUGEQHGUHQE', * * //first Datatable level3 (child of second Datatable level1 for example) * 3 => 'eghuighahgaueytae78yaet7yaetaeGRQWUBGUIQGH&QE', * ); */ public function getSerialized($maximumRowsInDataTable = null, $maximumRowsInSubDataTable = null, $columnToSortByBeforeTruncation = null) { static $depth = 0; if ($depth > self::$maximumDepthLevelAllowed) { $depth = 0; throw new Exception("Maximum recursion level of " . self::$maximumDepthLevelAllowed . " reached. Maybe you have set a DataTable_Row with an associated DataTable belonging already to one of its parent tables?"); } if (!is_null($maximumRowsInDataTable)) { $this->filter('AddSummaryRow', array($maximumRowsInDataTable - 1, Piwik_DataTable::LABEL_SUMMARY_ROW, $columnToSortByBeforeTruncation)); } // For each row, get the serialized row // If it is associated to a sub table, get the serialized table recursively ; // but returns all serialized tables and subtable in an array of 1 dimension $aSerializedDataTable = array(); foreach ($this->rows as $row) { if (($idSubTable = $row->getIdSubDataTable()) !== null) { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); $depth++; $aSerializedDataTable = $aSerializedDataTable + $subTable->getSerialized($maximumRowsInSubDataTable, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation); $depth--; } } // we load the current Id of the DataTable $forcedId = $this->getId(); // if the datatable is the parent we force the Id at 0 (this is part of the specification) if ($depth == 0) { $forcedId = 0; } // we then serialize the rows and store them in the serialized dataTable $addToRows = array(self::ID_SUMMARY_ROW => $this->summaryRow); if ($this->parents && Piwik_Config::getInstance()->General['enable_archive_parents_of_datatable']) { $addToRows[self::ID_PARENTS] = $this->parents; } $aSerializedDataTable[$forcedId] = serialize($this->rows + $addToRows); foreach ($this->rows as &$row) { $row->cleanPostSerialize(); } return $aSerializedDataTable; }
/** * 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 */ function test_general() { /* * create some fake tables to make sure that the serialized array of the first TABLE * does not take in consideration those tables */ $useless1 = new Piwik_DataTable(); $useless1->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(13))); /* * end fake tables */ /* * MAIN TABLE */ $table = new Piwik_DataTable(); $subtable = new Piwik_DataTable(); $idtable = $table->getId(); $idsubtable = $subtable->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 */ $useless2 = new Piwik_DataTable(); $useless1->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(8487))); $useless3 = new Piwik_DataTable(); $useless3->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(8487))); /* * end fake tables */ $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554, 1 => 42, 2 => 657, 3 => 155744), Piwik_DataTable_Row::METADATA => array('logo' => 'test.png')); $row = new Piwik_DataTable_Row($row); $table->addRow($row); $table->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554, 1 => 42), Piwik_DataTable_Row::METADATA => array('url' => 'piwik.org'))); $table->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(0 => 787877888787), Piwik_DataTable_Row::METADATA => array('url' => 'OUPLA ADDED'), Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subtable)); /* * SUB TABLE */ $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 1554), Piwik_DataTable_Row::METADATA => array('searchengine' => 'google')); $subtable->addRowFromArray($row); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 84894), Piwik_DataTable_Row::METADATA => array('searchengine' => 'yahoo')); $subtable->addRowFromArray($row); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 4898978989), Piwik_DataTable_Row::METADATA => array('searchengine' => 'ask')); $subtable->addRowFromArray($row); /* * SUB SUB TABLE */ $subsubtable = new Piwik_DataTable(); $subsubtable->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(245), Piwik_DataTable_Row::METADATA => array('yes' => 'subsubmetadata1'))); $subsubtable->addRowFromArray(array(Piwik_DataTable_Row::COLUMNS => array(13), Piwik_DataTable_Row::METADATA => array('yes' => 'subsubmetadata2'))); $row = array(Piwik_DataTable_Row::COLUMNS => array(0 => 666666666666666), Piwik_DataTable_Row::METADATA => array('url' => 'NEW ROW ADDED'), Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subsubtable); $subtable->addRowFromArray($row); $idsubsubtable = $subsubtable->getId(); $serialized = $table->getSerialized(); $this->assertEqual(array_keys($serialized), array($idsubsubtable, $idsubtable, 0)); $tableAfter = new Piwik_DataTable(); $tableAfter->addRowsFromSerializedArray($serialized[0]); $this->assertEqual($table->getRows(), $tableAfter->getRows()); $subsubtableAfter = new Piwik_DataTable(); $subsubtableAfter->addRowsFromSerializedArray($serialized[$idsubsubtable]); $this->assertEqual($subsubtable->getRows(), $subsubtableAfter->getRows()); $this->assertEqual($table, Piwik_DataTable_Manager::getInstance()->getTable($idtable)); $this->assertEqual($subsubtable, Piwik_DataTable_Manager::getInstance()->getTable($idsubsubtable)); }
protected function getArrayFromRecursiveDataTable($dataTable, $depth = 0) { $table = array(); foreach ($dataTable->getRows() as $row) { $phpArray = array(); if (($idSubtable = $row->getIdSubDataTable()) !== null) { $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubtable); if ($subTable->getRowsCount() > 0) { $phpArray = $this->getArrayFromRecursiveDataTable($subTable, $depth + 1); } } $newRow = array('level' => $depth, 'columns' => $row->getColumns(), 'metadata' => $row->getMetadata(), 'idsubdatatable' => $row->getIdSubDataTable()); $table[] = $newRow; if (count($phpArray) > 0) { $table = array_merge($table, $phpArray); } } return $table; }
/** * Converts the given data table to an array * * @param Piwik_DataTable $table * @return array */ protected function renderTable($table) { $array = array(); foreach ($table->getRows() as $id => $row) { $newRow = array('columns' => $row->getColumns(), 'metadata' => $row->getMetadata(), 'idsubdatatable' => $row->getIdSubDataTable()); if ($id == Piwik_DataTable::ID_SUMMARY_ROW) { $newRow['issummaryrow'] = true; } if ($this->isRenderSubtables() && $row->isSubtableLoaded()) { $subTable = $this->renderTable(Piwik_DataTable_Manager::getInstance()->getTable($row->getIdSubDataTable())); $newRow['subtable'] = $subTable; if ($this->hideIdSubDatatable === false && isset($newRow['metadata']['idsubdatatable_in_db'])) { $newRow['columns']['idsubdatatable'] = $newRow['metadata']['idsubdatatable_in_db']; } unset($newRow['metadata']['idsubdatatable_in_db']); } if ($this->hideIdSubDatatable !== false) { unset($newRow['idsubdatatable']); } $array[] = $newRow; } return $array; }
/** * Helper function to test if two rows are equal. * * Two rows are equal * - if they have exactly the same columns / metadata * - if they have a subDataTable associated, then we check that both of them are the same. * * @param Piwik_DataTable_Row row1 to compare * @param Piwik_DataTable_Row row2 to compare * * @return bool */ public static function isEqual(Piwik_DataTable_Row $row1, Piwik_DataTable_Row $row2) { //same columns $cols1 = $row1->getColumns(); $cols2 = $row2->getColumns(); $diff1 = array_udiff($cols1, $cols2, array(__CLASS__, 'compareElements')); $diff2 = array_udiff($cols2, $cols1, array(__CLASS__, 'compareElements')); if ($diff1 != $diff2) { return false; } $dets1 = $row1->getMetadata(); $dets2 = $row2->getMetadata(); ksort($dets1); ksort($dets2); if ($dets1 != $dets2) { return false; } // either both are null // or both have a value if (!(is_null($row1->getIdSubDataTable()) && is_null($row2->getIdSubDataTable()))) { $subtable1 = Piwik_DataTable_Manager::getInstance()->getTable($row1->getIdSubDataTable()); $subtable2 = Piwik_DataTable_Manager::getInstance()->getTable($row2->getIdSubDataTable()); if (!Piwik_DataTable::isEqual($subtable1, $subtable2)) { return false; } } return true; }