Newer
Older
<?php
/*+********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
********************************************************************************/
$theme_path = "themes/" . $theme . "/";
$image_path = $theme_path . "images/";
require_once('include/database/PearDatabase.php');
require_once('data/CRMEntity.php');
require_once("modules/Reports/Reports.php");
require_once 'modules/Reports/ReportUtils.php';
require_once("vtlib/Vtiger/Module.php");
require_once('modules/Vtiger/helpers/Util.php');
require_once('include/RelatedListView.php');
/*
* Helper class to determine the associative dependency between tables.
*/
class ReportRunQueryDependencyMatrix {
protected $matrix = array();
protected $computedMatrix = null;
function setDependency($table, array $dependents) {
$this->matrix[$table] = $dependents;
}
function addDependency($table, $dependent) {
if (isset($this->matrix[$table]) && !in_array($dependent, $this->matrix[$table])) {
$this->matrix[$table][] = $dependent;
} else {
$this->setDependency($table, array($dependent));
}
}
function getDependents($table) {
$this->computeDependencies();
return isset($this->computedMatrix[$table]) ? $this->computedMatrix[$table] : array();
$this->computedMatrix = array();
foreach ($this->matrix as $key => $values) {
$this->computedMatrix[$key] = $this->computeDependencyForKey($key, $values);
protected function computeDependencyForKey($key, $values) {
$merged = array();
foreach ($values as $value) {
$merged[] = $value;
if (isset($this->matrix[$value])) {
$merged = array_merge($merged, $this->matrix[$value]);
}
}
return $merged;
}
// Turn-off the query planning to revert back - backward compatiblity
protected $disablePlanner = false;
protected $tables = array();
protected $tempTables = array();
protected $tempTablesInitialized = false;
// Turn-off in case the query result turns-out to be wrong.
protected $allowTempTables = true;
protected $tempTablePrefix = 'vtiger_reptmptbl_';
function addTable($table) {
if (!empty($table))
$this->tables[$table] = $table;
if ($this->disablePlanner) {
return true;
}
if (isset($this->tables[$table])) {
return true;
}
if (is_array($dependencies)) {
foreach ($dependencies as $dependentTable) {
if (isset($this->tables[$dependentTable])) {
return true;
}
}
} else if ($dependencies instanceof ReportRunQueryDependencyMatrix) {
$dependents = $dependencies->getDependents($table);
if ($dependents) {
return php7_count(array_intersect($this->tables, $dependents)) > 0;
}
}
return false;
}
function getTables() {
return $this->tables;
}
function newDependencyMatrix() {
return new ReportRunQueryDependencyMatrix();
}
function registerTempTable($query, $keyColumns, $module = null) {
if ($this->allowTempTables && !$this->disablePlanner) {
global $current_user;
$keyColumns = is_array($keyColumns) ? array_unique($keyColumns) : array($keyColumns);
// Minor optimization to avoid re-creating similar temporary table.
$uniqueName = NULL;
foreach ($this->tempTables as $tmpUniqueName => $tmpTableInfo) {
if (strcasecmp($query, $tmpTableInfo['query']) === 0 && $tmpTableInfo['module'] == $module) {
// Capture any additional key columns
$tmpTableInfo['keycolumns'] = array_unique(array_merge($tmpTableInfo['keycolumns'], $keyColumns));
$uniqueName = $tmpUniqueName;
break;
}
}
// Nothing found?
if ($uniqueName === NULL) {
// TODO Adding randomness in name to avoid concurrency
// even when same-user opens the report multiple instances at same-time.
$uniqueName = $this->tempTablePrefix .
str_replace('.', '', uniqid($current_user->id, true)) . (self::$tempTableCounter++);
$this->tempTables[$uniqueName] = array(
'query' => $query,
'keycolumns' => is_array($keyColumns) ? array_unique($keyColumns) : array($keyColumns),
'module' => $module
);
}
return $uniqueName;
}
return "($query)";
}
function initializeTempTables() {
global $adb;
$oldDieOnError = $adb->dieOnError;
$adb->dieOnError = false; // If query planner is re-used there could be attempt for temp table...
foreach ($this->tempTables as $uniqueName => $tempTableInfo) {
$reportConditions = $this->getReportConditions($tempTableInfo['module']);
if ($tempTableInfo['module'] == 'Emails') {
$query1 = sprintf('CREATE TEMPORARY TABLE %s AS %s', $uniqueName, $tempTableInfo['query']);
} else {
$query1 = sprintf('CREATE TEMPORARY TABLE %s AS %s %s', $uniqueName, $tempTableInfo['query'], $reportConditions);
}
$adb->pquery($query1, array());
$keyColumns = $tempTableInfo['keycolumns'];
foreach ($keyColumns as $keyColumn) {
$query2 = sprintf('ALTER TABLE %s ADD INDEX (%s)', $uniqueName, $keyColumn);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
}
}
$adb->dieOnError = $oldDieOnError;
// Trigger cleanup of temporary tables when the execution of the request ends.
// NOTE: This works better than having in __destruct
// (as the reference to this object might end pre-maturely even before query is executed)
if (!$this->registeredCleanup) {
register_shutdown_function(array($this, 'cleanup'));
// To avoid duplicate registration on this instance.
$this->registeredCleanup = true;
}
}
function cleanup() {
global $adb;
$oldDieOnError = $adb->dieOnError;
$adb->dieOnError = false; // To avoid abnormal termination during shutdown...
foreach ($this->tempTables as $uniqueName => $tempTableInfo) {
$adb->pquery('DROP TABLE ' . $uniqueName, array());
}
$adb->dieOnError = $oldDieOnError;
$this->tempTables = array();
}
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/**
* Function to get report condition query for generating temporary table based on condition given on report.
* It generates condition query by considering fields of $module's base table or vtiger_crmentity table fields.
* It doesn't add condition for reference fields in query.
* @param String $module Module name for which temporary table is generated (Reports secondary module)
* @return string Returns condition query for generating temporary table.
*/
function getReportConditions($module) {
$db = PearDatabase::getInstance();
$moduleModel = Vtiger_Module_Model::getInstance($module);
$moduleBaseTable = $moduleModel->get('basetable');
$reportId = $this->reportRun->reportid;
if (isset($_REQUEST['mode']) && $_REQUEST['mode'] == 'generate') {
$advanceFilter = $_REQUEST['advanced_filter'];
$advfilterlist = transformAdvFilterListToDBFormat(json_decode($advanceFilter, true));
} else {
$advfilterlist = $this->reportRun->getAdvFilterList($reportId);
}
$newAdvFilterList = array();
$k = 0;
foreach ($advfilterlist as $i => $columnConditions) {
$conditionGroup = $advfilterlist[$i]['columns'];
reset($conditionGroup);
$firstConditionKey = key($conditionGroup);
$oldColumnCondition = $advfilterlist[$i]['columns'][$firstConditionKey]['column_condition'];
foreach ($columnConditions['columns'] as $j => $condition) {
$columnName = $condition['columnname'];
$columnParts = explode(':', $columnName);
list($moduleName, $fieldLabel) = explode('_', $columnParts[2], 2);
$fieldInfo = getFieldByReportLabel($moduleName, $columnParts[3], 'name');
if(!empty($fieldInfo)) {
$fieldInstance = WebserviceField::fromArray($db, $fieldInfo);
$dataType = $fieldInstance->getFieldDataType();
$uiType = $fieldInfo['uitype'];
$fieldTable = $fieldInfo['tablename'];
$allowedTables = array('vtiger_crmentity', $moduleBaseTable);
$columnCondition = $advfilterlist[$i]['columns'][$j]['column_condition'];
if (!in_array($fieldTable, $allowedTables) || $moduleName != $module || isReferenceUIType($uiType) || $columnCondition == 'or' || $oldColumnCondition == 'or' || in_array($dataType, array('reference', 'multireference'))) {
$oldColumnCondition = $advfilterlist[$i]['columns'][$j]['column_condition'];
} else {
$columnParts[0] = $fieldTable;
$newAdvFilterList[$i]['columns'][$k]['columnname'] = implode(':', $columnParts);
$newAdvFilterList[$i]['columns'][$k]['comparator'] = $advfilterlist[$i]['columns'][$j]['comparator'];
$newAdvFilterList[$i]['columns'][$k]['value'] = $advfilterlist[$i]['columns'][$j]['value'];
$newAdvFilterList[$i]['columns'][$k++]['column_condition'] = $oldColumnCondition;
}
}
}
if (!empty($newAdvFilterList) && (php7_count($newAdvFilterList[$i]))) {
$newAdvFilterList[$i]['condition'] = $advfilterlist[$i]['condition'];
}
if (isset($newAdvFilterList[$i]['columns'][$k - 1])) {
$newAdvFilterList[$i]['columns'][$k - 1]['column_condition'] = '';
}
if (!empty($newAdvFilterList) && (php7_count($newAdvFilterList[$i]) != 2)) {
unset($newAdvFilterList[$i]);
}
}
end($newAdvFilterList);
$lastConditionsGrpKey = key($newAdvFilterList);
if (!empty($newAdvFilterList) && (php7_count($newAdvFilterList[$lastConditionsGrpKey]))) {
$newAdvFilterList[$lastConditionsGrpKey]['condition'] = '';
}
$advfiltersql = $this->reportRun->generateAdvFilterSql($newAdvFilterList);
if ($advfiltersql && !empty($advfiltersql)) {
$advfiltersql = ' AND ' . $advfiltersql;
}
return $advfiltersql;
}
// Maximum rows that should be emitted in HTML view.
static $HTMLVIEW_MAX_ROWS = 1000;
var $reportid;
var $primarymodule;
var $secondarymodule;
var $orderbylistsql;
var $orderbylistcolumns;
var $selectcolumns;
var $groupbylist;
var $reporttype;
var $reportname;
var $totallist;
var $_groupinglist = false;
var $_groupbycondition = false;
var $_reportquery = false;
var $_tmptablesinitialized = false;
var $_columnslist = false;
var $_stdfilterlist = false;
var $_columnstotallist = false;
var $_advfiltersql = false;
// All UItype 72 fields are added here so that in reports the values are append currencyId::value
var $append_currency_symbol_to_value = array('Products_Unit_Price', 'Services_Price',
'Invoice_Total', 'Invoice_Sub_Total', 'Invoice_Pre_Tax_Total', 'Invoice_S&H_Amount', 'Invoice_Discount_Amount', 'Invoice_Adjustment',
'Quotes_Total', 'Quotes_Sub_Total', 'Quotes_Pre_Tax_Total', 'Quotes_S&H_Amount', 'Quotes_Discount_Amount', 'Quotes_Adjustment',
'SalesOrder_Total', 'SalesOrder_Sub_Total', 'SalesOrder_Pre_Tax_Total', 'SalesOrder_S&H_Amount', 'SalesOrder_Discount_Amount', 'SalesOrder_Adjustment',
'PurchaseOrder_Total', 'PurchaseOrder_Sub_Total', 'PurchaseOrder_Pre_Tax_Total', 'PurchaseOrder_S&H_Amount', 'PurchaseOrder_Discount_Amount', 'PurchaseOrder_Adjustment',
'Invoice_Received', 'PurchaseOrder_Paid', 'Invoice_Balance', 'PurchaseOrder_Balance'
);
var $ui10_fields = array();
var $ui101_fields = array();
var $groupByTimeParent = array('Quarter' => array('Year'),
'Month' => array('Year')
);
// Added to support line item fields calculation, if line item fields
// are selected then module fields cannot be selected and vice versa
var $lineItemFieldsInCalculation = false;
/** Function to set reportid,primarymodule,secondarymodule,reporttype,reportname, for given reportid
* This function accepts the $reportid as argument
* It sets reportid,primarymodule,secondarymodule,reporttype,reportname for the given reportid
* To ensure single-instance is present for $reportid
* as we optimize using ReportRunPlanner and setup temporary tables.
function __construct($reportid) {
$oReport = new Reports($reportid);
$this->reportid = $reportid;
$this->primarymodule = $oReport->primodule;
$this->secondarymodule = $oReport->secmodule;
$this->reporttype = $oReport->reporttype;
$this->reportname = $oReport->reportname;
$this->queryPlanner = new ReportRunQueryPlanner();
$this->queryPlanner->reportRun = $this;
}
if (self::$instances === false || !is_array(self::$instances)) {
self::$instances = array();
}
if (!isset(self::$instances[$reportid])) {
self::$instances[$reportid] = new ReportRun($reportid);
}
return self::$instances[$reportid];
}
/** Function to get the columns for the reportid
* This function accepts the $reportid and $outputformat (optional)
* This function returns $columnslist Array($tablename:$columnname:$fieldlabel:$fieldname:$typeofdata=>$tablename.$columnname As Header value,
* $tablename1:$columnname1:$fieldlabel1:$fieldname1:$typeofdata1=>$tablename1.$columnname1 As Header value,
* |
* $tablenamen:$columnnamen:$fieldlabeln:$fieldnamen:$typeofdatan=>$tablenamen.$columnnamen As Header value
* )
return $this->_columnslist;
}
global $adb;
global $modules;
$ssql = "select vtiger_selectcolumn.* from vtiger_report inner join vtiger_selectquery on vtiger_selectquery.queryid = vtiger_report.queryid";
$ssql .= " left join vtiger_selectcolumn on vtiger_selectcolumn.queryid = vtiger_selectquery.queryid";
$ssql .= " where vtiger_report.reportid = ?";
$ssql .= " order by vtiger_selectcolumn.columnindex";
$result = $adb->pquery($ssql, array($reportid));
$permitted_fields = Array();
$selectedModuleFields = array();
require('user_privileges/user_privileges_'.$current_user->id.'.php');
while ($columnslistrow = $adb->fetch_array($result)) {
$fieldname = "";
$fieldcolname = isset($columnslistrow["columnname"]) ? $columnslistrow["columnname"] : '';
if ($fieldcolname != null && substr_count($fieldcolname, ':') >= 4) {
list($tablename, $colname, $module_field, $fieldname, $single) = explode(':', $fieldcolname);
if ($module_field != null && substr_count($module_field, '_') >= 1) {
list($module, $field) = explode('_', $module_field, 2);
}
}
$inventory_fields = array('serviceid');
$inventory_modules = getInventoryModules();
if (empty($permitted_fields[$module]) && $is_admin == false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2] == 1) {
$permitted_fields[$module] = $this->getaccesfield($module);
}
if (in_array($module, $inventory_modules)) {
if (!empty($permitted_fields)) {
foreach ($inventory_fields as $value) {
array_push($permitted_fields[$module], $value);
}
}
}
$selectedfields = explode(":", $fieldcolname);
if ($is_admin == false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2] == 1 && !in_array($selectedfields[3], $permitted_fields[$module])) {
//user has no access to this field, skip it.
continue;
}
$querycolumns = $this->getEscapedColumns($selectedfields);
if (isset($module) && $module != "") {
$mod_strings = return_module_language($current_language, $module);
$targetTableName = isset($tablename) ? $tablename : '';
$fieldlabel = trim(preg_replace("/$module/", " ", isset($selectedfields[2]) ? $selectedfields[2] :'', 1));
$mod_arr = explode('_', $fieldlabel);
$fieldlabel = trim(str_replace("_", " ", $fieldlabel));
$fld_arr = explode(" ", $fieldlabel);
if (($mod_arr[0] == '')) {
} else {
$mod = $mod_arr[0];
array_shift($fld_arr);
$mod_lbl = getTranslatedString($fld_arr[0], $mod); //module
}
$fld_lbl_str = implode(" ", $fld_arr);
$fld_lbl = getTranslatedString($fld_lbl_str, $module); //fieldlabel
$fieldlabel = $mod_lbl . " " . $fld_lbl;
if (($selectedfields[0] == "vtiger_usersRel1") && ($selectedfields[1] == 'user_name') && ($selectedfields[2] == 'Quotes_Inventory_Manager')) {
$concatSql = getSqlForNameInDisplayFormat(array('first_name' => $selectedfields[0] . ".first_name", 'last_name' => $selectedfields[0] . ".last_name"), 'Users');
$columnslist[$fieldcolname] = "trim( $concatSql ) as " . $module . "_Inventory_Manager";
$this->queryPlanner->addTable($selectedfields[0]);
if ((CheckFieldPermission($fieldname, $mod) != 'true' && isset($colname) && $colname != "crmid" && (!in_array($fieldname, $inventory_fields) && in_array($module, $inventory_modules))) || empty($fieldname)) {
} else {
$this->labelMapping[$selectedfields[2]] = str_replace(" ", "_", $fieldlabel);
// To check if the field in the report is a custom field
// and if yes, get the label of this custom field freshly from the vtiger_field as it would have been changed.
// Asha - Reference ticket : #4906
if ($querycolumns == "") {
$columnslist[$fieldcolname] = $this->getColumnSQL($selectedfields);
} else {
$columnslist[$fieldcolname] = $querycolumns;
}
$this->queryPlanner->addTable($targetTableName);
}
}
if ($outputformat == "HTML" || $outputformat == "PDF" || $outputformat == "PRINT") {
if($this->primarymodule == 'ModComments') {
$columnslist['vtiger_modcomments:related_to:ModComments_Related_To_Id:related_to:V'] = "vtiger_modcomments.related_to AS '".$this->primarymodule."_LBL_ACTION'";
} else {
$columnslist['vtiger_crmentity:crmid:LBL_ACTION:crmid:I'] = 'vtiger_crmentity.crmid AS "' . $this->primarymodule . '_LBL_ACTION"';
}
if ($this->secondarymodule) {
$secondaryModules = explode(':', $this->secondarymodule);
foreach ($secondaryModules as $secondaryModule) {
$columnsSelected = isset($selectedModuleFields[$secondaryModule]) ? (array)$selectedModuleFields[$secondaryModule] : array();
$moduleModel = Vtiger_Module_Model::getInstance($secondaryModule);
/**
* To check whether any column is selected from secondary module. If so, then only add
* that module table to query planner
*/
$moduleFields = $moduleModel->getFields();
$moduleFieldNames = array_keys($moduleFields);
$commonFields = array_intersect($moduleFieldNames, $columnsSelected);
if(php7_count($commonFields) > 0){
$baseTable = $moduleModel->get('basetable');
$this->queryPlanner->addTable($baseTable);
if ($secondaryModule == "Emails") {
$baseTable .= "Emails";
}
$baseTableId = $moduleModel->get('basetableid');
$columnslist[$baseTable . ":" . $baseTableId . ":" . $secondaryModule . ":" . $baseTableId . ":I"] = $baseTable . "." . $baseTableId . " AS " . $secondaryModule . "_LBL_ACTION";
}
}
}
}
// Save the information
$this->_columnslist = $columnslist;
$log->info("ReportRun :: Successfully returned getQueryColumnsList" . $reportid);
return $columnslist;
}
function getColumnSQL($selectedfields) {
global $adb;
$header_label = $selectedfields[2] = addslashes($selectedfields[2]); // Header label to be displayed in the reports table
list($module, $field) = explode('_', $selectedfields[2]);
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
$concatSql = getSqlForNameInDisplayFormat(array('first_name' => $selectedfields[0] . ".first_name", 'last_name' => $selectedfields[0] . ".last_name"), 'Users');
$emailTableName = "vtiger_activity";
if ($module != $this->primarymodule) {
$emailTableName .="Emails";
}
if ($selectedfields[0] == 'vtiger_inventoryproductrel') {
if ($selectedfields[1] == 'discount_amount') {
$columnSQL = "CASE WHEN (vtiger_inventoryproductreltmp{$module}.discount_amount != '') THEN vtiger_inventoryproductreltmp{$module}.discount_amount ELSE ROUND((vtiger_inventoryproductreltmp{$module}.listprice * vtiger_inventoryproductreltmp{$module}.quantity * (vtiger_inventoryproductreltmp{$module}.discount_percent/100)),3) END AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0].'tmp'.$module);
} else if ($selectedfields[1] == 'productid') {
$columnSQL = "CASE WHEN (vtiger_products{$module}.productname NOT LIKE '') THEN vtiger_products{$module}.productname ELSE vtiger_service{$module}.servicename END AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable("vtiger_products{$module}");
$this->queryPlanner->addTable("vtiger_service{$module}");
} else if ($selectedfields[1] == 'listprice') {
$moduleInstance = CRMEntity::getInstance($module);
$fieldName = $selectedfields[0] .'tmp'. $module . "." . $selectedfields[1];
$columnSQL = "CASE WHEN vtiger_currency_info{$module}.id = vtiger_users{$module}.currency_id THEN $fieldName/vtiger_currency_info{$module}.conversion_rate ELSE $fieldName/$moduleInstance->table_name.conversion_rate END AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0] .'tmp'. $module);
$this->queryPlanner->addTable('vtiger_currency_info' . $module);
$this->queryPlanner->addTable('vtiger_users' . $module);
} else if(in_array($this->primarymodule, array('Products', 'Services'))) {
$columnSQL = $selectedfields[0] . 'tmp' . $module . ".$selectedfields[1] AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0] . $module);
} else {
if($selectedfields[0] == 'vtiger_inventoryproductrel'){
$selectedfields[0] = $selectedfields[0]. 'tmp';
}
$columnSQL = $selectedfields[0] . $module . ".$selectedfields[1] AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0] . $module);
}
} else if($selectedfields[0] == 'vtiger_pricebookproductrel'){
if ($selectedfields[1] == 'listprice') {
$listPriceFieldName = $selectedfields[0].'tmp'. $module . "." . $selectedfields[1];
$currencyPriceFieldName = $selectedfields[0].'tmp'. $module . "." . 'usedcurrency';
$columnSQL = 'CONCAT('.$currencyPriceFieldName.",'::',". $listPriceFieldName .")". " AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0] .'tmp'. $module);
}
} else if ($selectedfields[4] == 'C') {
$field_label_data = explode('_', $selectedfields[2]);
$module = $field_label_data[0];
if ($module != $this->primarymodule) {
$columnSQL = "case when (" . $selectedfields[0] . "." . $selectedfields[1] . "='1')then 'yes' else case when (vtiger_crmentity$module.crmid !='') then 'no' else '-' end end AS '" . decode_html($selectedfields[2]) . "'";
$this->queryPlanner->addTable("vtiger_crmentity$module");
} else {
$columnSQL = "case when (" . $selectedfields[0] . "." . $selectedfields[1] . "='1')then 'yes' else case when (vtiger_crmentity.crmid !='') then 'no' else '-' end end AS '" . decode_html($selectedfields[2]) . "'";
$this->queryPlanner->addTable($selectedfields[0]);
}
} elseif ($selectedfields[4] == 'D' || $selectedfields[4] == 'DT') {
if ($selectedfields[5] == 'Y') {
if ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "YEAR(cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE)) AS Emails_Date_Sent_Year";
} else {

Akshath
committed
$columnSQL = "YEAR(concat(vtiger_activity.date_start,' ',vtiger_activity.time_start)) AS Calendar_Start_Date_and_Time_Year";
}
} else if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "YEAR(vtiger_crmentity." . $selectedfields[1] . ") AS '" . decode_html($header_label) . "_Year'";
} else {
$columnSQL = 'YEAR(' . $selectedfields[0] . "." . $selectedfields[1] . ") AS '" . decode_html($header_label) . "_Year'";
}
$this->queryPlanner->addTable($selectedfields[0]);
} elseif ($selectedfields[5] == 'M') {
if ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "MONTHNAME(cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE)) AS Emails_Date_Sent_Month";
} else {

Akshath
committed
$columnSQL = "MONTHNAME(concat(vtiger_activity.date_start,' ',vtiger_activity.time_start)) AS Calendar_Start_Date_and_Time_Month";
}
} else if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "MONTHNAME(vtiger_crmentity." . $selectedfields[1] . ") AS '" . decode_html($header_label) . "_Month'";
} else {
$columnSQL = 'MONTHNAME(' . $selectedfields[0] . "." . $selectedfields[1] . ") AS '" . decode_html($header_label) . "_Month'";
}
$this->queryPlanner->addTable($selectedfields[0]);
} elseif ($selectedfields[5] == 'W') {
if ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "CONCAT('Week ',WEEK(cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE), 1)) AS Emails_Date_Sent_Week";
} else {

Akshath
committed
$columnSQL = "CONCAT('Week ',WEEK(concat(vtiger_activity.date_start,' ',vtiger_activity.time_start), 1)) AS Calendar_Start_Date_and_Time_Week";
}
} else if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "CONCAT('Week ',WEEK(vtiger_crmentity." . $selectedfields[1] . ", 1)) AS '" . decode_html($header_label) . "_Week'";
} else {
$columnSQL = "CONCAT('Week ',WEEK(" . $selectedfields[0] . "." . $selectedfields[1] . ", 1)) AS '" . decode_html($header_label) . "_Week'";
}
$this->queryPlanner->addTable($selectedfields[0]);
} elseif ($selectedfields[5] == 'MY') { // used in charts to get the year also, which will be used for click throughs
if ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "date_format(cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE), '%M %Y') AS Emails_Date_Sent_Month";
} else {

Akshath
committed
$columnSQL = "date_format(concat(vtiger_activity.date_start,' ',vtiger_activity.time_start), '%M %Y') AS Calendar_Start_Date_and_Time_Month";
}
} else if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "date_format(vtiger_crmentity." . $selectedfields[1] . ", '%M %Y') AS '" . decode_html($header_label) . "_Month'";
} else {
$columnSQL = 'date_format(' . $selectedfields[0] . "." . $selectedfields[1] . ", '%M %Y') AS '" . decode_html($header_label) . "_Month'";
}
$this->queryPlanner->addTable($selectedfields[0]);
} else {
if ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE) AS Emails_Date_Sent";
} else {

Akshath
committed
$columnSQL = "concat(vtiger_activity.date_start,' ',vtiger_activity.time_start) AS Calendar_Start_Date_and_Time";
}
} else if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "vtiger_crmentity." . $selectedfields[1] . " AS '" . decode_html($header_label) . "'";
} else {
$columnSQL = $selectedfields[0] . "." . $selectedfields[1] . " AS '" . decode_html($header_label) . "'";
}
$this->queryPlanner->addTable($selectedfields[0]);
}
} elseif ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'status') {
$columnSQL = " case when (vtiger_activity.status not like '') then vtiger_activity.status else vtiger_activity.eventstatus end AS Calendar_Status";
} elseif ($selectedfields[0] == 'vtiger_activity' && $selectedfields[1] == 'date_start') {
if ($module == 'Emails') {
$columnSQL = "cast(concat($emailTableName.date_start,' ',$emailTableName.time_start) as DATE) AS Emails_Date_Sent";

Akshath
committed
$columnSQL = "concat(vtiger_activity.date_start,' ',vtiger_activity.time_start) AS Calendar_Start_Date_and_Time";
} elseif (stristr($selectedfields[0], "vtiger_users") && ($selectedfields[1] == 'user_name')) {
$temp_module_from_tablename = str_replace("vtiger_users", "", $selectedfields[0]);
if ($module != $this->primarymodule) {
$condition = "and vtiger_crmentity" . $module . ".crmid!=''";
$this->queryPlanner->addTable("vtiger_crmentity$module");
} else {
$condition = "and vtiger_crmentity.crmid!=''";
}
if ($temp_module_from_tablename == $module) {
$concatSql = getSqlForNameInDisplayFormat(array('first_name' => $selectedfields[0] . ".first_name", 'last_name' => $selectedfields[0] . ".last_name"), 'Users');
$columnSQL = " case when(" . $selectedfields[0] . ".last_name NOT LIKE '' $condition ) THEN " . $concatSql . " else vtiger_groups" . $module . ".groupname end AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable('vtiger_groups' . $module); // Auto-include the dependent module table.
} else {//Some Fields can't assigned to groups so case avoided (fields like inventory manager)
$columnSQL = $selectedfields[0] . ".user_name AS '" . decode_html($header_label) . "'";
}
$this->queryPlanner->addTable($selectedfields[0]);
} elseif (stristr($selectedfields[0], "vtiger_crmentity") && ($selectedfields[1] == 'modifiedby')) {
$targetTableName = 'vtiger_lastModifiedBy' . $module;
$concatSql = getSqlForNameInDisplayFormat(array('last_name' => $targetTableName . '.last_name', 'first_name' => $targetTableName . '.first_name'), 'Users');
$columnSQL = "trim($concatSql) AS $header_label";
$this->queryPlanner->addTable("vtiger_crmentity$module");
$this->queryPlanner->addTable($targetTableName);
// Added when no fields from the secondary module is selected but lastmodifiedby field is selected
$moduleInstance = CRMEntity::getInstance($module);
$this->queryPlanner->addTable($moduleInstance->table_name);
} else if (stristr($selectedfields[0], "vtiger_crmentity") && ($selectedfields[1] == 'smcreatorid')) {
$targetTableName = 'vtiger_createdby' . $module;
$concatSql = getSqlForNameInDisplayFormat(array('last_name' => $targetTableName . '.last_name', 'first_name' => $targetTableName . '.first_name'), 'Users');
$columnSQL = "trim($concatSql) AS " . decode_html($header_label) . "";
$this->queryPlanner->addTable("vtiger_crmentity$module");
$this->queryPlanner->addTable($targetTableName);
// Added when no fields from the secondary module is selected but creator field is selected
$moduleInstance = CRMEntity::getInstance($module);
$this->queryPlanner->addTable($moduleInstance->table_name);
} elseif ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule) {
$columnSQL = "vtiger_crmentity." . $selectedfields[1] . " AS '" . decode_html($header_label) . "'";
} elseif ($selectedfields[0] == 'vtiger_products' && $selectedfields[1] == 'unit_price') {
$columnSQL = "concat(" . $selectedfields[0] . ".currency_id,'::',innerProduct.actual_unit_price) AS '" . decode_html($header_label) . "'";
} elseif (in_array(decode_html($selectedfields[2]), $this->append_currency_symbol_to_value)) {
if ($selectedfields[1] == 'discount_amount') {
$columnSQL = "CONCAT(" . $selectedfields[0] . ".currency_id,'::', IF(" . $selectedfields[0] . ".discount_amount != ''," . $selectedfields[0] . ".discount_amount, (" . $selectedfields[0] . ".discount_percent/100) * " . $selectedfields[0] . ".subtotal)) AS " . decode_html($header_label);
$columnSQL = "concat(" . $selectedfields[0] . ".currency_id,'::'," . $selectedfields[0] . "." . $selectedfields[1] . ") AS '" . decode_html($header_label) . "'";
} elseif ($selectedfields[0] == 'vtiger_notes' && ($selectedfields[1] == 'filelocationtype' || $selectedfields[1] == 'filesize' || $selectedfields[1] == 'folderid' || $selectedfields[1] == 'filestatus')) {
if ($selectedfields[1] == 'filelocationtype') {
$columnSQL = "case " . $selectedfields[0] . "." . $selectedfields[1] . " when 'I' then 'Internal' when 'E' then 'External' else '-' end AS '" . decode_html($selectedfields[2]) . "'";
} else if ($selectedfields[1] == 'folderid') {
$columnSQL = "vtiger_attachmentsfolder.foldername AS '$selectedfields[2]'";
$this->queryPlanner->addTable("vtiger_attachmentsfolder");
} elseif ($selectedfields[1] == 'filestatus') {
$columnSQL = "case " . $selectedfields[0] . "." . $selectedfields[1] . " when '1' then 'yes' when '0' then 'no' else '-' end AS '" . decode_html($selectedfields[2]) . "'";
} elseif ($selectedfields[1] == 'filesize') {
$columnSQL = "case " . $selectedfields[0] . "." . $selectedfields[1] . " when '' then '-' else concat(" . $selectedfields[0] . "." . $selectedfields[1] . "/1024,' ','KB') end AS '" . decode_html($selectedfields[2]) . "'";
$tableName = $selectedfields[0];
if ($module != $this->primarymodule && $module == "Emails" && $tableName == "vtiger_activity") {
$tableName = $emailTableName;
}
$columnSQL = $tableName . "." . $selectedfields[1] . " AS '" . decode_html($header_label) . "'";
$this->queryPlanner->addTable($selectedfields[0]);
}
return $columnSQL;
}
/** Function to get field columns based on profile
* @ param $module : Type string
* returns permitted fields in array format
*/
function getaccesfield($module) {
global $current_user;
global $adb;
$access_fields = Array();
//Reports should not be allowed to access user module fields.
if($module == "Users"){
return $access_fields;
}
$profileList = getCurrentUserProfileList();
$query = "select vtiger_field.fieldname from vtiger_field inner join vtiger_profile2field on vtiger_profile2field.fieldid=vtiger_field.fieldid inner join vtiger_def_org_field on vtiger_def_org_field.fieldid=vtiger_field.fieldid where";
$params = array();
if (php7_count($profileList) > 0) {
$query .= " vtiger_field.tabid in (9,16) and vtiger_field.displaytype in (1,2,3) and vtiger_profile2field.visible=0 and vtiger_def_org_field.visible=0
and vtiger_field.presence IN (0,2) and vtiger_profile2field.profileid in (" . generateQuestionMarks($profileList) . ") group by vtiger_field.fieldid order by block,sequence";
array_push($params, $profileList);
} else {
$query .= " vtiger_field.tabid in (9,16) and vtiger_field.displaytype in (1,2,3) and vtiger_profile2field.visible=0 and vtiger_def_org_field.visible=0
and vtiger_field.presence IN (0,2) group by vtiger_field.fieldid order by block,sequence";
}
if (php7_count($profileList) > 0) {
$query .= " vtiger_field.tabid in (select tabid from vtiger_tab where vtiger_tab.name in (?)) and vtiger_field.displaytype in (1,2,3,5) and vtiger_profile2field.visible=0
and vtiger_field.presence IN (0,2) and vtiger_def_org_field.visible=0 and vtiger_profile2field.profileid in (" . generateQuestionMarks($profileList) . ") group by vtiger_field.fieldid order by block,sequence";
array_push($params, $profileList);
} else {
$query .= " vtiger_field.tabid in (select tabid from vtiger_tab where vtiger_tab.name in (?)) and vtiger_field.displaytype in (1,2,3,5) and vtiger_profile2field.visible=0
and vtiger_field.presence IN (0,2) and vtiger_def_org_field.visible=0 group by vtiger_field.fieldid order by block,sequence";
}
}
$result = $adb->pquery($query, $params);
$access_fields[] = $collistrow["fieldname"];
}
//added to include ticketid for Reports module in select columnlist for all users
$access_fields[] = "ticketid";
return $access_fields;
}
/** Function to get Escapedcolumns for the field in case of multiple parents
* @ param $selectedfields : Type Array
* returns the case query for the escaped columns
*/
function getEscapedColumns($selectedfields) {
$columnName = isset($selectedfields[1]) ? $selectedfields[1] : '';
$moduleFieldLabel = isset($selectedfields[2]) ? $selectedfields[2] : '';
$fieldName = isset($selectedfields[3]) ? $selectedfields[3] : '';
if ($moduleFieldLabel !=null && substr_count($moduleFieldLabel, '_') >= 1) {
list($moduleName, $fieldLabel) = explode('_', $moduleFieldLabel, 2);
$fieldInfo = getFieldByReportLabel($moduleName, $fieldLabel);
}
if (isset($moduleName) && $moduleName == 'ModComments' && $fieldName == 'creator') {
$concatSql = getSqlForNameInDisplayFormat(array('first_name' => 'vtiger_usersModComments.first_name',
'last_name' => 'vtiger_usersModComments.last_name'), 'Users');
$queryColumn = "trim(case when (vtiger_usersModComments.user_name not like '' and vtiger_crmentity.crmid!='') then $concatSql end) AS ModComments_Creator";
$this->queryPlanner->addTable('vtiger_usersModComments');
} elseif (isset($fieldInfo) && (($fieldInfo['uitype'] == '10' || isReferenceUIType($fieldInfo['uitype'])) && $fieldInfo['tablename'] != 'vtiger_inventoryproductrel') && $fieldInfo['uitype'] != '52' && $fieldInfo['uitype'] != '53') {
$fieldSqlColumns = $this->getReferenceFieldColumnList($moduleName, $fieldInfo);
if (php7_count($fieldSqlColumns) > 0) {
$queryColumn = "(CASE WHEN $tableName.$columnName NOT LIKE '' THEN (CASE";
$queryColumn .= " WHEN $columnSql NOT LIKE '' THEN $columnSql";
}
$queryColumn .= " ELSE '' END) ELSE '' END) AS '".decode_html($moduleFieldLabel)."'";
$this->queryPlanner->addTable($tableName);
}
}
return $queryColumn;
}
/** Function to get selectedcolumns for the given reportid
* @ param $reportid : Type Integer
* returns the query of columnlist for the selected columns
*/
global $adb;
global $modules;
global $log;
$ssql = "select vtiger_selectcolumn.* from vtiger_report inner join vtiger_selectquery on vtiger_selectquery.queryid = vtiger_report.queryid";
$ssql .= " left join vtiger_selectcolumn on vtiger_selectcolumn.queryid = vtiger_selectquery.queryid where vtiger_report.reportid = ? ";
$ssql .= " order by vtiger_selectcolumn.columnindex";
$result = $adb->pquery($ssql, array($reportid));
$noofrows = $adb->num_rows($result);
if ($this->orderbylistsql != "") {
$sSQL .= $this->orderbylistsql . ", ";
for ($i = 0; $i < $noofrows; $i++) {
$fieldcolname = $adb->query_result($result, $i, "columnname");
for ($j = 0; $j < php7_count($this->orderbylistcolumns); $j++) {
if ($ordercolumnsequal) {
$selectedfields = explode(":", $fieldcolname);
if ($selectedfields[0] == "vtiger_crmentity" . $this->primarymodule)
$sSQLList[] = $selectedfields[0] . "." . $selectedfields[1] . " '" . $selectedfields[2] . "'";
$log->info("ReportRun :: Successfully returned getSelectedColumnsList" . $reportid);
return $sSQL;
}
/** Function to get advanced comparator in query form for the given Comparator and value
* @ param $comparator : Type String
* @ param $value : Type String
* returns the check query for the comparator
*/
function getAdvComparator($comparator, $value, $datatype = "", $columnName = '') {
global $log, $adb, $default_charset, $ogReport;
$value = html_entity_decode(trim($value), ENT_QUOTES, $default_charset);
if ($value_len > 1 && $value[0] == '$' && $value[$value_len - 1] == '$') {
$temp = str_replace('$', '', $value);
if ($datatype == 'C') {
$value = str_replace("yes", "1", str_replace("no", "0", $value));
if ($comparator == "e" || $comparator == 'y') {
if (trim($value) == "NULL") {
} elseif (trim($value) != "") {
$rtvalue = " = " . $adb->quote($value);
} elseif (trim($value) == "" && $datatype == "V") {
$rtvalue = " = " . $adb->quote($value);
} else {
if ($comparator == "n" || $comparator == 'ny') {
if (trim($value) == "NULL") {
} elseif (trim($value) != "") {
if ($columnName)
$rtvalue = " <> " . $adb->quote($value) . " OR " . $columnName . " IS NULL ";
else
$rtvalue = " <> " . $adb->quote($value);
}elseif (trim($value) == "" && $datatype == "V") {
$rtvalue = " <> " . $adb->quote($value);
} else {
if ($comparator == "s") {
$rtvalue = " like '" . formatForSqlLike($value, 2, $is_field) . "'";
if ($comparator == "ew") {
$rtvalue = " like '" . formatForSqlLike($value, 1, $is_field) . "'";
if ($comparator == "c") {
$rtvalue = " like '" . formatForSqlLike($value, 0, $is_field) . "'";
if ($comparator == "k") {
$rtvalue = " not like '" . formatForSqlLike($value, 0, $is_field) . "'";
if ($comparator == "l") {
$rtvalue = " < " . $adb->quote($value);
if ($comparator == "g") {
$rtvalue = " > " . $adb->quote($value);
if ($comparator == "m") {
$rtvalue = " <= " . $adb->quote($value);
if ($comparator == "h") {
$rtvalue = " >= " . $adb->quote($value);
if ($comparator == "b") {
$rtvalue = " < " . $adb->quote($value);
if ($comparator == "a") {
$rtvalue = " > " . $adb->quote($value);
if ($is_field == true) {
$rtvalue = str_replace("'", "", $rtvalue);
$rtvalue = str_replace("\\", "", $rtvalue);
}
$log->info("ReportRun :: Successfully returned getAdvComparator");
return $rtvalue;
}
/** Function to get field that is to be compared in query form for the given Comparator and field
* @ param $field : field
* returns the value for the comparator
*/
function getFilterComparedField($field) {
global $adb, $ogReport;
if (!empty($this->secondarymodule)) {
$secModules = explode(':', $this->secondarymodule);
foreach ($secModules as $secModule) {
$secondary = CRMEntity::getInstance($secModule);
$this->queryPlanner->addTable($secondary->table_name);
}
}
$field = explode('#', $field);
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
$module = $field[0];
$fieldname = trim($field[1]);
$tabid = getTabId($module);
$field_query = $adb->pquery("SELECT tablename,columnname,typeofdata,fieldname,uitype FROM vtiger_field WHERE tabid = ? AND fieldname= ?", array($tabid, $fieldname));
$fieldtablename = $adb->query_result($field_query, 0, 'tablename');
$fieldcolname = $adb->query_result($field_query, 0, 'columnname');
$typeofdata = $adb->query_result($field_query, 0, 'typeofdata');
$fieldtypeofdata = ChangeTypeOfData_Filter($fieldtablename, $fieldcolname, $typeofdata[0]);
$uitype = $adb->query_result($field_query, 0, 'uitype');
/* if($tr[0]==$ogReport->primodule)
$value = $adb->query_result($field_query,0,'tablename').".".$adb->query_result($field_query,0,'columnname');
else
$value = $adb->query_result($field_query,0,'tablename').$tr[0].".".$adb->query_result($field_query,0,'columnname');
*/
if ($uitype == 68 || $uitype == 59) {
$fieldtypeofdata = 'V';
}
if ($fieldtablename == "vtiger_crmentity" && $module != $this->primarymodule) {
$fieldtablename = $fieldtablename . $module;
}
if ($fieldname == "assigned_user_id") {
$fieldtablename = "vtiger_users" . $module;
$fieldcolname = "user_name";
}
if ($fieldtablename == "vtiger_crmentity" && $fieldname == "modifiedby") {
$fieldtablename = "vtiger_lastModifiedBy" . $module;
$fieldcolname = "user_name";
}
if ($fieldname == "assigned_user_id1") {
$fieldtablename = "vtiger_usersRel1";
$fieldcolname = "user_name";
}
$value = $fieldtablename . "." . $fieldcolname;
$this->queryPlanner->addTable($fieldtablename);
/** Function to get the advanced filter columns for the reportid
* This function accepts the $reportid
* This function returns $columnslist Array($columnname => $tablename:$columnname:$fieldlabel:$fieldname:$typeofdata=>$tablename.$columnname filtercriteria,
* $tablename1:$columnname1:$fieldlabel1:$fieldname1:$typeofdata1=>$tablename1.$columnname1 filtercriteria,
* |
* $tablenamen:$columnnamen:$fieldlabeln:$fieldnamen:$typeofdatan=>$tablenamen.$columnnamen filtercriteria
* )
function getAdvFilterList($reportid, $forClickThrough = false) {
global $adb, $log;
$advft_criteria = array();
// Not a good approach to get all the fields if not required(May leads to Performance issue)
$sql = 'SELECT groupid,group_condition FROM vtiger_relcriteria_grouping WHERE queryid = ? ORDER BY groupid';
$groupsresult = $adb->pquery($sql, array($reportid));
$i = 1;
$j = 0;
while ($relcriteriagroup = $adb->fetch_array($groupsresult)) {
$groupId = $relcriteriagroup["groupid"];
$groupCondition = $relcriteriagroup["group_condition"];
$ssql = 'select vtiger_relcriteria.* from vtiger_report
inner join vtiger_relcriteria on vtiger_relcriteria.queryid = vtiger_report.queryid
left join vtiger_relcriteria_grouping on vtiger_relcriteria.queryid = vtiger_relcriteria_grouping.queryid
and vtiger_relcriteria.groupid = vtiger_relcriteria_grouping.groupid';
$ssql.= " where vtiger_report.reportid = ? AND vtiger_relcriteria.groupid = ? order by vtiger_relcriteria.columnindex";
$result = $adb->pquery($ssql, array($reportid, $groupId));
$noOfColumns = $adb->num_rows($result);
$columnIndex = $relcriteriarow["columnindex"];
$criteria = array();
$criteria['columnname'] = html_entity_decode($relcriteriarow["columnname"]);
$criteria['comparator'] = $relcriteriarow["comparator"];
$advfilterval = $relcriteriarow["value"];
$col = explode(":",$relcriteriarow["columnname"]);
$criteria['value'] = $advfilterval;
$criteria['column_condition'] = $relcriteriarow["column_condition"];