mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-11-15 20:47:15 +01:00
352 lines
12 KiB
PHP
352 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Xentral\Modules\Report;
|
|
|
|
use Exception;
|
|
use Xentral\Components\Http\File\FileUpload;
|
|
use Xentral\Modules\Report\Data\ReportColumn;
|
|
use Xentral\Modules\Report\Data\ReportColumnCollection;
|
|
use Xentral\Modules\Report\Data\ReportData;
|
|
use Xentral\Modules\Report\Data\ReportParameter;
|
|
use Xentral\Modules\Report\Data\ReportParameterCollection;
|
|
use Xentral\Modules\Report\Exception\InvalidArgumentException;
|
|
use Xentral\Modules\Report\Exception\JsonParseException;
|
|
use Xentral\Modules\Report\Exception\ReportReadonlyException;
|
|
|
|
final class ReportJsonImportService
|
|
{
|
|
/** @var ReportGateway $gateway */
|
|
private $gateway;
|
|
|
|
/** @var ReportService $service */
|
|
private $service;
|
|
|
|
/**
|
|
* @param ReportGateway $gateway
|
|
* @param ReportService $service
|
|
*/
|
|
public function __construct(ReportGateway $gateway, ReportService $service)
|
|
{
|
|
$this->gateway = $gateway;
|
|
$this->service = $service;
|
|
}
|
|
|
|
/**
|
|
* @param array $jsonData
|
|
*
|
|
* @return int database entry id
|
|
*/
|
|
public function importReport($jsonData)
|
|
{
|
|
if (!is_array($jsonData)) {
|
|
throw new JsonParseException('Json data must be associative array.');
|
|
}
|
|
if (!isset($jsonData['name']) || $jsonData['name'] === '') {
|
|
throw new JsonParseException('Name of the report is required.');
|
|
}
|
|
|
|
$existing = $this->gateway->findReportByName($jsonData['name']);
|
|
$existingShare = [];
|
|
if ($existing !== null) {
|
|
$jsonData['id'] = $existing->getId();
|
|
$report = $this->parseReport($jsonData);
|
|
$columns = $this->gateway->getColumnsByReportId($existing->getId());
|
|
$params = $this->gateway->getParametersByReportId($existing->getId());
|
|
$areColumnsEqual = $this->areArraysEqual(
|
|
$columns->toArray(),
|
|
$report->getColumns() === null ? [] : $report->getColumns()
|
|
->toArray()
|
|
);
|
|
$areParamsEqual = $this->areArraysEqual(
|
|
$params->toArray(),
|
|
$report->getParameters() === null ? [] : $report->getParameters()
|
|
->toArray()
|
|
);
|
|
if ($areColumnsEqual && $areParamsEqual) {
|
|
$report->setColumns(new ReportColumnCollection());
|
|
$report->setParameters(new ReportParameterCollection());
|
|
} else {
|
|
foreach ($columns as $column) {
|
|
$this->service->deleteColumnById($column->getId());
|
|
}
|
|
foreach ($params as $param) {
|
|
$this->service->deleteParamById($param->getId());
|
|
}
|
|
}
|
|
$existingShare = $this->gateway->findShareArrayByReportId($existing->getId());
|
|
} else {
|
|
$report = $this->parseReport($jsonData);
|
|
}
|
|
$insertReportId = $this->service->saveReport($report);
|
|
|
|
if (array_key_exists('share', $jsonData) && $jsonData['share'] !== null) {
|
|
$share = $this->parseShare($jsonData['share'], $existingShare);
|
|
$share['id'] = 0;
|
|
$share['report_id'] = $insertReportId;
|
|
if ($existingShare !== null && count($existingShare) > 0) {
|
|
$share['id'] = $existingShare['id'];
|
|
}
|
|
$this->service->saveShareArray($share);
|
|
}
|
|
|
|
return $insertReportId;
|
|
}
|
|
|
|
/**
|
|
* @param array $jsonArray
|
|
*
|
|
* @return array errors
|
|
*/
|
|
public function findJsonStructureErrors($jsonArray)
|
|
{
|
|
$errors = [];
|
|
$required = ['name', 'sql_query', 'columns'];
|
|
$requiredInColumn = ['key_name', 'title'];
|
|
$requiredInParam = ['varname', 'default_value'];
|
|
foreach ($required as $key) {
|
|
if (!isset($jsonArray[$key]) || empty($jsonArray[$key])) {
|
|
$errors[] = sprintf('Field %s is required.', $key);
|
|
}
|
|
}
|
|
if (isset($jsonArray['columns']) && is_array($jsonArray['columns'])) {
|
|
foreach ($jsonArray['columns'] as $column) {
|
|
foreach ($requiredInColumn as $key) {
|
|
if (!isset($column[$key]) || $column[$key] === '') {
|
|
$errors[] = sprintf('Field column>%s is required.', $key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isset($jsonArray['parameters']) && is_array($jsonArray['parameters'])) {
|
|
foreach ($jsonArray['parameters'] as $param) {
|
|
foreach ($requiredInParam as $key) {
|
|
if (!isset($param[$key]) || $param[$key] === '') {
|
|
$errors[] = sprintf('Field column>%s is required.', $key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* @param FileUpload $upload
|
|
* @param int $currentId
|
|
*
|
|
* @return int
|
|
*/
|
|
public function importJsonUpload(FileUpload $upload, $currentId = 0)
|
|
{
|
|
if ($currentId > 0 && $this->gateway->isReportReadonly($currentId)) {
|
|
throw new ReportReadonlyException('Cannot overwrite report by JSON import');
|
|
}
|
|
if ($upload === null || !$upload->isValid() || $upload->getClientMimeType() !== 'application/json') {
|
|
throw new InvalidArgumentException('uploaded file is invalid');
|
|
}
|
|
if ($upload->hasError()) {
|
|
throw new InvalidArgumentException($upload->getErrorMessage(), $upload->getErrorCode());
|
|
}
|
|
$stringContent = $upload->getContent();
|
|
$dataArray = json_decode($stringContent, true);
|
|
if (empty($dataArray)) {
|
|
throw new JsonParseException('Error parsing JSON structure');
|
|
}
|
|
|
|
if (isset($dataArray['name'])) {
|
|
$dataArray['name'] = $this->service->generateIncrementedReportName($dataArray['name'], $currentId);
|
|
}
|
|
|
|
return $this->importReport($dataArray);
|
|
}
|
|
|
|
/**
|
|
* @param array $reportData
|
|
*
|
|
* @throws JsonParseException
|
|
*
|
|
* @return ReportData
|
|
*/
|
|
private function parseReport($reportData)
|
|
{
|
|
try {
|
|
$report = ReportData::fromFormData($reportData);
|
|
} catch (Exception $e) {
|
|
throw new JsonParseException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
if (isset($reportData['readonly']) && $reportData['readonly'] === true) {
|
|
$report->setReadonly(true);
|
|
}
|
|
|
|
$columnObjects = [];
|
|
if (isset($reportData['columns']) && is_array($reportData['columns'])) {
|
|
|
|
$sequence = 1;
|
|
foreach ($reportData['columns'] as $columnData) {
|
|
$parsedCol = $this->parseColumn($columnData);
|
|
if ($parsedCol->getSequence() === 0) {
|
|
$parsedCol = new ReportColumn(
|
|
$parsedCol->getKey(),
|
|
$parsedCol->getTitle(),
|
|
$parsedCol->getWidth(),
|
|
$parsedCol->getAlignment(),
|
|
$parsedCol->isSumColumn(),
|
|
$parsedCol->getId(),
|
|
$sequence,
|
|
$parsedCol->getSorting(),
|
|
$parsedCol->getFormatType(),
|
|
$parsedCol->getFormatStatement()
|
|
);
|
|
}
|
|
$columnObjects[] = $parsedCol;
|
|
$sequence++;
|
|
}
|
|
}
|
|
$colCollection = new ReportColumnCollection($columnObjects);
|
|
$report->setColumns($colCollection);
|
|
|
|
$paramObjects = [];
|
|
if (isset($reportData['parameters']) && is_array($reportData['parameters'])) {
|
|
foreach ($reportData['parameters'] as $paramData) {
|
|
$paramObjects[] = $this->parseParam($paramData);
|
|
}
|
|
}
|
|
$paramCollection = new ReportParameterCollection($paramObjects);
|
|
$report->setParameters($paramCollection);
|
|
|
|
return $report;
|
|
}
|
|
|
|
/**
|
|
* @param array $colData
|
|
*
|
|
* @throws JsonParseException
|
|
*
|
|
* @return ReportColumn
|
|
*/
|
|
private function parseColumn($colData)
|
|
{
|
|
try {
|
|
$column = ReportColumn::fromDbState($colData);
|
|
} catch (Exception $e) {
|
|
throw new JsonParseException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
if ($column === null) {
|
|
throw new JsonParseException('Error while parsing Column.');
|
|
}
|
|
|
|
return $column;
|
|
}
|
|
|
|
/**
|
|
* @param array $paramData
|
|
*
|
|
* @throws JsonParseException
|
|
*
|
|
* @return ReportParameter
|
|
*/
|
|
private function parseParam($paramData)
|
|
{
|
|
try {
|
|
$parameter = ReportParameter::fromDbState($paramData);
|
|
} catch (Exception $e) {
|
|
throw new JsonParseException($e->getMessage(), $e->getCode(), $e);
|
|
}
|
|
if ($parameter === null) {
|
|
throw new JsonParseException('Error while parsing Column.');
|
|
}
|
|
|
|
return $parameter;
|
|
}
|
|
|
|
/**
|
|
* @param array $share
|
|
* @param array $existingShare
|
|
*
|
|
* @return array
|
|
*/
|
|
private function parseShare($share, $existingShare = [])
|
|
{
|
|
$data = [
|
|
'chart_public' => 0,
|
|
'chart_axislabel' => '',
|
|
'chart_dateformat' => 'Y-m-d H:i:s',
|
|
'chart_type' => 'line',
|
|
'chart_x_column' => '',
|
|
'data_columns' => '',
|
|
'chart_group_column' => '',
|
|
'chart_interval_value' => 0,
|
|
'chart_interval_mode' => 'day',
|
|
'file_public' => 0,
|
|
'file_pdf_enabled' => 0,
|
|
'file_csv_enabled' => 0,
|
|
'file_xls_enabled' => 0,
|
|
'menu_public' => 0,
|
|
'menu_doctype' => '',
|
|
'menu_label' => '',
|
|
'menu_format' => 'csv',
|
|
'tab_public' => 0,
|
|
'tab_module' => '',
|
|
'tab_action' => '',
|
|
'tab_label' => '',
|
|
'tab_position' => 'nach_freifeld',
|
|
];
|
|
|
|
$data = array_merge($data, $existingShare);
|
|
$data = array_merge($data, $share);
|
|
|
|
$boolkeys = [
|
|
'chart_public',
|
|
'file_public',
|
|
'file_pdf_enabled',
|
|
'file_csv_enabled',
|
|
'file_xls_enabled',
|
|
'menu_public',
|
|
'tab_public',
|
|
];
|
|
|
|
foreach ($boolkeys as $booleanKey) {
|
|
if (array_key_exists($booleanKey, $share) && $share[$booleanKey] === true) {
|
|
$data[$booleanKey] = 1;
|
|
} else {
|
|
$data[$booleanKey] = 0;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* @param array $collection
|
|
* @param array $collectionToTest
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function areArraysEqual(array $collection, array $collectionToTest): bool
|
|
{
|
|
$collectionWithOutIds = array_map(
|
|
static function (array $array) {
|
|
unset($array['id']);
|
|
if(isset($array['sum'])) {
|
|
$array['sum'] = (int)$array['sum'];
|
|
}
|
|
return $array;
|
|
},
|
|
$collection
|
|
);
|
|
$collectionToTestWithOutIds = array_map(
|
|
static function (array $array) {
|
|
unset($array['id']);
|
|
if(isset($array['sum'])) {
|
|
$array['sum'] = (int)$array['sum'];
|
|
}
|
|
|
|
return $array;
|
|
},
|
|
$collectionToTest
|
|
);
|
|
|
|
return json_encode($collectionToTestWithOutIds) === json_encode($collectionWithOutIds);
|
|
}
|
|
}
|