Code

A lot of changes.
[gosa.git] / gosa-plugins / goto-ng / admin / newConfigManagement / class_newConfigManagement.inc
1 <?php
3 /*! \brief  This class allows to manage backend config items and packages.
4  */
5 class newConfigManagement extends plugin
6 {
7     var $initTime;
8     var $plHeadline = "Config management";
9     var $plDescription = "Config management";
11     var $selectedContainer;
13     var $dataModel = NULL;
14     var $listing = NULL;
16     var $cfgItemMap = NULL;
18     var $addableContainerItems = array();
19     var $currentObject = NULL;
22     /*! \brief  Initialize the plugin and finally update the data model.
23      */
24     function __construct($config, $dn)
25     {
26         $this->config = &$config;
27         $this->listing = new ConfigManagementListing($this->config, get_userinfo(), $this);
29         // Load the template engine and tell her what template
30         //  to use for the HTML it produces.
31         $this->TemplateEngine = new TemplateEngine($config);
33         // Preset item config - with Distribution and Release objects.
34         $items = array();
35         $items['root']['container'] = array('Distribution');
36         $items['root']['name'] = '/';
37         $items['root']['description'] = _('Root');
39         $items['Distribution']['container'] = array('Release');
40         $items['Distribution']['name'] = 'Distribution';
41         $items['Distribution']['description'] = _('Distribution');
42         $items['Distribution']['options']['name']['description'] = _("Name");
43         $items['Distribution']['options']['name']['default'] = "";
44         $items['Distribution']['options']['name']['value'] = "";
45         $items['Distribution']['options']['name']['required'] = true;
46         $items['Distribution']['options']['name']['type'] = 'string';
47         $items['Distribution']['options']['name']['display'] = _('Name');
48         $items['Distribution']['options']['type']['description'] = _("Distribution type");
49         $items['Distribution']['options']['type']['default'] = "deb";
50         $items['Distribution']['options']['type']['value'] = "deb";
51         $items['Distribution']['options']['type']['values'] = array("deb" => 'deb', "rpm" => 'rpm');
52         $items['Distribution']['options']['type']['required'] = true;
53         $items['Distribution']['options']['type']['type'] = 'combobox';
54         $items['Distribution']['options']['type']['display'] = _('Distribution type');
56         $items['Release']['container'] = array('Release', '__CFG_ITEMS__');
57         $items['Release']['name'] = 'Release';
58         $items['Release']['description'] = _('Release');
59         $items['Release']['options']['name']['description'] = _("Name");
60         $items['Release']['options']['name']['default'] = "";
61         $items['Release']['options']['name']['value'] = "";
62         $items['Release']['options']['name']['required'] = true;
63         $items['Release']['options']['name']['type'] = 'string';
64         $items['Release']['options']['name']['display'] = _('Name');
66         $this->installationMethods = array();
67         $this->installationMethods['root']['description'] = _('root');
68         $this->installationMethods['root']['name'] = 'root';
69         $this->installationMethods['root']['title'] = _('root');
70         $this->installationMethods['root']['items']['Distribution'] = &$items['Distribution'];
71         $this->installationMethods['root']['items']['Release'] = &$items['Release'];
72         $this->installationMethods['root']['items']['root'] = &$items['root'];
74         // Request an update of the data model
75         $this->loadInstallationMethods();
76         $this->updateDataModel();
77         $this->listing->setListingTypes($this->getListingTypes());
79         $this->setInstallMethod('root');
81     }
84     /*! \brief  Sets the installation method to the given method.
85      *          Updates the template engine and adds the initial root
86      *           object for the selected method.
87      *  @param  The method to use.
88      *  @return TRUE on success else FALSE.
89      */
90     function setInstallMethod($str)
91     {
92         if(!isset($this->installationMethods[$str])){
93             $this->invalidInstallMethod =TRUE;
94             $this->errorMessage = sprintf(_("Invalid installation method %s selected!"), bold($str));
95             msg_dialog::display(_("Setup"), $this->errorMessage, ERROR_DIALOG);
96             return(FALSE);
97         }else{
98    
99             $this->TemplateEngine->setTemplate($str.".tpl");
100             $this->invalidInstallMethod =FALSE;
101             $this->TemplateEngine->load($this->itemConfig);
102         }
103     }
106     /*! \brief  Updates all distributions, releases, packages and items in the dataModel
107      *          Load information from the backend.
108      */
109     function updateDataModel()
110     {
111         // Recreate the data model, to have a clean and fresh instance.
112         $this->dataModel = new ConfigManagementDataModel();
114         // Load distributions 
115         $rpc = $this->config->getRpcHandle();
116         $res = $rpc->getDistributions();
118         if(!$rpc->success()){
119             msg_dialog::display(_("Error"), sprintf(_("Failed to load distributions: %s"), $rpc->get_error()),ERROR_DIALOG);
120             return(NULL);
121         }else{
122             foreach($res as $dist){
123                 $dist['__removeable'] = TRUE;
124                 $this->dataModel->addItem('Distribution','/root', $dist['name'], $dist);
125                 if(isset($dist['releases'])){
126                     foreach($dist['releases'] as $release){
127                         $distPath = "/root/{$dist['name']}";
128                         $release['__removeable'] = TRUE;
129                         $this->dataModel->addItem('Release',$distPath, $release['name'], $release);
130                     }
131                 }
132             }
133         }
134     }
137     /*! \brief  Keep track of posted values and populate those 
138      *           which are interesting for us.
139      *          Inspects the _POST and _GET values.
140      */
141     function save_object()
142     {
143         // Update the listing class, this is necessary to get post
144         //  actions from it.
145         $this->listing->save_object();
147         // Get the selected distribution and release from the listing widget.
148         $cont = $this->listing->getSelectedContainer();
149         if(isset($_POST['ROOT'])){
150             $this->setCurrentContainer('/root');
151         }elseif(isset($_POST['BACK'])){
153             $path = $this->selectedContainer;
154             if($this->dataModel->itemExistsByPath($path)){
155                 $data = $this->dataModel->getItemByPath($path);
156                 if($data['parentPath']){
157                     $this->setCurrentContainer($data['parentPath']);
158                 }
159             }
160         }else{
161             $this->setCurrentContainer($cont);
162         }
163     }
166     /*! \brief  Load extended sub-objecte like 'config items' or 'packages'
167      *           for the given release path.
168      *  @param  String  The release path to load sub-objects for.
169      *  @return NULL 
170      */
171     function updateItemList($path)
172     {
173         // Fist get Item and check if it is an release 
174         if($this->dataModel->itemExistsByPath($path)){
175             $data = $this->dataModel->getItemByPath($path);
177             // Only releases can contain config-items.
178             if($data['type'] == 'Release' && $data['status'] != "fetched"){
180                 $rpc = $this->config->getRpcHandle();
181                 $res = $rpc->listConfigItems($data['name']);
182                 if(!$rpc->success() || !$res){
183                     msg_dialog::display(_("Error"), 
184                             sprintf(_("Failed to load distributions: %s"), 
185                                 $rpc->get_error()),ERROR_DIALOG);
186                 }else{
188                     // Sort entries by path length 
189                     $sLen = array();
190                     foreach($res as $itemPath => $type){
191                         $sLen[strlen($itemPath)."_".$itemPath] = $itemPath;
192                     }
193                     uksort($sLen, "strnatcasecmp");   
195                     // Walk through each entry and then try to add it to the model
196                     foreach($sLen as $unused => $itemPath){
198                         // Do not add the root element '/'
199                         if($itemPath == "/") continue;
201                         $type = $res[$itemPath];
202                 
203                         // Root installation objects do not have a name, so we use 'root' here.
204                         $targetPath = trim($path."/".$itemPath);
206                         // Remove trailing and duplicated slashes
207                         $targetPath = rtrim($targetPath, '/');
208                         $targetPath = preg_replace("/\/\/*/","/", $targetPath);
210                         // Extract the items name
211                         $name = preg_replace("/^.*\//","", $targetPath);
212     
213                         // Cleanup the path and then add the item.
214                         $targetPath = preg_replace("/[^\/]*$/","", $targetPath);
215                         $targetPath = rtrim($targetPath,'/');
216                         $this->dataModel->addItem($type, $targetPath, $name, 
217                                 array(    
218                                         '__editable' => TRUE,
219                                         '__removeable' => TRUE,
220                                         '__path' => $itemPath,
221                                         '__release' => $path
222                                     ),'-' ); 
223                     }
224                     $this->dataModel->setItemStatus($path, 'fetched');
225                 }
226             }
227         }
228     }
231     /*! \brief  Sets the currently selected container and item path. 
232      *  @param  String  The path of the container to set.
233      *  @param  String  The path of the item to set.
234      *  @return 
235      */
236     function setCurrentContainer($cont)
237     {
238         $this->selectedContainer = $cont;
240         // Update list of items within the selected container. 
241         $this->updateItemList($this->selectedContainer);
243         // Transfer checked values back to the listing class.
244         $this->listing->setContainers($this->getContainerList());
245         $this->listing->setContainer($cont);
247         // Update the list of addable sub objects
248         $item = $this->dataModel->getItemByPath($cont);
249         if(isset($this->itemConfig[$item['type']]['container'])){
250             $this->addableContainerItems = $this->itemConfig[$item['type']]['container'];
251         }else{
252             $this->addableContainerItems = array();
253         }
254         #print_a($this->installationMethods);
255         #print_a($this->itemConfig);
256         #echo $item['type'];
257         #print_a($this->addableContainerItems);
258     }
261     /*! \brief  Generate the HTML content for this plugin.
262      *          Actually renders the listing widget..
263      */
264     function execute()
265     {
266         // Get the selected release and store it in a session variable
267         //  to allow the configFilter to access it and display the
268         //  packages and items.
269         $res = $this->listing->execute();
270         $this->listing->setListingTypes($this->getListingTypes());
271         return($res);
272     }
275     /*! \brief      Returns a list of items which will then be displayed 
276      *               in the management-list. 
277      *              (The management class calls this method from its execute())
278      *  @return     Array   A list of items/objects for the listing. 
279      */
280     function getItemsToBeDisplayed()
281     {
282         $path = $this->selectedContainer;
283         $item = $this->dataModel->getItemByPath($path);
284         return($item);
285     }
288     /*! \brief  Returns a simply list of all distributions.
289      *          This list will then be used to generate the entries of the 
290      *           ItemSelectors in the listing class.
291      */
292     function getContainerList()
293     {
294         $data = $this->dataModel->getItemByPath('/root');
295         $res = array();
296         $res["/root"] = array("name" => "/", "desc" => "");
297         $res = array_merge($res,$this->__recurseItem($data, array('Distribution','Release')));
298         return($res);
299     }
302     /*! \brief  Recursivly wlks through an item and collects all path and name info.
303      *          The reult can then be used to fill the ItemSelector.
304      *  @param  Array   The Item to recurse. 
305      *  @param  Array   The type of of objects to collect. 
306      *  @param  String  The parent path prefix which should be removed.
307      *  @return Array   An array containing Array[path] = name
308      */
309     function __recurseItem($item, $types, $parent = "")
310     {
311         $res = array();
312         if(1 ||  in_array($item['type'], $types)){
313             $path = preg_replace("/".preg_quote($parent,'/')."/","",$item['path']);
314             $res[$path] = array('name' => $item['name'],'desc'=>$item['type']);
315         }
316         if(count($item['children'])){
317             foreach($item['children'] as $child){
318                 $res = array_merge($res, $this->__recurseItem($child, $types, $parent));
319             }
320         }
321         return($res);
322     }
325     /*! \brief  Intializes this plugin
326      *          All available installation methods will be loaded
327      */
328     function loadInstallationMethods()
329     {
330         // Reset erros
331         $this->rpcError = $this->initFailed = FALSE;
333         // Load configuration via rpc.
334         $rpc = $this->config->getRpcHandle();
336         // Populate install methods on success.
337         $res = $rpc->getSupportedInstallMethods();
338         if(!$rpc->success()){
339             $this->rpcError = TRUE;
340             $this->errorMessage = $rpc->get_error();;
341             return;
342         }
343         if(!count($res)){
344             $this->errorMessage = _("No selectable install methods returned!");
345             msg_dialog::display(_("Setup"), $this->errorMessage , ERROR_DIALOG);
346             $this->initFailed = TRUE;
347             return;
348         }else{
349             $this->installationMethods = array_merge($this->installationMethods, $res);
350             $this->cfgItemMap = array();
351             $this->itemConfig = array();
352             $rootElements = array();
353             foreach($this->installationMethods as $method => $items){
354                 foreach($items['items'] as $itemName => $item){
355                     $this->cfgItemMap[$itemName] = $method;
356                     $this->itemConfig[$itemName] = &$this->installationMethods[$method]['items'][$itemName];
357  
358                     foreach($item['container'] as $cont){
359                         if($cont == "__CFG_ITEMS__"){
360                             $this->installationMethods[$method]['items'][$itemName]['container'] = &$rootElements; 
361                         }
362                     }
363                 
364                     // This enables us to create the first level of config items when 
365                     //  a release is selected.
366                     if($item['name'] == "/" && $itemName != 'root'){
367                         $rootElements = array_merge($rootElements, $item['container']);
368                     }
369                 }
370             }
371         }
372     }
375     /*! \brief   Returns a info list about all items we can manage,
376      *            this used to fill the listings <objectType> settings.
377      *  @return Array   An array with item info.
378      */
379     function getListingTypes()
380     {
381         $types= array();
382         $types['Distribution']['objectClass'] = 'Distribution';
383         $types['Distribution']['label'] = _('Distribution');
384         $types['Distribution']['image'] = 'images/lists/edit.png';
385         $types['Distribution']['category'] = 'Device';
386         $types['Distribution']['class'] = 'Device';
388         $types['Release']['objectClass'] = 'Release';
389         $types['Release']['label'] = _('Release');
390         $types['Release']['image'] = 'images/lists/delete.png';
391         $types['Release']['category'] = 'Device';
392         $types['Release']['class'] = 'Device';
394         $types['Component']['objectClass'] = 'Component';
395         $types['Component']['label'] = _('Component');
396         $types['Component']['image'] = 'plugins/users/images/select_user.png';
397         $types['Component']['category'] = 'Device';
398         $types['Component']['class'] = 'Device';
400         foreach($this->installationMethods as $method => $items){
401             foreach($items['items'] as $itemName => $item){
402                 $types[$itemName]['objectClass'] = $itemName;
403                 $types[$itemName]['label'] = $item['name'];
404                 $types[$itemName]['image'] = 'plugins/fai/images/fai_script.png';
405                 $types[$itemName]['category'] = 'Device';
406                 $types[$itemName]['class'] = 'Device';
407             }
408         }
410         return($types);
411     }
414     /*! \brief      The plugins ACL and plugin-property definition. 
415      *  @return 
416      */
417     public static function plInfo()
418     {
419         return (array(
420                     "plShortName"   => _("Config management"),
421                     "plDescription" => _("Config management"),
422                     "plSelfModify"  => FALSE,
423                     "plDepends"     => array(),
424                     "plPriority"    => 0,
425                     "plSection"     => array("administration"),
426                     "plCategory"    => array(
427                         "newConfigManagement" => array("description"  => _("Config management"),
428                             "objectClass"  => "FAKE_OC_newConfigManagement")),
429                     "plProvidedAcls"=> array()
430                     ));
431     }
434     /*! \brief  Acts on open requests.
435      *          (This action is received from the ConfigManagementListing class.)
436      *  @param  Array   The items ids. (May contain multiple ids)
437      *  @return
438      */
439     function openEntry($ids)
440     {
441         $id = $ids[0];
442         $item = $this->dataModel->getItemById($id);
443         $this->setCurrentContainer($item['path']);
444         return;
445     }
449     /*! \brief  Removes an entry from the listing.
450      */
451     function removeEntry($ids)
452     {
454         $item = $this->dataModel->getItemById($ids[0]);
456         // Is an config item.
457         if(isset($this->cfgItemMap[$item['type']])){
458             $release = preg_replace("/^.*\//","",$item['values']['__release']);
459             $path = $item['values']['__path'];
460             $rpc = $this->config->getRpcHandle();
461             $rpc->removeConfigItem($release, $path);
462             if(!$rpc->success()){
463                 msg_dialog::display(_("Error"), sprintf(_("Failed to remove: %s"), $rpc->get_error()),ERROR_DIALOG);
464                 return(NULL);
465             }else{
466                 $this->dataModel->removeItem($item['path']);
467             }
468         }else{
469             echo $item['type']." - are not handled yet!";
470         }
471     }
474     /*! \brief      Edits a selected list item.
475      */
476     function editEntry($ids)
477     {
478         // Update the template engine to use another type of item and
479         //  some other values.
480         $item = $this->dataModel->getItemById($ids[0]);
481         if(isset($this->cfgItemMap[$item['type']])){
482             $release = preg_replace("/^.*\//","",$item['values']['__release']);
483             $path = $item['values']['__path'];
484             $method = $this->cfgItemMap[$item['type']];
486             // Load item values on demand
487             if($item['status'] == '-'){
488                 $rpc = $this->config->getRpcHandle();
489                 $item['values']['itemValues'] = $rpc->getConfigItem($release, $path);
490                 $this->dataModel->setItemStatus($item['path'], 'fetched');
491                 $this->dataModel->setItemValues($item['path'], $item['values']);
492             }
494             $this->setInstallMethod($method);
495             $this->TemplateEngine->setValues($item['type'],$item['values']['itemValues']);
496             $this->listing->setDialogObject($this->TemplateEngine);
497             $this->currentObject = $item;
498         }
499     }
502     /*! \brief  Initiates the creation of a new item
503      */
504     function newEntry($type)
505     {
506         // We've to add a config item
507         if(isset($this->cfgItemMap[$type])){
508             $method = $this->cfgItemMap[$type];
509             $this->setInstallMethod($method);
510             $this->TemplateEngine->setValues($type,array());
511             $this->listing->setDialogObject($this->TemplateEngine);
512             $this->currentObject = NULL;
513         }elseif($type == 'Distribution'){
514             $this->setInstallMethod('Distribution');
515             $this->TemplateEngine->setValues($type,array());
516             $this->listing->setDialogObject($this->TemplateEngine);
517             $this->currentObject = NULL;
518         }elseif($type == 'Release'){
519         }
520     }
523     /*! \brief  Extracts the item-path out of a path.
524      *          e.g. /debian/squeeze/test/module -> /test/module
525      */
526     function getItemPath($fullPath)
527     {
528         $fPath = $fullPath.'/';
529         while(preg_match("/\//", $fPath)){
530             $fPath = preg_replace("/\/[^\/]*$/","", $fPath);
531             $item = $this->dataModel->getItemByPath($fPath);
532             if(isset($this->cfgItemMap[$item['type']])){
533                 return(preg_replace("/".preg_quote($item['parentPath'],'/')."/", "", $fullPath));
534             }
535         }
536         return(NULL);
537     }
540     /*! \brief  Extracts the releaes path out of a path.
541      *          e.g. /debian/squeeze/test/module -> /debian/squeeze
542      */
543     function getReleasePath($fullPath)
544     {
545         $fullPath.='/';
546         while(preg_match("/\//", $fullPath)){
547             $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
548             $item = $this->dataModel->getItemByPath($fullPath);
549             if($item['type'] == 'Release'){
550                 return($fullPath);
551             }
552         }
553         return(NULL);
554     }
555    
556  
557     function saveItemChanges()
558     {
559         $item = $this->currentObject;
561         // Null means a new  object has to be added.        
562         if($item == NULL){
564             // Save template engine modifications
565             $this->TemplateEngine->save_object();
566             $release = preg_replace("/^.*\//","", $this->getReleasePath($this->selectedContainer));
567             $type = $this->TemplateEngine->getItemType();
569             // Collect modified values
570             $values = array();
571             foreach($this->TemplateEngine->getWidgets() as $w){
572                 $values[$w->getName()] = $w->getValue();
573             }
574            
575             // Create the elements target path  
576             $path = $this->getItemPath($this->selectedContainer)."/".$values['name'];
578             // Add the new item
579             $rpc = $this->config->getRpcHandle();
580             $res = $rpc->setConfigItem($release, $path, $type, $values);
581             if(!$rpc->success()){
582                 msg_dialog::display(_("Error"), sprintf(_("Failed to load distributions: %s"), $rpc->get_error()),ERROR_DIALOG);
583                 return(NULL);
584             }else{
586                 // We've successfully added the item, now add it to the tree.
587                 $this->dataModel->addItem($type, $this->selectedContainer, $values['name'], 
588                         array(    
589                             '__editable' => TRUE,
590                             '__removeable' => TRUE,
591                             '__path' => $path,
592                             '__release' => $this->getReleasePath($this->selectedContainer)
593                             ), '-' );
595                 // Finally - close the dialog. 
596                 $this->listing->clearDialogObject();
597             }
598         }else{
600             // Collect modified values.
601             $this->TemplateEngine->save_object();
602             $values = array();
603             foreach($this->TemplateEngine->getWidgets() as $w){
604                 $values[$w->getName()] = $w->getValue();
605             }
607             // Get the items release & path info
608             $release = preg_replace("/^.*\//","",$item['values']['__release']);
609             $path = $item['values']['__path'];
610     
611             // Write the modifications back to the server.
612             $rpc = $this->config->getRpcHandle();
613             $res = $rpc->setConfigItem($release, $path, $item['type'], $values);
614             if(!$rpc->success()){
615                 msg_dialog::display(_("Error"), sprintf(_("Failed to load distributions: %s"), $rpc->get_error()),ERROR_DIALOG);
616                 return(NULL);
617             }else{
618         
619                 // Update the data model
620                 $item['values']['itemValues'] = $values;
621                 $this->dataModel->setItemValues($item['path'], $item['values']);
622                 $this->listing->clearDialogObject();
623             }
624         }
625     }
626     function remove_lock() {}
630 ?>