_name = $name; $this->_interval = $interval; $this->_alias = $alias; $this->_sqlname = $alias; $this->_tName = $table; $this->_connection = $connection; $this->cipherer = $cipherer; if($table != '') $this->pSet = new ProjectSettings($table); } function getStringSql($forGroupedField = false) { die; } function getFieldName($fieldValue, $data = null) { die; } function getSelectSql($hasGrouping = false) { return $this->getStringSql(true) . ($this->alias() ? ' as ' . cached_ffn($this->alias()) : ''); } function getGroupSql() { return $this->getStringSql(); } function getOrderSql() { //return $this->alias().' ASC'; return $this->getStringSql().' '.$this->_orderBy.' '; } function getWhereSql($groups) { die; } function getGroup($data) { return $data[$this->alias()]; } function getKey($data) { return $data[$this->alias()]; } function setStart($start) { $this->_start = $start; $this->_sqlname = $this->alias(); return $start + 1; } function name() { return $this->_name; } function alias() { return $this->_alias . $this->_start; } function overrideFormat() { return false; } function setCaseSensitive($cs) { $this->_caseSensitive = $cs; } function cutNull(&$range, $checkEmty = false) { $ret = false; $out = array(); for($nCnt = 0; $nCnt < count($range); $nCnt++) { $b = false; if($range[$nCnt] === null) { $b = true; $ret = true; } else { if($checkEmty && (!$range[$nCnt] || strcasecmp($range[$nCnt], 'null') == 0)) { $b = true; $ret = true; } } if(!$b) { $out []= $range[$nCnt]; } } $range = $out; return $ret; } function getLtGt(&$lt, &$gt) { if($this->_orderBy != 'ASC') { $lt = ' >= '; $gt = ' <= '; } else { $lt = ' <= '; $gt = ' >= '; } } } class ReportNumericField extends ReportField { function ReportNumericField($name, $interval, $alias, $table, $connection, $cipherer) { ReportField::ReportField($name, $interval, $alias, $table, $connection, $cipherer); } function getStringSql($forGroupedField = false) { $fname = $this->_oldAlgorithm ? RunnerPage::_getFieldSQL($this->_name, $this->_connection, $this->pSet) : cached_ffn($this->_name, true); if($this->_interval > 0) { if( $this->_connection->dbType == nDATABASE_MySQL || $this->_connection->dbType == nDATABASE_MSSQLServer || $this->_connection->dbType == nDATABASE_PostgreSQL ) return 'floor('.$fname.'/'.$this->_interval.')*'.$this->_interval; if( $this->_connection->dbType == nDATABASE_Access ) return 'Int('.$fname.'/'.$this->_interval.')*'.$this->_interval; if( $this->_connection->dbType == nDATABASE_Oracle ) return '(floor('.$fname.'/'.$this->_interval.')*'.$this->_interval.')'; } else { return $fname; } } function getFieldName($fieldValue, $data) { $value = $data[$this->_recordBasedRequest ? $this->_name : $this->_sqlname]; if($value == null) return 'NULL'; if($this->_interval > 0) return intval($value) . ' - ' . (intval($value) + $this->_interval); else return $value; } function getKey($data) { if($this->_recordBasedRequest) { if($this->_interval > 0) return intval($data[$this->_name]/$this->_interval)*$this->_interval; else return $data[$this->_name]; } else return ReportField::getKey($data); } function getWhereSql($groups) { $ret = ''; $ssql = $this->getStringSql(); $hasNull = $this->cutNull($groups); if(count($groups) > 0) { $lt = ''; $gt = ''; $this->getLtGt($lt, $gt); $ret = '('.$ssql.$gt.$groups[0].' AND '.$ssql.$lt.$groups[count($groups) - 1].')'; } if($hasNull) { $ret .= ($ret ? ' OR ' : '').$ssql.' IS NULL'; } return $ret ? '('.$ret.')' : ''; } } class ReportCharField extends ReportField { function ReportCharField($name, $interval, $alias, $table, $connection, $cipherer) { ReportField::ReportField($name, $interval, $alias, $table, $connection, $cipherer); } function getStringSql($forGroupedField = false) { $fname = $this->_oldAlgorithm && !$forGroupedField ? RunnerPage::_getFieldSQL($this->_name, $this->_connection, $this->pSet) : cached_ffn($this->_name, $forGroupedField); if($this->_interval > 0) { if( $this->_connection->dbType == nDATABASE_MySQL || $this->_connection->dbType == nDATABASE_PostgreSQL ) return 'substr('.$fname.', 1, '.$this->_interval.')'; if( $this->_connection->dbType == nDATABASE_MSSQLServer ) return 'substring('.$fname.', 1, '.$this->_interval.')'; if( $this->_connection->dbType == nDATABASE_Access ) return 'Mid('.$fname.', 1, '.$this->_interval.')'; if( $this->_connection->dbType == nDATABASE_Oracle ) return 'SUBSTR('.$fname.', 1, '.$this->_interval.')'; } else { return $fname; } } function getFieldName($fieldValue, $data) { $value = $data[$this->_recordBasedRequest ? $this->_name : $this->_sqlname]; if($value == null) return 'NULL'; if($this->_interval > 0) return substr($value, 0, $this->_interval); else return $value; } function getKey($data) { if($this->_recordBasedRequest) { if($this->_interval > 0) { if($this->_caseSensitive) return substr($data[$this->_name], 0, $this->_interval); else return strtolower(substr($data[$this->_name], 0, $this->_interval)); } else { if($this->_caseSensitive) return $data[$this->_name]; else return strtolower($data[$this->_name]); } } else { if($this->_caseSensitive) return $data[$this->alias()]; else return strtolower($data[$this->alias()]); } } function getWhereSql($groups) { $ret = ''; $ssql = $this->getStringSql(); $hasNull = $this->cutNull($groups); if(count($groups) > 0) { $gr = array(); foreach($groups as $g) $gr []= '\''.$g.'\''; $lt = ''; $gt = ''; $this->getLtGt($lt, $gt); $ret = "(".$ssql.$gt.$this->_connection->prepareString( $groups[0] ) ." AND ".$ssql.$lt.$this->_connection->prepareString($groups[count($groups) - 1]).")"; } if($hasNull) { $ret .= ($ret ? ' OR ' : '').$ssql.' IS NULL'; $ret .= ' OR '.$ssql.'=\'\''; } return $ret ? '('.$ret.')' : ''; } } class ReportDateField extends ReportField { function ReportDateField($name, $interval, $alias, $table, $connection, $cipherer) { ReportField::ReportField($name, $interval, $alias, $table, $connection, $cipherer); } function setStart($start) { $this->_start = $start; if($this->_interval == 0) $this->_sqlname = $this->alias(); else $this->_sqlname = $this->alias().'MIN'; return $start + ($this->_interval > 0 ? $this->_interval : 1); } function getSqlList($all = true) { $grp = array(); $fname = $this->_oldAlgorithm ? RunnerPage::_getFieldSQLDecrypt($this->_name, $this->_connection, $this->pSet, $this->cipherer) : cached_ffn($this->_name); if($all) { // array = (year, quarter, month, week, day of week, full date, hour, minute) // each element = array(sql begin, sql end, prev index) if( $this->_connection->dbType == nDATABASE_MySQL ) { $symbols = array(array('YEAR(', ')', -1), array('QUARTER(', ')', 0), array('MONTH(', ')', 0), array('WEEK(', ')', 0), array('DATE(', ')', -1), array('HOUR(', ')', 4), array('MINUTE(', ')', 5)); } elseif( $this->_connection->dbType == nDATABASE_PostgreSQL ) { $symbols = array(array('date_part(\'year\', ', ')', -1), array('date_trunc(\'quarter\', ', ')', -1), array('date_trunc(\'month\', ', ')', -1), array('date_trunc(\'week\', ', ')', -1), array('date_trunc(\'day\', ', ')', -1), array('date_trunc(\'hour\', ', ')', 1), array('date_trunc(\'minute\', ', ')', -1)); } elseif( $this->_connection->dbType == nDATABASE_MSSQLServer ) { $symbols = array(array('DATEPART(year, ', ')', -1), array('DATEPART(quarter, ', ')', 0), array('DATEPART(month, ', ')', 0), array('DATEPART(week, ', ')', 0), array('DATEPART(day, ', ')', 2), array('DATEPART(hour, ', ')', 4), array('DATEPART(minute, ', ')', 5)); } elseif( $this->_connection->dbType == nDATABASE_Access ) { global $locale_info; $first_day_of_week=1; if($locale_info["LOCALE_IFIRSTDAYOFWEEK"]=="0") $first_day_of_week=2; $symbols = array(array('DatePart(\'yyyy\', ', ')', -1), array('DatePart(\'q\', ', ')', 0), array('DatePart(\'m\', ', ')', 0), array('DatePart(\'ww\', ', ','.$first_day_of_week.')', 0), array('DatePart(\'d\', ', ')', 2), array('DatePart(\'h\', ', ')', 4), array('DatePart(\'n\', ', ')', 5)); } elseif( $this->_connection->dbType == nDATABASE_Oracle ) { $symbols = array(array('EXTRACT(year from ', ')', -1), array('FLOOR(EXTRACT(month from ', ')/3)', 0), array('EXTRACT(month from ', ')', 0), array('TRUNC(', ', \'D\')', -1), array('TRUNC(', ', \'J\')', -1), array('TRUNC(hour from ', ')', -1), array('TRUNC(minute from ', ')', -1)); } $idx = $this->_interval - 1; do { array_unshift($grp, $symbols[$idx][0].cached_ffn($this->_name).$symbols[$idx][1]); $idx = $symbols[$idx][2]; } while($idx >= 0); } return $grp; } function getSelectSql($hasGrouping) { $fname = $this->_oldAlgorithm ? RunnerPage::_getFieldSQLDecrypt($this->_name, $this->_connection, $this->pSet, $this->cipherer) : cached_ffn($this->_name, true); if($this->_interval == 0) { return $fname . ' as ' . cached_ffn($this->alias()); } else { $grp = $this->getSqlList(); for($nCnt = 0; $nCnt < count($grp); $nCnt ++) { $grp[$nCnt] .= ' as ' . cached_ffn($this->_alias.($nCnt + $this->_start)); } if($hasGrouping) { $grp[] = 'MIN('.$fname.') as '.cached_ffn($this->alias().'MIN'); $grp[] = 'MAX('.$fname.') as '.cached_ffn($this->alias().'MAX'); } else $grp[] = $fname.' as '.cached_ffn($this->alias().'MIN'); return join(', ', $grp); } } function getGroupSql() { if($this->_interval == 0) { return cached_ffn($this->_name); } else { $grp = $this->getSqlList(); return join(', ', $grp); } } function getOrderSql() { if($this->_interval == 0) { $fname = $this->_oldAlgorithm ? RunnerPage::_getFieldSQLDecrypt($this->_name, $this->_connection, $this->pSet, $this->cipherer) : cached_ffn($this->_name); return $fname.' '.$this->_orderBy.' '; } else { $grp = $this->getSqlList(); $newgrp = array(); foreach($grp as $g) $newgrp[] = $g . ' '.$this->_orderBy.' '; return join(', ', $newgrp); } } function getWhereSql($groups) { $ret = ''; $hasNull = $this->cutNull($groups, true); if(count($groups) > 0) { $lt = ''; $gt = ''; if($this->_interval == 0) { $this->getLtGt($lt, $gt); $ret = '('.cached_ffn($this->_name).' '.$gt.' '.$this->_connection->addDateQuotes($groups[0]). ' AND '.cached_ffn($this->_name).' '.$lt.' '.$this->_connection->addDateQuotes($groups[count($groups)-1]).')'; } else { if($groups[0]['MIN'] <= $groups[count($groups) - 1]['MAX']) { $ret = '('.cached_ffn($this->_name).' >= '.$this->_connection->addDateQuotes($groups[0]['MIN']). ' AND '.cached_ffn($this->_name).' <= '.$this->_connection->addDateQuotes($groups[count($groups)-1]['MAX']).')'; } else { $ret = '('.cached_ffn($this->_name).' <= '.$this->_connection->addDateQuotes($groups[0]['MAX']). ' AND '.cached_ffn($this->_name).' >= '.$this->_connection->addDateQuotes($groups[count($groups)-1]['MIN']).')'; } } } if($hasNull) $ret .= ($ret ? ' OR ' : '').cached_ffn($this->_name).' IS NULL '; return $ret ? '('.$ret.')' : ''; } function getFieldName($fieldValue, $data) { global $locale_info; $value = $data[ $this->_recordBasedRequest ? $this->_name : $this->_sqlname ]; if($value == null || !$value || strcasecmp($value, 'null') == 0) return 'NULL'; if($this->_interval == 0) { if($this->_viewFormat) { global $pageObject; if( !$this->_recordBasedRequest ) $data[ $this->_name ] = $value; return $pageObject->formatReportFieldValue($this->_name, $data); } else { $date = db2time($value); return str_format_datetime($date); } } switch($this->_interval) { case 1: $date = cached_db2time($value); return $date[0]; case 2: $date = cached_db2time($value); return $date[0] . '/Q' . intval($date[1]/3); case 3: $date = cached_db2time($value); return @$locale_info["LOCALE_SABBREVMONTHNAME".$date[1]]." ".$date[0]; case 4: return cached_formatweekstart($value); case 5: $date = cached_db2time($value); return format_shortdate($date); case 6: $date = db2time($value); $date[4]=0; $date[5]=0; return str_format_datetime($date); case 7: $date = db2time($value); $date[5]=0; return str_format_datetime($date); } } function getGroup($data) { if($this->_interval == 0) return $data[$this->alias()]; else { if($data[$this->alias().'MIN'] == null || $data[$this->alias().'MAX'] == null) return null; else return array('MIN' => $data[$this->alias().'MIN'], 'MAX' => $data[$this->alias().'MAX']); } } function getKey($data) { if(!$this->_recordBasedRequest) { if($this->_interval == 0) { return $data[$this->alias()]; } else { $key = array(); for($nCnt = $this->_start; $nCnt < $this->_interval + $this->_start; $nCnt++) { $key []= $data[$this->_alias.$nCnt]; } return join('-', $key); } } else { $strdate = $data[$this->_name]; if($strdate == null) return 'NULL'; if($this->_interval == 0) { return $strdate; } else { switch($this->_interval) { case 1: $date = cached_db2time($strdate); return $date[0]; case 2: $date = cached_db2time($strdate); return $date[0].'-'.intval($date[1]/3); case 3: $date = cached_db2time($strdate); return $date[0].'-'.$date[1]; case 4: $start = cached_getweekstart($strdate); return $start[0].'-'.$start[1].'-'.$start[2]; case 5: $date = cached_db2time($strdate); return $date[0].'-'.$date[1].'-'.$date[2]; case 6: $date = db2time($strdate); return $date[0].'-'.$date[1].'-'.$date[2].'-'.$date[3]; case 7: $date = db2time($strdate); return $date[0].'-'.$date[1].'-'.$date[2].'-'.$date[3].'-'.$date[4]; } } } } function overrideFormat() { return true; } function cutNull(&$range, $checkEmpty = false) { $ret = false; $out = array(); for($nCnt = 0; $nCnt < count($range); $nCnt++) { $b = false; if($range[$nCnt] === null) { $b = true; $ret = true; } else { if($checkEmpty) { if(is_array($range[$nCnt])) { if(!$range[$nCnt]['MIN'] || strcasecmp($range[$nCnt]['MIN'], 'null') == 0) { $b = true; $ret = true; } } else { if(!$range[$nCnt] || strcasecmp($range[$nCnt], 'null') == 0) { $b = true; $ret = true; } } } } if(!$b) { $out []= $range[$nCnt]; } } $range = $out; return $ret; } } function getFormattedValue($pageObject, $value, $fieldName, $strViewFormat, $strEditFormat = '', $mode = MODE_LIST) { if($strViewFormat == FORMAT_TIME && is_numeric($value)) { $val = ''; $d = intval($value / 86400); $h = intval(($value % 86400) / 3600); $m = intval((($value % 86400) % 3600) / 60); $s = (($value % 86400) % 3600) % 60; $val .= $d > 0 ? $d . 'd ' : ''; $val .= str_format_time(array(0, 0, 0, $h, $m, $s)); } else { $arrValue = array($fieldName => $value); $val = $pageObject->formatReportFieldValue( $fieldName, $arrValue ); // $val = $pageObject->getViewControl($fieldName, $strViewFormat)->showDBValue($arrValue,""); } return $val; } $cache_db2time = array(); function cached_db2time($strtime) { global $cache_db2time; if(!isset($cache_db2time[$strtime])) { $res = db2time($strtime); $cache_db2time[$strtime] = $res; return $res; } else return $cache_db2time[$strtime]; } $cache_getdayofweek = array(); function cached_getdayofweek($strtime) { global $cache_getdayofweek; if(!isset($cache_getdayofweek[$strtime])) { $date = cached_db2time($strtime); $res = getdayofweek($date); $cache_getdayofweek[$strtime] = $res; return $res; } else return $cache_getdayofweek[$strtime]; } $cache_getweekstart = array(); function cached_getweekstart($strtime) { global $cache_getweekstart; if(!isset($cache_getweekstart[$strtime])) { $date = cached_db2time($strtime); $res = getweekstart($date); $cache_getweekstart[$strtime] = $res; return $res; } else return $cache_getweekstart[$strtime]; } $cache_formatweekstart = array(); function cached_formatweekstart($strtime) { global $cache_formatweekstart; if(!isset($cache_formatweekstart[$strtime])) { $start = cached_getweekstart($strtime); $end = adddays($start, 6); $res = format_shortdate($start)." - ".format_shortdate($end); $cache_formatweekstart[$strtime] = $res; return $res; } else return $cache_formatweekstart[$strtime]; } $cache_fullfieldname = array(); function cached_ffn($field, $forGroupedField = false) { global $cache_fullfieldname, $strTableName, $cman; if(!isset($cache_fullfieldname[$field])) { // commented for bug 6660. Correct fix needed // if(!$wr_is_standalone && !$forGroupedField) $res = GetFullFieldName($field,$strTableName,false); else { $connection = $cman->byTable( $strTableName ); $res = $connection->addFieldWrappers($field); //#9875 } $cache_fullfieldname[$field] = $res; return $res; } else return $cache_fullfieldname[$field]; } /////////////////////////////////////////////////////////////////////////////////// class SQLStatement { var $_fields = array(); var $_hasDetails = true; var $_originalSql = null; var $_order_in; var $_order_out; var $_order_old; var $_aggregates = array(); var $_skipCount = 0; var $_reportGlobalSummary = true; var $_reportSummary = true; var $_details = true; var $_from = 0; /* * Total number elements (groups or records) to show * 0 - show all */ var $_groupsTotal; var $_limitLevel = 0; var $_hasGroups = true; var $_recordBasedRequest = false; var $_oldAlgorithm = false; // report table info var $tName = ''; var $shortTName = ''; /* * number of group fields * @type int */ var $repGroupFieldsCount = 0; var $repPageSummary = 0; var $repGlobalSummary = 0; var $repLayout = 0; var $showGroupSummaryCount = 0; var $repShowDet = 0; // report field info var $repGroupFields = array(); // current table key fields var $tKeyFields = array(); // if any field used for totals var $isExistTotalFields = false; // table fields list var $fieldsArr = array(); // Order by fields info var $orderIndexes; // Instance of ProjectSettings var $pSet = null; /** * @type Connection */ var $_connection; var $_cipherer; var $searchWhereClause = ""; var $searchHavingClause = ""; function SQLStatement($sql, $order, $groupsTotal, $connection, &$params, $searchWhereClause, $searchHavingClause, $cipherer) { // copy properties to object RunnerApply($this, $params); $this->_connection = $connection; $this->_cipherer = $cipherer; $this->searchWhereClause = $searchWhereClause; $this->searchHavingClause = $searchHavingClause; $this->pSet = new ProjectSettings($this->tName, PAGE_REPORT); if(!is_array($sql)) die ('Invalid sql parameter'); global $reportCaseSensitiveGroupFields; // add search WHERE and HAVING clauses to the page's SQL $this->_originalSql = $this->applyWhere($sql); $start = 0; $fields = array(); for($i=0; $irepGroupFields); $i++) { for($j=0; $jfieldsArr); $j++) { if ($this->repGroupFields[$i]['strGroupField'] == $this->fieldsArr[$j]['name']) { $add = array(); $add['name'] = $this->fieldsArr[$j]['name']; if (IsNumberType($this->pSet->getFieldType($this->fieldsArr[$j]['name']))) { $add['type'] = 'numeric'; }elseif (IsCharType($this->pSet->getFieldType($this->fieldsArr[$j]['name']))){ $add['type'] = 'char'; $add['case_sensitive'] = $reportCaseSensitiveGroupFields; }elseif (IsDateFieldType($this->pSet->getFieldType($this->fieldsArr[$j]['name']))){ $add['type'] = 'date'; }else{ $add['type'] = 'char'; } $add['interval'] = $this->repGroupFields[$i]['groupInterval']; $add['viewformat'] = $this->fieldsArr[$j]['viewFormat']; $add['rowsinsummary'] = 1; if ($this->fieldsArr[$j]['totalMax'] || $this->fieldsArr[$j]['totalMin'] || $this->fieldsArr[$j]['totalAvg'] || $this->fieldsArr[$j]['totalSum']) { $add['rowsinsummary'] ++; } if ($this->repLayout == REPORT_STEPPED) { $add['rowsinheader'] = 1; }elseif ($this->repLayout == REPORT_BLOCK){ $add['rowsinheader'] = 0; }elseif ($this->repLayout == REPORT_OUTLINE || $this->repLayout == REPORT_ALIGN){ if ($j == count($this->fieldsArr)-1) { $add['rowsinheader'] = 2; }else{ $add['rowsinheader'] = 1; } }elseif ($this->repLayout == REPORT_TABULAR){ $add['rowsinheader'] = 0; } $fields []= $add; } } } $this->_hasGroups = count($fields) > 0; foreach($fields as $field) { $f = create_reportfield($field['name'], $field['type'], $field['interval'], 'grp', $this->tName, $this->_connection, $this->_cipherer); $start = $f->setStart($start); if(isset($field['case_sensitive'])) $f->setCaseSensitive($field['case_sensitive']); if(isset($field['rowsinsummary'])) $f->_rowsInSummary = $field['rowsinsummary']; if(isset($field['rowsinheader'])) $f->_rowsInHeader = $field['rowsinheader']; $f->_viewFormat = $field['viewformat']; $this->_fields []= $f; } // order if($order) { $order_in = array(); $order_out = array(); $order_old = array(); foreach($order as $o) { $order_in []= $o[2] . ' as ' . cached_ffn('originalorder'.$o[0]); $order_out []= cached_ffn('originalorder'.$o[0]).' '.$o[1]; $groupField = false; for($i=0; $irepGroupFields); $i++) { for($j=0; $jfieldsArr); $j++) { if ($this->repGroupFields[$i]['strGroupField'] == $this->fieldsArr[$j]['name']) { $fieldIndex = $this->pSet->getFieldIndex($this->repGroupFields[$i]['strGroupField']); if($fieldIndex == $o[0]) { $n = $this->repGroupFields[$i]['groupOrder']-1; $this->_fields[$n]->_orderBy = $o[1]; $groupField = true; } } } } // don't add group fields to the $order_old if(!$groupField) $order_old []= $o[2].' '.$o[1]; } $this->_order_in = join(', ', $order_in); $this->_order_out = join(', ', $order_out); $this->_order_old = join(', ', $order_old); } for($i=0; $ifieldsArr); $i++) { if ($this->fieldsArr[$i]['totalMax']) { $this->_aggregates []= 'MAX('.cached_ffn($this->fieldsArr[$i]['name'], true).') as '.cached_ffn($this->fieldsArr[$i]['name']."MAX"); } if ($this->fieldsArr[$i]['totalMin']){ $this->_aggregates []= 'MIN('.cached_ffn($this->fieldsArr[$i]['name'], true).') as '.cached_ffn($this->fieldsArr[$i]['name']."MIN"); } if ($this->fieldsArr[$i]['totalAvg']){ if (!IsDateFieldType($this->pSet->getFieldType($this->fieldsArr[$i]['name']))) { $this->_aggregates []= 'AVG('.cached_ffn($this->fieldsArr[$i]['name'], true).') as '.cached_ffn($this->fieldsArr[$i]['name']."AVG"); $this->_aggregates []= 'COUNT('.cached_ffn($this->fieldsArr[$i]['name'], true).') as '.cached_ffn($this->fieldsArr[$i]['name']."NAVG"); } } if ($this->fieldsArr[$i]['totalSum']){ if (!IsDateFieldType($this->pSet->getFieldType($this->fieldsArr[$i]['name']))) { $this->_aggregates []= 'SUM('.cached_ffn($this->fieldsArr[$i]['name'], true).') as '.cached_ffn($this->fieldsArr[$i]['name']."SUM"); } } } $this->_reportSummary = $this->repPageSummary || $this->repGlobalSummary; $this->_groupsTotal = $groupsTotal; } function getOriginal($useOriginalOrder = true) { global $strTableName; $sql = $this->_originalSql; if(tableEventExists("BeforeQueryReport", $strTableName)) { $hwhere = $sql[2]; $eventObj = getEventObject($strTableName); $eventObj->BeforeQueryReport($hwhere); $sql[2] = $hwhere; } return $sql[0].' '.($useOriginalOrder && $this->_order_in && !$this->_oldAlgorithm ? ', ' . $this->_order_in . ' ' : '').$sql[1].' '. ($sql[2] ? ' WHERE ' . $sql[2] : '').' '.$sql[3].' '.($sql[4] ? ' HAVING ' . $sql[4] : ''); } function setRecordBasedRequest($recordBasedRequest) { $this->_recordBasedRequest = $recordBasedRequest; for($nCnt = 0; $nCnt < count($this->_fields); $nCnt++) $this->_fields[$nCnt]->_recordBasedRequest = $recordBasedRequest; } function getGroup($data) { return $this->_fields[0]->getGroup($data); } function field($num) { return $this->_fields[$num]; } function getSQLLimits($sql, $from) { if($from >= 0 && $this->_groupsTotal > 0) { if( $this->_connection->dbType == nDATABASE_MySQL || $this->_connection->dbType == nDATABASE_PostgreSQL ) { $out = $sql.' LIMIT '.intval($this->_groupsTotal).' OFFSET '.intval($from); $this->_skipCount = 0; } elseif( $this->_connection->dbType == nDATABASE_MSSQLServer || $this->_connection->dbType == nDATABASE_Access ) { $nsel = stripos($sql, "select"); $out = substr_replace($sql, 'select top '.($from + $this->_groupsTotal), $nsel, strlen("select")); $this->_skipCount = $from; } elseif( $this->_connection->dbType == nDATABASE_Oracle ) { $out = 'select * from (select original2.*, rownum as '.cached_ffn('rownumber').' from ('. $sql.") original2) where ".cached_ffn('rownumber').' between '.$from.' and '.($from + $this->_groupsTotal); $this->_skipCount = 0; } return $out; } return $sql; } function sqlg($donotlimit = false, $doorder = true) { $hsql = array(); $s = array(); $g = array(); $o = array(); if($this->_hasGroups) { $s []= $this->_fields[0]->getSelectSql(true); $g []= $this->_fields[0]->getGroupSql(); $o []= $this->_fields[0]->getOrderSql(); } if(count($s)) $hsql['select'] []= join(', ', $s); if(count($g)) $hsql['groupby'] []= join(', ', $g); if(count($o) && $doorder) $hsql['orderby'] = join(', ', $o); if($this->_limitLevel == 1 && !$donotlimit) $hsql['limits'] = 1; return $this->buildsql($hsql); } function sqlcg() { $gsql = $this->sqlg(true, false); return 'select count(*) as '.cached_ffn("c").' from ('.$gsql.') countgroups'; } function sqlt() { $hsql = array(); $hsql['select'] []= 'count(1) as '.cached_ffn('countField'); if(count($this->_aggregates)) $hsql['select'] []= join(', ', $this->_aggregates); return $this->buildsql($hsql); } function sql2($groups = null) { $hsql = array(); if(!$this->_hasGroups || $this->_recordBasedRequest) { $hsql['original'] = true; $o = array(); foreach($this->_fields as $f) $o []= $f->getOrderSql(); if(count($o)) $hsql['orderby'] = join(', ', $o); } else { if($this->repShowDet) { $hsql['select'] []= 'original.*'; } else { if(count($this->_aggregates)) $hsql['select'] []= join(', ', $this->_aggregates); } $s = array(); $g = array(); $o = array(); foreach($this->_fields as $f) { $s []= $f->getSelectSql(!$this->repShowDet); if(!$this->repShowDet) $g []= $f->getGroupSql(); $o []= $f->getOrderSql(); } if($this->_reportSummary && $this->_hasGroups && !$this->repShowDet) { $hsql['select'] []= 'count(1) as '.cached_ffn('countField'); } if(count($s)) { $hsql['select'] []= join(', ', $s); } if($groups !== null && count($groups)) { $where = $this->_fields[0]->getWhereSql($groups); if($where) $hsql['where'] = $where; } if(count($g)) { $hsql['groupby'] = $g; } if(count($o)) { $hsql['orderby'] = join(', ', $o); } } if($this->_limitLevel == 2) { $hsql['limits'] = 1; } if($this->repShowDet) { $hsql['origorder'] = 1; } return $hsql; } function buildsql($hsql) { $this->_skipCount = 0; $ordered = false; if(count($hsql) == 0 || $hsql['original']) { $sql = $this->getOriginal(); } else { $sql = 'SELECT '; if($hsql['select'] && count($hsql['select']) > 0) $sql .= join(', ', $hsql['select']); else $sql .= ' * '; $sql .= ' FROM ('.$this->getOriginal($hsql['origorder']).') original'; if($hsql['where'] && count($hsql['where']) > 0) $sql .= ' WHERE '.$hsql['where']; if($hsql['groupby'] && count($hsql['groupby']) > 0) $sql .= ' GROUP BY '.join(', ', $hsql['groupby']); } $osql = ''; if($hsql['orderby'] && count($hsql['orderby']) > 0) { $osql .= $hsql['orderby']; $ordered = true; } if($hsql['origorder']) { if(!$this->_oldAlgorithm) { if($this->_order_out) { $osql .= ($osql ? ', ' : '').$this->_order_out; } } else { if($this->_order_old) { $osql .= ($osql ? ', ' : '').$this->_order_old; } } } if($osql) { $sql .= ' ORDER BY '.$osql; } if($hsql['limits']) $sql = $this->getSQLLimits($sql, $this->_from); return $sql; } /** * Add search WHERE and HAVING clauses * to the SQL representation array * @param &Array sql * @return Array; */ function applyWhere(&$sql) { if($this->searchWhereClause) { // set SQL WHERE $sql[2] = whereAdd($sql[2], $this->searchWhereClause); } if($this->searchHavingClause) { // set SQL HAVING if( $sql[4] ) $sql[4] = '('.$sql[4].') AND '; $sql[4] .= '('.$this->searchHavingClause.') '; } return $sql; } function setOldAlgorithm($useOldAlgorithm = true) { for($nCnt = 0; $nCnt < count($this->_fields); $nCnt ++) { $this->_fields[$nCnt]->_oldAlgorithm = $useOldAlgorithm; } $this->_oldAlgorithm = $useOldAlgorithm; } } //////////////////////////////////////////////////////////////////////////////////////// class Summarable { /* Array of all values used building report totals * Elements: * summary - array - array of values involved in totals calculating count MIN MAX AVG SUM _first - array of field values from the database _begin - row? _end - row? values - array where keys are group keys - another underlying summary */ var $_summary = array(); // report table info var $tName = ''; var $shortTName = ''; /* * number of group fields * @type int */ var $repGroupFieldsCount = 0; var $repPageSummary = 0; var $repGlobalSummary = 0; var $repLayout = 0; var $showGroupSummaryCount = 0; var $repShowDet = 0; // report field info var $repGroupFields = array(); // current table key fields var $tKeyFields = array(); // if any field used for totals var $isExistTotalFields = false; // table fields list var $fieldsArr = array(); var $cipherer = null; function Summarable(&$params) { RunnerApply($this, $params); Summarable::init(); } function init($from = 0) { $this->_from = $from; $this->cipherer = new RunnerCipherer($this->tName); } function writeGroup(&$begin, &$end, $gkey, $grp, $nField) {} /* * Update summary totals with the new fetched record data * * $recordsMode - true if report is being built from raw SQL query and false if the query is grouped * $summary - a summary to update * $data - record fetched from the database * $nTotalRecords - global records counter */ function addSummary($recordsMode, &$summary, $data, &$nTotalRecords) { $countInGroup = isset($summary['count']) ? $summary['count'] : 0; if ($this->isExistTotalFields) { if(!is_array($summary['summary'])) $summary['summary']=array(); $s =& $summary['summary']; } if($recordsMode) { // report is built from raw query results for($i=0; $ifieldsArr); $i++) { $field = &$this->fieldsArr[$i]; $fieldName = $field['name']; if (!$field['totalMax'] && !$field['totalMin'] && !$field['totalAvg'] && !$field['totalSum']) { // no summary to calculate continue; } if($data[$fieldName] === null) continue; if(!is_array($s[$fieldName])) $s[$fieldName] = array(); if(!isset($s[$fieldName]['count'])) $s[$fieldName]['count'] = 0; if ($field['totalMax']) { if(!isset($s[$fieldName]['MAX']) || $s[$fieldName]['MAX'] < $data[$fieldName]) $s[$fieldName]['MAX'] = $data[$fieldName]; } if ($field['totalMin']){ if(!isset($s[$fieldName]['MIN']) || $s[$fieldName]['MIN'] > $data[$fieldName]) $s[$fieldName]['MIN'] = $data[$fieldName]; } if ($field['totalAvg']){ if ($field['viewFormat'] == "Time") { $avg_value = $this->value2time($data[$fieldName]); }else{ $avg_value = $data[$fieldName]; } $s[$fieldName]['AVG'] = $s[$fieldName]['AVG']*$s[$fieldName]['count'] + $avg_value; $s[$fieldName]['count'] ++; if($s[$fieldName]['count']!=0) $s[$fieldName]['AVG'] = $s[$fieldName]['AVG']/$s[$fieldName]['count']; } if ($field['totalSum']){ if ($field['viewFormat'] == "Time") { $s[$fieldName]['SUM'] += $this->value2time($data[$fieldName]); }else{ $s[$fieldName]['SUM'] += $data[$fieldName]; } } } $nTotalRecords ++; $countInGroup ++; } else { // report is built from grouped query results for($i=0; $ifieldsArr); $i++) { $field = &$this->fieldsArr[$i]; if ( !$field['totalMax'] && !$field['totalMin'] && !$field['totalAvg'] && !$field['totalSum'] ) { // no summary to calculate continue; } $fieldName = $field['name']; if( !is_array( $s[$fieldName] )) $s[ $fieldName ] = array(); $summaryField =& $s[$fieldName]; if ($field['totalMax']) { if($data[$fieldName."MAX"] !== null) { if(!isset($summaryField['MAX']) || $summaryField['MAX'] < $data[$fieldName."MAX"]) $summaryField['MAX'] = $data[$fieldName."MAX"]; } } if ($field['totalMin']){ if($data[$fieldName."MIN"] !== null) { if(!isset($summaryField['MIN']) || $summaryField['MIN'] > $data[$fieldName."MIN"]) $summaryField['MIN'] = $data[$fieldName."MIN"]; } } if ($field['totalAvg']){ if($data[$fieldName."AVG"] !== null) { if ($field['viewFormat'] == "Time") { $avg_value = $this->value2time($data[$fieldName."AVG"]); }else{ $avg_value = $data[$fieldName."AVG"]; } $summaryField['AVG'] = $summaryField['AVG']*$summaryField['count'] + $avg_value*$data[$fieldName."NAVG"]; $summaryField['count'] += $data[$fieldName."NAVG"]; if($summaryField['count']!=0) $summaryField['AVG'] = $summaryField['AVG']/$summaryField['count']; } } if ($field['totalSum']){ if($data[$fieldName."SUM"] !== null) { if ($field['viewFormat'] == "Time") { $summaryField['SUM'] += $this->value2time($data[$fieldName."SUM"]); }else{ $summaryField['SUM'] += $data[$fieldName."SUM"]; } } } } $nTotalRecords += $data['countField']; $countInGroup += $data['countField']; } $summary['count'] = $countInGroup; } function _makeSummary(&$summary, $deep) { if( !$summary['values'] ) return; foreach($summary['values'] as $gkey => $group) { $grp =& $summary['values'][$gkey]; if(isset($grp['values'])) $this->_makeSummary($grp, $deep + 1); if(isset($grp['_begin']) && isset($grp['_end'])) $this->writeGroup($grp['_begin'], $grp['_end'], $gkey, $grp, $deep); if(!is_array($summary['summary'])) $summary['summary']=array(); for($i=0; $ifieldsArr); $i++) { if(!is_array($summary['summary'][$this->fieldsArr[$i]['name']])) $summary['summary'][$this->fieldsArr[$i]['name']]=array(); if(is_array($grp['summary'])) { if(is_array($grp['summary'][$this->fieldsArr[$i]['name']])) { if ($this->fieldsArr[$i]['totalMax']) { if(isset($grp['summary'][$this->fieldsArr[$i]['name']]['MAX'])) { if(!isset($summary['summary'][$this->fieldsArr[$i]['name']]['MAX']) || $summary['summary'][$this->fieldsArr[$i]['name']]['MAX'] < $grp['summary'][$this->fieldsArr[$i]['name']]['MAX']) $summary['summary'][$this->fieldsArr[$i]['name']]['MAX'] = $grp['summary'][$this->fieldsArr[$i]['name']]['MAX']; } } if ($this->fieldsArr[$i]['totalMin']){ if(isset($grp['summary'][$this->fieldsArr[$i]['name']]['MIN'])) { if(!isset($summary['summary'][$this->fieldsArr[$i]['name']]['MIN']) || $summary['summary'][$this->fieldsArr[$i]['name']]['MIN'] > $grp['summary'][$this->fieldsArr[$i]['name']]['MIN']) $summary['summary'][$this->fieldsArr[$i]['name']]['MIN'] = $grp['summary'][$this->fieldsArr[$i]['name']]['MIN']; } } if ($this->fieldsArr[$i]['totalAvg']){ if(isset($grp['summary'][$this->fieldsArr[$i]['name']]['AVG'])) { $summary['summary'][$this->fieldsArr[$i]['name']]['AVG'] = $summary['summary'][$this->fieldsArr[$i]['name']]['AVG']*$summary['summary'][$this->fieldsArr[$i]['name']]['count'] + $grp['summary'][$this->fieldsArr[$i]['name']]['AVG']*$grp['summary'][$this->fieldsArr[$i]['name']]['count']; $summary['summary'][$this->fieldsArr[$i]['name']]['count'] += $grp['summary'][$this->fieldsArr[$i]['name']]['count']; if($summary['summary'][$this->fieldsArr[$i]['name']]['count']!=0) $summary['summary'][$this->fieldsArr[$i]['name']]['AVG'] = $summary['summary'][$this->fieldsArr[$i]['name']]['AVG']/$summary['summary'][$this->fieldsArr[$i]['name']]['count']; } }if ($this->fieldsArr[$i]['totalSum']){ if($grp['summary'][$this->fieldsArr[$i]['name']]['SUM']) $summary['summary'][$this->fieldsArr[$i]['name']]['SUM'] += $grp['summary'][$this->fieldsArr[$i]['name']]['SUM']; } } } } $summary['count'] += $grp['count']; } } function value2time($value) { $res = 0; $arr = parsenumbers($value); if(isset($arr[0])) $res += $arr[0] * 60 * 60; if(isset($arr[1])) $res += $arr[1] * 60; if(isset($arr[2])) $res += $arr[2]; return $res; } function time2printable($time) { return array(intval($time / (60 * 60)), intval($time / 60), $time % 60); } } class ReportGroups extends Summarable { var $_global; var $_totalRecords; var $_maxpages; var $_nGroup; var $_oldFirst; var $_from; var $_sql; /* * Total number elements (groups or records) to show * 0 - show all * @type int */ var $_groupsTotal; /** * @type Connection */ var $_connection; var $_allGroupsUsed; var $_countGroups; // report table info var $tName = ''; var $shortTName = ''; /* * number of group fields * @type int */ var $repGroupFieldsCount = 0; var $repPageSummary = 0; var $repGlobalSummary = 0; var $repLayout = 0; var $showGroupSummaryCount = 0; var $repShowDet = 0; // report field info var $repGroupFields = array(); // current table key fields var $tKeyFields = array(); // if any field used for totals var $isExistTotalFields = false; // table fields list var $fieldsArr = array(); function ReportGroups(&$sql, $connection, $groupsTotal, &$params) { // copy properties to object RunnerApply($this, $params); Summarable::Summarable($params); $this->init(); $this->_groupsTotal = $groupsTotal; $this->_sql =& $sql; $this->_connection = $connection; } function init($from = 0) { Summarable::init($from); $this->_global = array(); $this->_totalRecords = 0; $this->_maxpages = -1; $this->_from = $from; $this->_nGroup = -1; $this->_oldFirst = ''; $this->_allGroupsUsed = false; $this->_countGroups = 0; } function setGlobalSummary($recordsMode, $data) { $this->addSummary($recordsMode, $this->_global, $data, $this->_totalRecords); } function setGroup($data) { $field = $this->_sql->field(0); $firstKey = $field->getKey($data); if($firstKey != $this->_oldFirst) { $this->_nGroup ++; $this->_oldFirst = $firstKey; } } function isVisibleGroup() { return $this->_nGroup >= $this->_from && $this->_nGroup < $this->_from + $this->_groupsTotal; } function getDisplayGroups($from) { $this->init($from); if( !$this->_groupsTotal ) { // request 'All Groups' return array(); } else { $groups = array(); $this->_allGroupsUsed = false; if ($this->repGroupFieldsCount) { $sql = $this->_sql->sqlg(); $qResult = $this->_connection->query( $sql ); while($data = $this->cipherer->DecryptFetchedArray( $qResult->fetchAssoc() )) { $groups[] = $this->_sql->getGroup($data); } if(count($groups) < $this->_groupsTotal) $this->_allGroupsUsed = true; } if($this->_sql->_skipCount > 0) { array_splice($groups, 0, $this->_sql->_skipCount); $this->_allGroupsUsed = false; } if($from > 0) { $this->_allGroupsUsed = false; } $this->_countGroups = count($groups); return $groups; } } function getCountGroups($fullRequest = false) { if ($this->repGroupFieldsCount) { if($this->_nGroup >= 0 && $fullRequest) { return $this->_nGroup + 1; } else { if($this->_allGroupsUsed) { return $this->_countGroups; } else { $sql = $this->_sql->sqlcg(); $fetchedArray = $this->_connection->query( $sql )->fetchAssoc(); $data = $this->cipherer->DecryptFetchedArray( $fetchedArray ); return $data['c']; } } }else{ return 0; } } function getSummary() { return $this->_global; } function allGroupsUsed() { return $this->_allGroupsUsed; } } class ReportLogic extends Summarable { var $_list; var $_totalRecords; var $_pages; /* * Total number elements (groups or records) to show * 0 - show all */ var $_groupsTotal; /* * Number elements (groups or records) to be displayed per page. * 0 - don't paginate */ var $_groupsPerPage; var $_groupCounter = 0; var $_from = 0; /** * @type Connection */ var $_connection; var $_sql; var $_groups; /* * An 0-based array containing a single element for each group field. * The element for each group is the group key - field value in simplest case. * The array is used when report is built from the raw data */ var $_groupKeys; var $_fullRequest = false; var $_recordBasedRequest = false; var $_doPaging = false; var $_lastPageNumber = 0; var $_pageSummary; var $_printRecordCount = 0; var $_listedRows = 0; var $_oldLevels; // report table info var $tName = ''; var $shortTName = ''; /* * number of group fields * @type int */ var $repGroupFieldsCount = 0; var $repPageSummary = 0; var $repGlobalSummary = 0; var $repLayout = 0; var $showGroupSummaryCount = 0; var $repShowDet = 0; // report field info var $repGroupFields = array(); // current table key fields var $tKeyFields = array(); // if any field used for totals var $isExistTotalFields = false; // table fields list var $fieldsArr = array(); var $cipherer = null; /** * Instance of RunnerPage or ViewControlsContainer * @var {object} */ var $pageObject = null; var $pSet = null; function ReportLogic($sql, $order, $connection, $groupsTotal, $groupsPerPage, &$params, $searchWhereClause, $searchHavingClause, $pageObject = null) { RunnerApply($this, $params); Summarable::Summarable($params); $this->_connection = $connection; $this->cipherer = new RunnerCipherer($this->tName); $this->_sql = new SQLStatement($sql, $order, $groupsTotal, $connection, $params, $searchWhereClause, $searchHavingClause, $this->cipherer ); $this->_groups = new ReportGroups($this->_sql, $connection, $groupsTotal, $params); $this->_groupsTotal = $groupsTotal; $this->_groupsPerPage = $groupsPerPage; $this->pSet = new ProjectSettings($this->tName, PAGE_REPORT); if(is_null($pageObject)) { include_once getabspath('classes/controls/ViewControlsContainer.php'); $this->pageObject = new ViewControlsContainer($this->pSet, PAGE_REPORT); } else $this->pageObject = $pageObject; $this->init(); } function init($from = 0) { Summarable::init($from); $this->_sql->_from = $from; $this->_list = array(); $this->_totalRecords = 0; $this->_pages = array(); $this->_groupKeys = array(); $this->_lastPageNumber = 0; $this->_pageSummary = array(); // $this->_printRecordCount = 0; $this->_listedRows = 0; $this->_oldLevels = array(); $this->cipherer = new RunnerCipherer($this->tName); } function getPages() { return $this->_pages; } /// logic function getFormattedRow($value) {} function writeGroup(&$begin, &$end, $gkey, $grp, $nField) {} function _writePage(&$page, $src, $count) {} function writeGlobalSummary($source) {} function writePageSummary() { if($this->_doPaging) { for($nCnt = 0; $nCnt < count($this->_list); $nCnt++) { if(!isset($this->_pages[$nCnt])) $this->_pages[$nCnt]=array(); $result =& $this->_pages[$nCnt]; if(isset($this->_pageSummary[$nCnt])) { $page = $this->_pageSummary[$nCnt]; $this->_writePage($result, isset($page['summary']) ? $page['summary'] : array(), isset($page['count']) ? $page['count'] : 0); } else $this->_writePage($result, array(), 0); } } else { $result = array(); $page = $this->_summary; $this->_writePage($result, isset($page['summary']) ? $page['summary'] : array(), isset($page['count']) ? $page['count'] : 0); $this->_summary = $result; } if(0 == count($this->_pages) && count($this->_list) > 0) $this->_pages []= $this->_summary; } function makeSummary() { $this->_makeSummary($this->_summary, 0); } /* * Update report with another record. Create a summary if needed. * * $recordsMode - true if report is being built from raw SQL query and false if the query is grouped * $data - record fetched from the database * $rowToAppend - record with formatted values to append (show raw data option) */ function setSummary($recordsMode, $data, $rowToAppend = null) { $level =& $this->_summary; $setBegin = false; if ($this->repGroupFieldsCount) { // get array of keys for current record $recordkeys = array(); for( $i = 0; $i < count( $this->repGroupFields ); $i++ ) { $groupIndex = $this->repGroupFields[ $i ][ 'groupOrder' ] - 1; $field = $this->_sql->field( $groupIndex ); $recordkeys[ $groupIndex ] = $field->getKey( $data ); } // add empty record for each closed group to hold its summary if( count($this->_groupKeys) > 0 ) { $changed = false; $nKey = 0; for(; $nKey < count($recordkeys); $nKey ++) { if($recordkeys[$nKey] != $this->_groupKeys[$nKey]) { $changed = true; break; } } if($changed) { // in reverse order for($nKey2 = count($recordkeys) - 1; $nKey2 >= $nKey; $nKey2 --) { $emptyRow =& $this->appendRow(array()); $field = $this->_sql->field($nKey2); $this->_printRecordCount += $field->_rowsInSummary; $this->_listedRows ++; $this->_oldLevels[$nKey2]['_end'] =& $emptyRow; } } // new top-level group if( $nKey == 0 ) ++$this->_groupCounter; } // store new record keys $this->_groupKeys = $recordkeys; // find current summary $levels = array(); for($i=0;$irepGroupFields); $i++) { $groupIndex = $this->repGroupFields[$i]['groupOrder'] - 1; $groupKey = $recordkeys[ $groupIndex ]; if(!isset($level['values'])) $level['values'] = array(); if(!isset($level['values'][ $groupKey ])) { $level['values'][ $groupKey ] = array(); $level =& $level['values'][ $groupKey ]; $field = $this->_sql->field( $groupIndex ); $this->_printRecordCount += $field->_rowsInHeader; $setBegin = true; $level['_first'] = $data; } else { $level =& $level[ 'values' ][ $groupKey ]; } $levels[] =& $level; } // and finally calculate summary $this->addSummary($recordsMode, $level, $data, $this->_totalRecords); $this->_oldLevels =& $levels; }else{ $this->addSummary($recordsMode, $level, $data, $this->_totalRecords); ++$this->_groupCounter; } if($rowToAppend) { $added =& $this->appendRow($rowToAppend); $this->_printRecordCount ++; $this->_listedRows ++; if($setBegin && $this->repGroupFieldsCount) { for($nCnt = 0; $nCnt < count($levels); $nCnt ++) if(!isset($levels[$nCnt]['_begin'])) $levels[$nCnt]['_begin'] =& $added; } } if ($this->repPageSummary) { if($this->_doPaging && $rowToAppend) { $nPage = count($this->_list) - 1; if(!isset($this->_pageSummary[$nPage])) $this->_pageSummary[$nPage]["count"]=0; $summaryCount = $this->_pageSummary[$nPage]['count']; $this->addSummary($recordsMode, $this->_pageSummary[$nPage], $data, $summaryCount); $this->_pageSummary[$nPage]['count'] = $summaryCount; } } } function setFinish() { if(count($this->_groupKeys) > 0) { for($nKey = count($this->_groupKeys) - 1; $nKey >= 0; $nKey --) { $field = $this->_sql->field($nKey); $this->_printRecordCount += $field->_rowsInSummary; $emptyRow =& $this->appendRow(array()); $this->_listedRows ++; $this->_oldLevels[$nKey]['_end'] =& $emptyRow; } } } function & appendRow($row) { if($this->_groupsPerPage) { $page = intval( ($this->_groupCounter - 1) / $this->_groupsPerPage); // OBSOLETE check we have no gaps in page list if($page > 0 && !isset($this->_list[$page - 1])) die("Increase number of records per print page to display report properly"); $this->_list[$page][] = $row; return $this->_list[$page][count($this->_list[$page]) - 1]; } else { $this->_list[] = $row; return $this->_list[count($this->_list) - 1]; } } function recordVisible($nRecord) { return // $this->_doPaging || // all records are printed, so there is no invisible records $this->_sql->_limitLevel == 1 || // only visible records were selected due to group filtering $this->_groupsTotal == 0 || // 'show all' mode ($this->_sql->_limitLevel == 2 && // DB specific record filter ($nRecord - $this->_sql->_skipCount >= 0 && $nRecord - $this->_sql->_skipCount < $this->_groupsTotal)) || ($this->_sql->_limitLevel == 0 && // fullmode record filter ($nRecord - $this->_from >= 0 && $nRecord - $this->_sql->_skipCount < $this->_from + $this->_groupsTotal)) ; } function getTotals() { if($this->_fullRequest) { return $this->_groups->getSummary(); } else { if($this->_groups->allGroupsUsed()) { return $this->_summary; } else { $totals = array(); $sql = $this->_sql->sqlt(); if($sql !== false) { $totalRecords = 0; $fetchedArray = $this->_connection->query( $sql )->fetchAssoc(); $data = $this->cipherer->DecryptFetchedArray( $fetchedArray ); $this->addSummary(false, $totals, $data, $totalRecords); } return $totals; } } } function getReport($from = 0) { $this->init($from); // $this->_doPaging = $from == -1; // split to pages at server $this->_doPaging = ( $this->_groupsPerPage != 0 ); $isExistTimeFormatField = false; for($i=0;$ifieldsArr); $i++) { if ($this->fieldsArr[$i]['viewFormat'] == "Time") { $isExistTimeFormatField = true; break; } } // retrieve ALL records from table // $this->_fullRequest = $this->_doPaging || ($this->repGlobalSummary && $isExistTimeFormatField); $this->_fullRequest = ($this->repGlobalSummary && $isExistTimeFormatField); // MYSQL version < 5.0 // a very bad thing to do, but we need this for global summary and pagination if( !$this->_connection->checkDBSubqueriesSupport() ) $this->_fullRequest = true; if( $this->_connection->dbType != nDATABASE_MySQL && $this->_connection->dbType != nDATABASE_PostgreSQL && $this->_connection->dbType != nDATABASE_MSSQLServer && $this->_connection->dbType != nDATABASE_Oracle && $this->_connection->dbType != nDATABASE_Access ) { $this->_fullRequest = true; } // use non-optimized algorithm $this->_recordBasedRequest = $this->_fullRequest; // request records if there is no grouping if(!$this->repGroupFieldsCount) $this->_recordBasedRequest=true; //////////////////////////////// start building report $this->_sql->setRecordBasedRequest($this->_recordBasedRequest); // if($this->_doPaging || $this->_fullRequest) if( $this->_fullRequest) { $this->_sql->_limitLevel = 0; // no limits } else { if(!$this->repGroupFieldsCount) $this->_sql->_limitLevel = 2; // limit records else $this->_sql->_limitLevel = 1; // limit groups } $page = -1; $nRow = 0; if(!$this->_recordBasedRequest) { // get groups to show $groups = $this->_groups->getDisplayGroups($from); // iterate through records in these groups $hsql = $this->_sql->sql2($groups); if(tableEventExists('BeforeQueryReport',$this->tName)) { $hwhere = $hsql['where']; $eventsObj = getEventObject($this->tName); $eventsObj->BeforeQueryReport($hwhere); $hsql['where'] = $hwhere; } $sql = $this->_sql->buildsql($hsql); $qResult = $this->_connection->query( $sql ); while($data = $this->cipherer->DecryptFetchedArray( $qResult->fetchAssoc() )) { $this->pageObject->recId = $nRow; $this->setSummary($this->repShowDet, $data, $this->recordVisible($nRow) ? $this->getFormattedRow($data) : null); $nRow ++; } } else { $this->_groups->init($from); $this->_sql->setOldAlgorithm(); $hsql = $this->_sql->sql2(null); $sql = $this->_sql->buildsql($hsql); $qResult = $this->_connection->query( $sql ); while($data = $this->cipherer->DecryptFetchedArray( $qResult->fetchAssoc() )) { if ($this->repGroupFieldsCount) { // take a record group into account $this->_groups->setGroup($data); } if($this->_fullRequest) $this->_groups->setGlobalSummary(true, $data); if ($this->repGroupFieldsCount) { // $visible = $this->_doPaging || $this->_groups->isVisibleGroup() || $this->_groupsTotal == 0; $visible = $this->_groups->isVisibleGroup() || $this->_groupsTotal == 0; }else{ $visible = $this->recordVisible($nRow); } if($visible) { $this->pageObject->recId = $nRow; $this->setSummary(true, $data, $this->getFormattedRow($data)); } else if(!$this->_fullRequest && count($this->_list) > 0) { // exit loop at the end of visible recordset break; } $nRow ++; } $this->_sql->setOldAlgorithm(false); } $this->setFinish(); $this->makeSummary(); $global_totals = $this->getTotals(); $this->writePageSummary(); $globals = $this->writeGlobalSummary($global_totals); if ($this->repGroupFieldsCount) { $countrows = $this->_groups->getCountGroups($this->_fullRequest); $countGroups = $countrows; }else{ $countrows = $global_totals['count']; $countGroups = 1; } $maxpages=1; if($this->_groupsTotal>0) $maxpages=ceil($countrows/$this->_groupsTotal); $returnthis = array('list' => $this->_list, 'global' => $globals, 'page' => $this->_summary, 'maxpages' => $maxpages, 'countRows'=>$countrows, 'countGroups'=>$countGroups); return $returnthis; } } ////////////////////////////////////////////////////////////////////////////// class Report extends ReportLogic { var $forExport = false; // report table info var $tName = ''; var $shortTName = ''; var $repGroupFieldsCount = 0; var $repPageSummary = 0; var $repGlobalSummary = 0; var $repLayout = 0; var $showGroupSummaryCount = 0; var $repShowDet = 0; var $mode = MODE_LIST; // report field info var $repGroupFields = array(); // current table key fields var $tKeyFields = array(); // if any field used for totals var $isExistTotalFields = false; // table fields list var $fieldsArr = array(); function Report($sql, $order, $connection, $groupsTotal, $groupsPerPage, &$params, $searchWhereClause, $searchHavingClause, $pageObject = null) { // copy properties to object RunnerApply($this, $params); ReportLogic::ReportLogic($sql, $order, $connection, $groupsTotal, $groupsPerPage, $params, $searchWhereClause, $searchHavingClause, $pageObject); } function getFormattedRow($value) { global $strTableName; $row = array('row_data' => true); $keylink = ""; for($i=0; $itKeyFields); $i++) { $keylink .= "&key".($i+1)."=".runner_htmlspecialchars(rawurlencode(@$value[$this->tKeyFields[$i]])); } if($this->forExport) $this->pageObject->setForExportVar($this->forExport); for($i=0; $ifieldsArr); $i++) { // for change pseudo foreach with condition with PHP for // foreach Fields as @f filter @f.bReportPage && (@TABLE.bReportShowDetails || @TABLE.arrReportGroupFields[strGroupField==@f.strName && nGroupInterval==0].len) order nReportPageOrder $pass = false; for($j=0; $jrepGroupFields); $j++) { if (!$this->fieldsArr[$i]['repPage'] || !($this->repShowDet || ($this->repGroupFields[$j]['strGroupField'] == $this->fieldsArr[$i]['name'] && $this->repGroupFields[$j]['groupInterval'] === 0))) { $pass = true; } } if ($pass) { continue; } $row[$this->fieldsArr[$i]['goodName']."_value"] = $this->pageObject->formatReportFieldValue($this->fieldsArr[$i]['name'], $value, $keylink); $row[$this->fieldsArr[$i]['goodName']."_dbvalue"] = $value[$this->fieldsArr[$i]['name']]; } if ($this->repLayout == REPORT_BLOCK) { $row[GoodFieldName('nonewgroup')] = true; } return $row; } function writeGroup(&$begin, &$end, $gkey, $grp, $nField) { $field = $this->_sql->field($nField); $gname = $field->name(); for($i=0;$irepGroupFields); $i++) { if($gname == $this->repGroupFields[$i]['strGroupField']) { if ($this->repLayout == REPORT_BLOCK) { $bFound = false; for($nG = 0; $nG < $this->repGroupFieldsCount; $nG ++) { $field = $this->_sql->field($nG); $gname2 = $field->name(); if($nG < $nField) { if(isset($begin[GoodFieldName($gname2.'_firstnewgroup')])) $bFound = true; } else unset($begin[GoodFieldName($gname2.'_firstnewgroup')]); } if(!$bFound) $begin[GoodFieldName($gname.'_firstnewgroup')] = true; unset($begin[GoodFieldName('nonewgroup')]); } else { $begin[GoodFieldName($gname.'_newgroup')] = true; } $end[GoodFieldName($gname.'_endgroup')] = true; if ($this->repGroupFields[$i]['showGroupSummary']) { $end[GoodFieldName('group'.$gname.'_total_cnt')] = str_format_number($grp['count'],0); } for($j=0; $jfieldsArr); $j++) { if(is_array($grp['summary'])) { if(is_array($grp['summary'][$this->fieldsArr[$j]['name']])) { if ($this->fieldsArr[$j]['totalMax']) { $end["group".GoodFieldName($gname)."_total".$this->fieldsArr[$j]['goodName']."_max"] = getFormattedValue($this->pageObject, $grp['summary'][$this->fieldsArr[$j]['name']]['MAX'], $this->fieldsArr[$j]['name'], $this->fieldsArr[$j]['viewFormat'], $this->fieldsArr[$j]['editFormat'], $this->mode); } if ($this->fieldsArr[$j]['totalMin']){ $end["group".GoodFieldName($gname)."_total".$this->fieldsArr[$j]['goodName']."_min"] = getFormattedValue($this->pageObject, $grp['summary'][$this->fieldsArr[$j]['name']]['MIN'], $this->fieldsArr[$j]['name'], $this->fieldsArr[$j]['viewFormat'], $this->fieldsArr[$j]['editFormat'], $this->mode); } if ($this->fieldsArr[$j]['totalAvg']){ $end["group".GoodFieldName($gname)."_total".$this->fieldsArr[$j]['goodName']."_avg"] = getFormattedValue($this->pageObject, $grp['summary'][$this->fieldsArr[$j]['name']]['AVG'], $this->fieldsArr[$j]['name'], $this->fieldsArr[$j]['viewFormat'], $this->fieldsArr[$j]['editFormat'], $this->mode); } if ($this->fieldsArr[$j]['totalSum']){ $end["group".GoodFieldName($gname)."_total".$this->fieldsArr[$j]['goodName']."_sum"] = getFormattedValue($this->pageObject, $grp['summary'][$this->fieldsArr[$j]['name']]['SUM'], $this->fieldsArr[$j]['name'], $this->fieldsArr[$j]['viewFormat'], $this->fieldsArr[$j]['editFormat'], $this->mode); } } } if ($this->fieldsArr[$j]['name'] == $this->repGroupFields[$i]['strGroupField']) { $field = $this->_sql->field($nField); $gvalue = $field->getFieldName($gkey, $grp['_first']); if($field->overrideFormat()) { $begin[GoodFieldName(GoodFieldName($gname).'_grval')] = ($this->forExport == 'excel') ? runner_htmlspecialchars($gvalue) : $gvalue; if ($this->showGroupSummaryCount) { $end[GoodFieldName(GoodFieldName($gname).'_grval')] = ($this->forExport == 'excel') ? runner_htmlspecialchars($gvalue) : $gvalue; } } else { $formattedValue = getFormattedValue($this->pageObject, $gvalue, $this->fieldsArr[$j]['name'], $this->fieldsArr[$j]['viewFormat'], $this->fieldsArr[$j]['editFormat'], $this->mode); $begin[GoodFieldName($gname.'_grval')] = ($this->forExport == 'excel') ? runner_htmlspecialchars($formattedValue) : $formattedValue; if ($this->showGroupSummaryCount) { $end[GoodFieldName($gname.'_grval')] = ($this->forExport == 'excel') ? runner_htmlspecialchars($formattedValue) : $formattedValue; } } } } } } } function _writePage(&$page, $src, $count) { $page['page_summary'] = true; if ($this->repPageSummary) { for($i=0; $ifieldsArr); $i++) { $field = & $this->fieldsArr[$i]; $fieldName = $field['name']; $fGoodName = $field['goodName']; if(is_array($src[$fieldName])) { if ($field['totalSum']) { $page["page_total".$fGoodName."_sum"] = getFormattedValue($this->pageObject, $src[$fieldName]['SUM'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalAvg']){ $page["page_total".$fGoodName."_avg"] = getFormattedValue($this->pageObject, $src[$fieldName]['AVG'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalMin']){ $page["page_total".$fGoodName."_min"] = getFormattedValue($this->pageObject, $src[$fieldName]['MIN'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalMax']){ $page["page_total".$fGoodName."_max"] = getFormattedValue($this->pageObject, $src[$fieldName]['MAX'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } } } $page['page_total_cnt'] = str_format_number($count,0); } } function writeGlobalSummary($source) { $result = array(); if (!$this->repGlobalSummary) return $result; if(is_array($source["summary"])) { for($i=0; $ifieldsArr); $i++) { $field = & $this->fieldsArr[$i]; $fieldName = $field['name']; $fGoodName = $field['goodName']; if(is_array($source["summary"][$fieldName])) { if ($field['totalMax']) { $result["global_total".$fGoodName."_max"] = getFormattedValue($this->pageObject, $source['summary'][$fieldName]['MAX'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalMin']){ $result["global_total".$fGoodName."_min"] = getFormattedValue($this->pageObject, $source['summary'][$fieldName]['MIN'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalAvg']){ $result["global_total".$fGoodName."_avg"] = getFormattedValue($this->pageObject, $source['summary'][$fieldName]['AVG'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } if ($field['totalSum']){ $result["global_total".$fGoodName."_sum"] = getFormattedValue($this->pageObject, $source['summary'][$fieldName]['SUM'], $fieldName, $field['viewFormat'], $field['editFormat'], $this->mode); } } } } $result["global_total_cnt"] = str_format_number($source['count'],0); return $result; } } ?>