예제 #1
0
 /**
  * Merge the columns of two data tables.
  * Manipulates the first table.
  *
  * @param DataTable|DataTable\Map $table1 The table to eventually filter.
  * @param DataTable|DataTable\Map $table2 Whether to delete rows with no visits or not.
  */
 public function mergeDataTables($table1, $table2)
 {
     // handle table arrays
     if ($table1 instanceof DataTable\Map && $table2 instanceof DataTable\Map) {
         $subTables2 = $table2->getDataTables();
         foreach ($table1->getDataTables() as $index => $subTable1) {
             if (!array_key_exists($index, $subTables2)) {
                 // occurs when archiving starts on dayN and continues into dayN+1, see https://github.com/piwik/piwik/issues/5168#issuecomment-50959925
                 continue;
             }
             $subTable2 = $subTables2[$index];
             $this->mergeDataTables($subTable1, $subTable2);
         }
         return;
     }
     $firstRow2 = $table2->getFirstRow();
     if (!$firstRow2 instanceof Row) {
         return;
     }
     $firstRow1 = $table1->getFirstRow();
     if (empty($firstRow1)) {
         $firstRow1 = $table1->addRow(new Row());
     }
     foreach ($firstRow2->getColumns() as $metric => $value) {
         $firstRow1->setColumn($metric, $value);
     }
 }
 /**
  * Manipulates child DataTables of a DataTable\Map. See @manipulate for more info.
  *
  * @param DataTable\Map $dataTable
  * @return DataTable\Map
  */
 protected function manipulateDataTableMap($dataTable)
 {
     $result = $dataTable->getEmptyClone();
     foreach ($dataTable->getDataTables() as $tableLabel => $childTable) {
         $newTable = $this->manipulate($childTable);
         $result->addTable($newTable, $tableLabel);
     }
     return $result;
 }
예제 #3
0
 /**
  * Computes the output of the given array of data tables
  *
  * @param DataTable\Map $map data tables to render
  * @param string $prefix prefix to output before table data
  * @return string
  */
 protected function renderDataTableMap(DataTable\Map $map, $prefix)
 {
     $output = "Set<hr />";
     $prefix = $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
     foreach ($map->getDataTables() as $descTable => $table) {
         $output .= $prefix . "<b>" . $descTable . "</b><br />";
         $output .= $prefix . $this->renderTable($table, $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
         $output .= "<hr />";
     }
     return $output;
 }
예제 #4
0
 private function getSeriesData($rowLabel, $columnName, DataTable\Map $dataTable)
 {
     $seriesData = array();
     foreach ($dataTable->getDataTables() as $childTable) {
         // get the row for this label (use the first if $rowLabel is false)
         if ($rowLabel === false) {
             $row = $childTable->getFirstRow();
         } else {
             $row = $childTable->getRowFromLabel($rowLabel);
         }
         // get series data point. defaults to 0 if no row or no column value.
         if ($row === false) {
             $seriesData[] = 0;
         } else {
             $seriesData[] = $row->getColumn($columnName) ?: 0;
         }
     }
     return $seriesData;
 }
예제 #5
0
파일: Sparkline.php 프로젝트: piwik/piwik
 /**
  * @param DataTable\Map $dataTableMap
  * @param string $columnToPlot
  *
  * @return array
  * @throws \Exception
  */
 protected function getValuesFromDataTableMap($dataTableMap, $columnToPlot)
 {
     $dataTableMap->applyQueuedFilters();
     $values = array();
     foreach ($dataTableMap->getDataTables() as $table) {
         if ($table->getRowsCount() > 1) {
             throw new Exception("Expecting only one row per DataTable");
         }
         $value = 0;
         $onlyRow = $table->getFirstRow();
         if (false !== $onlyRow) {
             if (!empty($columnToPlot)) {
                 $value = $onlyRow->getColumn($columnToPlot);
             } else {
                 $columns = $onlyRow->getColumns();
                 $value = current($columns);
             }
         }
         $values[] = $value;
     }
     return $values;
 }
예제 #6
0
 /** Get row evolution for a multiple labels */
 private function getMultiRowEvolution(DataTable\Map $dataTable, $metadata, $apiModule, $apiAction, $labels, $column, $legendAppendMetric = true, $labelUseAbsoluteUrl = true)
 {
     if (!isset($metadata['metrics'][$column])) {
         // invalid column => use the first one that's available
         $metrics = array_keys($metadata['metrics']);
         $column = reset($metrics);
     }
     // get the processed label and logo (if any) for every requested label
     $actualLabels = $logos = array();
     foreach ($labels as $labelIdx => $label) {
         foreach ($dataTable->getDataTables() as $table) {
             $labelRow = $this->getRowEvolutionRowFromLabelIdx($table, $labelIdx);
             if ($labelRow) {
                 $actualLabels[$labelIdx] = $this->getRowUrlForEvolutionLabel($labelRow, $apiModule, $apiAction, $labelUseAbsoluteUrl);
                 $logos[$labelIdx] = $labelRow->getMetadata('logo');
                 if (!empty($actualLabels[$labelIdx])) {
                     break;
                 }
             }
         }
         if (empty($actualLabels[$labelIdx])) {
             $actualLabels[$labelIdx] = $this->cleanOriginalLabel($label);
         }
     }
     // convert rows to be array($column.'_'.$labelIdx => $value) as opposed to
     // array('label' => $label, 'column' => $value).
     $dataTableMulti = $dataTable->getEmptyClone();
     foreach ($dataTable->getDataTables() as $tableLabel => $table) {
         $newRow = new Row();
         foreach ($labels as $labelIdx => $label) {
             $row = $this->getRowEvolutionRowFromLabelIdx($table, $labelIdx);
             $value = 0;
             if ($row) {
                 $value = $row->getColumn($column);
                 $value = floatVal(str_replace(',', '.', $value));
             }
             if ($value == '') {
                 $value = 0;
             }
             $newLabel = $column . '_' . (int) $labelIdx;
             $newRow->addColumn($newLabel, $value);
         }
         $newTable = $table->getEmptyClone();
         if (!empty($labels)) {
             // only add a row if the row has data (no labels === no data)
             $newTable->addRow($newRow);
         }
         $dataTableMulti->addTable($newTable, $tableLabel);
     }
     // the available metrics for the report are returned as metadata / columns
     $metadata['columns'] = $metadata['metrics'];
     // metadata / metrics should document the rows that are compared
     // this way, UI code can be reused
     $metadata['metrics'] = array();
     foreach ($actualLabels as $labelIndex => $label) {
         if ($legendAppendMetric) {
             $label .= ' (' . $metadata['columns'][$column] . ')';
         }
         $metricName = $column . '_' . $labelIndex;
         $metadata['metrics'][$metricName] = SafeDecodeLabel::decodeLabelSafe($label);
         if (!empty($logos[$labelIndex])) {
             $metadata['logos'][$metricName] = $logos[$labelIndex];
         }
     }
     $this->enhanceRowEvolutionMetaData($metadata, $dataTableMulti);
     return array('column' => $column, 'reportData' => $dataTableMulti, 'metadata' => $metadata);
 }
예제 #7
0
 /**
  * Aggregates the DataTable\Map into the destination $aggregated
  * @param $map
  * @param $aggregated
  */
 protected function aggregatedDataTableMapsAsOne(Map $map, DataTable $aggregated)
 {
     foreach ($map->getDataTables() as $tableToAggregate) {
         if ($tableToAggregate instanceof Map) {
             $this->aggregatedDataTableMapsAsOne($tableToAggregate, $aggregated);
         } else {
             $aggregated->addDataTable($tableToAggregate, $this->isAggregateSubTables());
         }
     }
 }
예제 #8
0
 /**
  * Computes the output of the given data table array
  *
  * @param DataTable\Map $table
  * @param array $allColumns
  * @return string
  */
 protected function renderDataTableMap($table, &$allColumns = array())
 {
     $str = '';
     foreach ($table->getDataTables() as $currentLinePrefix => $dataTable) {
         $returned = explode("\n", $this->renderTable($dataTable, $allColumns));
         // get rid of the columns names
         $returned = array_slice($returned, 1);
         // case empty datatable we dont print anything in the CSV export
         // when in xml we would output <result date="2008-01-15" />
         if (!empty($returned)) {
             foreach ($returned as &$row) {
                 $row = $currentLinePrefix . $this->separator . $row;
             }
             $str .= "\n" . implode("\n", $returned);
         }
     }
     // prepend table key to column list
     $allColumns = array_merge(array($table->getKeyName() => true), $allColumns);
     // add header to output string
     $str = $this->getHeaderLine(array_keys($allColumns)) . $str;
     return $str;
 }
예제 #9
0
 /**
  * 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 Simple|Set : $rowsMetadata
  * - translate metric names to a separate array : $columns
  *
  * @param int $idSite enables monetary value formatting based on site currency
  * @param \Piwik\DataTable\Map|\Piwik\DataTable\Simple $dataTable
  * @param array $reportMetadata
  * @param bool $showRawMetrics
  * @param bool|null $formatMetrics
  * @return array Simple|Set $newReport with human readable format & array $columns list of translated column names & Simple|Set $rowsMetadata
  */
 private function handleTableReport($idSite, $dataTable, &$reportMetadata, $showRawMetrics = false, $formatMetrics = null)
 {
     $hasDimension = isset($reportMetadata['dimension']);
     $columns = @$reportMetadata['metrics'] ?: array();
     if ($hasDimension) {
         $columns = array_merge(array('label' => $reportMetadata['dimension']), $columns);
     }
     if (isset($reportMetadata['processedMetrics']) && is_array($reportMetadata['processedMetrics'])) {
         $processedMetricsAdded = Metrics::getDefaultProcessedMetrics();
         foreach ($reportMetadata['processedMetrics'] as $processedMetricId => $processedMetricTranslation) {
             // this processed metric can be displayed for this report
             if ($processedMetricTranslation && $processedMetricId !== $processedMetricTranslation) {
                 $columns[$processedMetricId] = $processedMetricTranslation;
             } elseif (isset($processedMetricsAdded[$processedMetricId])) {
                 // for instance in case 'nb_visits' => 'nb_visits' we will translate it
                 $columns[$processedMetricId] = $processedMetricsAdded[$processedMetricId];
             }
         }
     }
     // 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];
             }
         }
     }
     $columns = $this->hideShowMetrics($columns);
     $totals = array();
     // $dataTable is an instance of Set when multiple periods requested
     if ($dataTable instanceof DataTable\Map) {
         // Need a new Set to store the 'human readable' values
         $newReport = new DataTable\Map();
         $newReport->setKeyName("prettyDate");
         // Need a new Set to store report metadata
         $rowsMetadata = new DataTable\Map();
         $rowsMetadata->setKeyName("prettyDate");
         // Process each Simple entry
         foreach ($dataTable->getDataTables() as $simpleDataTable) {
             $this->removeEmptyColumns($columns, $reportMetadata, $simpleDataTable);
             list($enhancedSimpleDataTable, $rowMetadata) = $this->handleSimpleDataTable($idSite, $simpleDataTable, $columns, $hasDimension, $showRawMetrics, $formatMetrics);
             $enhancedSimpleDataTable->setAllTableMetadata($simpleDataTable->getAllTableMetadata());
             $period = $simpleDataTable->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX)->getLocalizedLongString();
             $newReport->addTable($enhancedSimpleDataTable, $period);
             $rowsMetadata->addTable($rowMetadata, $period);
             $totals = $this->aggregateReportTotalValues($simpleDataTable, $totals);
         }
     } else {
         $this->removeEmptyColumns($columns, $reportMetadata, $dataTable);
         list($newReport, $rowsMetadata) = $this->handleSimpleDataTable($idSite, $dataTable, $columns, $hasDimension, $showRawMetrics, $formatMetrics);
         $totals = $this->aggregateReportTotalValues($dataTable, $totals);
     }
     return array($newReport, $columns, $rowsMetadata, $totals);
 }
예제 #10
0
 /**
  * Sets the total evolution metadata for a datatable returned by $this->buildDataTable
  * given data for the last period.
  *
  * @param DataTable|DataTable\Map $dataTable
  * @param DataTable|DataTable\Map $pastData
  * @param array $apiMetrics Metrics info.
  */
 private function setPastDataMetadata($dataTable, $pastData, $apiMetrics)
 {
     if ($dataTable instanceof DataTable\Map) {
         $pastArray = $pastData->getDataTables();
         foreach ($dataTable->getDataTables() 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 = CalculateEvolutionFilter::calculate($currentTotal, $pastTotal);
             $dataTable->setMetadata($totalEvolutionMetadataName, $evolution);
         }
     }
 }
예제 #11
0
파일: Xml.php 프로젝트: brienomatty/elmsln
 /**
  * Computes the output for the given data table array
  *
  * @param Map $table
  * @param array $array
  * @param string $prefixLines
  * @return string
  */
 protected function renderDataTableMap($table, $array, $prefixLines = "")
 {
     // CASE 1
     //array
     //  'day1' => string '14' (length=2)
     //  'day2' => string '6' (length=1)
     $firstTable = current($array);
     if (!is_array($firstTable)) {
         $xml = '';
         $nameDescriptionAttribute = $table->getKeyName();
         foreach ($array as $valueAttribute => $value) {
             if (empty($value)) {
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\" />\n";
             } elseif ($value instanceof Map) {
                 $out = $this->renderTable($value, true);
                 //TODO somehow this code is not tested, cover this case
                 $xml .= "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\">\n{$out}</result>\n";
             } else {
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\">" . self::formatValueXml($value) . "</result>\n";
             }
         }
         return $xml;
     }
     $subTables = $table->getDataTables();
     $firstTable = current($subTables);
     // CASE 2
     //array
     //  'day1' =>
     //    array
     //      'nb_uniq_visitors' => string '18'
     //      'nb_visits' => string '101'
     //  'day2' =>
     //    array
     //      'nb_uniq_visitors' => string '28'
     //      'nb_visits' => string '11'
     if ($firstTable instanceof Simple) {
         $xml = '';
         $nameDescriptionAttribute = $table->getKeyName();
         foreach ($array as $valueAttribute => $dataTableSimple) {
             if (count($dataTableSimple) == 0) {
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\" />\n";
             } else {
                 if (is_array($dataTableSimple)) {
                     $dataTableSimple = "\n" . $this->renderDataTableSimple($dataTableSimple, $prefixLines . "\t") . $prefixLines . "\t";
                 }
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\">" . $dataTableSimple . "</result>\n";
             }
         }
         return $xml;
     }
     // CASE 3
     //array
     //  'day1' =>
     //    array
     //      0 =>
     //        array
     //          'label' => string 'phpmyvisites'
     //          'nb_uniq_visitors' => int 11
     //          'nb_visits' => int 13
     //      1 =>
     //        array
     //          'label' => string 'phpmyvisits'
     //          'nb_uniq_visitors' => int 2
     //          'nb_visits' => int 2
     //  'day2' =>
     //    array
     //      0 =>
     //        array
     //          'label' => string 'piwik'
     //          'nb_uniq_visitors' => int 121
     //          'nb_visits' => int 130
     //      1 =>
     //        array
     //          'label' => string 'piwik bis'
     //          'nb_uniq_visitors' => int 20
     //          'nb_visits' => int 120
     if ($firstTable instanceof DataTable) {
         $xml = '';
         $nameDescriptionAttribute = $table->getKeyName();
         foreach ($array as $keyName => $arrayForSingleDate) {
             $dataTableOut = $this->renderDataTable($arrayForSingleDate, $prefixLines . "\t");
             if (empty($dataTableOut)) {
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$keyName}\" />\n";
             } else {
                 $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$keyName}\">\n";
                 $xml .= $dataTableOut;
                 $xml .= $prefixLines . "\t</result>\n";
             }
         }
         return $xml;
     }
     if ($firstTable instanceof Map) {
         $xml = '';
         $tables = $table->getDataTables();
         $nameDescriptionAttribute = $table->getKeyName();
         foreach ($tables as $valueAttribute => $tableInArray) {
             $out = $this->renderTable($tableInArray, true, $prefixLines . "\t");
             $xml .= $prefixLines . "\t<result {$nameDescriptionAttribute}=\"{$valueAttribute}\">\n" . $out . $prefixLines . "\t</result>\n";
         }
         return $xml;
     }
     return '';
 }