7b1867c7926adde5ccc49082dd57c0017d871e43
1 <?php
3 class filter {
5 var $xmlData;
6 var $elements= array();
7 var $elementValues= array();
8 var $alphabetElements= array();
9 var $search;
10 var $definition;
11 var $category= "";
12 var $objectStorage= array();
13 var $objectBase= "";
14 var $base= "";
15 var $bases= array();
16 var $scope= "";
17 var $query;
18 var $baseMode= false;
19 var $scopeMode= "auto";
20 var $alphabet= null;
21 var $templatePath= "";
22 var $target= "";
24 function filter($filename)
25 {
26 if (!$this->load($filename)) {
27 die("Cannot parse $filename!");
28 }
29 }
31 function load($filename)
32 {
33 // Load data into array
34 $xmlData= simplexml_load_file($filename);
35 if ($xmlData === false) {
36 return false;
37 }
39 // Load definition
40 if (isset($xmlData->definition)) {
41 foreach ($xmlData->definition as $entry) {
42 if (!isset($entry->target) || !isset($entry->template)) {
43 return false;
44 }
46 // Move information
47 $this->templatePath= (string)$entry->template;
48 $this->target= (string)$entry->target;
50 // One is enough
51 break;
52 }
53 }
55 // Load filter
56 if (isset($xmlData->search)) {
57 foreach ($xmlData->search as $entry) {
58 if (!isset($entry->query) || !isset($entry->base) || !isset($entry->scope)) {
59 return false;
60 }
62 // Move information
63 $this->baseMode= (string)$entry->base;
64 $this->scopeMode= (string)$entry->scope;
65 $this->query= $entry->query;
67 // One is enough
68 break;
69 }
70 }
72 // Generate formular data
73 if (isset($xmlData->element)) {
74 foreach ($xmlData->element as $element) {
76 // Ignore elements without type
77 if (!isset($element->type)) {
78 next;
79 }
81 $tag= (string)$element->tag;
83 // Store element for quick access
84 $this->elements[$tag] = $element;
86 // Preset elementValues with default values if exist
87 if (isset($element->default)) {
88 $this->elementValues[$tag] = (string)$element->default;
89 } else {
90 $this->elementValues[$tag] = "";
91 }
93 // Does this element react on alphabet links?
94 if (isset($element->alphabet) && (string)$element->alphabet == "true") {
95 $this->alphabetElements[]= $tag;
96 }
97 }
98 }
100 // Save definition
101 if (isset($xmlData->definition)) {
102 $this->definition = $xmlData->definition;
103 }
105 // Save search
106 if (isset($xmlData->search)) {
107 $this->search = $xmlData->search;
108 }
110 return true;
111 }
114 function getTextfield($element)
115 {
116 $tag= (string)$element->tag;
117 $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='30' maxlength='30' value='".$this->elementValues[$tag]."'>";
118 if (isset($element->autocomplete)) {
119 $frequency= "0.5";
120 $characters= "1";
121 if (isset($element->autocomplete->frequency)) {
122 $frequency= (string)$element->autocomplete->frequency;
123 }
124 if (isset($element->autocomplete->characters)) {
125 $characters= (string)$element->autocomplete->characters;
126 }
127 $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
128 "<script type='text/javascript'>".
129 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
130 "</script>";
131 }
132 return $result;
133 }
136 function getCheckbox($element)
137 {
138 $tag= (string)$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();'>";
152 foreach ($element->value as $key=>$value) {
153 $selected= "";
154 if ($this->elementValues[(string)$element->tag] == $value->key) {
155 $selected= " selected";
156 }
157 $result.= "<option value='".$value->key."'$selected>{t}".$value->set."{/t}</option>";
158 }
159 $result.= "</select>";
161 return $result;
162 }
165 function getCurrentBase()
166 {
167 if (isset($this->search->base) && (string)$this->search->scope != "auto") {
168 return false;
169 }
171 return $this->base;
172 }
175 function getCurrentScope()
176 {
177 if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
178 return (string)$this->search->scope;
179 }
181 return $this->scope;
182 }
185 function setBases($bases) {
186 $this->bases= $bases;
187 }
190 function setObjectStorage($storage) {
191 $this->objectStorage= $storage;
192 }
195 function setObjectBase($base) {
196 $this->objectBase= $base;
197 }
200 function setCategory($category) {
201 $this->category= $category;
202 }
205 function setCurrentBase($base) {
206 $this->base= $base;
207 }
210 function setCurrentScope($scope) {
211 $this->scope= $scope;
212 }
215 function renderBase()
216 {
217 $result= "<select name='currentMainBase' onChange='mainform.submit()' size='1'>";
219 foreach ($this->bases as $key=>$value) {
220 $selected= "";
221 if ($key == $this->base) {
222 $selected= " selected";
223 }
224 $result.= "<option value='".$key."'$selected>".$value."</option>";
225 }
226 $result.= "</select>";
228 return $result;
229 }
232 function renderAlphabet($columns= 10)
233 {
234 // Return pre-rendered alphabet if available
235 if ($this->alphabet) {
236 return ($this->alphabet);
237 }
239 $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
240 $alphabet= "";
241 $c= 0;
243 /* Fill cells with charaters */
244 for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
245 if ($c == 0){
246 $alphabet.= "<tr>";
247 }
249 $ch = mb_substr($characters, $i, 1, "UTF8");
250 $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
251 validate($_GET['plug'])."&filter=".$ch."\"> ".$ch." </a></td>";
253 if ($c++ == $columns){
254 $alphabet.= "</tr>";
255 $c= 0;
256 }
257 }
259 /* Fill remaining cells */
260 while ($c++ <= $columns){
261 $alphabet.= "<td> </td>";
262 }
264 /* Save alphabet */
265 $this->alphabet= "<table width='100%'>$alphabet</table>";
267 return ($this->alphabet);
268 }
271 function renderApply()
272 {
273 return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
274 }
277 function renderScope()
278 {
279 $checked= $this->scope == "sub"?" checked":"";
280 return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked> "._("Search in subtrees");
281 }
284 function renderFilter()
285 {
286 $smarty= get_smarty();
287 $smarty->assign("ALPHABET", $this->renderAlphabet());
288 $smarty->assign("APPLY", $this->renderApply());
289 $smarty->assign("SCOPE", $this->renderScope());
290 $smarty->assign("BASE", $this->renderBase());
292 // Load template and replace elementsHtml[]
293 foreach ($this->elements as $tag => $element) {
294 $htmlCode= "";
295 switch ($element->type) {
296 case "textfield":
297 $htmlCode = $this->getTextfield($element);
298 break;
300 case "checkbox":
301 $htmlCode = $this->getCheckbox($element);
302 break;
304 case "combobox":
305 $htmlCode = $this->getCombobox($element);
306 break;
308 default:
309 die ("Unknown element type specified!");
310 }
311 $smarty->assign("$tag", $htmlCode);
312 }
314 // Load template
315 return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path("filter/$this->templatePath")));
316 }
319 function query()
320 {
321 global $class_mapping;
322 $result= array();
324 // Go thru all queries and merge results
325 foreach ($this->query as $query) {
326 if (!isset($query->backend) || !isset($query->filter) || !isset($query->attribute)) {
327 die("No backend specified in search config.");
328 }
330 // Is backend available?
331 $backend= "filter".(string)$query->backend;
332 if (!isset($class_mapping["$backend"])) {
333 die("Invalid backend specified in search config.");
334 }
336 // Load filter and attributes
337 $filter= $query->filter;
338 $attributes= array();
339 foreach($query->attribute as $attr) {
340 $attributes[]= (string)$attr;
341 }
343 // Generate final filter
344 foreach ($this->elements as $tag => $element) {
345 $e_set= (string)$element->set;
346 $e_unset= (string)$element->unset;
348 if ($this->elementValues[$tag] == "") {
349 $e_unset= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_unset);
350 $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
351 } else {
352 $e_set= preg_replace('/\$/', normalizeLdap($this->elementValues[$tag]), $e_set);
353 $filter= preg_replace("/\\$$tag/", $e_set, $filter);
354 }
355 }
357 $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
358 $this->category, $this->objectStorage, $this->objectBase));
359 }
362 return ($result);
363 }
366 function isValid()
367 {
368 foreach ($this->elements as $tag => $element) {
369 if (isset($element->regex)){
370 if (!preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])){
371 return false;
372 }
373 }
374 }
375 return true;
376 }
379 function update()
380 {
382 /* React on alphabet links if needed */
383 if (isset($_GET['filter'])){
384 $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
385 if ($s == "**"){
386 $s= "*";
387 }
388 foreach ($this->alphabetElements as $tag) {
389 $this->elementValues[$tag]= $s;
390 }
391 }
393 if (isset($_POST['FILTER_LOADED'])) {
394 // Load post values and adapt filter, base and scope accordingly - but
395 // only if we didn't get a _GET
396 foreach ($this->elements as $tag => $element) {
397 if (isset($_POST[$tag])){
398 $this->elementValues[$tag]= validate($_POST[$tag]);
399 } else {
400 $this->elementValues[$tag]= "";
401 }
402 }
403 }
405 // Save base
406 if (isset($_POST['BASE']) && $this->baseMode == "true") {
407 $base= validate($_POST['BASE']);
408 if (isset($this->bases[$base])) {
409 $this->base= $base;
410 }
411 }
413 // Save scope if needed
414 if ($this->scopeMode == "auto") {
415 $this->scope= isset($_POST['SCOPE'])?"sub":"one";
416 }
417 }
419 }
421 ?>