Esempio n. 1
0
 /**
  * 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;
 }
Esempio n. 2
0
 private function createInstanceWithDataTableArrays()
 {
     $dataTable = new Piwik_DataTable_Array();
     $subDataTableArray1 = $this->createInstanceWithDataTables();
     $subDataTableArray1->metadata['metadataKey1'] = 'metadataValue1';
     $dataTable->addTable($subDataTableArray1, 'subArray1');
     $subDataTableArray2 = $this->createInstanceWithDataTables();
     $dataTable->addTable($subDataTableArray2, 'subArray2');
     return $dataTable;
 }
Esempio n. 3
0
 /**
  * Computes the output of the given array of data tables
  *
  * @param Piwik_DataTable_Array  $tableArray  data tables to render
  * @param string                 $prefix      prefix to output before table data
  * @return string
  */
 protected function renderDataTableArray(Piwik_DataTable_Array $tableArray, $prefix)
 {
     $output = "Piwik_DataTable_Array<hr />";
     $prefix = $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
     foreach ($tableArray->getArray() as $descTable => $table) {
         $output .= $prefix . "<b>" . $descTable . "</b><br />";
         $output .= $prefix . $this->renderTable($table, $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
         $output .= "<hr />";
     }
     $output .= "Metadata<br />";
     foreach ($tableArray->metadata as $id => $metadata) {
         $output .= "<br />";
         $output .= $prefix . " <b>{$id}</b><br />";
         foreach ($metadata as $name => $value) {
             $output .= $prefix . $prefix . "{$name} => {$value}";
         }
     }
     $output .= "<hr />";
     return $output;
 }
Esempio n. 4
0
 /** Prepare metrics toggles with spark lines */
 protected function getMetricsToggles($controller)
 {
     // calculate meta-metrics
     $subDataTables = $this->dataTable->getArray();
     $firstDataTable = current($subDataTables);
     $firstDataTableRow = $firstDataTable->getFirstRow();
     $lastDataTable = end($subDataTables);
     $lastDataTableRow = $lastDataTable->getFirstRow();
     $maxValues = array();
     $minValues = array();
     foreach ($subDataTables as $subDataTable) {
         // $subDataTable is the report for one period, it has only one row
         $firstRow = $subDataTable->getFirstRow();
         foreach ($this->availableMetrics as $metric => $label) {
             $value = $firstRow ? floatval($firstRow->getColumn($metric)) : 0;
             if (!isset($minValues[$metric]) || $minValues[$metric] > $value) {
                 $minValues[$metric] = $value;
             }
             if (!isset($maxValues[$metric]) || $maxValues[$metric] < $value) {
                 $maxValues[$metric] = $value;
             }
         }
     }
     $chart = new Piwik_Visualization_Chart_Evolution();
     $colors = $chart->getSeriesColors();
     // put together metric info
     $i = 0;
     $metrics = array();
     foreach ($this->availableMetrics as $metric => $label) {
         if ($maxValues[$metric] == 0 && !$this instanceof Piwik_CoreHome_DataTableAction_MultiRowEvolution) {
             // series with only 0 cause trouble in js
             continue;
         }
         $first = $firstDataTableRow ? floatval($firstDataTableRow->getColumn($metric)) : 0;
         $last = $lastDataTableRow ? floatval($lastDataTableRow->getColumn($metric)) : 0;
         $changePercent = $first > 0 ? round($last / $first * 100 - 100) : 100;
         $changePercentHtml = $changePercent . '%';
         if ($changePercent > 0) {
             $changePercentHtml = '+' . $changePercentHtml;
             $changeClass = 'up';
             $changeImage = 'arrow_up';
         } else {
             $changeClass = $changePercent < 0 ? 'down' : 'nochange';
             $changeImage = $changePercent < 0 ? 'arrow_down' : false;
         }
         $changePercentHtml = '<span class="' . $changeClass . '">' . ($changeImage ? '<img src="plugins/MultiSites/images/' . $changeImage . '.png" /> ' : '') . $changePercentHtml . '</span>';
         $details = Piwik_Translate('RowEvolution_MetricDetailsText', array($minValues[$metric], $maxValues[$metric], $changePercentHtml));
         $color = $colors[$i % count($colors)];
         $metrics[] = array('label' => $label, 'color' => $color, 'details' => $details, 'sparkline' => $this->getSparkline($metric, $controller));
         $i++;
     }
     return $metrics;
 }
 /**
  * This method searches for a recursive label.
  * The label parts are used to descend recursively until a complete match is found. 
  * 
  * The method will return a table containing only the matching row 
  * or an empty data table. 
  */
 private function filterRecursive($labelParts, $dataTable)
 {
     if ($dataTable instanceof Piwik_DataTable_Array) {
         // search an array of tables, e.g. when using date=last30
         // note that if the root is an array, we filter all children
         // if an array occurs inside the nested table, we only look for the first match (see below)
         $newTableArray = new Piwik_DataTable_Array();
         $newTableArray->metadata = $dataTable->metadata;
         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 (first 10 characters)
             $dateForApiRequest = substr($date, 0, 10);
             $subTable = $this->doFilterRecursive($labelParts, $subTable, $dateForApiRequest);
             $newTableArray->addTable($subTable, $date);
         }
         return $newTableArray;
     }
     return $this->doFilterRecursive($labelParts, $dataTable);
 }
Esempio n. 6
0
 /** Get row evolution for a multiple labels */
 private function getMultiRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $column, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true)
 {
     $actualLabels = $logos = array();
     $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal);
     if (!isset($metadata['metrics'][$column])) {
         // invalid column => use the first one that's available
         $metrics = array_keys($metadata['metrics']);
         $column = reset($metrics);
     }
     // load the tables for each label
     $dataTablesPerLabel = array();
     $dataTableMetadata = false;
     foreach ($labels as $labelIndex => $label) {
         $dataTable = $this->loadRowEvolutionDataFromAPI($idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $idGoal);
         $dataTablesPerLabel[$labelIndex] = $dataTable->getArray();
         if (!$dataTableMetadata) {
             $dataTableMetadata = $dataTable->metadata;
         }
         $urlFound = false;
         foreach ($dataTablesPerLabel[$labelIndex] as $table) {
             if ($table->getRowsCount() > 0) {
                 $firstRow = $table->getFirstRow();
                 // in case labels were replaced in the data table (e.g. for browsers report),
                 // display the label from the table, not the one passed as filter
                 $columnLabel = $firstRow->getColumn('label');
                 if (!empty($columnLabel)) {
                     $actualLabels[$labelIndex] = $columnLabel;
                 }
                 list($actualLabel, $urlFound) = $this->cleanUrlForLabel($firstRow, $apiModule, $apiAction, $labelUseAbsoluteUrl);
                 if ($actualLabel) {
                     $actualLabels[$labelIndex] = $actualLabel;
                 }
                 // Forward the logo path to display logos in multi rows comparison
                 $logos[$labelIndex] = $firstRow->getMetadata('logo');
                 break;
             }
         }
         if (!$urlFound) {
             $actualLabels[$labelIndex] = str_replace(Piwik_API_DataTableManipulator_LabelFilter::SEPARATOR_RECURSIVE_LABEL, ' - ', $label);
         }
     }
     // combine the tables
     $dataTableMulti = new Piwik_DataTable_Array();
     $dataTableMulti->setKeyName($dataTable->getKeyName());
     $dataTableMulti->metadata = $dataTableMetadata;
     foreach (array_keys(reset($dataTablesPerLabel)) as $dateLabel) {
         $newRow = new Piwik_DataTable_Row();
         foreach ($dataTablesPerLabel as $labelIndex => $tableArray) {
             $table = $tableArray[$dateLabel];
             if ($table->getRowsCount() == 0) {
                 $value = 0;
             } else {
                 $value = $table->getFirstRow()->getColumn($column);
                 $value = floatVal(str_replace(',', '.', $value));
                 if ($value == '') {
                     $value = 0;
                 }
             }
             // keep metric in the label so that unit (%, s, ...) can be guessed correctly
             $label = $column . '_' . $labelIndex;
             $newRow->addColumn($label, $value);
         }
         $newTable = new Piwik_DataTable();
         $newTable->addRow($newRow);
         $dataTableMulti->addTable($newTable, $dateLabel);
     }
     // 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] = Piwik_DataTable_Filter_SafeDecodeLabel::safeDecodeLabel($label);
         if (!empty($logos[$labelIndex])) {
             $metadata['logos'][$metricName] = $logos[$labelIndex];
         }
     }
     $this->enhanceRowEvolutionMetaData($metadata, $dataTableMulti);
     return array('column' => $column, 'reportData' => $dataTableMulti, 'metadata' => $metadata);
 }
Esempio n. 7
0
 /**
  * Returns a newly created Piwik_DataTable_Array.
  *
  * @return Piwik_DataTable_Array
  */
 protected function getNewDataTableArray()
 {
     $table = new Piwik_DataTable_Array();
     $table->setKeyName($this->getIndexName());
     return $table;
 }
Esempio n. 8
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 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);
 }
Esempio n. 9
0
 /**
  * Computes the output of the given data table array
  *
  * @param Piwik_DataTable_Array  $table
  * @param array                  $allColumns
  * @return string
  */
 protected function renderDataTableArray($table, &$allColumns = array())
 {
     $str = '';
     foreach ($table->getArray() 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;
 }
Esempio n. 10
0
 /**
  * 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));
         }
     }
 }
Esempio n. 11
0
 /**
  * Returns a new DataTable_Array w/o any child DataTables, but with
  * the same key name as this instance.
  *
  * @return Piwik_DataTable_Array
  */
 public function getEmptyClone()
 {
     $newTableArray = new Piwik_DataTable_Array();
     $newTableArray->setKeyName($this->getKeyName());
     return $newTableArray;
 }
Esempio n. 12
0
 /**
  * Given a Piwik_DataTable_Array made of DataTable_Simple rows, returns a php array with the structure:
  * array(
  * 	array( label => X, value => Y),
  * 	array( label => A, value => B),
  * ...
  * )
  *
  * This is used for example for the evolution graph (last 30 days visits) or the sparklines.
  * 
  * @param Piwik_DataTable_Array $dataTableArray
  * @return array
  */
 protected function generateDataFromDataTableArray(Piwik_DataTable_Array $dataTableArray)
 {
     // we have to fill a $data array with each row = array('label' => X, 'value' => y)
     $data = array();
     foreach ($dataTableArray->getArray() as $keyName => $table) {
         $value = false;
         $onlyRow = $table->getFirstRow();
         if ($onlyRow !== false) {
             $value = $onlyRow->getColumn('value');
             if ($value == false) {
                 // TEMP
                 // quite a hack, useful in the case at this point we do have a normal row with nb_visits, nb_actions, nb_uniq_visitors, etc.
                 // instead of the dataTable_Simple row (label, value)
                 // to do it properly we'd need to
                 // - create a filter that removes columns
                 // - apply this filter to keep only the column called nb_uniq_visitors
                 // - rename this column as 'value'
                 // and at this point the getcolumn('value') would have worked
                 // this code is executed eg. when displaying a sparkline for the last 30 days displaying the number of unique visitors coming from search engines
                 //TODO solution: use a filter rename column etc.
                 // another solution would be to add a method to the Referers API giving directly the integer 'visits from search engines'
                 // and we would build automatically the dataTable_array of datatatble_simple from these integers
                 // but we'd have to add this integer to be recorded during archiving etc.
                 $value = $onlyRow->getColumn('nb_uniq_visitors');
             }
         }
         if ($value === false) {
             $value = 0;
         }
         $data[] = array('label' => $keyName, 'value' => $value);
     }
     return $data;
 }
Esempio n. 13
0
 /**
  * Computes the output for the given data table array
  *
  * @param Piwik_DataTable_Array  $table
  * @param array                  $array
  * @param string                 $prefixLines
  * @return string
  */
 protected function renderDataTableArray($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 Piwik_DataTable_Array) {
                 $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->getArray();
     $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 Piwik_DataTable_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 Piwik_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 Piwik_DataTable_Array) {
         $xml = '';
         $tables = $table->getArray();
         $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;
     }
 }
Esempio n. 14
0
 /**
  * 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));
         }
     }
 }
Esempio n. 15
0
 /**
  * Will search in the DataTable for a Label matching the searched string
  * and return only the matching row, or an empty datatable
  */
 protected function getFilterPageDatatableSearch($callBackParameters, $search, $actionType, $table = false, $searchTree = false)
 {
     if ($searchTree === false) {
         // build the query parts that are searched inside the tree
         if ($actionType == Piwik_Tracker_Action::TYPE_ACTION_NAME) {
             $searchedString = Piwik_Common::unsanitizeInputValue($search);
         } else {
             $idSite = $callBackParameters[1];
             try {
                 $searchedString = Piwik_Tracker_Action::excludeQueryParametersFromUrl($search, $idSite);
             } catch (Exception $e) {
                 $searchedString = $search;
             }
         }
         $searchTree = Piwik_Actions::getActionExplodedNames($searchedString, $actionType);
     }
     if ($table === false) {
         // fetch the data table
         $table = call_user_func_array(array('Piwik_Archive', 'getDataTableFromArchive'), $callBackParameters);
         if ($table instanceof Piwik_DataTable_Array) {
             // search an array of tables, e.g. when using date=last30
             // note that if the root is an array, we filter all children
             // if an array occurs inside the nested table, we only look for the first match (see below)
             $newTableArray = new Piwik_DataTable_Array();
             $newTableArray->metadata = $table->metadata;
             $newTableArray->setKeyName($table->getKeyName());
             foreach ($table->getArray() as $label => $subTable) {
                 $subTable = $this->doFilterPageDatatableSearch($callBackParameters, $subTable, $searchTree);
                 $newTableArray->addTable($subTable, $label);
             }
             return $newTableArray;
         }
     }
     return $this->doFilterPageDatatableSearch($callBackParameters, $table, $searchTree);
 }
Esempio n. 16
0
 /**
  * Merges the rows of every child DataTable into a new DataTable and
  * returns it. This function will also set the label of the merged rows
  * to the label of the DataTable they were originally from.
  * 
  * The result of this function is determined by the type of DataTable
  * this instance holds. If this DataTable_Array instance holds an array
  * of DataTables, this function will transform it from:
  * <code>
  * Label 0:
  *   DataTable(row1)
  * Label 1:
  *   DataTable(row2)
  * </code>
  * to:
  * <code>
  * DataTable(row1[label = 'Label 0'], row2[label = 'Label 1'])
  * </code>
  * 
  * If this instance holds an array of DataTable_Arrays, this function will
  * transform it from:
  * <code>
  * Outer Label 0:			// the outer DataTable_Array
  *   Inner Label 0:			// one of the inner DataTable_Arrays
  *     DataTable(row1)
  *   Inner Label 1:
  *     DataTable(row2)
  * Outer Label 1:
  *   Inner Label 0:
  *     DataTable(row3)
  *   Inner Label 1:
  *     DataTable(row4)
  * </code>
  * to:
  * <code>
  * Inner Label 0:
  *   DataTable(row1[label = 'Outer Label 0'], row3[label = 'Outer Label 1'])
  * Inner Label 1:
  *   DataTable(row2[label = 'Outer Label 0'], row4[label = 'Outer Label 1'])
  * </code>
  * 
  * In addition, if this instance holds an array of DataTable_Arrays, the
  * metadata of the first child is used as the metadata of the result.
  * 
  * This function can be used, for example, to smoosh IndexedBySite archive
  * query results into one DataTable w/ different rows differentiated by site ID.
  * 
  * @return Piwik_DataTable|Piwik_DataTable_Array
  */
 public function mergeChildren()
 {
     $firstChild = reset($this->array);
     if ($firstChild instanceof Piwik_DataTable_Array) {
         $result = new Piwik_DataTable_Array();
         $result->setKeyName($firstChild->getKeyName());
         $result->metadata = $firstChild->metadata;
         foreach ($this->array as $label => $subTableArray) {
             foreach ($subTableArray->array as $innerLabel => $subTable) {
                 if (!isset($result->array[$innerLabel])) {
                     $result->addTable(new Piwik_DataTable(), $innerLabel);
                 }
                 $this->copyRowsAndSetLabel($result->array[$innerLabel], $subTable, $label);
             }
         }
     } else {
         $result = new Piwik_DataTable();
         foreach ($this->array as $label => $subTable) {
             $this->copyRowsAndSetLabel($result, $subTable, $label);
         }
     }
     return $result;
 }
Esempio n. 17
0
 /**
  * Returns a newly created Piwik_DataTable_Array.
  * The future elements of this array should be indexed by their dates (we set the index name to 'date').
  *
  * @return Piwik_DataTable_Array
  */
 protected function getNewDataTableArray()
 {
     $table = new Piwik_DataTable_Array();
     $table->setNameKey('date');
     return $table;
 }
Esempio n. 18
0
 protected function _getDataTableArray_containsDataTableArray_simpleOneRow()
 {
     $table = new Piwik_DataTable_Array();
     $table->setKeyName('parentArrayKey');
     $table->addTable($this->_getDataTableSimpleOneRowArrayTest(), 'idSite');
     return $table;
 }
Esempio n. 19
0
 /**
  * Returns a new DataTable_Array w/ child tables that have had their
  * subtables merged.
  * 
  * @see Piwik_DataTable::mergeSubtables
  * 
  * @return Piwik_DataTable_Array
  */
 public function mergeSubtables()
 {
     $result = new Piwik_DataTable_Array();
     foreach ($this->array as $label => $childTable) {
         $result->addTable($childTable->mergeSubtables(), $label);
     }
     return $result;
 }
Esempio n. 20
0
 /** Get row evolution for a multiple labels */
 private function getMultiRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $column, $language = false)
 {
     $actualLabels = array();
     $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $segment, $language);
     if (!isset($metadata['metrics'][$column])) {
         // invalid column => use the first one that's available
         $column = reset(array_keys($metadata['metrics']));
     }
     // load the tables for each label
     $dataTablesPerLabel = array();
     $dataTableMetadata = false;
     foreach ($labels as $labelIndex => $label) {
         $dataTable = $this->loadRowEvolutionData($idSite, $period, $date, $apiModule, $apiAction, $label, $segment);
         $dataTablesPerLabel[$labelIndex] = $dataTable->getArray();
         if (!$dataTableMetadata) {
             $dataTableMetadata = $dataTable->metadata;
         }
         $urlFound = false;
         foreach ($dataTablesPerLabel[$labelIndex] as $table) {
             if ($table->getRowsCount() > 0) {
                 $firstRow = $table->getFirstRow();
                 // in case labels were replaced in the data table (e.g. for browsers report),
                 // display the label from the table, not the one passed as filter
                 $columnLabel = $firstRow->getColumn('label');
                 if (!empty($columnLabel)) {
                     $actualLabels[$labelIndex] = $columnLabel;
                     // TODO: confirm we need this
                     // special case: websites report
                     //if ($apiAction == 'getWebsites')
                     //{
                     //	$actualLabels[$labelIndex] = html_entity_decode($actualLabels[$labelIndex]);
                     //}
                 }
                 // if url is available as metadata, use it (only for actions reports)
                 if ($url = $firstRow->getMetadata('url')) {
                     $actualLabels[$labelIndex] = $url;
                     $urlFound = true;
                 }
                 break;
             }
         }
         if (!$urlFound) {
             // if we have a recursive label and no url, use the path
             $actualLabels[$labelIndex] = str_replace(Piwik_API_DataTableLabelFilter::SEPARATOR_RECURSIVE_LABEL, ' - ', $label);
         }
     }
     // combine the tables
     $dataTable = new Piwik_DataTable_Array();
     $dataTable->setKeyName($dataTable->getKeyName());
     $dataTable->metadata = $dataTableMetadata;
     foreach (array_keys(reset($dataTablesPerLabel)) as $dateLabel) {
         $newRow = new Piwik_DataTable_Row();
         foreach ($dataTablesPerLabel as $labelIndex => $tableArray) {
             $table = $tableArray[$dateLabel];
             if ($table->getRowsCount() == 0) {
                 $value = 0;
             } else {
                 $value = $table->getFirstRow()->getColumn($column);
                 $value = floatVal(str_replace(',', '.', $value));
                 if ($value == '') {
                     $value = 0;
                 }
             }
             // keep metric in the label so that unit (%, s, ...) can be guessed correctly
             $label = $column . '_' . $labelIndex;
             $newRow->addColumn($label, $value);
         }
         $newTable = new Piwik_DataTable();
         $newTable->addRow($newRow);
         $dataTable->addTable($newTable, $dateLabel);
     }
     // the available metrics for the report are returned as metadata / availableColumns
     $metadata['availableColumns'] = $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) {
         $label .= ' (' . $metadata['availableColumns'][$column] . ')';
         $metadata['metrics'][$column . '_' . $labelIndex] = $label;
     }
     $this->enhanceRowEvolutionMetaData($metadata, $dataTable);
     return array('column' => $column, 'data' => $dataTable, 'metadata' => $metadata);
 }
Esempio n. 21
0
 /**
  * Load the data tables from the API and combine them into a data table
  * that can be plotted
  */
 protected function loadDataTable()
 {
     $metadata = false;
     $dataTableArrays = array();
     // load the tables for each label
     foreach ($this->labels as $rowLabelIndex => $rowLabel) {
         // TODO this used to be: $_GET['label'] = $this->label = $rowLabel;
         // is the $_GET assignment obsolete after label filter refactorings?
         $this->label = $rowLabel;
         $table = $this->doLoadDataTable();
         $dataTableArrays[$rowLabelIndex] = $table->getArray();
         if (!$metadata) {
             $metadata = $table->metadata;
         }
         $urlFound = false;
         foreach ($dataTableArrays[$rowLabelIndex] as $table) {
             if ($table->getRowsCount() > 0) {
                 $firstRow = $table->getFirstRow();
                 // in case labels were replaced in the data table (e.g. for browsers report),
                 // display the label from the table, not the one passed as filter
                 $label = $firstRow->getColumn('label');
                 if (!empty($label)) {
                     $this->labels[$rowLabelIndex] = $label;
                     // special case: websites report
                     if ($this->apiMethod == 'Referers.getWebsites') {
                         $this->labels[$rowLabelIndex] = html_entity_decode($this->labels[$rowLabelIndex]);
                         $urlFound = true;
                     }
                 }
                 // if url is available as metadata, use it (only for actions reports)
                 if (substr($this->apiMethod, 0, 7) == 'Actions' && ($url = $firstRow->getMetadata('url'))) {
                     $this->labels[$rowLabelIndex] = $url;
                     $urlFound = true;
                 }
                 break;
             }
         }
         if (!$urlFound && strpos($rowLabel, Piwik_API_DataTableLabelFilter::RECURSIVE_LABEL_SEPARATOR) !== false) {
             // if we have a recursive label and no url, use the path
             $this->labels[$rowLabelIndex] = str_replace(Piwik_API_DataTableLabelFilter::RECURSIVE_LABEL_SEPARATOR, ' - ', $rowLabel);
         }
     }
     // combine the tables
     $dataTable = new Piwik_DataTable_Array();
     $dataTable->metadata = $metadata;
     foreach (array_keys(reset($dataTableArrays)) as $dateLabel) {
         $newRow = new Piwik_DataTable_Row();
         foreach ($dataTableArrays as $rowLabelIndex => $tableArray) {
             $table = $tableArray[$dateLabel];
             if ($table->getRowsCount() == 0) {
                 $value = 0;
             } else {
                 $value = $table->getFirstRow()->getColumn($this->metric);
                 $value = floatVal(str_replace(',', '.', $value));
                 if ($value == '') {
                     $value = 0;
                 }
             }
             // keep metric in the label so that unit (%, s, ...) can be guessed correctly
             $label = $this->metric . '_' . $rowLabelIndex;
             $newRow->addColumn($label, $value);
         }
         $newTable = new Piwik_DataTable();
         $newTable->addRow($newRow);
         $dataTable->addTable($newTable, $dateLabel);
     }
     // available metrics for metrics picker
     $this->metricsForSelect = $this->availableMetrics;
     $this->availableMetrics = array();
     foreach ($this->labels as $rowLabelIndex => $label) {
         // add metric name
         $label .= ' (' . $this->metricsForSelect[$this->metric] . ')';
         $this->availableMetrics[$this->metric . '_' . $rowLabelIndex] = $label;
     }
     return $dataTable;
 }