Linux multi-monitor fullscreen support
[ryzomcore.git] / nelns / admin / public_html / display_view.php
blobbc75264a9eb1b460ef12eeaa67e2f5d2a5d21699
1 <?php
2 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
3 // Copyright (C) 2010 Winch Gate Property Limited
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Affero General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Affero General Public License for more details.
15 // You should have received a copy of the GNU Affero General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //include('fake_request_interface.php');
19 include('request_interface.php');
21 /* displayViewTable
22 * displays view $tid for user $uid in group $gid
23 * $selection is an array of preselected lines in the form shard.server.service.variable
24 * each address member might be incomplete (like '*' or 'GPM*')
26 function displayViewTable($uid, $gid, $tid, $selection)
28 global $keep_shard, $keep_server, $keep_service, $display_view;
30 // 1. create views tree
31 buildVariableEnv($uid, $gid, $tid, $vardisp, $bounds, $privilege, $tree, $condensed, $autoDisplay);
33 if ($autoDisplay || $display_view)
35 // 2. select branches
36 if (count($selection) > 0)
38 foreach ($selection as $sel)
40 if ($sel != "")
42 $selarray = expandQuery($sel);
44 foreach ($selarray as $sel)
46 $address = explode(".", $sel);
47 //echo "select address ".$sel."<br>\n";
48 addToSelectNode($tree, $address, 0);
54 // 3. remove unselected branches
55 clearupNode($tree);
57 // 4. build and factorize query
58 $query = factorizeQuery(buildQuery($tree));
60 if ($numsteps == 5)
62 echo "Unsupported entity request now<br>\n";
63 return;
66 $bef = microtime();
67 $qstate = nel_query($query, $result);
68 $aft = microtime();
70 list($usec, $sec) = explode(" ", $bef);
71 $bef = ((float)$sec + (float)$usec);
72 list($usec, $sec) = explode(" ", $aft);
73 $aft = ((float)$sec + (float)$usec);
74 $tm = (int)(($aft-$bef)*1000.0);
76 if (!$qstate)
77 echo "<b>$result</b>\n";
80 displayResult($result, $vardisp, $bounds, $privilege, $condensed, $autoDisplay);
82 return "Executed query '$query'<br>$tm milliseconds computation time<br>\n";
85 function buildVariableEnv($uid, $gid, $tid, &$vardisp, &$bounds, &$privilege, &$tree, &$condensed, &$autoDisplay)
87 $result = sqlquery("SELECT view_row.name AS user_name, variable.name AS var_name, path, warning_bound, error_bound, alarm_order, view_row.filter as varfilter, view_table.filter as viewfilter, display, auto_display, view_row.vid AS vid ".
88 "FROM variable, view_row, view_table ".
89 "WHERE variable.command='variable' AND (view_table.uid='$uid' OR view_table.uid='$gid') AND view_table.tid='$tid' AND view_row.tid='$tid' AND variable.vid=view_row.vid ORDER BY view_row.ordering");
91 while ($result && ($arr=sqlfetch($result)))
93 $vid = $arr["vid"];
94 if (!hasAccessToVariable($vid))
95 continue;
97 $path = $arr["path"];
98 if ($arr["varfilter"] != "" && ($path = filterPath($path, $arr["varfilter"])) == "")
99 continue;
100 if ($arr["viewfilter"] != "" && ($path = filterPath($path, $arr["viewfilter"])) == "")
101 continue;
103 $condensed = ($arr["display"] == "condensed");
104 $autoDisplay = ($arr["auto_display"] == "auto");
106 $varName = getVarName($path);
107 $vardisp[$varName] = $arr["user_name"];
108 $bounds[$varName] = array($arr["warning_bound"], $arr["error_bound"], $arr["alarm_order"]);
109 $privilege[$varName] = getVariableRight($vid);
111 $address = explode(".", $path);
112 //echo "add to tree address $path<br>\n";
113 if (!isset($numsteps))
114 $numsteps = count($address);
115 if ($numsteps != count($address))
117 echo "Invalid table <b>$tid</b>, contains different variable path length (typically, mixed shard/server/service variables with entity variables)\n";
118 return;
120 addToNode($tree, $address, 0);
124 function humanReadableToRaw($str)
126 $l=strlen($str);
128 if ($l==0)
129 return 0;
131 $regexp = '([\+-]?[0-9]+|[\+-]?[0-9]+\.[0-9]*|[\+-]?[0-9]+\.[0-9]*e[0-9]+) *(b|kb|mb|gb|h|mn|s|d|ms)?';
133 if (!eregi($regexp, strtolower($str), $regs))
134 return 0;
136 $num = (float)$regs[1];
137 $unit = $regs[2];
139 switch($unit)
141 case "kb": return $num*1024;
142 case "mb": return $num*1024*1024;
143 case "gb": return $num*1024*1024*1024;
144 case "mn": return $num*60;
145 case "h": return $num*3600;
146 case "ms": return $num/1000.0;
147 case "d": return $num*86400;
148 default: return $num;
151 return $num;
154 function vcmp($a, $b)
156 return ($a["_path_"] == $b["_path_"] ? 0 : $a["_path_"] < $b["_path_"] ? -1 : 1);
159 function displayResult($result, $vardisp, $bounds, $privilege, $condensed=false, $autoDisplay=true)
161 global $admlogin, $filter_shard, $filter_server, $filter_service, $filter_entity, $current_tid, $listPath, $current_tname, $usersData;
162 global $uid, $REMOTE_ADDR, $shardLockState, $enablelock, $IsNevrax;
164 addToLog($result);
166 $colorKeyWords = array("Offline" => "#FF4422", "Failed" => "#FF4422");
168 //echo "result=$result<br>\n";
170 echo "<table border=1>\n";
171 echo "<tr><th rowspan=2>&nbsp;Filters&nbsp;</th><th>shard</th><th>server</th><th>service</th><th>entity</th><td rowspan=2>&nbsp;<input type=submit name='display_view' value='Display\nView'>&nbsp;</td><td rowspan=2>&nbsp;<input type=submit name='reset_filters' value='Reset\nFilters'>&nbsp;</td></tr>\n";
172 echo "<tr>\n";
173 echo "<td><input type=text name=filter_shard value='$filter_shard' size=12 maxlength=256></td>\n";
174 echo "<td><input type=text name=filter_server value='$filter_server' size=12 maxlength=256></td>\n";
175 echo "<td><input type=text name=filter_service value='$filter_service' size=12 maxlength=256></td>\n";
176 echo "<td><input type=text name=filter_entity value='$filter_entity' size=28 maxlength=1024></td>\n";
177 echo "</tr>\n";
178 echo "</table><br>\n";
180 unset($maxvarwidth);
182 if (strlen($result)>0)
184 $arr = explode(" ", $result);
185 $result = &$arr;
186 $numRes = count($result);
187 $numRows = current($result);
188 if ($numRows < 1)
190 echo "<b>NeL query returned no answer</b><br>\n";
191 return;
193 $numLines = ($numRes-$numRows-2)/$numRows;
194 //echo "numRes=$numRes, numLines=$numLines, numRows=$numRows<br>\n";
195 next($result);
197 for ($i=0; $i<$numRows; ++$i)
199 $vars[] = current($result);
200 next($result);
203 unset($lineMap);
204 unset($resultArray);
206 for ($i=0; $i<$numLines; ++$i)
208 $shard = '*';
209 $server = '*';
210 $service = '*';
211 unset($entity);
212 $path = "";
214 foreach($vars as $var)
216 $maxvarwidth[$var] = strlen($var);
218 $val = current($result);
220 next($result);
222 if ($val == "???")
223 unset($val);
225 if ($var == "shard" || $var == "server" || $var == "service" || $var == "entity")
227 if ($path != "")
228 $path .= ".";
229 $path .= $val;
231 if ($var == "shard") { $shard = $val; $listShard[] = $shard; }
232 if ($var == "server") $server = $val;
233 if ($var == "service") $service = $val;
234 if ($var == "entity") $entity = $val;
236 else
238 $line = $lineMap[$path];
239 if (!isset($line))
241 $line = count($resultArray);
242 $lineMap[$path] = $line;
243 $resultArray[$line]["shard"] = $shard;
244 $resultArray[$line]["server"] = $server;
245 $resultArray[$line]["service"] = $service;
246 $resultArray[$line]["_path_"] = $path;
248 $serviceDecomp = explode("/", $service);
249 if (count($serviceDecomp) == 1)
251 $serviceAlias = $service;
252 $serviceSid = $service;
254 else
256 $serviceAlias = $serviceDecomp[0];
257 $serviceSid = $serviceDecomp[1];
260 if (isset($entity))
262 $resultArray[$line]["entity"] = $entity;
263 $listPath[] = $shard.".".$server.".".$service.".".$entity;
265 else
267 $listPath[] = $shard.".".$server.".".$service;
271 if (isset($val))
272 $resultArray[$line][$var] = $val;
274 //echo "set resultArray[$line][$var]=$val<br>\n";
279 //echo "<pre>\n";
280 //print_r($resultArray);
281 //echo "</pre>\n";
283 if (count($listShard) > 0)
285 $listShard = array_unique($listShard);
286 sort($listShard);
288 echo "<table border=1>\n";
289 echo "<tr><th>Shard</th>";
290 if ($enablelock)
291 echo "<th>Locked by</th><th></th>";
292 echo "<th>Annotation by</th><th width='500'>Annotation</th><th></th></tr>\n";
293 foreach($listShard as $shard)
295 $annotation = &$shardLockState[$shard];
297 $hasColor = time()-strtotime($annotation['post_date'])< 120;
298 $lockState = $annotation['lock_state'];
299 echo "<tr".($hasColor ? ' bgcolor=#FFBB88' : '')."><td>&nbsp;$shard&nbsp;</td>";
301 if ($enablelock)
303 echo "<td><font size=0>&nbsp;".($lockState != 0 ? ($usersData[$annotation['lock_user']]["login"]."/".$annotation['lock_ip']."&nbsp;<br>&nbsp;".$annotation['lock_date']) : "not locked")."&nbsp;</font></td>";
304 echo "<td>";
305 if ($lockState == 0)
306 echo "<input type=submit name='upd_lock_button_$shard' value='Lock'>";
307 else if ($lockState == 1)
308 echo "<input type=submit name='upd_unlock_button_$shard' value='Unlock'>";
309 else
310 echo "<input type=submit name='upd_lock_button_$shard' value='Force Lock'>";
311 echo "</td>";
314 echo "<td>&nbsp;".$usersData[$annotation['user_annot']]["login"]."&nbsp;/&nbsp;".$annotation['post_date']."&nbsp;</td>";
315 echo "<td>&nbsp;".($lockState == 1 ? ("<input type=text name='upd_annot_text_$shard' value='".$annotation['annot']."' size=90 maxlength=255".($hasColor ? " style='background-color: #FFBB88;'" : "").">") : $annotation['annot'])."&nbsp;</td>";
316 echo "<td>".($lockState == 1 ? ("<input type=submit name='upd_annot_button_$shard' value='Update'>") : (""))."</td>";
318 echo "</tr>\n";
320 echo "</table><br>\n";
323 echo "<table border=1>\n";
324 echo "<tr valign=center>";
325 foreach ($vars as $var)
327 $display = (isset($vardisp[$var]) ? $vardisp[$var] : "<i>".$var."</i>");
328 if ($var == "shard" || $var == "server" || $var == "service" || $var == "entity" || !$condensed)
329 echo "<th>$display</th>";
330 else
331 break;
334 if ($condensed)
335 echo "<th>Variable</th><th>Value</th>";
337 echo "</tr>\n";
339 if (count($resultArray) > 0)
340 usort($resultArray, "vcmp");
342 $prevShard = "";
343 $idxShard = 0;
344 $dispUpdateButton = false;
346 if ($condensed)
348 for ($i=0; $i<count($resultArray); ++$i)
350 $shard = '*';
351 $server = '*';
352 $service = '*';
353 unset($entity);
355 $arr = &$resultArray[$i];
357 if ($arr["shard"] != $prevShard)
359 if ($prevShard != "")
360 $idxShard = 1-$idxShard;
361 $prevShard = $arr["shard"];
364 $bgcolor = ($idxShard == 0 ? ($i&1 ? "#DDDDDD" : "#EEEEEE") : ($i&1 ? "#D0DDDD" : "#E0EEEE"));
366 $first = true;
368 echo "<tr bgcolor=$bgcolor>";
370 for ($j=0; $j<count($vars); ++$j)
372 $var = $vars[$j];
373 if ($var != "shard" && $var != "server" && $var != "service" && $var != "entity")
374 break;
376 $val = $arr[$var];
377 $bgcolor2 = ((strstr($val, "((TIMEOUT))") == FALSE) ? $bgcolor : "#FF4422");
379 if ($var == "shard") $shard = $val;
380 if ($var == "server") $server = $val;
381 if ($var == "entity" && $val != "") $entity = $val;
384 // parse service name
386 if ($var == "service")
388 splitServiceName($val, $serviceAlias, $serviceName, $serviceId);
389 $service = $serviceName;
392 $vval = ($var == "service" ? $serviceName : $val);
393 if ($var == "shard") $selects = "&filter_shard=$shard";
394 else if ($var == "server") $selects = "&filter_shard=$shard&filter_server=$server";
395 else if ($var == "service") $selects = "&filter_shard=$shard&filter_server=$server&filter_service=$service";
396 else if ($var == "entity") $selects = "&filter_shard=$shard&filter_server=$server&filter_service=$service&filter_entity=$vval";
397 $vval .= ",Default".ucfirst(strtolower($var == "entity" ? "player" : $var)).(isset($current_tname) ? ",$current_tname" : "");
399 echo "<td bgcolor=$bgcolor2 nowrap>&nbsp;<a href='".$_SERVER['PHP_SELF']."?select_view=$vval$selects'>$val</a>".((($admlogin=="root" || $IsNevrax) && $var=="service") ? "&nbsp;<a href='commands.php?preselServ=$shard.$server.$serviceAlias'><font size=1>[cmd]</font></a>" : "")."</td>";
402 $numprev = $j;
404 for (; $j<count($vars); ++$j)
406 $var = $vars[$j];
407 $val = $arr[$var];
409 if (!isset($val) || $val == "")
410 continue;
412 if (!$first)
414 echo "<tr bgcolor=$bgcolor>";
415 for ($k=0; $k<$numprev; ++$k)
416 echo "<td bgcolor=$bgcolor></td>";
419 $first = false;
421 $maxvarwidth[$var] = max($maxvarwidth[$var], strlen($val));
423 $bound = &$bounds[$var];
424 $state = 0;
425 if (isset($bound) && $val != "")
427 $realval = humanReadableToRaw($val);
428 if ($bound[2] == 'gt')
430 if ($bound[0]!=-1 && $realval >= $bound[0])
431 $state = 1;
432 if ($bound[1]!=-1 && $realval >= $bound[1])
433 $state = 2;
435 else
437 if ($bound[0]!=-1 && $realval <= $bound[0])
438 $state = 1;
439 if ($bound[1]!=-1 && $realval <= $bound[1])
440 $state = 2;
444 $btcolor = ($state==0 ? $bgcolor : ($state==1 ? "#FFCC88" : "#FF4422"));
446 if (isset($colorKeyWords[$val]))
447 $btcolor = $colorKeyWords[$val];
449 if ($privilege[$var] == 'rw' && $shardLockState[$shard]['lock_state'] == 1)
451 $valdisp = "<input name='updvar_$shard|$server|$serviceAlias|".(isset($entity)?"$entity|":"")."$var' value='$val' size=16 maxlength=64 style='background-color: $btcolor;'><input type=hidden name='prevvar_$shard|$server|$serviceAlias|".(isset($entity)?"$entity|":"")."$var' value='$val'>";
452 $dispUpdateButton = true;
454 else
456 $valdisp = "$val";
459 echo "<td>$var</td><td bgcolor=$btcolor nowrap>$valdisp</td></tr>\n";
463 else
465 for ($i=0; $i<count($resultArray); ++$i)
467 $arr = &$resultArray[$i];
468 foreach($vars as $var)
470 $val = $arr[$var];
471 $maxvarwidth[$var] = max($maxvarwidth[$var], strlen($val));
475 for ($i=0; $i<count($resultArray); ++$i)
477 $shard = '*';
478 $server = '*';
479 $service = '*';
480 unset($entity);
481 unset($line);
483 $arr = &$resultArray[$i];
485 if ($arr["shard"] != $prevShard)
487 if ($prevShard != "")
488 $idxShard = 1-$idxShard;
489 $prevShard = $arr["shard"];
492 $bgcolor = ($idxShard == 0 ? ($i&1 ? "#DDDDDD" : "#EEEEEE") : ($i&1 ? "#D0DDDD" : "#E0EEEE"));
494 foreach($vars as $var)
496 $val = $arr[$var];
498 if ($val == "???") $val = NULL;
499 $addlink = false;
501 $bgcolor2 = ((strstr($val, "((TIMEOUT))") == FALSE) ? $bgcolor : "#FF4422");
503 if ($var == "shard") { $addlink = true; $shard = $val; }
504 if ($var == "server") { $addlink = true; $server = $val; }
505 if ($var == "entity" && $val != "") { $addlink = true; $entity = $val; }
508 // parse service name
510 if ($var == "service")
512 splitServiceName($val, $serviceAlias, $serviceName, $serviceId);
513 $service = $serviceName;
514 $addlink = true;
517 //$maxvarwidth[$var] = max($maxvarwidth[$var], strlen($val));
519 $bound = &$bounds[$var];
520 $state = 0;
521 if (isset($bound) && $val != "")
523 $realval = humanReadableToRaw($val);
524 if ($bound[2] == 'gt')
526 if ($bound[0]!=-1 && $realval >= $bound[0])
527 $state = 1;
528 if ($bound[1]!=-1 && $realval >= $bound[1])
529 $state = 2;
531 else
533 if ($bound[0]!=-1 && $realval <= $bound[0])
534 $state = 1;
535 if ($bound[1]!=-1 && $realval <= $bound[1])
536 $state = 2;
540 $btcolor = ($state==0 ? $bgcolor : ($state==1 ? "#FFCC88" : "#FF4422"));
542 if (isset($colorKeyWords[$val]))
543 $btcolor = $colorKeyWords[$val];
545 if (strstr($val, "((TIMEOUT))") != FALSE)
546 $btcolor = "#FF4422";
548 if ($privilege[$var] == 'rw' && $shardLockState[$shard]['lock_state'] == 1)
550 $len = max(min($maxvarwidth[$var], 16), 4);
551 $valdisp = "<input name='updvar_$shard|$server|$serviceAlias|".(isset($entity)?"$entity|":"")."$var' value='$val' size=$len maxlength=64 style='background-color: $btcolor;'><input type=hidden name='prevvar_$shard|$server|$serviceAlias|".(isset($entity)?"$entity|":"")."$var' value='$val'>";
552 $dispUpdateButton = true;
554 else
556 $valdisp = "$val";
559 if ($addlink)
561 $vval = ($var == "service" ? $serviceName : $val);
562 if ($var == "shard") $selects = "&filter_shard=$shard";
563 else if ($var == "server") $selects = "&filter_shard=$shard&filter_server=$server";
564 else if ($var == "service") $selects = "&filter_shard=$shard&filter_server=$server&filter_service=$vval";
565 else if ($var == "entity") $selects = "&filter_shard=$shard&filter_server=$server&filter_service=$service&filter_entity=$vval";
566 $vval .= ",Default".ucfirst(strtolower($var == "entity" ? "player" : $var)).(isset($current_tname) ? ",$current_tname" : "");
568 $line .= "<td bgcolor=$btcolor nowrap>&nbsp;<a href='".$_SERVER['PHP_SELF']."?select_view=$vval$selects'>$valdisp</a>".((($admlogin=="root" || $IsNevrax) && $var=="service") ? "&nbsp;<a href='commands.php?preselServ=$shard.$server.$serviceAlias'><font size=1>[cmd]</font></a>" : "")."&nbsp;</td>";
570 else
572 $line .= "<td bgcolor=$btcolor nowrap>&nbsp;$valdisp&nbsp;</td>";
576 echo "<tr bgcolor=$bgcolor>";
577 echo $line;
578 echo "</tr>\n";
583 if (!$condensed)
585 echo "<tr height=5><td colspan=".(count($vars)+1)."></td></tr>";
586 echo "<tr>";
587 foreach($vars as $var)
589 $len = max(min($maxvarwidth[$var], 16), 4);
590 if ($var != "shard" && $var != "server" && $var != "service" && $var != "entity" && $privilege[$var] == 'rw')
591 echo "<td>&nbsp;<input name='override_$var' size=$len maxlength=64>&nbsp;</td>";
592 else
593 echo "<td><i>&nbsp;All</i></td>";
595 echo "</tr>\n";
598 echo "</table><br>\n";
599 if ($dispUpdateButton)
600 echo "<input type=submit name='upd_values' value='Update Values'>\n";
602 else
604 echo "<b>NeL query returned no answer</b><br>\n";
609 function addToNode(&$node, &$address, $step)
611 if ($step >= count($address))
612 return;
613 //echo "addToNode:$address[$step]<br>\n";
614 addToNode($node[$address[$step]], $address, $step+1);
617 function filterPath($path, $filter)
619 $pnodes = explode(".", $path);
620 $fnodes = explode(".", $filter);
622 for ($i=0; $i<count($pnodes); ++$i)
624 if ($fnodes[$i][0] == '@')
626 $rnodes[] = substr($fnodes[$i], 1);
628 else if ($fnodes[$i] == "*" || $fnodes[$i] == "#" || $fnodes[$i] == "" || $pnodes[$i] == $fnodes[$i])
630 $rnodes[] = $pnodes[$i];
632 else if ($pnodes[$i] == "*" || $pnodes[$i] == "#")
634 $rnodes[] = $fnodes[$i];
636 else
638 return "";
642 //echo "filter($path, $filter)=".join(".", $rnodes)."<br>\n";
644 return join(".", $rnodes);
647 function partialFilterPath($path, $filter)
649 $pnodes = explode(".", $path);
650 $fnodes = explode(".", $filter);
652 for ($i=0; $i<count($pnodes); ++$i)
654 if ($fnodes[$i][0] == '@')
656 $rnodes[] = substr($fnodes[$i], 1);
658 else if ($fnodes[$i] == "*" || $fnodes[$i] == "#" || $fnodes[$i] == "" || (strstr($pnodes[$i], $fnodes[$i]) !== FALSE) && $i==0 || $pnodes[$i] == $fnodes[$i])
660 $rnodes[] = $pnodes[$i];
662 else if ($pnodes[$i] == "*" || $pnodes[$i] == "#")
664 $rnodes[] = $fnodes[$i];
666 else
668 return "";
672 //echo "filter($path, $filter)=".join(".", $rnodes)."<br>\n";
674 return join(".", $rnodes);
677 function splitServiceName($service, &$serviceAlias, &$serviceName, &$serviceId)
679 if (($p1 = strpos($service, "/")) === FALSE || ($p2 = strpos($service, "-")) === FALSE || $p2<$p1)
681 $serviceName = $service;
682 $serviceAlias = $service;
683 $serviceId = $service;
685 else
687 $serviceName = substr($service, $p1+1, $p2-$p1-1);
688 $serviceAlias = substr($service, 0, $p1);
689 $serviceId = substr($service, $p2);
693 function filterPathUsingAliases($path, $filter)
695 $pnodes = explode(".", $path);
696 $fnodes = explode(".", $filter);
698 for ($i=0; $i<count($pnodes) || $i<count($fnodes); ++$i)
700 $aliases = split( '[/-]', $pnodes[$i] );
701 if (count($aliases) == 3)
703 $pmatch = $aliases[1];
704 $palias = $aliases[0];
706 else
708 $pmatch = $aliases[0];
709 $palias = $aliases[0];
712 if ($fnodes[$i][0] == '@')
714 $rnodes[] = substr($fnodes[$i], 1);
716 else if ($fnodes[$i] == "*" || $fnodes[$i] == "#" || $fnodes[$i] == "" || $pmatch == $fnodes[$i])
718 $rnodes[] = $palias;
720 else if ($pnodes[$i] == "*" || $pnodes[$i] == "#" || $pnodes[$i] == "")
722 $rnodes[] = $fnodes[$i];
724 else
726 return "";
730 //echo "filter($path, $filter)=".join(".", $rnodes)."<br>\n";
732 return join(".", $rnodes);
735 function addToSelectNode(&$node, &$address, $step)
737 //echo "--addToSelectNode(step=$step,count(address)=".count($address).")<br>\n";
738 if ($node == NULL)
740 return true;
742 else if ($step >= count($address))
744 $nodes = array_keys($node);
745 foreach($nodes as $nod)
747 if ($nod == "___flag")
748 continue;
749 $subnode = &$node[$nod];
750 addToSelectNode($subnode, $address, $step+1);
751 $subnode["___flag"] = true;
753 return true;
756 $sel = $address[$step];
757 $sel_reg = "^".str_replace("*", ".*", $sel)."$";
758 $sel_cut = str_replace("*", "&&&&&", $sel);
760 //echo "----addToSelectNode: sel=$sel sel_reg=$sel_reg sel_cut=$sel_cut<br>\n";
762 $nodes = array_keys($node);
764 $flag = false;
766 foreach($nodes as $nod)
768 if ($nod == "___flag")
769 continue;
771 $subnode = &$node[$nod];
772 $nod_reg = "^".str_replace("#", ".*", str_replace("*", ".*", $nod))."$";
773 //$nod_reg = "^".str_replace("*", ".*", $nod)."$";
774 $nod_cut = str_replace("*", "&&&&&", $nod);
776 //echo "addToSelectNode: nod=$nod nod_reg=$nod_reg nod_cut=$nod_cut<br>\n";
778 // if subnode matches selection, subnode is more restrictive and then flag subnode and keep subnode
779 if (eregi($sel_reg, $nod_cut))
781 //echo "node $nod matches select $sel<br>\n";
782 if (addToSelectNode($subnode, $address, $step+1))
784 $subnode["___flag"] = true;
785 $flag = true;
788 // if selection matches subnode, selection is more restrictive and then copy subnode as selection, flag new subnode and keep it
789 else if (eregi($nod_reg, $sel_cut))
791 //echo "selection $sel matches node $nod, adding node $sel<br>\n";
792 addNode($node[$sel], $subnode);
793 $subnode = &$node[$sel];
794 if (addToSelectNode($subnode, $address, $step+1))
796 $subnode["___flag"] = true;
797 $flag = true;
802 return $flag;
805 function clearupNode(&$node)
807 if (!is_array($node))
808 return;
810 $nodes = array_keys($node);
812 foreach ($nodes as $key)
814 $subnode = &$node[$key];
815 if ($subnode["___flag"])
817 unset($subnode["___flag"]);
818 clearupNode($subnode);
820 else
822 unset($node[$key]);
827 function dispNode(&$node, $indent)
829 if (count($node) < 1)
830 return;
832 foreach ($node as $key => $subnode)
834 if ($key != "___flag")
836 for ($i=0;$i<$indent; ++$i)
837 echo "-";
838 echo $key.($subnode["___flag"] ? " flag":"")."<br>\n";
839 dispNode($subnode, $indent+1);
844 function addNode(&$dest, &$src)
846 if (!is_array($src) || count($src) < 1)
847 return;
849 foreach ($src as $key => $subnode)
850 if ($key != "___flag")
851 addNode($dest[$key], $subnode);
854 function buildQuery(&$node)
856 if (!is_array($node) || count($node) < 1)
857 return;
859 $hasChild = count($node)>1;
861 if ($hasChild)
862 $sub .= "[";
863 $i = 0;
864 foreach ($node as $key => $subnode)
866 $sub .= "$key";
867 if (is_array($subnode) && count($subnode)>=1)
869 $sub .= ".";
870 $sub .= buildQuery($subnode);
872 if ($i < count($node)-1)
873 $sub .= ",";
874 ++$i;
876 if ($hasChild)
877 $sub .= "]";
879 return $sub;
887 function factorizeQuery($query)
889 global $factorizeForward;
891 $factorizeForward = true;
892 $ret = factorizeQueryInternal($query);
893 /* $factorizeForward = false;
894 $ret = factorizeQueryInternal($ret)
895 */ return $ret;
898 function factorizeQueryInternal($query)
900 global $alev;
901 ++$alev;
903 if ($query == "")
904 return $query;
906 //echo "$alev factorizeQuery($query)<br>\n";
907 $blocs = splitQuery($query);
908 unset($newQuery);
910 $first = true;
912 foreach ($blocs as $bloc)
914 $newBloc = factorizeBloc($bloc);
915 if (!$first)
916 $newQuery .= '.';
917 $newQuery .= $newBloc;
918 $first = false;
921 //echo "$alev factorizeQuery($query) = $newQuery<br>\n";
922 --$alev;
923 return $newQuery;
926 function splitQuery($query)
928 $i=0;
929 while ($i<strlen($query))
931 $bloc = "";
932 $level = 0;
933 while ($i<strlen($query) && (($char=$query{$i})!='.' || $level!=0))
935 if ($char == '[') ++$level;
936 else if ($char == ']') --$level;
937 $bloc .= $char;
938 ++$i;
940 ++$i;
941 if ($level != 0)
942 echo "Error on query '$query', badly formed (missing end bracket?)<br>\n";
943 $arr[] = $bloc;
945 return $arr;
948 function separateLastQueryBloc($query, &$lead, &$last)
950 $i=strlen($query)-1;
951 $level = 0;
952 while ($i>=0 && (($char=$query{$i})!='.' || $level!=0))
954 if ($char == '[') ++$level;
955 else if ($char == ']') --$level;
956 --$i;
958 if ($level != 0)
959 echo "Error on query '$query', badly formed (missing end bracket?)<br>\n";
961 if ($i == -1)
963 $lead = "";
964 $last = $query;
966 else
968 $lead = substr($query, 0, $i);
969 $last = substr($query, $i+1);
973 function separateFirstQueryBloc($query, &$first, &$follow)
975 $i=0;
976 $level = 0;
977 while ($i<strlen($query) && (($char=$query{$i})!='.' || $level!=0))
979 if ($char == '[') ++$level;
980 else if ($char == ']') --$level;
981 ++$i;
983 if ($level != 0)
984 echo "Error on query '$query', badly formed (missing end bracket?)<br>\n";
986 if ($i == strlen($query))
988 $follow = "";
989 $first = $query;
991 else
993 $first = substr($query, 0, $i);
994 $follow = substr($query, $i+1);
998 function factorizeBloc($bloc)
1000 global $factorizeForward;
1001 return $factorizeForward ? factorizeForwardBloc($bloc) : factorizeBackwardBloc($bloc);
1004 function factorizeForwardBloc($bloc)
1006 if ($bloc{0} != '[')
1007 return $bloc;
1009 $queries = splitBloc($bloc);
1011 if (count($queries) == 0)
1012 return;
1013 if (count($queries) == 1)
1014 return $queries[0];
1016 global $alev;
1017 ++$alev;
1018 //echo "$alev factorizeForwardBloc($bloc)<br>\n";
1020 unset($factors);
1021 foreach ($queries as $query)
1023 $newQuery = factorizeQueryInternal($query);
1024 separateFirstQueryBloc($query, $first, $follow);
1025 //echo "$alev found factor $first - $follow<br>\n";
1027 $factors[$first][] = $follow;
1030 if (count($factors) == 1)
1032 reset($factors);
1033 $a = array_keys($factors);
1034 $factor = $a[0];
1035 $follows = $factors[$factor];
1036 if (count($follows) == 1)
1038 $factorized = $factor.($follows[0] != "" ? '.'.$follows[0] : "");
1040 else
1042 $fbloc = joinArray($follows, ",");
1043 $factorized = ($fbloc == "") ? $factor : $factor.'.'.factorizeBloc('['.$fbloc.']');
1046 else
1048 unset($subblocs);
1049 foreach ($factors as $factor => $follows)
1051 //echo "$alev factor $factor, ".count($follows)." leads<br>\n";
1052 if (count($follows) == 1)
1054 $subblocs[] = $factor.($follows[0] != "" ? '.'.$follows[0] : "");
1056 else
1058 $fbloc = joinArray($follows, ",");
1059 $subblocs[] = ($fbloc == "") ? $factor : $factor.'.'.factorizeBloc('['.$fbloc.']');
1062 $factorized = '['.joinArray($subblocs, ",").']';
1065 //echo "$alev factorizeForwardBloc($bloc) = $factorized<br>\n";
1066 --$alev;
1067 return $factorized;
1070 function factorizeBackwardBloc($bloc)
1072 if ($bloc{0} != '[')
1073 return $bloc;
1075 $queries = splitBloc($bloc);
1077 if (count($queries) == 0)
1078 return;
1079 if (count($queries) == 1)
1080 return $queries[0];
1082 global $alev;
1083 ++$alev;
1084 //echo "$alev factorizeBloc($bloc)<br>\n";
1086 unset($factors);
1087 foreach ($queries as $query)
1089 $newQuery = factorizeQueryInternal($query);
1090 separateLastQueryBloc($query, $lead, $last);
1091 //echo "$alev found factor $lead - $last<br>\n";
1093 $factors[$last][] = $lead;
1096 if (count($factors) == 1)
1098 reset($factors);
1099 $a = array_keys($factors);
1100 $factor = $a[0];
1101 $leads = $factors[$factor];
1102 if (count($leads) == 1)
1104 $factorized = ($leads[0] != "" ? $leads[0].'.' : "").$factor;
1106 else
1108 $fbloc = joinArray($leads, ",");
1109 $factorized = ($fbloc == "") ? $factor : factorizeBloc('['.$fbloc.']').'.'.$factor;
1112 else
1114 unset($subblocs);
1115 foreach ($factors as $factor => $leads)
1117 //echo "$alev factor $factor, ".count($leads)." leads<br>\n";
1118 if (count($leads) == 1)
1120 $subblocs[] = ($leads[0] != "" ? $leads[0].'.' : "").$factor;
1122 else
1124 $fbloc = joinArray($leads, ",");
1125 $subblocs[] = ($fbloc == "") ? $factor : factorizeBloc('['.$fbloc.']').'.'.$factor;
1128 $factorized = '['.joinArray($subblocs, ",").']';
1131 //echo "$alev factorizeBloc($bloc) = $factorized<br>\n";
1132 --$alev;
1133 return $factorized;
1136 function splitBloc($bloc)
1138 if ($bloc{0} != '[')
1140 $arr[] = $bloc;
1142 else
1144 if ($bloc{strlen($bloc)-1}!=']')
1145 echo "Error on bloc '$bloc', unexpected character after ']'<br>\n";
1147 $i=1;
1148 while ($i<strlen($bloc)-1)
1150 $alt = "";
1151 $level = 0;
1152 while ( $i<strlen($bloc)-1 && ( ($char=$bloc{$i}) != ',' || $level!=0 ) )
1154 if ($char == '[') ++$level;
1155 else if ($char == ']') --$level;
1156 $alt .= $char;
1157 ++$i;
1159 ++$i;
1160 if ($level != 0)
1161 echo "Error on bloc '$bloc', badly formed (missing end bracket?)<br>\n";
1162 $arr[] = $alt;
1165 return $arr;
1168 function joinArray(&$array, $sep)
1170 if (count($array) == 0)
1171 return "";
1172 $first = true;
1173 foreach ($array as $val)
1175 $result .= ($first ? "" : $sep).$val;
1176 $first = false;
1178 return $result;
1181 function getVarName($path)
1183 $arr = explode(".", $path);
1184 return $arr[count($arr)-1];
1187 function isAtom($atom)
1189 for ($i=0; $i<strlen($atom); ++$i)
1190 if ($atom{$i} == '.' || $atom{$i} == '[')
1191 return false;
1192 return true;
1195 // takes a factorized query, and expands it in a list a simple paths
1196 function expandQuery($query)
1198 if (isAtom($query))
1199 return array($query);
1201 //echo "expand query: $query<br>";
1202 $blocs = splitQuery($query);
1203 //echo "splitted query: blocs=";
1204 //print_r($blocs);
1205 //echo "<br>-------------------<br>";
1207 for ($i=0; $i<count($blocs); ++$i)
1209 $subblocs = splitBloc($blocs[$i]);
1210 //echo "splitted blocs: subblocs=";
1211 //print_r($subblocs);
1212 //echo "<br>-------------------<br>";
1214 unset($nodes);
1215 $nodes = array();
1216 for ($ii=0; $ii<count($subblocs); ++$ii)
1218 $nodes = array_merge($nodes, expandQuery($subblocs[$ii]));
1221 if (count($current_nodes) >= 1)
1223 $num_nodes = count($current_nodes);
1224 for ($j=0; $j<$num_nodes; ++$j)
1226 for ($k=0; $k<count($nodes)-1; ++$k)
1227 $current_nodes[] = $current_nodes[$j].".".$nodes[$k];
1228 $current_nodes[$j] .= ".".$nodes[$k];
1231 else
1233 $current_nodes = $nodes;
1236 return $current_nodes;