| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugins\API; |
|
|
| use Exception; |
| use Piwik\API\DataTableManipulator\LabelFilter; |
| use Piwik\API\DataTablePostProcessor; |
| use Piwik\API\Request; |
| use Piwik\Cache; |
| use Piwik\Common; |
| use Piwik\DataTable; |
| use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal; |
| use Piwik\DataTable\Filter\CalculateEvolutionFilter; |
| use Piwik\DataTable\Filter\SafeDecodeLabel; |
| use Piwik\DataTable\Row; |
| use Piwik\Period; |
| use Piwik\Piwik; |
| use Piwik\Plugins\API\Filter\DataComparisonFilter; |
| use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\ConversionRate; |
| use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Conversions; |
| use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Revenue; |
| use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\RevenuePerVisit; |
| use Piwik\Site; |
|
|
| |
| |
| |
| |
| |
| class RowEvolution |
| { |
| |
| |
| |
| private static $actionsUrlReports = [ |
| 'getPageUrls', |
| 'getPageUrlsFollowingSiteSearch', |
| 'getEntryPageUrls', |
| 'getExitPageUrls', |
| 'getPageUrl', |
| ]; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $apiParameters = [], $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $labelSeries = '', $showGoalMetricsForGoal = false) |
| { |
| $idSite = (int)$idSite; |
|
|
| |
| if ($period == 'range') { |
| |
| $period = 'day'; |
| } |
|
|
| if (!Period::isMultiplePeriod($date, $period)) { |
| throw new Exception("Row evolutions can not be processed with this combination of \'date\' and \'period\' parameters."); |
| } |
|
|
| $label = DataTablePostProcessor::unsanitizeLabelParameter($label); |
| $labels = Piwik::getArrayFromApiParameter($label, $onlyUnique = empty($labelSeries)); |
|
|
| $labels = array_slice($labels, 0, 100); |
|
|
| $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $apiParameters); |
|
|
| |
| if ($showGoalMetricsForGoal !== false) { |
| if (array_key_exists('nb_visits', $metadata['metrics'])) { |
| $metadata['metrics'] = [ |
| 'nb_visits' => $metadata['metrics']['nb_visits'], |
| ]; |
| } else { |
| |
| $metadata['metrics'] = array_slice($metadata['metrics'], 0, 1); |
| } |
|
|
| |
| if ($showGoalMetricsForGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { |
| $metadata['metrics']['goal_ecommerceOrder_nb_conversions'] = Piwik::translate('General_EcommerceOrders'); |
| $metadata['metrics']['goal_ecommerceOrder_revenue'] = Piwik::translate('General_TotalRevenue'); |
| $metadata['metrics']['goal_ecommerceOrder_conversion_rate'] = Piwik::translate('Goals_ConversionRate', Piwik::translate('General_EcommerceOrders')); |
| $metadata['metrics']['goal_ecommerceOrder_avg_order_revenue'] = Piwik::translate('General_AverageOrderValue'); |
| $metadata['metrics']['goal_ecommerceOrder_items'] = Piwik::translate('General_PurchasedProducts'); |
| $metadata['metrics']['goal_ecommerceOrder_revenue_per_visit'] = Piwik::translate('General_ColumnValuePerVisit'); |
| } else { |
| $goalsToProcess = $this->getGoalsToProcess($showGoalMetricsForGoal, $idSite); |
|
|
| foreach ($goalsToProcess as $idGoal) { |
| if ($idGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { |
| $metadata['metrics']['goal_ecommerceOrder_conversion_rate'] = Piwik::translate('Goals_ConversionRate', Piwik::translate('General_EcommerceOrders')); |
|
|
| if ((int) $showGoalMetricsForGoal === AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) { |
| |
| continue; |
| } |
|
|
| $metadata['metrics']['goal_ecommerceOrder_nb_conversions'] = Piwik::translate('Goals_Conversions', Piwik::translate('General_EcommerceOrders')); |
| $metadata['metrics']['goal_ecommerceOrder_revenue'] = Piwik::translate('General_EcommerceOrders') . ' ' . Piwik::translate('General_ColumnRevenue'); |
| $metadata['metrics']['goal_ecommerceOrder_revenue_per_visit'] = Piwik::translate('General_EcommerceOrders') . ' ' . Piwik::translate('General_ColumnValuePerVisit'); |
| continue; |
| } |
|
|
| $conversionRateMetric = new ConversionRate($idSite, $idGoal); |
| $metadata['metrics'][$conversionRateMetric->getName()] = $conversionRateMetric->getTranslatedName(); |
|
|
| if ((int) $showGoalMetricsForGoal === AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) { |
| |
| continue; |
| } |
|
|
| $conversionsMetric = new Conversions($idSite, $idGoal); |
| $revenueMetric = new Revenue($idSite, $idGoal); |
| $revenuePerVisitMetric = new RevenuePerVisit($idSite, $idGoal); |
|
|
| $metadata['metrics'][$conversionsMetric->getName()] = $conversionsMetric->getTranslatedName(); |
| $metadata['metrics'][$revenueMetric->getName()] = $revenueMetric->getTranslatedName(); |
| $metadata['metrics'][$revenuePerVisitMetric->getName()] = $revenuePerVisitMetric->getTranslatedName(); |
| } |
|
|
| $metadata['metrics']['revenue_per_visit'] = Piwik::translate('General_ColumnValuePerVisit'); |
| } |
| } |
|
|
| $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $apiParameters, $showGoalMetricsForGoal); |
|
|
| if (empty($dataTable->getDataTables())) { |
| return []; |
| } |
|
|
| if (empty($labels)) { |
| $labels = $this->getLabelsFromDataTable($dataTable, $labels); |
| $dataTable = $this->enrichRowAddMetadataLabelIndex($labels, $dataTable); |
| } |
| if (count($labels) != 1) { |
| $data = $this->getMultiRowEvolution( |
| $dataTable, |
| $metadata, |
| $apiModule, |
| $apiAction, |
| $labels, |
| $column, |
| $legendAppendMetric, |
| $labelUseAbsoluteUrl, |
| $labelSeries |
| ); |
| } else { |
| $data = $this->getSingleRowEvolution( |
| $idSite, |
| $dataTable, |
| $metadata, |
| $apiModule, |
| $apiAction, |
| $labels[0], |
| $labelUseAbsoluteUrl |
| ); |
| } |
| return $data; |
| } |
|
|
| |
| |
| |
| |
| |
| protected function getGoalsToProcess($goalId, $idSite): array |
| { |
| switch ($goalId) { |
| case AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE: |
| case AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW: |
| return $this->getAllGoalIds($idSite); |
| case Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER: |
| default: |
| return [$goalId]; |
| } |
| } |
|
|
| |
| |
| |
| |
| protected function getAllGoalIds($idSite): array |
| { |
| $idSite = (int)$idSite; |
| $cache = Cache::getTransientCache(); |
| $key = 'RowEvolution_allGoalIds_' . $idSite; |
|
|
| if ($cache->contains($key)) { |
| $cachedGoalIds = $cache->fetch($key); |
| if (is_array($cachedGoalIds)) { |
| return $cachedGoalIds; |
| } |
| } |
|
|
| $goalIds = []; |
|
|
| if (Site::isEcommerceEnabledFor($idSite)) { |
| $goalIds[] = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER; |
| } |
|
|
| $siteGoals = Request::processRequest('Goals.getGoals', ['idSite' => $idSite, 'filter_limit' => '-1'], $default = []); |
|
|
| if (is_iterable($siteGoals)) { |
| foreach ($siteGoals as $goal) { |
| if (is_array($goal) && isset($goal['idgoal'])) { |
| $goalIds[] = $goal['idgoal']; |
| } |
| } |
| } |
|
|
| $cache->save($key, $goalIds); |
|
|
| return $goalIds; |
| } |
|
|
| |
| |
| |
| |
| |
| protected function enrichRowAddMetadataLabelIndex($labels, $dataTable) |
| { |
| |
| $labelsToIndex = array_flip($labels); |
| |
| $subDataTables = $dataTable->getDataTables(); |
| foreach ($subDataTables as $table) { |
| foreach ($table->getRows() as $row) { |
| $label = $row->getColumn('label'); |
| if (isset($labelsToIndex[$label])) { |
| $row->setMetadata(LabelFilter::FLAG_IS_ROW_EVOLUTION, $labelsToIndex[$label]); |
| } |
| } |
| } |
| return $dataTable; |
| } |
|
|
| |
| |
| |
| |
| |
| protected function getLabelsFromDataTable($dataTable, $labels) |
| { |
| |
| |
| $subDataTables = $dataTable->getDataTables(); |
| foreach ($subDataTables as $table) { |
| $labels = array_merge($labels, $table->getColumn('label')); |
| } |
| $labels = array_values(array_unique($labels)); |
|
|
| |
| |
| $limit = \Piwik\Request::fromRequest()->getIntegerParameter('filter_limit', -1); |
| if ($limit >= 0) { |
| $labels = array_slice($labels, 0, $limit); |
| } |
| return $labels; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function getSingleRowEvolution($idSite, $dataTable, $metadata, $apiModule, $apiAction, $label, $labelUseAbsoluteUrl = true) |
| { |
| $metricNames = array_keys($metadata['metrics']); |
|
|
| $logo = $actualLabel = false; |
| $urlFound = false; |
| |
| $subDataTables = $dataTable->getDataTables(); |
| foreach ($subDataTables as $subTable) { |
| $subTable->applyQueuedFilters(); |
| if ($subTable->getRowsCount() > 0) { |
| |
| $row = $subTable->getFirstRow(); |
|
|
| if (!$actualLabel) { |
| $logo = $row->getMetadata('logo'); |
|
|
| $actualLabel = $this->getRowUrlForEvolutionLabel($row, $apiModule, $apiAction, $labelUseAbsoluteUrl); |
| $urlFound = $actualLabel !== false; |
| if (empty($actualLabel)) { |
| $rowLabel = $row->getColumn('label'); |
| $actualLabel = is_scalar($rowLabel) ? (string)$rowLabel : ''; |
| } |
| } |
|
|
| |
| |
| |
| foreach ($row->getColumns() as $column => $value) { |
| if (!in_array($column, $metricNames) && $column != 'label_html') { |
| $row->deleteColumn($column); |
| } |
| } |
| $row->deleteMetadata(); |
| } |
| } |
|
|
| $this->enhanceRowEvolutionMetaData($metadata, $dataTable); |
|
|
| |
| if (!$urlFound) { |
| $label = Common::sanitizeInputValue(\Piwik\Request::fromRequest()->getStringParameter('labelPretty', '')) ?: $label; |
| $actualLabel = $this->formatQueryLabelForDisplay($idSite, $apiModule, $apiAction, $label); |
| } |
| $actualLabel = is_string($actualLabel) ? $actualLabel : ''; |
|
|
| $return = [ |
| 'label' => SafeDecodeLabel::decodeLabelSafe($actualLabel), |
| 'reportData' => $dataTable, |
| 'metadata' => $metadata, |
| ]; |
| if (!empty($logo)) { |
| $return['logo'] = $logo; |
| } |
| return $return; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function formatQueryLabelForDisplay($idSite, $apiModule, $apiAction, $label) |
| { |
| |
| |
| if ( |
| $apiModule == 'Actions' |
| && in_array($apiAction, self::$actionsUrlReports) |
| ) { |
| $mainUrl = Site::getMainUrlFor((int)$idSite); |
| $mainUrlHost = @parse_url($mainUrl, PHP_URL_HOST); |
|
|
| $replaceRegex = "/\\s*" . preg_quote(LabelFilter::SEPARATOR_RECURSIVE_LABEL) . "\\s*/"; |
| $cleanLabel = preg_replace($replaceRegex, '/', $label); |
|
|
| $result = $mainUrlHost . '/' . $cleanLabel . '/'; |
| } else { |
| $result = str_replace(LabelFilter::SEPARATOR_RECURSIVE_LABEL, ' - ', $label); |
| } |
|
|
| |
| return str_replace(LabelFilter::TERMINAL_OPERATOR, '', $result); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function getRowUrlForEvolutionLabel($row, $apiModule, $apiAction, $labelUseAbsoluteUrl) |
| { |
| $url = $row->getMetadata('url'); |
| if ( |
| is_string($url) |
| && $url !== '' |
| && ($apiModule == 'Actions' |
| || ($apiModule == 'Referrers' |
| && $apiAction == 'getWebsites')) |
| && $labelUseAbsoluteUrl |
| ) { |
| $actualLabel = preg_replace(';^http(s)?://(www.)?;i', '', $url); |
| return $actualLabel ?? $url; |
| } |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $apiParameters, $showGoalMetricsForGoal) |
| { |
| if (!is_array($label)) { |
| $label = [$label]; |
| } |
| $label = array_map('strval', $label); |
| $label = array_map('rawurlencode', $label); |
|
|
| $parameters = [ |
| 'method' => $apiModule . '.' . $apiAction, |
| 'label' => $label, |
| 'idSite' => $idSite, |
| 'period' => $period, |
| 'date' => $date, |
| 'format' => 'original', |
| 'serialize' => '0', |
| 'segment' => $segment, |
| |
| 'filter_limit' => -1, |
|
|
| |
| |
| |
| 'labelFilterAddLabelIndex' => count($label) > 1 ? 1 : 0, |
| ]; |
|
|
| if ($showGoalMetricsForGoal !== false) { |
| $parameters['filter_show_goal_columns_process_goals'] = implode(',', $this->getGoalsToProcess($showGoalMetricsForGoal, $idSite)); |
| $parameters['filter_update_columns_when_show_all_goals'] = 1; |
| $parameters['idGoal'] = $showGoalMetricsForGoal; |
| } |
|
|
| if (!empty($apiParameters) && is_array($apiParameters)) { |
| foreach ($apiParameters as $param => $value) { |
| $parameters[$param] = $value; |
| } |
| } |
|
|
| |
| |
| |
| |
| if (isset($metadata['metrics']['nb_visits'])) { |
| $parameters['filter_add_columns_when_show_all_columns'] = '0'; |
| } |
|
|
| $parameters = array_filter($parameters, function ($value) { |
| return $value !== null && $value !== false; |
| }); |
|
|
| $request = new Request($parameters); |
|
|
| try { |
| $dataTable = $request->process(); |
| } catch (Exception $e) { |
| throw new Exception("API returned an error: " . $e->getMessage() . "\n"); |
| } |
|
|
| if (!($dataTable instanceof DataTable\Map)) { |
| throw new Exception("Unexpected state: row evolution API call returned incorrect data table type."); |
| } |
|
|
| return $dataTable; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $apiParameters) |
| { |
| $reportMetadata = API::getInstance()->getMetadata( |
| $idSite, |
| $apiModule, |
| $apiAction, |
| $apiParameters, |
| $language, |
| $period, |
| $date, |
| $hideMetricsDoc = false, |
| $showSubtableReports = true |
| ); |
|
|
| if (empty($reportMetadata)) { |
| throw new Exception("Requested report $apiModule.$apiAction for Website id=$idSite " |
| . "not found in the list of available reports. \n"); |
| } |
|
|
| $reportMetadata = reset($reportMetadata); |
|
|
| $metrics = (isset($reportMetadata['metrics']) && is_array($reportMetadata['metrics']) ? $reportMetadata['metrics'] : []); |
| if (isset($reportMetadata['processedMetrics']) && is_array($reportMetadata['processedMetrics'])) { |
| $metrics = $metrics + $reportMetadata['processedMetrics']; |
| } |
|
|
| if (empty($reportMetadata['dimension'])) { |
| throw new Exception(sprintf('Reports like %s.%s which do not have a dimension are not supported by row evolution', $apiModule, $apiAction)); |
| } |
|
|
| $dimension = $reportMetadata['dimension']; |
|
|
| return compact('metrics', 'dimension'); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| private function enhanceRowEvolutionMetaData(&$metadata, $dataTable) |
| { |
| |
| $metricsResult = []; |
| foreach ($metadata['metrics'] as $metric => $name) { |
| $metricsResult[$metric] = ['name' => $name]; |
|
|
| if (!empty($metadata['logos'][$metric])) { |
| $metricsResult[$metric]['logo'] = $metadata['logos'][$metric]; |
| } |
| } |
| unset($metadata['logos']); |
|
|
| |
| $subDataTables = $dataTable->getDataTables(); |
| if (empty($subDataTables)) { |
| throw new \Exception("Unexpected state: row evolution API call returned empty DataTable\\Map."); |
| } |
|
|
| $firstDataTable = reset($subDataTables); |
| $this->checkDataTableInstance($firstDataTable); |
| $firstDataTableRow = $firstDataTable->getFirstRow(); |
|
|
| $lastDataTable = end($subDataTables); |
| $this->checkDataTableInstance($lastDataTable); |
| $lastDataTableRow = $lastDataTable->getFirstRow(); |
|
|
| |
| $firstNonZeroFound = []; |
| foreach ($subDataTables as $subDataTable) { |
| |
| $firstRow = $subDataTable->getFirstRow(); |
| foreach ($metadata['metrics'] as $metric => $label) { |
| $value = $firstRow ? $this->getNumericColumnValue($firstRow, $metric) : 0; |
| if ($value > 0) { |
| $firstNonZeroFound[$metric] = true; |
| } elseif (!isset($firstNonZeroFound[$metric])) { |
| continue; |
| } |
| if ( |
| !isset($metricsResult[$metric]['min']) |
| || $metricsResult[$metric]['min'] > $value |
| ) { |
| $metricsResult[$metric]['min'] = $value; |
| } |
| if ( |
| !isset($metricsResult[$metric]['max']) |
| || $metricsResult[$metric]['max'] < $value |
| ) { |
| $metricsResult[$metric]['max'] = $value; |
| } |
| } |
| } |
|
|
| |
| foreach ($metadata['metrics'] as $metric => $label) { |
| $first = $firstDataTableRow ? $this->getNumericColumnValue($firstDataTableRow, $metric) : 0; |
| $last = $lastDataTableRow ? $this->getNumericColumnValue($lastDataTableRow, $metric) : 0; |
|
|
| |
| if ($first == 0) { |
| continue; |
| } |
|
|
| $change = CalculateEvolutionFilter::calculate($last, $first, $quotientPrecision = 0, true, true); |
|
|
| $metricsResult[$metric]['change'] = $change; |
| } |
|
|
| $metadata['metrics'] = $metricsResult; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| private function getMultiRowEvolution( |
| DataTable\Map $dataTable, |
| $metadata, |
| $apiModule, |
| $apiAction, |
| $labels, |
| $column, |
| $legendAppendMetric = true, |
| $labelUseAbsoluteUrl = true, |
| $labelSeries = '' |
| ) { |
| $labelSeries = explode(',', $labelSeries); |
| $labelSeries = array_filter($labelSeries, 'strlen'); |
| $labelSeries = array_map('intval', $labelSeries); |
|
|
| if (!isset($metadata['metrics'][$column])) { |
| |
| $metrics = array_keys($metadata['metrics']); |
| $column = reset($metrics); |
| } |
|
|
| $labelPretty = Common::sanitizeInputValue(\Piwik\Request::fromRequest()->getStringParameter('labelPretty', '')); |
| |
| $labelPretty = Piwik::getArrayFromApiParameter($labelPretty); |
|
|
| |
| |
| $actualLabels = []; |
| |
| $logos = []; |
| |
| $subDataTables = $dataTable->getDataTables(); |
| foreach ($labels as $labelIdx => $label) { |
| foreach ($subDataTables as $table) { |
| $labelRow = $this->getRowEvolutionRowFromLabelIdx($table, $labelIdx); |
|
|
| if ($labelRow) { |
| $actualLabels[$labelIdx] = $this->getRowUrlForEvolutionLabel( |
| $labelRow, |
| $apiModule, |
| $apiAction, |
| $labelUseAbsoluteUrl |
| ); |
|
|
| $prettyLabel = $labelRow->getColumn('label_html'); |
| if ($prettyLabel !== false) { |
| $actualLabels[$labelIdx] = is_scalar($prettyLabel) ? (string)$prettyLabel : ''; |
| } elseif (!empty($labelPretty[$labelIdx])) { |
| $actualLabels[$labelIdx] = $labelPretty[$labelIdx]; |
| } |
|
|
| $logos[$labelIdx] = $labelRow->getMetadata('logo'); |
|
|
| if (!empty($actualLabels[$labelIdx])) { |
| break; |
| } |
| } elseif (!empty($labelPretty[$labelIdx])) { |
| $actualLabels[$labelIdx] = $labelPretty[$labelIdx]; |
| } |
| } |
|
|
| if (empty($actualLabels[$labelIdx])) { |
| $cleanLabel = $this->cleanOriginalLabel($label); |
| $actualLabels[$labelIdx] = $cleanLabel; |
| } |
|
|
| if (isset($labelSeries[$labelIdx])) { |
| $labelSeriesIndex = $labelSeries[$labelIdx]; |
| $actualLabels[$labelIdx] .= ' ' . DataComparisonFilter::getPrettyComparisonLabelFromSeriesIndex($labelSeriesIndex); |
| } |
| } |
|
|
| |
| |
| |
| $dataTableMulti = $dataTable->getEmptyClone(); |
| foreach ($subDataTables as $tableLabel => $table) { |
| $newRow = new Row(); |
|
|
| foreach ($labels as $labelIdx => $label) { |
| $row = $this->getRowEvolutionRowFromLabelIdx($table, $labelIdx); |
|
|
| $value = 0; |
| if ($row) { |
| $value = $this->getNumericColumnValue($row, (string)$column); |
| } |
|
|
| if ($value == '') { |
| $value = 0; |
| } |
|
|
| $newLabel = (string)$column . '_' . (int)$labelIdx; |
| $newRow->addColumn($newLabel, $value); |
| } |
|
|
| |
| $newTable = $table->getEmptyClone(); |
| if (!empty($labels)) { |
| $newTable->addRow($newRow); |
| } |
|
|
| $dataTableMulti->addTable($newTable, $tableLabel); |
| } |
|
|
| |
| $metadata['columns'] = $metadata['metrics']; |
|
|
| |
| |
| $metadata['metrics'] = []; |
| foreach ($actualLabels as $labelIndex => $label) { |
| if ($legendAppendMetric) { |
| $label .= ' (' . $metadata['columns'][(string)$column] . ')'; |
| } |
| $metricName = (string)$column . '_' . $labelIndex; |
| $metadata['metrics'][$metricName] = $label; |
|
|
| if (!empty($logos[$labelIndex])) { |
| $metadata['logos'][$metricName] = $logos[$labelIndex]; |
| } |
| } |
|
|
| $this->enhanceRowEvolutionMetaData($metadata, $dataTableMulti); |
|
|
| return [ |
| 'column' => $column, |
| 'reportData' => $dataTableMulti, |
| 'metadata' => $metadata, |
| ]; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| private function getRowEvolutionRowFromLabelIdx($table, $labelIdx) |
| { |
| $labelIdx = (int)$labelIdx; |
| foreach ($table->getRows() as $row) { |
| if ($row->getMetadata(LabelFilter::FLAG_IS_ROW_EVOLUTION) === $labelIdx) { |
| return $row; |
| } |
| } |
| return false; |
| } |
|
|
| |
| |
| |
| |
| private function cleanOriginalLabel($label) |
| { |
| $label = str_replace(LabelFilter::SEPARATOR_RECURSIVE_LABEL, ' - ', $label); |
| return SafeDecodeLabel::decodeLabelSafe($label); |
| } |
|
|
| |
| |
| |
| |
| private function getNumericColumnValue(Row $row, $column) |
| { |
| $value = $row->getColumn($column); |
| if (!is_scalar($value) && $value !== null) { |
| return 0.0; |
| } |
|
|
| return floatVal(str_replace(',', '.', (string)$value)); |
| } |
|
|
| |
| |
| |
| |
| |
| private function checkDataTableInstance($lastDataTable) |
| { |
| if (!($lastDataTable instanceof DataTable)) { |
| $actualType = is_object($lastDataTable) ? get_class($lastDataTable) : gettype($lastDataTable); |
| throw new \Exception("Unexpected state: row evolution returned DataTable\\Map w/ incorrect child table type: " . $actualType); |
| } |
| } |
| } |
|
|