mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-25 06:00:28 +01:00
214 lines
6.4 KiB
PHP
214 lines
6.4 KiB
PHP
<?php
|
|
|
|
namespace Xentral\Modules\Report;
|
|
|
|
use Xentral\Components\Database\Database;
|
|
use Xentral\Modules\Report\Data\ReportData;
|
|
use Xentral\Modules\Report\Exception\InvalidArgumentException;
|
|
use Xentral\Modules\Report\Exception\EmptyQueryException;
|
|
use Xentral\Widgets\Chart\Chart;
|
|
use Xentral\Widgets\Chart\Dataset;
|
|
use Xentral\Widgets\Chart\HtmlRenderer;
|
|
|
|
class ReportChartService
|
|
{
|
|
/** @var Database $db */
|
|
private $db;
|
|
|
|
/** @var ReportService $service */
|
|
protected $service;
|
|
|
|
/** @var ReportGateway $gateway */
|
|
protected $gateway;
|
|
|
|
/**
|
|
* @param Database $db
|
|
*/
|
|
public function __construct(Database $db, ReportService $service, ReportGateway $gateway)
|
|
{
|
|
$this->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);
|
|
}
|
|
}
|