0
0
mirror of https://github.com/salesagility/SuiteCRM.git synced 2024-11-25 00:56:49 +00:00
salesagility_SuiteCRM/modules/AOR_Reports/AOR_Report.php

1941 lines
86 KiB
PHP
Executable File

<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
* reasonably feasible for technical reasons, the Appropriate Legal Notices must
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use SuiteCRM\CleanCSV;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
#[\AllowDynamicProperties]
class AOR_Report extends Basic
{
public $new_schema = true;
public $module_dir = 'AOR_Reports';
public $object_name = 'AOR_Report';
public $table_name = 'aor_reports';
public $importable = true;
public $disable_row_level_security = true;
public $id;
public $name;
public $date_entered;
public $date_modified;
public $modified_user_id;
public $modified_by_name;
public $created_by;
public $created_by_name;
public $description;
public $deleted;
public $created_by_link;
public $modified_user_link;
public $assigned_user_id;
public $assigned_user_name;
public $assigned_user_link;
public $report_module;
public function __construct()
{
parent::__construct();
require_once('modules/AOW_WorkFlow/aow_utils.php');
require_once('modules/AOR_Reports/aor_utils.php');
}
public function bean_implements($interface)
{
switch ($interface) {
case 'ACL':
return true;
}
return false;
}
public function save($check_notify = false)
{
// TODO: process of saveing the fields and conditions is too long so we will have to make some optimization on save_lines functions
set_time_limit(3600);
if (empty($this->id) || (isset($_POST['duplicateSave']) && $_POST['duplicateSave'] == 'true')) {
unset($_POST['aor_conditions_id']);
unset($_POST['aor_fields_id']);
}
$return_id = parent::save($check_notify);
require_once('modules/AOR_Fields/AOR_Field.php');
$field = BeanFactory::newBean('AOR_Fields');
$field->save_lines($_POST, $this, 'aor_fields_');
require_once('modules/AOR_Conditions/AOR_Condition.php');
$condition = BeanFactory::newBean('AOR_Conditions');
$condition->save_lines($_POST, $this, 'aor_conditions_');
require_once('modules/AOR_Charts/AOR_Chart.php');
$chart = BeanFactory::newBean('AOR_Charts');
$chart->save_lines($_POST, $this, 'aor_chart_');
return $return_id;
}
/**
* @param string $view
* @param string $is_owner
* @param string $in_group
* @return bool
*/
public function ACLAccess($view, $is_owner = 'not_set', $in_group = 'not_set')
{
$result = parent::ACLAccess($view, $is_owner, $in_group);
if ($result && $this->report_module !== '') {
$result = ACLController::checkAccess($this->report_module, 'list', true);
}
return $result;
}
public function fill_in_additional_detail_fields()
{
parent::fill_in_additional_detail_fields();
$this->load_report_beans();
}
public function load_report_beans()
{
global $beanList, $app_list_strings;
$app_list_strings['aor_moduleList'] = $app_list_strings['moduleList'];
foreach ($app_list_strings['aor_moduleList'] as $mkey => $mvalue) {
if (!isset($beanList[$mkey]) || str_begin($mkey, 'AOR_') || str_begin($mkey, 'AOW_')) {
unset($app_list_strings['aor_moduleList'][$mkey]);
}
if (!ACLController::checkAccess($mkey, 'list', true)) {
unset($app_list_strings['aor_moduleList'][$mkey]);
}
}
$app_list_strings['aor_moduleList'] = array_merge(
array('' => ''),
(array)$app_list_strings['aor_moduleList']
);
asort($app_list_strings['aor_moduleList']);
}
public function getReportFields()
{
$fields = array();
foreach ($this->get_linked_beans('aor_fields', 'AOR_Fields') as $field) {
$fields[] = $field;
}
usort($fields, function ($a, $b) {
return $a->field_order - $b->field_order;
});
return $fields;
}
public const CHART_TYPE_PCHART = 'pchart';
public const CHART_TYPE_CHARTJS = 'chartjs';
public const CHART_TYPE_RGRAPH = 'rgraph';
public function build_report_chart($chartIds = null, $chartType = self::CHART_TYPE_PCHART)
{
global $beanList;
$linkedCharts = $this->get_linked_beans('aor_charts', 'AOR_Charts');
if (!$linkedCharts) {
//No charts to display
LoggerManager::getLogger()->warn('No charts to display to build report chart for AOR Report.');
return '';
}
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
$result = $this->db->query($sql);
$fields = array();
$i = 0;
$mainGroupField = null;
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$field_bean = new $beanList[$this->report_module]();
$field_module = $this->report_module;
$field_alias = $field_bean->table_name;
if ($path[0] != $this->report_module) {
foreach ($path as $rel) {
if (empty($rel)) {
continue;
}
$field_module = getRelatedModule($field_module, $rel);
$field_alias = $field_alias . ':' . $rel;
}
}
$label = str_replace(' ', '_', (string) $field->label) . $i;
$fields[$label]['field'] = $field->field;
$fields[$label]['label'] = $field->label;
$fields[$label]['display'] = $field->display;
$fields[$label]['function'] = $field->field_function;
$fields[$label]['module'] = $field_module;
$fields[$label]['alias'] = $field_alias;
$fields[$label]['link'] = $field->link;
$fields[$label]['total'] = $field->total;
$fields[$label]['format'] = $field->format;
// get the main group
if ($field->group_display) {
// if we have a main group already thats wrong cause only one main grouping field possible
if (!is_null($mainGroupField)) {
$GLOBALS['log']->fatal('main group already found');
}
$mainGroupField = $field;
}
++$i;
}
$query = $this->build_report_query();
$result = $this->db->query($query);
$data = array();
while ($row = $this->db->fetchByAssoc($result, false)) {
foreach ($fields as $name => $att) {
$currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
if ($att['function'] != 'COUNT' && empty($att['format']) && !is_numeric($row[$name])) {
$row[$name] = trim(strip_tags(getModuleField(
$att['module'],
$att['field'],
$att['field'],
'DetailView',
$row[$name],
'',
$currency_id
)));
}
}
$data[] = $row;
}
$fields = $this->getReportFields();
$html = '';
switch ($chartType) {
case self::CHART_TYPE_PCHART:
$html = '<script src="modules/AOR_Charts/lib/pChart/imagemap.js"></script>';
break;
case self::CHART_TYPE_CHARTJS:
$html = '<script src="modules/AOR_Reports/js/Chart.js"></script>';
break;
case self::CHART_TYPE_RGRAPH:
if ($_REQUEST['module'] != 'Home') {
require_once('include/SuiteGraphs/RGraphIncludes.php');
}
break;
}
$x = 0;
foreach ($linkedCharts as $chart) {
if ($chartIds !== null && !in_array($chart->id, $chartIds)) {
continue;
}
$html .= $chart->buildChartHTML($data, $fields, $x, $chartType, $mainGroupField);
$x++;
}
return $html;
}
public function buildMultiGroupReport($offset = -1, $links = true, $level = 2, $path = array())
{
global $beanList;
$rows = $this->getGroupDisplayFieldByReportId($this->id, $level);
$rowsCount = is_countable($rows) ? count($rows) : 0;
if ($rowsCount > 1) {
$GLOBALS['log']->fatal('ambiguous group display for report ' . $this->id);
} else {
if ($rowsCount == 1) {
$rows[0]['module_path'] = unserialize(base64_decode($rows[0]['module_path']));
if (!$rows[0]['module_path'][0]) {
$module = new $beanList[$this->report_module]();
$rows[0]['field_id_name'] = $module->field_defs[$rows[0]['field']]['id_name'] ? $module->field_defs[$rows[0]['field']]['id_name'] : $module->field_defs[$rows[0]['field']]['name'];
$rows[0]['module_path'][0] = $module->table_name;
} else {
$rows[0]['field_id_name'] = $rows[0]['field'];
}
$path[] = $rows[0];
if ($level > 10) {
$msg = 'Too many nested groups';
$GLOBALS['log']->fatal($msg);
return null;
}
return $this->buildMultiGroupReport($offset, $links, $level + 1, $path);
}
if (!$rows) {
if ($path) {
$html = '';
foreach ($path as $pth) {
$_fieldIdName = $this->db->quoteIdentifier($pth['field_id_name']);
$query = "SELECT $_fieldIdName FROM " . $this->db->quoteIdentifier($pth['module_path'][0]) . " GROUP BY $_fieldIdName;";
$values = $this->dbSelect($query);
foreach ($values as $value) {
$moduleFieldByGroupValue = $this->getModuleFieldByGroupValue(
$beanList,
$value[$pth['field_id_name']]
);
$moduleFieldByGroupValue = $this->addDataIdValueToInnertext($moduleFieldByGroupValue);
$html .= $this->getMultiGroupFrameHTML(
$moduleFieldByGroupValue,
$this->build_group_report($offset, $links)
);
}
}
return $html;
}
return $this->build_group_report($offset, $links, array());
}
throw new Exception('incorrect results');
}
throw new Exception('incorrect state');
}
private function getGroupDisplayFieldByReportId($reportId = null, $level = 1)
{
// set the default values
if (is_null($reportId)) {
$reportId = $this->id;
}
if (!$level) {
$level = 1;
}
// escape values for query
$_id = $this->db->quote($reportId);
$_level = (int)$level;
// get results array
$query = "SELECT id, field, module_path FROM aor_fields WHERE aor_report_id = '$_id' AND group_display = $_level AND deleted = 0;";
$rows = $this->dbSelect($query);
return $rows;
}
private function dbSelect($query)
{
$results = $this->db->query($query);
$rows = array();
while ($row = $this->db->fetchByAssoc($results)) {
$rows[] = $row;
}
return $rows;
}
private function getMultiGroupFrameHTML($header, $body)
{
$html = '<div class="multi-group-list" style="border: 1px solid black; padding: 10px;">
<h3>' . $header . '</h3>
<div class="multi-group-list-inner">' . $body . '</div>
</div>';
return $html;
}
private function addDataIdValueToInnertext($html)
{
preg_match('/\sdata-id-value\s*=\s*"([^"]*)"/', (string) $html, $match);
$html = preg_replace('/(>)([^<]*)(<\/\w+>$)/', '$1$2' . $match[1] . '$3', (string) $html);
return $html;
}
public function build_group_report($offset = -1, $links = true, $extra = array(), $subgroup = '')
{
global $beanList, $timedate, $app_strings;
$html = '';
$query = '';
$query_array = array();
$module = new $beanList[$this->report_module]();
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND group_display = 1 AND deleted = 0 ORDER BY field_order ASC";
$field_id = $this->db->getOne($sql);
if (!$field_id) {
$query_array['select'][] = $module->table_name . ".id AS '" . $module->table_name . "_id'";
}
if ($field_id != '' && empty($subgroup)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($field_id);
$field_label = str_replace(' ', '_', (string) $field->label);
$path = unserialize(base64_decode($field->module_path));
$field_module = $module;
$table_alias = $field_module->table_name;
if (!empty($path[0]) && $path[0] != $module->module_dir) {
foreach ($path as $rel) {
$new_field_module = new $beanList[getRelatedModule($field_module->module_dir, $rel)];
$oldAlias = $table_alias;
$table_alias = $table_alias . ":" . $rel;
$query_array = $this->build_report_query_join(
$rel,
$table_alias,
$oldAlias,
$field_module,
'relationship',
$query_array,
$new_field_module
);
$field_module = $new_field_module;
}
}
$data = $field_module->field_defs[$field->field];
if ($data['type'] == 'relate' && isset($data['id_name'])) {
$field->field = $data['id_name'];
}
if ($data['type'] == 'currency' && !stripos(
(string) $field->field,
'_USD'
) && isset($field_module->field_defs['currency_id'])
) {
if ((isset($field_module->field_defs['currency_id']['source']) && $field_module->field_defs['currency_id']['source'] == 'custom_fields')) {
$query_array['select'][$table_alias . '_currency_id'] = $table_alias . '_cstm' . ".currency_id AS '" . $table_alias . "_currency_id'";
} else {
$query_array['select'][$table_alias . '_currency_id'] = $table_alias . ".currency_id AS '" . $table_alias . "_currency_id'";
}
}
if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
$select_field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $field->field;
// Fix for #1251 - added a missing parameter to the function call
$query_array = $this->build_report_query_join(
$table_alias . '_cstm',
$table_alias . '_cstm',
$table_alias,
$field_module,
'custom',
$query_array
);
} else {
$select_field = $this->db->quoteIdentifier($table_alias) . '.' . $field->field;
}
if ($field->sort_by != '') {
$query_array['sort_by'][] = $field_label . ' ' . $field->sort_by;
}
if ($field->format && in_array($data['type'], array('date', 'datetime', 'datetimecombo'))) {
if (in_array($data['type'], array('datetime', 'datetimecombo'))) {
$select_field = $this->db->convert($select_field, 'add_tz_offset');
}
$select_field = $this->db->convert(
$select_field,
'date_format',
array($timedate->getCalFormat($field->format))
);
}
if ($field->field_function != null) {
$select_field = $field->field_function . '(' . $select_field . ')';
}
$query_array['group_by'][] = $select_field;
$query_array['select'][] = $select_field . " AS '" . $field_label . "'";
if (isset($extra['select']) && $extra['select']) {
foreach ($extra['select'] as $selectField => $selectAlias) {
if ($selectAlias) {
$query_array['select'][] = $selectField . " AS " . $selectAlias;
} else {
$query_array['select'][] = $selectField;
}
}
}
$query_array['where'][] = $select_field . " IS NOT NULL AND ";
if (isset($extra['where']) && $extra['where']) {
$query_array['where'][] = implode(' AND ', $extra['where']) . ' AND ';
}
$query_array = $this->build_report_query_where($query_array);
foreach ($query_array['select'] as $select) {
$query .= ($query == '' ? 'SELECT ' : ', ') . $select;
}
$query .= ' FROM ' . $module->table_name . ' ';
if (isset($query_array['join'])) {
foreach ($query_array['join'] as $join) {
$query .= $join;
}
}
if (isset($query_array['where'])) {
$query_where = '';
foreach ($query_array['where'] as $where) {
$query_where .= ($query_where == '' ? 'WHERE ' : ' ') . $where;
}
$query_where = $this->queryWhereRepair($query_where);
$query .= ' ' . $query_where;
}
if (isset($query_array['group_by'])) {
$query_group_by = '';
foreach ($query_array['group_by'] as $group_by) {
$query_group_by .= ($query_group_by == '' ? 'GROUP BY ' : ', ') . $group_by;
}
$query .= ' ' . $query_group_by;
}
if (isset($query_array['sort_by'])) {
$query_sort_by = '';
foreach ($query_array['sort_by'] as $sort_by) {
$query_sort_by .= ($query_sort_by == '' ? 'ORDER BY ' : ', ') . $sort_by;
}
$query .= ' ' . $query_sort_by;
}
$result = $this->db->query($query);
while ($row = $this->db->fetchByAssoc($result)) {
if ($html !== '') {
$html .= '<br />';
}
$groupValue = $row[$field_label];
$groupDisplay = $this->getModuleFieldByGroupValue($beanList, $groupValue);
if (empty(trim($groupValue))) {
$groupValue = '_empty';
$groupDisplay = $app_strings['LBL_NONE'];
}
// Fix #5427 If download pdf then not use tab-content and add css inline to work with mpdf
$pdf_style = "";
$action = $_REQUEST['action'];
if ($action == 'DownloadPDF') {
$pdf_style = "background: #333 !important; color: #fff !important; margin-bottom: 0px;";
}
$html .= '<div class="panel panel-default">
<div class="panel-heading" style="' . $pdf_style . '">
<a class="" role="button" data-toggle="collapse" href="#detailpanel_report_group_' . $groupValue . '" aria-expanded="false">
<div class="col-xs-10 col-sm-11 col-md-11">
' . $groupDisplay . '
</div>
</a>
</div>';
if ($action != 'DownloadPDF') {
$html .= '<div class="panel-body panel-collapse collapse in" id="detailpanel_report_group_' . $groupValue . '">
<div class="tab-content">';
} else {
$html .= '</div>';
}
$html .= $this->build_report_html($offset, $links, $groupValue, create_guid(), $extra);
$html .= ($action == 'downloadPDF') ? '' : '</div></div></div>';
// End
}
}
if ($html == '') {
$html = $this->build_report_html($offset, $links, $subgroup, create_guid(), $extra);
}
return $html;
}
public function build_report_html($offset = -1, $links = true, $group_value = '', $tableIdentifier = '', $extra = array())
{
global $beanList, $sugar_config;
$_group_value = $this->db->quote($group_value);
$report_sql = $this->build_report_query($_group_value, $extra);
// Fix for issue 1232 - items listed in a single report, should adhere to the same standard as ListView items.
if ($sugar_config['list_max_entries_per_page'] != '') {
$max_rows = $sugar_config['list_max_entries_per_page'];
} else {
$max_rows = 20;
}
// See if the report actually has any fields, if not we don't want to run any queries since we can't show anything
$fieldCount = is_countable($this->getReportFields()) ? count($this->getReportFields()) : 0;
if (!$fieldCount) {
$GLOBALS['log']->info('Running report "' . $this->name . '" with 0 fields');
}
$total_rows = 0;
if ($fieldCount) {
$count_sql = explode('ORDER BY', $report_sql);
$count_query = 'SELECT count(*) c FROM (' . $count_sql[0] . ') as n';
// We have a count query. Run it and get the results.
$result = $this->db->query($count_query);
$assoc = $this->db->fetchByAssoc($result);
if (!empty($assoc['c'])) {
$total_rows = $assoc['c'];
}
}
$html = '<div class="list-view-rounded-corners">';
$html.='<table id="report_table_'.$tableIdentifier.$group_value.'" width="100%" border="0" class="list view table-responsive aor_reports">';
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
$result = $this->db->query($sql);
$html .= '<thead>';
$html .= '<tr>';
$fields = array();
$i = 0;
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$field_bean = new $beanList[$this->report_module]();
$field_module = $this->report_module;
$field_alias = $field_bean->table_name;
if ($path[0] != $this->report_module) {
foreach ($path as $rel) {
if (empty($rel)) {
continue;
}
$field_module = getRelatedModule($field_module, $rel);
$field_alias = $field_alias . ':' . $rel;
}
}
$label = str_replace(' ', '_', (string) $field->label) . $i;
$fields[$label]['field'] = $field->field;
$fields[$label]['label'] = $field->label;
$fields[$label]['display'] = $field->display;
$fields[$label]['function'] = $field->field_function;
$fields[$label]['module'] = $field_module;
$fields[$label]['alias'] = $field_alias;
$fields[$label]['link'] = $field->link;
$fields[$label]['total'] = $field->total;
$fields[$label]['format'] = $field->format;
$fields[$label]['params'] = [];
if ($fields[$label]['display']) {
// Fix #5427
$html .= "<th scope='col'>";
// End
$html .= "<div>";
$html .= $field->label;
$html .= "</div></th>";
}
++$i;
}
$html .= '</tr>';
if ($offset >= 0) {
$start = 0;
$end = 0;
$previous_offset = 0;
$next_offset = 0;
$last_offset = 0;
if ($total_rows > 0) {
$start = $offset + 1;
$end = (($offset + $max_rows) < $total_rows) ? $offset + $max_rows : $total_rows;
$previous_offset = ($offset - $max_rows) < 0 ? 0 : $offset - $max_rows;
$next_offset = $offset + $max_rows;
if (is_int($total_rows / $max_rows)) {
$last_offset = $max_rows * ($total_rows / $max_rows - 1);
} else {
$last_offset = $max_rows * floor($total_rows / $max_rows);
}
}
$html .= '<tr id="pagination" class="pagination-unique" role="presentation">';
$html .= "<td colspan='$i'>
<table class='paginationTable' border='0' cellpadding='0' cellspacing='0' width='100%'>
<td nowrap=\"nowrap\" class=\"paginationActionButtons\" ></td>";
$html .= '<td nowrap="nowrap" align="right" class="paginationChangeButtons" width="1%">';
if ($offset == 0) {
$html .= "<button type='button' id='listViewStartButton_top' name='listViewStartButton' title='Start' class='list-view-pagination-button' disabled='disabled'>
<span class='suitepicon suitepicon-action-first'></span>
</button>
<button type='button' id='listViewPrevButton_top' name='listViewPrevButton' class='list-view-pagination-button' title='Previous' disabled='disabled'>
<span class='suitepicon suitepicon-action-left'></span>
</button>";
} else {
$html .= "<button type='button' id='listViewStartButton_top' name='listViewStartButton' title='Start' class='list-view-pagination-button' onclick='changeReportPage(\"" . $this->id . '",0,"' . $group_value . '","' . $tableIdentifier . "\")'>
<span class='suitepicon suitepicon-action-first'></span>
</button>
<button type='button' id='listViewPrevButton_top' name='listViewPrevButton' class='list-view-pagination-button' title='Previous' onclick='changeReportPage(\"" . $this->id . '",' . $previous_offset . ',"' . $group_value . '","' . $tableIdentifier . "\")'>
<span class='suitepicon suitepicon-action-left'></span>
</button>";
}
$html .= '</td><td style="vertical-align:middle" nowrap="nowrap" width="1%" class="paginationActionButtons">';
$html .= ' <div class="pageNumbers">(' . $start . ' - ' . $end . ' of ' . $total_rows . ')</div>';
$html .= '</td><td nowrap="nowrap" align="right" class="paginationActionButtons" width="1%">';
if ($next_offset < $total_rows) {
$html .= "<button type='button' id='listViewNextButton_top' name='listViewNextButton' title='Next' class='list-view-pagination-button' onclick='changeReportPage(\"" . $this->id . '",' . $next_offset . ',"' . $group_value . '","' . $tableIdentifier . "\")'>
<span class='suitepicon suitepicon-action-right'></span>
</button>
<button type='button' id='listViewEndButton_top' name='listViewEndButton' title='End' class='list-view-pagination-button' onclick='changeReportPage(\"" . $this->id . '",' . $last_offset . ',"' . $group_value . '","' . $tableIdentifier . "\")'>
<span class='suitepicon suitepicon-action-last'></span>
</button>";
} else {
$html .= "<button type='button' id='listViewNextButton_top' name='listViewNextButton' title='Next' class='list-view-pagination-button' disabled='disabled'>
<span class='suitepicon suitepicon-action-right'></span>
</button>
<button type='button' id='listViewEndButton_top' name='listViewEndButton' title='End' class='list-view-pagination-button' disabled='disabled'>
<span class='suitepicon suitepicon-action-last'></span>
</button>";
}
$html .= '</td><td nowrap="nowrap" width="4px" class="paginationActionButtons"></td>
</table>
</td>';
$html .= '</tr>';
}
$html .= '</thead>';
$html .= '<tbody>';
if ($fieldCount) {
if ($offset >= 0) {
$result = $this->db->limitQuery($report_sql, $offset, $max_rows);
} else {
$result = $this->db->query($report_sql);
}
}
$row_class = 'oddListRowS1';
$totals = array();
while ($fieldCount && $row = $this->db->fetchByAssoc($result)) {
$html .= "<tr class='" . $row_class . "' height='20'>";
foreach ($fields as $name => $att) {
if ($att['display']) {
$html .= "<td class='' valign='top' align='left'>";
if ($att['link'] && $links) {
$html .= "<a href='" . $sugar_config['site_url'] . "/index.php?module=" . $att['module'] . "&action=DetailView&record=" . $row[$att['alias'] . '_id'] . "'>";
}
$currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
if ($att['function'] == 'COUNT' || !empty($att['format'])) {
$html .= $row[$name];
} else {
// Make sure the `{$module}_id` key exists on $row, to prevent PHP notices.
if (isset($row[$att['alias'] . '_id'])) {
$params = array('record_id' => $row[$att['alias'] . '_id']);
} else {
$params = [];
}
$html .= trim(getModuleField(
$att['module'],
$att['field'],
$att['field'],
'DetailView',
$row[$name],
'',
$currency_id,
$params
));
}
if ($att['total']) {
$totals[$name][] = $row[$name];
}
if ($att['link'] && $links) {
$html .= "</a>";
}
$html .= "</td>";
}
}
$html .= "</tr>";
$row_class = $row_class == 'oddListRowS1' ? 'evenListRowS1' : 'oddListRowS1';
}
$html .= "</tbody>";
$html .= $this->getTotalHTML($fields, $totals);
$html .= '</table>';
$html .= '</div>';
$currentTheme = SugarThemeRegistry::current();
if (empty($_REQUEST['action']) || $_REQUEST['action'] !== 'DownloadPDF') {
$html .= " <script type=\"text/javascript\">
groupedReportToggler = {
toggleList: function(elem) {
$(elem).closest('table.list').find('thead, tbody').each(function(i, e){
if(i>1) {
$(e).toggle();
}
});
if($(elem).find('img').first().attr('src') == '" . $currentTheme->getImageURL('basic_search.gif') . "') {
$(elem).find('img').first().attr('src', '" . $currentTheme->getImageURL('advanced_search.gif') . "');
}
else {
$(elem).find('img').first().attr('src', '" . $currentTheme->getImageURL('basic_search.gif') . "');
}
}
};
</script>";
}
return $html;
}
private function getModuleFieldByGroupValue($beanList, $group_value)
{
global $app_list_strings;
$moduleFieldByGroupValues = array();
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND group_display = 1 AND deleted = 0 ORDER BY field_order ASC";
$result = $this->db->limitQuery($sql, 0, 1);
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
if ($field->field_function != 'COUNT' || $field->format != '') {
// Fix grouping on assignment displays ID and not name #5427
$report_bean = BeanFactory::getBean($this->report_module);
$field_def = $report_bean->field_defs[$field->field];
if ($field_def['type'] == 'relate' && isset($field_def['id_name'])) {
$related_bean = BeanFactory::getBean($field_def['module']);
$related_bean->retrieve($group_value);
$moduleFieldByGroupValues[] = ($related_bean instanceof Person) ? $related_bean->full_name : $related_bean->name;
} elseif ($field_def['type'] == 'enum') {
$moduleFieldByGroupValues[] = $app_list_strings[$field_def['options']][$group_value];
} else {
$moduleFieldByGroupValues[] = $group_value;
}
continue;
// End
}
$path = unserialize(base64_decode($field->module_path));
$field_bean = new $beanList[$this->report_module]();
$field_module = $this->report_module;
$field_alias = $field_bean->table_name;
if ($path[0] != $this->report_module) {
foreach ($path as $rel) {
if (empty($rel)) {
continue;
}
$field_module = getRelatedModule($field_module, $rel);
$field_alias = $field_alias . ':' . $rel;
}
}
$currency_id = isset($row[$field_alias . '_currency_id']) ? $row[$field_alias . '_currency_id'] : '';
$moduleFieldByGroupValues[] = getModuleField(
$this->report_module,
$field->field,
$field->field,
'DetailView',
$group_value,
'',
$currency_id
);
}
$moduleFieldByGroupValue = implode(', ', $moduleFieldByGroupValues);
return $moduleFieldByGroupValue;
}
public function getTotalHTML($fields, $totals)
{
global $app_list_strings;
$currency = BeanFactory::newBean('Currencies');
$currency->retrieve($GLOBALS['current_user']->getPreference('currency'));
$showTotal = false;
foreach ($fields as $label => $field) {
if (!$field['display']) {
continue;
}
if (!empty($field['total'])) {
$showTotal = true;
}
}
if (!$showTotal) {
return '';
}
$html = "<tr class='totalReportRow oddListRowS1'>";
foreach ($fields as $label => $field) {
if (!$field['display']) {
continue;
}
if ($field['total'] && isset($totals[$label])) {
$type = $field['total'];
$total = $this->calculateTotal($type, $totals[$label]);
$params = isset($field['params']) ? $field['params'] : [];
switch ($type) {
case 'SUM':
case 'AVG':
$total = getModuleField(
$field['module'],
$field['field'],
$field['field'],
'DetailView',
$total,
'',
$currency->id,
$params
);
break;
case 'COUNT':
default:
break;
}
$html .= '<td>' . $total . '</td>';
} else {
$html .= '<td></td>';
}
}
$html .= '</tr>';
return $html;
}
public function calculateTotal($type, $totals)
{
$totalCount = is_countable($totals) ? count($totals) : 0;
switch ($type) {
case 'SUM':
return array_sum($totals);
case 'COUNT':
return $totalCount;
case 'AVG':
return array_sum($totals) / $totalCount;
default:
return '';
}
}
/**
* @param string $field
* @return string
*/
private function encloseForCSV($field)
{
$cleanCSV = new CleanCSV();
return '"' . $cleanCSV->escapeField($field) . '"';
}
public function build_report_csv()
{
global $beanList;
ini_set('zlib.output_compression', 'Off');
ob_start();
require_once('include/export_utils.php');
$delimiter = getDelimiter();
$csv = '';
//text/comma-separated-values
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
$result = $this->db->query($sql);
$fields = array();
$field = null;
$i = 0;
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$path = unserialize(base64_decode($field->module_path));
$field_bean = new $beanList[$this->report_module]();
$field_module = $this->report_module;
$field_alias = $field_bean->table_name;
if ($path[0] != $this->report_module) {
foreach ($path as $rel) {
if (empty($rel)) {
continue;
}
$field_module = getRelatedModule($field_module, $rel);
$field_alias = $field_alias . ':' . $rel;
}
}
$label = str_replace(' ', '_', (string) $field->label) . $i;
$fields[$label]['field'] = $field->field;
$fields[$label]['display'] = $field->display;
$fields[$label]['function'] = $field->field_function;
$fields[$label]['module'] = $field_module;
$fields[$label]['alias'] = $field_alias;
$fields[$label]['format'] = $field->format;
if ($field->display) {
$csv .= $this->encloseForCSV($field->label);
$csv .= $delimiter;
}
++$i;
}
// Remove last delimiter of the line
if ($field->display) {
$csv = substr($csv, 0, strlen($csv) - strlen((string) $delimiter));
}
$sql = $this->build_report_query();
$result = $this->db->query($sql);
while ($row = $this->db->fetchByAssoc($result, false)) {
$csv .= "\r\n";
foreach ($fields as $name => $att) {
$currency_id = isset($row[$att['alias'] . '_currency_id']) ? $row[$att['alias'] . '_currency_id'] : '';
if ($att['display']) {
if ($att['function'] != '' || $att['format'] != '') {
$csv .= $this->encloseForCSV($row[$name]);
} else {
$t = getModuleField(
$att['module'],
$att['field'],
$att['field'],
'DetailView',
$row[$name],
'',
$currency_id
);
if (false !== strpos((string) $t, 'checkbox')) {
$csv .= $row[$name];
} else {
$csv .= $this->encloseForCSV(trim(strip_tags($t)));
}
}
$csv .= $delimiter;
}
}
// Remove last delimiter of the line
$csv = substr($csv, 0, strlen($csv) - strlen((string) $delimiter));
}
ob_clean();
printCSV($csv, $this->name);
sugar_cleanup(true);
}
public function build_report_query($group_value = '', $extra = array())
{
global $beanList;
$module = new $beanList[$this->report_module]();
$query = '';
$query_array = array();
//Check if the user has access to the target module
if (!(ACLController::checkAccess($this->report_module, 'list', true))) {
return false;
}
$query_array = $this->build_report_query_select($query_array, $group_value);
if (isset($extra['where']) && $extra['where']) {
$query_array['where'][] = implode(' AND ', $extra['where']) . ' AND ';
}
$query_array = $this->build_report_query_where($query_array);
if (!isset($query_array['select'])) {
LoggerManager::getLogger()->warn('Trying to build report query without database select definition.');
} else {
foreach ($query_array['select'] as $select) {
$query .= ($query == '' ? 'SELECT ' : ', ') . $select;
}
}
if (empty($query_array['group_by'])) {
foreach ($query_array['id_select'] as $select) {
if (!$query) {
$query = 'SELECT ' . $select;
} else {
$query .= ', ' . $select;
}
}
}
$query .= ' FROM ' . $this->db->quoteIdentifier($module->table_name) . ' ';
if (isset($query_array['join'])) {
foreach ($query_array['join'] as $join) {
$query .= $join;
}
}
if (isset($query_array['where'])) {
$query_where = '';
foreach ($query_array['where'] as $where) {
$query_where .= ($query_where == '' ? 'WHERE ' : ' ') . $where;
}
$query_where = $this->queryWhereRepair($query_where);
$query .= ' ' . $query_where;
}
if (isset($query_array['group_by'])) {
$query_group_by = '';
foreach ($query_array['group_by'] as $group_by) {
$query_group_by .= ($query_group_by == '' ? 'GROUP BY ' : ', ') . $group_by;
}
if (isset($query_array['second_group_by']) && $query_group_by != '') {
foreach ($query_array['second_group_by'] as $group_by) {
$query_group_by .= ', ' . $group_by;
}
}
$query .= ' ' . $query_group_by;
}
if (isset($query_array['sort_by'])) {
$query_sort_by = '';
foreach ($query_array['sort_by'] as $sort_by) {
$query_sort_by .= ($query_sort_by == '' ? 'ORDER BY ' : ', ') . $sort_by;
}
$query .= ' ' . $query_sort_by;
}
return $query;
}
private function queryWhereRepair($query_where)
{
// remove empty parenthesis and fix query syntax
$safe = 0;
$query_where_clean = '';
while ($query_where_clean != $query_where) {
$query_where_clean = $query_where;
$query_where = preg_replace('/\b(AND|OR)\s*\(\s*\)|[^\w+\s*]\(\s*\)/i', '', (string) $query_where_clean);
$safe++;
if ($safe > 100) {
$GLOBALS['log']->fatal('Invalid report query conditions');
break;
}
}
return $query_where;
}
public function build_report_query_select($query = array(), $group_value = '')
{
global $beanList, $timedate;
if ($beanList[$this->report_module]) {
$module = new $beanList[$this->report_module]();
$query['id_select'][$module->table_name] = $this->db->quoteIdentifier($module->table_name) . ".id AS '" . $module->table_name . "_id'";
$query['id_select_group'][$module->table_name] = $this->db->quoteIdentifier($module->table_name) . ".id";
$sql = "SELECT id FROM aor_fields WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY field_order ASC";
$result = $this->db->query($sql);
$i = 0;
while ($row = $this->db->fetchByAssoc($result)) {
$field = BeanFactory::newBean('AOR_Fields');
$field->retrieve($row['id']);
$field->label = str_replace(' ', '_', (string) $field->label) . $i;
$path = unserialize(base64_decode($field->module_path));
$field_module = $module;
$table_alias = $field_module->table_name;
$oldAlias = $table_alias;
if (!empty($path[0]) && $path[0] != $module->module_dir) {
foreach ($path as $rel) {
$new_field_module = new $beanList[getRelatedModule($field_module->module_dir, $rel)];
$oldAlias = $table_alias;
$table_alias = $table_alias . ":" . $rel;
$query =
$this->build_report_query_join(
$rel,
$table_alias,
$oldAlias,
$field_module,
'relationship',
$query,
$new_field_module
);
$field_module = $new_field_module;
}
}
$data = $field_module->field_defs[$field->field];
if ($data['type'] == 'relate' && isset($data['id_name'])) {
$field->field = $data['id_name'];
$data_new = $field_module->field_defs[$field->field];
if (isset($data_new['source']) && $data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
$data_new['type'] = 'link';
$data_new['relationship'] = $data['link'];
}
$data = $data_new;
}
if ($data['type'] == 'link' && $data['source'] == 'non-db') {
$new_field_module = new $beanList[getRelatedModule(
$field_module->module_dir,
$data['relationship']
)];
$table_alias = $data['relationship'];
$query = $this->build_report_query_join(
$data['relationship'],
$table_alias,
$oldAlias,
$field_module,
'relationship',
$query,
$new_field_module
);
$field_module = $new_field_module;
$field->field = 'id';
}
if ($data['type'] == 'currency' && isset($field_module->field_defs['currency_id']) && !stripos((string) $field->field,'_USD')) {
if ((isset($field_module->field_defs['currency_id']['source']) && $field_module->field_defs['currency_id']['source'] == 'custom_fields')) {
$query['select'][$table_alias . '_currency_id'] = $this->db->quoteIdentifier($table_alias . '_cstm') . ".currency_id AS '" . $table_alias . "_currency_id'";
$query['second_group_by'][] = $this->db->quoteIdentifier($table_alias . '_cstm') . ".currency_id";
} else {
$query['select'][$table_alias . '_currency_id'] = $this->db->quoteIdentifier($table_alias) . ".currency_id AS '" . $table_alias . "_currency_id'";
$query['second_group_by'][] = $this->db->quoteIdentifier($table_alias) . ".currency_id";
}
}
if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
$select_field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $field->field;
$query = $this->build_report_query_join(
$table_alias . '_cstm',
$table_alias . '_cstm',
$table_alias,
$field_module,
'custom',
$query
);
} else {
$select_field = $this->db->quoteIdentifier($table_alias) . '.' . $field->field;
}
$select_field_db = $select_field;
if ($field->format && in_array($data['type'], array('date', 'datetime', 'datetimecombo'))) {
if (in_array($data['type'], array('datetime', 'datetimecombo'))) {
$select_field = $this->db->convert($select_field, 'add_tz_offset');
}
$select_field = $this->db->convert(
$select_field,
'date_format',
array($timedate->getCalFormat($field->format))
);
}
if ($field->link && isset($query['id_select'][$table_alias])) {
$query['select'][] = $query['id_select'][$table_alias];
$query['second_group_by'][] = $query['id_select_group'][$table_alias];
unset($query['id_select'][$table_alias]);
}
if ($field->group_by == 1) {
$query['group_by'][] = $select_field;
} elseif ($field->field_function != null) {
$select_field = $field->field_function . '(' . $select_field . ')';
} else {
$query['second_group_by'][] = $select_field;
}
if ($field->sort_by != '') {
// If the field is a date, sort by the natural date and not the user-formatted date
if ($data['type'] == 'date' || $data['type'] == 'datetime') {
$query['sort_by'][] = $select_field_db . " " . $field->sort_by;
} else {
$query['sort_by'][] = $select_field . " " . $field->sort_by;
}
}
$query['select'][] = $select_field . " AS '" . $field->label . "'";
if ($field->group_display == 1 && $group_value) {
if ($group_value === '_empty') {
$query['where'][] = '(' . $select_field . " = '' OR " . $select_field . ' IS NULL) AND ';
} else {
$query['where'][] = $select_field . " = '" . $group_value . "' AND ";
}
}
++$i;
}
}
return $query;
}
public function build_report_query_join(
$name,
$alias,
$parentAlias,
SugarBean $module,
$type,
$query = array(),
SugarBean $rel_module = null
) {
// Alias to keep lines short
$db = $this->db;
$params = [];
if (!isset($query['join'][$alias])) {
switch ($type) {
case 'custom':
$customTable = $module->get_custom_table_name();
$query['join'][$alias] =
'LEFT JOIN ' .
$db->quoteIdentifier($customTable) .' '. $db->quoteIdentifier($alias) .
' ON ' .
$db->quoteIdentifier($parentAlias) . '.id = ' . $db->quoteIdentifier($name) . '.id_c ';
break;
case 'relationship':
if ($module->load_relationship($name)) {
$params['join_type'] = 'LEFT JOIN';
if ($module->$name->relationship_type != 'one-to-many') {
if ($module->$name->getSide() == REL_LHS) {
$params['right_join_table_alias'] = $db->quoteIdentifier($alias);
$params['join_table_alias'] = $db->quoteIdentifier($alias);
$params['left_join_table_alias'] = $db->quoteIdentifier($parentAlias);
} else {
$params['right_join_table_alias'] = $db->quoteIdentifier($parentAlias);
$params['join_table_alias'] = $db->quoteIdentifier($alias);
$params['left_join_table_alias'] = $db->quoteIdentifier($alias);
}
} else {
$params['right_join_table_alias'] = $db->quoteIdentifier($parentAlias);
$params['join_table_alias'] = $db->quoteIdentifier($alias);
$params['left_join_table_alias'] = $db->quoteIdentifier($parentAlias);
}
$linkAlias = $parentAlias . "|" . $alias;
$params['join_table_link_alias'] = $db->quoteIdentifier($linkAlias);
$join = $module->$name->getJoin($params, true);
$query['join'][$alias] = $join['join'];
if ($rel_module != null) {
$query['join'][$alias] .= $this->build_report_access_query(
$rel_module,
$db->quoteIdentifier($alias)
);
}
$query['id_select'][$alias] = $join['select'] . " AS '" . $alias . "_id'";
$query['id_select_group'][$alias] = $join['select'];
}
break;
default:
break;
}
}
return $query;
}
public function build_report_access_query(SugarBean $module, $alias)
{
$tempTableName = $module->table_name;
$module->table_name = $alias;
$where = $module->buildAccessWhere('list');
if (!empty($where)) {
$where = ' AND ' . $where;
}
$module->table_name = $tempTableName;
return $where;
}
/**
* @param array $query
* @return array
*/
public function build_report_query_where($query = array())
{
global $beanList, $app_list_strings, $sugar_config, $timedate;
$aor_sql_operator_list = [];
$aor_sql_operator_list['Equal_To'] = '=';
$aor_sql_operator_list['Not_Equal_To'] = '!=';
$aor_sql_operator_list['Greater_Than'] = '>';
$aor_sql_operator_list['Less_Than'] = '<';
$aor_sql_operator_list['Greater_Than_or_Equal_To'] = '>=';
$aor_sql_operator_list['Less_Than_or_Equal_To'] = '<=';
$aor_sql_operator_list['Contains'] = 'LIKE';
$aor_sql_operator_list['Starts_With'] = 'LIKE';
$aor_sql_operator_list['Ends_With'] = 'LIKE';
$closure = false;
if (!empty($query['where'])) {
$query['where'][] = '(';
$closure = true;
}
if ($beanList[$this->report_module]) {
$module = new $beanList[$this->report_module]();
$sql = "SELECT id FROM aor_conditions WHERE aor_report_id = '" . $this->id . "' AND deleted = 0 ORDER BY condition_order ASC";
$result = $this->db->query($sql);
$tiltLogicOp = true;
while ($row = $this->db->fetchByAssoc($result)) {
$condition = BeanFactory::newBean('AOR_Conditions');
$condition->retrieve($row['id']);
$path = unserialize(base64_decode($condition->module_path));
$condition_module = $module;
$table_alias = $condition_module->table_name;
$oldAlias = $table_alias;
if (!empty($path[0]) && $path[0] != $module->module_dir) {
foreach ($path as $rel) {
if (empty($rel)) {
continue;
}
// Bug: Prevents relationships from loading.
$new_condition_module = new $beanList[getRelatedModule($condition_module->module_dir, $rel)];
//Check if the user has access to the related module
if (!(ACLController::checkAccess($new_condition_module->module_name, 'list', true))) {
return false;
}
$oldAlias = $table_alias;
$table_alias = $table_alias . ":" . $rel;
$query = $this->build_report_query_join(
$rel,
$table_alias,
$oldAlias,
$condition_module,
'relationship',
$query,
$new_condition_module
);
$condition_module = $new_condition_module;
}
}
if (isset($aor_sql_operator_list[$condition->operator])) {
$where_set = false;
$data = $condition_module->field_defs[$condition->field];
if ($data['type'] == 'relate' && isset($data['id_name'])) {
$condition->field = $data['id_name'];
$data_new = $condition_module->field_defs[$condition->field];
if (!empty($data_new['source']) && $data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
$data_new['type'] = 'link';
$data_new['relationship'] = $data['link'];
}
$data = $data_new;
}
if ($data['type'] == 'link' && $data['source'] == 'non-db') {
$new_field_module = new $beanList[getRelatedModule(
$condition_module->module_dir,
$data['relationship']
)];
$table_alias = $data['relationship'];
$query = $this->build_report_query_join(
$data['relationship'],
$table_alias,
$oldAlias,
$condition_module,
'relationship',
$query,
$new_field_module
);
$condition_module = $new_field_module;
// Debugging: security groups conditions - It's a hack to just get the query working
if ($condition_module->module_dir = 'SecurityGroups' && (is_countable($path) ? count($path) : 0) > 1) {
$table_alias = $oldAlias . ':' . $rel;
}
$condition->field = 'id';
}
if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
$field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $condition->field;
$query = $this->build_report_query_join(
$table_alias . '_cstm',
$table_alias . '_cstm',
$table_alias,
$condition_module,
'custom',
$query
);
} else {
$field = $this->db->quoteIdentifier($table_alias) . '.' . $condition->field;
}
if (!empty($this->user_parameters[$condition->id]) && $condition->parameter) {
$condParam = $this->user_parameters[$condition->id];
$condition->value = $condParam['value'];
$condition->operator = $condParam['operator'];
$condition->value_type = $condParam['type'];
}
$value = '';
switch ($condition->value_type) {
case 'Field':
$data = $condition_module->field_defs[$condition->value];
if ($data['type'] == 'relate' && isset($data['id_name'])) {
$condition->value = $data['id_name'];
$data_new = $condition_module->field_defs[$condition->value];
if ($data_new['source'] == 'non-db' && $data_new['type'] != 'link' && isset($data['link'])) {
$data_new['type'] = 'link';
$data_new['relationship'] = $data['link'];
}
$data = $data_new;
}
if ($data['type'] == 'link' && $data['source'] == 'non-db') {
$new_field_module = new $beanList[getRelatedModule(
$condition_module->module_dir,
$data['relationship']
)];
$table_alias = $data['relationship'];
$query = $this->build_report_query_join(
$data['relationship'],
$table_alias,
$oldAlias,
$condition_module,
'relationship',
$query,
$new_field_module
);
$condition_module = $new_field_module;
$condition->field = 'id';
}
if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
$value = $condition_module->table_name . '_cstm.' . $condition->value;
$query = $this->build_report_query_join(
$condition_module->table_name . '_cstm',
$table_alias . '_cstm',
$table_alias,
$condition_module,
'custom',
$query
);
} else {
$value = ($table_alias ? $this->db->quoteIdentifier($table_alias) : $condition_module->table_name) . '.' . $condition->value;
}
break;
case 'Date':
$params = unserialize(base64_decode($condition->value));
// Fix for issue #1272 - AOR_Report module cannot update Date type parameter.
if ($params == false) {
$params = $condition->value;
}
if ($params[0] == 'now') {
if ($sugar_config['dbconfig']['db_type'] == 'mssql') {
$value = 'GetDate()';
} else {
$value = 'NOW()';
}
} else {
if ($params[0] == 'today') {
if ($sugar_config['dbconfig']['db_type'] == 'mssql') {
//$field =
$value = 'CAST(GETDATE() AS DATE)';
} else {
$field = 'DATE(' . $field . ')';
$value = 'Curdate()';
}
} else {
$data = $condition_module->field_defs[$params[0]];
if ((isset($data['source']) && $data['source'] == 'custom_fields')) {
$value = $condition_module->table_name . '_cstm.' . $params[0];
$query = $this->build_report_query_join(
$condition_module->table_name . '_cstm',
$table_alias . '_cstm',
$table_alias,
$condition_module,
'custom',
$query
);
} else {
$value = $condition_module->table_name . '.' . $params[0];
}
}
}
if ($params[1] !== 'now') {
switch ($params[3]) {
case 'business_hours';
if ($params[0] === 'now') {
$businessHours = BeanFactory::getBean('AOBH_BusinessHours');
$amount = $params[2];
if ($params[1] !== 'plus') {
$amount = 0 - $amount;
}
$value = $businessHours->addBusinessHours($amount);
$value = "'" . $timedate->asDb($value) . "'";
break;
}
$params[3] = 'hour';
default:
if ($sugar_config['dbconfig']['db_type'] === 'mssql') {
$value = "DATEADD(" . $params[3] . ", " . $app_list_strings['aor_date_operator'][$params[1]] . " $params[2], $value)";
} else {
$value = "DATE_ADD($value, INTERVAL " . $app_list_strings['aor_date_operator'][$params[1]] . " $params[2] " . $params[3] . ")";
}
break;
}
}
break;
case 'Multi':
$sep = ' AND ';
if ($condition->operator == 'Equal_To') {
$sep = ' OR ';
}
$multi_values = unencodeMultienum($condition->value);
if (!empty($multi_values)) {
$value = '(';
if ($data['type'] == 'multienum') {
$multi_operator = $condition->operator == 'Equal_To' ? 'LIKE' : 'NOT LIKE';
foreach ($multi_values as $multi_value) {
if ($value != '(') {
$value .= $sep;
}
$value .= $field . ' ' . $multi_operator . ' \'%' . $this->db->quote(encodeMultienumValue(array($multi_value))) . '%\'';
}
} else {
foreach ($multi_values as $multi_value) {
if ($value != '(') {
$value .= $sep;
}
$value .= $field . ' ' . $aor_sql_operator_list[$condition->operator] . " '" . $multi_value . "'";
}
}
$value .= ')';
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $value;
}
$where_set = true;
break;
case "Period":
if (array_key_exists($condition->value, $app_list_strings['date_time_period_list'])) {
$params = $condition->value;
} else {
$params = base64_decode($condition->value);
}
$value = '"' . getPeriodDate($params, $data['type'])->format('Y-m-d H:i:s') . '"';
break;
case "CurrentUserID":
global $current_user;
$value = '"' . $current_user->id . '"';
break;
case 'Value':
$utc = new DateTimeZone("UTC");
$dateTime = DateTime::createFromFormat('Y-m-d H:i:s', $condition->value, $utc);
if ($condition->operator === 'Equal_To') {
if ($dateTime !== false) {
$day_ahead = $dateTime->modify('+1 day');
$equal_query = "( $field BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$equal_query = "( $field BETWEEN '" . $this->db->quote($query_date);
$day_ahead = $dateTime->modify('+1 day');
$equal_query .= "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} elseif ($condition->operator === 'Not_Equal_To') {
if ($dateTime !== false) {
$day_ahead = $dateTime->modify('+1 day');
$not_equal_query = "( $field NOT BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $not_equal_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$not_equal_query = "( $field NOT BETWEEN '" . $this->db->quote($query_date);
$day_ahead = $dateTime->modify('+1 day');
$not_equal_query .= "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $not_equal_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} elseif ($condition->operator === 'Greater_Than') {
if ($dateTime !== false) {
$greater_than_query = "( $field > '" . $this->db->quote($condition->value) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $greater_than_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$greater_than_query = "( $field > '" . $this->db->quote($query_date) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $greater_than_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} elseif ($condition->operator === 'Less_Than') {
if ($dateTime !== false) {
$less_than_query = "( $field < '" . $this->db->quote($condition->value) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $less_than_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$less_than_query = "( $field < '" . $this->db->quote($query_date) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $less_than_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} elseif ($condition->operator === 'Greater_Than_or_Equal_To') {
if ($dateTime !== false) {
$equal_greater_than_query = "( $field > '" . $this->db->quote($condition->value) . "'";
$day_ahead = $dateTime->modify('+1 day');
$equal_greater_than_query .= " OR $field BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_greater_than_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$equal_greater_than_query = "( $field > '" . $this->db->quote($query_date) . "'";
$day_ahead = $dateTime->modify('+1 day');
$equal_greater_than_query .= " OR $field BETWEEN '" . $this->db->quote($query_date) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_greater_than_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} elseif ($condition->operator === 'Less_Than_or_Equal_To') {
if ($dateTime !== false) {
$equal_less_than_query = "( $field < '" . $this->db->quote($condition->value) . "'";
$day_ahead = $dateTime->modify('+1 day');
$equal_less_than_query .= " OR $field BETWEEN '" . $this->db->quote($condition->value) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_less_than_query;
} elseif ($dateTime === false && $data['type'] === 'datetime') { // check for incorrectly converted dateTime
$dateTime = convertToDateTime($condition->value);
$query_date = $dateTime->format('Y-m-d H:i:s');
$equal_less_than_query = "( $field < '" . $this->db->quote($query_date) . "'";
$day_ahead = $dateTime->modify('+1 day');
$equal_less_than_query .= " OR $field BETWEEN '" . $this->db->quote($query_date) . "' AND '" . $this->db->quote($day_ahead->format('Y-m-d H:i:s')) . "' ) ";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $equal_less_than_query;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
$where_set = true;
} else {
$value = "'" . $this->db->quote($condition->value) . "'";
}
break;
default:
$value = "'" . $this->db->quote($condition->value) . "'";
break;
}
//handle like conditions
switch ($condition->operator) {
case 'Contains':
$value = "CONCAT('%', " . $value . " ,'%')";
break;
case 'Starts_With':
$value = "CONCAT(" . $value . " ,'%')";
break;
case 'Ends_With':
$value = "CONCAT('%', " . $value . ")";
break;
}
if ($condition->value_type == 'Value' && !$condition->value && $condition->operator == 'Equal_To') {
if (!isset($value)) {
$GLOBALS['log']->warn(
$condition->field
. ' value is not set, assuming empty string value'
);
$value = '';
}
$value = "{$value} OR {$field} IS NULL)";
$field = "(" . $field;
}
if (!$where_set) {
if ($condition->value_type == "Period") {
if (array_key_exists($condition->value, $app_list_strings['date_time_period_list'])) {
$params = $condition->value;
} else {
$params = base64_decode($condition->value);
}
$date = getPeriodEndDate($params, $data['type'])->format('Y-m-d H:i:s');
$value = "'" . $this->db->quote(getPeriodDate($params, $data['type'])->format('Y-m-d H:i:s')) . "'";
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND '));
$tiltLogicOp = false;
switch ($aor_sql_operator_list[$condition->operator]) {
case "=":
$query['where'][] = $field . " BETWEEN " . $value . " AND " . "'" . $this->db->quote($date) . "'";
break;
case "!=":
$query['where'][] = $field . " NOT BETWEEN " . $value . " AND " . "'" . $this->db->quote($date) . "'";
break;
case ">":
case "<":
case ">=":
case "<=":
$query['where'][] = $field . ' ' . $aor_sql_operator_list[$condition->operator] . ' ' . $value;
break;
}
} else {
if (!$where_set) {
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . $field . ' ' . $aor_sql_operator_list[$condition->operator] . ' ' . $value;
}
}
}
$tiltLogicOp = false;
} else {
if ($condition->parenthesis) {
if ($condition->parenthesis == 'START') {
$query['where'][] = ($tiltLogicOp ? '' : ($condition->logic_op ? $condition->logic_op . ' ' : 'AND ')) . '(';
$tiltLogicOp = true;
} else {
$query['where'][] = ')';
$tiltLogicOp = false;
}
} else {
$GLOBALS['log']->debug('illegal condition');
}
}
}
if (isset($query['where']) && $query['where']) {
array_unshift($query['where'], '(');
$query['where'][] = ') AND ';
}
$query['where'][] = $module->table_name . ".deleted = 0 " . $this->build_report_access_query(
$module,
$module->table_name
);
}
if ($closure) {
$query['where'][] = ')';
}
return $query;
}
}