Code

9d4d9384e81ada3a402ad0fa91573df6a4e5cfa4
[gosa.git] / gosa-core / include / class_filter.inc
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 $initial= false;
18   var $baseMode= false;
19   var $scopeMode= "auto";
20   var $alphabet= null;
23   function filter($filename)
24   {
25     if (!$this->load($filename)) {
26       die("Cannot parse $filename!");
27     }
28   }
31   function load($filename)
32   {
33     $contents = file_get_contents($filename);
34     $this->xmlData= xml::xml2array($contents, 1);
36     if (!isset($this->xmlData['filter'])) {
37       return false;
38     }
40     $this->xmlData= $this->xmlData["filter"];
42     // Load filter
43     if (isset($this->xmlData['search'])) {
44       if (!isset($this->xmlData['search']['query'][0])){
45         $this->xmlData['search']['query']= array($this->xmlData['search']['query']);
46       }
48       // Move information
49       $entry= $this->xmlData['search'];
50       $this->baseMode= $entry['base'];
51       $this->scopeMode= $entry['scope'];
52       $this->query= $entry['query'];
53     } else {
54       return false;
55     }
57     // Transfer initial value
58     if (isset($this->xmlData['definition']['initial']) && $this->xmlData['definition']['initial'] == "true"){
59       $this->initial= true;
60     }
62     // Transfer category
63     if (isset($this->xmlData['definition']['category'])){
64       $this->category= $this->xmlData['definition']['category'];
65     }
67     // Generate formular data
68     if (isset($this->xmlData['element'])) {
69       if (!isset($this->xmlData['element'][0])){
70         $this->xmlData['element']= array($this->xmlData['element']);
71       }
72       foreach ($this->xmlData['element'] as $element) {
74         // Ignore elements without type
75         if (!isset($element['type']) || !isset($element['tag'])) {
76           next;
77         }
79         $tag= $element['tag'];
81         // Fix arrays
82         if (isset($element['value']) && !isset($element['value'][0])) {
83           $element['value']= array($element['value']);
84         }
86         // Store element for quick access
87         $this->elements[$tag] = $element;
89         // Preset elementValues with default values if exist
90         if (isset($element['default']) && !is_array($element['default'])) {
91           $this->elementValues[$tag] = $element['default'];
92         } else {
93           $this->elementValues[$tag] = "";
94         }
96         // Does this element react on alphabet links?
97         if (isset($element['alphabet']) && $element['alphabet'] == "true") {
98           $this->alphabetElements[]= $tag;
99         }
100       }
101     }
103     return true;  
104   }
107   function getTextfield($element)
108   {
109     $tag= $element['tag'];
110     $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='30' maxlength='30' value='".$this->elementValues[$tag]."'>";
111     if (isset($element['autocomplete'])) {
112       $frequency= "0.5";
113       $characters= "1";
114       if (isset($element['autocomplete']['frequency'])) {
115         $frequency= $element['autocomplete']['frequency'];
116       }
117       if (isset($element['autocomplete']['characters'])) {
118         $characters= $element['autocomplete']['characters'];
119       }
120       $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
121                 "<script type='text/javascript'>".
122                 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
123                 "</script>";
125        $this->autocompleters[$tag]= $element['autocomplete'];
126     }
127     return $result;
128   }
131   function getCheckbox($element)
132   {
133     $tag= $element['tag'];
134     $checked= "";
135     if ($this->elementValues[$tag] == "true") {
136       $checked= " checked";
137     }
139     $result= "<input class='filter_checkbox' name='$tag' type='checkbox' onClick='document.mainform.submit();' value='true'$checked>";
140     return $result;
141   }
144   function getCombobox($element)
145   {
146     $result= "<select name='".$element['tag']."' size='1' onClick='document.mainform.submit();'>";
148     // Fill with presets
149     foreach ($element['value'] as $value) {
150       $selected= "";
151       if ($this->elementValues[$element['tag']] == $value['key']) {
152         $selected= " selected";
153       }
155       // Handle translations
156       if (is_array($value['set'])) {
157         $result.= "<option value='".$value['key']."'$selected>".xml::getLocalizedAttribute($value['set'], $GLOBALS['t_language'])."</option>";
158       } else {
159         $result.= "<option value='".$value['key']."'$selected>".$value['set']."</option>";
160       }
161     }
163     // Use autocompleter for additional data
164     if (isset($element['autocomplete'])) {
165       $list= $this->getCompletitionList($element['autocomplete'], $element['tag']);
166       foreach ($list as $value) {
167         $selected= "";
168         if ($this->elementValues[$element['tag']] == $value) {
169           $selected= " selected";
170         }
171         $result.= "<option value='$value'$selected>$value</option>";
172       }
173     }
175     $result.= "</select>";
177     return $result;
178   }
181   function getCurrentBase()
182   {
183     if (isset($this->search->base) && (string)$this->search->scope != "auto") {
184       return false;
185     }
187     return $this->base;
188   }
191   function getCurrentScope()
192   {
193     if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
194       return (string)$this->search->scope;
195     }
197     return $this->scope;
198   }
201   function setBases($bases) {
202     $this->bases= $bases;    
203   }
206   function setObjectStorage($storage) {
207     $this->objectStorage= $storage;    
208   }
211   function setObjectBase($base) {
212     $this->objectBase= $base;    
213   }
216   function setCurrentBase($base) {
217     $this->base= $base;
218   }
221   function setCurrentScope($scope) {
222     $this->scope= $scope;
223   }
226   function renderBase()
227   {
228     $result= "<select name='currentMainBase' onChange='mainform.submit()' size='1'>";
230     foreach ($this->bases as $key=>$value) {
231       $selected= "";
232       if ($key == $this->base) {
233         $selected= " selected";
234       }
235       $result.= "<option value='".$key."'$selected>".$value."</option>";
236     }
237     $result.= "</select>";
239     return $result;
240   }
243   function renderAlphabet($columns= 10)
244   {
245     // Return pre-rendered alphabet if available
246     if ($this->alphabet) {
247       return ($this->alphabet);
248     }
250     $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
251     $alphabet= "";
252     $c= 0;
254     /* Fill cells with charaters */
255     for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
256       if ($c == 0){
257         $alphabet.= "<tr>";
258       }
260       $ch = mb_substr($characters, $i, 1, "UTF8");
261       $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
262         validate($_GET['plug'])."&amp;filter=".$ch."\">&nbsp;".$ch."&nbsp;</a></td>";
264       if ($c++ == $columns){
265         $alphabet.= "</tr>";
266         $c= 0;
267       }
268     }
270     /* Fill remaining cells */
271     while ($c++ <= $columns){
272       $alphabet.= "<td>&nbsp;</td>";
273     }
275     /* Save alphabet */
276     $this->alphabet= "<table width='100%'>$alphabet</table>";
278     return ($this->alphabet);
279   }
282   function renderApply()
283   {
284     return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
285   }
288   function renderScope()
289   {
290     $checked= $this->scope == "sub"?" checked":"";
291     return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked>&nbsp;"._("Search in subtrees");
292   }
295   function render()
296   {
297     $smarty= get_smarty();
298     $smarty->assign("ALPHABET", $this->renderAlphabet());
299     $smarty->assign("APPLY", $this->renderApply());
300     $smarty->assign("SCOPE", $this->renderScope());
301     $smarty->assign("BASE", $this->renderBase());
303     // Load template and replace elementsHtml[]
304     foreach ($this->elements as $tag => $element) {
305       $htmlCode= "";
306       switch ($element['type']) {
307         case "textfield":
308           $htmlCode = $this->getTextfield($element);
309           break;
311         case "checkbox":
312           $htmlCode = $this->getCheckbox($element);
313           break;
315         case "combobox":
316           $htmlCode = $this->getCombobox($element);
317           break;
319         default:
320           die ("Unknown element type specified!");
321       }
322       $smarty->assign("$tag", $htmlCode);
323     }
325     // Load template
326     return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path($this->xmlData['definition']['template'], true)));
327   }
330   function query()
331   {
332     global $class_mapping;
333     $result= array();
335     // Go thru all queries and merge results
336     foreach ($this->query as $query) {
337       if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
338         die("No backend specified in search config.");
339       }
341       // Is backend available?
342       $backend= "filter".$query['backend'];
343       if (!isset($class_mapping["$backend"])) {
344         die("Invalid backend specified in search config.");
345       }
347       // Load filter and attributes
348       $filter= $query['filter'];
349       $attributes= $query['attribute'];
351       // Generate final filter
352       foreach ($this->elements as $tag => $element) {
353         if (!isset($element['set']) || !isset($element['unset'])) {
354           continue;
355         }
356         $e_set= is_array($element['set'])?"":$element['set'];
357         $e_unset= is_array($element['unset'])?"":$element['unset'];
359         if ($this->elementValues[$tag] == "") {
360           $e_unset= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_unset);
361           $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
362         } else {
363           $e_set= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_set);
364           $filter= preg_replace("/\\$$tag/", $e_set, $filter);
365         }
366       }
368       $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
369                                $this->category, $this->objectStorage, $this->objectBase));
370     }
371     
373     return ($result);
374   }
377   function isValid()
378   {
379     foreach ($this->elements as $tag => $element) {
380       if (isset($element->regex)){
381         if (!preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])){
382           return false;
383         }
384       }
385     }
386     return true;
387   }
390   function update()
391   {
393     /* React on alphabet links if needed */
394     if (isset($_GET['filter'])){
395       $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
396       if ($s == "**"){
397         $s= "*";
398       }
399       foreach ($this->alphabetElements as $tag) {
400         $this->elementValues[$tag]= $s;
401       }
402     }
404     if (isset($_POST['FILTER_LOADED'])) {
405       // Load post values and adapt filter, base and scope accordingly - but
406       // only if we didn't get a _GET
407       foreach ($this->elements as $tag => $element) {
408         if (isset($_POST[$tag])){
409           $this->elementValues[$tag]= validate($_POST[$tag]);
410         } else {
411           $this->elementValues[$tag]= "";
412         }
413       }
414     }
416     // Save base
417     if (isset($_POST['BASE']) && $this->baseMode == "true") {
418       $base= validate($_POST['BASE']);
419       if (isset($this->bases[$base])) {
420         $this->base= $base;
421       }
422     }
424     // Save scope if needed
425     if ($this->scopeMode == "auto") {
426       $this->scope= isset($_POST['SCOPE'])?"sub":"one";
427     }
428   }
431   function getCompletitionList($config, $tag, $value="*")
432   {
433     global $class_mapping;
434     $res= array();
436     // Is backend available?
437     $backend= "filter".$config['backend'];
438     if (!isset($class_mapping["$backend"])) {
439       die("Invalid backend specified in search config.");
440     }
442     // Load filter and attributes
443     $filter= $config['filter'];
444     $attributes= $config['attribute'];
445     if (!is_array($attributes)) {
446       $attributes= array($attributes);
447     }
449     // Make filter
450     $filter= preg_replace("/\\$$tag/", normalizeLDAP($value), $filter);
451     if (isset($config['base']) && isset($config['scope'])
452         && isset($config['category']) && isset($config['objectbase']) ) {
453       $result= call_user_func(array($backend, 'query'), $config['base'], $config['scope'], $filter, $attributes,
454                            $config["category"], $config["objectbase"]);
455     } else {
456       $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
457                            $this->category, $this->objectStorage, $this->objectBase);
458     }
460     foreach ($result as $entry) {
461       foreach ($attributes as $attribute) {
462         if (is_array($entry[$attribute])) {
463           for ($i= 0; $i<$entry[$attribute]['count']; $i++) {
464             $res[]= $entry[$attribute][$i];
465           }
466         } else {
467           $res[]= $entry[$attribute];
468         }
469       }
470     }
472     return $res;
473   }
476   function processAutocomplete()
477   {
478     global $class_mapping;
479     $result= array();
481     foreach ($this->autocompleters as $tag => $config) {
482       if(isset($_POST[$tag])){
483         $result= $this->getCompletitionList($config, $tag, $_POST[$tag]);
485         echo '<ul>';
486         foreach ($result as $entry) {
487           echo '<li>'.$entry.'</li>';
488         }
490         echo '</ul>';
491       }
493     }
494   }
498 ?>