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;
20 var $itemsPerMethod = NULL;
22 var $initFailed = TRUE;
23 var $initialized = FALSE;
24 var $errorMessage = "";
27 /*! \brief Initialize the plugin and finally update the data model.
28 */
29 function __construct($config, $dn)
30 {
31 $this->config = &$config;
32 $this->listing = new ConfigManagementListing($this->config, get_userinfo(), $this);
34 // Load the template engine and tell her what template
35 // to use for the HTML it produces.
36 $this->TemplateEngine = new TemplateEngine($config);
37 $this->installationMethods = json_decode(file_get_contents(get_template_path('goto/Config/root.json', TRUE)), TRUE);
38 }
41 function init()
42 {
43 $success = TRUE;
44 $success &= $this->loadInstallationMethods();
45 $success &= $this->updateDataModel();
46 $this->initFailed = !$success;
47 if($success){
48 $this->initialized = TRUE;
49 $this->listing->setListingTypes($this->getListingTypes());
50 $this->setCurrentContainer('/root');
51 }
52 }
55 /*! \brief Intializes this plugin
56 * All available installation methods will be loaded
57 */
58 function loadInstallationMethods()
59 {
60 // Load configuration via rpc.
61 $rpc = $this->config->getRpcHandle();
62 $res = $rpc->getSupportedInstallMethods();
63 if(!$rpc->success()){
64 $this->errorMessage = $rpc->get_error();;
65 return(FALSE);
66 }
68 // Populate install methods on success.
69 if(!count($res)){
70 $this->errorMessage = _("No selectable install methods returned!");
71 return(FALSE);
72 }else{
74 // Merge result with hard coded methods
75 $this->installationMethods = array_merge($this->installationMethods, $res);
77 // Walk through entries and create useful mappings.
78 $this->cfgItemMap = array();
79 $this->itemConfig = array();
80 $this->itemsPerMethod = array();
81 $rootElements = array();
82 foreach($this->installationMethods as $method => $items){
83 foreach($items['items'] as $itemName => $item){
84 $this->itemsPerMethod[$method][] = $itemName;
85 $this->cfgItemMap[$itemName] = $method;
86 $this->itemConfig[$itemName] = &$this->installationMethods[$method]['items'][$itemName];
88 // This enables us to create the first level of config items when
89 // a release is selected.
90 if($item['name'] == "/" && $itemName != 'root'){
91 $rootElements = array_merge($rootElements, $item['container']);
92 }
93 }
94 }
96 // Merge in root elements to releases.
97 foreach($this->itemConfig as $item => $data){
98 if(in_array('__CFG_ITEMS__', $data['container'])){
99 $this->itemConfig[$item]['container'] = array_merge($this->itemConfig[$item]['container'], $rootElements );
100 }
101 }
102 }
103 return(TRUE);
104 }
107 /*! \brief Updates all distributions, releases, packages and items in the dataModel
108 * Load information from the backend.
109 */
110 function updateDataModel()
111 {
112 // Recreate the data model, to have a clean and fresh instance.
113 $this->dataModel = new ConfigManagementDataModel();
116 // Load templates from the backend and append them on the base
117 $rpc = $this->config->getRpcHandle();
118 $res = $rpc->installListTemplates();
119 if(!$rpc->success()){
120 $this->errorMessage = sprintf(_("Failed to load templates: %s"), $rpc->get_error());
121 return(FALSE);
122 }
123 foreach($res as $tName => $tData){
124 $tData['name'] = $tName;
125 $this->dataModel->addItem('Template','/root', $tName, $tData, '-');
126 }
129 // Load distributions
130 $rpc = $this->config->getRpcHandle();
131 $res = $rpc->getDistributions();
132 if(!$rpc->success()){
133 $this->errorMessage = sprintf(_("Failed to load distributions: %s"), $rpc->get_error());
134 return(FALSE);
135 }else{
136 if(is_array($res)){
138 foreach($res as $dist){
140 // Simple strings
141 $values = array();
142 foreach(array('origin','installation_method', 'installation_method','debian_security',
143 'debian_volatile', 'name', 'mirror_sources', 'managed', 'path') as $attr){
144 $values[$attr] = $dist[$attr];
145 }
147 // Boxed strings
148 foreach(array('type') as $attr){
149 $values[$attr] = $dist[$attr]['name'];
150 }
152 // Arrays
153 foreach(array('releases', 'architectures', 'components', 'sections') as $attr){
154 $values[$attr] = array();
155 if(is_array($dist[$attr])){
156 foreach($dist[$attr] as $aEntry){
157 $values[$attr][] = $aEntry['name'];
158 }
159 }
160 }
162 $this->dataModel->addItem('Distribution','/root', $dist['name'], $values);
164 if(isset($dist['releases'])){
166 // Sort releases by name length
167 $sort = array();
168 foreach($dist['releases'] as $id => $release){
169 $sort[strlen($release['name']) . $release['name']] = $id;
170 }
171 uksort($sort, "strnatcasecmp");
173 // Append release tags
174 foreach($sort as $id){
175 $release = $dist['releases'][$id];
176 $rPath = $release['name'];
177 $rPath = "/root/{$dist['name']}/$rPath";
178 $rName = preg_replace("/^.*\//","", $rPath);
179 $rPath = preg_replace("/\/[^\/]*$/","", $rPath);
180 $values = array('name' => $rName);
182 if(!$this->dataModel->itemExistsByPath($rPath)){
183 trigger_error("Invalid release name '{$rName}' in path '{$rPath}' received! Skipping entry!");
184 }else{
185 $id = $this->dataModel->addItem('Release',$rPath, $rName, $values);
186 }
187 }
188 }
189 }
190 }
191 }
192 return(TRUE);
193 }
196 /*! \brief Keep track of posted values and populate those
197 * which are interesting for us.
198 * Inspects the _POST and _GET values.
199 */
200 function save_object()
201 {
202 // Update the listing class, this is necessary to get post
203 // actions from it.
204 $this->listing->save_object();
206 // Get the selected distribution and release from the listing widget.
207 $cont = $this->listing->getSelectedContainer();
208 if(isset($_POST['ROOT'])){
209 $this->setCurrentContainer('/root');
210 }elseif(isset($_POST['BACK'])){
211 $path = $this->selectedContainer;
212 if($this->dataModel->itemExistsByPath($path)){
213 $data = $this->dataModel->getItemByPath($path);
214 if($data['parentPath']){
215 $this->setCurrentContainer($data['parentPath']);
216 }
217 }
218 }else{
219 $this->setCurrentContainer($cont);
220 }
221 }
224 /*! \brief Load extended sub-objecte like 'config items' or 'packages'
225 * for the given release path.
226 * @param String The release path to load sub-objects for.
227 * @return NULL
228 */
229 function updateItemList($path)
230 {
231 // Fist get Item and check if it is an release
232 if($this->dataModel->itemExistsByPath($path)){
233 $data = $this->dataModel->getItemByPath($path);
235 // Only releases can contain config-items.
236 if($data['type'] == 'Release' && $data['status'] != "fetched"){
238 // Request all config items for the selected release via rpc.
239 $rpc = $this->config->getRpcHandle();
240 $releasePath = $this->getReleasePart($path);
241 $res = $rpc->listConfigItems($releasePath);
242 if(!$rpc->success()){
243 msg_dialog::display(_("Error"),sprintf(_("Failed to load distributions: %s"),$rpc->get_error()),ERROR_DIALOG);
244 return;
245 }else{
247 if(!$res) return;
249 // Sort entries by path length
250 $sLen = array();
251 foreach($res as $itemPath => $type){
252 $sLen[strlen($itemPath)."_".$itemPath] = $itemPath;
253 }
254 uksort($sLen, "strnatcasecmp");
256 // Walk through each entry and then try to add it to the model
257 foreach($sLen as $unused => $itemPath){
259 // Do not add the root element '/'
260 if($itemPath == "/") continue;
262 $type = $res[$itemPath];
264 // Append the items-path to the current path to create the
265 // effective item path in the data model.
266 $targetPath = trim($path."/".$itemPath);
268 // Remove trailing and duplicated slashes
269 $targetPath = rtrim($targetPath, '/');
270 $targetPath = preg_replace("/\/\/*/","/", $targetPath);
272 // Extract the items name
273 $name = preg_replace("/^.*\//","", $targetPath);
275 // Cleanup the path and then add the item.
276 $targetPath = preg_replace("/[^\/]*$/","", $targetPath);
277 $targetPath = rtrim($targetPath,'/');
278 $this->dataModel->addItem($type, $targetPath, $name,array(),'-' );
279 }
280 $this->dataModel->setItemStatus($path, 'fetched');
281 }
282 }
283 }
284 }
287 /*! \brief Sets the currently selected container and item path.
288 * @param String The path of the container to set.
289 * @param String The path of the item to set.
290 * @return
291 */
292 function setCurrentContainer($cont)
293 {
294 // Do nothing while the service wasn't initialized.
295 if(!$this->initialized) return;
297 $this->selectedContainer = $cont;
299 // Update list of items within the selected container.
300 $this->updateItemList($this->selectedContainer);
302 // Transfer checked values back to the listing class.
303 $this->listing->setContainers($this->getContainerList());
304 $this->listing->setContainer($cont);
306 // Update the list of addable sub objects
307 $this->addableContainerItems = $this->getAddableContainersPerPath($cont);
308 }
311 function getAddableContainersPerPath($path)
312 {
313 $currentItem = $this->dataModel->getItemByPath($path);
314 $method = $this->getInstallationMethodPerPath($path);
316 // Get allowed items for the currently selected method
317 // merge in root elements, they are allowed everywhere.
318 $allowedItems = $this->itemsPerMethod[$method];
319 $allowedItems = array_merge($allowedItems, $this->itemsPerMethod['root']);
321 // Get addable items
322 $possibleItems = $this->itemConfig[$currentItem['type']]['container'];
323 return(array_unique(array_intersect($allowedItems, $possibleItems)));
324 }
327 function getInstallationMethodPerPath($path)
328 {
329 $path .= '/';
330 while(preg_match("/\//", $path)){
331 $path = preg_replace("/\/[^\/]*$/","",$path);
332 $item = $this->dataModel->getItemByPath($path);
333 if(isset($item['values']['installation_method'])){
334 return($item['values']['installation_method']);
335 }
336 }
337 return('root');
338 }
341 /*! \brief Generate the HTML content for this plugin.
342 * Actually renders the listing widget..
343 */
344 function execute()
345 {
346 // Request an update of the data model
347 if(!$this->initialized){
348 $this->init();
349 }
351 // Act on init fails
352 if($this->initFailed){
353 $smarty = get_smarty();
354 $smarty->assign('error', $this->errorMessage);
355 return($smarty->fetch(get_template_path('rpcError.tpl', TRUE)));
356 }else{
358 // Get the selected release and store it in a session variable
359 // to allow the configFilter to access it and display the
360 // packages and items.
361 $res = $this->listing->execute();
362 $this->listing->setListingTypes($this->getListingTypes());
363 return($res);
364 }
365 }
368 /*! \brief Returns a list of items which will then be displayed
369 * in the management-list.
370 * (The management class calls this method from its execute())
371 * @return Array A list of items/objects for the listing.
372 */
373 function getItemsToBeDisplayed()
374 {
375 $path = $this->selectedContainer;
376 $item = $this->dataModel->getItemByPath($path);
377 return($item);
378 }
381 /*! \brief Returns a simply list of all distributions.
382 * This list will then be used to generate the entries of the
383 * ItemSelectors in the listing class.
384 */
385 function getContainerList()
386 {
387 $data = $this->dataModel->getItemByPath('/root');
388 $res = array();
389 $res["/root"] = array("name" => "/", "desc" => "");
390 $res = array_merge($res,$this->__recurseItem($data));
391 return($res);
392 }
395 /*! \brief Recursivly wlks through an item and collects all path and name info.
396 * The reult can then be used to fill the ItemSelector.
397 * @param Array The Item to recurse.
398 * @param Array The type of of objects to collect.
399 * @param String The parent path prefix which should be removed.
400 * @return Array An array containing Array[path] = name
401 */
402 function __recurseItem($item, $parent = "")
403 {
404 $res = array();
405 $path = preg_replace("/".preg_quote($parent,'/')."/","",$item['path']);
406 $res[$path] = array('name' => $item['name'],'desc'=>$item['type']);
407 if(count($item['children'])){
408 foreach($item['children'] as $child){
409 $res = array_merge($res, $this->__recurseItem($child, $parent));
410 }
411 }
412 return($res);
413 }
416 /*! \brief Returns a info list about all items we can manage,
417 * this used to fill the listings <objectType> settings.
418 * @return Array An array with item info.
419 */
420 function getListingTypes()
421 {
422 $types= array();
423 $types['Distribution']['objectClass'] = 'Distribution';
424 $types['Distribution']['label'] = _('Distribution');
425 $types['Distribution']['image'] = 'images/lists/edit.png';
426 $types['Distribution']['category'] = 'Device';
427 $types['Distribution']['class'] = 'Device';
429 $types['Release']['objectClass'] = 'Release';
430 $types['Release']['label'] = _('Release');
431 $types['Release']['image'] = 'images/lists/delete.png';
432 $types['Release']['category'] = 'Device';
433 $types['Release']['class'] = 'Device';
435 $types['Component']['objectClass'] = 'Component';
436 $types['Component']['label'] = _('Component');
437 $types['Component']['image'] = 'plugins/users/images/select_user.png';
438 $types['Component']['category'] = 'Device';
439 $types['Component']['class'] = 'Device';
441 foreach($this->installationMethods as $method => $items){
442 foreach($items['items'] as $itemName => $item){
443 $types[$itemName]['objectClass'] = $itemName;
444 $types[$itemName]['label'] = $item['name'];
445 $types[$itemName]['image'] = 'plugins/fai/images/fai_script.png';
446 $types[$itemName]['category'] = 'Device';
447 $types[$itemName]['class'] = 'Device';
448 }
449 }
451 return($types);
452 }
455 /*! \brief The plugins ACL and plugin-property definition.
456 * @return
457 */
458 public static function plInfo()
459 {
460 return (array(
461 "plShortName" => _("Config management"),
462 "plDescription" => _("Config management"),
463 "plSelfModify" => FALSE,
464 "plDepends" => array(),
465 "plPriority" => 0,
466 "plSection" => array("administration"),
467 "plCategory" => array(
468 "newConfigManagement" => array("description" => _("Config management"),
469 "objectClass" => "FAKE_OC_newConfigManagement")),
470 "plProvidedAcls"=> array()
471 ));
472 }
475 /*! \brief Acts on open requests.
476 * (This action is received from the ConfigManagementListing class.)
477 * @param Array The items ids. (May contain multiple ids)
478 * @return
479 */
480 function openEntry($ids)
481 {
482 $id = $ids[0];
483 $item = $this->dataModel->getItemById($id);
484 $this->setCurrentContainer($item['path']);
485 return;
486 }
490 /*! \brief Removes an entry from the listing.
491 */
492 function removeEntry($ids)
493 {
494 foreach($ids as $id){
495 $item = $this->dataModel->getItemById($id);
497 // Is an config item.
498 if($this->cfgItemMap[$item['type']] != 'root'){
499 $release = $this->getReleasePart($item['path']);
500 $path = $this->getItemPath($item['path']);
501 $rpc = $this->config->getRpcHandle();
502 $rpc->removeConfigItem($release, $path);
503 if(!$rpc->success()){
504 msg_dialog::display(_("Error"), sprintf(_("Failed to remove: %s"), $rpc->get_error()),ERROR_DIALOG);
505 return(NULL);
506 }else{
507 $this->dataModel->removeItem($item['path']);
508 }
509 }else{
511 // Remove distribution
512 if($item['type'] == 'Distribution'){
514 $dist = $this->getDistributionPart($item['path']);
515 $rpc = $this->config->getRpcHandle();
516 $rpc->removeDistribution($dist, array('recursive' => TRUE));
517 if(!$rpc->success()){
518 msg_dialog::display(_("Error"), sprintf(_("Failed to remove the distribution: %s. Error was: %s"),
519 $dist, $rpc->get_error()), ERROR_DIALOG);
520 return(NULL);
521 }else{
522 $this->dataModel->removeItem($item['path']);
523 }
524 }elseif($item['type'] == 'Release'){
526 // Remove release
527 $release = preg_replace("/^.*\//","", $this->getReleasePart($item['path']));
528 $rpc = $this->config->getRpcHandle();
529 $rpc->removeRelease($release, array('recursive' => TRUE));
530 if(!$rpc->success()){
531 msg_dialog::display(_("Error"), sprintf(_("Failed to remove the release: %s. Error was: %s"),
532 $release, $rpc->get_error()),ERROR_DIALOG);
533 return(NULL);
534 }else{
535 $this->dataModel->removeItem($item['path']);
536 }
538 }else{
539 trigger_error($item['type']." - are not handled yet!");
540 }
541 }
542 }
543 }
546 /*! \brief Returns a list of used item names for a given path.
547 */
548 function getUsedNamesForPath($path)
549 {
550 $item = $this->dataModel->getItemByPath($path);
551 $names = array();
552 foreach($item['children'] as $path => $data){
553 $names[] = $data['name'];
554 }
555 return($names);
556 }
559 /*! \brief Edits a selected list item.
560 */
561 function editEntry($ids)
562 {
563 $item = $this->dataModel->getItemById($ids[0]);
564 $release = $this->getReleasePart($item['path']);
565 $path = $this->getItemPath($item['path']);
566 $method = $this->cfgItemMap[$item['type']];
568 // Load item values on demand
569 if($this->cfgItemMap[$item['type']] != 'root'){
570 if($item['status'] == '-'){
571 $rpc = $this->config->getRpcHandle();
572 $res = $rpc->getConfigItem($release, $path);
573 if(!$rpc->success()){
574 msg_dialog::display(_("Error"), sprintf(_("Failed to load config item details: %s"), $rpc->get_error()),ERROR_DIALOG);
575 return;
576 }else{
577 $item['values'] = $res;
578 $this->dataModel->setItemStatus($item['path'], 'fetched');
579 $this->dataModel->setItemValues($item['path'], $item['values']);
580 }
581 }
582 }elseif($item['type'] == 'Template'){
583 if($item['status'] == '-'){
584 $rpc = $this->config->getRpcHandle();
585 $res = $rpc->installGetTemplate($item['name']);
586 if(!$rpc->success()){
587 msg_dialog::display(_("Error"), sprintf(_("Failed to load template details: %s"), $rpc->get_error()),ERROR_DIALOG);
588 return;
589 }else{
590 $item['values'] = $res;
591 $this->dataModel->setItemStatus($item['path'], 'fetched');
592 $this->dataModel->setItemValues($item['path'], $item['values']);
593 }
594 }
595 }
597 $this->TemplateEngine->load($this->itemConfig);
598 $this->TemplateEngine->setTemplate($method.".tpl");
599 $this->TemplateEngine->editItem($item['type'],$item['values']);
600 $this->listing->setDialogObject($this->TemplateEngine);
601 $this->currentObject = $item;
602 }
605 /*! \brief Initiates the creation of a new item
606 */
607 function newEntry($type)
608 {
609 // We've to add a config item
610 $this->TemplateEngine->load($this->itemConfig);
611 if($this->cfgItemMap[$type] != 'root'){
612 $method = $this->cfgItemMap[$type];
613 $this->TemplateEngine->setTemplate($method.".tpl");
614 $this->TemplateEngine->createItem($type,array());
615 $this->listing->setDialogObject($this->TemplateEngine);
616 $this->currentObject = NULL;
617 }else{
618 $this->TemplateEngine->setTemplate("root.tpl");
619 $this->TemplateEngine->createItem($type,array());
620 $this->listing->setDialogObject($this->TemplateEngine);
621 $this->currentObject = NULL;
622 }
623 }
626 /*! \brief Extracts the item-path out of a path.
627 * e.g. /debian/squeeze/test/module -> /test/module
628 */
629 function getItemPath($fullPath)
630 {
631 $fPath = $fullPath.'/';
632 while(preg_match("/\//", $fPath)){
633 $fPath = preg_replace("/\/[^\/]*$/","", $fPath);
634 $item = $this->dataModel->getItemByPath($fPath);
635 if(in_array($item['type'], array('Release', 'Distribution', 'root'))){
636 return(preg_replace("/".preg_quote($item['path'],'/')."/", "", $fullPath));
637 }
638 }
639 return(NULL);
640 }
643 /*! \brief Extracts the releaes path out of a path.
644 * e.g. /debian/squeeze/test/module -> /debian/squeeze
645 */
646 function getReleasePath($fullPath)
647 {
648 $fullPath.='/';
649 while(preg_match("/\//", $fullPath)){
650 $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
651 $item = $this->dataModel->getItemByPath($fullPath);
652 if($item['type'] == 'Release'){
653 return($fullPath);
654 }
655 }
656 return(NULL);
657 }
660 /*! \brief Extracts the distribution path out of a path.
661 * e.g. /root/debian/squeeze/test/module -> /root/debian
662 */
663 function getDistributionPath($fullPath)
664 {
665 $fullPath.='/';
666 while(preg_match("/\//", $fullPath)){
667 $fullPath = preg_replace("/\/[^\/]*$/","", $fullPath);
668 $item = $this->dataModel->getItemByPath($fullPath);
669 if($item['type'] == 'Distribution'){
670 return($fullPath);
671 }
672 }
673 return(NULL);
674 }
677 /*! \brief Extracts the distribution-part out of a path.
678 * e.g. /root/debian/squeeze/test/module -> debian
679 */
680 function getDistributionPart($fullPath)
681 {
682 return(trim(preg_replace("#^/root/#","", $this->getDistributionPath($fullPath)), '/'));
683 }
686 /*! \brief Extracts the release-part out of a path.
687 * e.g. /root/debian/squeeze/test/module -> squeeze/test
688 */
689 function getReleasePart($path)
690 {
691 $rPath = $this->getReleasePath($path);
692 $dPath = $this->getDistributionPath($path);
693 return(preg_replace("/^".preg_quote($dPath, '/')."\/?/", "", $rPath));
694 }
697 function saveItemChanges()
698 {
699 // Save template engine modifications and validate values.
700 $this->TemplateEngine->save_object();
701 $msgs = $this->TemplateEngine->check();
703 // Get values to be saved
704 $values = array();
705 foreach($this->TemplateEngine->getWidgets() as $w){
706 $values[$w->getName()] = $w->getValue();
707 }
709 // No input error were found, now check that we do not use the same name twice
710 // and that it is valid.
711 if(!count($msgs)){
713 // Get used item names for the current path
714 if($this->currentObject){
716 // Get used item names in the parent path.
717 $usedNames = $this->getUsedNamesForPath($this->currentObject['parentPath']);
718 }else{
720 // Get used items for the selected path.
721 $usedNames = $this->getUsedNamesForPath($this->selectedContainer);
722 }
724 // Allow the item to keep its name.
725 if($this->currentObject != NULL && isset($this->currentObject['values']['name'])){
726 $usedNames = array_remove_entries(array($this->currentObject['values']['name']), $usedNames);
727 }
728 if(in_array($values['name'],$usedNames)){
729 $msgs[] = msgPool::duplicated(_("Name"));
730 #}elseif(preg_match("/[^a-z0-9\.]/i",$values['name'])){
731 # $msgs[] = msgPool::invalid(_("Name"), $values['name'], '/[a-z0-9\.]/');
732 }
733 }
735 // Display errors
736 if(count($msgs)){
737 msg_dialog::displayChecks($msgs);
738 return;
739 }
741 // Get the item type to be saved
742 $item = $this->currentObject;
743 $type = $this->TemplateEngine->getItemType();
744 if($this->cfgItemMap[$type] == 'root'){
746 // We've to create a new distribution
747 if($type == 'Distribution'){
749 // Distributions cannot be renamed!
750 if(isset($item['name']) && $item['name'] != $values['name']){
751 msg_dialog::displayChecks(array("Distributions cannot be renamed!"));
752 return;
753 }
755 // Create a new distribution
756 if(!$item){
757 $name = $values['name'];
758 $itype = $values['installation_type'];
759 $imethod = $values['installation_method'];
760 $origin = $values['origin'];
762 // Initiate the rpc request.
763 $rpc = $this->config->getRpcHandle();
764 $res = $rpc->createDistribution($name, $itype, array('mirror'=>$origin, 'install_method' => $imethod));
765 if(!$rpc->success()){
766 msg_dialog::display(_("Error"), sprintf(_("Failed to save distributions: %s"),
767 $rpc->get_error()),ERROR_DIALOG);
768 return(NULL);
769 }
770 }
772 // Collect distribution properties
773 $data = array();
774 $data['distribution'] = $values['name'];
775 $data['arch'] = $values['architectures'];
776 $data['component'] = $values['components'];
777 $data['mirror_sources'] = $values['mirror_sources'];
779 // Set distribution properties
780 $rpc = $this->config->getRpcHandle();
781 $rpc->setDistribution($data);
782 if(!$rpc->success()){
783 msg_dialog::display(_("Error"), sprintf(_("Failed to save distribution properties: %s"),
784 $rpc->get_error()),ERROR_DIALOG);
785 return(NULL);
786 }
788 // We've successfully added the item, now add it to the tree.
789 $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
791 // Finally - close the dialog.
792 $this->listing->clearDialogObject();
794 }elseif($type == 'Release'){
796 // We've to update a release.
797 if($item){
799 // Check if we've to rename the item.
800 $path = $this->getReleasePart($item['parentPath']);
801 $curPath = $this->getReleasePart($item['path']);
802 $newPath = trim($path."/".$values['name'], '/');
803 if($curPath != $newPath){
804 $rpc = $this->config->getRpcHandle();
805 $res = $rpc->renameRelease($curPath, $newPath);
806 if(!$rpc->success()){
807 msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
808 return(NULL);
809 }else{
810 $nP = $item['parentPath'].'/'.$values['name'];
811 $this->dataModel->moveItem($item['path'], $nP);
812 $this->dataModel->setItemValues($nP, $values);
813 $this->listing->clearDialogObject();
814 }
815 }else{
816 $this->listing->clearDialogObject();
817 }
820 }else{
822 // Build up the new release path.
823 $name = $values['name'];
824 $rPath = $this->getReleasePart($this->selectedContainer);
825 $newPath = trim($rPath."/".$name, '/');
827 // Detect the parent distribution
828 $dist = $this->getDistributionPart($this->selectedContainer);
830 // Initiate the rpc request.
831 $rpc = $this->config->getRpcHandle();
832 $res = $rpc->createRelease($dist, $newPath);
833 if(!$rpc->success()){
834 msg_dialog::display(_("Error"), sprintf(_("Failed to save release: %s"), $rpc->get_error()),ERROR_DIALOG);
835 return(NULL);
836 }else{
838 // We've successfully added/saved the item, now add it to the tree.
839 $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],$values, '-' );
840 $this->listing->clearDialogObject();
841 }
842 }
843 }else{
844 echo "{$type} Cannot be saved yet";
845 $this->listing->clearDialogObject();
846 return;
847 }
848 }
850 // Save a CONFIG-ITEM object.
851 if($this->cfgItemMap[$type] != 'root'){
853 // Get paths
854 $release = $this->getReleasePart($this->selectedContainer);
856 if($item){
857 $oldPath = $item['path'];
858 $oldItemPath = $this->getItemPath($item['path']);
859 $newPath = $item['parentPath']."/".$values['name'];
860 $newItemPath = $this->getItemPath($newPath);
861 }else{
862 $newPath = $this->selectedContainer."/".$values['name'];
863 $newItemPath = $this->getItemPath($this->selectedContainer)."/".$values['name'];
864 }
866 // If this is a new item, then create it now.
867 if($item == NULL){
869 // Add the new item
870 $rpc = $this->config->getRpcHandle();
871 $res = $rpc->setConfigItem($release, $newItemPath, $type, $values);
872 if(!$rpc->success()){
873 msg_dialog::display(_("Error"), sprintf(_("Failed to save %s: %s"),$type, $rpc->get_error()),ERROR_DIALOG);
874 return(NULL);
875 }else{
877 // We've successfully added the item, now add it to the tree.
878 $this->dataModel->addItem($type, $this->selectedContainer, $values['name'],array(), '-' );
880 // Finally - close the dialog.
881 $this->listing->clearDialogObject();
882 }
883 }else{
885 // Write the modifications back to the server.
886 $rpc = $this->config->getRpcHandle();
887 $res = $rpc->setConfigItem($release, $oldItemPath, $type, $values);
888 if(!$rpc->success()){
889 msg_dialog::display(_("Error"), sprintf(_("Failed to save config item: %s"), $rpc->get_error()),ERROR_DIALOG);
890 return(NULL);
891 }else{
893 // Update the data model
894 $this->dataModel->setItemValues($oldPath, $values);
895 if($oldPath != $newPath){
896 $this->dataModel->moveItem($oldPath, $newPath);
897 }
898 $this->listing->clearDialogObject();
899 }
900 }
901 }
902 }
903 function remove_lock() {}
904 }
907 ?>