Code

ffb8789553a8db5238af8e7923345e4e586870f8
[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 $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'])."&amp;filter=".$ch."\">&nbsp;".$ch."&nbsp;</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>&nbsp;</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>&nbsp;"._("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     }
344     
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])){
411       
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   }
451 ?>