[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /* ************************************************************************************ 3 * The contents of this file are subject to the vtiger CRM Public License Version 1.0 4 * ("License"); You may not use this file except in compliance with the License 5 * The Original Code is: vtiger CRM Open Source 6 * The Initial Developer of the Original Code is vtiger. 7 * Portions created by vtiger are Copyright (C) vtiger. 8 * All Rights Reserved. 9 * *********************************************************************************** */ 10 11 class Reports_Chart_Model extends Vtiger_Base_Model { 12 13 public static function getInstanceById($reportModel) { 14 $self = new self(); 15 $db = PearDatabase::getInstance(); 16 $result = $db->pquery('SELECT * FROM vtiger_reporttype WHERE reportid = ?', array($reportModel->getId())); 17 $data = $db->query_result($result, 0, 'data'); 18 if(!empty($data)) { 19 $decodeData = Zend_Json::decode(decode_html($data)); 20 $self->setData($decodeData); 21 $self->setParent($reportModel); 22 $self->setId($reportModel->getId()); 23 } 24 return $self; 25 } 26 27 function getId() { 28 return $this->get('reportid'); 29 } 30 31 function setId($id) { 32 $this->set('reportid', $id); 33 } 34 35 function getParent() { 36 return $this->parent; 37 } 38 39 function setParent($parent) { 40 $this->parent = $parent; 41 } 42 43 function getChartType() { 44 $type = $this->get('type'); 45 if(empty($type)) $type = 'pieChart'; 46 return $type; 47 } 48 49 function getGroupByField() { 50 return $this->get('groupbyfield'); 51 } 52 53 function getDataFields() { 54 return $this->get('datafields'); 55 } 56 57 function getData() { 58 $type = ucfirst($this->getChartType()); 59 $chartModel = new $type($this); 60 return $chartModel->generateData(); 61 } 62 } 63 64 abstract class Base_Chart extends Vtiger_Base_Model{ 65 66 function __construct($parent) { 67 $this->setParent($parent); 68 $this->setReportRunObject(); 69 70 $this->setQueryColumns($this->getParent()->getDataFields()); 71 $this->setGroupByColumns($this->getParent()->getGroupByField()); 72 } 73 74 function setParent($parent) { 75 $this->parent = $parent; 76 } 77 78 function getParent() { 79 return $this->parent; 80 } 81 82 function getReportModel() { 83 $parent = $this->getParent(); 84 return $parent->getParent(); 85 } 86 87 function isRecordCount() { 88 return $this->isRecordCount; 89 } 90 91 function setRecordCount() { 92 $this->isRecordCount = true; 93 } 94 95 function setReportRunObject() { 96 $chartModel = $this->getParent(); 97 $reportModel = $chartModel->getParent(); 98 $this->reportRun = ReportRun::getInstance($reportModel->getId()); 99 } 100 101 function getReportRunObject() { 102 return $this->reportRun; 103 } 104 105 function getFieldModelByReportColumnName($column) { 106 $fieldInfo = explode(':', $column); 107 $moduleFieldLabelInfo = explode('_', $fieldInfo[2]); 108 $moduleName = $moduleFieldLabelInfo[0]; 109 $fieldName = $fieldInfo[3]; 110 111 if($moduleName && $fieldName) { 112 $moduleModel = Vtiger_Module_Model::getInstance($moduleName); 113 return $moduleModel->getField($fieldName); 114 } 115 return false; 116 } 117 118 function getQueryColumnsByFieldModel() { 119 return $this->fieldModels; 120 } 121 122 function setQueryColumns($columns) { 123 if($columns && is_string($columns)) $columns = array($columns); 124 125 if(is_array($columns)) { 126 foreach($columns as $column) { 127 if($column == 'count(*)') { 128 $this->setRecordCount(); 129 } else { 130 131 $fieldModel = $this->getFieldModelByReportColumnName($column); 132 $columnInfo = explode(':', $column); 133 134 $referenceFieldReportColumnSQL = $this->getReportRunObject()->getEscapedColumns($columnInfo); 135 136 $aggregateFunction = $columnInfo[5]; 137 if(empty($referenceFieldReportColumnSQL)) { 138 $reportColumnSQL = $this->getReportTotalColumnSQL($columnInfo); 139 $reportColumnSQLInfo = split(' AS ', $reportColumnSQL); 140 141 if($aggregateFunction == 'AVG') { // added as mysql will ignore null values 142 $label = $this->reportRun->replaceSpecialChar($reportColumnSQLInfo[1]).'_AVG'; 143 $reportColumn = '(SUM('. $reportColumnSQLInfo[0] .')/COUNT(*)) AS '.$label; 144 } else { 145 $label = $this->reportRun->replaceSpecialChar($reportColumnSQLInfo[1]).'_'.$aggregateFunction; 146 $reportColumn = $aggregateFunction. '('. $reportColumnSQLInfo[0] .') AS '.$label; 147 } 148 149 $fieldModel->set('reportcolumn', $reportColumn); 150 $fieldModel->set('reportlabel', $this->reportRun->replaceSpecialChar($label)); 151 } else { 152 $reportColumn = $referenceFieldReportColumnSQL; 153 $groupColumnSQLInfo = split(' AS ', $referenceFieldReportColumnSQL); 154 $fieldModel->set('reportlabel', $this->reportRun->replaceSpecialChar($groupColumnSQLInfo[1])); 155 $fieldModel->set('reportcolumn', $this->reportRun->replaceSpecialChar($reportColumn)); 156 } 157 158 $fieldModel->set('reportcolumninfo', $column); 159 160 if($fieldModel) { 161 $fieldModels[] = $fieldModel; 162 } 163 } 164 } 165 } 166 if($fieldModels) $this->fieldModels = $fieldModels; 167 } 168 169 function setGroupByColumns($columns) { 170 if($columns && is_string($columns)) $columns = array($columns); 171 172 if(is_array($columns)) { 173 foreach($columns as $column) { 174 $fieldModel = $this->getFieldModelByReportColumnName($column); 175 176 if($fieldModel) { 177 $columnInfo = explode(':', $column); 178 179 $referenceFieldReportColumnSQL = $this->getReportRunObject()->getEscapedColumns($columnInfo); 180 if(empty($referenceFieldReportColumnSQL)) { 181 $reportColumnSQL = $this->getReportColumnSQL($columnInfo); 182 $fieldModel->set('reportcolumn', $this->reportRun->replaceSpecialChar($reportColumnSQL)); 183 // Added support for date and date time fields with Year and Month support 184 if($columnInfo[4] == 'D' || $columnInfo[4] == 'DT') { 185 $reportColumnSQLInfo = split(' AS ', $reportColumnSQL); 186 $fieldModel->set('reportlabel', trim($this->reportRun->replaceSpecialChar($reportColumnSQLInfo[1]), '\'')); // trim added as single quote on labels was not grouping properly 187 } else { 188 $fieldModel->set('reportlabel', $this->reportRun->replaceSpecialChar($columnInfo[2])); 189 } 190 } else { 191 $groupColumnSQLInfo = split(' AS ', $referenceFieldReportColumnSQL); 192 $fieldModel->set('reportlabel', $this->reportRun->replaceSpecialChar($groupColumnSQLInfo[1])); 193 $fieldModel->set('reportcolumn', $this->reportRun->replaceSpecialChar($referenceFieldReportColumnSQL)); 194 } 195 196 $fieldModel->set('reportcolumninfo', $column); 197 198 $fieldModels[] = $fieldModel; 199 } 200 } 201 } 202 if($fieldModels) $this->groupByFieldModels = $fieldModels; 203 } 204 205 function getGroupbyColumnsByFieldModel() { 206 return $this->groupByFieldModels; 207 } 208 209 /** 210 * Function returns sql column for group by fields 211 * @param <Array> $selectedfields - field info report format 212 * @return <String> 213 */ 214 function getReportColumnSQL($selectedfields) { 215 $reportRunObject = $this->getReportRunObject(); 216 $append_currency_symbol_to_value = $reportRunObject->append_currency_symbol_to_value; 217 $reportRunObject->append_currency_symbol_to_value = array(); 218 219 $columnSQL = $reportRunObject->getColumnSQL($selectedfields); 220 221 $reportRunObject->append_currency_symbol_to_value = $append_currency_symbol_to_value; 222 return $columnSQL; 223 } 224 225 226 /** 227 * Function returns sql column for data fields 228 * @param <Array> $fieldInfo - field info report format 229 * @return <string> 230 */ 231 function getReportTotalColumnSQL($fieldInfo) { 232 $primaryModule = $this->getPrimaryModule(); 233 $columnTotalSQL = $this->getReportRunObject()->getColumnsTotalSQL($fieldInfo, $primaryModule). ' AS '. $fieldInfo[2]; 234 return $columnTotalSQL; 235 } 236 237 /** 238 * Function returns labels for aggregate functions 239 * @param type $aggregateFunction 240 * @return string 241 */ 242 function getAggregateFunctionLabel($aggregateFunction) { 243 switch($aggregateFunction) { 244 case 'SUM' : return 'LBL_TOTAL_SUM_OF'; 245 case 'AVG' : return 'LBL_AVG_OF'; 246 case 'MIN' : return 'LBL_MIN_OF'; 247 case 'MAX' : return 'LBL_MAX_OF'; 248 } 249 } 250 251 /** 252 * Function returns translated label for the field from report label 253 * Report label format MODULE_FIELD_LABEL eg:Leads_Lead_Source 254 * @param <String> $column 255 */ 256 function getTranslatedLabelFromReportLabel($column) { 257 $columnLabelInfo = explode('_', $column); 258 $columnLabelInfo = array_diff($columnLabelInfo, array('SUM','MIN','MAX','AVG')); // added to remove aggregate functions from the graph labels 259 return vtranslate(implode(' ', array_slice($columnLabelInfo, 1)), $columnLabelInfo[0]); 260 } 261 262 /** 263 * Function returns primary module of the report 264 * @return <String> 265 */ 266 function getPrimaryModule() { 267 $chartModel = $this->getParent(); 268 $reportModel = $chartModel->getParent(); 269 $primaryModule = $reportModel->getPrimaryModule(); 270 return $primaryModule; 271 } 272 273 /** 274 * Function returns list view url of the Primary module 275 * @return <String> 276 */ 277 function getBaseModuleListViewURL() { 278 $primaryModule = $this->getPrimaryModule(); 279 $primaryModuleModel = Vtiger_Module_Model::getInstance($primaryModule); 280 $listURL = $primaryModuleModel->getListViewUrl(); 281 282 return $listURL; 283 } 284 285 abstract function generateData(); 286 287 function getQuery() { 288 $chartModel = $this->getParent(); 289 $reportModel = $chartModel->getParent(); 290 291 $this->reportRun = ReportRun::getInstance($reportModel->getId()); 292 $advFilterSql = $reportModel->getAdvancedFilterSQL(); 293 294 $queryColumnsByFieldModel = $this->getQueryColumnsByFieldModel(); 295 296 if(is_array($queryColumnsByFieldModel)) { 297 foreach($queryColumnsByFieldModel as $field) { 298 $this->reportRun->queryPlanner->addTable($field->get('table')); 299 $columns[] = $field->get('reportcolumn'); 300 } 301 } 302 303 $groupByColumnsByFieldModel = $this->getGroupbyColumnsByFieldModel(); 304 305 if(is_array($groupByColumnsByFieldModel)) { 306 foreach($groupByColumnsByFieldModel as $groupField) { 307 $this->reportRun->queryPlanner->addTable($groupField->get('table')); 308 $groupByColumns[] = $groupField->get('reportlabel'); 309 $columns[] = $groupField->get('reportcolumn'); 310 } 311 } 312 313 $sql = split(' from ', $this->reportRun->sGetSQLforReport($reportModel->getId(), $advFilterSql, 'PDF')); 314 315 $columnLabels = array(); 316 317 $chartSQL = "SELECT "; 318 if($this->isRecordCount()) { 319 $chartSQL .= " count(*) AS RECORD_COUNT,"; 320 } 321 322 // Add other columns 323 if($columns && is_array($columns)) { 324 $columnLabels = array_merge($columnLabels, $groupByColumns); 325 $chartSQL .= implode(',', $columns); 326 } 327 328 $chartSQL .= " FROM $sql[1] "; 329 330 if($groupByColumns && is_array($groupByColumns)) { 331 $chartSQL .= " GROUP BY " . implode(',', $groupByColumns); 332 } 333 return $chartSQL; 334 } 335 336 /** 337 * Function generate links 338 * @param <String> $field - fieldname 339 * @param <Decimal> $value - value 340 * @return <String> 341 */ 342 function generateLink($field, $value) { 343 $reportRunObject= $this->getReportRunObject(); 344 345 $chartModel = $this->getParent(); 346 $reportModel = $chartModel->getParent(); 347 348 $filter = $reportRunObject->getAdvFilterList($reportModel->getId()); 349 350 // Special handling for date fields 351 $comparator = 'e'; 352 $dataFieldInfo = @explode(':', $field); 353 if(($dataFieldInfo[4] == 'D' || $dataFieldInfo[4] == 'DT') && !empty($dataFieldInfo[5])) { 354 $dataValue = explode(' ',$value); 355 if(count($dataValue) > 1) { 356 $comparator = 'bw'; 357 $value = date('Y-m-d H:i:s' ,strtotime($value)).','.date('Y-m-d' ,strtotime('last day of'.$value)).' 23:59:59'; 358 } else { 359 $comparator = 'bw'; 360 $value = date('Y-m-d H:i:s' ,strtotime('first day of JANUARY '.$value)).','.date('Y-m-d' ,strtotime('last day of DECEMBER '.$value)).' 23:59:59'; 361 } 362 } elseif($dataFieldInfo[4] == 'DT') { 363 $value = Vtiger_Date_UIType::getDisplayDateTimeValue($value); 364 } 365 366 if(empty($value)) { 367 $comparator = 'empty'; 368 } 369 370 //Step 1. Add the filter condition for the field 371 $filter[1]['columns'][] = array( 372 'columnname' => $field, 373 'comparator' => $comparator, 374 'value' => $value, 375 'column_condition' => '' 376 ); 377 378 //Step 2. Convert report field format to normal field names 379 foreach($filter as $index => $filterInfo) { 380 foreach($filterInfo['columns'] as $i => $column) { 381 if($column) { 382 $fieldInfo = @explode(':', $column['columnname']); 383 $filter[$index]['columns'][$i]['columnname'] = $fieldInfo[3]; 384 } 385 } 386 } 387 388 //Step 3. Convert advanced filter format to list view search format 389 $listSearchParams = array(); 390 $i=0; 391 if($filter) { 392 foreach($filter as $index => $filterInfo) { 393 foreach($filterInfo['columns'] as $j => $column) { 394 if($column) { 395 $listSearchParams[$i][] = array($column['columnname'], $column['comparator'], $column['value']); 396 } 397 } 398 $i++; 399 } 400 } 401 //Step 4. encode and create the link 402 $baseModuleListLink = $this->getBaseModuleListViewURL(); 403 return $baseModuleListLink.'&search_params='. json_encode($listSearchParams); 404 } 405 406 /** 407 * Function generates graph label 408 * @return <String> 409 */ 410 function getGraphLabel() { 411 return $this->getReportModel()->getName(); 412 } 413 } 414 415 class PieChart extends Base_Chart { 416 417 function generateData(){ 418 $db = PearDatabase::getInstance(); 419 $values = array(); 420 421 $chartSQL = $this->getQuery(); 422 $result = $db->pquery($chartSQL, array()); 423 $rows = $db->num_rows($result); 424 425 $queryColumnsByFieldModel = $this->getQueryColumnsByFieldModel(); 426 if(is_array($queryColumnsByFieldModel)) { 427 foreach($queryColumnsByFieldModel as $field) { 428 $sector = strtolower($field->get('reportlabel')); 429 $sectorField = $field; 430 } 431 } 432 433 if($this->isRecordCount()) { 434 $sector = strtolower('RECORD_COUNT'); 435 } 436 437 $groupByColumnsByFieldModel = $this->getGroupbyColumnsByFieldModel(); 438 439 if(is_array($groupByColumnsByFieldModel)) { 440 foreach($groupByColumnsByFieldModel as $groupField) { 441 $legend = $groupByColumns[] = $groupField->get('reportlabel'); 442 $legendField = $groupField; 443 } 444 } 445 446 $currentUserModel = Users_Record_Model::getCurrentUserModel(); 447 $currencyRateAndSymbol = getCurrencySymbolandCRate($currentUserModel->currency_id); 448 449 for($i = 0; $i < $rows; $i++) { 450 $row = $db->query_result_rowdata($result, $i); 451 $value = (float) $row[$sector]; 452 453 if(!$this->isRecordCount()) { 454 if($sectorField) { 455 if($sectorField->get('uitype') == '71' || $sectorField->get('uitype') == '72') { //convert currency fields 456 $value = (float) ($row[$sector]); 457 $value = CurrencyField::convertFromDollar($value, $currencyRateAndSymbol['rate']); 458 } else { 459 $value = (int) $sectorField->getDisplayValue($row[$sector]); 460 } 461 } 462 } 463 464 $values[] = $value; 465 466 //translate picklist and multiselect picklist values 467 if($legendField) { 468 $fieldDataType = $legendField->getFieldDataType(); 469 if($fieldDataType == 'picklist') { 470 $label = vtranslate($row[strtolower($legend)], $legendField->getModuleName()); 471 } else if($fieldDataType == 'multipicklist') { 472 $multiPicklistValue = $row[strtolower($legend)]; 473 $multiPicklistValues = explode(' |##| ', $multiPicklistValue); 474 foreach($multiPicklistValues as $multiPicklistValue) { 475 $labelList[] = vtranslate($multiPicklistValue, $legendField->getModuleName()); 476 } 477 $label = implode(',', $labelList); 478 } else if($fieldDataType == 'date') { 479 $label = Vtiger_Date_UIType::getDisplayDateValue($row[strtolower($legendField->get('reportlabel'))]); 480 } else if($fieldDataType == 'datetime') { 481 $label = Vtiger_Date_UIType::getDisplayDateTimeValue($row[strtolower($legendField->get('reportlabel'))]); 482 } else { 483 $label = $row[strtolower($legend)]; 484 } 485 } else { 486 $label = $row[strtolower($legend)]; 487 } 488 $labels[] = (strlen($label) > 30) ? substr($label, 0, 30).'..' : $label; 489 $links[] = $this->generateLink($legendField->get('reportcolumninfo'), $row[strtolower($legend)]); 490 } 491 492 $data = array( 'labels' => $labels, 493 'values' => $values, 494 'links' => $links, 495 'graph_label' => $this->getGraphLabel() 496 ); 497 return $data; 498 } 499 } 500 501 class VerticalbarChart extends Base_Chart { 502 function generateData() { 503 $db = PearDatabase::getInstance(); 504 $chartSQL = $this->getQuery(); 505 506 $result = $db->pquery($chartSQL, array()); 507 $rows = $db->num_rows($result); 508 $values = array(); 509 510 $queryColumnsByFieldModel = $this->getQueryColumnsByFieldModel(); 511 512 $recordCountLabel = ''; 513 if($this->isRecordCount()) { 514 $recordCountLabel = 'RECORD_COUNT'; 515 } 516 517 $groupByColumnsByFieldModel = $this->getGroupbyColumnsByFieldModel(); 518 519 $currentUserModel = Users_Record_Model::getCurrentUserModel(); 520 $currencyRateAndSymbol = getCurrencySymbolandCRate($currentUserModel->currency_id); 521 $links = array(); 522 523 for($i = 0; $i < $rows; $i++) { 524 $row = $db->query_result_rowdata($result, $i); 525 526 if($recordCountLabel) { 527 $values[$i][] = (int) $row[strtolower($recordCountLabel)]; 528 } 529 530 if($queryColumnsByFieldModel) { 531 foreach($queryColumnsByFieldModel as $fieldModel) { 532 if($fieldModel->get('uitype') == '71' || $fieldModel->get('uitype') == '72') { 533 $value = (float) ($row[strtolower($fieldModel->get('reportlabel'))]); 534 $values[$i][] = CurrencyField::convertFromDollar($value, $currencyRateAndSymbol['rate']); 535 } else { 536 $values[$i][] = (int) $row[strtolower($fieldModel->get('reportlabel'))]; 537 } 538 } 539 } 540 541 if($groupByColumnsByFieldModel) { 542 foreach($groupByColumnsByFieldModel as $gFieldModel) { 543 $fieldDataType = $gFieldModel->getFieldDataType(); 544 if($fieldDataType == 'picklist') { 545 $label = vtranslate($row[strtolower($gFieldModel->get('reportlabel'))], $gFieldModel->getModuleName()); 546 } else if($fieldDataType == 'multipicklist') { 547 $multiPicklistValue = $row[strtolower($gFieldModel->get('reportlabel'))]; 548 $multiPicklistValues = explode(' |##| ', $multiPicklistValue); 549 foreach($multiPicklistValues as $multiPicklistValue) { 550 $labelList[] = vtranslate($multiPicklistValue, $gFieldModel->getModuleName()); 551 } 552 $label = implode(',', $labelList); 553 } else if($fieldDataType == 'date') { 554 $label = Vtiger_Date_UIType::getDisplayDateValue($row[strtolower($gFieldModel->get('reportlabel'))]); 555 } else if($fieldDataType == 'datetime') { 556 $label = Vtiger_Date_UIType::getDisplayDateTimeValue($row[strtolower($gFieldModel->get('reportlabel'))]); 557 } else { 558 $label = $row[strtolower($gFieldModel->get('reportlabel'))]; 559 } 560 $labels[] = (strlen($label) > 30) ? substr($label, 0, 30).'..' : $label; 561 $links[] = $this->generateLink($gFieldModel->get('reportcolumninfo'), $row[strtolower($gFieldModel->get('reportlabel'))]); 562 } 563 } 564 } 565 566 $data = array( 'labels' => $labels, 567 'values' => $values, 568 'links' => $links, 569 'type' => (count($values[0]) == 1) ? 'singleBar' : 'multiBar', 570 'data_labels' => $this->getDataLabels(), 571 'graph_label' => $this->getGraphLabel() 572 ); 573 return $data; 574 } 575 576 function getDataLabels() { 577 $dataLabels = array(); 578 if($this->isRecordCount()) { 579 $dataLabels[] = vtranslate('LBL_RECORD_COUNT', 'Reports'); 580 } 581 $queryColumnsByFieldModel = $this->getQueryColumnsByFieldModel(); 582 if($queryColumnsByFieldModel) { 583 foreach($queryColumnsByFieldModel as $fieldModel) { 584 $fieldTranslatedLabel = $this->getTranslatedLabelFromReportLabel($fieldModel->get('reportlabel')); 585 $reportColumn = $fieldModel->get('reportcolumninfo'); 586 $reportColumnInfo = explode(':', $reportColumn); 587 588 $aggregateFunction = $reportColumnInfo[5]; 589 $aggregateFunctionLabel = $this->getAggregateFunctionLabel($aggregateFunction); 590 591 $dataLabels[] = vtranslate($aggregateFunctionLabel, 'Reports', $fieldTranslatedLabel); 592 } 593 } 594 return $dataLabels; 595 } 596 } 597 598 class HorizontalbarChart extends VerticalbarChart { 599 600 } 601 602 class LineChart extends VerticalbarChart{ 603 604 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |