array( * 'label' => 'Piwik', * 'column1' => 42, * 'visits' => 657, * 'time_spent' => 155744, * ), * Piwik_DataTable_Row::DETAILS => array( * 'logo' => 'test.png' * ), * Piwik_DataTable_Row::DATATABLE_ASSOCIATED => #Piwik_DataTable object (but in the row only the ID will be stored) * ) */ public function __construct( $row = array() ) { $this->c[self::COLUMNS] = array(); $this->c[self::DETAILS] = array(); $this->c[self::DATATABLE_ASSOCIATED] = null; if(isset($row[self::COLUMNS])) { $this->c[self::COLUMNS] = $row[self::COLUMNS]; } if(isset($row[self::DETAILS])) { $this->c[self::DETAILS] = $row[self::DETAILS]; } if(isset($row[self::DATATABLE_ASSOCIATED]) && $row[self::DATATABLE_ASSOCIATED] instanceof Piwik_DataTable) { $this->c[self::DATATABLE_ASSOCIATED] = $row[self::DATATABLE_ASSOCIATED]->getId(); } } /** * When destroyed, a row destroys its associated subTable if there is one */ public function __destruct() { $idSubtable = $this->getIdSubDataTable(); if(!is_null($idSubtable)) { unset($idSubtable); } } /** * Applys a basic rendering to the Row and returns the output * * @return string characterizing the row. Example: - 1 ['label' => 'piwik', 'nb_uniq_visitors' => 1685, 'nb_visits' => 1861, 'nb_actions' => 2271, 'max_actions' => 13, 'sum_visit_length' => 920131, 'bounce_count' => 1599] [] [idsubtable = 1375] */ public function __toString() { $columns = array(); foreach($this->getColumns() as $column => $value) { if(is_string($value)) $value = "'$value'"; $columns[] = "'$column' => $value"; } $columns = implode(", ", $columns); $details=array(); foreach($this->getDetails() as $detail => $value) { if(is_string($value)) $value = "'$value'"; $details[] = "'$detail' => $value"; } $details = implode(", ", $details); $output = "# [".$columns."] [".$details."] [idsubtable = " . $this->getIdSubDataTable()."]
\n"; return $output; } /** * Deletes the given column * * @param string Column name * @return bool True on success, false if the column didn't exist */ public function deleteColumn( $name ) { if(!isset($this->c[self::COLUMNS][$name])) { return false; } unset($this->c[self::COLUMNS][$name]); return true; } /** * Returns the given column * * @param string Column name * @return mixed|false The column value */ public function getColumn( $name ) { if(!isset($this->c[self::COLUMNS][$name])) { return false; } return $this->c[self::COLUMNS][$name]; } /** * Returns the given detail * * @param string Detail name * @return mixed|false The detail value */ public function getDetail( $name ) { if(!isset($this->c[self::DETAILS][$name])) { return false; } return $this->c[self::DETAILS][$name]; } /** * Returns the array containing all the columns * * @return array Example: array( * 'column1' => VALUE, * 'label' => 'www.php.net' * 'nb_visits' => 15894, * ) */ public function getColumns() { return $this->c[self::COLUMNS]; } /** * Returns the array containing all the details * * @return array Example: array( * 'logo' => 'images/logo/www.google.png', * 'url' => 'www.google.com' * ) */ public function getDetails() { return $this->c[self::DETAILS]; } /** * Returns the ID of the subDataTable. * If there is no such a table, returns null. * * @return int|null */ public function getIdSubDataTable() { return $this->c[self::DATATABLE_ASSOCIATED]; } /** * Sums a DataTable to this row subDataTable. * If this row doesn't have a SubDataTable yet, we create a new one. * Then we add the values of the given DataTable to this row's DataTable. * * @param Piwik_DataTable Table to sum to this row's subDatatable * @see Piwik_DataTable::addDataTable() for the algorithm used for the sum */ public function sumSubtable(Piwik_DataTable $subTable) { $thisSubtableID = $this->getIdSubDataTable(); if($thisSubtableID === null) { $thisSubTable = new Piwik_DataTable; $this->addSubtable($thisSubTable); } else { $thisSubTable = Piwik_DataTable_Manager::getInstance()->getTable( $thisSubtableID ); } $thisSubTable->addDataTable($subTable); } /** * Set a DataTable to be associated to this row. * If the row already has a DataTable associated to it, throws an Exception. * * @param Piwik_DataTable DataTable to associate to this row * @throws Exception * */ public function addSubtable(Piwik_DataTable $subTable) { if(!is_null($this->c[self::DATATABLE_ASSOCIATED])) { throw new Exception("Adding a subtable to the row, but it already has a subtable associated."); } $this->c[self::DATATABLE_ASSOCIATED] = $subTable->getId(); } /** * Set a DataTable to this row. If there is already * a DataTable associated, it is simply overwritten. * * @param Piwik_DataTable DataTable to associate to this row */ public function setSubtable(Piwik_DataTable $subTable) { $this->c[self::DATATABLE_ASSOCIATED] = $subTable->getId(); } /** * Set all the columns at once. Overwrites previously set columns. * * @param array array( * 'label' => 'www.php.net' * 'nb_visits' => 15894, * ) */ public function setColumns( $columns ) { $this->c[self::COLUMNS] = $columns; } /** * Set the value $value to the column called $name. * * @param string $name of the column to set * @param mixed $value of the column to set */ public function setColumn($name, $value) { if(isset($this->c[self::COLUMNS][$name]) || $name != 'label') { $this->c[self::COLUMNS][$name] = $value; } // we make sure when adding the label it goes first in the table else { $this->c[self::COLUMNS] = array($name => $value) + $this->c[self::COLUMNS]; } } /** * Add a new column to the row. If the column already exists, throws an exception * * @param string $name of the column to add * @param mixed $value of the column to set * @throws Exception */ public function addColumn($name, $value) { if(isset($this->c[self::COLUMNS][$name])) { throw new Exception("Column $name already in the array!"); } $this->c[self::COLUMNS][$name] = $value; } /** * Add a new detail to the row. If the column already exists, throws an exception. * * @param string $name of the detail to add * @param mixed $value of the detail to set * @throws Exception */ public function addDetail($name, $value) { if(isset($this->c[self::DETAILS][$name])) { throw new Exception("Detail $name already in the array!"); } $this->c[self::DETAILS][$name] = $value; } /** * Sums the given $row columns values to the existing row' columns values. * It will sum only the int or float values of $row. * It will not sum the column 'label' even if it has a numeric value. * * If a given column doesn't exist in $this then it is added with the value of $row. * If the column already exists in $this then we have * this.columns[idThisCol] += $row.columns[idThisCol] */ public function sumRow( Piwik_DataTable_Row $rowToSum ) { foreach($rowToSum->getColumns() as $name => $value) { if($name != 'label' && Piwik::isNumeric($value)) { $current = $this->getColumn($name); if($current === false) { $current = 0; } $this->setColumn( $name, $current + $value); } } } /** * 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 */ static public 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; } } require_once "Row/DataTableSummary.php";