ffb8789553a8db5238af8e7923345e4e586870f8
1 <?php
3 class filter {
5 var $xmlData;
6 var $elements= array();
7 var $elementValues= array();
8 var $alphabetElements= array();
9 var $autocompleter= array();
10 var $category= "";
11 var $objectStorage= array();
12 var $objectBase= "";
13 var $base= "";
14 var $bases= array();
15 var $scope= "";
16 var $query;
17 var $baseMode= false;
18 var $scopeMode= "auto";
19 var $alphabet= null;
22 function filter($filename)
23 {
24 if (!$this->load($filename)) {
25 die("Cannot parse $filename!");
26 }
27 }
30 function load($filename)
31 {
32 $contents = file_get_contents($filename);
33 $this->xmlData= xml::xml2array($contents, 1);
35 if (!isset($this->xmlData['filter'])) {
36 return false;
37 }
39 $this->xmlData= $this->xmlData["filter"];
41 // Load filter
42 if (isset($this->xmlData['search'])) {
43 if (!isset($this->xmlData['search']['query'][0])){
44 $this->xmlData['search']['query']= array($this->xmlData['search']['query']);
45 }
47 // Move information
48 $entry= $this->xmlData['search'];
49 $this->baseMode= $entry['base'];
50 $this->scopeMode= $entry['scope'];
51 $this->query= $entry['query'];
52 } else {
53 return false;
54 }
56 // Generate formular data
57 if (isset($this->xmlData['element'])) {
58 if (!isset($this->xmlData['element'][0])){
59 $this->xmlData['element']= array($this->xmlData['element']);
60 }
61 foreach ($this->xmlData['element'] as $element) {
63 // Ignore elements without type
64 if (!isset($element['type']) || !isset($element['tag'])) {
65 next;
66 }
68 $tag= $element['tag'];
70 // Fix arrays
71 if (isset($element['value']) && !isset($element['value'][0])) {
72 $element['value']= array($element['value']);
73 }
75 // Store element for quick access
76 $this->elements[$tag] = $element;
78 // Preset elementValues with default values if exist
79 if (isset($element['default']) && !is_array($element['default'])) {
80 $this->elementValues[$tag] = $element['default'];
81 } else {
82 $this->elementValues[$tag] = "";
83 }
85 // Does this element react on alphabet links?
86 if (isset($element['alphabet']) && $element['alphabet'] == "true") {
87 $this->alphabetElements[]= $tag;
88 }
89 }
90 }
92 return true;
93 }
96 function getTextfield($element)
97 {
98 $tag= $element['tag'];
99 $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='30' maxlength='30' value='".$this->elementValues[$tag]."'>";
100 if (isset($element['autocomplete'])) {
101 $frequency= "0.5";
102 $characters= "1";
103 if (isset($element['autocomplete']['frequency'])) {
104 $frequency= $element['autocomplete']['frequency'];
105 }
106 if (isset($element['autocomplete']['characters'])) {
107 $characters= $element['autocomplete']['characters'];
108 }
109 $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
110 "<script type='text/javascript'>".
111 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
112 "</script>";
114 $this->autocompleters[$tag]= $element['autocomplete'];
115 }
116 return $result;
117 }
120 function getCheckbox($element)
121 {
122 $tag= $element['tag'];
123 $checked= "";
124 if ($this->elementValues[$tag] == "true") {
125 $checked= " checked";
126 }
128 $result= "<input class='filter_checkbox' name='$tag' type='checkbox' onClick='document.mainform.submit();' value='true'$checked>";
129 return $result;
130 }
133 function getCombobox($element)
134 {
135 $result= "<select name='".$element['tag']."' size='1' onClick='document.mainform.submit();'>";
136 foreach ($element['value'] as $value) {
137 $selected= "";
138 if ($this->elementValues[$element['tag']] == $value['key']) {
139 $selected= " selected";
140 }
141 $result.= "<option value='".$value['key']."'$selected>{t}".$value['set']."{/t}</option>";
142 }
143 $result.= "</select>";
145 return $result;
146 }
149 function getCurrentBase()
150 {
151 if (isset($this->search->base) && (string)$this->search->scope != "auto") {
152 return false;
153 }
155 return $this->base;
156 }
159 function getCurrentScope()
160 {
161 if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
162 return (string)$this->search->scope;
163 }
165 return $this->scope;
166 }
169 function setBases($bases) {
170 $this->bases= $bases;
171 }
174 function setObjectStorage($storage) {
175 $this->objectStorage= $storage;
176 }
179 function setObjectBase($base) {
180 $this->objectBase= $base;
181 }
184 function setCategory($category) {
185 $this->category= $category;
186 }
189 function setCurrentBase($base) {
190 $this->base= $base;
191 }
194 function setCurrentScope($scope) {
195 $this->scope= $scope;
196 }
199 function renderBase()
200 {
201 $result= "<select name='currentMainBase' onChange='mainform.submit()' size='1'>";
203 foreach ($this->bases as $key=>$value) {
204 $selected= "";
205 if ($key == $this->base) {
206 $selected= " selected";
207 }
208 $result.= "<option value='".$key."'$selected>".$value."</option>";
209 }
210 $result.= "</select>";
212 return $result;
213 }
216 function renderAlphabet($columns= 10)
217 {
218 // Return pre-rendered alphabet if available
219 if ($this->alphabet) {
220 return ($this->alphabet);
221 }
223 $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
224 $alphabet= "";
225 $c= 0;
227 /* Fill cells with charaters */
228 for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
229 if ($c == 0){
230 $alphabet.= "<tr>";
231 }
233 $ch = mb_substr($characters, $i, 1, "UTF8");
234 $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
235 validate($_GET['plug'])."&filter=".$ch."\"> ".$ch." </a></td>";
237 if ($c++ == $columns){
238 $alphabet.= "</tr>";
239 $c= 0;
240 }
241 }
243 /* Fill remaining cells */
244 while ($c++ <= $columns){
245 $alphabet.= "<td> </td>";
246 }
248 /* Save alphabet */
249 $this->alphabet= "<table width='100%'>$alphabet</table>";
251 return ($this->alphabet);
252 }
255 function renderApply()
256 {
257 return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
258 }
261 function renderScope()
262 {
263 $checked= $this->scope == "sub"?" checked":"";
264 return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked> "._("Search in subtrees");
265 }
268 function renderFilter()
269 {
270 $smarty= get_smarty();
271 $smarty->assign("ALPHABET", $this->renderAlphabet());
272 $smarty->assign("APPLY", $this->renderApply());
273 $smarty->assign("SCOPE", $this->renderScope());
274 $smarty->assign("BASE", $this->renderBase());
276 // Load template and replace elementsHtml[]
277 foreach ($this->elements as $tag => $element) {
278 $htmlCode= "";
279 switch ($element['type']) {
280 case "textfield":
281 $htmlCode = $this->getTextfield($element);
282 break;
284 case "checkbox":
285 $htmlCode = $this->getCheckbox($element);
286 break;
288 case "combobox":
289 $htmlCode = $this->getCombobox($element);
290 break;
292 default:
293 die ("Unknown element type specified!");
294 }
295 $smarty->assign("$tag", $htmlCode);
296 }
298 // Load template
299 return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path("filter/".$this->xmlData['definition']['template'])));
300 }
303 function query()
304 {
305 global $class_mapping;
306 $result= array();
308 // Go thru all queries and merge results
309 foreach ($this->query as $query) {
310 if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
311 die("No backend specified in search config.");
312 }
314 // Is backend available?
315 $backend= "filter".$query['backend'];
316 if (!isset($class_mapping["$backend"])) {
317 die("Invalid backend specified in search config.");
318 }
320 // Load filter and attributes
321 $filter= $query['filter'];
322 $attributes= $query['attribute'];
324 // Generate final filter
325 foreach ($this->elements as $tag => $element) {
326 if (!isset($element['set']) || !isset($element['unset'])) {
327 next;
328 }
329 $e_set= is_array($element['set'])?"":$element['set'];
330 $e_unset= is_array($element['unset'])?"":$element['unset'];
332 if ($this->elementValues[$tag] == "") {
333 $e_unset= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_unset);
334 $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
335 } else {
336 $e_set= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_set);
337 $filter= preg_replace("/\\$$tag/", $e_set, $filter);
338 }
339 }
341 $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
342 $this->category, $this->objectStorage, $this->objectBase));
343 }
346 return ($result);
347 }
350 function isValid()
351 {
352 foreach ($this->elements as $tag => $element) {
353 if (isset($element->regex)){
354 if (!preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])){
355 return false;
356 }
357 }
358 }
359 return true;
360 }
363 function update()
364 {
366 /* React on alphabet links if needed */
367 if (isset($_GET['filter'])){
368 $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
369 if ($s == "**"){
370 $s= "*";
371 }
372 foreach ($this->alphabetElements as $tag) {
373 $this->elementValues[$tag]= $s;
374 }
375 }
377 if (isset($_POST['FILTER_LOADED'])) {
378 // Load post values and adapt filter, base and scope accordingly - but
379 // only if we didn't get a _GET
380 foreach ($this->elements as $tag => $element) {
381 if (isset($_POST[$tag])){
382 $this->elementValues[$tag]= validate($_POST[$tag]);
383 } else {
384 $this->elementValues[$tag]= "";
385 }
386 }
387 }
389 // Save base
390 if (isset($_POST['BASE']) && $this->baseMode == "true") {
391 $base= validate($_POST['BASE']);
392 if (isset($this->bases[$base])) {
393 $this->base= $base;
394 }
395 }
397 // Save scope if needed
398 if ($this->scopeMode == "auto") {
399 $this->scope= isset($_POST['SCOPE'])?"sub":"one";
400 }
401 }
404 function processAutocomplete()
405 {
406 global $class_mapping;
407 $result= array();
409 foreach ($this->autocompleters as $tag => $config) {
410 if(isset($_POST[$tag])){
412 // Is backend available?
413 $backend= "filter".$config['backend'];
414 if (!isset($class_mapping["$backend"])) {
415 die("Invalid backend specified in search config.");
416 }
418 // Load filter and attributes
419 $filter= $config['filter'];
420 $attributes= $config['attribute'];
421 if (!is_array($attributes)) {
422 $attributes= array($attributes);
423 }
425 // Make filter
426 $filter= preg_replace("/\\$$tag/", normalizeLDAP($_POST[$tag]), $filter);
427 $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
428 $this->category, $this->objectStorage, $this->objectBase);
430 echo '<ul>';
431 foreach ($result as $entry) {
432 foreach ($attributes as $attribute) {
433 if (is_array($entry[$attribute])) {
434 for ($i= 0; $i<$entry[$attribute]['count']; $i++) {
435 echo '<li>'.$entry[$attribute][$i].'</li>';
436 }
437 } else {
438 echo '<li>'.$entry[$entry][$attribute].'</li>';
439 }
440 }
441 }
443 echo '</ul>';
444 }
446 }
447 }
449 }
451 ?>