/** * Serializes an entire DataTable hierarchy and returns the array of serialized DataTables. * * The first element in the returned array will be the serialized representation of this DataTable. * Every subsequent element will be a serialized subtable. * * This DataTable and subtables can optionally be truncated before being serialized. In most * cases where DataTables can become quite large, they should be truncated before being persisted * in an archive. * * The result of this method is intended for use with the {@link ArchiveProcessor::insertBlobRecord()} method. * * @throws Exception If infinite recursion detected. This will occur if a table's subtable is one of its parent tables. * @param int $maximumRowsInDataTable If not null, defines the maximum number of rows allowed in the serialized DataTable. * @param int $maximumRowsInSubDataTable If not null, defines the maximum number of rows allowed in serialized subtables. * @param string $columnToSortByBeforeTruncation The column to sort by before truncating, eg, `Metrics::INDEX_NB_VISITS`. * @return array The array of serialized DataTables: * * array( * // this DataTable (the root) * 0 => 'eghuighahgaueytae78yaet7yaetae', * * // a subtable * 1 => 'gaegae gh gwrh guiwh uigwhuige', * * // another subtable * 2 => 'gqegJHUIGHEQjkgneqjgnqeugUGEQHGUHQE', * * // etc. * ); */ public function getSerialized($maximumRowsInDataTable = null, $maximumRowsInSubDataTable = null, $columnToSortByBeforeTruncation = null) { static $depth = 0; // make sure subtableIds are consecutive from 1 to N static $subtableId = 0; if ($depth > self::$maximumDepthLevelAllowed) { $depth = 0; $subtableId = 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('Truncate', array($maximumRowsInDataTable - 1, DataTable::LABEL_SUMMARY_ROW, $columnToSortByBeforeTruncation, $filterRecursive = false)); } $consecutiveSubtableIds = array(); $forcedId = $subtableId; // 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 $id => $row) { $subTable = $row->getSubtable(); if ($subTable) { $consecutiveSubtableIds[$id] = ++$subtableId; $depth++; $aSerializedDataTable = $aSerializedDataTable + $subTable->getSerialized($maximumRowsInSubDataTable, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation); $depth--; } else { $row->removeSubtable(); } } // if the datatable is the parent we force the Id at 0 (this is part of the specification) if ($depth == 0) { $forcedId = 0; $subtableId = 0; } // we then serialize the rows and store them in the serialized dataTable $rows = array(); foreach ($this->rows as $id => $row) { if (array_key_exists($id, $consecutiveSubtableIds)) { $backup = $row->subtableId; $row->subtableId = $consecutiveSubtableIds[$id]; $rows[$id] = $row->export(); $row->subtableId = $backup; } else { $rows[$id] = $row->export(); } } if (isset($this->summaryRow)) { $rows[self::ID_SUMMARY_ROW] = $this->summaryRow->export(); } $aSerializedDataTable[$forcedId] = serialize($rows); unset($rows); return $aSerializedDataTable; }