/** * Computes the output for the given data table * * @param Piwik_DataTable $table * @return string * @throws Exception */ protected function renderTable($table) { if (!$table instanceof Piwik_DataTable_Array || $table->getKeyName() != 'date') { throw new Exception("RSS feeds can be generated for one specific website &idSite=X." . "\nPlease specify only one idSite or consider using &format=XML instead."); } $idSite = Piwik_Common::getRequestVar('idSite', 1, 'int'); $period = Piwik_Common::getRequestVar('period'); $piwikUrl = Piwik_Url::getCurrentUrlWithoutFileName() . "?module=CoreHome&action=index&idSite=" . $idSite . "&period=" . $period; $out = ""; $moreRecentFirst = array_reverse($table->getArray(), true); foreach ($moreRecentFirst as $date => $subtable) { $timestamp = $table->metadata[$date]['timestamp']; $site = $table->metadata[$date]['site']; $pudDate = date('r', $timestamp); $dateInSiteTimezone = Piwik_Date::factory($timestamp)->setTimezone($site->getTimezone())->toString('Y-m-d'); $thisPiwikUrl = Piwik_Common::sanitizeInputValue($piwikUrl . "&date={$dateInSiteTimezone}"); $siteName = $site->getName(); $title = $siteName . " on " . $date; $out .= "\t<item>\n\t\t<pubDate>{$pudDate}</pubDate>\n\t\t<guid>{$thisPiwikUrl}</guid>\n\t\t<link>{$thisPiwikUrl}</link>\n\t\t<title>{$title}</title>\n\t\t<author>http://piwik.org</author>\n\t\t<description>"; $out .= Piwik_Common::sanitizeInputValue($this->renderDataTable($subtable)); $out .= "</description>\n\t</item>\n"; } $header = $this->getRssHeader(); $footer = $this->getRssFooter(); return $header . $out . $footer; }
/** * This method can be used by subclasses to iterate over data tables that might be * data table arrays. It calls back the template method self::doManipulate for each table. * This way, data table arrays can be handled in a transparent fashion. * * @param Piwik_DataTable_Array|Piwik_DataTable $dataTable * @throws Exception * @return Piwik_DataTable_Array|Piwik_DataTable */ protected function manipulate($dataTable) { if ($dataTable instanceof Piwik_DataTable_Array) { $newTableArray = new Piwik_DataTable_Array(); $newTableArray->metadata = $dataTable->metadata; $newTableArray->setKeyName($dataTable->getKeyName()); foreach ($dataTable->getArray() as $date => $subTable) { // for period=week, the label is "2011-08-15 to 2011-08-21", which is // an invalid date parameter => only use the first date // in other languages the whole string does not start with the date so // we need to preg match it. if (!preg_match('/[0-9]{4}(-[0-9]{2})?(-[0-9]{2})?/', $date, $match)) { throw new Exception("Could not recognize date: {$date}"); } $dateForApiRequest = $match[0]; $subTable = $this->doManipulate($subTable, $dateForApiRequest); $newTableArray->addTable($subTable, $date); } return $newTableArray; } if ($dataTable instanceof Piwik_DataTable) { return $this->doManipulate($dataTable); } return $dataTable; }
/** * Computes the output for the given data table * * @param Piwik_DataTable $table * @return string */ protected function renderTable($table) { if ($table instanceof Piwik_DataTable_Array) { foreach ($table->getArray() as $date => $subtable) { if ($subtable->getRowsCount()) { $this->buildTableStructure($subtable, '_' . $table->getKeyName(), $date); } } } else { if ($table->getRowsCount()) { $this->buildTableStructure($table); } } $out = $this->renderDataTable(); return $out; }
/** * Apply generic filters to the DataTable object resulting from the API Call. * Disable this feature by setting the parameter disable_generic_filters to 1 in the API call request. * * @param Piwik_DataTable $datatable * @return bool */ protected function applyGenericFilters($datatable) { if ($datatable instanceof Piwik_DataTable_Array) { $tables = $datatable->getArray(); $filterWasApplied = false; foreach ($tables as $table) { $filterWasApplied = $this->applyGenericFilters($table); } return; } $genericFilters = self::getGenericFiltersInformation(); $filterApplied = false; foreach ($genericFilters as $filterName => $parameters) { $filterParameters = array(); $exceptionRaised = false; foreach ($parameters as $name => $info) { // parameter type to cast to $type = $info[0]; // default value if specified, when the parameter doesn't have a value $defaultValue = null; if (isset($info[1])) { $defaultValue = $info[1]; } // third element in the array, if it exists, overrides the name of the request variable $varName = $name; if (isset($info[2])) { $varName = $info[2]; } try { $value = Piwik_Common::getRequestVar($name, $defaultValue, $type, $this->request); settype($value, $type); $filterParameters[] = $value; } catch (Exception $e) { $exceptionRaised = true; break; } } if (!$exceptionRaised) { $datatable->filter($filterName, $filterParameters); $filterApplied = true; } } return $filterApplied; }
/** * Enhance a $dataTable using metadata : * * - remove metrics based on $reportMetadata['metrics'] * - add 0 valued metrics if $dataTable doesn't provide all $reportMetadata['metrics'] * - format metric values to a 'human readable' format * - extract row metadata to a separate Piwik_DataTable_Simple|Piwik_DataTable_Array : $rowsMetadata * - translate metric names to a separate array : $columns * * @param int $idSite enables monetary value formatting based on site currency * @param Piwik_DataTable|Piwik_DataTable_Array $dataTable * @param array $reportMetadata * @param boolean $hasDimension * @return array Piwik_DataTable_Simple|Piwik_DataTable_Array $newReport with human readable format & array $columns list of translated column names & Piwik_DataTable_Simple|Piwik_DataTable_Array $rowsMetadata **/ private function handleTableReport($idSite, $dataTable, &$reportMetadata, $hasDimension) { $columns = $reportMetadata['metrics']; if ($hasDimension) { $columns = array_merge(array('label' => $reportMetadata['dimension']), $columns); if (isset($reportMetadata['processedMetrics'])) { $processedMetricsAdded = $this->getDefaultProcessedMetrics(); foreach ($processedMetricsAdded as $processedMetricId => $processedMetricTranslation) { // this processed metric can be displayed for this report if (isset($reportMetadata['processedMetrics'][$processedMetricId])) { $columns[$processedMetricId] = $processedMetricTranslation; } } } // Display the global Goal metrics if (isset($reportMetadata['metricsGoal'])) { $metricsGoalDisplay = array('revenue'); // Add processed metrics to be displayed for this report foreach ($metricsGoalDisplay as $goalMetricId) { if (isset($reportMetadata['metricsGoal'][$goalMetricId])) { $columns[$goalMetricId] = $reportMetadata['metricsGoal'][$goalMetricId]; } } } if (isset($reportMetadata['processedMetrics'])) { // Add processed metrics $dataTable->filter('AddColumnsProcessedMetrics', array($deleteRowsWithNoVisit = false)); } } // $dataTable is an instance of Piwik_DataTable_Array when multiple periods requested if ($dataTable instanceof Piwik_DataTable_Array) { // Need a new Piwik_DataTable_Array to store the 'human readable' values $newReport = new Piwik_DataTable_Array(); $newReport->setKeyName("prettyDate"); $dataTableMetadata = $dataTable->metadata; $newReport->metadata = $dataTableMetadata; // Need a new Piwik_DataTable_Array to store report metadata $rowsMetadata = new Piwik_DataTable_Array(); $rowsMetadata->setKeyName("prettyDate"); // Process each Piwik_DataTable_Simple entry foreach ($dataTable->getArray() as $label => $simpleDataTable) { list($enhancedSimpleDataTable, $rowMetadata) = $this->handleSimpleDataTable($idSite, $simpleDataTable, $columns, $hasDimension); $period = $dataTableMetadata[$label]['period']->getLocalizedLongString(); $newReport->addTable($enhancedSimpleDataTable, $period); $rowsMetadata->addTable($rowMetadata, $period); } } else { list($newReport, $rowsMetadata) = $this->handleSimpleDataTable($idSite, $dataTable, $columns, $hasDimension); } return array($newReport, $columns, $rowsMetadata); }
/** * Utility function used by getAll. Performs a binary filter of two * DataTables in order to correctly calculate evolution metrics. * * @param Piwik_DataTable|Piwik_DataTable_Array $currentData * @param Piwik_DataTable|Piwik_DataTable_Array $pastData * @param array $fields The array of string fields to calculate evolution * metrics for. */ private function calculateEvolutionPercentages($currentData, $pastData, $fields) { if ($currentData instanceof Piwik_DataTable_Array) { $pastArray = $pastData->getArray(); foreach ($currentData->getArray() as $label => $subTable) { $this->calculateEvolutionPercentages($subTable, current($pastArray), $fields); next($pastArray); } } else { foreach ($fields as $field) { $currentData->filter('Piwik_MultiSites_CalculateEvolutionFilter', array($pastData, $this->evolutionColumnNames[$field], $field, $quotientPrecision = 2)); } } }
/** * Utility function that adds a visit percent column to a data table, * regardless of whether the data table is an data table array or just * a data table. * * @param Piwik_DataTable $dataTable The data table to modify. */ private static function addVisitsPercentColumn($dataTable) { if ($dataTable instanceof Piwik_DataTable_Array) { foreach ($dataTable->getArray() as $table) { self::addVisitsPercentColumn($table); } } else { $totalVisits = array_sum($dataTable->getColumn(Piwik_Archive::INDEX_NB_VISITS)); $dataTable->queueFilter('ColumnCallbackAddColumnPercentage', array('nb_visits_percentage', 'nb_visits', $totalVisits)); } }
/** * Performs a binary filter of two * DataTables in order to correctly calculate evolution metrics. * * @param Piwik_DataTable|Piwik_DataTable_Array $currentData * @param Piwik_DataTable|Piwik_DataTable_Array $pastData * @param array $fields The array of string fields to calculate evolution * metrics for. */ private function calculateEvolutionPercentages($currentData, $pastData, $apiMetrics) { if ($currentData instanceof Piwik_DataTable_Array) { $pastArray = $pastData->getArray(); foreach ($currentData->getArray() as $subTable) { $this->calculateEvolutionPercentages($subTable, current($pastArray), $apiMetrics); next($pastArray); } } else { foreach ($apiMetrics as $metricSettings) { $currentData->filter('Piwik_MultiSites_CalculateEvolutionFilter', array($pastData, $metricSettings[self::METRIC_EVOLUTION_COL_NAME_KEY], $metricSettings[self::METRIC_RECORD_NAME_KEY], $quotientPrecision = 2)); } } }
/** * Sets the subtable IDs for the DataTable returned by getSocial. * * The IDs are int indexes into the array in /core/DataFiles/Socials.php. * * @param Piwik_DataTable $dataTable */ private function setSocialIdSubtables($dataTable) { if ($dataTable instanceof Piwik_DataTable_Array) { foreach ($dataTable->getArray() as $childTable) { $this->setSocialIdSubtables($childTable); } } else { foreach ($dataTable->getRows() as $row) { $socialName = $row->getColumn('label'); $i = 1; // start at one because idSubtable=0 is equivalent to idSubtable=false foreach ($GLOBALS['Piwik_socialUrl'] as $domain => $name) { if ($name == $socialName) { $row->c[Piwik_DataTable_Row::DATATABLE_ASSOCIATED] = $i; break; } ++$i; } } } }
/** * Sets the total evolution metadata for a datatable returned by $this->buildDataTable * given data for the last period. * * @param Piwik_DataTable $dataTable * @param Piwik_DataTable $pastData * @param array $apiMetrics Metrics info. */ private function setPastDataMetadata($dataTable, $pastData, $apiMetrics) { if ($dataTable instanceof Piwik_DataTable_Array) { $pastArray = $pastData->getArray(); foreach ($dataTable->getArray() as $subTable) { $this->setPastDataMetadata($subTable, current($pastArray), $apiMetrics); next($pastArray); } } else { // calculate total visits/actions/revenue for past data $this->setMetricsTotalsMetadata($pastData, $apiMetrics); foreach ($apiMetrics as $label => $metricInfo) { // get the names of metadata to set $totalMetadataName = self::getTotalMetadataName($label); $lastPeriodTotalMetadataName = self::getLastPeriodMetadataName($totalMetadataName); $totalEvolutionMetadataName = self::getTotalMetadataName($metricInfo[self::METRIC_EVOLUTION_COL_NAME_KEY]); // set last period total $pastTotal = $pastData->getMetadata($totalMetadataName); $dataTable->setMetadata($lastPeriodTotalMetadataName, $pastTotal); // calculate & set evolution $currentTotal = $dataTable->getMetadata($totalMetadataName); $evolution = Piwik_MultiSites_CalculateEvolutionFilter::calculate($currentTotal, $pastTotal); $dataTable->setMetadata($totalEvolutionMetadataName, $evolution); } } }