Code

Removed divSelect list
[gosa.git] / gosa-plugins / goto / admin / groups / apps / class_groupApplication.inc
1 <?php
2 class appgroup extends plugin
3 {
4   var $config;
5   var $curbase;
7   /* Contains the menu structure in an array.
8    */
9   var $a_Structure= array();
10   var $a_Structure_on_load = array();
11   var $Releases;
12   var $FAIrelease = 0;
13   var $apps = array();
14   var $_cache = array();
16   var $app_parameter = array();
17   var $edit_entry    = array();
18   var $enableReleaseManagement = FALSE;
20   var $copied_release = ""; 
21    
23   public function __construct(&$config, $dn= NULL, $parent= NULL)
24   {
25     plugin::plugin($config,$dn,$parent);
26     $this->dn = $dn; 
27     $this->_load_menu_structure();
28     $this->a_Structure_on_load = $this->a_Structure;
30     /* Check if we have relase mangement enabled and prepare group application for release management */
31     $tmp = $config->search("faiManagement", "CLASS",array('menu','tabs'));
32     if(!empty($tmp)){
33       $this->enableReleaseManagement = true;
34     }
36     $this->Releases   = $this->getReleases();
38     /* Set intial release */
39     $this->FAIrelease = $config->search("faiManagement","DEFAULTFAIRELEASE",array("menu"));
40     if(empty($this->FAIrelease) || !isset($this->Releases[$this->FAIrelease])){
41       $this->FAIrelease = "/";
42     }
44     $this->curbase    = $this->config->current['BASE'];
45     $this->reload();
46  
47     /* If we have at least one assigned application-
48        Enable this account.
49      */ 
50     $this->is_account = FALSE;
51     if(count($this->_get_all_entries()) > 1){
52       $this->is_account= TRUE;
53     }   
54     $this->initially_was_account = $this->is_account;
56     // Prepare lists
57     $this->applicationList = new sortableListing();
58     $this->applicationList->setDeleteable(false);
59     $this->applicationList->setEditable(true);
60     $this->applicationList->setWidth("100%");
61     $this->applicationList->setHeight("300px");
62     $this->applicationList->setColspecs(array('20px','20px','*'));
63     $this->applicationList->setHeader(array("&nbsp;","&nbsp;",_("Application")));
64     $this->applicationList->setDefaultSortColumn(2);
65     $this->applicationList->setAcl('rwcdm'); // All ACLs, we filter on our own here.
67   }
70   /*! \brief Reload the list of applications for the currently selected release.
71              If necessary, maybe the list is already cached.
72    */
73   function reload()
74   {
75     $ret = array();
76     $release_info = $this->Releases[$this->FAIrelease];
78     /* Check if the available application were already been fetched.
79        If not, build up a list of available applications.
80      */  
81     if(!isset($this->_cache['ReleaseApps'][$release_info['suffix']])){
83       /* First of all, get all application departments to search in.
84        */  
85       $ldap = $this->config->get_ldap_link();
86       $ldap->cd($this->config->current['BASE']);
87       $ldap->search("ou=apps",array("dn"));
88       $app_deps = array();
89       while($attrs = $ldap->fetch()){
90         $app_deps[] = $attrs['dn'];
91       }
93       /* Search all release departments for the above fetched application departments
94        */
95       foreach($app_deps as $dep){
96         $ldap->cd($dep);
97         $ldap->search("objectClass=FAIbranch",array("dn"));
98         while($attrs = $ldap->fetch()){
99           $app_deps[] = $attrs['dn'];
100         }
101       }
103       /* Filter out those releases that match the currently selected release, 
104           and fetch all applications from those departments.
105        */
106       foreach($app_deps as $dep){
107         if(preg_match("/^".preg_quote($release_info['suffix'], '/')."/",$dep)){
108           $ret = array_merge($ret,get_list("(objectClass=gosaApplication)","application",$dep,array("*"),GL_NONE));
109         }
110       }
112       /* Create a new array containing all fetch apps for the currently selected release,
113           sort it and store results in cache. 
114        */ 
115       $tmp = array();
116       foreach($ret as $key => $app){
117         $tmp[$key] = $app['cn'][0];
118       }
119       natcasesort($tmp);
120       $res = array();
121       foreach($tmp as $key => $app){
122         $res[] = $ret[$key];
123       }
125       $this->_cache['ReleaseApps'][$release_info['suffix']] = $res;
126     } 
127     $this->apps = $this->_cache['ReleaseApps'][$release_info['suffix']];
128   }
130   
131   
132   /*! \brief generate a list of available releases
133       @return return an array with all available releases.
135       e.g.
137       /     "name"    /
138             "found"   1
139             "parts"   Array (empty)
140             "suffix"  ou=apps,
142       halut "name"    halut
143             "found"   1
144             "FAIstate"  
145             "dn"      ou=halut,ou=apps,ou=Direktorium,o=Landeshauptstadt München,c=de
146             "parts"   0 halut
147             "suffix"  ou=halut,ou=apps,
149       This will be used as base for the application menu structure.
150       If there is a menu assigned for a release, this menu will be 
151        appended with the index 'ENTRIES';
152     */
153   function getReleases()
154   {
155     $ret =array("/" => array("name" => "/", "found" => TRUE , "parts" => array(),"suffix" => get_ou('applicationRDN')));
156     if($this->enableReleaseManagement){
158       /* Only display those releases that we are able to read 
159        */
160       $dn     = get_ou("applicationRDN").$this->config->current['BASE'];
161       $filter = "(&(objectClass=organizationalUnit)(objectClass=FAIbranch))";
162       $res    = get_sub_list($filter,array("application","fai"), 
163           array(get_ou("applicationRDN"),get_ou("faiBaseRDN")),$dn, array("ou","FAIstate"), GL_SUBSEARCH);
165       /* Go through all departments and check which department is a valid 
166           department release.
167        */
168       foreach($res as $attrs){
169         if(preg_match("/".get_ou('applicationRDN')."/i",$attrs['dn'])){
171           /* Parse all returned departments dns into a useable type.
172              (ou=1.0.0,ou=halut,ou=apps  ==> halue/1.0.0)
173            */
174           $bb     = preg_replace("/".preg_quote(get_ou('applicationRDN'), '/').".*/i","",$attrs['dn']);
175           $parts  = array_reverse(explode("ou=",$bb));
177           $str ="";
178           foreach($parts as $key => $part){
179             if(empty($part)) {
180               unset($parts[$key]);
181               continue;
182             }
183             $part = str_replace(",","",$part);
184             $str .= $part."/";
185             $parts[$key] = $part;
186           }
187           $name = preg_replace("/\/$/","",$str);
188           if(empty($name)) {
189             $name ="/";
190           }
192           $FAIstate = "";
193           if(isset($attrs['FAIstate'])){
194             $FAIstate = $attrs['FAIstate'][0];
195           }
197           /* Check if this department has a menu structure assigned 
198            */
199           $all = $this->_get_all_entries();
200           $found = FALSE;
201           foreach($all as $entry){
202             if(isset($entry['DN']) && preg_match("/^".preg_quote($bb, '/')."/",$entry['DN'])){
203               $found =TRUE;
204               break;
205             }
206           }
208           $ret[$name] = array("name"     => $name, 
209               "found"    => $found,
210               "FAIstate" => $FAIstate,
211               "dn"       => $attrs['dn'], 
212               "parts"    => $parts,"suffix" => $bb.get_ou('applicationRDN'));
213         }
214       }
215     }
216     ksort($ret);
217     return($ret);
218   }
221   /*! \brief Load the menu structure from ldap and create a multi dimensional array.
223       This will create a multidimensional array.
224       e.g.:
226       $this->a_Structure =
227   
228       [0]['TYPE']   = "BASE"
229       [0]['ENTRIES']  [0]['TYPE']   = "RELEASE"
230                       [0]['NAME']   = "halut"
231                       [0]['ENTRIES']= array()
232                       ...
233       [0]['ENTRIES']  [1]['TYPE']   = "RELEASE"
234                       [1]['NAME']   = "halut/1.0.0"
235                       [1]['ENTRIES']  [0]['TYPE']   = "TYPE"
236                                       [0]['NAME']   = "Programme"
237                                       [0]['ENTRIES'][0]['TYPE'] = "ENTRY"
238                                                     [0]['NAME'] = "konqueror"
239                                                     [1]['TYPE'] = "ENTRY"
240                                                     [1]['NAME'] = "firefox"
241    */
242   function _load_menu_structure()
243   {
244     /* Create the base object
245      */
246     $base =  array();
247     $base['UNIQID'] = uniqid();
248     $base['PARENT'] = 0; 
249     $base['NAME']   = "";
250     $base['TYPE']   = "BASE";
251     $base['ENTRIES']= array();
252     $base['STATUS'] = "LOADED";
253     
254     $this->a_Structure  = array();
255     $this->a_Structure[0] = $base;
257     /* Search for all Releases/Menu Folders and Menu Entries,
258         to append them to our structure array.
259      */
260     $ldap = $this->config->get_ldap_link();
261     $ldap->cd($this->dn);
262     $ldap->search("(|(objectClass=gotoSubmenuEntry)(objectClass=FAIbranch)(objectClass=gotoMenuEntry))",array("*"));
263     while($attrs = $ldap->fetch()){
265       /* Find the correct position where to add this entry.
266           e.g. If we have cn=firefox,cn=Programme,ou=halut...
268           1. get a pointer to the halut array ($this->a_Structure['0'][ENTRIES''][]['halut'])
269           2. then get a pointer to the halut['ENTRIES'][]['Programme'] array. 
270           3. append 'firefox' to the 'ENTRIES' of our "Programme" pointer.
271        */
272       $cur          = &$this->a_Structure[0]['ENTRIES'];
273       $parent_id    = $base['UNIQID'];
274       $sub_dn       = preg_replace("/,".preg_quote($this->dn, '/')."$/","",$attrs['dn']);
275       $sub_dn_array = explode(",",$sub_dn);
277       /* Walk through our menu structure array while we have found 
278           the correct position where to add this object. 
279        */
280       $found = true;
281       for($i = (count($sub_dn_array)-1) ; $i >= 0 ; $i--){
282         $name = preg_replace("/^[^=]*+=/","",$sub_dn_array[$i]);
283         
284         /* We haven't found the end node where this object has to be added
285          */
286         if($i > 0){
287           $found =FALSE;
288           foreach($cur as $key => $entry){
289             if($entry['NAME'] == $name){
290               $cur = &$cur[$key]['ENTRIES'];
291               $parent_id = $entry['UNIQID'];
292               $found =true;
293               break;
294             }
295           }
296         }else{
297           
298           if(!$found){
299             break;
300           }
302           /* Get application priority.
303              And ensure that each priority exists once.
304            */
305           $priority = 1;
306           if(isset($attrs['gosaApplicationPriority'])){
307             $priority= $attrs['gosaApplicationPriority'][0];
308           }
309           while(isset($cur[$priority])){
310             $priority ++;
311           }
313           /* Create the data object that should be added 
314              * Folder
315              * Entry
316              * Release
317            */
318           $data = array();
319     
320           /* Add a menu folder 
321            */
322           if(in_array("gotoSubmenuEntry",$attrs['objectClass'])){
323             $type = "FOLDER";
325             $data['ICON'] = "";
326             if(isset($attrs['gosaApplicationIcon'])){
327               $data['ICON'] = $ldap->get_attribute($attrs['dn'],"gosaApplicationIcon");
328             }
330           /* Add a menu entry 
331            */
332           }elseif(in_array("gotoMenuEntry",$attrs['objectClass'])){
334             $type = "ENTRY";
335             $data['INFO'] = "";
336             $data['PARAMETER'] = array();
337             if(isset($attrs['gosaApplicationParameter'])){
338               for($p = 0 ; $p < $attrs['gosaApplicationParameter']['count'] ; $p ++){
339                 if(preg_match("/:/",$attrs['gosaApplicationParameter'][$p])){
340                   $tmp = explode(":",$attrs['gosaApplicationParameter'][$p]);
341                   $data['PARAMETER'][$tmp[0]] = preg_replace('/^[^:]+:/', '', $attrs['gosaApplicationParameter'][$p]);
342                 }elseif($attrs['gosaApplicationParameter'][$p] == "*separator*"){
343                   $type = "SEPERATOR";
344                   $data['PARAMETER'] = array();
345                   break;
346                 }
347               }
348             }
350           /* Add a release
351            */
352           }elseif(in_array("FAIbranch",$attrs['objectClass'])){
353             $type = "RELEASE";
354             if(isset($attrs['FAIstate'][0])){
355               $data['FAIstate'] = $attrs['FAIstate'][0];
356             }else{
357               $data['FAIstate'] = "";
358             }
359           }
361           /* Create object and append it to the current structure pointer 
362            */
363           $data['LDAP_ATTRS'] = $attrs;
364           $data['DN']       = $attrs['dn'];
365           $data['NAME']     = $name;
366           $data['TYPE']     = $type;
367           $data['PRIORITY'] = $priority;
368           $data['ENTRIES']  = array();
369           $data['UNIQID']   = uniqid();
370           $data['PARENT']   = $parent_id;
371           $data['STATUS']   = "LOADED";
372           $cur[$priority]   = $data;
373           ksort($cur);
374         }
375       }
376     }
377   } 
380   function execute()
381   {
382     /* Call parent execute */
383     plugin::execute();
385     if(isset($_GET['r'])) $this->__construct($this->config,$this->dn);
387     if (isset($_POST['modify_state'])){
388       $this->is_account = !$this->is_account;
389     }
391     /* Do we represent a valid account? */
392     if (!$this->is_account){
393       $display= $this->show_disable_header(msgPool::addFeaturesButton(_("Menu")), msgPool::featuresDisabled(_("Menu")));
394       return ($display);
395     }
397     $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("Menu")), msgPool::featuresEnabled(_("Menu")));
399     if(isset($_GET['send'])){
400       $id = $_GET['send'];
401       $all = $this->_get_all_entries();
402       if(isset($all[$id])){
403         send_binary_content($all[$id]['ICON'],$id.".jpg","image/jpeg");
404         exit;
405       }
406     }
408     if(isset($_GET['r']))
409     $this->__construct($this->config,$this->dn);
411     if(count($this->edit_entry)){
412       if($this->edit_entry['TYPE'] == "ENTRY"){
413         $smarty = get_smarty();
414         $smarty->assign("type", "ENTRY");
415         $smarty->assign("entry",$this->edit_entry);
416         $smarty->assign("paras",$this->app_parameter);
417         $display= $smarty->fetch (get_template_path('edit_entry.tpl', TRUE, dirname(__FILE__)));
418         return($display);
419       }
420       if($this->edit_entry['TYPE'] == "FOLDER"){
421         $smarty = get_smarty();
423         session::set("binarytype" , "image/jpeg");
424         session::set("binary" , $this->edit_entry['ICON']);
425   
426         $smarty->assign("rand", microtime(TRUE));
427         $smarty->assign("image_set" , strlen($this->edit_entry['ICON']) > 0); 
428         $smarty->assign("type", "FOLDER");
429         $smarty->assign("entry",$this->edit_entry);
430         $display= $smarty->fetch (get_template_path('edit_entry.tpl', TRUE, dirname(__FILE__)));
431         return($display);
432       }
433     }
435     $smarty = get_smarty();
436     $smarty->assign("plug_id" , $_GET['plug']);
438     /* Create application list */
439     $departments = array();
440     if(!$this->enableReleaseManagement){
441       $res = get_list("(objectClass=gosaDepartment)", "application", $this->curbase,array("description","cn","ou"),GL_SIZELIMIT);
442       foreach($res as $value){
443         $fdn = $value['dn'];
444         $fdn = preg_replace("/".preg_quote($this->curbase, '/')."/","",$fdn);
445         $fdn= LDAP::fix($fdn);
446         if($value["description"][0]!=".."){
447           $departments[$value['dn']]= convert_department_dn($fdn)." - [".$value["description"][0]."]";
448         }else{
449           $departments[$value['dn']]=convert_department_dn($fdn)." ["._("Back")."]";
450         }
451       }
452     }
454     /* Create base back entry */
455     $base_back = preg_replace("/^[^,]+,/","",$this->curbase);
456     if((strlen($base_back)>= strlen($this->config->current['BASE']))&&($this->curbase!=$this->config->current['BASE'])){
457       $departments[$base_back]=".. ["._("back")."]";
458     }
460     // Append departments for current base 
461     $data = $lData = array();
462     foreach($departments as $key => $app){
463         $img = image('images/lists/folder.png');
464         $data[$key] = array('TYPE'=>'DEP','ID'=> $app);
465         $lData[$key] = array('data' => array($img,"&nbsp;",$app));
467     }
469     // Add applications found on this base 
470     $used_apps = $this->_get_used_entry_name();
471     foreach($this->apps as $key => $app){
472         if(in_array($app['cn'][0],$used_apps)) continue;
473         if(!preg_match("/".get_ou('applicationRDN').preg_quote($this->curbase, '/')."$/",$app['dn'])){
474             continue;
475         }
477         $name = $app['cn'][0];
478         if(isset($app['description'])){
479             $name .= "&nbsp;[".$app['description'][0]."]";
480         }
481         $img = image('plugins/goto/images/select_application.png');
482         $chk = "<input class='center' type='checkbox' value='1' name='AddApp_".$key."'>";
483         $data[$key] = array('TYPE'=>'APP','ID'=> $app);
484         $lData[$key] = array('data' => array($img,$chk,$name));
485     }
486     $this->applicationList->setListData($data,$lData);
487     $this->applicationList->update();
489     /* Assign copy / paste values 
490      */
491     if(!empty($this->copied_release)){
492       $smarty->assign("copied", TRUE);
493       $smarty->assign("copy_source", $this->copied_release);
494     }else{
495       $smarty->assign("copied", FALSE);
496     }
497     $smarty->assign("enableReleaseManagement",$this->enableReleaseManagement);
498     $smarty->assign("FAIrelease",$this->FAIrelease);
499     $smarty->assign("app_list",$this->applicationList->render());
500     $smarty->assign("i",0);
501     $smarty->assign("releases",$this->Releases);
502     $smarty->assign("folders" , $this->_get_folder_names());
503     $entries = $this->_get_entries_for_release($this->FAIrelease);
504     $smarty->assign("entries",$entries);
505     $display.= $smarty->fetch (get_template_path('app_list.tpl', TRUE, dirname(__FILE__)));
506     return($display);
507   }
509    
510   /*! \brief Returns all used folder names 
511       @return Array  All used folder names.
512    */ 
513   function _get_folder_names()
514   {
515     $data = $this->_get_entries_for_release($this->FAIrelease);
516     $all    = $this->_get_all_entries();
517     $ret = array("BASE" => ".");
518     foreach($data as $entry){
520       if($entry['TYPE'] == "FOLDER"){
521         $str = $entry['NAME'];
522         $parent = $entry['PARENT'];
523         $i = 10;
524         while(isset($all[$parent]) && $i){  
525           $i --;
526           $parent_o = $all[$parent];
527           $str      = $parent_o['NAME']."/".$str;
528           $parent   = $all[$parent_o['UNIQID']]['PARENT'];
529         }        
530         $ret[$entry['UNIQID']] = $str;
531       }
532     }
533     return($ret);
534   }
537   /*! \brief return all used applications 
538       @return Array  All used applications.
539    */ 
540   function _get_used_entry_name()
541   {
542     $data = $this->_get_entries_for_release($this->FAIrelease);
543     $ret = array();
544     foreach($data as $entry){
545       if($entry['TYPE'] == "ENTRY"){
546         $ret[] = $entry['NAME'];
547       }
548     }
549     return($ret);
550   }
553   /*! \brief Returns all folder an entries for the selected release 
554       @return Array  Returns the complete menu structure for the given array.
555    */ 
556   function _get_entries_for_release($release,$cur = NULL)
557   {
558     $all = $this->_get_all_entries();
559     $key = $this->_get_release_key($release);
560     if(isset($all[$key]) && count($all[$key]['ENTRIES'])){
561       $res = $this->_get_all_entries(TRUE,TRUE,$all[$key]['ENTRIES']);
562       return($res);
563     } 
564     return(array());
565   }
568   /*! \brief Save the currently edited entry 
569     */
570   function _save_entry_edit()
571   {
572     $all    = $this->_get_all_entries();
573     $entry  = $this->edit_entry;
574     $r_entry= &$all[$entry['UNIQID']];
577     if($entry['TYPE'] == "ENTRY"){
578       $r_entry['PARAMETER'] = $this->app_parameter;
579       if($r_entry['STATUS'] != "ADDED"){
580         $r_entry['STATUS'] = "EDITED";
581       } 
582     }
583     if($entry['TYPE'] == "FOLDER"){
584       $r_entry['ICON']   = $this->edit_entry['ICON'];
585       $r_entry['STATUS'] = "EDITED";
586     }
587     $this->dialog = FALSE;
588     $this->edit_entry = array();
589   }
592   /*! \brief prepare the entry with the given ID, to be edited.
593               Read application Parameter from ldap.
594    */
595   function _edit_entry_edit($id)
596   {
597     $all   = $this->_get_all_entries();
598     $entry = $all[$id];
600     $this->app_parameter = array();
601     if($entry['TYPE'] == "ENTRY"){
602       $found = FALSE;
603       foreach($this->apps as $id => $app){
605         if($app['cn'][0] == $entry['NAME']){
606           $found = TRUE;
607           break;
608         }
609       }
610       if($found){
611       
612         /* Create a list of editable parameter */
613         if(isset($app['gosaApplicationParameter'])){
614           for($i = 0 ; $i < $app['gosaApplicationParameter']['count'] ; $i++) {
615             $para = $app['gosaApplicationParameter'][$i];
616             $tmp  = explode(":",$para);
617             $this->app_parameter[$tmp[0]] = $tmp[1];
618           }
619         }
621         /* Overwrite parameters with entry parameters */
622         foreach($entry['PARAMETER'] as $name => $value){
623           $this->app_parameter[$name] = $value;
624         }
625         
626         $this->dialog = TRUE;
627         $this->edit_entry = $entry;
628       }
629     }
631     if($entry['TYPE'] == "FOLDER"){
632       $this->dialog = TRUE;
633       $this->edit_entry = $entry;
634     }
635   }
638   /*! \brief Removes the menu structure from ldap 
639    */
640   function remove_from_parent()
641   {
642     $ldap = $this->config->get_ldap_link();
643     $ldap->cd($this->dn);
644     $ldap->ls("(|(objectClass=gotoSubmenuEntry)(objectClass=FAIbranch)(objectClass=gotoMenuEntry))",$this->dn,array("*"));
645     $a_remove = array();
646     while($attrs = $ldap->fetch()){
647       $a_remove[] = $attrs['dn'];
648     }
649     foreach($a_remove as $remove){
650       $ldap->rmdir_recursive($remove);
651       if (!$ldap->success()){
652         msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_DEL, get_class()));
653       }
654     }
655     $this->_load_menu_structure();
656   }
659   function check()
660   {
661     $message = plugin::check();
662     return($message);
663   }
666   /*! \brief Create missing releases, if there is a release selected \
667               that is currently not part of the menu structure \
668               then create this entry
669    */
670   function _check_missing_release($release)
671   {
672     $release_info = $this->Releases[$release];
674     $parent_id = $this->a_Structure[0]['UNIQID'];
675     $cur = &$this->a_Structure[0]['ENTRIES'];
676     for($i = 0 ; $i < count($release_info['parts']) ; $i ++){
677       $part = $release_info['parts'][$i];
678       $found = FALSE;
679       foreach($cur as $key => $name){
680         if($name['NAME'] == $part){
681           $parent_id = $cur[$key]['UNIQID'];
682           $cur = &$cur[$key]['ENTRIES'];
683           
684           $found =TRUE;
685           break;
686         }
687       }
688       if(!$found){
689         $release           =  array();
690         $release['UNIQID'] = uniqid();
691         $release['PARENT'] = $parent_id;
692         $release['NAME']   = $part;
693         $release['TYPE']   = "RELEASE";
694         $release['ENTRIES']= array();
695         $release['STATUS']   = "ADDED";
696         $release['FAIstate'] =  $release_info['FAIstate'];
697         $cur[] = $release;
698         $i --;
699       }
700     }
701   }
705   /*! \brief Moves a given object ($id) in a specified direction ($dir).
706       @param  String The object ID of the object we want to move
707       @dir    String Move "up" or "down"
708    */
709   function _move_entry($id,$dir)
710   {
711     $all   = $this->_get_all_entries();
712     if($dir == "down"){
713       $to = $this->_get_next($id);
714     } 
715     if($dir == "up"){
716       $to = $this->_get_last($id);
717     }
719     if(!$to){
720       return;
721     }
723     $o_to   = $all[$to];
724     $o_from = $all[$id];
726     if($o_to['PARENT'] == $o_from['UNIQID'] && $dir == "down"){
727       $to    = $this->_get_next($to,$o_from['PARENT']); 
728       $o_to  = $all[$to]; 
729     }
730  
731     /* Target is ENTRY && same BASE, just switch */
732     if($o_to['PARENT'] == $o_from['PARENT'] ){
733       $parent = $all[$o_to['PARENT']];
734       $pos = 0;
735       foreach($parent['ENTRIES'] as $entry){
736         $pos ++;
737         if($entry['UNIQID'] == $to){
738           break;
739         }
740       }
741       if($dir == "up" && $pos > 0){
742         $pos --;
743       }
744       $this->_add_entry($parent['UNIQID'],$o_from,$pos);
745       $this->_remove_entry_id($id);
746       return(TRUE);
747     }
748     return(FALSE);
749   }
752    
753   /*! \brief  Returns the railing object ID of the given object.
754       @return String  The id of the trailing object.
755    */ 
756   function _get_last($id)
757   {
758     $all_l = array_reverse($this->_get_entries_for_release($this->FAIrelease));
759     for($i = 0 ; $i < count($all_l) ; $i ++){
760       if(isset($all_l[$i]['UNIQID']) && $all_l[$i]['UNIQID'] == $id){
761         $i++;
762         break;
763       }
764     }
765     while(isset($all_l[$i]) && !in_array($all_l[$i]['TYPE'],array("ENTRY","FOLDER","CLOSE","OPEN")) && $i < count($all_l)){
766       $i++;
767     }
769     if(!isset($all_l[$i])){
770       return(FALSE);
771     }
773     if(in_array($all_l[$i]['TYPE'],array("CLOSE","OPEN"))){
774       return($all_l[$i]['PARENT']);
775     }     
777     return($all_l[$i]['UNIQID']);
778   }
781   /*! \brief  Returns the following object ID of the given object.
782       @return String  The id of the following object.
783    */ 
784   function _get_next($id,$parent = 0)
785   {
786     $all_l = $this->_get_entries_for_release($this->FAIrelease);
787     for($i = 0 ; $i < count($all_l) ; $i ++){
788       if(isset($all_l[$i]['UNIQID']) && $all_l[$i]['UNIQID'] == $id){
789         $i++;
790         break;
791       }
792     }
793     if($parent != 0){
794       while(isset($all_l[$i]) && $all_l[$i]['PARENT'] != $parent){
795         $i++;
796       }
797     }else{
798       while(isset($all_l[$i]) && !in_array($all_l[$i]['TYPE'],array("ENTRY","FOLDER")) && $i < count($all_l)){
799         $i++;
800       }
801     }
802     if(!isset($all_l[$i])){
803       return(FALSE);
804     }
805     if(in_array($all_l[$i]['TYPE'],array("CLOSE","OPEN"))){
806       return($all_l[$i]['PARENT']);
807     }
808     return($all_l[$i]['UNIQID']);
809   }
814   /* !\brief Handle ui POSTS, like sort up/down/delete
815    */ 
816   function save_object()
817   {
818     foreach($_POST as $name => $value){
820       if(preg_match("/^menu_copy/",$name)){
821         $this->copied_release = $this->FAIrelease;
822         break;
823       }
824       if(preg_match("/^menu_delete/",$name)){
825         $current_rel  = $this->_get_release_key($this->FAIrelease); 
826         $this->_remove_entry_id($current_rel);
827         break;
828       }
829       if(preg_match("/^menu_paste/",$name)){
830         $source_rel   = $this->_get_release_key($this->copied_release); 
831         $current_rel  = $this->_get_release_key($this->FAIrelease);
833         $all = $this->_get_all_entries();
834         $menu = $all[$source_rel]['ENTRIES'];
835     
836         foreach($menu as $entry){
837           if(in_array($entry['TYPE'],array("FOLDER","ENTRY","SEPERATOR"))){
838             $this->_add_entry($current_rel,$entry,-1);
839           }
840         }
841         $this->copied_release = "";
842         break;
843       }
845       if(preg_match("/del_/",$name)){
846         $id = preg_replace("/^del_/","",$name);
847         $this->_remove_entry_id($id);
848         break;
849       }
850       if(preg_match("/app_entry_edit/",$name)){
851         $id = preg_replace("/^app_entry_edit/","",$name);
852         $this->_edit_entry_edit($id);
853         break;
854       }
855       if(preg_match("/up_/",$name)){
856         $id = preg_replace("/^up_/","",$name);
857         $this->_move_entry($id,"up");
858         break;
859       }
860       if(preg_match("/down_/",$name)){
861         $id = preg_replace("/^down_/","",$name);
862         $this->_move_entry($id,"down");
863         break;
864       }
865       if(preg_match("/^parameter_/",$name) && 
866         count($this->edit_entry) && $this->edit_entry['TYPE'] == "ENTRY"){
867         $name = preg_replace("/^parameter_/","",$name);
868         $this->app_parameter[$name] = $value;
869       }
870     }
871     if(isset($_POST['FAIrelease'])){
872       $this->FAIrelease = $_POST['FAIrelease'];
873       $this->_check_missing_release($this->FAIrelease);
874     }
875     
876     $this->applicationList->save_object();
877     $action = $this->applicationList->getAction();
878     if($action['action'] == "edit"){
879         $data= $this->applicationList->getData($action['targets'][0]);
880         $dn= $this->applicationList->getKey($action['targets'][0]);
881         if($data['TYPE'] == 'DEP'){
882             $this->curbase = $dn; 
883         }elseif($data['TYPE'] == 'APP' && isset($_POST['folder'])){
884             $this->_add_app_id($_POST['folder'],$dn); 
885         }
886     }
887     if(isset($_POST['add_to_folder']) && isset($_POST['folder'])){
888       $folder = $_POST['folder'];
889       foreach($_POST as $name => $value){
890         if(preg_match("/^AddApp_[0-9]*$/",$name)){
891           $this->_add_app_id($folder,preg_replace("/^AddApp_/","",$name));   
892         }
893       }
894     }
896     /* Add seperator */
897     if(isset($_POST['add_seperator']) && isset($_POST['menu_folder'])){
898       $folder = $_POST['menu_folder'];
899       $this->_add_seperator($folder);
900     }
902     if(isset($_POST['add_menu_to_folder']) && isset($_POST['menu_folder'])){
903       $folder = $_POST['menu_folder'];
904       $name = $_POST['menu_folder_name'];
905       if(strlen($name) > 0 && preg_match("/[a-z ]/i",$name)){
906         $this->_add_sub_folder($folder,$name);
907       }
908     }
909     if(isset($_POST['app_entry_save'])){ 
910       $this->_save_entry_edit();
911     }
913     if(isset($_FILES['folder_image']) && isset($_POST['folder_image_upload'])){
914       if($_FILES['folder_image']['error'] == 0 && $_FILES['folder_image']['size'] > 0){
915         $this->edit_entry['ICON'] = file_get_contents($_FILES['folder_image']['tmp_name']);
916       }
917     }
919     if(isset($_POST['edit_reset_image'])){
920       $this->edit_entry['ICON'] = "";
921     }
923     if(isset($_POST['app_entry_cancel'])){
924       $this->edit_entry = array();
925       $this->dialog = FALSE;
926     }
927     $this->reload();
928   }
930  
931   /*! \brief Returns the UNIQID of the currently selected release 
932    */ 
933   function _get_release_key($release,$add_if_missing = FALSE)
934   {
935     $release_info = $this->Releases[$release];
937     if($release_info['name'] == "/"){
938       return($this->a_Structure['0']['UNIQID']);
939     }
941     $cur = &$this->a_Structure[0]['ENTRIES'];
942     $s_key = "";
943     $found = FALSE;
944     foreach($release_info['parts'] as $name){
945       foreach($cur as $key => $obj){
946         if($obj['TYPE'] == "RELEASE" && $obj['NAME'] == $name){
947           $s_key = $cur[$key]['UNIQID'];
948           $cur = &$cur[$key]['ENTRIES'];
949           $found = TRUE;
950           break;
951         }
952         $found = FALSE;
953       }
954     }
955     if($found){
956       return($s_key);  
957     }  
958     return(FALSE);
959   }
961  
962   /*! \brief Add a new folder folder to the specified folder id
963       @param  String $folder The folder id in where we want to add the new folder.
964       @param  String $name   The name of the new folder.
965    */ 
966   function _add_sub_folder($folder,$name)
967   {
968     $all = $this->_get_all_entries();
969     if($folder == "BASE"){
970       $folder = $this->_get_release_key($this->FAIrelease,TRUE);
971     }
972     
973     if(isset($all[$folder])){
974       $a_folder = array();
975       $a_folder['STATUS'] = "ADDED";
976       $a_folder['NAME']   = $name;
977       $a_folder['UNIQID'] = uniqid();
978       $a_folder['ENTRIES']= array();
979       $a_folder['PARENT'] = $folder;      
980       $a_folder['TYPE']   = "FOLDER";
981       $a_folder['ICON']   = "";
982       $all[$folder]['ENTRIES'][] = $a_folder;
983     }
984   }
987   /* !\brief  Remove the given id from the menu structure.
988       @param  String  ID to of the entry we want to remove.
989       @return Boolean TRUE on success
990    */
991   function _remove_entry_id($id)
992   {
993     $all = $this->_get_all_entries();
994     if(isset($all[$id])){
995       $all[$id]['STATUS'] = "REMOVED";
996       $all[$id]['ENTRIES'] = array();
997       return(TRUE);
998     }
999     return(FALSE);
1000   }
1002   
1003   /* !\brief  Adds an object to a given folder.
1004       @param  String  The folder where we should add the entry
1005       @param  Array   The entry we want to add.
1006       @param  Array   The position in the destination entry array.
1007    */
1008   function _add_entry($folder_id,$entry,$pos = 0)
1009   {
1010     $all = $this->_get_all_entries();
1012     /* Do not add removed */
1013     if($entry['STATUS'] == "REMOVED"){
1014       return;
1015     }
1017     /* Check if the folder exists 
1018      */
1019     if(isset($all[$folder_id])){
1021       /* Check if the entry we want to add, 
1022           contains su objects.
1023        */
1024       if(!isset($entry['ENTRIES'])){
1025         $entries = array();
1026       }else{
1027         $entries = $entry['ENTRIES'];
1028       }
1029       $folder  = &$all[$folder_id];
1031       /* Prepare the entry to be added.
1032        */
1033       $entry['UNIQID'] = uniqid();     
1034       $entry['PARENT'] = $folder_id;
1035       $entry['ENTRIES']= array();
1036       $entry['STATUS'] = "ADDED";
1037      
1038       /* Append the ebtry to the given folder 
1039           and to the given position \$pos
1040        */ 
1041       $cnt = 0; 
1042       $new = array();
1043       $added =FALSE;
1044       foreach($folder['ENTRIES'] as $key => $obj){
1045         if($obj['STATUS'] == "LOADED"){
1046           $obj['STATUS'] = "EDITED";
1047         }
1048         if($pos == $cnt){
1049           $new[] = $entry;
1050           $added = TRUE;
1051         }
1052         $cnt ++;
1053         $new[] = $obj;
1054       }
1055       if(!$added){
1056         $new[] = $entry;
1057       }
1058       $all[$folder_id]['ENTRIES'] = &$new;
1059  
1060       /* Add sub entries too.
1061        */ 
1062       foreach($entries as $sub){
1063         $this->_add_entry($entry['UNIQID'],$sub,-1);
1064       }
1065       return(TRUE);
1066     }
1067     return(FALSE);
1068   }
1070  
1071   /*! \brief Add the application identified by $app_id to folder $folder_id 
1072       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1073       @param  Integer app_id    The ID of the application which should be added.
1074    */ 
1075   function _add_app_id($folder_id,$app_id)
1076   {
1077     $all = $this->_get_all_entries();
1078     if($folder_id == "BASE"){
1079       $folder_id = $this->_get_release_key($this->FAIrelease);
1080     }
1081     if(isset($all[$folder_id]) && isset($this->apps[$app_id])){
1083       $new = array();
1084       $new['TYPE']  = "ENTRY";
1085       $new['NAME']  = $this->apps[$app_id]['cn'][0];
1086       $new['UNIQID']= uniqid(); 
1087       $new['PARENT']= $folder_id;
1088       $new['PARAMETER']= array();
1089       if(isset($this->apps[$app_id]['description'][0])){
1090         $new['INFO']  = $this->apps[$app_id]['description'][0];
1091       }else{
1092         $new['INFO']  = "";
1093       }
1094       $new['STATUS']= "ADDED";
1095       $all[$folder_id]['ENTRIES'][] = $new;
1096     }
1097   }
1100   /*! \brief Add the application identified by $app_id to folder $folder_id 
1101       @param  String  folder_id The UNIQID of the folder where we want to add the new folder.
1102       @param  Integer app_id    The ID of the application which should be added.
1103    */ 
1104   function _add_seperator($folder_id)
1105   {
1106     $all = $this->_get_all_entries();
1107     if($folder_id == "BASE"){
1108       $folder_id = $this->_get_release_key($this->FAIrelease);
1109     }
1111     if(isset($all[$folder_id])){
1112       $new = array();
1113       $new['TYPE']  = "SEPERATOR";
1114       $new['NAME']  = "SEPERATOR";
1115       $new['UNIQID']= uniqid(); 
1116       $new['PARENT']= $folder_id;
1117       $new['PARAMETER']= array();
1118       $new['STATUS']= "ADDED";
1119       $all[$folder_id]['ENTRIES'][] = $new;
1120     }
1121   }
1124   /*! \brief  Return all entries linear. ($this->a_Structure is a multidimensional array) 
1125       @param  Boolean   $add_tags  If TRUE, OPEN/CLOSE Tags will be appended.
1126                         Used in the smarty template to display logical sperations.
1127       @param  &Array    Start here, Pointer to an array.
1128    */ 
1129   function _get_all_entries($add_tags = FALSE, $skip_release = FALSE, &$cur = NULL)
1130   {
1131     $ret = array();
1132     if($cur == NULL){
1133       $cur = &$this->a_Structure;
1134     }
1136     /* Walk through all entries and append them to our return array 
1137      */
1138     foreach($cur as $key => $entry){
1139       if($skip_release && $entry['TYPE'] == "RELEASE"){
1140         continue;
1141       }    
1142       if($entry['TYPE'] == "ENTRY"){
1143         $found = FALSE;
1144         foreach($this->apps as $app){
1145           if($app['cn'][0] == $entry['NAME']){
1146             $found = TRUE;
1147             if(isset($app['description'][0])){
1148               $entry['INFO'] = "[".$app['description'][0]."]";
1149             }
1150             break;
1151           }
1152         } 
1153         if(!$found){
1154           $entry['INFO'] = "<font color='red'>"._("Not available in release.")."</font>";
1155         }
1156       }
1158       $tmp = $entry;
1159   
1160       /* Recursive resolution of the subentries  
1161          There are two methods.
1162             - Just add sub entries  
1163             - Add sub entries and additionaly add OPEN / CLOSE tags to be able 
1164                 to display logical seperators in the smarty template.
1165        */ 
1166       if(!$add_tags){
1167         $ret[$tmp['UNIQID']] = &$cur[$key];
1168         if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1169           $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1170         }
1171       }else{
1172       
1173         if(isset($tmp['ENTRIES'])){
1174           unset($tmp['ENTRIES']);
1175         }
1176         if($tmp['STATUS'] != "REMOVED"){
1177           $ret[] = $tmp;
1178           if(isset($entry['ENTRIES']) && count($entry['ENTRIES'])){
1179             $add = false;
1180             foreach($entry['ENTRIES'] as $entry){
1181               if($entry['STATUS'] != "REMOVED"){
1182                 $add = TRUE;
1183                 break;
1184               }
1185             }
1187             if($add){
1188               $ret[] = array("TYPE" => "OPEN", "PARENT" => $entry['PARENT']);
1189               $ret = array_merge($ret,$this->_get_all_entries($add_tags,$skip_release,$cur[$key]['ENTRIES']));
1190               $ret[] = array("TYPE" => "CLOSE" , "PARENT" => $entry['PARENT']);
1191             }
1192           }
1193         }
1194       }
1195     }
1196     return($ret);
1197   }
1200   /*! \brief Save this plugin data to ldap.
1201              Save the current menu structure to ldap.
1202    */
1203   function save()
1204   {
1205     $ldap = $this->config->get_ldap_link();
1206     $all = $this->_get_all_entries();
1207     $prio = 0;
1208     $Actions = array("Remove" => array(),"Edit" => array() , "Add" => array());
1210     /* Walk through the menu structure and build up the ldap data object, 
1211         the entry dn and the entry priority.
1212      */
1213     $sep_id = 0;
1214     foreach($all as $entry){
1215       $prio ++;
1216       $cur = $entry;
1217       $dn = "";
1219       /* Build entry dn
1220        */
1221       do{  
1222         if($cur['TYPE'] == "SEPERATOR"){
1223           $sep_id ++;
1224           $dn.= "cn=seperator_".$sep_id.",";
1225         }elseif($cur['TYPE'] == "ENTRY"){
1226           $dn.= "cn=".$cur['NAME'].",";
1227         }elseif($cur['TYPE'] == "FOLDER"){
1228           $dn.= "cn=".$cur['NAME'].",";
1229         }elseif($cur['TYPE'] == "RELEASE"){
1230           $dn.= "ou=".$cur['NAME'].",";
1231         }elseif($cur['TYPE'] == "BASE"){
1232         }
1233         if(!isset($all[$cur['PARENT']])){
1234           $cur = NULL;
1235         }else{
1236           $cur = $all[$cur['PARENT']];
1237         }
1238       }while(is_array($cur));
1240       $cur_dn = $dn.$this->dn;
1241       $attrs = array();
1243       /* Build entry data object.
1244        */
1245       switch($entry['TYPE']){
1246         case "SEPERATOR"    :
1247         { 
1248           $attrs['objectClass'] = array("gotoMenuEntry");
1249           $attrs['cn']          = "seperator_".$sep_id;
1250           $attrs['gosaApplicationPriority'] = $prio;
1251           $attrs['gosaApplicationParameter'] = "*separator*";
1252         }
1253         break;
1254         case "ENTRY"    :
1255         { 
1256           $attrs['objectClass'] = array("gotoMenuEntry");
1257           $attrs['cn']          = $entry['NAME'];
1258           $attrs['gosaApplicationPriority'] = $prio;
1259           $attrs['gosaApplicationParameter'] = array(); 
1260           
1261           foreach($entry['PARAMETER'] as $name => $value){
1262             $attrs['gosaApplicationParameter'][] = $name.":".$value; 
1263           }
1264           if($entry['STATUS'] == "ADDED" && !count($attrs['gosaApplicationParameter'])){
1265             unset($attrs['gosaApplicationParameter']);
1266           } 
1267         }
1268         break;
1269         case "FOLDER"   : 
1270         { 
1271           $attrs['objectClass'] = array("gotoSubmenuEntry");
1272           $attrs['cn']          = $entry['NAME'];
1273           $attrs['gosaApplicationPriority'] = $prio;
1274           if($entry['STATUS'] != "ADDED"){
1275             $attrs['gosaApplicationIcon'] = array();
1276           }
1277           
1278           if(!empty($entry['ICON'])){
1279             $attrs['gosaApplicationIcon']     = $entry['ICON'];
1280           }
1281         }
1282         break;
1283         case "RELEASE"  : 
1284         {
1285           $attrs['ou']            = $entry['NAME'];
1286           $attrs['objectClass']   = array();
1287           $attrs['objectClass'][] = "top";
1288           $attrs['objectClass'][] = "organizationalUnit";
1289           $attrs['objectClass'][] = "FAIbranch";
1290           if(!empty($entry['FAIstate'])){
1291             $attrs['FAIstate']      = $entry['FAIstate'];
1292           }
1293         }
1294         break;
1295       }
1296  
1297       /* Append missing ObjectClasses,  ...  Tagging 
1298        */
1299       if(isset($entry['LDAP_ATTRS'])){
1300         for($i = 0 ; $i < $entry['LDAP_ATTRS']['objectClass']['count']; $i ++){
1301           $oc = $entry['LDAP_ATTRS']['objectClass'][$i];
1302           if(!in_array($oc,$attrs['objectClass'])){
1303             $attrs['objectClass'][] = $oc;
1304           }
1305         }
1306       }
1307   
1308       /* Create an array containing all operations sorted by type. (add,remove...)
1309        */
1310       if($entry['STATUS'] == "LOADED"){
1311         continue;
1312       }
1313       if($entry['STATUS'] == "REMOVED"){
1314         if(isset($entry['DN'])){
1315           $Actions['Remove'][$entry['DN']] = $entry['DN'];
1316         }else{
1317           $Actions['Remove'][$cur_dn] = $cur_dn;
1318         }
1319       }
1320       if($entry['STATUS'] == "EDITED"){
1321         $Actions['Edit'][$cur_dn] = $attrs;
1322       }
1323       if($entry['STATUS'] == "ADDED"){
1324         $Actions['Add'][$cur_dn] = $attrs;
1325       }
1326     }
1328     /* First remove entries
1329      */
1330     $ldap = $this->config->get_ldap_link();
1331     $ldap->cd($this->config->current['BASE']);
1332     foreach($Actions['Remove'] as $dn){
1333       $ldap->cd($dn);
1334       $ldap->cat($dn);
1335       if($ldap->count()){
1336         $ldap->rmdir_recursive($dn);
1337         if (!$ldap->success()){
1338           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_DEL, get_class()));
1339         }
1340       }
1341     }
1342     
1343     /* Add new entries
1344      */
1345     foreach($Actions['Add'] as $dn => $data){
1346       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1347       $ldap->cd($dn);
1348       $ldap->cat($dn);
1349       if(!$ldap->count()){
1350         $ldap->add($data);
1351         if (!$ldap->success()){
1352           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_ADD, get_class()));
1353         }
1354       }
1355     }
1357     /* Modify entries
1358      */
1359     foreach($Actions['Edit'] as $dn => $data){
1360       $this->tag_attrs($data,$dn,$this->gosaUnitTag);
1361       $ldap->cd($dn);
1362       $ldap->cat($dn);
1363       if($ldap->count()){
1364         $ldap->modify($data);
1365         if (!$ldap->success()){
1366           msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, get_class()));
1367         }
1368       }
1369     }
1371     $this->_load_menu_structure();
1372   }
1375   /*! \brief  Return plugin informations for acl handling  
1376       @return Array containing all plugin ACL informations
1377    */ 
1378   static function plInfo()
1379   {
1380     return (array(
1381           "plShortName"   => _("Applications"),
1382           "plDescription" => _("Group applications"),
1383           "plSelfModify"  => FALSE,
1384           "plDepends"     => array(),
1385           "plPriority"    => 7,
1386           "plSection"     => array("administration"),
1387           "plCategory"    => array("groups"),
1388           "plProvidedAcls"=> array(
1389             "gosaMemberApplication"     => _("Application"),
1390             "FAIrelease"                => _("Release"),
1391             "gosaApplicationParameter"  => _("Application parameter"))
1392           ));
1393   }
1396   /* \brief   Prepare this plugin to be copied.
1397               Adapt all required attributes from the source object.
1398               In this case, update the menu structure too, mark all elements
1399                as newly added, so they will be saved in save();
1400    */
1401   function PrepareForCopyPaste($source)
1402   {
1403     plugin::PrepareForCopyPaste($source);
1404    
1405     $tmp = new appgroup($this->config,$source['dn']);
1406     $this->is_account = TRUE;
1407     $this->a_Structure = $tmp->a_Structure;
1408     $all = $this->_get_all_entries();
1409     foreach($all as &$entry){
1410       if(isset($entry['STATUS'])){
1411         $entry['STATUS'] = "ADDED";
1412       }
1413     }
1414   }
1417   /*! \brief  Save HTML posts in multiple edit mode
1418    */
1419   function multiple_save_object()
1420   {
1421     if(isset($_POST['group_apps_multi'])){
1422       $this->save_object(); 
1423       plugin::multiple_save_object();    
1424   
1425       /* Get posts */
1426       foreach(array("apps") as $attr){
1427         if(isset($_POST['use_'.$attr])) {
1428           $this->multi_boxes[] = $attr;
1429         }
1430       }
1431     }
1432   }
1433   
1435   /*! \brief  Return values used in multiple edit mode.
1436               Some values can be modified for multiple 
1437               groups at the same time.
1438       @return Array  All values that support multiple edit.
1439    */
1440   function get_multi_edit_values()
1441   {
1442     $ret = plugin::get_multi_edit_values();
1444     if(in_array("apps",$this->multi_boxes)){
1445       $ret['gosaApplicationParameter'] = $this->gosaApplicationParameter;
1446       $ret['Categories']               = $this->Categories;
1447       $ret['gosaMemberApplication']    = $this->gosaMemberApplication;
1448       $ret['FAIrelease']               = $this->FAIrelease;
1449       $ret['appoption']                = $this->appoption;
1450     }
1451     return($ret);
1452   }
1454 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1455 ?>