Code

Applied in_array strict patches from trunk
[gosa.git] / gosa-core / include / class_multi_plug.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 /*
25 Data structure : 
26 ================ 
27   |->o_tab                      <-- dummy object, collects HTML posts, displays ui 
28   |->a_handles                  <-- tab object for each given dn
29      |->tab object for dn 1 
30      |->tab object for dn 2
31       ...
32      |->tab object for dn n
35 Other functions implemented:
36 ============================
38 CLASS tab
39   - multiple_support_available()  Check if there is at least one plugin with 
40                                   enabled multiple edit support
41   - enable_multiple_support()     Enable multiple edit, for this tab.
42   
43 CLASS plugin
44   - enable_multiple_support()     Enable multiple support for this plugin.
45   - init_multiple_support()       Init summy object, to preset some values.
46   - multiple_execute()            Display dummy object ui.
47   - multiple_save_object()        Get posted values in multiple edit mode.
48   - multiple_check()              Check values specified in dummy object.
49   - get_multi_edit_values()       Get values changed from dummy object.
50   - set_multi_edit_values()       Set values collected with get_multi_edit_values.
51                                   to all objects currently edited.
54 Process:
55 ========
57 multi_plug::multi_plug()
58   |->o_tab = new tab()                      #Initialize ui handle
59   |
60   |->handles
61   | |->handles[] = new tab()                #Initialize objects we want to edit at once
62   |
63   |->o_tab->enable_multiple_support()       #Enable multiple support for ui handle
64   |->detect_multiple_used_attributes()      #Update ui handle with some default values
65     |->handles[]
66       |->by_object->get_multi_init_values() #Get attributes from all handles
67     |->o_tab
68       |->by_object->init_multiple_support() #Assign values to ui handle
69   |
70   |->execute()                              #Display ui
71   | |->o_tab->execute()
72       |->by_object->multiple_execute()
73   |
74   |->check()                                #Check given values
75     |->o_tab->check()
76       |->by_object->multiple_check()
77   |
78   |->save_object()                          #Save posts 
79     |->o_tab->save_object()
80       |->by_object->multiple_save_object()
81   |
82   |->save()                                 #Save collected values 
83     |->populate_values()                    #Populate values to all handles
84       |->o_tab->get_multi_edit_values()     #Get values to populate
85       |->handles->set_multi_edit_values()   #Set values 
86     |->handles->save()                      #Save handles
87   
91 Using this class: 
92 =================
93   Simple Example:
95     $dn   = array(dn1,dn2,dn3);
96     $tmp  = new multi_plug($config,"usertabs",$config->data['TABS']['USERTABS'],$dn);
97     echo $tmp->execute();
99   $tmp can now be used like the normal tab class, execute, save_object ...
100   
101   To enable multipe edit for a specific plugin, 
102   just set the plugin variable 'multiple_support' to true:
104     var $multiple_support = TRUE;
106   If plugin::multiple_support is true, the member function 
107   multiple_execute() will be called and displayed, NOT execute().
109   (I will put this in the wiki, later. This are just notes for me.)
110   
111 */
114 /*! \brief   Handles multiple edits for a given set of dns.
115     \author  Fabian Hickert
116     \version 1.01
117     \date    2007/12/07
119     This class edits multiple tab objects at once. 
120     1. There is a dummy tab object initialized that collects the user input.
121     2. All given objects specified by '$dn' will be initialized and the collected
122      data from the dummy object will be populated to them.
123  */
124 class multi_plug
126   /* Tab handler for each given dn entry */
127         public $a_handles = array();
129   /* Dummy handler which collects the data */
130   private $o_tab     = NULL;  
132   public $dn      = array();
133   public $config  = NULL;
134   private $s_class= "";
135   public $current = "";
136   public $by_object = array();
137   public $by_name = array();
139   /*! \brief    Creates a multi_plug object
140      @param   object  $config GOsa Configuration object
141      @param   string  $class  The class name of the tab we want to edit. e.g. usertabs
142      @param   string  $tab    The config tab name e.g. USERTABS 
143      @param   array   $dns    The object dns we want to edit.
144      @return  object  multi_plug
145    */
146   public function __construct($config,$class,$tab,$dns,$acl_base,$acl_category)
147   {
148     if(!count($dns)){
149       return;
150     }
152     $this->dn       = $dns;
153     $this->config   = $config;
154     $this->s_class  = $class;
156     /* Initialize collector object 
157      * Used to display the ui and to collect the user input.
158      */
159     $this->o_tab    = new $class($config,$tab,"new",$acl_category, TRUE, TRUE);
160     $this->o_tab->set_acl_base($acl_base);
161     $this->by_object = &$this->o_tab->by_object;
162     $this->by_name   = &$this->o_tab->by_name;
163     $this->current   = &$this->o_tab->current;
165     /* Check if the specified tab object supports multiple edits 
166      */
167     if($this->o_tab->multiple_support_available()){
169       /* Enable multiple actions for the collector object 
170        */ 
171       $this->o_tab->enable_multiple_support();
173       /* Initialize the objects we want to edit at once 
174        */
175       foreach($dns as $dn){
176         $obj = new $class($config,$tab,$dn,$acl_category, TRUE, TRUE);
177         $obj->set_acl_base($acl_base);
178         $this->a_handles[] = $obj;
179       }
180     }
182     /* Detect attributes used by all plugins and set 
183      *  those values as default in edit handle 
184      */
185     $this->detect_multiple_used_attributes();
186   }
189   /*! \brief    Combine two ldap result arrays. 
190    * @param     array   $base   Base array 
191    * @param     array   $add    Array to add
192    * @returns   array   Combination of $base and $add
193    */  
194   private function array_combine($base,$add)
195   {
197     foreach($add as $key => $attr) {
198       if(!is_numeric($key)){
199   
200         if(!is_array($add[$key])){
201           $add[$key] = array('count' => 1,$add[$key]);
202         }
204         if(!isset($base[$key])){
205           $base[$key] = $add[$key]; 
206         }else{
208           if(!isset($base[$key]['count'])){
209             $base[$key]['count'] = count($base[$key]);
210           }
212           if(!isset($add[$key]['count'])){
213             $add[$key]['count'] = count($add[$key]);
214           }
215           for($i=0;$i<$add[$key]['count'];$i++){
216             if(!in_array_strict($add[$key][$i],$base[$key])){
217               $base[$key][] = $add[$key][$i];
218               $base[$key]['count']++;
219             }
220           }
221         }
222       }
223     }
224     return($base);
225   }
228   /*! \brief    Intersect two ldap result arrays/Inner join of two ldap result arrays
229    * @param     array   $base   Base array 
230    * @param     array   $minus  Array number two
231    * @returns   array   Result intersection
232    */  
233   private function array_intersect($base,$minus)
234   {
235     foreach($base as $key => $entry){
236       if(is_numeric($key) || !isset($minus[$key])){
237         unset($base[$key]);
238       }elseif(gettype($base[$key]) != gettype($minus[$key])){
239         unset($base[$key]);
240       }elseif(is_string($base[$key]) && $base[$key]!=$minus[$key]){
241         unset($base[$key]);
242       }elseif(is_array($base[$key])){
243         $tmp = array();
244           if(!isset($base[$key]['count'])){
245             $base[$key]['count'] = count($base[$key]);
246           }
247         for($i = 0 ; $i < $base[$key]['count'] ; $i ++){
248           if(isset($base[$key][$i]) && in_array_strict($base[$key][$i],$minus[$key])){
249             $tmp[] = $base[$key][$i];
250           }
251         }
252         if(count($tmp)){
253           $tmp['count'] = count($tmp);
254           $base[$key] = $tmp;
255         }else{
256           unset($base[$key]);
257         }
258       }
259     }
260     return($base);
261   }
263   
264   /*! \brief    Detect values that are used in all edited objects.
265    */  
266   private function detect_multiple_used_attributes()
267   {
268     foreach($this->o_tab->by_object as $name => $plug){
270       if(empty($name))    continue;
272       $attrs = array();
273       $all   = array();
274       foreach($this->a_handles as $hid => $handle){
275         $h_attrs = $this->a_handles[$hid]->by_object[$name]->get_multi_init_values();
276         if(count($attrs) == 0){
277           $attrs = $h_attrs;
278         }else{
279           $attrs = $this->array_intersect($attrs,$h_attrs);
280         }
281         $all = $this->array_combine($all,$h_attrs);
282       }
283       $this->o_tab->by_object[$name]->init_multiple_support($attrs,$all);
284     }
285   }
288   /*! \brief    Returns the edit ui for multiple edit.
289      @return    string  HTML User interface for given tab object.
290    */
291   public function execute()
292   {
293     $str = $this->o_tab->execute();
294     return($str);
295   }
298   /*! \brief    Checks if one of the objects we want to edit is locked. 
299      @return    boolean   Returns TRUE if at least one entry is locked, else false.
300    */
301   public function entries_locked()
302   {
303     $ui = get_userinfo();
304     foreach($this->dn as $dn){
305       if(get_lock($dn) != ""){
306         return(TRUE);
307       }
308     }
309     return(FALSE);
310   }
313   /*! \brief    Generates a lock message that can be displayed if an entry is locked.
314      @return    string  Returns a list of locked entries 
315    */
316   public function display_lock_message()
317   {
318     $ui = get_userinfo();
319     $lock_msg = "";
320     $lock_msg.=  gen_locked_message ($ui->dn, $this->dn);
321     return($lock_msg);
322   }
325   /*! \brief    Locks all currently managed objects (array $this->dn) 
326      @return    boolean   Returns TRUE
327    */
328   public function lock_entries($uid)
329   {
330     foreach($this->dn as $dn)
331     add_lock($dn,$uid);
332     return(TRUE);
333   }
336   /*! \brief    Checks if the given tab object supports multiple edit.
337      @return    boolean   Returns TRUE if the given tab objects supports multiple edit else FALSE.
338    */
339   public function multiple_available()
340   { 
341     if(isset($this->o_tab) && is_object($this->o_tab)){
342       return($this->o_tab->multiple_support_available());
343     }else{
344       return(FALSE);
345     }
346   }
349   /*! \brief    Sets the currently active tab. The tab that will be displayed by $this->execute(). 
350    */
351   public function set_active_tab($str)
352   {
353     $this->current = $str;
354   }
357   /*! \brief    Returns the object info string, that can be displayed in the tab header.
358       @return   string  Returns an information string, containing the list of currently edited dns.
359    */
360   public function get_object_info()
361   {
362     return(_("You are currently editing multiple entries."));
363   }
366   /*! \brief    Handles all HTML posts from the dummy tab object. 
367    */
368   public function save_object()
369   {
370     $this->o_tab->save_object(); 
371   }
374   /*! \brief    Checks if the values fetched by $this->save_object() are valid.
375       @param    array Returns an array containig all error messages.
376    */
377   public function check()
378   {
379     $messages = $this->o_tab->check();
380     return($messages);
381   }
384   /*! \brief    Currently not implemented, later be used to trigger password changes. 
385       @param    boolean Returns TRUE if a password change is needed.
386    */
387   public function password_change_needed()
388   {
389     foreach($this->a_handles as $i_id => $o_handle){
390       if($o_handle->password_change_needed() && isset($o_handle->by_object['user'])){
391         if(!change_password ($o_handle->dn, "",FALSE, $o_handle->by_object['user']->pw_storage,'',$message)){
392             msg_dialog::displayChecks(array($message));
393         }else{
394             new msg_dialog(_("Reset password"),_("The user password has been reset. Please set a new password!"),WARNING_DIALOG);
395         }
396       }
397     }
398     return(FALSE);
399   }
402   /*! \brief    Populate all collected values to the target tab objects ($this->o_handles)
403    */
404   public function populate_values()
405   {
406     if($this->multiple_available() && is_array($this->a_handles)){
407       foreach($this->o_tab->by_object as $name => $obj){
409         $values = $this->o_tab->by_object[$name]->get_multi_edit_values();
410         foreach($this->a_handles as $i_id => $o_handle){
411           $this->a_handles[$i_id]->by_object[$name]->set_multi_edit_values($values);
412         }
413       }
414     }
415   }
418   /*! \brief    Save all edited tab objects ($this->o_handles). 
419    */
420   public function save()
421   {
422     if($this->multiple_available() && is_array($this->a_handles)){
423       $this->populate_values();
424       foreach($this->a_handles as $i_id => $o_handle){
425         $o_handle->save();
426       }
427     }
428   }
431 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
432 ?>