Code

Updated class config mangement
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 19 May 2011 06:35:34 +0000 (06:35 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 19 May 2011 06:35:34 +0000 (06:35 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@20868 594d385d-05f5-0310-b6e9-bd551577e9d8

gosa-plugins/goto-ng/admin/newConfigManagement/DeviceConfig-list.xml
gosa-plugins/goto-ng/admin/newConfigManagement/class_ConfigManagement.inc [new file with mode: 0644]
gosa-plugins/goto-ng/admin/newConfigManagement/class_newConfigManagement.inc [deleted file]

index 99bc644f86ee34df72a492b9465ce50e357cbc38..883cfb1dcb5b860ea6fe324af0eb6975064f6836 100644 (file)
@@ -79,6 +79,7 @@
       <name>remove</name>
       <type>entry</type>
       <image>images/lists/trash.png</image>
+      <acl>ConfigManagement/cfgItem[w]</acl>
       <label>Remove item</label>
     </action>
 
diff --git a/gosa-plugins/goto-ng/admin/newConfigManagement/class_ConfigManagement.inc b/gosa-plugins/goto-ng/admin/newConfigManagement/class_ConfigManagement.inc
new file mode 100644 (file)
index 0000000..0ee36f1
--- /dev/null
@@ -0,0 +1,980 @@
+<?php
+
+/*! \brief  This class allows to manage backend config items and packages.
+ */
+class newConfigManagement extends plugin
+{
+    var $initTime;
+    var $plHeadline = "Config management";
+    var $plDescription = "Config management";
+    var $plIcon = "plugins/goto/images/ConfigManagement.png";
+
+    var $selectedContainer;
+
+    var $dataModel = NULL;
+    var $listing = NULL;
+
+    var $cfgItemMap = NULL;
+
+    var $addableContainerItems = array();
+    var $currentObject = NULL;
+    var $itemsPerMethod = NULL;
+
+    var $initFailed = TRUE;
+    var $initialized = FALSE;
+    var $errorMessage = "";
+
+
+    /*! \brief  Initialize the plugin and finally update the data model.
+     */
+    function __construct($config, $dn)
+    {
+        $this->config = &$config;
+        $this->listing = new ConfigManagementListing($this->config, get_userinfo(), $this);
+
+        // Load the template engine and tell her what template
+        //  to use for the HTML it produces.
+        $this->TemplateEngine = new TemplateEngine($config);
+    }
+
+    
+    function init()
+    {
+        $success = TRUE;
+        $success &= $this->loadInstallationMethods();
+        $success &= $this->updateDataModel();
+        $this->initFailed = !$success;
+        if($success){
+            $this->initialized = TRUE;
+            $this->listing->setListingTypes($this->getListingTypes());
+            $this->setCurrentContainer('/root');
+        }
+    }
+
+
+    /*! \brief  Intializes this plugin
+     *          All available installation methods will be loaded
+     */
+    function loadInstallationMethods()
+    {
+        // Get static installation methods.
+        $this->installationMethods = json_decode(file_get_contents(get_template_path('goto/Config/root.json', TRUE)), TRUE);
+
+        // Load configuration via rpc.
+        $rpc = $this->config->getRpcHandle();
+
+        // Load some base install parameters
+        $res = $rpc->getSupportedBaseInstallMethods();
+        $baseInstTypes = $installationTypes = $installationMethods = array();
+        foreach($res as $type => $data){
+            $baseInstTypes[$type] = $type;
+            if(isset($data['repositories'])){
+                foreach($data['repositories'] as $m){
+                    $installationTypes[$m] = $m;
+                }
+            }
+            if(isset($data['methods'])){
+                foreach($data['methods'] as $m){
+                    $installationMethods[$m] =$m;
+                }
+            }
+        }
+
+        $res = $rpc->getSupportedInstallMethods();
+        if(!$rpc->success()){
+            $this->errorMessage = $rpc->get_error();;
+            return(FALSE);
+        }
+
+        // Populate install methods on success.
+        if(!count($res)){
+            $this->errorMessage = _("No selectable install methods returned!");
+            return(FALSE);
+        }else{
+
+            // Merge result with hard coded methods
+            $this->installationMethods = array_merge($this->installationMethods, $res);
+
+            // Walk through entries and create useful mappings.
+            $this->cfgItemMap = array();
+            $this->itemConfig = array();
+            $this->itemsPerMethod = array();
+            $rootElements = array('Release');
+            foreach($this->installationMethods as $method => $items){
+                foreach($items['items'] as $itemName => $item){
+                    $this->itemsPerMethod[$method][] = $itemName;
+                    $this->cfgItemMap[$itemName] = $method;
+                    $this->itemConfig[$itemName] = &$this->installationMethods[$method]['items'][$itemName];
+                    // This enables us to create the first level of config items when 
+                    //  a release is selected.
+                    if($item['name'] == "/" && $itemName != 'root'){
+                        $rootElements = array_merge($rootElements, $item['container']);
+                    }
+                }
+            }
+        }
+
+        // Fill replacements
+        $map['%ROOT_CFG_ITEMS'] = &$rootElements;
+        $map['%INSTALLATION_TYPES'] = array('dep' => 'dep', 'rpm' => 'rpm');
+        $map['%INSTALLATION_METHODS'] = array('puppet' => 'puppet');
+        $map['%BASE_INSTALLATION_METHODS'] = array('preseed' => 'preseed');
+        $this->itemConfig = $this->__fillPlaceholder($this->itemConfig, $map);
+        return(TRUE);
+    }
+
+
+    /*! \brief  Fill in replacements in the itemConfig
+     *          Some values are dynamic and cannot be hardcoded, a placeholder is
+     *           used in this case in the deinition file root.json. 
+     */
+    function __fillPlaceholder($data, $placeholder)
+    {
+        foreach($data as $name => $sData){
+            if(is_array($sData)){
+                $data[$name] = $this->__fillPlaceholder($data[$name], $placeholder);
+            }elseif(is_string($sData) && isset($placeholder[$sData])){
+                $data[$name] = &$placeholder[$sData];
+            }
+        }
+        return($data);
+    }
+
+
+    /*! \brief  Updates all distributions, releases, packages and items in the dataModel
+     *          Load information from the backend.
+     */
+    function updateDataModel()
+    {
+        // Recreate the data model, to have a clean and fresh instance.
+        $this->dataModel = new ConfigManagementDataModel();
+
+
+        // Load templates from the backend and append them on the base 
+        $rpc = $this->config->getRpcHandle();
+        $res = $rpc->installListTemplates();
+        if(!$rpc->success()){
+            $this->errorMessage = sprintf(_("Failed to load templates: %s"), $rpc->get_error());
+            return(FALSE);
+        } 
+        foreach($res as $tName => $tData){
+            $tData['name'] = $tName;
+            $this->dataModel->addItem('Template','/root', $tName, $tData, '-');
+        }
+
+
+        // Load distributions 
+        $rpc = $this->config->getRpcHandle();
+        $res = $rpc->getDistributions();
+        if(!$rpc->success()){
+            $this->errorMessage = sprintf(_("Failed to load distributions: %s"), $rpc->get_error());
+            return(FALSE);
+        }else{
+            if(is_array($res)){
+
+                foreach($res as $dist){
+           
+                    // Simple strings 
+                    $values = array();
+                    foreach(array('origin','installation_method', 'installation_method','debian_security',
+                            'debian_volatile', 'name', 'mirror_sources', 'managed', 'path') as $attr){
+                        $values[$attr] = $dist[$attr];
+                    }
+
+                    // Boxed strings
+                    foreach(array('type') as $attr){
+                        $values[$attr] = $dist[$attr]['name'];
+                    }
+
+                    // Arrays
+                    foreach(array('releases', 'architectures', 'components', 'sections') as $attr){
+                        $values[$attr] = array();
+                        if(is_array($dist[$attr])){
+                            foreach($dist[$attr] as $aEntry){
+                                $values[$attr][] = $aEntry['name'];
+                            }
+                        }
+                    }
+        
+                    $this->dataModel->addItem('Distribution','/root', $dist['name'], $values);
+
+                    if(isset($dist['releases'])){
+
+                        // Sort releases by name length
+                        $sort = array();
+                        foreach($dist['releases'] as $id => $release){
+                            $sort[strlen($release['name']) . $release['name']]  = $id;
+                        }
+                        uksort($sort, "strnatcasecmp");   
+
+                        // Append release tags
+                        foreach($sort as $id){
+                            $release = $dist['releases'][$id];
+                            $rPath = $release['name'];
+                            $rPath = "/root/{$dist['name']}/$rPath";
+                            $rName = preg_replace("/^.*\//","", $rPath);
+                            $rPath = preg_replace("/\/[^\/]*$/","", $rPath);
+                            $values = array('name' => $rName);
+
+                            if(!$this->dataModel->itemExistsByPath($rPath)){
+                                trigger_error("Invalid release name '{$rName}' in path '{$rPath}' received! Skipping entry!");
+                            }else{
+                                $id = $this->dataModel->addItem('Release',$rPath, $rName, $values);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return(TRUE);
+    }
+
+
+    /*! \brief  Keep track of posted values and populate those 
+     *           which are interesting for us.
+     *          Inspects the _POST and _GET values.
+     */
+    function save_object()
+    {
+        // Update the listing class, this is necessary to get post
+        //  actions from it.
+        $this->listing->save_object();
+
+        // Get the selected distribution and release from the listing widget.
+        $cont = $this->listing->getSelectedContainer();
+        if(isset($_POST['ROOT'])){
+            $this->setCurrentContainer('/root');
+        }elseif(isset($_POST['BACK'])){
+            $path = $this->selectedContainer;
+            if($this->dataModel->itemExistsByPath($path)){
+                $data = $this->dataModel->getItemByPath($path);
+                if($data['parentPath']){
+                    $this->setCurrentContainer($data['parentPath']);
+                }
+            }
+        }else{
+            $this->setCurrentContainer($cont);
+        }
+    }
+
+
+    /*! \brief  Load extended sub-objecte like 'config items' or 'packages'
+     *           for the given release path.
+     *  @param  String  The release path to load sub-objects for.
+     *  @return NULL 
+     */
+    function updateItemList($path)
+    {
+        // Fist get Item and check if it is an release 
+        if($this->dataModel->itemExistsByPath($path)){
+            $data = $this->dataModel->getItemByPath($path);
+
+            // Only releases can contain config-items.
+            if($data['type'] == 'Release' && $data['status'] != "fetched"){
+
+                // Request all config items for the selected release via rpc.
+                $rpc = $this->config->getRpcHandle();
+                $releasePath = $this->getReleasePart($path);
+                $res = $rpc->listConfigItems($releasePath);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"),sprintf(_("Failed to load distributions: %s"),$rpc->get_error()),ERROR_DIALOG);
+                    return;
+                }else{
+            
+                    if(!$res) return;
+
+                    // Sort entries by path length 
+                    $sLen = array();
+                    foreach($res as $itemPath => $type){
+                        $sLen[strlen($itemPath)."_".$itemPath] = $itemPath;
+                    }
+                    uksort($sLen, "strnatcasecmp");   
+
+                    // Walk through each entry and then try to add it to the model
+                    foreach($sLen as $unused => $itemPath){
+
+                        // Do not add the root element '/'
+                        if($itemPath == "/") continue;
+
+                        $type = $res[$itemPath];
+                
+                        // Append the items-path to the current path to create the 
+                        //  effective item path in the data model.
+                        $targetPath = trim($path."/".$itemPath);
+
+                        // Remove trailing and duplicated slashes
+                        $targetPath = rtrim($targetPath, '/');
+                        $targetPath = preg_replace("/\/\/*/","/", $targetPath);
+
+                        // Extract the items name
+                        $name = preg_replace("/^.*\//","", $targetPath);
+    
+                        // Cleanup the path and then add the item.
+                        $targetPath = preg_replace("/[^\/]*$/","", $targetPath);
+                        $targetPath = rtrim($targetPath,'/');
+                        $this->dataModel->addItem($type, $targetPath, $name,array(),'-' ); 
+                    }
+                    $this->dataModel->setItemStatus($path, 'fetched');
+                }
+            }
+        }
+    }
+
+
+    /*! \brief  Sets the currently selected container and item path. 
+     *  @param  String  The path of the container to set.
+     *  @param  String  The path of the item to set.
+     *  @return 
+     */
+    function setCurrentContainer($cont)
+    {
+        // Do nothing while the service wasn't initialized.
+        if(!$this->initialized) return;
+
+        $this->selectedContainer = $cont;
+
+        // Update list of items within the selected container. 
+        $this->updateItemList($this->selectedContainer);
+
+        // Transfer checked values back to the listing class.
+        $this->listing->setContainers($this->getContainerList());
+        $this->listing->setContainer($cont);
+
+        // Update the list of addable sub objects
+        $this->addableContainerItems = $this->getAddableContainersPerPath($cont);
+    }
+
+
+    function getAddableContainersPerPath($path)
+    {
+        $currentItem = $this->dataModel->getItemByPath($path);
+        $method = $this->getInstallationMethodPerPath($path);
+
+        // Get allowed items for the currently selected method 
+        //  merge in root elements, they are allowed everywhere.
+        $allowedItems = $this->itemsPerMethod[$method];
+        $allowedItems = array_merge($allowedItems, $this->itemsPerMethod['root']);
+
+        // Get addable items
+        $possibleItems = $this->itemConfig[$currentItem['type']]['container'];
+        return(array_unique(array_intersect($allowedItems, $possibleItems)));
+    }
+
+    
+    function getInstallationMethodPerPath($path)
+    {
+        $path .= '/';
+        while(preg_match("/\//", $path)){
+            $path = preg_replace("/\/[^\/]*$/","",$path);
+            $item = $this->dataModel->getItemByPath($path);
+            if(isset($item['values']['installation_method'])){
+                return($item['values']['installation_method']);
+            }
+        }
+        return('root'); 
+    }
+
+
+    /*! \brief  Generate the HTML content for this plugin.
+     *          Actually renders the listing widget..
+     */
+    function execute()
+    {
+        // Request an update of the data model
+        if(!$this->initialized){
+            $this->init();
+        }
+
+        // Act on init fails
+        if($this->initFailed){
+            $smarty = get_smarty();
+            $smarty->assign('error', $this->errorMessage);
+            return($smarty->fetch(get_template_path('rpcError.tpl', TRUE)));
+        }else{
+
+            // Get the selected release and store it in a session variable
+            //  to allow the configFilter to access it and display the
+            //  packages and items.
+            $res = $this->listing->execute();
+            $this->listing->setListingTypes($this->getListingTypes());
+            return($res);
+        }
+    }
+
+
+    /*! \brief      Returns a list of items which will then be displayed 
+     *               in the management-list. 
+     *              (The management class calls this method from its execute())
+     *  @return     Array   A list of items/objects for the listing. 
+     */
+    function getItemsToBeDisplayed()
+    {
+        $path = $this->selectedContainer;
+        $item = $this->dataModel->getItemByPath($path);
+        return($item);
+    }
+
+
+    /*! \brief  Returns a simply list of all distributions.
+     *          This list will then be used to generate the entries of the 
+     *           ItemSelectors in the listing class.
+     */
+    function getContainerList()
+    {
+        $data = $this->dataModel->getItemByPath('/root');
+        $res = array();
+        $res["/root"] = array("name" => "/", "desc" => "");
+        $res = array_merge($res,$this->__recurseItem($data));
+        return($res);
+    }
+
+
+    /*! \brief  Recursivly wlks through an item and collects all path and name info.
+     *          The reult can then be used to fill the ItemSelector.
+     *  @param  Array   The Item to recurse. 
+     *  @param  Array   The type of of objects to collect. 
+     *  @param  String  The parent path prefix which should be removed.
+     *  @return Array   An array containing Array[path] = name
+     */
+    function __recurseItem($item, $parent = "")
+    {
+        $res = array();
+        $path = preg_replace("/".preg_quote($parent,'/')."/","",$item['path']);
+        $res[$path] = array('name' => $item['name'],'desc'=>$item['type']);
+        if(count($item['children'])){
+            foreach($item['children'] as $child){
+                $res = array_merge($res, $this->__recurseItem($child, $parent));
+            }
+        }
+        return($res);
+    }
+
+
+    /*! \brief   Returns a info list about all items we can manage,
+     *            this used to fill the listings <objectType> settings.
+     *  @return Array   An array with item info.
+     */
+    function getListingTypes()
+    {
+        $types= array();
+        $types['Distribution']['objectClass'] = 'Distribution';
+        $types['Distribution']['label'] = _('Distribution');
+        $types['Distribution']['image'] = 'images/lists/edit.png';
+        $types['Distribution']['category'] = 'Device';
+        $types['Distribution']['class'] = 'Device';
+
+        $types['Release']['objectClass'] = 'Release';
+        $types['Release']['label'] = _('Release');
+        $types['Release']['image'] = 'images/lists/delete.png';
+        $types['Release']['category'] = 'Device';
+        $types['Release']['class'] = 'Device';
+
+        $types['Component']['objectClass'] = 'Component';
+        $types['Component']['label'] = _('Component');
+        $types['Component']['image'] = 'plugins/users/images/select_user.png';
+        $types['Component']['category'] = 'Device';
+        $types['Component']['class'] = 'Device';
+
+        foreach($this->installationMethods as $method => $items){
+            foreach($items['items'] as $itemName => $item){
+                $types[$itemName]['objectClass'] = $itemName;
+                $types[$itemName]['label'] = $item['name'];
+                $types[$itemName]['image'] = 'plugins/fai/images/fai_script.png';
+                $types[$itemName]['category'] = 'Device';
+                $types[$itemName]['class'] = 'Device';
+            }
+        }
+
+        return($types);
+    }
+
+
+    /*! \brief      The plugins ACL and plugin-property definition. 
+     *  @return 
+     */
+    public static function plInfo()
+    {
+        return (array(
+                    "plShortName"   => _("Config management"),
+                    "plDescription" => _("Config management"),
+                    "plSelfModify"  => FALSE,
+                    "plDepends"     => array(),
+                    "plPriority"    => 0,
+                    "plSection"     => array("administration"),
+                    "plCategory"    => array(
+                        "ConfigManagement" => array("description"  => _("Config management"),
+                            "objectClass"  => "FAKE_OC_ConfigManagement")),
+                    "plProvidedAcls"=> array(
+                            "cfgItem" => _("Config item")
+                        )
+                    ));
+    }
+
+
+    /*! \brief  Acts on open requests.
+     *          (This action is received from the ConfigManagementListing class.)
+     *  @param  Array   The items ids. (May contain multiple ids)
+     *  @return
+     */
+    function openEntry($ids)
+    {
+        $id = $ids[0];
+        $item = $this->dataModel->getItemById($id);
+        $this->setCurrentContainer($item['path']);
+        return;
+    }
+
+
+
+    /*! \brief  Removes an entry from the listing.
+     */
+    function removeEntry($ids)
+    {
+        foreach($ids as $id){
+            $item = $this->dataModel->getItemById($id);
+
+            // Is an config item.
+            if($this->cfgItemMap[$item['type']] != 'root'){
+                $release = $this->getReleasePart($item['path']);
+                $path = $this->getItemPath($item['path']);
+                $rpc = $this->config->getRpcHandle();
+                $rpc->removeConfigItem($release, $path);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to remove: %s"), $rpc->get_error()),ERROR_DIALOG);
+                    return(NULL);
+                }else{
+                    $this->dataModel->removeItem($item['path']);
+                }
+            }else{
+
+                // Remove distribution
+                if($item['type'] == 'Distribution'){
+
+                    $dist = $this->getDistributionPart($item['path']);
+                    $rpc = $this->config->getRpcHandle();
+                    $rpc->removeDistribution($dist, array('recursive' => TRUE));
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the distribution: %s. Error was: %s"), 
+                                    $dist, $rpc->get_error()), ERROR_DIALOG);
+                        return(NULL);
+                    }else{
+                        $this->dataModel->removeItem($item['path']);
+                    }
+                }elseif($item['type'] == 'Release'){
+
+                    // Remove release
+                    $release = preg_replace("/^.*\//","", $this->getReleasePart($item['path']));
+                    $rpc = $this->config->getRpcHandle();
+                    $rpc->removeRelease($release, array('recursive' => TRUE));
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the release: %s. Error was: %s"), 
+                                    $release, $rpc->get_error()),ERROR_DIALOG);
+                        return(NULL);
+                    }else{
+                        $this->dataModel->removeItem($item['path']);
+                    }
+
+                }elseif($item['type'] == 'Template'){
+
+                    // Remove Template
+                    $rpc = $this->config->getRpcHandle();
+                    $rpc->installRemoveTemplate($item['name']);
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the template: %s. Error was: %s"), 
+                                    $release, $rpc->get_error()),ERROR_DIALOG);
+                        return(NULL);
+                    }else{
+                        $this->dataModel->removeItem($item['path']);
+                    }
+                }else{
+                    trigger_error($item['type']." - are not handled yet!");
+                }
+            }
+        }
+    }
+
+
+    /*! \brief  Returns a list of used item names for a given path.
+     */
+    function getUsedNamesForPath($path)
+    {
+        $item = $this->dataModel->getItemByPath($path);
+        $names = array();
+        foreach($item['children'] as $path => $data){
+            $names[] = $data['name'];
+        }
+        return($names);
+    }
+
+
+    /*! \brief      Edits a selected list item.
+     */
+    function editEntry($ids)
+    {
+        $item = $this->dataModel->getItemById($ids[0]);
+        $release = $this->getReleasePart($item['path']);
+        $path = $this->getItemPath($item['path']);
+        $method = $this->cfgItemMap[$item['type']];
+
+        // Load item values on demand
+        if($this->cfgItemMap[$item['type']] != 'root'){
+            if($item['status'] == '-'){
+                $rpc = $this->config->getRpcHandle();
+                $res = $rpc->getConfigItem($release, $path);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to load config item details: %s"), $rpc->get_error()),ERROR_DIALOG);
+                    return;
+                }else{
+                    $item['values'] = $res;
+                    $this->dataModel->setItemStatus($item['path'], 'fetched');
+                    $this->dataModel->setItemValues($item['path'], $item['values']);
+                }
+            }
+        }elseif($item['type'] == 'Template'){
+            if($item['status'] == '-'){
+                $rpc = $this->config->getRpcHandle();
+                $res = $rpc->installGetTemplate($item['name']);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to load template details: %s"), $rpc->get_error()),ERROR_DIALOG);
+                    return;
+                }else{
+                    $item['values'] = $res;
+                    $this->dataModel->setItemStatus($item['path'], 'fetched');
+                    $this->dataModel->setItemValues($item['path'], $item['values']);
+                }
+            }
+        }
+
+        $this->TemplateEngine->load($this->itemConfig);
+        $this->TemplateEngine->setTemplate($method.".tpl");
+        $this->TemplateEngine->editItem($item['type'],$item['values']);
+        $this->listing->setDialogObject($this->TemplateEngine);
+        $this->currentObject = $item;
+    }
+
+
+    /*! \brief  Initiates the creation of a new item
+     */
+    function newEntry($type)
+    {
+        // We've to add a config item
+        $this->TemplateEngine->load($this->itemConfig);
+        if($this->cfgItemMap[$type] != 'root'){
+            $method = $this->cfgItemMap[$type];
+            $this->TemplateEngine->setTemplate($method.".tpl");
+            $this->TemplateEngine->createItem($type,array());
+            $this->listing->setDialogObject($this->TemplateEngine);
+            $this->currentObject = NULL;
+        }else{
+            $this->TemplateEngine->setTemplate("root.tpl");
+            $this->TemplateEngine->createItem($type,array());
+            $this->listing->setDialogObject($this->TemplateEngine);
+            $this->currentObject = NULL;
+        }
+    }
+
+
+    /*! \brief  Extracts the item-path out of a path.
+     *          e.g. /debian/squeeze/test/module -> /test/module
+     */
+    function getItemPath($fullPath)
+    {
+        $fPath = $fullPath.'/';
+        while(preg_match("/\//", $fPath)){
+            $fPath = preg_replace("/\/[^\/]*$/","", $fPath);
+            $item = $this->dataModel->getItemByPath($fPath);
+            if(in_array($item['type'], array('Release', 'Distribution', 'root'))){
+                return(preg_replace("/".preg_quote($item['path'],'/')."/", "", $fullPath));
+            }
+        }
+        return(NULL);
+    }
+
+
+    /*! \brief  Extracts the releaes path out of a path.
+     *          e.g. /debian/squeeze/test/module -> /debian/squeeze
+     */
+    function getReleasePath($fullPath)
+    {
+        $fullPath.='/';
+        while(preg_match("/\//", $fullPath)){
+            $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
+            $item = $this->dataModel->getItemByPath($fullPath);
+            if($item['type'] == 'Release'){
+                return($fullPath);
+            }
+        }
+        return(NULL);
+    }
+  
+    
+    /*! \brief  Extracts the distribution path out of a path.
+     *          e.g. /root/debian/squeeze/test/module -> /root/debian
+     */
+    function getDistributionPath($fullPath)
+    {
+        $fullPath.='/';
+        while(preg_match("/\//", $fullPath)){
+            $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
+            $item = $this->dataModel->getItemByPath($fullPath);
+            if($item['type'] == 'Distribution'){
+                return($fullPath);
+            }
+        }
+        return(NULL);
+    }
+
+
+    /*! \brief  Extracts the distribution-part out of a path.
+     *          e.g. /root/debian/squeeze/test/module -> debian
+     */
+    function getDistributionPart($fullPath)
+    {
+        return(trim(preg_replace("#^/root/#","", $this->getDistributionPath($fullPath)), '/'));
+    }
+    
+    
+    /*! \brief  Extracts the release-part out of a path.
+     *          e.g. /root/debian/squeeze/test/module -> squeeze/test
+     */
+    function getReleasePart($path)
+    {
+        $rPath = $this->getReleasePath($path);
+        $dPath = $this->getDistributionPath($path);
+        return(preg_replace("/^".preg_quote($dPath, '/')."\/?/", "", $rPath));
+    }
+    function saveItemChanges()
+    {
+        // Save template engine modifications and validate values.
+        $this->TemplateEngine->save_object();
+        $msgs = $this->TemplateEngine->check();
+
+        // Get values to be saved
+        $values = array();
+        foreach($this->TemplateEngine->getWidgets() as $w){
+            $values[$w->getName()] = $w->getValue();
+        }
+           
+        // No input error were found, now check that we do not use the same name twice
+        //  and that it is valid.
+        if(!count($msgs)){
+
+            // Get used item names for the current path
+            if($this->currentObject){
+    
+                // Get used item names in the parent path.
+                $usedNames = $this->getUsedNamesForPath($this->currentObject['parentPath']);
+            }else{
+
+                // Get used items for the selected path.
+                $usedNames = $this->getUsedNamesForPath($this->selectedContainer);
+            }
+
+            // Allow the item to keep its name.
+            if($this->currentObject != NULL && isset($this->currentObject['values']['name'])){
+                $usedNames = array_remove_entries(array($this->currentObject['values']['name']), $usedNames);
+            }
+            if(in_array($values['name'],$usedNames)){
+                $msgs[] = msgPool::duplicated(_("Name"));
+            }
+        }
+
+        // Display errors
+        if(count($msgs)){
+            msg_dialog::displayChecks($msgs);
+            return;
+        }
+
+        // Get the item type to be saved
+        $item = $this->currentObject;
+        $type = $this->TemplateEngine->getItemType();
+        if($this->cfgItemMap[$type] == 'root'){
+
+            // We've to create a new distribution
+            if($type == 'Distribution'){
+                
+                // Distributions cannot be renamed!
+                if(isset($item['name']) && $item['name'] != $values['name']){
+                    msg_dialog::displayChecks(array("Distributions cannot be renamed!"));
+                    return;
+                }
+
+                // Create a new distribution 
+                if(!$item){
+                    $name = $values['name'];
+                    $itype = $values['installation_type'];
+                    $imethod = $values['installation_method'];
+                    $origin = $values['origin'];
+
+                    // Initiate the rpc request.
+                    $rpc = $this->config->getRpcHandle();
+                    $res = $rpc->createDistribution($name, $itype, array('mirror'=>$origin, 'install_method' => $imethod));
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to save distributions: %s"), 
+                            $rpc->get_error()),ERROR_DIALOG);
+                        return(NULL);
+                    }
+                }
+
+                // Collect distribution properties
+                $data = array();
+                $data['distribution'] = $values['name'];
+                $data['arch'] = $values['architectures'];
+                $data['component'] = $values['components'];
+                $data['mirror_sources'] = $values['mirror_sources'];
+
+                // Set distribution properties
+                $rpc = $this->config->getRpcHandle();
+                $rpc->setDistribution($data);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to save distribution properties: %s"), 
+                                $rpc->get_error()),ERROR_DIALOG);
+                    return(NULL);
+                }
+
+                // We've successfully added the item, now add it to the tree.
+                $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
+
+                // Finally - close the dialog. 
+                $this->listing->clearDialogObject();
+
+            }elseif($type == 'Release'){
+           
+                // We've to update a release. 
+                if($item){
+
+                    // Check if we've to rename the item.
+                    $path = $this->getReleasePart($item['parentPath']);
+                    $curPath = $this->getReleasePart($item['path']);
+                    $newPath = trim($path."/".$values['name'], '/');
+                    if($curPath != $newPath){
+                        $rpc = $this->config->getRpcHandle();
+                        $res = $rpc->renameRelease($curPath, $newPath);
+                        if(!$rpc->success()){
+                            msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
+                            return(NULL);
+                        }else{
+                            $nP = $item['parentPath'].'/'.$values['name'];
+                            $this->dataModel->moveItem($item['path'], $nP);
+                            $this->dataModel->setItemValues($nP, $values);
+                            $this->listing->clearDialogObject();
+                        }
+                    }else{
+                        $this->listing->clearDialogObject();
+                    }
+                
+                }else{
+
+                    // Build up the new release path.
+                    $name = $values['name'];
+                    $rPath = $this->getReleasePart($this->selectedContainer);
+                    $newPath = trim($rPath."/".$name, '/');
+
+                    // Detect the parent distribution
+                    $dist = $this->getDistributionPart($this->selectedContainer);
+
+                    // Initiate the rpc request.
+                    $rpc = $this->config->getRpcHandle();
+                    $res = $rpc->createRelease($dist, $newPath);
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
+                        return(NULL);
+                    }else{
+
+                        // We've successfully added/saved the item, now add it to the tree.
+                        $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
+                        $this->listing->clearDialogObject();
+                    }
+                }
+            }elseif($type == "Template"){
+
+                    // Initiate the rpc request.
+                    $rpc = $this->config->getRpcHandle();
+                    $res = $rpc->installSetTemplate($values['name'], $values);
+                    if(!$rpc->success()){
+                        msg_dialog::display(_("Error"), sprintf(_("Failed to save template: %s"), $rpc->get_error()),ERROR_DIALOG);
+                        return(NULL);
+                    }else{
+                        
+                        // We've successfully added/saved the item, now add it to the tree.
+                        if(!$item){
+                            $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
+                            $this->listing->clearDialogObject();
+                        }else{
+
+                            // Update the model and clear the dialogs 
+                            $path = $item['path'];
+                            $this->dataModel->setItemValues($path, $values);
+                            $this->listing->clearDialogObject();
+                        }
+                    }
+                
+            }else{
+                echo "{$type} Cannot be saved yet";
+                $this->listing->clearDialogObject();
+                return;
+            }
+        }
+
+        // Save a CONFIG-ITEM object.
+        if($this->cfgItemMap[$type] != 'root'){
+
+            // Get paths 
+            $release =  $this->getReleasePart($this->selectedContainer);
+
+            if($item){
+                $oldPath = $item['path'];
+                $oldItemPath = $this->getItemPath($item['path']);
+                $newPath = $item['parentPath']."/".$values['name'];
+                $newItemPath = $this->getItemPath($newPath);
+            }else{
+                $newPath = $this->selectedContainer."/".$values['name'];
+                $newItemPath = $this->getItemPath($this->selectedContainer)."/".$values['name'];
+            }
+
+            // If this is a new item, then create it now.
+            if($item == NULL){
+
+                // Add the new item
+                $rpc = $this->config->getRpcHandle();
+                $res = $rpc->setConfigItem($release, $newItemPath, $type, $values);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to save %s: %s"),$type, $rpc->get_error()),ERROR_DIALOG);
+                    return(NULL);
+                }else{
+
+                    // We've successfully added the item, now add it to the tree.
+                    $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],array(), '-' );
+
+                    // Finally - close the dialog. 
+                    $this->listing->clearDialogObject();
+                }
+            }else{
+
+                // Write the modifications back to the server.
+                $rpc = $this->config->getRpcHandle();
+                $res = $rpc->setConfigItem($release, $oldItemPath, $type, $values);
+                if(!$rpc->success()){
+                    msg_dialog::display(_("Error"), sprintf(_("Failed to save config item: %s"), $rpc->get_error()),ERROR_DIALOG);
+                    return(NULL);
+                }else{
+            
+                    // Update the data model
+                    $this->dataModel->setItemValues($oldPath, $values);
+                    if($oldPath != $newPath){
+                        $this->dataModel->moveItem($oldPath, $newPath);
+                    }
+                    $this->listing->clearDialogObject();
+                }
+            }
+        }
+    }
+    function remove_lock() {}
+}
+
+
+?>
diff --git a/gosa-plugins/goto-ng/admin/newConfigManagement/class_newConfigManagement.inc b/gosa-plugins/goto-ng/admin/newConfigManagement/class_newConfigManagement.inc
deleted file mode 100644 (file)
index 4436b21..0000000
+++ /dev/null
@@ -1,980 +0,0 @@
-<?php
-
-/*! \brief  This class allows to manage backend config items and packages.
- */
-class newConfigManagement extends plugin
-{
-    var $initTime;
-    var $plHeadline = "Config management";
-    var $plDescription = "Config management";
-    var $plIcon = "plugins/goto/images/ConfigManagement.png";
-
-    var $selectedContainer;
-
-    var $dataModel = NULL;
-    var $listing = NULL;
-
-    var $cfgItemMap = NULL;
-
-    var $addableContainerItems = array();
-    var $currentObject = NULL;
-    var $itemsPerMethod = NULL;
-
-    var $initFailed = TRUE;
-    var $initialized = FALSE;
-    var $errorMessage = "";
-
-
-    /*! \brief  Initialize the plugin and finally update the data model.
-     */
-    function __construct($config, $dn)
-    {
-        $this->config = &$config;
-        $this->listing = new ConfigManagementListing($this->config, get_userinfo(), $this);
-
-        // Load the template engine and tell her what template
-        //  to use for the HTML it produces.
-        $this->TemplateEngine = new TemplateEngine($config);
-    }
-
-    
-    function init()
-    {
-        $success = TRUE;
-        $success &= $this->loadInstallationMethods();
-        $success &= $this->updateDataModel();
-        $this->initFailed = !$success;
-        if($success){
-            $this->initialized = TRUE;
-            $this->listing->setListingTypes($this->getListingTypes());
-            $this->setCurrentContainer('/root');
-        }
-    }
-
-
-    /*! \brief  Intializes this plugin
-     *          All available installation methods will be loaded
-     */
-    function loadInstallationMethods()
-    {
-        // Get static installation methods.
-        $this->installationMethods = json_decode(file_get_contents(get_template_path('goto/Config/root.json', TRUE)), TRUE);
-
-        // Load configuration via rpc.
-        $rpc = $this->config->getRpcHandle();
-
-        // Load some base install parameters
-        $res = $rpc->getSupportedBaseInstallMethods();
-        $baseInstTypes = $installationTypes = $installationMethods = array();
-        foreach($res as $type => $data){
-            $baseInstTypes[$type] = $type;
-            if(isset($data['repositories'])){
-                foreach($data['repositories'] as $m){
-                    $installationTypes[$m] = $m;
-                }
-            }
-            if(isset($data['methods'])){
-                foreach($data['methods'] as $m){
-                    $installationMethods[$m] =$m;
-                }
-            }
-        }
-
-        $res = $rpc->getSupportedInstallMethods();
-        if(!$rpc->success()){
-            $this->errorMessage = $rpc->get_error();;
-            return(FALSE);
-        }
-
-        // Populate install methods on success.
-        if(!count($res)){
-            $this->errorMessage = _("No selectable install methods returned!");
-            return(FALSE);
-        }else{
-
-            // Merge result with hard coded methods
-            $this->installationMethods = array_merge($this->installationMethods, $res);
-
-            // Walk through entries and create useful mappings.
-            $this->cfgItemMap = array();
-            $this->itemConfig = array();
-            $this->itemsPerMethod = array();
-            $rootElements = array('Release');
-            foreach($this->installationMethods as $method => $items){
-                foreach($items['items'] as $itemName => $item){
-                    $this->itemsPerMethod[$method][] = $itemName;
-                    $this->cfgItemMap[$itemName] = $method;
-                    $this->itemConfig[$itemName] = &$this->installationMethods[$method]['items'][$itemName];
-                    // This enables us to create the first level of config items when 
-                    //  a release is selected.
-                    if($item['name'] == "/" && $itemName != 'root'){
-                        $rootElements = array_merge($rootElements, $item['container']);
-                    }
-                }
-            }
-        }
-
-        // Fill replacements
-        $map['%ROOT_CFG_ITEMS'] = &$rootElements;
-        $map['%INSTALLATION_TYPES'] = array('dep' => 'dep', 'rpm' => 'rpm');
-        $map['%INSTALLATION_METHODS'] = array('puppet' => 'puppet');
-        $map['%BASE_INSTALLATION_METHODS'] = array('preseed' => 'preseed');
-        $this->itemConfig = $this->__fillPlaceholder($this->itemConfig, $map);
-        return(TRUE);
-    }
-
-
-    /*! \brief  Fill in replacements in the itemConfig
-     *          Some values are dynamic and cannot be hardcoded, a placeholder is
-     *           used in this case in the deinition file root.json. 
-     */
-    function __fillPlaceholder($data, $placeholder)
-    {
-        foreach($data as $name => $sData){
-            if(is_array($sData)){
-                $data[$name] = $this->__fillPlaceholder($data[$name], $placeholder);
-            }elseif(is_string($sData) && isset($placeholder[$sData])){
-                $data[$name] = &$placeholder[$sData];
-            }
-        }
-        return($data);
-    }
-
-
-    /*! \brief  Updates all distributions, releases, packages and items in the dataModel
-     *          Load information from the backend.
-     */
-    function updateDataModel()
-    {
-        // Recreate the data model, to have a clean and fresh instance.
-        $this->dataModel = new ConfigManagementDataModel();
-
-
-        // Load templates from the backend and append them on the base 
-        $rpc = $this->config->getRpcHandle();
-        $res = $rpc->installListTemplates();
-        if(!$rpc->success()){
-            $this->errorMessage = sprintf(_("Failed to load templates: %s"), $rpc->get_error());
-            return(FALSE);
-        } 
-        foreach($res as $tName => $tData){
-            $tData['name'] = $tName;
-            $this->dataModel->addItem('Template','/root', $tName, $tData, '-');
-        }
-
-
-        // Load distributions 
-        $rpc = $this->config->getRpcHandle();
-        $res = $rpc->getDistributions();
-        if(!$rpc->success()){
-            $this->errorMessage = sprintf(_("Failed to load distributions: %s"), $rpc->get_error());
-            return(FALSE);
-        }else{
-            if(is_array($res)){
-
-                foreach($res as $dist){
-           
-                    // Simple strings 
-                    $values = array();
-                    foreach(array('origin','installation_method', 'installation_method','debian_security',
-                            'debian_volatile', 'name', 'mirror_sources', 'managed', 'path') as $attr){
-                        $values[$attr] = $dist[$attr];
-                    }
-
-                    // Boxed strings
-                    foreach(array('type') as $attr){
-                        $values[$attr] = $dist[$attr]['name'];
-                    }
-
-                    // Arrays
-                    foreach(array('releases', 'architectures', 'components', 'sections') as $attr){
-                        $values[$attr] = array();
-                        if(is_array($dist[$attr])){
-                            foreach($dist[$attr] as $aEntry){
-                                $values[$attr][] = $aEntry['name'];
-                            }
-                        }
-                    }
-        
-                    $this->dataModel->addItem('Distribution','/root', $dist['name'], $values);
-
-                    if(isset($dist['releases'])){
-
-                        // Sort releases by name length
-                        $sort = array();
-                        foreach($dist['releases'] as $id => $release){
-                            $sort[strlen($release['name']) . $release['name']]  = $id;
-                        }
-                        uksort($sort, "strnatcasecmp");   
-
-                        // Append release tags
-                        foreach($sort as $id){
-                            $release = $dist['releases'][$id];
-                            $rPath = $release['name'];
-                            $rPath = "/root/{$dist['name']}/$rPath";
-                            $rName = preg_replace("/^.*\//","", $rPath);
-                            $rPath = preg_replace("/\/[^\/]*$/","", $rPath);
-                            $values = array('name' => $rName);
-
-                            if(!$this->dataModel->itemExistsByPath($rPath)){
-                                trigger_error("Invalid release name '{$rName}' in path '{$rPath}' received! Skipping entry!");
-                            }else{
-                                $id = $this->dataModel->addItem('Release',$rPath, $rName, $values);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return(TRUE);
-    }
-
-
-    /*! \brief  Keep track of posted values and populate those 
-     *           which are interesting for us.
-     *          Inspects the _POST and _GET values.
-     */
-    function save_object()
-    {
-        // Update the listing class, this is necessary to get post
-        //  actions from it.
-        $this->listing->save_object();
-
-        // Get the selected distribution and release from the listing widget.
-        $cont = $this->listing->getSelectedContainer();
-        if(isset($_POST['ROOT'])){
-            $this->setCurrentContainer('/root');
-        }elseif(isset($_POST['BACK'])){
-            $path = $this->selectedContainer;
-            if($this->dataModel->itemExistsByPath($path)){
-                $data = $this->dataModel->getItemByPath($path);
-                if($data['parentPath']){
-                    $this->setCurrentContainer($data['parentPath']);
-                }
-            }
-        }else{
-            $this->setCurrentContainer($cont);
-        }
-    }
-
-
-    /*! \brief  Load extended sub-objecte like 'config items' or 'packages'
-     *           for the given release path.
-     *  @param  String  The release path to load sub-objects for.
-     *  @return NULL 
-     */
-    function updateItemList($path)
-    {
-        // Fist get Item and check if it is an release 
-        if($this->dataModel->itemExistsByPath($path)){
-            $data = $this->dataModel->getItemByPath($path);
-
-            // Only releases can contain config-items.
-            if($data['type'] == 'Release' && $data['status'] != "fetched"){
-
-                // Request all config items for the selected release via rpc.
-                $rpc = $this->config->getRpcHandle();
-                $releasePath = $this->getReleasePart($path);
-                $res = $rpc->listConfigItems($releasePath);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"),sprintf(_("Failed to load distributions: %s"),$rpc->get_error()),ERROR_DIALOG);
-                    return;
-                }else{
-            
-                    if(!$res) return;
-
-                    // Sort entries by path length 
-                    $sLen = array();
-                    foreach($res as $itemPath => $type){
-                        $sLen[strlen($itemPath)."_".$itemPath] = $itemPath;
-                    }
-                    uksort($sLen, "strnatcasecmp");   
-
-                    // Walk through each entry and then try to add it to the model
-                    foreach($sLen as $unused => $itemPath){
-
-                        // Do not add the root element '/'
-                        if($itemPath == "/") continue;
-
-                        $type = $res[$itemPath];
-                
-                        // Append the items-path to the current path to create the 
-                        //  effective item path in the data model.
-                        $targetPath = trim($path."/".$itemPath);
-
-                        // Remove trailing and duplicated slashes
-                        $targetPath = rtrim($targetPath, '/');
-                        $targetPath = preg_replace("/\/\/*/","/", $targetPath);
-
-                        // Extract the items name
-                        $name = preg_replace("/^.*\//","", $targetPath);
-    
-                        // Cleanup the path and then add the item.
-                        $targetPath = preg_replace("/[^\/]*$/","", $targetPath);
-                        $targetPath = rtrim($targetPath,'/');
-                        $this->dataModel->addItem($type, $targetPath, $name,array(),'-' ); 
-                    }
-                    $this->dataModel->setItemStatus($path, 'fetched');
-                }
-            }
-        }
-    }
-
-
-    /*! \brief  Sets the currently selected container and item path. 
-     *  @param  String  The path of the container to set.
-     *  @param  String  The path of the item to set.
-     *  @return 
-     */
-    function setCurrentContainer($cont)
-    {
-        // Do nothing while the service wasn't initialized.
-        if(!$this->initialized) return;
-
-        $this->selectedContainer = $cont;
-
-        // Update list of items within the selected container. 
-        $this->updateItemList($this->selectedContainer);
-
-        // Transfer checked values back to the listing class.
-        $this->listing->setContainers($this->getContainerList());
-        $this->listing->setContainer($cont);
-
-        // Update the list of addable sub objects
-        $this->addableContainerItems = $this->getAddableContainersPerPath($cont);
-    }
-
-
-    function getAddableContainersPerPath($path)
-    {
-        $currentItem = $this->dataModel->getItemByPath($path);
-        $method = $this->getInstallationMethodPerPath($path);
-
-        // Get allowed items for the currently selected method 
-        //  merge in root elements, they are allowed everywhere.
-        $allowedItems = $this->itemsPerMethod[$method];
-        $allowedItems = array_merge($allowedItems, $this->itemsPerMethod['root']);
-
-        // Get addable items
-        $possibleItems = $this->itemConfig[$currentItem['type']]['container'];
-        return(array_unique(array_intersect($allowedItems, $possibleItems)));
-    }
-
-    
-    function getInstallationMethodPerPath($path)
-    {
-        $path .= '/';
-        while(preg_match("/\//", $path)){
-            $path = preg_replace("/\/[^\/]*$/","",$path);
-            $item = $this->dataModel->getItemByPath($path);
-            if(isset($item['values']['installation_method'])){
-                return($item['values']['installation_method']);
-            }
-        }
-        return('root'); 
-    }
-
-
-    /*! \brief  Generate the HTML content for this plugin.
-     *          Actually renders the listing widget..
-     */
-    function execute()
-    {
-        // Request an update of the data model
-        if(!$this->initialized){
-            $this->init();
-        }
-
-        // Act on init fails
-        if($this->initFailed){
-            $smarty = get_smarty();
-            $smarty->assign('error', $this->errorMessage);
-            return($smarty->fetch(get_template_path('rpcError.tpl', TRUE)));
-        }else{
-
-            // Get the selected release and store it in a session variable
-            //  to allow the configFilter to access it and display the
-            //  packages and items.
-            $res = $this->listing->execute();
-            $this->listing->setListingTypes($this->getListingTypes());
-            return($res);
-        }
-    }
-
-
-    /*! \brief      Returns a list of items which will then be displayed 
-     *               in the management-list. 
-     *              (The management class calls this method from its execute())
-     *  @return     Array   A list of items/objects for the listing. 
-     */
-    function getItemsToBeDisplayed()
-    {
-        $path = $this->selectedContainer;
-        $item = $this->dataModel->getItemByPath($path);
-        return($item);
-    }
-
-
-    /*! \brief  Returns a simply list of all distributions.
-     *          This list will then be used to generate the entries of the 
-     *           ItemSelectors in the listing class.
-     */
-    function getContainerList()
-    {
-        $data = $this->dataModel->getItemByPath('/root');
-        $res = array();
-        $res["/root"] = array("name" => "/", "desc" => "");
-        $res = array_merge($res,$this->__recurseItem($data));
-        return($res);
-    }
-
-
-    /*! \brief  Recursivly wlks through an item and collects all path and name info.
-     *          The reult can then be used to fill the ItemSelector.
-     *  @param  Array   The Item to recurse. 
-     *  @param  Array   The type of of objects to collect. 
-     *  @param  String  The parent path prefix which should be removed.
-     *  @return Array   An array containing Array[path] = name
-     */
-    function __recurseItem($item, $parent = "")
-    {
-        $res = array();
-        $path = preg_replace("/".preg_quote($parent,'/')."/","",$item['path']);
-        $res[$path] = array('name' => $item['name'],'desc'=>$item['type']);
-        if(count($item['children'])){
-            foreach($item['children'] as $child){
-                $res = array_merge($res, $this->__recurseItem($child, $parent));
-            }
-        }
-        return($res);
-    }
-
-
-    /*! \brief   Returns a info list about all items we can manage,
-     *            this used to fill the listings <objectType> settings.
-     *  @return Array   An array with item info.
-     */
-    function getListingTypes()
-    {
-        $types= array();
-        $types['Distribution']['objectClass'] = 'Distribution';
-        $types['Distribution']['label'] = _('Distribution');
-        $types['Distribution']['image'] = 'images/lists/edit.png';
-        $types['Distribution']['category'] = 'Device';
-        $types['Distribution']['class'] = 'Device';
-
-        $types['Release']['objectClass'] = 'Release';
-        $types['Release']['label'] = _('Release');
-        $types['Release']['image'] = 'images/lists/delete.png';
-        $types['Release']['category'] = 'Device';
-        $types['Release']['class'] = 'Device';
-
-        $types['Component']['objectClass'] = 'Component';
-        $types['Component']['label'] = _('Component');
-        $types['Component']['image'] = 'plugins/users/images/select_user.png';
-        $types['Component']['category'] = 'Device';
-        $types['Component']['class'] = 'Device';
-
-        foreach($this->installationMethods as $method => $items){
-            foreach($items['items'] as $itemName => $item){
-                $types[$itemName]['objectClass'] = $itemName;
-                $types[$itemName]['label'] = $item['name'];
-                $types[$itemName]['image'] = 'plugins/fai/images/fai_script.png';
-                $types[$itemName]['category'] = 'Device';
-                $types[$itemName]['class'] = 'Device';
-            }
-        }
-
-        return($types);
-    }
-
-
-    /*! \brief      The plugins ACL and plugin-property definition. 
-     *  @return 
-     */
-    public static function plInfo()
-    {
-        return (array(
-                    "plShortName"   => _("Config management"),
-                    "plDescription" => _("Config management"),
-                    "plSelfModify"  => FALSE,
-                    "plDepends"     => array(),
-                    "plPriority"    => 0,
-                    "plSection"     => array("administration"),
-                    "plCategory"    => array(
-                        "newConfigManagement" => array("description"  => _("Config management"),
-                            "objectClass"  => "FAKE_OC_newConfigManagement")),
-                    "plProvidedAcls"=> array(
-                            "cfgItem" => _("Config item")
-                        )
-                    ));
-    }
-
-
-    /*! \brief  Acts on open requests.
-     *          (This action is received from the ConfigManagementListing class.)
-     *  @param  Array   The items ids. (May contain multiple ids)
-     *  @return
-     */
-    function openEntry($ids)
-    {
-        $id = $ids[0];
-        $item = $this->dataModel->getItemById($id);
-        $this->setCurrentContainer($item['path']);
-        return;
-    }
-
-
-
-    /*! \brief  Removes an entry from the listing.
-     */
-    function removeEntry($ids)
-    {
-        foreach($ids as $id){
-            $item = $this->dataModel->getItemById($id);
-
-            // Is an config item.
-            if($this->cfgItemMap[$item['type']] != 'root'){
-                $release = $this->getReleasePart($item['path']);
-                $path = $this->getItemPath($item['path']);
-                $rpc = $this->config->getRpcHandle();
-                $rpc->removeConfigItem($release, $path);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to remove: %s"), $rpc->get_error()),ERROR_DIALOG);
-                    return(NULL);
-                }else{
-                    $this->dataModel->removeItem($item['path']);
-                }
-            }else{
-
-                // Remove distribution
-                if($item['type'] == 'Distribution'){
-
-                    $dist = $this->getDistributionPart($item['path']);
-                    $rpc = $this->config->getRpcHandle();
-                    $rpc->removeDistribution($dist, array('recursive' => TRUE));
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the distribution: %s. Error was: %s"), 
-                                    $dist, $rpc->get_error()), ERROR_DIALOG);
-                        return(NULL);
-                    }else{
-                        $this->dataModel->removeItem($item['path']);
-                    }
-                }elseif($item['type'] == 'Release'){
-
-                    // Remove release
-                    $release = preg_replace("/^.*\//","", $this->getReleasePart($item['path']));
-                    $rpc = $this->config->getRpcHandle();
-                    $rpc->removeRelease($release, array('recursive' => TRUE));
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the release: %s. Error was: %s"), 
-                                    $release, $rpc->get_error()),ERROR_DIALOG);
-                        return(NULL);
-                    }else{
-                        $this->dataModel->removeItem($item['path']);
-                    }
-
-                }elseif($item['type'] == 'Template'){
-
-                    // Remove Template
-                    $rpc = $this->config->getRpcHandle();
-                    $rpc->installRemoveTemplate($item['name']);
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to remove the template: %s. Error was: %s"), 
-                                    $release, $rpc->get_error()),ERROR_DIALOG);
-                        return(NULL);
-                    }else{
-                        $this->dataModel->removeItem($item['path']);
-                    }
-                }else{
-                    trigger_error($item['type']." - are not handled yet!");
-                }
-            }
-        }
-    }
-
-
-    /*! \brief  Returns a list of used item names for a given path.
-     */
-    function getUsedNamesForPath($path)
-    {
-        $item = $this->dataModel->getItemByPath($path);
-        $names = array();
-        foreach($item['children'] as $path => $data){
-            $names[] = $data['name'];
-        }
-        return($names);
-    }
-
-
-    /*! \brief      Edits a selected list item.
-     */
-    function editEntry($ids)
-    {
-        $item = $this->dataModel->getItemById($ids[0]);
-        $release = $this->getReleasePart($item['path']);
-        $path = $this->getItemPath($item['path']);
-        $method = $this->cfgItemMap[$item['type']];
-
-        // Load item values on demand
-        if($this->cfgItemMap[$item['type']] != 'root'){
-            if($item['status'] == '-'){
-                $rpc = $this->config->getRpcHandle();
-                $res = $rpc->getConfigItem($release, $path);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to load config item details: %s"), $rpc->get_error()),ERROR_DIALOG);
-                    return;
-                }else{
-                    $item['values'] = $res;
-                    $this->dataModel->setItemStatus($item['path'], 'fetched');
-                    $this->dataModel->setItemValues($item['path'], $item['values']);
-                }
-            }
-        }elseif($item['type'] == 'Template'){
-            if($item['status'] == '-'){
-                $rpc = $this->config->getRpcHandle();
-                $res = $rpc->installGetTemplate($item['name']);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to load template details: %s"), $rpc->get_error()),ERROR_DIALOG);
-                    return;
-                }else{
-                    $item['values'] = $res;
-                    $this->dataModel->setItemStatus($item['path'], 'fetched');
-                    $this->dataModel->setItemValues($item['path'], $item['values']);
-                }
-            }
-        }
-
-        $this->TemplateEngine->load($this->itemConfig);
-        $this->TemplateEngine->setTemplate($method.".tpl");
-        $this->TemplateEngine->editItem($item['type'],$item['values']);
-        $this->listing->setDialogObject($this->TemplateEngine);
-        $this->currentObject = $item;
-    }
-
-
-    /*! \brief  Initiates the creation of a new item
-     */
-    function newEntry($type)
-    {
-        // We've to add a config item
-        $this->TemplateEngine->load($this->itemConfig);
-        if($this->cfgItemMap[$type] != 'root'){
-            $method = $this->cfgItemMap[$type];
-            $this->TemplateEngine->setTemplate($method.".tpl");
-            $this->TemplateEngine->createItem($type,array());
-            $this->listing->setDialogObject($this->TemplateEngine);
-            $this->currentObject = NULL;
-        }else{
-            $this->TemplateEngine->setTemplate("root.tpl");
-            $this->TemplateEngine->createItem($type,array());
-            $this->listing->setDialogObject($this->TemplateEngine);
-            $this->currentObject = NULL;
-        }
-    }
-
-
-    /*! \brief  Extracts the item-path out of a path.
-     *          e.g. /debian/squeeze/test/module -> /test/module
-     */
-    function getItemPath($fullPath)
-    {
-        $fPath = $fullPath.'/';
-        while(preg_match("/\//", $fPath)){
-            $fPath = preg_replace("/\/[^\/]*$/","", $fPath);
-            $item = $this->dataModel->getItemByPath($fPath);
-            if(in_array($item['type'], array('Release', 'Distribution', 'root'))){
-                return(preg_replace("/".preg_quote($item['path'],'/')."/", "", $fullPath));
-            }
-        }
-        return(NULL);
-    }
-
-
-    /*! \brief  Extracts the releaes path out of a path.
-     *          e.g. /debian/squeeze/test/module -> /debian/squeeze
-     */
-    function getReleasePath($fullPath)
-    {
-        $fullPath.='/';
-        while(preg_match("/\//", $fullPath)){
-            $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
-            $item = $this->dataModel->getItemByPath($fullPath);
-            if($item['type'] == 'Release'){
-                return($fullPath);
-            }
-        }
-        return(NULL);
-    }
-  
-    
-    /*! \brief  Extracts the distribution path out of a path.
-     *          e.g. /root/debian/squeeze/test/module -> /root/debian
-     */
-    function getDistributionPath($fullPath)
-    {
-        $fullPath.='/';
-        while(preg_match("/\//", $fullPath)){
-            $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
-            $item = $this->dataModel->getItemByPath($fullPath);
-            if($item['type'] == 'Distribution'){
-                return($fullPath);
-            }
-        }
-        return(NULL);
-    }
-
-
-    /*! \brief  Extracts the distribution-part out of a path.
-     *          e.g. /root/debian/squeeze/test/module -> debian
-     */
-    function getDistributionPart($fullPath)
-    {
-        return(trim(preg_replace("#^/root/#","", $this->getDistributionPath($fullPath)), '/'));
-    }
-    
-    
-    /*! \brief  Extracts the release-part out of a path.
-     *          e.g. /root/debian/squeeze/test/module -> squeeze/test
-     */
-    function getReleasePart($path)
-    {
-        $rPath = $this->getReleasePath($path);
-        $dPath = $this->getDistributionPath($path);
-        return(preg_replace("/^".preg_quote($dPath, '/')."\/?/", "", $rPath));
-    }
-    function saveItemChanges()
-    {
-        // Save template engine modifications and validate values.
-        $this->TemplateEngine->save_object();
-        $msgs = $this->TemplateEngine->check();
-
-        // Get values to be saved
-        $values = array();
-        foreach($this->TemplateEngine->getWidgets() as $w){
-            $values[$w->getName()] = $w->getValue();
-        }
-           
-        // No input error were found, now check that we do not use the same name twice
-        //  and that it is valid.
-        if(!count($msgs)){
-
-            // Get used item names for the current path
-            if($this->currentObject){
-    
-                // Get used item names in the parent path.
-                $usedNames = $this->getUsedNamesForPath($this->currentObject['parentPath']);
-            }else{
-
-                // Get used items for the selected path.
-                $usedNames = $this->getUsedNamesForPath($this->selectedContainer);
-            }
-
-            // Allow the item to keep its name.
-            if($this->currentObject != NULL && isset($this->currentObject['values']['name'])){
-                $usedNames = array_remove_entries(array($this->currentObject['values']['name']), $usedNames);
-            }
-            if(in_array($values['name'],$usedNames)){
-                $msgs[] = msgPool::duplicated(_("Name"));
-            }
-        }
-
-        // Display errors
-        if(count($msgs)){
-            msg_dialog::displayChecks($msgs);
-            return;
-        }
-
-        // Get the item type to be saved
-        $item = $this->currentObject;
-        $type = $this->TemplateEngine->getItemType();
-        if($this->cfgItemMap[$type] == 'root'){
-
-            // We've to create a new distribution
-            if($type == 'Distribution'){
-                
-                // Distributions cannot be renamed!
-                if(isset($item['name']) && $item['name'] != $values['name']){
-                    msg_dialog::displayChecks(array("Distributions cannot be renamed!"));
-                    return;
-                }
-
-                // Create a new distribution 
-                if(!$item){
-                    $name = $values['name'];
-                    $itype = $values['installation_type'];
-                    $imethod = $values['installation_method'];
-                    $origin = $values['origin'];
-
-                    // Initiate the rpc request.
-                    $rpc = $this->config->getRpcHandle();
-                    $res = $rpc->createDistribution($name, $itype, array('mirror'=>$origin, 'install_method' => $imethod));
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to save distributions: %s"), 
-                            $rpc->get_error()),ERROR_DIALOG);
-                        return(NULL);
-                    }
-                }
-
-                // Collect distribution properties
-                $data = array();
-                $data['distribution'] = $values['name'];
-                $data['arch'] = $values['architectures'];
-                $data['component'] = $values['components'];
-                $data['mirror_sources'] = $values['mirror_sources'];
-
-                // Set distribution properties
-                $rpc = $this->config->getRpcHandle();
-                $rpc->setDistribution($data);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to save distribution properties: %s"), 
-                                $rpc->get_error()),ERROR_DIALOG);
-                    return(NULL);
-                }
-
-                // We've successfully added the item, now add it to the tree.
-                $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
-
-                // Finally - close the dialog. 
-                $this->listing->clearDialogObject();
-
-            }elseif($type == 'Release'){
-           
-                // We've to update a release. 
-                if($item){
-
-                    // Check if we've to rename the item.
-                    $path = $this->getReleasePart($item['parentPath']);
-                    $curPath = $this->getReleasePart($item['path']);
-                    $newPath = trim($path."/".$values['name'], '/');
-                    if($curPath != $newPath){
-                        $rpc = $this->config->getRpcHandle();
-                        $res = $rpc->renameRelease($curPath, $newPath);
-                        if(!$rpc->success()){
-                            msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
-                            return(NULL);
-                        }else{
-                            $nP = $item['parentPath'].'/'.$values['name'];
-                            $this->dataModel->moveItem($item['path'], $nP);
-                            $this->dataModel->setItemValues($nP, $values);
-                            $this->listing->clearDialogObject();
-                        }
-                    }else{
-                        $this->listing->clearDialogObject();
-                    }
-                
-                }else{
-
-                    // Build up the new release path.
-                    $name = $values['name'];
-                    $rPath = $this->getReleasePart($this->selectedContainer);
-                    $newPath = trim($rPath."/".$name, '/');
-
-                    // Detect the parent distribution
-                    $dist = $this->getDistributionPart($this->selectedContainer);
-
-                    // Initiate the rpc request.
-                    $rpc = $this->config->getRpcHandle();
-                    $res = $rpc->createRelease($dist, $newPath);
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
-                        return(NULL);
-                    }else{
-
-                        // We've successfully added/saved the item, now add it to the tree.
-                        $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
-                        $this->listing->clearDialogObject();
-                    }
-                }
-            }elseif($type == "Template"){
-
-                    // Initiate the rpc request.
-                    $rpc = $this->config->getRpcHandle();
-                    $res = $rpc->installSetTemplate($values['name'], $values);
-                    if(!$rpc->success()){
-                        msg_dialog::display(_("Error"), sprintf(_("Failed to save template: %s"), $rpc->get_error()),ERROR_DIALOG);
-                        return(NULL);
-                    }else{
-                        
-                        // We've successfully added/saved the item, now add it to the tree.
-                        if(!$item){
-                            $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
-                            $this->listing->clearDialogObject();
-                        }else{
-
-                            // Update the model and clear the dialogs 
-                            $path = $item['path'];
-                            $this->dataModel->setItemValues($path, $values);
-                            $this->listing->clearDialogObject();
-                        }
-                    }
-                
-            }else{
-                echo "{$type} Cannot be saved yet";
-                $this->listing->clearDialogObject();
-                return;
-            }
-        }
-
-        // Save a CONFIG-ITEM object.
-        if($this->cfgItemMap[$type] != 'root'){
-
-            // Get paths 
-            $release =  $this->getReleasePart($this->selectedContainer);
-
-            if($item){
-                $oldPath = $item['path'];
-                $oldItemPath = $this->getItemPath($item['path']);
-                $newPath = $item['parentPath']."/".$values['name'];
-                $newItemPath = $this->getItemPath($newPath);
-            }else{
-                $newPath = $this->selectedContainer."/".$values['name'];
-                $newItemPath = $this->getItemPath($this->selectedContainer)."/".$values['name'];
-            }
-
-            // If this is a new item, then create it now.
-            if($item == NULL){
-
-                // Add the new item
-                $rpc = $this->config->getRpcHandle();
-                $res = $rpc->setConfigItem($release, $newItemPath, $type, $values);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to save %s: %s"),$type, $rpc->get_error()),ERROR_DIALOG);
-                    return(NULL);
-                }else{
-
-                    // We've successfully added the item, now add it to the tree.
-                    $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],array(), '-' );
-
-                    // Finally - close the dialog. 
-                    $this->listing->clearDialogObject();
-                }
-            }else{
-
-                // Write the modifications back to the server.
-                $rpc = $this->config->getRpcHandle();
-                $res = $rpc->setConfigItem($release, $oldItemPath, $type, $values);
-                if(!$rpc->success()){
-                    msg_dialog::display(_("Error"), sprintf(_("Failed to save config item: %s"), $rpc->get_error()),ERROR_DIALOG);
-                    return(NULL);
-                }else{
-            
-                    // Update the data model
-                    $this->dataModel->setItemValues($oldPath, $values);
-                    if($oldPath != $newPath){
-                        $this->dataModel->moveItem($oldPath, $newPath);
-                    }
-                    $this->listing->clearDialogObject();
-                }
-            }
-        }
-    }
-    function remove_lock() {}
-}
-
-
-?>