Code

Added rendering for action menu
[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       if ($entry['scope'] == "auto") {
53         $this->scope= "one";
54       } else {
55         $this->scope= $entry['scope'];
56       }
57       $this->query= $entry['query'];
58     } else {
59       return false;
60     }
62     // Transfer initial value
63     if (isset($this->xmlData['definition']['initial']) && $this->xmlData['definition']['initial'] == "true"){
64       $this->initial= true;
65     }
67     // Transfer category
68     if (isset($this->xmlData['definition']['category'])){
69       $this->category= $this->xmlData['definition']['category'];
70     }
72     // Generate formular data
73     if (isset($this->xmlData['element'])) {
74       if (!isset($this->xmlData['element'][0])){
75         $this->xmlData['element']= array($this->xmlData['element']);
76       }
77       foreach ($this->xmlData['element'] as $element) {
79         // Ignore elements without type
80         if (!isset($element['type']) || !isset($element['tag'])) {
81           next;
82         }
84         $tag= $element['tag'];
86         // Fix arrays
87         if (isset($element['value']) && !isset($element['value'][0])) {
88           $element['value']= array($element['value']);
89         }
91         // Store element for quick access
92         $this->elements[$tag] = $element;
94         // Preset elementValues with default values if exist
95         if (isset($element['default']) && !is_array($element['default'])) {
96           $this->elementValues[$tag] = $element['default'];
97         } else {
98           $this->elementValues[$tag] = "";
99         }
101         // Does this element react on alphabet links?
102         if (isset($element['alphabet']) && $element['alphabet'] == "true") {
103           $this->alphabetElements[]= $tag;
104         }
105       }
106     }
108     return true;  
109   }
112   function getTextfield($element)
113   {
114     $tag= $element['tag'];
115     $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='30' maxlength='30' value='".$this->elementValues[$tag]."'>";
116     if (isset($element['autocomplete'])) {
117       $frequency= "0.5";
118       $characters= "1";
119       if (isset($element['autocomplete']['frequency'])) {
120         $frequency= $element['autocomplete']['frequency'];
121       }
122       if (isset($element['autocomplete']['characters'])) {
123         $characters= $element['autocomplete']['characters'];
124       }
125       $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
126                 "<script type='text/javascript'>".
127                 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
128                 "</script>";
130        $this->autocompleters[$tag]= $element['autocomplete'];
131     }
132     return $result;
133   }
136   function getCheckbox($element)
137   {
138     $tag= $element['tag'];
139     $checked= "";
140     if ($this->elementValues[$tag] == "true") {
141       $checked= " checked";
142     }
144     $result= "<input class='filter_checkbox' name='$tag' type='checkbox' onClick='document.mainform.submit();' value='true'$checked>";
145     return $result;
146   }
149   function getCombobox($element)
150   {
151     $result= "<select name='".$element['tag']."' size='1' onClick='document.mainform.submit();'>";
153     // Fill with presets
154     foreach ($element['value'] as $value) {
155       $selected= "";
156       if ($this->elementValues[$element['tag']] == $value['key']) {
157         $selected= " selected";
158       }
160       // Handle translations
161       $result.= "<option value='".$value['key']."'$selected>"._($value['label'])."</option>";
162     }
164     // Use autocompleter for additional data
165     if (isset($element['autocomplete'])) {
166       $list= $this->getCompletitionList($element['autocomplete'], $element['tag']);
167       foreach ($list as $value) {
168         $selected= "";
169         if ($this->elementValues[$element['tag']] == $value) {
170           $selected= " selected";
171         }
172         $result.= "<option value='$value'$selected>$value</option>";
173       }
174     }
176     $result.= "</select>";
178     return $result;
179   }
182   function getCurrentBase()
183   {
184     if (isset($this->search->base) && (string)$this->search->scope != "auto") {
185       return false;
186     }
188     return $this->base;
189   }
192   function getCurrentScope()
193   {
194     if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
195       return (string)$this->search->scope;
196     }
198     return $this->scope;
199   }
202   function setBases($bases) {
203     $this->bases= $bases;    
204   }
207   function setObjectStorage($storage) {
208     $this->objectStorage= $storage;    
209   }
212   function setObjectBase($base) {
213     $this->objectBase= $base;    
214   }
217   function setCurrentBase($base) {
218     $this->base= $base;
219   }
222   function setCurrentScope($scope) {
223     $this->scope= $scope;
224   }
227   function renderBase()
228   {
229     $result= "<select name='base' onChange='mainform.submit()' size='1'>";
231     foreach ($this->bases as $key=>$value) {
232       $selected= "";
233       if ($key == $this->base) {
234         $selected= " selected";
235       }
236       $result.= "<option value='".$key."'$selected>".$value."</option>";
237     }
238     $result.= "</select>";
240     return $result;
241   }
244   function renderAlphabet($columns= 10)
245   {
246     // Return pre-rendered alphabet if available
247     if ($this->alphabet) {
248       return ($this->alphabet);
249     }
251     $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
252     $alphabet= "";
253     $c= 0;
255     /* Fill cells with charaters */
256     for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
257       if ($c == 0){
258         $alphabet.= "<tr>";
259       }
261       $ch = mb_substr($characters, $i, 1, "UTF8");
262       $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
263         validate($_GET['plug'])."&amp;filter=".$ch."\">&nbsp;".$ch."&nbsp;</a></td>";
265       if ($c++ == $columns){
266         $alphabet.= "</tr>";
267         $c= 0;
268       }
269     }
271     /* Fill remaining cells */
272     while ($c++ <= $columns){
273       $alphabet.= "<td>&nbsp;</td>";
274     }
276     /* Save alphabet */
277     $this->alphabet= "<table width='100%'>$alphabet</table>";
279     return ($this->alphabet);
280   }
283   function renderApply()
284   {
285     return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
286   }
289   function renderScope()
290   {
291     $checked= $this->scope == "sub"?" checked":"";
292     return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked>&nbsp;"._("Search in subtrees");
293   }
296   function render()
297   {
298     $smarty= get_smarty();
299     $smarty->assign("ALPHABET", $this->renderAlphabet());
300     $smarty->assign("APPLY", $this->renderApply());
301     $smarty->assign("SCOPE", $this->renderScope());
302     $smarty->assign("BASE", $this->renderBase());
304     // Load template and replace elementsHtml[]
305     foreach ($this->elements as $tag => $element) {
306       $htmlCode= "";
307       switch ($element['type']) {
308         case "textfield":
309           $htmlCode = $this->getTextfield($element);
310           break;
312         case "checkbox":
313           $htmlCode = $this->getCheckbox($element);
314           break;
316         case "combobox":
317           $htmlCode = $this->getCombobox($element);
318           break;
320         default:
321           die ("Unknown element type specified!");
322       }
323       $smarty->assign("$tag", $htmlCode);
324     }
326     // Load template
327     return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path($this->xmlData['definition']['template'], true)));
328   }
331   function query()
332   {
333     global $class_mapping;
334     $result= array();
336     // Go thru all queries and merge results
337     foreach ($this->query as $query) {
338       if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
339         die("No backend specified in search config.");
340       }
342       // Is backend available?
343       $backend= "filter".$query['backend'];
344       if (!isset($class_mapping["$backend"])) {
345         die("Invalid backend specified in search config.");
346       }
348       // Load filter and attributes
349       $filter= $query['filter'];
350       $attributes= $query['attribute'];
352       // Generate final filter
353       foreach ($this->elements as $tag => $element) {
354         if (!isset($element['set']) || !isset($element['unset'])) {
355           continue;
356         }
357         $e_set= is_array($element['set'])?"":$element['set'];
358         $e_unset= is_array($element['unset'])?"":$element['unset'];
360         if ($this->elementValues[$tag] == "") {
361           $e_unset= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_unset);
362           $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
363         } else {
364           $e_set= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_set);
365           $filter= preg_replace("/\\$$tag/", $e_set, $filter);
366         }
367       }
369       $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
370                                $this->category, $this->objectStorage, $this->objectBase));
371     }
372     
374     return ($result);
375   }
378   function isValid()
379   {
380     foreach ($this->elements as $tag => $element) {
381       if (isset($element->regex)){
382         if (!preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])){
383           return false;
384         }
385       }
386     }
387     return true;
388   }
391   function update()
392   {
394     /* React on alphabet links if needed */
395     if (isset($_GET['filter'])){
396       $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
397       if ($s == "**"){
398         $s= "*";
399       }
400       foreach ($this->alphabetElements as $tag) {
401         $this->elementValues[$tag]= $s;
402       }
403     }
405     if (isset($_POST['FILTER_LOADED'])) {
406       // Load post values and adapt filter, base and scope accordingly - but
407       // only if we didn't get a _GET
408       foreach ($this->elements as $tag => $element) {
409         if (isset($_POST[$tag])){
410           $this->elementValues[$tag]= validate($_POST[$tag]);
411         } else {
412           $this->elementValues[$tag]= "";
413         }
414       }
415     }
417     // Save base
418     if (isset($_POST['BASE']) && $this->baseMode == "true") {
419       $base= validate($_POST['BASE']);
420       if (isset($this->bases[$base])) {
421         $this->base= $base;
422       }
423     }
425     // Save scope if needed
426     if ($this->scopeMode == "auto") {
427       $this->scope= isset($_POST['SCOPE'])?"sub":"one";
428     }
429   }
432   function getCompletitionList($config, $tag, $value="*")
433   {
434     global $class_mapping;
435     $res= array();
437     // Is backend available?
438     $backend= "filter".$config['backend'];
439     if (!isset($class_mapping["$backend"])) {
440       die("Invalid backend specified in search config.");
441     }
443     // Load filter and attributes
444     $filter= $config['filter'];
445     $attributes= $config['attribute'];
446     if (!is_array($attributes)) {
447       $attributes= array($attributes);
448     }
450     // Make filter
451     $filter= preg_replace("/\\$$tag/", normalizeLDAP($value), $filter);
452     if (isset($config['base']) && isset($config['scope'])
453         && isset($config['category']) && isset($config['objectbase']) ) {
454       $result= call_user_func(array($backend, 'query'), $config['base'], $config['scope'], $filter, $attributes,
455                            $config["category"], $config["objectbase"]);
456     } else {
457       $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
458                            $this->category, $this->objectStorage, $this->objectBase);
459     }
461     foreach ($result as $entry) {
462       foreach ($attributes as $attribute) {
463         if (is_array($entry[$attribute])) {
464           for ($i= 0; $i<$entry[$attribute]['count']; $i++) {
465             $res[]= $entry[$attribute][$i];
466           }
467         } else {
468           $res[]= $entry[$attribute];
469         }
470       }
471     }
473     return $res;
474   }
477   function processAutocomplete()
478   {
479     global $class_mapping;
480     $result= array();
482     foreach ($this->autocompleters as $tag => $config) {
483       if(isset($_POST[$tag])){
484         $result= $this->getCompletitionList($config, $tag, $_POST[$tag]);
486         echo '<ul>';
487         foreach ($result as $entry) {
488           echo '<li>'.$entry.'</li>';
489         }
491         echo '</ul>';
492       }
494     }
495   }
499 ?>