35 private $columnSQLArray;
49 $date=
new DateTime();
50 $dateText= $date->format(
"Ym");
51 $date= DateTime::createFromFormat(
"Ym", $dateText);
53 for($i=0; $i <= 12; $i++)
55 $row= array(
"date" =>
"'" . $date->format(
"Ym") .
"'::varchar",
"title" => $date->format(
"M"),
"months" => array_fill(0,13, 0),
"quarters" => array_fill(0,4,0));
56 $row[
"months"][$i]= 1;
57 $row[
"quarters"][floor($i/4)]= 1;
59 $date->modify(
"-1 month");
64 throw new exception (
"Pivot CTE not created correctly: " . $e->getMessage());
67 $this->pivotArray= $pivotArray;
68 $this->columnSQLArray= array();
78 if (isset($this->cte))
82 foreach($this->pivotArray as $pivotRow)
84 $cteArray[]=
"(" . $pivotRow[
"date"] .
"," . implode(
",", $pivotRow[
"months"]) .
"," . implode(
",", $pivotRow[
"quarters"]) .
")";
87 $this->cte=
"with monthPivotCTE(yearmo,m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12,q0,q1,q2,q3) as (values " . implode(
",", $cteArray) .
")";
101 if (isset($this->columnSQLArray[$toBeSummed]))
102 return $this->columnSQLArray[$toBeSummed];
104 $columnArray= array();
105 for($i=0; $i <= 12; $i++)
107 $columnArray[]=
"sum($toBeSummed * m$i)";
110 $this->columnSQLArray[$toBeSummed]= implode(
",", $columnArray);
111 return $this->columnSQLArray[$toBeSummed];
125 foreach($this->pivotArray as $pivotRow)
127 $col= $first ?
"MTD" : $pivotRow[
"title"];
128 $columnArray[$col]=
"number";
143 function getIsFilterChanged() { ?>
144 function isFilterChanged(oldFilter, newFilter)
147 if (oldFilter ==
null)
149 if (newFilter ==
null)
153 else if (newFilter ==
null)
156 var oldConstructor= oldFilter.constructor;
157 var newConstructor= newFilter.constructor;
158 var oldLogic, oldFilters, newLogic, newFilters;
159 if (oldConstructor === Array)
162 oldFilters= oldFilter;
164 else if (oldConstructor === Object)
166 oldLogic= oldFilter.logic ==
null ?
"and" : oldFilter.logic.trim();
167 oldFilters= oldFilter.filters;
171 if (newConstructor === Array)
174 newFilters= newFilter;
176 else if (newConstructor === Object)
178 newLogic= newFilter.logic ==
null ?
"and" : newFilter.logic.trim();
179 newFilters= newFilter.filters;
183 if (oldLogic != newLogic)
185 var oldFiltersEmpty= oldFilters ==
null || oldFilters.constructor !== Array || oldFilters.length == 0;
186 var newFiltersEmpty= newFilters ==
null || newFilters.constructor !== Array || newFilters.length == 0;
187 if (oldFiltersEmpty != newFiltersEmpty)
189 if (oldFilters.length != newFilters.length)
193 for(var i=0; i!= oldFilters.length; i++)
195 var record= oldFilters[i];
196 if (record.field ==
null || record.operator ==
null || record.value ==
null)
198 map[
""+record.field+
"||"+record.operator+
"||"+record.value]=
true;
200 for(var i=0; i!= newFilters.length; i++)
202 var record= newFilters[i];
203 if (record.field ==
null || record.operator ==
null || record.value ==
null)
205 if (map[
""+record.field+
"||"+record.operator+
"||"+record.value] ==
null)
232 function initReport($reportPage, $report, $pageable=
"true", $pageSize=30, $printerFriendly=
false, $sort=
"", $filter=
"") {
233 $dataUrl= $reportPage . (
false !== strpos($reportPage,
"?") ?
"&" :
"?") .
"operation=readReport";
235 var filterChanged=
true;
236 function initReport(afterInitFunc, parameterMapFunc, parseFunc, dataBoundFunc, preInitFunc)
239 var pageSize= <?php echo $pageSize; ?>;
241 var currentFilter=
null;
243 $.post(
"<?php echo $dataUrl; ?>", {report:
"<?php echo $report;?>", limit: pageSize, includeSchema:
"Y", excludeData:
"Y"},
247 if (!errorsAreShown(topData,
"formValidateMainDiv"))
249 if (typeof(preInitFunc) ==
"function")
250 (preInitFunc)(topData);
251 count= topData.reportData.total;
252 var sort= <?php echo trim($sort) ==
"" ?
'{field: topData.columnData[0].field, dir: "asc"};' :
"$sort;"; ?>
253 var filter= <?php echo trim($filter) ==
"" ?
"[];" :
"$filter;"; ?>
254 var grid= $(
"#reportGrid").kendoGrid({
258 url:
"<?php echo $dataUrl; ?>",
262 parameterMap:
function(data, type) {
263 <?php
if ($printerFriendly) { ?>
264 var parameters= {report:
"<?php echo $report; ?>", limit: -1, offset: 0};
266 var parameters= {report:
"<?php echo $report; ?>", limit: pageSize, offset: data.skip};
268 if (data.sort !=
null && data.sort.length > 0)
270 var sortCols= [], sortDirs= [];
271 for(var i=0, length=data.sort.length; i!= length; i++)
273 var record= data.sort[i];
274 sortCols.push(record.field);
275 sortDirs.push(record.dir);
277 parameters.sortCols= kendo.stringify(sortCols);
278 parameters.sortDirs= kendo.stringify(sortDirs);
280 if (data.filter !=
null)
282 var filterCols= [], filterOps= [], filterValues= [];
283 var filters= data.filter.filters;
284 for(var i=0, length=filters.length; i!= length; i++)
286 var record= filters[i];
287 filterCols.push(record.field);
288 filterOps.push(record.operator);
290 if (record.value.constructor == Date)
291 filterValues.push(kendo.toString(record.value,
'yyyy-MM-dd'));
293 filterValues.push(record.value);
295 parameters.filterCols= kendo.stringify(filterCols);
296 parameters.filterOps= kendo.stringify(filterOps);
297 parameters.filterValues= kendo.stringify(filterValues);
299 filterChanged= initial || isFilterChanged(currentFilter, data.filter);
300 currentFilter= data.filter;
302 if (typeof(parameterMapFunc) ==
"function")
303 (parameterMapFunc)(data, parameters, filterChanged);
307 parameters.includeCount=
"Y";
308 filterChanged=
false;
315 model: topData.modelData,
318 parse:
function(data) {
320 if (!errorsAreShown(data,
"formValidateMainDiv"))
322 var countChanged=
false;
323 if (data.reportData.total == -1)
325 data.reportData.total= count;
329 count= data.reportData.total;
333 if (typeof(parseFunc) ==
"function")
334 (parseFunc)(data, countChanged);
336 return data.reportData;
341 serverFiltering:
true,
346 columns: topData.columnData,
347 <?php
if (!$printerFriendly) { ?>
348 pageable: <?php echo $pageable; ?>,
353 dataBound:
function(e) {
354 if (typeof(dataBoundFunc) ==
"function")
355 (dataBoundFunc) (
this, e);
359 }).data(
"kendoGrid");
361 <?php
if (!$printerFriendly) { ?>
362 $(
"#downloadCSVBtn").click(
function () {
363 $(
"#downloadCSVForm .extraCSVForm").
remove();
364 var sort= grid.dataSource.sort();
367 var sortCols= [], sortDirs= [];
368 for(var i=0, length=sort.length; i!= length; i++)
371 sortCols.push(record.field);
372 sortDirs.push(record.dir);
374 $(
"#downloadCSVForm").append(
"<input class='extraCSVForm' name='sortCols' value='" + kendo.stringify(sortCols) +
"'>");
375 $(
"#downloadCSVForm").append(
"<input class='extraCSVForm' name='sortDirs' value='" + kendo.stringify(sortDirs) +
"'>");
377 var filter= grid.dataSource.filter();
380 var filterCols= [], filterOps= [], filterValues= [];
381 var filters= filter.filters;
382 for(var i=0, length=filters.length; i!= length; i++)
384 var record= filters[i];
385 filterCols.push(record.field);
386 filterOps.push(record.operator);
387 filterValues.push(record.value);
389 $(
"#downloadCSVForm").append(
"<input class='extraCSVForm' name='filterCols' value='" + kendo.stringify(filterCols) +
"'>");
390 $(
"#downloadCSVForm").append(
"<input class='extraCSVForm' name='filterOps' value='" + kendo.stringify(filterOps) +
"'>");
391 $(
"#downloadCSVForm").append(
"<input class='extraCSVForm' name='filterValues' value='" + kendo.stringify(filterValues) +
"'>");
393 $(
"#downloadCSVForm").submit();
396 if (typeof(afterInitFunc) ==
"function")
417 function initReportClientSide($reportPage, $report, $title, $additionalParameters= array(), $scrollable=
false, $beforeInitFunc=
"", $afterInitFunc=
"") {
418 $dataUrl= $reportPage . (
false !== strpos($reportPage,
"?") ?
"&" :
"?") .
"operation=readReport";
419 $parameters= array(
"report" => $report,
"limit" => -1,
"offset" => 0,
"includeSchema" =>
"Y");
420 foreach($additionalParameters as $key => $value)
422 $parameters[$key]= $value;
425 function initReport()
430 var currentFilter=
null;
432 $.post(
"<?php echo $dataUrl; ?>", <?php echo json_encode($parameters); ?>,
436 if (!errorsAreShown(topData,
"formValidateMainDiv"))
438 var sort= {field: topData.columnData[0].field, dir:
"asc"};
439 var gridDefinition= {
442 read:
function (options) {
443 options.success(topData.reportData.data);
447 model: topData.modelData
452 columns: topData.columnData,
458 scrollable: <?php echo ($scrollable ?
"true" :
"false"); ?>
461 <?php echo ($beforeInitFunc !=
"" ?
"($beforeInitFunc) (gridDefinition);" :
""); ?>
463 var grid= $(
"#reportGrid").kendoGrid(gridDefinition).data(
"kendoGrid");
465 $(
"#downloadCSVBtn").click(
function () {
466 downloadCSVClientSide();
469 <?php echo ($afterInitFunc !=
"" ?
"($afterInitFunc) (grid);" :
""); ?>
482 function downloadCSVClientSide()
484 var grid= $(
"#reportGrid").data(
"kendoGrid");
488 for(var i=0, length= grid.columns.length; i!= length; i++)
490 var record= grid.columns[i];
492 if (record.hidden ==
null || !record.hidden)
494 columns.push(record.field);
495 csvRecord.push(csvEscape(record.title));
498 csvData.push(csvRecord.join());
500 var data= grid.dataSource.data();
501 var filter= grid.dataSource.filter();
502 var sort= grid.dataSource.sort();
503 var query =
new kendo.data.Query(data);
504 data= query.filter(filter).sort(sort).data;
506 for(var i=0; i!= data.length; i++)
511 for(var j=0; j!= grid.columns.length; j++)
513 if (record.hidden ==
null || !record.hidden)
515 var column= grid.columns[j];
516 var kendoCol= column.field;
517 var value= column.template !=
null ? kendo.template(record[kendoCol]) : (column.format !=
null ? kendo.format(column.format, record[kendoCol]) : record[kendoCol]);
518 csvRecord.push(csvEscape(value));
522 csvData.push(csvRecord.join());
525 var blob =
new Blob([csvData.join(
"\r\n")], { type:
'text/csv;charset=utf-8;' });
526 var filename=
"<?php echo $title; ?>.csv";
527 if (navigator.msSaveBlob)
528 navigator.msSaveBlob(blob, filename);
531 var link = document.createElement(
"a");
532 if (link.download !=
null)
535 var url = URL.createObjectURL(blob);
536 link.setAttribute(
"href", url);
537 link.setAttribute(
"download", filename);
538 link.style.visibility =
'hidden';
539 document.body.appendChild(link);
541 document.body.removeChild(link);
555 function csvEscape(
string)
557 if (
string ==
null || typeof(
string) !=
"string")
559 string=
string.indexOf(
'"') != -1 ?
string.replace(
'"',
'""') : string;
560 string=
string.indexOf(
',') != -1 ||
string.indexOf(
'\n') != -1 ?
'"' +
string +
'"' : string;
571 function getReportTitles()
574 $reportTitles= array();
575 foreach($reportList as $key => $record)
577 $reportTitles[$key]= isset($record[
"title"]) ? $record[
"title"] : $key;
579 return $reportTitles;
589 function getCamelCase($string)
591 $camelCase= lcfirst(str_replace(
" ",
"", ucwords(strtolower(trim(preg_replace(
"/[^a-z0-9 ]+/i",
" ", $string))))));
592 return is_numeric($camelCase[0]) ?
"n$camelCase" : $camelCase;
605 function compileMenu($conf, $reportList, $reportFrontEndFile, $useRadioButtons=
false)
607 $menu=
"<table class='reportMenu'>";
608 foreach($conf as $sectionTitle => $reports)
610 $menu.=
"<tr class='sectionHeader'><td>$sectionTitle</td></tr>";
612 foreach($reports as $report)
614 $class= $count % 2 == 1 ?
"odd" :
"even";
615 $reportTitle= isset($reportList[$report][
"title"]) ? $reportList[$report][
"title"] : $report;
616 $href= isset($reportList[$report][
"url"]) ? $reportList[$report][
"url"] : $reportFrontEndFile . (
false !== strpos($reportFrontEndFile,
"?") ?
"&" :
"?") .
"report=$report";
618 $menu.=
"<tr class='$class'><td>" . ($useRadioButtons ?
"<input type='radio' class='reportRadioButton' name='reportRadioButton' value='$href'> $reportTitle" :
"<a href=$href>$reportTitle</a>");
619 $menu.=
"</td></tr>";
650 function getSchemaUsingBaseSQL($dbh, &$baseSQL, $dateFormat, $dateIfNull, $colArray, $replaceString, $replaceCode, $values, &$sqls, &$errors, &$modelData, &$columnData, $includeSchema, $report,
651 $defaultDateFormat, $cookieName=
"")
655 foreach($colArray as $colTitle => $colType)
657 $kendoCol= getCamelCase($colTitle);
658 $modelRecord= array(
"type" => $colType ==
"ignore" ?
"string" : $colType);
659 $newTitle= explode(
".", $colTitle);
660 $newTitle= $newTitle[0];
661 $columnRecord= array(
"field" => $kendoCol,
"title" => $newTitle,
"type" => $colType);
662 if ($colType ==
"date")
664 $ifNull= isset($dateIfNull) ? trim($dateIfNull) :
"";
665 $format= isset($dateFormat) ? trim($dateFormat) : (isset($defaultDateFormat) ? trim($defaultDateFormat) :
"");
667 $columnRecord[
"template"]=
"# if ($kendoCol == null || $kendoCol == '') { # $ifNull # } else { # #: kendo.toString(new Date($kendoCol), '$format') # # } #";
669 else if ($colType ==
"number")
671 $columnRecord[
"attributes"]= array(
"style" =>
"text-align: right;");
672 $columnRecord[
"headerAttributes"]= array(
"style" =>
"text-align: right;");
674 else if ($colType ==
"currency")
676 $columnRecord[
"type"]=
"number";
677 $modelRecord[
"type"]=
"number";
678 $columnRecord[
"attributes"]= array(
"style" =>
"text-align: right;");
679 $columnRecord[
"headerAttributes"]= array(
"style" =>
"text-align: right;");
680 $columnRecord[
"format"]=
"{0:c2}";
682 else if ($colType ==
"list")
684 $columnRecord[
"type"]=
"string";
685 $modelRecord[
"type"]=
"string";
688 foreach($values[$colTitle] as $value => $text)
690 $ddl[]= array(
"text" => $text,
"value" => $value);
692 $columnRecord[
"values"]= $ddl;
695 $modelData[$kendoCol]= $modelRecord;
697 if ($colType !=
"ignore")
698 $columnData[]= $columnRecord;
702 if (isset($replaceString) && isset($replaceCode))
705 $replaceCodeString=
"";
706 $cookieExists=
false;
707 if (isset($_COOKIE[$cookieName]))
709 parse_str($_COOKIE[$cookieName], $cookie);
713 if (!$includeSchema && $cookieExists && isset($cookie[$report]) && trim($cookie[$report]) !=
"")
715 $replaceCodeString= trim($cookie[$report]);
719 $replaceCodeString= eval($replaceCode);
720 $cookie[$report]= $replaceCodeString;
721 $expiresInDay= time()+86400;
723 setcookie($cookieName, http_build_query($cookie), $expiresInDay,
"/", $_SERVER[
'SERVER_NAME']);
725 $baseSQL= str_replace($replaceString, $replaceCodeString, $baseSQL);
728 updateSelectSQL($baseSQL, $cols, $errors);
739 function updateSelectSQL(&$baseSQL, $cols, &$errors)
743 $nonAlphaFound=
false;
753 for($i=0,$count=strlen($baseSQL); $i != $count; $i++)
757 if(ctype_alnum ($char) || $char ==
"_")
760 $nonAlphaFound=
false;
764 $willNotBeInExpression=
false;
765 $numInStack= count($stack);
766 $stackEmpty= $numInStack == 0;
767 $lastInStack= $stackEmpty ?
"" : $stack[$numInStack-1];
769 if ($selectFound && $word !=
"" && !$nonAlphaFound && $stackEmpty)
770 $inExpression=
false;
772 switch(strtolower($word))
775 if (!$selectFound && $stackEmpty)
779 if ($selectFound && $stackEmpty)
783 if ($selectFound && $stackEmpty)
785 $selectArray.=
"$selectCalc as " . $cols[$selectIndex++];
792 array_push($stack, $word);
797 if ($lastInStack ==
"case" && !$nonAlphaFound)
800 if (count($stack) == 0)
802 $willNotBeInExpression=
true;
806 $lastInStack= $stack[$numInStack-2];
814 $nonAlphaFound=
true;
815 if ($fromIndex != -1)
817 else if ($word !=
"")
825 array_push($stack, $char);
830 if ($lastInStack == $char)
833 if (count($stack) == 0)
834 $willNotBeInExpression=
true;
838 array_push($stack, $char);
843 if ($lastInStack ==
"{")
846 if (count($stack) == 0)
847 $willNotBeInExpression=
true;
851 if ($lastInStack ==
"[")
854 if (count($stack) == 0)
855 $willNotBeInExpression=
true;
859 if ($lastInStack ==
"(")
862 if (count($stack) == 0)
863 $willNotBeInExpression=
true;
868 if ($selectFound && $stackEmpty)
870 $selectArray.=
"$selectCalc as " . $cols[$selectIndex++];
899 $inExpression= !$willNotBeInExpression;
904 $restOfSQL= substr($baseSQL, $fromIndex);
905 $baseSQL=
"$selectArray from $restOfSQL";
922 function getData($dbh, $fullSQL, &$reportData, &$modelData, &$columnData, &$sqls, &$errors, $dontIncludeId=
false, $excludeData=
false)
925 foreach($modelData as $key => $unused)
927 $colMap[strtolower($key)]= $key;
934 $modelData[$idName]= array(
"type" =>
"number");
935 $modelData= array(
"id" => $idName,
"fields" => $modelData);
939 $modelData= array(
"fields" => $modelData);
945 $sth = db_query($fullSQL,$dbh);
946 $newError= trim(db_last_error());
949 $errors[]= $newError;
950 db_free_result($sth);
953 $booleanFields= array();
955 foreach($modelData[
"fields"] as $kendoCol => $kendoColArray)
957 if ($kendoColArray[
"type"] ==
"boolean")
958 $booleanFields[$kendoCol]= array(
"trueFound" =>
false,
"falseFound" =>
false,
"trueValue" =>
"",
"falseValue" =>
"",
"index" => $index);
963 while($dRecord = db_fetch_assoc($sth, $i++))
965 $kendoRecord= array();
967 $kendoRecord[$idName]= $i;
969 foreach($dRecord as $key => $value)
971 $kendoCol= $colMap[strtolower($key)];
972 $value= trim($value);
974 if (isset($booleanFields[$kendoCol]))
976 $falseFound= $booleanFields[$kendoCol][
"falseFound"];
977 $trueFound= $booleanFields[$kendoCol][
"trueFound"];
980 if (!$trueFound || !$falseFound)
986 $booleanFields[$kendoCol][
"falseValue"]=
"No";
991 $booleanFields[$kendoCol][
"falseValue"]=
"no";
996 $booleanFields[$kendoCol][
"falseValue"]=
"N";
1001 $booleanFields[$kendoCol][
"falseValue"]=
"n";
1006 $booleanFields[$kendoCol][
"falseValue"]=
"0";
1011 $booleanFields[$kendoCol][
"falseValue"]=
"false";
1016 $booleanFields[$kendoCol][
"falseValue"]=
"False";
1021 $booleanFields[$kendoCol][
"trueValue"]=
"Yes";
1026 $booleanFields[$kendoCol][
"trueValue"]=
"yes";
1031 $booleanFields[$kendoCol][
"trueValue"]=
"y";
1036 $booleanFields[$kendoCol][
"trueValue"]=
"Y";
1041 $booleanFields[$kendoCol][
"trueValue"]=
"1";
1046 $booleanFields[$kendoCol][
"trueValue"]=
"true";
1051 $booleanFields[$kendoCol][
"trueValue"]=
"True";
1060 $booleanFields[$kendoCol][
"trueValue"]= $value;
1061 $booleanFields[$kendoCol][
"trueFound"]=
true;
1062 $kendoRecord[$kendoCol]=
true;
1064 else if ($updateFalse)
1066 $booleanFields[$kendoCol][
"falseValue"]= $value;
1067 $booleanFields[$kendoCol][
"falseFound"]=
true;
1068 $kendoRecord[$kendoCol]=
false;
1074 $kendoRecord[$kendoCol]= trim($value);
1077 $reportData[]= $kendoRecord;
1079 db_free_result($sth);
1081 foreach($booleanFields as $kendoCol => $record)
1083 $columnData[$record[
"index"]][
"values"]= array(array(
"text" => $record[
"trueValue"],
"value" =>
true), array(
"text" => $record[
"falseValue"],
"value" =>
false));
1098 function addSort(&$sql, &$errors, $sortCols, $sortDirs, $modelData)
1100 $sortCols= trim($sortCols);
1101 $sortDirs= trim($sortDirs);
1103 if ($sortCols !=
"" && $sortDirs !=
"")
1105 $colsExpanded= json_decode($sortCols,
true);
1106 $dirsExpanded= json_decode($sortDirs,
true);
1107 if (!is_array($colsExpanded))
1108 $errors[]=
"Sort columns is not a valid array.";
1109 if (!is_array($dirsExpanded))
1110 $errors[]=
"Sort directions is not a valid array.";
1111 if (count($colsExpanded) != count($dirsExpanded))
1112 $errors[]=
"Sort arrays need to be the same size.";
1115 $allValidDirs=
true;
1116 foreach($colsExpanded as $col)
1118 $type= trim($modelData[$col][
"type"]);
1119 $dir= strtolower(strval($dirsExpanded[$index]));
1120 $databaseCol= strtolower($type) ==
"string" ?
"nullif(trim($col), '')" : $col;
1121 if (in_array($dir, array(
"asc",
"desc")) ===
false)
1122 $allValidDirs=
false;
1123 $sortSQL[]=
"$databaseCol $dir";
1129 $errors[]=
"Sort directions must be either asc or desc.";
1131 if (count($sortSQL) != 0)
1132 $sql.=
" order by " . implode(
", ", $sortSQL);
1134 else if (($sortCols !=
"" && $sortDirs ==
"") || ($sortCols ==
"" && $sortDirs !=
""))
1135 $errors[]=
"Both sort column and sort direction arrays must be defined for a sort.";
1139 foreach($modelData as $kendoCol => $kendoColArray)
1143 $sql.=
" order by " . (strtolower($kendoColArray[
"type"]) ==
"string" ?
"trim(coalesce($kendoCol, ''))" : $kendoCol) .
" asc";
1158 function cmpSort($a, $b, $compArray)
1160 foreach($compArray as $comp)
1162 switch($comp[
"type"])
1165 $aComp= trim($a[$comp[
"field"]]);
1166 $bComp= trim($b[$comp[
"field"]]);
1167 $comp= $comp[
"dir"] ==
"asc" ? strcmp($aComp, $bComp) : strcmp($bComp, $aComp);
1170 $aComp= floatval($a[$comp[
"field"]]);
1171 $bComp= floatval($b[$comp[
"field"]]);
1172 $comp= $comp[
"dir"] ==
"asc" ? $aComp - $bComp : $bComp - $aComp;
1175 $aComp= strtotime($a[$comp[
"field"]]);
1176 $bComp= strtotime($b[$comp[
"field"]]);
1177 $comp= $comp[
"dir"] ==
"asc" ? $aComp - $bComp : $bComp - $aComp;
1198 function addSortFromData(&$data, &$sqls, &$errors, $sortCols, $sortDirs, $modelData)
1200 $sortCols= trim($sortCols);
1201 $sortDirs= trim($sortDirs);
1203 if ($sortCols !=
"" && $sortDirs !=
"")
1205 $colsExpanded= json_decode($sortCols,
true);
1206 $dirsExpanded= json_decode($sortDirs,
true);
1207 if (!is_array($colsExpanded))
1208 $errors[]=
"Sort columns is not a valid array.";
1209 if (!is_array($dirsExpanded))
1210 $errors[]=
"Sort directions is not a valid array.";
1211 if (count($colsExpanded) != count($dirsExpanded))
1212 $errors[]=
"Sort arrays need to be the same size.";
1215 $allValidDirs=
true;
1216 $compArray= array();
1217 foreach($colsExpanded as $col)
1219 $type= trim($modelData[
"fields"][$col][
"type"]);
1220 $dir= strtolower(strval($dirsExpanded[$index]));
1221 if (in_array($dir, array(
"asc",
"desc")) ===
false)
1222 $allValidDirs=
false;
1223 $compArray[]= array(
"field" => $col,
"dir" => $dir,
"type" => $type);
1229 $errors[]=
"Sort directions must be either asc or desc.";
1231 if (count($sortSQL) != 0)
1232 $sql.=
" order by " . implode(
", ", $sortSQL);
1234 else if (($sortCols !=
"" && $sortDirs ==
"") || ($sortCols ==
"" && $sortDirs !=
""))
1235 $errors[]=
"Both sort column and sort direction arrays must be defined for a sort.";
1238 foreach($modelData as $kendoCol => $kendoColArray)
1240 $compArray[]= array(
"field" => $kendoCol,
"dir" =>
"asc",
"type" => isset($kendoColArray[
"type"]) ? $kendoColArray[
"type"] :
"string");
1245 usort($data,
function($a, $b) use ($compArray) {
1246 return cmpSort($a, $b, $compArray);
1258 function addPagingFromData(&$data, $limit, $offset)
1260 $total= count($data);
1262 $data= array_slice($data, $offset, $limit);
1263 $data= array(
"total" => $total,
"data" => $data);
1278 function addFilter(&$sql, &$countSQL, &$errors, $filterCols, $filterOps, $filterValues, $modelData)
1280 $filterCols= trim($filterCols);
1281 $filterOps= trim($filterOps);
1282 $filterValues= trim($filterValues);
1283 $filterSQL= array();
1285 if ($filterCols !=
"" && $filterOps !=
"" && $filterValues !=
"")
1287 $colsExpanded= json_decode($filterCols,
true);
1288 $opsExpanded= json_decode($filterOps,
true);
1289 $valuesExpanded= json_decode($filterValues,
true);
1290 if (!is_array($colsExpanded))
1291 $errors[]=
"Filter columns is not a valid array.";
1292 if (!is_array($opsExpanded))
1293 $errors[]=
"Filter operators is not a valid array.";
1294 if (!is_array($valuesExpanded))
1295 $errors[]=
"Values is not a valid array.";
1296 if (!(count($colsExpanded) == count($opsExpanded) && count($opsExpanded) == count($valuesExpanded)))
1297 $errors[]=
"Filter arrays need to be the same size.";
1298 $allValidCols=
true;
1301 $opStartMap= array(
"eq" =>
"= '",
"neq" =>
"<> '",
"lt" =>
"< '",
"lte" =>
"<= '",
"gt" =>
"> '",
"gte" =>
">= '",
"startswith" =>
"like '",
"contains" =>
"like '%",
1302 "endswith" =>
"like '%",
"doesnotcontain" =>
"not like '%");
1303 $opEndMap= array(
"eq" =>
"'",
"neq" =>
"'",
"lt" =>
"'",
"lte" =>
"'",
"gt" =>
"'",
"gte" =>
"'",
"startswith" =>
"%'",
"contains" =>
"%'",
"endswith" =>
"'",
"doesnotcontain" =>
"%'");
1306 foreach($colsExpanded as $col)
1308 $databaseCol= strtolower($col);
1309 $op= strtolower(strval($opsExpanded[$index]));
1310 $value= strtolower(strval($valuesExpanded[$index]));
1311 if (!isset($opStartMap[$op]))
1312 $allValidOps=
false;
1314 switch($modelData[$col][
"type"])
1317 $filterSQL[]=
"trim(from lower($databaseCol)) " . $opStartMap[$op] . trim($value) . $opEndMap[$op];
1321 $filterSQL[]=
"$databaseCol " . $opStartMap[$op] . trim($value) . $opEndMap[$op];
1331 else if (!($filterCols ==
"" && $filterOps ==
"" && $filterValues ==
""))
1332 $errors[]=
"All three filter arrays (Columns, operators, and values) must be defined for a filter.";
1334 $filterSQL= count($filterSQL) == 0 ?
"" :
" where (" . implode(
") and (", $filterSQL) .
")";
1336 $countSQL.= $filterSQL;
1372 function readReportCommon($report, &$errors, &$sqls, $dbh, $limit, $offset, $includeSchema, $includeCount, $excludeData, $dontIncludeId, $excludeSort, $sortCols, $sortDirs,
1373 $filterCols, $filterOps, $filterValues, $reportList, $defaultDateFormat, $cookieName)
1375 $reportRecord= $reportList[$report];
1376 validateReportRecord($reportRecord, $errors);
1378 if (count($errors) == 0)
1380 $baseSQL= $reportRecord[
"sql"];
1383 $modelData= array();
1384 $columnData= array();
1386 $dateFormat = isset($reportRecord[
"dateFormat"]) ? $reportRecord[
"dateFormat"] :
"";
1387 $dateEmpty = isset($reportRecord[
"dateEmpty"]) ? $reportRecord[
"dateEmpty"] :
"";
1388 $replaceString = isset($reportRecord[
"replaceString"]) ? $reportRecord[
"replaceString"] :
null;
1389 $replaceCode = isset($reportRecord[
"replaceCode"]) ? $reportRecord[
"replaceCode"] :
null;
1390 $ddl = isset($reportRecord[
"ddl"]) ? $reportRecord[
"ddl"] :
"";
1392 getSchemaUsingBaseSQL($dbh, $baseSQL, $dateFormat, $dateEmpty, $reportRecord[
"cols"], $replaceString, $replaceCode,
1393 $ddl, $sqls, $errors, $modelData, $columnData, $includeSchema, $report, $defaultDateFormat, $cookieName);
1395 $fullSQL=
"select * from ($baseSQL) t";
1396 $countSQL=
"select count(*) from ($baseSQL) t";
1398 addFilter($fullSQL, $countSQL, $errors, $filterCols, $filterOps, $filterValues, $modelData);
1401 addSort($fullSQL, $errors, $sortCols, $sortDirs, $modelData);
1405 $fullSQL.=
" limit $limit offset $offset";
1409 $reportData= array();
1411 if (count($errors) == 0)
1413 getData($dbh, $fullSQL, $reportData, $modelData, $columnData, $sqls, $errors, $dontIncludeId, $excludeData);
1416 $reportData= array(
"total" => -1,
"data" => $reportData);
1421 $sth = db_query($sql,$dbh);
1422 $newError= trim(db_last_error());
1423 if ($newError !=
"")
1425 $errors[]= $newError;
1429 list($count) = db_fetch_array($sth,0);
1430 $reportData[
"total"]= $count;
1432 db_free_result($sth);
1434 return array(
"sql" => $sqls,
"error" => $errors,
"reportData" => $reportData,
"modelData" => $modelData,
"columnData" => $columnData);
1449 function runReadReportCurl($server, $parameters, $showSQL, $cookieName=
"")
1452 $cmd =
"https://${server}.homecu.net${dataFile}?operation=readReport";
1455 return runCurl($server, $parameters, $showSQL, $cmd, $cookieName);
1471 function runCurl($server, $parameters, $cookieName)
1474 $remoteFile = substr($dataFile, 0, -4);
1476 $curlServers = array(
"www3",
"www5",
"www6");
1479 $curlCookies .=
"HCUTicket=" . urlencode($_COOKIE[
'HCUTicket']);
1480 $curlCookies .= ($cookieName !=
"" ?
";$cookieName=" . urlencode($_COOKIE[$cookieName]) :
"");
1482 $cmd =
"https://${server}.homecu.net${remoteFile}?operation=readReport";
1484 $ch=curl_init($cmd);
1485 curl_setopt($ch, CURLOPT_COOKIE, $curlCookies);
1486 curl_setopt($ch, CURLOPT_USERPWD,
"nobody:no1home");
1487 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); #
get response as
string 1488 curl_setopt($ch, CURLOPT_POST,
true);
1489 curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
1490 curl_setopt($ch, CURLOPT_FOLLOWLOCATION,
true);
1491 curl_setopt($ch, CURLOPT_COOKIESESSION,
true );
1492 curl_setopt($ch, CURLOPT_COOKIEJAR,
"/tmp/reportCookie");
1493 curl_setopt($ch, CURLOPT_COOKIEFILE,
"/tmp/reportCookie");
1495 $rawresp=curl_exec($ch);
1512 function printCSVData($reportValues, $report, $reportTitle, $reportList, $defaultDateFormat, $delimiter=
",")
1514 $reportRecord= $reportList[$report];
1515 $reportName= $reportTitle !=
"" ? $reportTitle : (isset($reportRecord[
"title"]) ? $reportRecord[
"title"] : trim($report));
1516 $kendoDateFormat= isset($reportRecord[
"dateFormat"]) ? $reportRecord[
"dateFormat"] : (isset($defaultDateFormat) ? $defaultDateFormat :
"MM/dd/yyyy");
1521 $phpDateFormatArray= array(
"yyyy" =>
"Y",
"dd" =>
"d",
"HH" =>
"H",
"MM" =>
"m",
"mm" =>
"i",
"ss" =>
"s");
1522 $dateArray= array();
1524 $phpDateFormat= $kendoDateFormat;
1525 foreach($phpDateFormatArray as $from => $to)
1527 $phpDateFormat= str_replace($from, $to, $phpDateFormat);
1531 foreach($reportValues[
"modelData"][
"fields"] as $kendoCol => $modelRecord)
1533 if ($modelRecord[
"type"] ==
"date")
1534 $dateArray[$kendoCol]=
true;
1537 foreach($reportValues[
"columnData"] as $column)
1539 $title= strval($column[
"title"]);
1540 if (strpos($title,
"$delimiter") !==
false)
1541 $title=
"\"$title\"";
1544 $csvData[]= implode(
"$delimiter ", $csvRow);
1546 foreach($reportValues[
"reportData"][
"data"] as $row)
1549 foreach($row as $col => $value)
1551 if (isset($dateArray[$col]))
1555 $dateTime=
new DateTime($value);
1556 $value= $dateTime->format($phpDateFormat);
1558 catch (exception $e)
1560 $value=
"(Invalid Date Format)";
1564 $value= strval($value);
1566 if (strpos($value,
"$delimiter") !==
false || strpos($value,
"\n") !==
false)
1567 $value=
"\"$value\"";
1570 $csvData[]= implode(
"$delimiter ", $csvRow);
1572 $csvData= implode(
"\r\n", $csvData);
1574 header(
"Content-length: " . strlen($csvData) );
1575 header(
"Content-type: application/octetstream");
1576 header(
"Content-disposition: inline; filename=\"$reportName.csv\"");
1588 function validateReportRecord($reportRecord, &$errors)
1592 if (!isset($reportRecord[
"sql"]))
1593 throw new exception(
"SQL is required!", 1);
1594 if (!isset($reportRecord[
"cols"]))
1595 throw new exception(
"Cols are required!", 2);
1596 foreach($reportRecord[
"cols"] as $colName => $colType)
1598 if (!in_array($colType, array(
"number",
"string",
"date",
"boolean",
"odata",
"currency",
"ignore",
"list")))
1599 throw new exception(
"Column type is not known.", 3);
1600 if ($colType ==
"list")
1602 if (!isset($reportRecord[
"ddl"]))
1603 throw new exception (
"DDLs are not defined.", 4);
1604 if (!isset($reportRecord[
"ddl"][$colName]))
1605 throw new exception (
"DDL is not defined for $colName.", 5);
1611 $errors[]= $e->getMessage();
getColumnSQL($toBeSummed)