607b95a69489d0154c8a1da08a22ba9e06b85d32
1 <?php
3 class filter {
5 var $xmlData;
6 var $elements= array();
7 var $elementValues= array();
8 var $alphabetElements= array();
9 var $category= "";
10 var $objectStorage= array();
11 var $objectBase= "";
12 var $base= "";
13 var $bases= array();
14 var $scope= "";
15 var $query;
16 var $baseMode= false;
17 var $scopeMode= "auto";
18 var $alphabet= null;
21 function filter($filename)
22 {
23 if (!$this->load($filename)) {
24 die("Cannot parse $filename!");
25 }
26 }
29 function load($filename)
30 {
31 $contents = file_get_contents($filename);
32 $this->xmlData= xml::xml2array($contents, 1);
34 if (!isset($this->xmlData['filter'])) {
35 return false;
36 }
38 $this->xmlData= $this->xmlData["filter"];
40 // Load filter
41 if (isset($this->xmlData['search'])) {
42 if (!isset($this->xmlData['search']['query'][0])){
43 $this->xmlData['search']['query']= array($this->xmlData['search']['query']);
44 }
46 // Move information
47 $entry= $this->xmlData['search'];
48 $this->baseMode= $entry['base'];
49 $this->scopeMode= $entry['scope'];
50 $this->query= $entry['query'];
51 } else {
52 return false;
53 }
55 // Generate formular data
56 if (isset($this->xmlData['element'])) {
57 if (!isset($this->xmlData['element'][0])){
58 $this->xmlData['element']= array($this->xmlData['element']);
59 }
60 foreach ($this->xmlData['element'] as $element) {
62 // Ignore elements without type
63 if (!isset($element['type']) || !isset($element['tag'])) {
64 next;
65 }
67 $tag= $element['tag'];
69 // Fix arrays
70 if (isset($element['value']) && !isset($element['value'][0])) {
71 $element['value']= array($element['value']);
72 }
74 // Store element for quick access
75 $this->elements[$tag] = $element;
77 // Preset elementValues with default values if exist
78 if (isset($element['default']) && !is_array($element['default'])) {
79 $this->elementValues[$tag] = $element['default'];
80 } else {
81 $this->elementValues[$tag] = "";
82 }
84 // Does this element react on alphabet links?
85 if (isset($element['alphabet']) && $element['alphabet'] == "true") {
86 $this->alphabetElements[]= $tag;
87 }
88 }
89 }
91 return true;
92 }
95 function getTextfield($element)
96 {
97 $tag= $element['tag'];
98 $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='30' maxlength='30' value='".$this->elementValues[$tag]."'>";
99 if (isset($element['autocomplete'])) {
100 $frequency= "0.5";
101 $characters= "1";
102 if (isset($element['autocomplete']['frequency'])) {
103 $frequency= $element['autocomplete']['frequency'];
104 }
105 if (isset($element['autocomplete']['characters'])) {
106 $characters= $element['autocomplete']['characters'];
107 }
108 $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
109 "<script type='text/javascript'>".
110 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
111 "</script>";
112 }
113 return $result;
114 }
117 function getCheckbox($element)
118 {
119 $tag= $element['tag'];
120 $checked= "";
121 if ($this->elementValues[$tag] == "true") {
122 $checked= " checked";
123 }
125 $result= "<input class='filter_checkbox' name='$tag' type='checkbox' onClick='document.mainform.submit();' value='true'$checked>";
126 return $result;
127 }
130 function getCombobox($element)
131 {
132 $result= "<select name='".$element['tag']."' size='1' onClick='document.mainform.submit();'>";
133 foreach ($element['value'] as $value) {
134 $selected= "";
135 if ($this->elementValues[$element['tag']] == $value['key']) {
136 $selected= " selected";
137 }
138 $result.= "<option value='".$value['key']."'$selected>{t}".$value['set']."{/t}</option>";
139 }
140 $result.= "</select>";
142 return $result;
143 }
146 function getCurrentBase()
147 {
148 if (isset($this->search->base) && (string)$this->search->scope != "auto") {
149 return false;
150 }
152 return $this->base;
153 }
156 function getCurrentScope()
157 {
158 if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
159 return (string)$this->search->scope;
160 }
162 return $this->scope;
163 }
166 function setBases($bases) {
167 $this->bases= $bases;
168 }
171 function setObjectStorage($storage) {
172 $this->objectStorage= $storage;
173 }
176 function setObjectBase($base) {
177 $this->objectBase= $base;
178 }
181 function setCategory($category) {
182 $this->category= $category;
183 }
186 function setCurrentBase($base) {
187 $this->base= $base;
188 }
191 function setCurrentScope($scope) {
192 $this->scope= $scope;
193 }
196 function renderBase()
197 {
198 $result= "<select name='currentMainBase' onChange='mainform.submit()' size='1'>";
200 foreach ($this->bases as $key=>$value) {
201 $selected= "";
202 if ($key == $this->base) {
203 $selected= " selected";
204 }
205 $result.= "<option value='".$key."'$selected>".$value."</option>";
206 }
207 $result.= "</select>";
209 return $result;
210 }
213 function renderAlphabet($columns= 10)
214 {
215 // Return pre-rendered alphabet if available
216 if ($this->alphabet) {
217 return ($this->alphabet);
218 }
220 $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
221 $alphabet= "";
222 $c= 0;
224 /* Fill cells with charaters */
225 for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
226 if ($c == 0){
227 $alphabet.= "<tr>";
228 }
230 $ch = mb_substr($characters, $i, 1, "UTF8");
231 $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
232 validate($_GET['plug'])."&filter=".$ch."\"> ".$ch." </a></td>";
234 if ($c++ == $columns){
235 $alphabet.= "</tr>";
236 $c= 0;
237 }
238 }
240 /* Fill remaining cells */
241 while ($c++ <= $columns){
242 $alphabet.= "<td> </td>";
243 }
245 /* Save alphabet */
246 $this->alphabet= "<table width='100%'>$alphabet</table>";
248 return ($this->alphabet);
249 }
252 function renderApply()
253 {
254 return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
255 }
258 function renderScope()
259 {
260 $checked= $this->scope == "sub"?" checked":"";
261 return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked> "._("Search in subtrees");
262 }
265 function renderFilter()
266 {
267 $smarty= get_smarty();
268 $smarty->assign("ALPHABET", $this->renderAlphabet());
269 $smarty->assign("APPLY", $this->renderApply());
270 $smarty->assign("SCOPE", $this->renderScope());
271 $smarty->assign("BASE", $this->renderBase());
273 // Load template and replace elementsHtml[]
274 foreach ($this->elements as $tag => $element) {
275 $htmlCode= "";
276 switch ($element['type']) {
277 case "textfield":
278 $htmlCode = $this->getTextfield($element);
279 break;
281 case "checkbox":
282 $htmlCode = $this->getCheckbox($element);
283 break;
285 case "combobox":
286 $htmlCode = $this->getCombobox($element);
287 break;
289 default:
290 die ("Unknown element type specified!");
291 }
292 $smarty->assign("$tag", $htmlCode);
293 }
295 // Load template
296 return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path("filter/".$this->xmlData['definition']['template'])));
297 }
300 function query()
301 {
302 global $class_mapping;
303 $result= array();
305 // Go thru all queries and merge results
306 foreach ($this->query as $query) {
307 if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
308 die("No backend specified in search config.");
309 }
311 // Is backend available?
312 $backend= "filter".$query['backend'];
313 if (!isset($class_mapping["$backend"])) {
314 die("Invalid backend specified in search config.");
315 }
317 // Load filter and attributes
318 $filter= $query['filter'];
319 $attributes= $query['attribute'];
321 // Generate final filter
322 foreach ($this->elements as $tag => $element) {
323 if (!isset($element['set']) || !isset($element['unset'])) {
324 next;
325 }
326 $e_set= is_array($element['set'])?"":$element['set'];
327 $e_unset= is_array($element['unset'])?"":$element['unset'];
329 if ($this->elementValues[$tag] == "") {
330 $e_unset= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_unset);
331 $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
332 } else {
333 $e_set= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_set);
334 $filter= preg_replace("/\\$$tag/", $e_set, $filter);
335 }
336 }
338 $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
339 $this->category, $this->objectStorage, $this->objectBase));
340 }
343 return ($result);
344 }
347 function isValid()
348 {
349 foreach ($this->elements as $tag => $element) {
350 if (isset($element->regex)){
351 if (!preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])){
352 return false;
353 }
354 }
355 }
356 return true;
357 }
360 function update()
361 {
363 /* React on alphabet links if needed */
364 if (isset($_GET['filter'])){
365 $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
366 if ($s == "**"){
367 $s= "*";
368 }
369 foreach ($this->alphabetElements as $tag) {
370 $this->elementValues[$tag]= $s;
371 }
372 }
374 if (isset($_POST['FILTER_LOADED'])) {
375 // Load post values and adapt filter, base and scope accordingly - but
376 // only if we didn't get a _GET
377 foreach ($this->elements as $tag => $element) {
378 if (isset($_POST[$tag])){
379 $this->elementValues[$tag]= validate($_POST[$tag]);
380 } else {
381 $this->elementValues[$tag]= "";
382 }
383 }
384 }
386 // Save base
387 if (isset($_POST['BASE']) && $this->baseMode == "true") {
388 $base= validate($_POST['BASE']);
389 if (isset($this->bases[$base])) {
390 $this->base= $base;
391 }
392 }
394 // Save scope if needed
395 if ($this->scopeMode == "auto") {
396 $this->scope= isset($_POST['SCOPE'])?"sub":"one";
397 }
398 }
400 }
402 ?>