/** * @param Piwik_DataTable_Row $row * @param Piwik_DataTable $dataTable * @param string $date * @param string $labelPrefix * @param bool $parentLogo */ private function flattenRow(Piwik_DataTable_Row $row, Piwik_DataTable $dataTable, $date, $labelPrefix = '', $parentLogo = false) { $label = $row->getColumn('label'); if ($label !== false) { $label = trim($label); if (substr($label, 0, 1) == '/' && $this->recursiveLabelSeparator == '/') { $label = substr($label, 1); } $label = $labelPrefix . $label; $row->setColumn('label', $label); } $logo = $row->getMetadata('logo'); if ($logo === false && $parentLogo !== false) { $logo = $parentLogo; $row->setMetadata('logo', $logo); } $subTable = $this->loadSubtable($row, $date); $row->removeSubtable(); if ($subTable === null) { if ($this->includeAggregateRows) { $row->setMetadata('is_aggregate', 0); } $dataTable->addRow($row); } else { if ($this->includeAggregateRows) { $row->setMetadata('is_aggregate', 1); $dataTable->addRow($row); } $prefix = $label . $this->recursiveLabelSeparator; foreach ($subTable->getRows() as $row) { $this->flattenRow($row, $dataTable, $date, $prefix, $logo); } } }
/** * Add a row to the table and rebuild the index if necessary * * @param Piwik_DataTable_Row $row to add at the end of the array */ public function addRow(Piwik_DataTable_Row $row) { $this->rows[] = $row; if (!$this->indexNotUpToDate && $this->rebuildIndexContinuously) { $label = $row->getColumn('label'); if ($label !== false) { $this->rowsIndexByLabel[$label] = count($this->rows) - 1; } $this->indexNotUpToDate = false; } }
protected function updateActionsTableWithRowQuery($query) { $rowsProcessed = 0; while ($row = $query->fetch()) { // in some unknown case, the type field is NULL, as reported in #1082 - we ignore this page view if (empty($row['type'])) { continue; } $actionExplodedNames = $this->getActionExplodedNames($row['name'], $row['type']); // we work on the root table of the given TYPE (either ACTION_URL or DOWNLOAD or OUTLINK etc.) $currentTable =& $this->actionsTablesByType[$row['type']]; // go to the level of the subcategory $end = count($actionExplodedNames) - 1; for ($level = 0; $level < $end; $level++) { $actionCategory = $actionExplodedNames[$level]; $currentTable =& $currentTable[$actionCategory]; } $actionName = $actionExplodedNames[$end]; // we are careful to prefix the page URL / name with some value // so that if a page has the same name as a category // we don't merge both entries if ($row['type'] == Piwik_Tracker_Action::TYPE_ACTION_URL) { $actionName = '/' . $actionName; } else { $actionName = ' ' . $actionName; } // currentTable is now the array element corresponding the the action // at this point we may be for example at the 4th level of depth in the hierarchy $currentTable =& $currentTable[$actionName]; // add the row to the matching sub category subtable if (!$currentTable instanceof Piwik_DataTable_Row) { if ($row['type'] == Piwik_Tracker_Action::TYPE_ACTION_NAME) { $currentTable = new Piwik_DataTable_Row(array(Piwik_DataTable_Row::COLUMNS => array('label' => (string) $actionName))); } else { $currentTable = new Piwik_DataTable_Row(array(Piwik_DataTable_Row::COLUMNS => array('label' => (string) $actionName), Piwik_DataTable_Row::METADATA => array('url' => (string) $row['name']))); } } foreach ($row as $name => $value) { // we don't add this information as itnot pertinent // name is already set as the label // and it has been cleaned from the categories and extracted from the initial string // type is used to partition the different actions type in different table. Adding the info to the row would be a duplicate. if ($name != 'name' && $name != 'type') { // in some edge cases, we have twice the same action name with 2 different idaction // this happens when 2 visitors visit the same new page at the same time, there is a SELECT and an INSERT for each new page, // and in between the two the other visitor comes. // here we handle the case where there is already a row for this action name, if this is the case we add the value if (($alreadyValue = $currentTable->getColumn($name)) !== false) { $currentTable->setColumn($name, $alreadyValue + $value); } else { $currentTable->addColumn($name, $value); } } } // if the exit_action was not recorded properly in the log_link_visit_action // there would be an error message when getting the nb_hits column // we must fake the record and add the columns if ($currentTable->getColumn('nb_hits') === false) { // to test this code: delete the entries in log_link_action_visit for // a given exit_idaction_url foreach ($this->defaultRow->getColumns() as $name => $value) { $currentTable->addColumn($name, $value); } } // simple count $rowsProcessed++; } // just to make sure php copies the last $currentTable in the $parentTable array $currentTable =& $this->actionsTablesByType; return $rowsProcessed; }
/** * Returns the element that should be replaced * * @param Piwik_DataTable_Row $row * @param string $columnToFilter * @return mixed */ protected function getElementToReplace($row, $columnToFilter) { return $row->getColumn($columnToFilter); }
/** * Returns column from a given row. * Will work with 2 types of datatable * - raw datatables coming from the archive DB, which columns are int indexed * - datatables processed resulting of API calls, which columns have human readable english names * * @param Piwik_DataTable_Row $row * @param int $columnIdRaw see consts in Piwik_Archive:: * @return mixed Value of column, false if not found */ protected function getColumn($row, $columnIdRaw, $mappingIdToName = false) { if (empty($mappingIdToName)) { $mappingIdToName = Piwik_Archive::$mappingFromIdToName; } $columnIdReadable = $mappingIdToName[$columnIdRaw]; if ($row instanceof Piwik_DataTable_Row) { $raw = $row->getColumn($columnIdRaw); if ($raw !== false) { return $raw; } return $row->getColumn($columnIdReadable); } if (isset($row[$columnIdRaw])) { return $row[$columnIdRaw]; } if (isset($row[$columnIdReadable])) { return $row[$columnIdReadable]; } return false; }
/** * Utility function. Returns the current row in the past DataTable. * * @param Piwik_DataTable_Row $row The row in the 'current' DataTable. */ private function getPastRowFromCurrent($row) { return $this->pastDataTable->getRowFromLabel($row->getColumn('label')); }
/** * Returns the divisor to use when calculating the new column value. Can * be overridden by descendent classes to customize behavior. * * @param Piwik_DataTable_Row $row The row being modified. * @return int|float */ protected function getDivisor($row) { if (!is_null($this->totalValueUsedAsDivisor)) { return $this->totalValueUsedAsDivisor; } else { return $row->getColumn($this->columnNameUsedAsDivisor); } }
/** * Returns the divisor to use when calculating the new column value. Can * be overridden by descendent classes to customize behavior. * * @param Piwik_DataTable_Row $row The row being modified. * @return int|float */ protected function getDivisor($row) { if (!is_null($this->totalValueUsedAsDivisor)) { return $this->totalValueUsedAsDivisor; } else { if ($this->getDivisorFromSummaryRow) { $summaryRow = $this->table->getRowFromId(Piwik_DataTable::ID_SUMMARY_ROW); return $summaryRow->getColumn($this->columnNameUsedAsDivisor); } else { return $row->getColumn($this->columnNameUsedAsDivisor); } } }
/** * Sets the column to be used for sorting * * @param Piwik_DataTable_Row $row * @return int */ protected function selectColumnToSort($row) { $value = $row->getColumn($this->columnToSort); if ($value !== false) { return $this->columnToSort; } // sorting by "nb_visits" but the index is Piwik_Archive::INDEX_NB_VISITS in the table if (isset(Piwik_Archive::$mappingFromNameToId[$this->columnToSort])) { $column = Piwik_Archive::$mappingFromNameToId[$this->columnToSort]; $value = $row->getColumn($column); if ($value !== false) { return $column; } } // eg. was previously sorted by revenue_per_visit, but this table // doesn't have this column; defaults with nb_visits $column = Piwik_Archive::INDEX_NB_VISITS; $value = $row->getColumn($column); if ($value !== false) { return $column; } // even though this column is not set properly in the table, // we select it for the sort, so that the table's internal state is set properly return $this->columnToSort; }