Code

I really start hating those @ in front of function calls... makes debugging very...
[gosa.git] / gosa-core / include / class_filter.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id$$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 class filter {
25   var $xmlData;
26   var $searches= array();
27   var $search;
28   var $category= "";
29   var $objectStorage= array();
30   var $base= "";
31   var $scope= "";
32   var $query;
33   var $value= "";
34   var $initial= false;
35   var $scopeMode= "auto";
36   var $converter= null;
37   var $pid;
40   function filter($filename)
41   {
42     global $config;
44     // Load eventually passed filename
45     if (!$this->load($filename)) {
46       die("Cannot parse $filename!");
47     }
49     $this->pid= preg_replace("/[^0-9]/", "", microtime(TRUE)); 
50   }
53   function load($filename)
54   {
55     $contents = file_get_contents($filename);
56     $this->xmlData= xml::xml2array($contents, 1);
58     if (!isset($this->xmlData['filterdef'])) {
59       return false;
60     }
62     $this->xmlData= $this->xmlData["filterdef"];
64     // Load filter
65     if (isset($this->xmlData['search'])) {
67       // Array conversion
68       if (!is_array($this->xmlData['search'])) {
69         $searches= array($this->xmlData['search']);
70       } else {
71         $searches= $this->xmlData['search'];
72       }
74       /* Store available searches */
75       foreach ($this->xmlData['search'] as $search) {
77         /* Do multi conversation */ 
78         if (!is_array($search['query'])){
79           $search['query']= array($search['query']);
80         }
82         /* Store search */
83         $this->searches[$search['label']]= $search;
85       }
86     } else {
87       return false;
88     }
90     // Transfer scope
91     $this->scopeMode= $this->xmlData['definition']['scope'];
92     if ($this->scopeMode == "auto") {
93       $this->scope= "one";
94     } else {
95       $this->scope= $this->scopeMode;
96     }
98     // Transfer initial value
99     if (isset($this->xmlData['definition']['initial']) && $this->xmlData['definition']['initial'] == "true"){
100       $this->initial= true;
101     }
103     // Transfer category
104     if (isset($this->xmlData['definition']['category'])){
105       $this->category= $this->xmlData['definition']['category'];
106     }
108     // Set default search mode
109     $this->setSearch($this->xmlData['definition']['default']);
111     return true;  
112   }
115   function setSearch($method)
116   {
117     // Move information
118     if (isset($this->searches[$method])) {
119       $this->query= $this->searches[$method]['query'];
120       if (!isset($this->query[0])) {
121         $this->query= array($this->query);
122       }
123       $this->search= $method;
124     } else {
125       die ("Invalid search module!");
126     }
127   }
130   function getTextfield($element)
131   {
132     $tag= $element['tag'];
133     $size= 30;
134     if (isset($element['size'])){
135       $size= $element['size'];
136     }
137     $maxlength= 30;
138     if (isset($element['maxlength'])){
139       $maxlength= $element['maxlength'];
140     }
141     $result= "<input class='filter_textfield' id='$tag' name='$tag' type='text' size='$size' maxlength='{$maxlength}' value='".$this->elementValues[$tag]."'>";
142     if (isset($element['autocomplete'])) {
143       $frequency= "0.5";
144       $characters= "1";
145       if (isset($element['autocomplete']['frequency'])) {
146         $frequency= $element['autocomplete']['frequency'];
147       }
148       if (isset($element['autocomplete']['characters'])) {
149         $characters= $element['autocomplete']['characters'];
150       }
151       $result.= "<div id='autocomplete$tag' class='autocomplete'></div>".
152                 "<script type='text/javascript'>".
153                 "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });".
154                 "</script>";
156        $this->autocompleters[$tag]= $element['autocomplete'];
157     }
158     return $result;
159   }
162   function getCurrentBase()
163   {
164     if (isset($this->search->base) && (string)$this->search->scope != "auto") {
165       return false;
166     }
168     return $this->base;
169   }
172   function getCurrentScope()
173   {
174     if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
175       return (string)$this->search->scope;
176     }
178     return $this->scope;
179   }
182   function setConverter($hook)
183   {
184     $this->converter= $hook;
185   }
188   function setObjectStorage($storage)
189   {
190     $this->objectStorage= $storage;    
191   }
194   function setBase($base)
195   {
196     $this->base= $base;
197   }
200   function setCurrentScope($scope)
201   {
202     $this->scope= $scope;
203   }
206   function renderApply()
207   {
208     return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
209   }
212   function renderScope()
213   {
214     $checked= $this->scope == "sub"?" checked":"";
215     return "<input type='checkbox' id='SCOPE' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked>&nbsp;<LABEL for='SCOPE'>"._("Search in subtrees")."</LABEL>";
216   }
219   function render()
220   {
221     $content= "Search comes here...";
223     // Return meta data
224     return ("<input type='hidden' name='FILTER_PID' value='".$this->pid."'>".$content);
225   }
228   function query()
229   {
230     global $class_mapping;
231     $result= array();
233     // Return empty list if initial is not set
234     if (!$this->initial) {
235       $this->initial= true;
236       return $result;
237     }
239     // Go thru all queries and merge results
240     foreach ($this->query as $query) {
241       if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
242         die("No backend specified in search config.");
243       }
245       // Is backend available?
246       $backend= "filter".$query['backend'];
247       if (!isset($class_mapping["$backend"])) {
248         die("Invalid backend specified in search config.");
249       }
251       // Load filter and attributes
252       $filter= $query['filter'];
253       $attributes= $query['attribute'];
255       // Handle converters if present
256       if ($this->converter) {
257         preg_match('/([^:]+)::(.*)$/', $this->converter, $m);
258         $filter= call_user_func(array($m[1], $m[2]), preg_replace('/\$/', $this->value, $filter));
259       }
261       // Do not replace escaped \$ - This is required to be able to search for e.g. windows machines.
262       if ($this->value == "") {
263         $filter= preg_replace("/\\$/", '*', $filter);
264       } else {
265         $filter= preg_replace("/\\$/", normalizeLdap($this->value), $filter);
266       }
268       $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes, $this->category, $this->objectStorage));
269     }
270     
271     return ($result);
272   }
275   function update()
276   {
277     if (isset($_POST['FILTER_PID']) && $_POST['FILTER_PID'] == $this->pid) {
279       // Save input field
280       if (isset($_POST['search_filter'])) {
281         $this->value= validate($_POST['search_filter']);
282       }
284       // Save scope if needed
285       if ($this->scopeMode == "auto") {
286         $this->scope= isset($_POST['SCOPE'])?"sub":"one";
287       }
288     }
290   }
293   function getCompletitionList($config, $value="*")
294   {
295     global $class_mapping;
296     $res= array();
298     // Is backend available?
299     $backend= "filter".$config['backend'];
300     if (!isset($class_mapping["$backend"])) {
301       die("Invalid backend specified in search config.");
302     }
304     // Load filter and attributes
305     $filter= $config['filter'];
306     $attributes= $config['attribute'];
307     if (!is_array($attributes)) {
308       $attributes= array($attributes);
309     }
311     // Make filter
312     $filter= preg_replace("/\\$/", normalizeLdap($value), $filter);
313     if (isset($config['base']) && isset($config['scope']) && isset($config['category'])) {
314       $result= call_user_func(array($backend, 'query'), $config['base'], $config['scope'], $filter, $attributes,
315                            $config["category"], $config["objectStorage"]);
316     } else {
317       $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
318                            $this->category, $this->objectStorage);
319     }
321     foreach ($result as $entry) {
322       foreach ($attributes as $attribute) {
323         if (is_array($entry[$attribute])) {
324           for ($i= 0; $i<$entry[$attribute]['count']; $i++) {
325             if (mb_stristr($entry[$attribute][$i], $value)) {
326               $res[]= $entry[$attribute][$i];
327             }
328           }
329         } else {
330           $res[]= $entry[$attribute];
331         }
332       }
333     }
335     return $res;
336   }
339   function processAutocomplete()
340   {
341     global $class_mapping;
342     $result= array();
344     // Introduce maximum number of entries
345     $max= 25;
347     if(isset($this->searches[$this->search]['autocomplete'])){
348       $result= $this->getCompletitionList($this->searches[$this->search]['autocomplete'], $_POST['search_filter']);
349       $result= array_unique($result);
350       asort($result);
352       echo '<ul>';
353       foreach ($result as $entry) {
354         echo '<li>'.mark($_POST['search_filter'], $entry).'</li>';
355         if ($max-- == 0) {
356           break;
357         }
358       }
360       echo '</ul>';
361     }
362   }
365   function getObjectBase($dn)
366   {
367     global $config;
368     $base= "";
370     // Try every object storage
371     $storage= $this->objectStorage;
372     if (!is_array($storage)){
373       $storage= array($storage);
374     }
375     foreach ($storage as $location) {
376       $pattern= "/^[^,]+,".preg_quote($location, '/')."/i";
377       $base= preg_replace($pattern, '', $dn);
378     }
380     /* Set to base, if we're not on a correct subtree */
381     if (!isset($config->idepartments[$base])){
382       $base= $config->current['BASE'];
383     }
385     return $base;
386   }
390 ?>