OpenXE/classes/Modules/Report/ReportGateway.php
2021-05-21 08:49:41 +02:00

589 lines
18 KiB
PHP

<?php
namespace Xentral\Modules\Report;
use PHPUnit\Runner\Exception;
use Xentral\Components\Database\Database;
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;
final class ReportGateway
{
/** @var Database $db */
private $db;
/**
* @param Database $database
*/
public function __construct(Database $database)
{
$this->db = $database;
}
/**
* @param string $category
* @param string $searchTerm
* @param int $userId
* @param bool $onlyOwn
* @param bool $onlyFavorites
*
* @return array
*/
public function getReportList($category = '', $searchTerm = '', $userId = 0, $onlyOwn = false, $onlyFavorites = false)
{
$result = [];
$select = $this->db->select();
$select->cols([
'r.id',
'r.name',
'r.description',
'r.project',
'r.category',
'IF(rs.file_public = 1 OR ru.file_enabled = 1 OR u.type = \'admin\', 1, 0) as allow_download',
'IF(rs.file_csv_enabled = 1 OR u.type = \'admin\', 1, 0) as allow_csv',
'IF(rs.file_pdf_enabled = 1 OR u.type = \'admin\', 1, 0) as allow_pdf',
'IF(rs.menu_public = 1 OR ru.menu_enabled = 1 OR u.type = \'admin\', 1, 0) as allow_menu',
'IF(rs.tab_public = 1 OR ru.tab_enabled = 1 OR u.type = \'admin\', 1, 0) as allow_tab',
'IF( (rs.chart_public = 1 OR ru.chart_enabled = 1 OR u.type = \'admin\') AND rs.chart_x_column <> \'\', 1, 0) as allow_chart',
'IF(rf.id IS NULL, 0, 1) as is_favorite',
'r.readonly'
]);
$select->from('report AS r');
try {
$select->leftJoin('report_share AS rs', 'r.id = rs.report_id')
->leftJoin('report_favorite AS rf', '(r.id = rf.report_id AND rf.user_id = :userId)')
->leftJoin('report_user AS ru', '(r.id = ru.report_id AND ru.user_id = :userId)')
->leftJoin('user AS u', 'u.id = :userId');
} catch (\Aura\SqlQuery\Exception $e) {
return [];
}
if ($userId > 0) {
$select->where(
'(
(
ru.id IS NOT NULL
OR rs.file_public = 1
OR rs.menu_public = 1
OR rs.chart_public = 1
OR rs.tab_public = 1
)
AND
(r.project = 0 OR r.project IN (SELECT ar.projekt
FROM adresse_rolle AS ar
LEFT JOIN user as u ON ar.adresse = u.adresse
WHERE u.id = :userId)
)
OR :userId IN (SELECT u.id as `c` FROM `user` AS u WHERE u.id = :userId AND u.type = \'admin\')
)
'
);
}
if ($category !== '') {
$select->Where('r.category LIKE :filterCategory');
}
if ($searchTerm !== '') {
$select->Where('(r.name LIKE :searchTerm OR r.description LIKE :searchTerm)');
}
if ($userId > 0 && $onlyFavorites === true) {
$select->Where('rf.user_id IS NOT NULL');
}
if ($onlyOwn === true) {
$select->Where('r.readonly = 0');
}
$select->orderBy(['rf.user_id DESC', 'r.readonly ASC', 'r.name']);
$sql = $select->getStatement();
$values = [
'filterCategory' => $category,
'searchTerm' => sprintf('%%%s%%', $searchTerm),
'userId' => $userId
];
$list = $this->db->fetchAll($sql, $values);
if (is_array($list) && count($list) > 0) {
$result = $list;
}
return $result;
}
/**
* @param int $id
*
* @return ReportData|null
*/
public function getReportById($id)
{
$report = $this->getOnlyReportById($id);
if ($report === null) {
return null;
}
$columns = $this->getColumnsByReportId($id);
$report->setColumns($columns);
$params = $this->getParametersByReportId($id);
$report->setParameters($params);
return $report;
}
/**
* @param string $name
*
* @return ReportData|null
*/
public function findReportByName($name)
{
$sql = 'SELECT r.id FROM `report` AS `r` WHERE r.name=:name ORDER BY r.id LIMIT 1';
$row = $this->db->fetchRow($sql, ['name' => $name]);
if (!is_array($row) || count($row) < 1) {
return null;
}
return $this->getReportById($row['id']);
}
/**
* @param int $id
*
* @return ReportData|null
*/
public function getOnlyReportById($id)
{
$sql = 'SELECT r.id, r.name, r.description, r.project, r.sql_query, r.remark, r.category, r.readonly,
r.csv_delimiter, r.csv_enclosure
FROM `report` AS `r`
WHERE r.id=:idvalue';
$values = ['idvalue' => $id];
$row = $this->db->fetchRow($sql, $values);
if ($row === null || count($row) === 0) {
return null;
}
return ReportData::fromFormData($row);
}
/**
* @param int $id
*
* @return ReportColumnCollection
*/
public function getColumnsByReportId($id)
{
$sql = 'SELECT c.id, c.key_name, c.title, c.width, c.alignment, c.sorting, c.sum, c.sequence, c.format_type,
c.format_statement
FROM `report_column` AS `c`
WHERE c.report_id=:idvalue
ORDER BY c.sequence';
$values = ['idvalue' => $id];
$rows = $this->db->fetchAll($sql, $values);
$objects = [];
foreach ($rows as $row) {
$objects[] = new ReportColumn(
$row['key_name'],
$row['title'],
$row['width'],
$row['alignment'],
$row['sum'],
$row['id'],
$row['sequence'],
$row['sorting'],
$row['format_type'],
$row['format_statement']
);
}
return new ReportColumnCollection($objects);
}
/**
* @param int $id
*
* @return ReportParameterCollection
*/
public function getParametersByReportId($id)
{
$sql = 'SELECT p.id, p.varname, p.displayname, p.default_value, p.options, p.description,
p.editable, p.control_type
FROM `report_parameter` AS `p`
WHERE p.report_id = :idvalue';
$values = ['idvalue' => $id];
$rows = $this->db->fetchAll($sql, $values);
return ReportParameterCollection::fromFormData($rows);
}
/**
* @param int $id
*
* @return bool
*/
public function reportExists($id)
{
if ((int)$id < 1) {
return false;
}
$sql = 'SELECT r.id FROM `report` AS `r` WHERE r.id = :idvalue';
$values = ['idvalue' => (int)$id];
$idResult = $this->db->fetchRow($sql, $values);
return (isset($idResult['id']) && $idResult['id'] === $id);
}
/**
* @param $id
*
* @return bool
*/
public function isReportReadonly($id)
{
if ((int)$id < 1) {
return false;
}
$sql = 'SELECT r.readonly FROM `report` AS `r` WHERE r.id = :idvalue';
$values = ['idvalue' => (int)$id];
$result = $this->db->fetchRow($sql, $values);
return (isset($result['readonly']) && $result['readonly'] === 1);
}
/**
* @param int $id
*
* @return bool
*/
public function columnExists($id)
{
if ((int)$id < 1) {
return false;
}
$sql = 'SELECT c.id FROM `report_column` AS `c` WHERE c.id = :idvalue';
$values = ['idvalue' => (int)$id];
$idResult = $this->db->fetchRow($sql, $values);
return (isset($idResult['id']) && $idResult['id'] === $id);
}
/**
* @param int $columnId
*
* @return int
*/
public function getReportIdByColumn($columnId)
{
$sql = 'SELECT r.id
FROM `report` AS `r`
JOIN `report_column` AS `rc` ON r.id = rc.report_id
WHERE rc.id = :idValue';
$values = ['idValue' => $columnId];
return (int)$this->db->fetchValue($sql, $values);
}
/**
* @param int $id
*
* @return bool
*/
public function parameterExists($id)
{
if ((int)$id < 1) {
return false;
}
$sql = 'SELECT p.id FROM `report_parameter` AS `p` WHERE p.id = :idvalue';
$values = ['idvalue' => (int)$id];
$idResult = $this->db->fetchRow($sql, $values);
return (isset($idResult['id']) && $idResult['id'] === $id);
}
/**
* @param int $parameterId
*
* @return int
*/
public function getReportIdByParameter($parameterId)
{
$sql = 'SELECT r.id
FROM `report` AS `r`
JOIN `report_parameter` AS `rp` ON r.id = rp.report_id
WHERE rp.id = :idValue';
$values = ['idValue' => $parameterId];
return (int)$this->db->fetchValue($sql, $values);
}
/**
* @param int $id
*
* @return ReportParameter
*/
public function getParameterById($id)
{
$sql = 'SELECT p.id, p.varname, p.displayname, p.default_value, p.options, p.editable, p.description,
p.control_type
FROM `report_parameter` AS `p`
WHERE id = :idValue';
$values = ['idValue' => $id];
$data = $this->db->fetchRow($sql, $values);
return ReportParameter::fromDbState($data);
}
/**
* @param int $id
*
* @return ReportColumn
*/
public function getColumnById($id)
{
$sql = 'SELECT c.id, c.key_name, c.title, c.width, c.alignment, c.sorting, c.sum, c.sequence, c.format_type,
c.format_statement
FROM `report_column` AS `c`
WHERE c.id = :idValue';
$values = ['idValue' => $id];
$data = $this->db->fetchRow($sql, $values);
return ReportColumn::fromDbState($data);
}
/**
* @param int $id
*
* @return array
*/
public function findTransferArrayByReportId($id)
{
$sql = 'SELECT id, report_id, ftp_active, ftp_passive, ftp_type, ftp_host, ftp_port, ftp_user, ftp_password,
ftp_interval_mode, ftp_interval_value, ftp_daytime, ftp_format, ftp_filename, ftp_last_transfer,
email_active, email_recipient, email_subject, email_interval_mode, email_interval_value,
email_daytime, email_format, email_filename, email_last_transfer, url_format, url_begin,
url_end, url_address, api_active, api_account_id, api_format
FROM `report_transfer` AS `t`
WHERE report_id=:idValue';
$array = $this->db->fetchRow($sql, ['idValue' => $id]);
if ($array === null || empty($array)) {
return [];
}
return $array;
}
/**
* @param int $userId
* @param string $module
* @param string $action
*
* @return array
*/
public function findShareByModuleAction($userId, $module, $action)
{
$sql = "SELECT s.id, s.report_id, s.chart_public, s.chart_axislabel, s.chart_dateformat, s.chart_interval_value,
s.chart_interval_mode, s.file_public, s.file_pdf_enabled, s.file_csv_enabled,
s.file_xls_enabled, s.menu_public, s.menu_doctype, s.menu_label, s.menu_format, s.tab_public,
s.tab_module, s.tab_action, IF(s.tab_label <> '', s.tab_label, r.name) as `tab_label`,
s.tab_position, s.chart_type, s.chart_x_column, s.data_columns, s.chart_group_column
FROM `report_share` AS `s`
JOIN `report` AS `r` on s.report_id = r.id
LEFT JOIN `report_user` AS `ru` ON r.id = ru.report_id AND ru.user_id = :userid
WHERE (s.tab_public = 1 OR NOT ISNULL(ru.id)) AND s.tab_module = :module
AND (s.tab_action = '' OR s.tab_action = :action)";
$array = $this->db->fetchAll(
$sql,
[
'userid' => (int)$userId,
'module' => (string)$module,
'action' => (string)$action
]
);
if ($array === null || empty($array)) {
return [];
}
return $array;
}
/**
* @param int $id
*
* @return array
*/
public function findShareArrayByReportId($id)
{
$sql = 'SELECT s.id,s.report_id, s.chart_public, s.chart_axislabel, s.chart_dateformat, s.chart_interval_value,
s.chart_interval_mode, s.file_public, s.file_pdf_enabled, s.file_csv_enabled,
s.file_xls_enabled, s.menu_public, s.menu_doctype, s.menu_label, s.menu_format, s.tab_public,
s.tab_module, s.tab_action, s.tab_label, s.tab_position, s.chart_type,
s.chart_x_column, s.data_columns, s.chart_group_column
FROM `report_share` AS `s`
WHERE s.report_id=:idValue';
$array = $this->db->fetchRow($sql, ['idValue' => $id]);
if ($array === null || empty($array)) {
return [];
}
return $array;
}
/**
* @param int $id
*
* @return array
*/
public function findSharedUserById($id)
{
$sql = 'SELECT ru.id, ru.report_id, ru.user_id, ru.name, ru.chart_enabled, ru.file_enabled,
ru.menu_enabled, ru.tab_enabled
FROM `report_user` AS `ru`
WHERE ru.id=:idValue';
$array = $this->db->fetchRow($sql, ['idValue' => $id]);
if ($array === null || empty($array)) {
return [];
}
return $array;
}
/**
* @param int $userId
* @param int $reportId
*
* @return bool
*/
public function isSharedUserOfReport($userId, $reportId)
{
$sql = 'SELECT ru.id FROM `report_user` AS `ru` WHERE ru.user_id = :userId AND ru.report_id = :reportId';
$values = ['userId' => $userId, 'reportId' => $reportId];
$id = $this->db->fetchValue($sql, $values);
return !empty($id);
}
/**
* @param string $doctype
* @param int $userId
*
* @return array
*/
public function getDocumentAddActionMenuData($doctype, $userId = 0)
{
$sql = 'SELECT r.id, r.name, s.menu_doctype, s.menu_format, s.menu_label
FROM `report` as `r`
JOIN `report_share` as `s` ON r.id = s.report_id
LEFT JOIN `report_user` as `u` ON r.id = u.report_id
WHERE (s.menu_doctype = :docType AND (s.menu_public = 1 OR (u.user_id = :userId AND u.menu_enabled = 1))
AND
(r.project = 0 OR r.project IN (SELECT ar.projekt
FROM `adresse_rolle` AS `ar`
LEFT JOIN `user` as `u` ON ar.adresse = u.adresse
WHERE u.id = :userId)
OR :userId IN (SELECT u.id as `c` FROM `user` AS `u`
WHERE u.id = :userId AND u.type = \'admin\'))
)';
$data = $this->db->fetchAll($sql, ['docType' => strtolower($doctype), 'userId' => $userId]);
if (empty($data)) {
return [];
}
return $data;
}
/**
* @param int $reportId
* @param int $userId
*
* @return bool
*/
public function isFavoriteReportOfUser($reportId, $userId)
{
if ($reportId < 1 || $userId < 0){
return false;
}
$sql = 'SELECT rf.id
FROM `report_favorite` AS `rf`
WHERE rf.report_id = :reportID AND rf.user_id = :userId
LIMIT 1';
$id = $this->db->fetchValue($sql, ['reportID' => $reportId, 'userId' => $userId]);
return !empty($id);
}
/**
* @param $reportId
* @param $userId
*
* @return bool
*/
public function userCanDownloadCsv($reportId, $userId)
{
return $this->userCanDownload($reportId, $userId, 'csv');
}
/**
* @param $reportId
* @param $userId
*
* @return bool
*/
public function userCanDownloadPdf($reportId, $userId)
{
return $this->userCanDownload($reportId, $userId, 'pdf');
}
/**
* @todo: implement when xls exporter is ready
*
* @param $reportId
* @param $userId
*
* @return bool
*/
public function userCanDownloadXls($reportId, $userId)
{
//return $this->userCanDownload($reportId, $userId, 'xls');
return false;
}
/**
* @param $reportId
* @param $userId
*
* @param $filetype 'csv', 'pdf' or 'xls'
*
* @return bool
*/
private function userCanDownload($reportId, $userId, $filetype)
{
try {
$sql = sprintf(
'SELECT r.id
FROM `report` AS `r`
LEFT JOIN `report_share` AS `s` ON r.id = s.report_id
LEFT JOIN `report_user` AS `u` ON r.id = u.report_id
WHERE r.id = :reportId AND (
:userId IN (SELECT `u`.`id` AS `c` FROM `user` AS `u` WHERE `u`.`id` = :userId AND `u`.`type` = \'admin\')
OR
(s.file_%s_enabled = 1 AND (s.file_public = 1 OR (u.user_id = :userId AND u.file_enabled = 1)))
)',
$filetype
);
$data = $this->db->fetchAll($sql, ['reportId' => $reportId, 'userId' => $userId]);
return !empty($data);
} catch (Exception $e) {
return false;
}
}
}