db = $db; $this->service = $service; $this->gateway = $gateway; } /** * @param array $data * @param string $groupColumn * @param string $valueCol * * @return array[] */ private function groupDataByColumn($data, $groupColumn, $axesCol, $valueCol) { $groupedData = []; $groupValues = []; foreach($data as $row) { if(!isset($row[$groupColumn])) { continue; } if(isset($row[$axesCol]) && isset($row[$valueCol])) { $groupedData[$row[$axesCol]][$row[$groupColumn]] = $row; } if(!in_array($row[$groupColumn], $groupValues)) { $groupValues[] = $row[$groupColumn]; } } if(empty($groupValues) || empty($groupedData)) { return [$data, $groupValues]; } sort($groupValues); $data = []; foreach($groupedData as $axeValue => $groupedRows) { $firstRow = reset($groupedRows); unset($firstRow[$valueCol]); unset($firstRow[$groupColumn]); foreach($groupValues as $groupValue) { if(isset($groupedRows[$groupValue])) { $firstRow[$groupValue] = $groupedRows[$groupValue][$valueCol]; } else { $firstRow[$groupValue] = 0; } } $data[] = $firstRow; } return [$data, $groupValues]; } /** * @param ReportData $report * * @return Chart */ private function getChartFromReport(ReportData $report, $parameterValues = []) { $struktur = $this->service->resolveParameters($report, $parameterValues); if(!$this->service->isSqlStatementAllowed($struktur)) { throw new InvalidArgumentException('Resolved Query not executable.'); } $arr = $this->db->fetchAll($struktur); if(empty($arr)) { throw new EmptyQueryException('Result empty'); } $share = $this->gateway->findShareArrayByReportId($report->getId()); if(empty($share)) { throw new EmptyQueryException('Share Object empty'); } $chartType = $share['chart_type']; if(empty($chartType)) { $chartType = 'line'; } $yAxis = $share['chart_axislabel']; $groupColumn = $share['chart_group_column']; $firstColumn = $share['chart_x_column']; $dataColumns = trim($share['data_columns'],';'); $dataColumnsArr = explode(';', $dataColumns); $dataColumnsArr = array_map('trim', $dataColumnsArr); $firstName = $yAxis; $secondColumn = $dataColumns; $groupValues = []; $isLineOrBar = in_array($chartType, ['line','bar']); if(!empty($groupColumn) && !empty($firstColumn) && !empty($dataColumns) && $isLineOrBar) { list($arr, $groupValues) = $this->groupDataByColumn($arr, $groupColumn, $firstColumn, $dataColumns); if(!empty($groupValues)) { $secondColumn = reset($groupValues); $firstName = $secondColumn; } } elseif($isLineOrBar && count($dataColumnsArr) > 1) { $groupValues = $dataColumnsArr; } foreach ($report->getColumns() as $column) { if(empty($firstColumn)) { $firstColumn = $column->getKey(); if(empty($firstName)) { $firstName = $column->getTitle(); } continue; } if($column->getKey() === $firstColumn) { continue; } if(empty($secondColumn)) { $secondColumn = $column->getKey(); break; } } $data = array_column($arr, $secondColumn); $data = array_map('floatVal', str_replace(',','.', $data)); $labels = array_column($arr, $firstColumn); $dataset = new Dataset($firstName, $data); $chart = new Chart($chartType, $labels, [$dataset]); if(!empty($groupValues) && count($groupValues) > 1) { foreach($groupValues as $groupValue) { if($groupValue === $secondColumn) { continue; } $chart->addDataset( new Dataset( $groupValue, array_map( 'floatVal', str_replace(',','.', array_column( $arr, $groupValue ) ) ) ) ); } } return $chart; } /** * @param Chart $chart * @param string $title * @param int $width * @param int $height * * @return HtmlRenderer */ private function getChartRenderer(Chart $chart, $title, $width = 400, $height = 150) { return new HtmlRenderer($chart, $title, $width, $height); } /** * @param HtmlRenderer $render * * @return string */ private function getChartString(HtmlRenderer $render) { return $render->render(); } /** * @param ReportData $report * @param int $width * @param int $height * * @return string */ public function renderChartByReport(ReportData $report, $width = 400, $height = 150) { $chart = $this->getChartFromReport($report); $renderer = $this->getChartRenderer($chart, $report->getName(), $width, $height); return $this->getChartString($renderer); } }