--- /dev/null
+<?php\r
+\r
+// for PHP4\r
+// copied from http://www.php.net/json_encode\r
+if (!function_exists('json_encode'))\r
+{\r
+ function json_encode($a=false)\r
+ {\r
+ if (is_null($a)) return 'null';\r
+ if ($a === false) return 'false';\r
+ if ($a === true) return 'true';\r
+ if (is_scalar($a))\r
+ {\r
+ if (is_float($a))\r
+ {\r
+ // Always use "." for floats.\r
+ return floatval(str_replace(",", ".", strval($a)));\r
+ }\r
+\r
+ if (is_string($a))\r
+ {\r
+ static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));\r
+ return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';\r
+ }\r
+ else\r
+ return $a;\r
+ }\r
+ $isList = true;\r
+ for ($i = 0, reset($a); $i < count($a); $i++, next($a))\r
+ {\r
+ if (key($a) !== $i)\r
+ {\r
+ $isList = false;\r
+ break;\r
+ }\r
+ }\r
+ $result = array();\r
+ if ($isList)\r
+ {\r
+ foreach ($a as $v) $result[] = json_encode($v);\r
+ return '[' . join(',', $result) . ']';\r
+ }\r
+ else\r
+ {\r
+ foreach ($a as $k => $v) $result[] = json_encode($k).':'.json_encode($v);\r
+ return '{' . join(',', $result) . '}';\r
+ }\r
+ }\r
+}\r
+\r
+class ricoXmlResponse {\r
+\r
+ // public properties\r
+ var $orderByRef;\r
+ var $sendDebugMsgs;\r
+ var $readAllRows; // always return the total number of rows? (if true, the user will always see the total number of rows, but there is a small performance hit)\r
+ var $convertCharSet; // set to true if database is ISO-8859-1 encoded, false if UTF-8\r
+ var $AllRowsMax; // max # of rows to send if numrows=-1\r
+ var $fmt; // xml, json, html, xl\r
+ \r
+ // private properties\r
+ var $objDB;\r
+ var $eof;\r
+ var $oParse;\r
+ var $sqltext;\r
+ var $arParams;\r
+ var $allParams;\r
+ var $condType;\r
+ var $RowsStart;\r
+ var $RowsEnd;\r
+ var $SendHdg;\r
+ var $Headings;\r
+ var $HiddenCols;\r
+\r
+ function ricoXmlResponse() {\r
+ if (isset($GLOBALS['oDB']) && is_object($GLOBALS['oDB'])) {\r
+ $this->objDB=$GLOBALS['oDB']; // use oDB global as database connection, if it exists\r
+ }\r
+ $this->orderByRef=false;\r
+ $this->sendDebugMsgs=false;\r
+ $this->readAllRows=true; // has no effect on SQL Server 2005, Oracle, and MySQL because they use Query2xmlRaw_Limit()\r
+ $this->convertCharSet=false;\r
+ $this->SendHdg=false;\r
+ $this->AllRowsMax=1999;\r
+ $this->Headings=array();\r
+ $this->HiddenCols=array();\r
+ }\r
+\r
+ function ProcessQuery($id, $sqlselect, $filters=array(), $errmsg='') {\r
+ $this->fmt=isset($_GET["_fmt"]) ? $_GET["_fmt"] : "xml";\r
+ $offset=isset($_GET["offset"]) ? $_GET["offset"] : "0";\r
+ $size=isset($_GET["page_size"]) ? $_GET["page_size"] : "";\r
+ $total=isset($_GET["get_total"]) ? strtolower($_GET["get_total"]) : "false";\r
+ $distinct=isset($_GET["distinct"]) ? $_GET["distinct"] : "";\r
+ $edit=isset($_GET["edit"]) ? $_GET["edit"] : "";\r
+ if (isset($_GET["hidden"]) && $_GET["hidden"]!="") $this->HiddenCols=explode(",", $_GET["hidden"]);\r
+\r
+ ob_clean();\r
+ if ($this->fmt != "xl") {\r
+ header("Cache-Control: no-cache");\r
+ header("Pragma: no-cache");\r
+ header("Expires: ".gmdate("D, d M Y H:i:s",time()+(-1*60))." GMT");\r
+ }\r
+\r
+ switch ($this->fmt) {\r
+ case "html":\r
+ header("Content-type: text/html");\r
+ echo "<html><head></head><body>\n";\r
+ $closetags="</body></html>";\r
+ $this->RowsStart="\n<table border='1'>";\r
+ $this->RowsEnd="\n</table>";\r
+ $total="false";\r
+ $this->sendDebugMsgs=false;\r
+ $this->SendHdg=true;\r
+ break;\r
+ case "xl":\r
+ $this->convertCharSet=false;\r
+ header("Content-type: application/vnd.ms-excel");\r
+ echo "<html><head></head><body>\n";\r
+ $closetags="</body></html>";\r
+ $this->RowsStart="\n<table>";\r
+ $this->RowsEnd="\n</table>";\r
+ $total="false";\r
+ $this->sendDebugMsgs=false;\r
+ $this->SendHdg=true;\r
+ break;\r
+ case "json":\r
+ header("Content-type: application/json");\r
+ echo "{\n\"id\":\"" . $id . "\"";\r
+ $this->RowsStart=",\n\"update_ui\":true,\n\"offset\":" . $offset . ",\n\"rows\":[";\r
+ $this->RowsEnd="\n]";\r
+ $closetags="}";\r
+ $this->sendDebugMsgs=false;\r
+ break;\r
+ default:\r
+ // default to xml\r
+ $this->fmt="xml";\r
+ header("Content-type: text/xml");\r
+ echo "<?xml version='1.0' encoding='UTF-8'?".">\n";\r
+ echo "\n<ajax-response><response type='object' id='" . $id . "'>";\r
+ $closetags="</response></ajax-response>";\r
+ $this->RowsStart="\n<rows update_ui='true' offset='" . $offset . "'>";\r
+ $this->RowsEnd="\n</rows>";\r
+ break;\r
+ }\r
+ if (!empty($errmsg)) {\r
+ $this->ErrorResponse($errmsg);\r
+ } elseif (empty($id)) {\r
+ $this->ErrorResponse("No ID provided!");\r
+ } elseif ($distinct=="" && !is_numeric($offset)) {\r
+ $this->ErrorResponse("Invalid offset!");\r
+ } elseif ($distinct=="" && !is_numeric($size)) {\r
+ $this->ErrorResponse("Invalid size!");\r
+ } elseif ($distinct!="" && !is_numeric($distinct)) {\r
+ $this->ErrorResponse("Invalid distinct parameter!");\r
+ } else {\r
+ if ($this->SendHdg && is_array($sqlselect)) {\r
+ // populate $Headings from $sqlselect[9] taking into account hidden columns\r
+ for ($i=0,$j=0,$SkipIdx=0; $i<count($sqlselect[9]); $i++) {\r
+ $skip=false;\r
+ if ($SkipIdx < count($this->HiddenCols)) {\r
+ $skip=($this->HiddenCols[$SkipIdx] == $i);\r
+ if ($skip) $SkipIdx++;\r
+ }\r
+ if (!$skip) {\r
+ $this->Headings[$j++]=$sqlselect[9][$i];\r
+ }\r
+ }\r
+ }\r
+ $this->objDB->DisplayErrors=false;\r
+ $this->objDB->ErrMsgFmt="MULTILINE";\r
+ if ($distinct!="" && is_numeric($distinct)) {\r
+ $this->Query2xmlDistinct($sqlselect, intval($distinct), -1, $filters);\r
+ } elseif ($edit!="" && is_numeric($edit) && is_array($sqlselect)) {\r
+ $this->Query2xml($sqlselect[8][intval($edit)], intval($offset), intval($size), $total!="false", $filters);\r
+ } else {\r
+ $this->Query2xml($sqlselect, intval($offset), intval($size), $total!="false", $filters);\r
+ }\r
+ if (!empty($this->objDB->LastErrorMsg)) {\r
+ $this->ErrorResponse($this->objDB->LastErrorMsg);\r
+ }\r
+ }\r
+ echo "\n".$closetags;\r
+ }\r
+\r
+ function ErrorResponse($msg) {\r
+ $this->AppendResponse("error",$msg);\r
+ }\r
+\r
+ function AppendResponse($tag, $content) {\r
+ switch ($this->fmt) {\r
+ case "html":\r
+ echo "\n<p>".$tag."<br>".htmlspecialchars($content)."</p>";\r
+ break;\r
+ case "xl":\r
+ echo "\n<p>".$tag."<br>".htmlspecialchars($content)."</p>";\r
+ break;\r
+ case "json":\r
+ echo ",\n\"".$tag."\":".json_encode($content);\r
+ break;\r
+ case "xml":\r
+ echo "\n<".$tag.">".htmlspecialchars($content)."</".$tag.">";\r
+ break;\r
+ }\r
+ }\r
+\r
+ // All Oracle and SQL Server 2005 queries *must* have an ORDER BY clause\r
+ // "as" clauses are now ok\r
+ // If numrows < 0, then retrieve all rows\r
+ function Query2xml($sqlselect, $offset, $numrows, $gettotal, $filters=array()) {\r
+ if ($numrows >= 0) {\r
+ $Dialect=$this->objDB->Dialect;\r
+ } else {\r
+ $numrows=$this->AllRowsMax;\r
+ $Dialect=""; // don't use limit query\r
+ }\r
+ switch ($this->objDB->Dialect) {\r
+ case "MySQL": $this->orderByRef=true; break;\r
+ }\r
+ $this->arParams=array('H'=>array(), 'W'=>array());\r
+ $this->oParse= new sqlParse();\r
+ if (is_array($sqlselect)) {\r
+ $this->oParse->LoadArray($sqlselect);\r
+ } else {\r
+ $this->oParse->ParseSelect($sqlselect);\r
+ }\r
+ $this->ApplyQStringParms($filters);\r
+ $this->allParams=array_merge($this->arParams['W'],$this->arParams['H']);\r
+ echo $this->RowsStart;\r
+ switch ($Dialect) {\r
+\r
+ case "TSQL":\r
+ $this->objDB->SingleRecordQuery("select @@VERSION", $version);\r
+ if (is_string($sqlselect) && strtoupper(substr($sqlselect,0,7))!="SELECT ") {\r
+ $this->allParams=array();\r
+ $totcnt=$this->Query2xmlRaw($sqlselect, $offset, $numrows);\r
+ }\r
+ else if (preg_match("/SQL Server 200(5|8)/i",$version[0])) {\r
+ $this->sqltext=$this->UnparseWithRowNumber($offset, $numrows + 1, true);\r
+ $totcnt=$this->Query2xmlRaw_Limit($this->sqltext, $offset, $numrows, 1);\r
+ }\r
+ else {\r
+ $this->sqltext=$this->oParse->UnparseSelectSkip($this->HiddenCols);\r
+ $totcnt=$this->Query2xmlRaw($this->sqltext, $offset, $numrows);\r
+ }\r
+ break;\r
+\r
+ case "Oracle":\r
+ $this->sqltext=$this->UnparseWithRowNumber($offset, $numrows + 1, false);\r
+ $totcnt=$this->Query2xmlRaw_Limit($this->sqltext, $offset, $numrows, 1);\r
+ break;\r
+\r
+ case "MySQL":\r
+ $this->sqltext=$this->oParse->UnparseSelectSkip($this->HiddenCols)." LIMIT ".$offset.",".($numrows + 1);\r
+ $totcnt=$this->Query2xmlRaw_Limit($this->sqltext, $offset, $numrows, 0);\r
+ break;\r
+\r
+ default:\r
+ $this->sqltext=$this->oParse->UnparseSelectSkip($this->HiddenCols);\r
+ $totcnt=$this->Query2xmlRaw($this->sqltext, $offset, $numrows);\r
+ break;\r
+ }\r
+ echo $this->RowsEnd;\r
+ if ($this->sendDebugMsgs) {\r
+ $this->AppendResponse("debug",$this->objDB->db->lastQuery);\r
+ }\r
+ if (!$this->eof && $gettotal) {\r
+ $totcnt=$this->getTotalRowCount();\r
+ }\r
+ if ($this->fmt=="xml" || $this->fmt=="json") {\r
+ if ($this->eof) $this->AppendResponse("rowcount",$totcnt);\r
+ }\r
+ $this->oParse=NULL;\r
+ return $totcnt;\r
+ }\r
+\r
+\r
+ function Query2xmlDistinct($sqlselect, $colnum, $numrows, $filters=array()) {\r
+ if ($numrows < 0) $numrows=$this->AllRowsMax;\r
+ $this->arParams=array('H'=>array(), 'W'=>array());\r
+ $this->oParse= new sqlParse();\r
+ if (is_array($sqlselect)) {\r
+ $this->oParse->LoadArray($sqlselect);\r
+ } else {\r
+ $this->oParse->ParseSelect($sqlselect);\r
+ }\r
+ $this->ApplyQStringParms($filters);\r
+ $this->allParams=array_merge($this->arParams['W'],$this->arParams['H']);\r
+ echo $this->RowsStart;\r
+ $this->sqltext=$this->oParse->UnparseDistinctColumn($colnum);\r
+ $totcnt=$this->Query2xmlRaw($this->sqltext, 0, $numrows);\r
+ echo $this->RowsEnd;\r
+ if ($this->sendDebugMsgs) {\r
+ $this->AppendResponse("debug",$this->objDB->db->lastQuery);\r
+ }\r
+ $this->oParse=NULL;\r
+ }\r
+\r
+\r
+ // Tested ok with SQL Server 2005, MySQL, and Oracle\r
+ function getTotalRowCount() {\r
+ $countSql="SELECT ".$this->oParse->UnparseColumnList()." FROM ".$this->oParse->FromClause;\r
+ if (!empty($this->oParse->WhereClause)) {\r
+ $countSql.=" WHERE ".$this->oParse->WhereClause;\r
+ }\r
+ if (is_array($this->oParse->arGroupBy)) {\r
+ if (count($this->oParse->arGroupBy) > 0) {\r
+ $countSql.=" GROUP BY ".implode(",",$this->oParse->arGroupBy);\r
+ }\r
+ }\r
+ if (!empty($this->oParse->HavingClause)) {\r
+ $countSql.=" HAVING ".$this->oParse->HavingClause;\r
+ }\r
+ $countSql="SELECT COUNT(*) FROM (".$countSql.")";\r
+ if ($this->objDB->Dialect != "Oracle") {\r
+ $countSql.=" AS rico_Main";\r
+ }\r
+ if (count($this->allParams)>0) {\r
+ $rsMain=$this->objDB->RunParamQuery($countSql,$this->allParams);\r
+ } else {\r
+ $rsMain=$this->objDB->RunQuery($countSql);\r
+ }\r
+ if (!$rsMain) {\r
+ echo "\n<debug>getTotalRowCount: rsMain is null</debug>";\r
+ return;\r
+ }\r
+ if (!$this->objDB->db->FetchArray($rsMain,$a)) return;\r
+ $this->objDB->rsClose($rsMain);\r
+ $this->eof=true;\r
+ return $a[0];\r
+ }\r
+\r
+\r
+ function UnparseWithRowNumber($offset, $numrows, $includeAS) {\r
+ if (is_array($this->oParse->arOrderBy)) {\r
+ if (count($this->oParse->arOrderBy) > 0) {\r
+ $strOrderBy=implode(",",$this->oParse->arOrderBy);\r
+ }\r
+ }\r
+ if (empty($strOrderBy) && !preg_match("/\bjoin\b/",$this->oParse->FromClause)) {\r
+ // order by clause should be included in main sql select statement\r
+ // However, if it isn't, then use primary key as sort - assuming FromClause is a simple table name\r
+ $strOrderBy=$this->objDB->PrimaryKey($this->oParse->FromClause);\r
+ }\r
+ $unparseText="SELECT ROW_NUMBER() OVER (ORDER BY ".$strOrderBy.") AS rico_rownum,";\r
+ $unparseText.=$this->oParse->UnparseColumnListSkip($this->HiddenCols)." FROM ".$this->oParse->FromClause;\r
+ if (!empty($this->oParse->WhereClause)) {\r
+ $unparseText.=" WHERE ".$this->oParse->WhereClause;\r
+ }\r
+ if (is_array($this->oParse->arGroupBy)) {\r
+ if (count($this->oParse->arGroupBy) > 0) {\r
+ $unparseText.=" GROUP BY ".implode(",",$this->oParse->arGroupBy);\r
+ }\r
+ }\r
+ if (!empty($this->oParse->HavingClause)) {\r
+ $unparseText.=" HAVING ".$this->oParse->HavingClause;\r
+ }\r
+ $unparseText="SELECT * FROM (".$unparseText.")";\r
+ if ($includeAS) {\r
+ $unparseText.=" AS rico_Main";\r
+ }\r
+ $unparseText.=" WHERE rico_rownum > ".$offset." AND rico_rownum <= ".($offset + $numrows);\r
+ return $unparseText;\r
+ }\r
+\r
+ function Query2xmlRaw($rawsqltext, $offset, $numrows) {\r
+ if (count($this->allParams)>0) {\r
+ $rsMain=$this->objDB->RunParamQuery($rawsqltext,$this->allParams);\r
+ } else {\r
+ $rsMain=$this->objDB->RunQuery($rawsqltext);\r
+ }\r
+ if (!$rsMain) return;\r
+ \r
+ $colcnt = $this->objDB->db->NumFields($rsMain);\r
+ $totcnt = $this->objDB->db->NumRows($rsMain);\r
+ //echo "<debug>Query2xmlRaw: NumRows=$totcnt</debug>";\r
+ if ($offset < $totcnt || $totcnt==-1) {\r
+ $this->objDB->db->Seek($rsMain,$offset);\r
+ switch ($this->fmt) {\r
+ case "json": $rowcnt=$this->WriteRowsJSON($rsMain, $numrows, 0); break;\r
+ default: $rowcnt=$this->WriteRowsXHTML($rsMain, $numrows, 0); break;\r
+ }\r
+ if ($totcnt < 0) {\r
+ $totcnt=$offset+$rowcnt;\r
+ while($this->objDB->db->FetchRow($rsMain,$row))\r
+ $totcnt++;\r
+ }\r
+ } else {\r
+ $totcnt=$offset;\r
+ }\r
+ $this->objDB->rsClose($rsMain);\r
+ $this->eof=true;\r
+ return $totcnt;\r
+ }\r
+\r
+ function Query2xmlRaw_Limit($rawsqltext, $offset, $numrows, $firstcol) {\r
+ if (count($this->allParams)>0) {\r
+ $rsMain=$this->objDB->RunParamQuery($rawsqltext,$this->allParams);\r
+ } else {\r
+ $rsMain=$this->objDB->RunQuery($rawsqltext);\r
+ }\r
+ //if ($this->objDB->db->HasError()) echo "<error>" . $this->objDB->db->ErrorMsg() . "</error>";\r
+ $totcnt=$offset;\r
+ $this->eof=true;\r
+ if (!$rsMain) return;\r
+ switch ($this->fmt) {\r
+ case "json": $totcnt+=$this->WriteRowsJSON($rsMain, $numrows, $firstcol); break;\r
+ default: $totcnt+=$this->WriteRowsXHTML($rsMain, $numrows, $firstcol); break;\r
+ }\r
+ $this->objDB->rsClose($rsMain);\r
+ return $totcnt;\r
+ }\r
+\r
+ function WriteRowsXHTML($rsMain, $numrows, $firstcol) {\r
+ $colcnt = $this->objDB->db->NumFields($rsMain);\r
+ $rowcnt=0;\r
+ if ($this->SendHdg) {\r
+ echo "\n<tr>";\r
+ for ($i=$firstcol; $i < $colcnt; $i++) {\r
+ $n=empty($this->Headings[$i-$firstcol]) ? $this->objDB->db->FieldName($rsMain,$i) : $this->Headings[$i-$firstcol];\r
+ print $this->XmlStringCell($n);\r
+ }\r
+ echo "</tr>";\r
+ }\r
+ while(($this->objDB->db->FetchRow($rsMain,$row)) && $rowcnt < $numrows) {\r
+ $rowcnt++;\r
+ print "\n<tr>";\r
+ for ($i=$firstcol; $i < $colcnt; $i++)\r
+ print $this->XmlStringCell($row[$i]);\r
+ print "</tr>";\r
+ }\r
+ $this->eof=($rowcnt < $numrows);\r
+ return $rowcnt;\r
+ }\r
+ \r
+ function WriteRowsJSON($rsMain, $numrows, $firstcol) {\r
+ $colcnt = $this->objDB->db->NumFields($rsMain);\r
+ $rowcnt=0;\r
+ if ($this->SendHdg) {\r
+ echo "\n[";\r
+ for ($i=$firstcol; $i < $colcnt; $i++) {\r
+ //$n=empty($this->Headings($i-$firstcol)) ? $this->objDB->db->FieldName($rsMain,$i) : $this->Headings($i-$firstcol);\r
+ print json_encode($n);\r
+ }\r
+ echo "]";\r
+ }\r
+ while(($this->objDB->db->FetchRow($rsMain,$row)) && $rowcnt < $numrows) {\r
+ if ($rowcnt>0 || $this->SendHdg) echo ",";\r
+ $rowcnt++;\r
+ print "\n[";\r
+ for ($i=$firstcol; $i < $colcnt; $i++) {\r
+ if ($i>$firstcol) echo ",";\r
+ $value=$row[$i];\r
+ if ($this->convertCharSet) $value=utf8_encode($value);\r
+ print json_encode($value);\r
+ }\r
+ print "]";\r
+ }\r
+ $this->eof=($rowcnt < $numrows);\r
+ return $rowcnt;\r
+ }\r
+ \r
+ function SetDbConn(&$dbcls) {\r
+ $this->objDB=&$dbcls;\r
+ }\r
+\r
+ function PushParam($newvalue) {\r
+ $parm=$this->convertCharSet ? utf8_decode($newvalue) : $newvalue;\r
+ if (get_magic_quotes_gpc()) $parm=stripslashes($parm);\r
+ array_push($this->arParams[$this->condType], $parm);\r
+ if ($this->sendDebugMsgs) {\r
+ echo "\n<debug>".$this->condType." param=".htmlspecialchars($parm)."</debug>";\r
+ }\r
+ }\r
+ \r
+ function setCondType($selectItem) {\r
+ $this->condType=(preg_match("/\bmin\(|\bmax\(|\bsum\(|\bcount\(/i",$selectItem) && !preg_match("/\bselect\b/i",$selectItem)) ? 'H' : 'W';\r
+ }\r
+ \r
+ function addCondition($newfilter) {\r
+ switch ($this->condType) {\r
+ case 'H': $this->oParse->AddHavingCondition($newfilter); break;\r
+ case 'W': $this->oParse->AddWhereCondition($newfilter); break;\r
+ }\r
+ }\r
+\r
+ function ApplyQStringParms($filters) {\r
+ foreach($_GET as $qs => $value) {\r
+ $prefix=substr($qs,0,1);\r
+ switch ($prefix) {\r
+\r
+ // user-invoked condition\r
+ case "w":\r
+ case "h":\r
+ $i=substr($qs,1);\r
+ if (!is_numeric($i)) break;\r
+ $i=intval($i);\r
+ if ($i<0 || $i>=count($filters)) break;\r
+ $newfilter=$filters[$i];\r
+ $this->condType=strtoupper($prefix);\r
+\r
+ $j=strpos($newfilter," in (?)");\r
+ if ($j !== false) {\r
+ $a=explode(",", $value);\r
+ for ($i=0; $i < count($a); $i++) {\r
+ $this->PushParam($a[$i]);\r
+ $a[$i]="?";\r
+ }\r
+ $newfilter=substr($newfilter,0,$j+4) . implode(",",$a) . substr($newfilter,$j+5);\r
+ } elseif (strpos($newfilter,"?") !== false) {\r
+ $this->PushParam($value);\r
+ }\r
+\r
+ $this->addCondition($newfilter);\r
+ break;\r
+\r
+ // sort\r
+ case "s":\r
+ $i=substr($qs,1);\r
+ if (!is_numeric($i)) break;\r
+ $i=intval($i);\r
+ if ($i<0 || $i>=count($this->oParse->arSelList)) break;\r
+ $value=strtoupper(substr($value,0,4));\r
+ if (!in_array($value,array('ASC','DESC'))) $value="ASC";\r
+ if ($this->orderByRef)\r
+ $this->oParse->AddSort(($i + 1)." ".$value);\r
+ else\r
+ $this->oParse->AddSort($this->oParse->arSelList[$i]." ".$value);\r
+ break;\r
+\r
+ // user-supplied filter\r
+ case "f":\r
+ //print_r($value);\r
+ foreach($value as $i => $filter) {\r
+ if ($i<0 || $i>=count($this->oParse->arSelList)) break;\r
+ $newfilter=$this->oParse->arSelList[$i];\r
+ $this->setCondType($newfilter);\r
+ switch ($filter['op']) {\r
+ case "EQ":\r
+ $newfilter='('.$this->AddCoalesce($newfilter).' IN '.$this->GetMultiParmFilter($filter).')';\r
+ break;\r
+ case "LE":\r
+ $newfilter.="<=?";\r
+ $this->PushParam($filter[0]);\r
+ break;\r
+ case "GE":\r
+ $newfilter.=">=?";\r
+ $this->PushParam($filter[0]);\r
+ break;\r
+ case "NULL": $newfilter.=" is null"; break;\r
+ case "NOTNULL": $newfilter.=" is not null"; break;\r
+ case "LIKE":\r
+ $newfilter.=" LIKE ?";\r
+ $this->PushParam(str_replace("*",$this->objDB->Wildcard,$filter[0]));\r
+ break;\r
+ case "NE":\r
+ $newfilter='('.$this->AddCoalesce($newfilter).' NOT IN '.$this->GetMultiParmFilter($filter).')';\r
+ break;\r
+ }\r
+ $this->addCondition($newfilter);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ function AddCoalesce($newfilter) {\r
+ if ($this->objDB->Dialect=="Access") {\r
+ return "iif(IsNull(" . $newfilter . "),''," . $newfilter . ")";\r
+ } else {\r
+ return "coalesce(" . $newfilter . ",'')";\r
+ }\r
+ }\r
+\r
+\r
+ function GetMultiParmFilter($filter) {\r
+ $flen=$filter['len'];\r
+ if (!is_numeric($flen)) return "";\r
+ $flen=intval($flen);\r
+ $newfilter='(';\r
+ for ($j=0; $j<$flen; $j++) {\r
+ if ($j > 0) $newfilter.=",";\r
+ $newfilter.='?';\r
+ $this->PushParam($filter[$j]);\r
+ }\r
+ $newfilter.=')';\r
+ return $newfilter;\r
+ }\r
+\r
+ function XmlStringCell($value) {\r
+ if (!isset($value)) {\r
+ $result="";\r
+ }\r
+ else {\r
+ if ($this->convertCharSet) {\r
+ $value=utf8_encode($value);\r
+ $result=htmlspecialchars($value, ENT_COMPAT, 'UTF-8');\r
+ } else {\r
+ $result=htmlspecialchars($value);\r
+ }\r
+ }\r
+ if ($this->fmt=="html" && $result=="") $result=" ";\r
+ return "<td>".$result."</td>";\r
+ }\r
+\r
+ // for the root node, parentID should "" (empty string)\r
+ // containerORleaf: L/zero (leaf), C/non-zero (container)\r
+ // selectable: 0->not selectable, 1->selectable\r
+ function WriteTreeRow($parentID, $ID, $description, $containerORleaf, $selectable) {\r
+ echo "\n<tr>";\r
+ echo $this->XmlStringCell($parentID);\r
+ echo $this->XmlStringCell($ID);\r
+ echo $this->XmlStringCell($description);\r
+ echo $this->XmlStringCell($containerORleaf);\r
+ echo $this->XmlStringCell($selectable);\r
+ echo "</tr>";\r
+ }\r
+\r
+}\r
+\r
+?>\r
+\r