Code

Some backport from trunk
[gosa.git] / gosa-core / include / class_pluglist.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 pluglist 
24 {
25     // The id of the last registered plugin id 
26     var $index= 0;
28     var $config= NULL;
29     var $ui= NULL;
31     // Contains a list of the paths for all registered plugins.
32     var $dirlist= array();
34     // Seems to be used in the help menu to generate an overview.
35     var $headlines = array();
36     // Remember stuff in here.
37     var $silly_cache= array();
39     // The pluglist keeps track of all registered plugins.
40     // (Registered plugins are those we are able to access)
41     var $pluginList = array();
43     // Some cache vars to avoid regenration of the menus.   
44     var $pathMenu = "";
45     var $menu= "";
46     var $iconmenu= "";
48     // Classes plInfo list
49     var $info = array();
50     var $registeredMenuEntries = array();
51     var $registeredPathEntries = array();
52     var $registeredIconEntries = array();
53     var $registeredShortCutEntries = array();
56     function getRegisteredMenuEntries ()
57     {
58         return($this->registeredMenuEntries);
59     }
62     function getRegisteredPathEntries ()
63     {
64         return($this->registeredPathEntries);
65     }
68     function getRegisteredIconEntries ()
69     {
70         return($this->registeredIconEntries);
71     }
74     function getRegisteredShortCutEntries ()
75     {
76         return($this->registeredShortCutEntries);
77     }
80     function pluglist(&$config, &$ui)
81     {
82         $this->ui= &$ui;
83         $this->config= &$config;
84         $this->loadPluginList();
85     }
87     function loadPluginList()
88     {
89         $this->pluginList = array();
91         /* Fill info part of pluglist */
92         $classes= get_declared_classes();
93         foreach ($classes as $cname){
94             $cmethods = get_class_methods($cname);
95             if (in_array_ics('plInfo',$cmethods)){
96                 $this->info[$cname]= call_user_func(array($cname, 'plInfo'));
97             }
98         }
100         if(!session::is_set('maxC')){
101             session::set('maxC',"RO0K9CzEYCSAAOtOICCFhEDBKGSKANyHMKDHAEwFLNTJILwEMODJYPgMRA0F9IOPSPUKNEVCUKyDBAHNbIWFJOIP");
102         }
103         //
104         //   // Now generate menu - usually they are cached
105         //   $this->gen_menu();
106         //   $this->show_iconmenu();
107         //   $this->genPathMenu();
108     }
111     /*! \brief    Tries to register a plugin in the pluglist
112      *            Checks existence and ACL for the given plugin.
113      *            Returns true in case of success else false. 
114      */
115     function registerPlugin(&$plug)
116     {
117         global $class_mapping;
119         // Clean ACL string, we do not want any spaces or lines breaks here. 
120         $plug['ACL'] = trim($plug['ACL']);
122         // Clean ACL string, we do not want any spaces or lines breaks here.
123         $acl = trim($plug['ACL']);
124         if(preg_match("/,/",$acl)){
125             $acls = explode(",",$acl);
126         }else{
127             $acls = array($acl);
128         }
129         foreach($acls as $key => $aclEntry){
130             $aclEntry = trim($aclEntry);
131             $tmp = preg_replace("/[^a-z0-9\/:]/i","",$aclEntry);
133             // Check if cleaned 'acl' tag doesn't match the configured one from the gosa.conf.
134             // Display a notification to tell the user that there is something wrong.
135             if($tmp != $aclEntry){
136                 trigger_error("Please check acl='{$aclEntry}' tag for plugin '{$plug['CLASS']}' in your gosa.conf, it contains invalid characters!" );
137             }
138             $acls[$key] = $tmp;
139         }
140         $plug['ACL'] = implode(',',$acls);
143         // Check class
144         if (!isset($plug['CLASS'])){
145             msg_dialog::display(
146                     _("Configuration error"),
147                     _("The configuration format has changed: please run the setup again!"),
148                     FATAL_ERROR_DIALOG);
149             exit();
150         }
151         if (!plugin_available($plug['CLASS'])){
152             return(FALSE);
153         }
154         if (!$this->check_access($plug['ACL'])){
155             return(FALSE);
156         }
157         $this->dirlist[$this->index] = dirname($class_mapping[$plug['CLASS']]);
158         $this->pluginList[$this->index] = $plug['CLASS'];
159         $this->index++;
160         return(TRUE);
161     }
164     /*! \brief  Check whether we are allowed to modify the given acl or not..
165      *          This function is used to check which plugins are visible.
166      *          
167      *  @param  The acl tag to check for, eg.   "users/user:self", "systems", ...
168      *  @return Boolean TRUE on success else FALSE
169      */
170     function check_access($aclname)
171     {
172         if (isset($this->silly_cache[$aclname])) {
173             return $this->silly_cache[$aclname];
174         }
176         // Split given acl string into an array. e.g. "user,systems" => array("users","systems");
177         $acls_to_check = array();
178         if(preg_match("/,/",$aclname)){
179             $acls_to_check = explode(",",$aclname);
180         }else{
181             $acls_to_check = array($aclname);
182         }
184         foreach($acls_to_check as $acl_to_check){
186             // Remove spaces and line breaks.
187             $acl_to_check = trim($acl_to_check);
188             $acl_to_check = preg_replace("/ /","",$acl_to_check);
190             if($acl_to_check == "none"){
191                 $this->silly_cache[$aclname]= TRUE;
192                 return(TRUE);
193             }
195             /* Check if the given acl tag is only valid for self acl entries  
196              *          <plugin acl="users/user:self" class="user"...  
197              */ 
198             if(preg_match("/:self$/",$acl_to_check)){
199                 $acl_to_check = preg_replace("/:self$/","",$acl_to_check);      
200                 if(strpos($acl_to_check,"/")){
201                     if($this->ui->get_permissions($this->ui->dn,$acl_to_check,"") != ""){
202                         $this->silly_cache[$aclname]= TRUE;
203                         return(TRUE);
204                     }
205                 }else{
206                     if($this->ui->get_category_permissions($this->ui->dn,$acl_to_check,"") != ""){
207                         $this->silly_cache[$aclname]= TRUE;
208                         return(TRUE);
209                     }
210                 }
211             }else{
213                 // No self acls. Check if we have any acls for the given ACL type 
214                 $deps = $this->ui->get_module_departments($acl_to_check,TRUE);
215                 if(count($deps)){
216                     $this->silly_cache[$aclname]= TRUE;
217                     return TRUE;
218                 }
219             }
220         }
222         $this->silly_cache[$aclname]= FALSE;
223         return (FALSE);
224     }
228     /*! \brief    Generate the GOsa Main-Menu here (The menu on the left), 
229      *             this usually only done once during login.
230      *            -----------------------------------------------------------------
231      *            Do NOT add style changes here manually, use the style.css or 
232      *             if you prefer create your own theme!!
233      *            -----------------------------------------------------------------
234      */
235     function gen_menu()
236     {
237         if ($this->menu == ""){
239             // First load the menu plugins and try to register them in the pluglist
240             //  if this fails for some reason, then remove the plugin from the menu.
241             if(isset($this->config->data['MENU'])){
242                 foreach($this->config->data['MENU'] as $section => $plugins){
243                     foreach($plugins as $id => $plug){
244                         if(!$this->registerPlugin($this->config->data['MENU'][$section][$id])){ 
245                             unset($this->config->data['MENU'][$section][$id]); 
246                         }
247                     }
249                     // Remove empty sections 
250                     if(count($this->config->data['MENU'][$section]) == 0){ 
251                         unset($this->config->data['MENU'][$section]); 
252                     } 
253                 }
254             }
256             $disabledPlugins = $this->config->configRegistry->getDisabledPlugins();
258             $cfg= $this->config->data['MENU'];
259             $menu = "";
260             foreach ($cfg as $headline => $plug){
263                 if(!count($plug)) continue;
265                 $menu.= "\n        <div class='menu'>";
266                 $menu.= "\n          <ul>";
267                 $menu.= "\n            <li class='menu-header'>"._($headline)."</li>";
268                 $id = 0;
269                 foreach ($plug as $info){
271                     // The Plugin has been deactivated for some reason, perhabs a missing ldap schema.
272                     if(isset($disabledPlugins[$info['CLASS']])) continue;
274                     // Used to detect the last element in the menu
275                     $id ++;
277                     list($index, $title, $desc, $icon) = $this->getPlugData($info['CLASS']);
278                     $class= "";
279                     if($id == count($plug)) $class=" class='menu-last' ";
280                     $menu .=  "\n            <li id='plugMenuId_{$index}' $class onClick='return openPlugin({$index});'>".$title."</li>";
282                     $this->registeredMenuEntries[] = $index;
283                 }
284                 $menu.= "\n          </ul>";
285                 $menu.= "\n          <div style='font-size:0'>&nbsp;</div>";
286                 $menu.= "\n        </div>\n";
287                 $menu.= "\n        <div style='font-size:0'>&nbsp;</div>";
288                 $menu.= "\n        <div class='v-spacer'></div>\n";
289             }
290             if(count($this->registeredMenuEntries)){
291                 $this->menu = "\n<div class='navigation'>\n{$menu}</div>";
292             }
294             // Add javascript method to print out warning messages while leaving an unsaved form.
295             // We do it in here to get the string translated.
296             $this->menu .=  
297                 "\n      <script language='javascript' type='text/javascript'>".
298                 "\n        function openPlugin(id, plugin){".
299                 "\n          if(plugin){ ".
300                 "\n             plugin = '&pluginTab=' +  plugin".
301                 "\n          }else{".
302                 "\n             plugin = '';".
303                 "\n          }".
304                 "\n          return question(\""._("You are currently editing a database entry. Do you want to discard the changes?")."\",".
305                 "\n            \"main.php?plug=\" + id + \"&reset=1\" + plugin);".
306                 "\n        }".
307                 "\n      </script>\n"; 
308         }
310         // Use javascript to mark the currently selected plugin.
311         $menu = $this->menu;
312         if(isset($_GET['plug'])){
313             $menu.= 
314                 "\n      <script language='javascript' type='text/javascript'>".
315                 "\n        if($('plugMenuId_".$_GET['plug']."')){".
316                 "\n          $('plugMenuId_".$_GET['plug']."').className= 'current'".
317                 "\n        }".
318                 "\n      </script>\n";
319         }
321         // Return the generated/cached gosa menu.
322         return ($menu);
323     }
326     /*! \brief    Generate the GOsa Icon-Menu here, this usually only done once during
327      *             login.
328      *            -----------------------------------------------------------------
329      *            Do NOT add style changes here manually, use the style.css or 
330      *             if you prefer create your own theme!!
331      *            -----------------------------------------------------------------
332      */
333     function show_iconmenu()
334     {
335         $add_hr =FALSE;
336         if ($this->iconmenu == ""){
338             $disabledPlugins = $this->config->configRegistry->getDisabledPlugins();
340             $cfg= $this->config->data['MENU'];
341             foreach ($cfg as $headline => $plug){
342                 $col= 0;
344                 $this->iconmenu .= "\n        <div class='clear'></div>";
345                 if($add_hr){
346                     $add_hr = FALSE;
347                     $this->iconmenu .= "\n        <hr>";
348                 }
349                 $this->iconmenu .= "\n        <h3 class='icon-menu-title'>". _($headline)."</h3>";
351                 foreach ($plug as $info){
353                     // Get Plugin info
354                     list($index, $title, $desc, $icon) = $this->getPlugData($info['CLASS']);
355                     $this->registeredIconEntries[] = $index;
357                     // The Plugin has been deactivated for some reason, perhabs a missing ldap schema.
358                     if(isset($disabledPlugins[$info['CLASS']])) continue;
360                     // Add a seperating row
361                     if (($col % 4) == 0){ 
362                         $this->iconmenu .= "\n        <div class='clear'></div>";
363                     }
365                     $this->iconmenu.= "\n        <div class='icon-menu-item' style='width: 25%;' onclick='openPlugin({$index})'>";
366                     $this->iconmenu.= "\n          ".image($icon);
367                     $this->iconmenu.= "\n          <div class='dsc'>";
368                     $this->iconmenu.= "\n            <h1>{$title}</h1>";
369                     $this->iconmenu.= "\n            <p>{$desc}</p>";
370                     $this->iconmenu.= "\n          </div>";
371                     $this->iconmenu.= "\n        </div>";
372                     $col++ ;
373                 }
374                 $add_hr = TRUE;
375             }
376         }
377         return ($this->iconmenu);
378     }
381     /*! \brieg    Generates and the path menu (the one on the upper right) and keeps
382      *             the generated HTML content, so we are not forced to generate it on every 
383      *             page request.
384      *            (See <pathMenu> of your gosa.conf)
385      */
386     function genPathMenu()
387     {
388         if(empty($this->pathMenu)){
390             $disabledPlugins = $this->config->configRegistry->getDisabledPlugins();
392             // Now load the icon menu and try to register the plugins in the pluglist
393             //  if this fails for some reason, then remove the plugins from the menu.
394             if(isset($this->config->data['SHORTCUTMENU'])){
395                 foreach($this->config->data['SHORTCUTMENU'] as $id => $plugin){
396                     if(!$this->registerPlugin($this->config->data['SHORTCUTMENU'][$id])){
397                         unset($this->config->data['SHORTCUTMENU'][$id]); 
398                     } 
399                 }
400             }
402             // Now load the path menu and try to register the plugins in the pluglist
403             //  if this fails for some reason, then remove the plugin from the menu.
404             if(isset($this->config->data['PATHMENU'])){
405                 foreach($this->config->data['PATHMENU'] as $id => $plugin){
406                     if(!$this->registerPlugin($this->config->data['PATHMENU'][$id])){
407                         unset($this->config->data['PATHMENU'][$id]); 
408                     } 
409                 }
410             }
412             $this->pathMenu = 
413                 "\n        <div class='plugin-path'>".
414                 "\n          <ul class='path-navigation'>";
416             // Check if we've at least one entry defined ih the iconmenu
417             if(isset($this->config->data['SHORTCUTMENU'])){
418                 $icfg= &$this->config->data['SHORTCUTMENU'];
419                 $rcfg = array_reverse($icfg);
420                 foreach($rcfg as $id => $plug){
421                     list($index, $title, $desc, $icon, $shortIcon) = $this->getPlugData($plug['CLASS']);
422                     $this->registeredShortCutEntries[] = $index;
424                     // The Plugin has been deactivated for some reason, perhabs a missing ldap schema.
425                     if(isset($disabledPlugins[$plug['CLASS']])) continue;
427                     $cssClass= (!isset($rcfg[$id+1]))? 'left' : 'left right-border';
428                     $this->pathMenu.= "            
429                         <li class='{$cssClass}' onClick='openPlugin({$index})' title='{$title}'>".
430                         image(get_template_path($shortIcon))."</li>";
431                 }
432             }
434             // Place the navigator part, this will be replaced during runtime.
435             $this->pathMenu .= "\n            %navigator%";
437             // Check if we've at least one entry defined ih the pathmenu
438             if(isset($this->config->data['PATHMENU'])){
439                 $cfg= &$this->config->data['PATHMENU'];
440                 $rcfg = array_reverse($cfg);
441                 foreach($rcfg as $id => $plug){
442                     list($index, $title, $desc, $icon) = $this->getPlugData($plug['CLASS']);
443                     $this->registeredPathEntries[] = $index;
445                     // The Plugin has been deactivated for some reason, perhabs a missing ldap schema.
446                     if(isset($disabledPlugins[$plug['CLASS']])) continue;
448                     $this->pathMenu.= "\n            <li class='right left-border' onClick='openPlugin({$index})'>{$title}</li>";
449                 }
450             }
451             $this->pathMenu.= "\n          </ul>";
452             $this->pathMenu.= "\n        </div>";
453         }
455         $menu = pathNavigator::getCurrentPath();
456         return(preg_replace("/%navigator%/", $menu, $this->pathMenu)); 
457     }
460     /*! \brief    Returns additional info for a given class name, like 
461      *             plugin-icon, title, description and the index of the element 
462      in the pluglist which uses this class.
463      */
464     function getPlugData($class)
465     {
466         global $class_mapping;
467         $vars= get_class_vars($class);
468         $plHeadline= _($vars['plHeadline']);
469         $plDescription= _($vars['plDescription']);
470         $plIcon = (isset($vars['plIcon'])) ? $vars['plIcon']: "plugin.png";
471         $plShortIcon = (isset($vars['plShortIcon'])) ? $vars['plShortIcon']: "plugin.png";
473         $index= $this->get_index($class);
475         /* Check if class is available. If the class doesn't exists display error symbol
476          *  to avoid that a user clicks on a non existing plugin
477          */
478         if(!$vars){
479             $plHeadline = $plDescription = _("Unknown");
480             $plIcon = "error.png";
481             $index = '';
482         } 
484         // Detect the correct position of the plugin icon
485         if(!preg_match("/\//",$plIcon)){
486             $image= get_template_path("plugins/".preg_replace('%^.*/([^/]+)/[^/]+$%', '\1', 
487                         $class_mapping[$class])."/images/$plIcon");
488         }else{
489             $image = $plIcon; 
490         }
491         // Detect the correct position of the plugin icon
492         if(!preg_match("/\//",$plShortIcon)){
493             $shortImage= get_template_path("plugins/".preg_replace('%^.*/([^/]+)/[^/]+$%', '\1', 
494                         $class_mapping[$class])."/images/$plShortIcon");
495         }else{
496             $shortImage = $plShortIcon; 
497         }
498         return(array($index, $plHeadline, $plDescription, $image, $shortImage));
499     }
502     /*! \brief    Returns the installation path of a plugin.
503      *            e.g. '../plugins/admin/mimetypes'
504      */
505     function get_path($index)
506     {
507         if(!isset($this->dirlist[$index])){
508             return ("");
509         }
510         return ("../".$this->dirlist[$index]);
511     }
514     /*! \brief    Returns the plugins id for a given class.
515      */
516     function get_index($class)
517     {
518         return (array_search($class, $this->pluginList));
519     }
522     /*! \brief    Returns the plugins id for a given class.
523      */
524     function get_class($index)
525     {
526         return($this->pluginList[$index]);
527     }
530     /*! \brief  This function checks if we are allowed to view the plugin with the given id 
531      *
532      *  @param  $plug_id  Integer  The ID of the plugin.
533      *  @return Boolean   TRUE if we are allowed to view the plugin else FASLE
534      */
535     function plugin_access_allowed($plug_id)
536     {
537         return(isset($this->pluginList[$plug_id]) && $plug_id != "");
538     }
541     /*! \brief  Force the menu to be recreated 
542      */
543     function reset_menus()
544     {
545         $this->menu = "";
546         $this->iconmenu ="";
547     }
550     /*! \brief    Generates an array containing plugin names (headlines) and theirs ids.
551      *            This is just used in the helpviewer.php  
552      */
553     function gen_headlines()
554     {
555         $ret = array();
556         if(count($this->headlines) == 0){
557             foreach($this->config->data['MENU'] as $headline => $plugins){
558                 foreach( $plugins as $id => $plug){
559                     if (plugin_available($plug['CLASS'])){
560                         $attrs = (get_class_vars($plug['CLASS']));
561                         $ret[$id]['HEADLINE'] = $headline;
562                         $ret[$id]['NAME']         = $attrs['plHeadline'];
563                     }
564                 }
565             }
566             $this->headlines = $ret;
567         }
568         return($this->headlines);
569     }
571 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
572 ?>