Code

Added reminder
[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= "<table class='filter-wrapper'><tr><td>".$this->renderFilterMenu()."</td><td>";
222     $content.= "<div class='search-filter'><input type='text' name='search_filter' value='".$this->value."'></div>".
223               "&nbsp;<button class='search-filter' type='submit' title='"._("Search")."'>".image("images/find.png")."</button></td></tr></table>";
225     // Return meta data
226     return ("<input type='hidden' name='FILTER_PID' value='".$this->pid."'>".$content);
227   }
230   function query()
231   {
232     global $class_mapping;
233     $result= array();
235     // Return empty list if initial is not set
236     if (!$this->initial) {
237       $this->initial= true;
238       return $result;
239     }
241     // Go thru all queries and merge results
242     foreach ($this->query as $query) {
243       if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) {
244         die("No backend specified in search config.");
245       }
247       // Is backend available?
248       $backend= "filter".$query['backend'];
249       if (!isset($class_mapping["$backend"])) {
250         die("Invalid backend specified in search config.");
251       }
253       // Load filter and attributes
254       $filter= $query['filter'];
255       $attributes= $query['attribute'];
257       // Handle converters if present
258       if ($this->converter) {
259         preg_match('/([^:]+)::(.*)$/', $this->converter, $m);
260         $filter= call_user_func(array($m[1], $m[2]), preg_replace('/\$/', $this->value, $filter));
261       }
263       // Do not replace escaped \$ - This is required to be able to search for e.g. windows machines.
264       if ($this->value == "") {
265         $filter= preg_replace("/\\$/", '*', $filter);
266       } else {
267         $filter= preg_replace("/\\$/", "*".normalizeLdap($this->value)."*", $filter);
268       }
270       $result= array_merge($result, call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes, $this->category, $this->objectStorage));
271     }
272     
273     return ($result);
274   }
277   function update()
278   {
279     if (isset($_POST['FILTER_PID']) && $_POST['FILTER_PID'] == $this->pid) {
281       // Save input field
282       if (isset($_POST['search_filter'])) {
283         $this->value= validate($_POST['search_filter']);
284       }
286       // Save scope if needed
287       if ($this->scopeMode == "auto") {
288         $this->scope= isset($_POST['SCOPE'])?"sub":"one";
289       }
290     }
292   }
295   function getCompletitionList($config, $value="*")
296   {
297     global $class_mapping;
298     $res= array();
300     // Is backend available?
301     $backend= "filter".$config['backend'];
302     if (!isset($class_mapping["$backend"])) {
303       die("Invalid backend specified in search config.");
304     }
306     // Load filter and attributes
307     $filter= $config['filter'];
308     $attributes= $config['attribute'];
309     if (!is_array($attributes)) {
310       $attributes= array($attributes);
311     }
313     // Make filter
314     $filter= preg_replace("/\\$/", normalizeLdap($value), $filter);
315     if (isset($config['base']) && isset($config['scope']) && isset($config['category'])) {
316       $result= call_user_func(array($backend, 'query'), $config['base'], $config['scope'], $filter, $attributes,
317                            $config["category"], $config["objectStorage"]);
318     } else {
319       $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
320                            $this->category, $this->objectStorage);
321     }
323     foreach ($result as $entry) {
324       foreach ($attributes as $attribute) {
325         if (is_array($entry[$attribute])) {
326           for ($i= 0; $i<$entry[$attribute]['count']; $i++) {
327             if (mb_stristr($entry[$attribute][$i], $value)) {
328               $res[]= $entry[$attribute][$i];
329             }
330           }
331         } else {
332           $res[]= $entry[$attribute];
333         }
334       }
335     }
337     return $res;
338   }
341   function processAutocomplete()
342   {
343     global $class_mapping;
344     $result= array();
346     // Introduce maximum number of entries
347     $max= 25;
349     if(isset($this->searches[$this->search]['autocomplete'])){
350       $result= $this->getCompletitionList($this->searches[$this->search]['autocomplete'], $_POST['search_filter']);
351       $result= array_unique($result);
352       asort($result);
354       echo '<ul>';
355       foreach ($result as $entry) {
356         echo '<li>'.mark($_POST['search_filter'], $entry).'</li>';
357         if ($max-- == 0) {
358           break;
359         }
360       }
362       echo '</ul>';
363     }
364   }
367   function getObjectBase($dn)
368   {
369     global $config;
370     $base= "";
372     // Try every object storage
373     $storage= $this->objectStorage;
374     if (!is_array($storage)){
375       $storage= array($storage);
376     }
377     foreach ($storage as $location) {
378       $pattern= "/^[^,]+,".preg_quote($location, '/')."/i";
379       $base= preg_replace($pattern, '', $dn);
380     }
382     /* Set to base, if we're not on a correct subtree */
383     if (!isset($config->idepartments[$base])){
384       $base= $config->current['BASE'];
385     }
387     return $base;
388   }
392   function renderFilterMenu()
393   {
394     // Load shortcut
395     $result= "<input type='hidden' name='act' id='filter' value=''><div style='display:none'><input type='submit' name='exec_filter' id='exec_filter' value=''></div>".
396              "<ul class='level1' id='filter-root'><li><a href='#'>".image("images/filter.png")._("...")."&nbsp;".image("images/lists/sort-down.png")."</a>";
398     // Build ul/li list
399     $result.= "<ul class='level2'>";
400     $result.= "<li><a href='#'>Dummy placeholder</a></li>";
401     #$result.= "<li$separator><a href='#' onClick='document.getElementById(\"actionmenu\").value= \"".$action['name']."\";mainform.submit();'>$img"._($action['label'])."</a></li>";
403     # AUTOCOMPLETER and getTextbox
405     $result.= "</ul>";
407     $script= '<script type="text/javascript" language="JavaScript">var menu2; menu2= new Menu("filter-root", "menu2", configMenu)</script>';
409     return "<div id='filtermenu'>".$result."</li></ul><div>$script";
410   }
415 ?>