1 <?php
2 /*
3 * This code is part of GOsa (http://www.gosa-project.org)
4 * Copyright (C) 2003-2008 GONICUS GmbH
5 *
6 * ID: $$Id$$
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
23 class management
24 {
25 // Public
26 public $config = null;
27 public $ui = null;
29 // The plugin description
30 public $plugname = "unconfigured";
31 public $plIcon = "unconfigured";
32 public $plDescription = "unconfigured";
33 public $plHeadline = "unconfigured";
35 // The currently used object(s) (e.g. in edit, removal)
36 protected $dn = "";
37 protected $dns = array();
39 // The last used object(s).
40 protected $last_dn = "";
41 protected $last_dns = array();
43 // The common places the displayed objects are stored in. (e.g. array("ou=groups,",".."))
44 protected $storagePoints = array();
46 // The tab definitions to use for the current object.
47 protected $tabClass = ""; // e.g. usertabs
48 protected $tabType = ""; // e.g. USERTABS
49 protected $aclCategory = ""; // e.g. users
50 protected $objectName = ""; // e.g. users
52 // The opened object.
53 protected $tabObject = null;
54 protected $dialogObject = null;
56 // The last opened object.
57 protected $last_tabObject = null;
58 protected $last_dialogObject = null;
60 // Whether to display the apply button or not
61 protected $displayApplyBtn = "";
63 // Whether to display a footer or not.
64 protected $skipFooter = false;
66 // Copy&Paste handler
67 protected $cpHandler = null;
69 // Indicates that we want to paste objects right now.
70 protected $cpPastingStarted = FALSE;
72 // The Snapshot handler class.
73 protected $snapHandler = null;
75 // The listing handlers
76 private $headpage = null;
77 private $filter = null;
79 // A list of configured actions/events
80 protected $actions = array();
82 function __construct(&$config,$ui,$plugname, $headpage)
83 {
84 $this->plugname = $plugname;
85 $this->headpage = $headpage;
86 $this->ui = $ui;
87 $this->config = $config;
89 if($this->cpHandler) $this->headpage->setCopyPasteHandler($this->cpHandler);
90 if($this->snapHandler) $this->headpage->setSnapshotHandler($this->snapHandler);
92 if(empty($this->plIcon)){
93 $this->plIcon = "plugins/".$plugname."/images/plugin.png";
94 }
96 // Register default actions
97 $this->registerAction("new", "newEntry");
98 $this->registerAction("edit", "editEntry");
99 $this->registerAction("apply", "applyChanges");
100 $this->registerAction("save", "saveChanges");
101 $this->registerAction("cancel", "cancelEdit");
102 $this->registerAction("cancelDelete", "cancelEdit");
103 $this->registerAction("remove", "removeEntryRequested");
104 $this->registerAction("removeConfirmed", "removeEntryConfirmed");
106 $this->registerAction("copy", "copyPasteHandler");
107 $this->registerAction("cut", "copyPasteHandler");
108 $this->registerAction("paste", "copyPasteHandler");
110 $this->registerAction("snapshot", "createSnapshotDialog");
111 $this->registerAction("restore", "restoreSnapshotDialog");
112 $this->registerAction("saveSnapshot","saveSnapshot");
113 $this->registerAction("restoreSnapshot","restoreSnapshot");
114 $this->registerAction("cancelSnapshot","closeDialogs");
115 }
117 /*! \brief Execute this plugin
118 * Handle actions/events, locking, snapshots, dialogs, tabs,...
119 */
120 function execute()
121 {
122 // Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog.
123 $vars = array('/^act$/','/^listing/','/^PID$/','/^FILTER_PID$/');
124 session::set('LOCK_VARS_TO_USE',$vars);
126 /* Display the copy & paste dialog, if it is currently open */
127 $ret = $this->copyPasteHandler("",array());
128 if($ret){
129 return($this->getHeader().$ret);
130 }
132 // Update filter
133 if ($this->filter) {
134 $this->filter->update();
135 session::global_set(get_class($this)."_filter", $this->filter);
136 session::set('autocomplete', $this->filter);
137 if (!$this->filter->isValid()){
138 msg_dialog::display(_("Filter error"), _("The filter is incomplete!"), ERROR_DIALOG);
139 }
140 }
142 // Handle actions (POSTs and GETs)
143 $str = $this->handleActions($this->detectPostActions());
144 if($str) return($this->getHeader().$str);
146 // Open single dialog objects
147 if(is_object($this->dialogObject)){
148 if(method_exists($this->dialogObject,'save_object')) $this->dialogObject->save_object();
149 if(method_exists($this->dialogObject,'execute')){
150 $display = $this->dialogObject->execute();
151 $display.= $this->_getTabFooter();
152 return($this->getHeader().$display);
153 }
154 }
156 // Display tab object.
157 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
158 $this->tabObject->save_object();
159 $display = $this->tabObject->execute();
160 $display.= $this->_getTabFooter();
161 return($this->getHeader().$display);
162 }
164 // Set current restore base for snapshot handling.
165 if(is_object($this->snapHandler)){
166 $bases = array();
167 foreach($this->storagePoints as $sp){
168 $bases[] = $sp.$this->headpage->getBase();
169 }
171 // No bases specified? Try base
172 if(!count($bases)) $bases[] = $this->headpage->getBase();
174 $this->snapHandler->setSnapshotBases($bases);
175 }
177 // Display list
178 return($this->renderList());
179 }
181 function renderList()
182 {
183 $this->headpage->update();
184 $display = $this->headpage->render();
185 return($this->getHeader().$display);
186 }
188 function getHeadpage()
189 {
190 return($this->headpage);
191 }
193 function getFilter()
194 {
195 return($this->filter);
196 }
198 /*! \brief Generates the plugin header which is displayed whenever a tab object is
199 * opened.
200 */
201 protected function getHeader()
202 {
203 if (get_object_info() != ""){
204 $display= print_header(get_template_path($this->plIcon),_($this->plDescription),
205 "<img alt=\"\" class=\"center\" src=\"".get_template_path('images/lists/locked.png')."\">".
206 LDAP::fix(get_object_info()));
207 } else {
208 $display= print_header(get_template_path($this->plIcon),_($this->plDescription));
209 }
210 return($display);
211 }
214 /*! \brief Generates the footer which is used whenever a tab object is
215 * displayed.
216 */
217 protected function _getTabFooter()
218 {
219 // Do not display tab footer for non tab objects
220 if(!($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug)){
221 return("");
222 }
224 // Check if there is a dialog opened - We don't need any buttons in this case.
225 if($this->tabObject->by_object[$this->tabObject->current]){
226 $current = $this->tabObject->by_object[$this->tabObject->current];
227 if(isset($current->dialog) && (is_object($current->dialog) || $current->dialog)){
228 return("");
229 }
230 }
232 // Skip footer if requested;
233 if($this->skipFooter) return("");
235 // In case an of locked entry, we may have opened a read-only tab.
236 $str = "";
237 if(isset($this->tabObject->read_only) && $this->tabObject->read_only == TRUE){
238 $str.= "<p style=\"text-align:right\">
239 <input type=submit name=\"edit_cancel\" value=\"".msgPool::cancelButton()."\">
240 </p>";
241 return($str);
242 }else{
244 // Display ok, (apply) and cancel buttons
245 $str.= "<p style=\"text-align:right\">\n";
246 $str.= "<input type=submit name=\"edit_finish\" style=\"width:80px\" value=\"".msgPool::okButton()."\">\n";
247 $str.= " \n";
248 if($this->displayApplyBtn){
249 $str.= "<input type=submit name=\"edit_apply\" value=\"".msgPool::applyButton()."\">\n";
250 $str.= " \n";
251 }
252 $str.= "<input type=submit name=\"edit_cancel\" value=\"".msgPool::cancelButton()."\">\n";
253 $str.= "</p>";
254 }
255 return($str);
256 }
259 /*! \brief Initiates the removal for the given entries
260 * and displays a confirmation dialog.
261 *
262 * @param String 'action' The name of the action which was the used as trigger.
263 * @param Array 'target' A list of object dns, which should be affected by this method.
264 * @param Array 'all' A combination of both 'action' and 'target'.
265 */
266 protected function removeEntryRequested($action="",$target=array(),$all=array())
267 {
268 $disallowed = array();
269 $this->dns = array();
271 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel requested!");
273 // Check permissons for each target
274 foreach($target as $dn){
275 $acl = $this->ui->get_permissions($dn, $this->aclCategory."/".$this->aclPlugin);
276 if(preg_match("/d/",$acl)){
277 $this->dns[] = $dn;
278 }else{
279 $disallowed[] = $dn;
280 }
281 }
282 if(count($disallowed)){
283 msg_dialog::display(_("Permission"),msgPool::permDelete($disallowed),INFO_DIALOG);
284 }
286 // We've at least one entry to delete.
287 if(count($this->dns)){
289 // check locks
290 if ($user= get_multiple_locks($this->dns)){
291 return(gen_locked_message($user,$this->dns));
292 }
294 // Add locks
295 $dns_names = array();
296 foreach($this->dns as $dn){
297 $dns_names[] =LDAP::fix($dn);
298 }
299 add_lock ($this->dns, $this->ui->dn);
301 // Display confirmation dialog.
302 $smarty = get_smarty();
303 $smarty->assign("info", msgPool::deleteInfo($dns_names,_($this->objectName)));
304 $smarty->assign("multiple", true);
305 return($smarty->fetch(get_template_path('remove.tpl', TRUE)));
306 }
307 }
310 /*! \brief Object removal was confirmed, now remove the requested entries.
311 *
312 * @param String 'action' The name of the action which was the used as trigger.
313 * @param Array 'target' A list of object dns, which should be affected by this method.
314 * @param Array 'all' A combination of both 'action' and 'target'.
315 */
316 function removeEntryConfirmed($action="",$target=array(),$all=array(),
317 $altTabClass="",$altTabType="",$altAclCategory="")
318 {
319 $tabType = $this->tabType;
320 $tabClass = $this->tabClass;
321 $aclCategory = $this->aclCategory;
322 if(!empty($altTabClass)) $tabClass = $altTabClass;
323 if(!empty($altTabType)) $tabType = $altTabType;
324 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
326 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel confirmed!");
328 foreach($this->dns as $key => $dn){
330 // Check permissions, are we allowed to remove this object?
331 $acl = $this->ui->get_permissions($dn, $this->aclCategory."/".$this->aclPlugin);
332 if(preg_match("/d/",$acl)){
334 // Delete the object
335 $this->dn = $dn;
336 $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$tabType], $this->dn, $aclCategory, true, true);
337 $this->tabObject->set_acl_base($this->dn);
338 $this->tabObject->delete ();
339 $this->tabObject->parent = &$this;
341 // Remove the lock for the current object.
342 del_lock($this->dn);
343 } else {
344 msg_dialog::display(_("Permission error"), msgPool::permDelete(), ERROR_DIALOG);
345 new log("security","groups/".get_class($this),$dn,array(),"Tried to trick deletion.");
346 }
347 }
349 // Cleanup
350 $this->remove_lock();
351 $this->closeDialogs();
352 }
355 /*! \brief Detects actions/events send by the ui
356 * and the corresponding targets.
357 */
358 function detectPostActions()
359 {
360 if(!is_object($this->headpage)){
361 trigger_error("No valid headpage given....!");
362 return(array());
363 }
364 $action= $this->headpage->getAction();
365 if(isset($_POST['edit_apply'])) $action['action'] = "apply";
366 if(isset($_POST['edit_finish'])) $action['action'] = "save";
367 if(isset($_POST['edit_cancel'])) $action['action'] = "cancel";
368 if(isset($_POST['delete_confirmed'])) $action['action'] = "removeConfirmed";
369 if(isset($_POST['delete_cancel'])) $action['action'] = "cancelDelete";
371 // Detect Snapshot actions
372 if(isset($_POST['CreateSnapshot'])) $action['action'] = "saveSnapshot";
373 if(isset($_POST['CancelSnapshot'])) $action['action'] = "cancelSnapshot";
374 foreach($_POST as $name => $value){
375 $once =TRUE;
376 if(preg_match("/^RestoreSnapShot_/",$name) && $once){
377 $once = FALSE;
378 $entry = base64_decode(preg_replace("/^RestoreSnapShot_([^_]*)_[xy]$/i","\\1",$name));
379 $action['action'] = "restoreSnapshot";
380 $action['targets'] = array($entry);
381 }
382 }
384 return($action);
385 }
388 /*! \brief Calls the registered method for a given action/event.
389 */
390 function handleActions($action)
391 {
392 // Start action
393 if(isset($this->actions[$action['action']])){
394 $func = $this->actions[$action['action']];
395 if(!isset($action['targets']))$action['targets']= array();
396 return($this->$func($action['action'],$action['targets'],$action));
397 }
398 }
401 /*! \brief Opens the snapshot creation dialog for the given target.
402 *
403 * @param String 'action' The name of the action which was the used as trigger.
404 * @param Array 'target' A list of object dns, which should be affected by this method.
405 * @param Array 'all' A combination of both 'action' and 'target'.
406 */
407 function createSnapshotDialog($action="",$target=array(),$all=array())
408 {
409 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Snaptshot creation initiated!");
411 foreach($target as $entry){
412 if(!empty($entry) && $this->ui->allow_snapshot_create($entry,$this->aclCategory)){
413 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
414 $this->dialogObject->aclCategories = array($this->aclCategory);
415 $this->dialogObject->parent = &$this;
417 }else{
418 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to create a snapshot for %s."),$entry),
419 ERROR_DIALOG);
420 }
421 }
422 }
425 /*! \brief Creates a snapshot new entry - This method is called when the somebody
426 * clicks 'save' in the "Create snapshot dialog" (see ::createSnapshotDialog).
427 *
428 * @param String 'action' The name of the action which was the used as trigger.
429 * @param Array 'target' A list of object dns, which should be affected by this method.
430 * @param Array 'all' A combination of both 'action' and 'target'.
431 */
432 function saveSnapshot($action="",$target=array(),$all=array())
433 {
434 $this->dialogObject->save_object();
435 $msgs = $this->dialogObject->check();
436 if(count($msgs)){
437 foreach($msgs as $msg){
438 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
439 }
440 }else{
441 $this->dn = $this->dialogObject->dn;
442 $this->snapHandler->create_snapshot( $this->dn,$this->dialogObject->CurrentDescription);
443 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Snaptshot created!");
444 $this->closeDialogs();
445 }
446 }
449 /*! \brief Restores a snapshot object.
450 * The dn of the snapshot entry has to be given as ['target'] parameter.
451 *
452 * @param String 'action' The name of the action which was the used as trigger.
453 * @param Array 'target' A list of object dns, which should be affected by this method.
454 * @param Array 'all' A combination of both 'action' and 'target'.
455 */
456 function restoreSnapshot($action="",$target=array(),$all=array())
457 {
458 $entry = array_pop($target);
459 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
460 $this->snapHandler->restore_snapshot($entry);
461 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Snaptshot restored!");
462 $this->closeDialogs();
463 }else{
464 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
465 ERROR_DIALOG);
466 }
467 }
470 /*! \brief Displays the "Restore snapshot dialog" for a given target.
471 * If no target is specified, open the restore removed object
472 * dialog.
473 * @param String 'action' The name of the action which was the used as trigger.
474 * @param Array 'target' A list of object dns, which should be affected by this method.
475 * @param Array 'all' A combination of both 'action' and 'target'.
476 */
477 function restoreSnapshotDialog($action="",$target=array(),$all=array())
478 {
479 // Set current restore base for snapshot handling.
480 if(is_object($this->snapHandler)){
481 $bases = array();
482 foreach($this->storagePoints as $sp){
483 $bases[] = $sp.$this->headpage->getBase();
484 }
485 }
487 // No bases specified? Try base
488 if(!count($bases)) $bases[] = $this->headpage->getBase();
490 // No target, open the restore removed object dialog.
491 if(!count($target)){
492 $entry = $this->headpage->getBase();
493 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
494 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry,"Snaptshot restoring initiated!");
495 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
496 $this->dialogObject->set_snapshot_bases($bases);
497 $this->dialogObject->display_all_removed_objects = true;
498 $this->dialogObject->display_restore_dialog = true;
499 $this->dialogObject->parent = &$this;
500 }else{
501 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
502 ERROR_DIALOG);
503 }
504 }else{
506 // Display the restore points for a given object.
507 $entry = array_pop($target);
508 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
509 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry,"Snaptshot restoring initiated!");
510 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
511 $this->dialogObject->set_snapshot_bases($bases);
512 $this->dialogObject->display_restore_dialog = true;
513 $this->dialogObject->parent = &$this;
514 }else{
515 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s."),$entry),
516 ERROR_DIALOG);
517 }
518 }
519 }
522 /*! \brief This method intiates the object creation.
523 *
524 * @param String 'action' The name of the action which was the used as trigger.
525 * @param Array 'target' A list of object dns, which should be affected by this method.
526 * @param Array 'all' A combination of both 'action' and 'target'.
527 */
528 function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
529 {
530 /* To handle mutliple object types overload this method.
531 * ...
532 * registerAction('newUser', 'newEntry');
533 * registerAction('newGroup','newEntry');
534 * ...
535 *
536 * function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
537 * {
538 * switch($action){
539 * case 'newUser' : {
540 * mangement::newEntry($action,$target,$all,"usertabs","USERTABS","users");
541 * }
542 * case 'newGroup' : {
543 * mangement::newEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
544 * }
545 * }
546 * }
547 **/
548 $tabType = $this->tabType;
549 $tabClass = $this->tabClass;
550 $aclCategory = $this->aclCategory;
551 if(!empty($altTabClass)) $tabClass = $altTabClass;
552 if(!empty($altTabType)) $tabType = $altTabType;
553 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
555 // Check locking & lock entry if required
556 $this->displayApplyBtn = FALSE;
557 $this->dn = "new";
558 $this->is_new = TRUE;
559 $this->is_single_edit = FALSE;
560 $this->is_multiple_edit = FALSE;
562 set_object_info($this->dn);
564 // Open object.
565 if(empty($tabClass) || empty($tabType)){
566 // No tab type defined
567 }else{
568 $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$tabType], $this->dn, $aclCategory);
569 $this->tabObject->set_acl_base($this->headpage->getBase());
570 $this->tabObject->parent = &$this;
571 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Create new entry initiated!");
572 }
573 }
576 /*! \brief This method opens an existing object or a list of existing objects to be edited.
577 *
578 *
579 * @param String 'action' The name of the action which was the used as trigger.
580 * @param Array 'target' A list of object dns, which should be affected by this method.
581 * @param Array 'all' A combination of both 'action' and 'target'.
582 */
583 function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
584 {
585 /* To handle mutliple object types overload this method.
586 * ...
587 * registerAction('editUser', 'editEntry');
588 * registerAction('editGroup','editEntry');
589 * ...
590 *
591 * function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
592 * {
593 * switch($action){
594 * case 'editUser' : {
595 * mangement::editEntry($action,$target,$all,"usertabs","USERTABS","users");
596 * }
597 * case 'editGroup' : {
598 * mangement::editEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
599 * }
600 * }
601 * }
602 **/
604 // Do not create a new tabObject while there is already one opened,
605 // the user may have just pressed F5 to reload the page.
606 if(is_object($this->tabObject)){
607 return;
608 }
610 $tabType = $this->tabType;
611 $tabClass = $this->tabClass;
612 $aclCategory = $this->aclCategory;
613 if(!empty($altTabClass)) $tabClass = $altTabClass;
614 if(!empty($altTabType)) $tabType = $altTabType;
615 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
617 // Single edit - we only got one object dn.
618 if(count($target) == 1){
619 $this->displayApplyBtn = TRUE;
620 $this->is_new = FALSE;
621 $this->is_single_edit = TRUE;
622 $this->is_multiple_edit = FALSE;
624 // Get the dn of the object and creates lock
625 $this->dn = array_pop($target);
626 set_object_info($this->dn);
627 $user = get_lock($this->dn);
628 if ($user != ""){
629 return(gen_locked_message ($user, $this->dn,TRUE));
630 }
631 add_lock ($this->dn, $this->ui->dn);
633 // Open object.
634 if(empty($tabClass) || empty($tabType)){
635 trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
636 }else{
637 $tab = $tabClass;
638 $this->tabObject= new $tab($this->config,$this->config->data['TABS'][$tabType], $this->dn,$aclCategory);
639 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Edit entry initiated!");
640 $this->tabObject->set_acl_base($this->dn);
641 $this->tabObject->parent = &$this;
642 }
643 }else{
645 // We've multiple entries to edit.
646 $this->is_new = FALSE;
647 $this->is_singel_edit = FALSE;
648 $this->is_multiple_edit = TRUE;
650 // Open multiple edit handler.
651 if(empty($tabClass) || empty($tabType)){
652 trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
653 }else{
654 $this->dns = $target;
655 $tmp = new multi_plug($this->config,$tabClass,$this->config->data['TABS'][$tabType],
656 $this->dns,$this->headpage->getBase(),$aclCategory);
658 // Check for locked entries
659 if ($tmp->entries_locked()){
660 return($tmp->display_lock_message());
661 }
663 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Edit entry initiated!");
665 // Now lock entries.
666 $tmp->lock_entries($this->ui->dn);
667 if($tmp->multiple_available()){
668 $this->tabObject = $tmp;
669 set_object_info($this->tabObject->get_object_info());
670 }
671 }
672 }
673 }
676 /*! \brief Save object modifications and closes dialogs (returns to object listing).
677 * - Calls '::check' to validate the given input.
678 * - Calls '::save' to save back object modifications (e.g. to ldap).
679 * - Calls '::remove_locks' to remove eventually created locks.
680 * - Calls '::closeDialogs' to return to the object listing.
681 */
682 protected function saveChanges()
683 {
684 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
685 $this->tabObject->save_object();
686 $msgs = $this->tabObject->check();
687 if(count($msgs)){
688 msg_dialog::displayChecks($msgs);
689 return("");
690 }else{
691 $this->tabObject->save();
692 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Entry saved!");
693 $this->remove_lock();
694 $this->closeDialogs();
695 }
696 }elseif($this->dialogObject instanceOf plugin){
697 $this->dialogObject->save_object();
698 $msgs = $this->dialogObject->check();
699 if(count($msgs)){
700 msg_dialog::displayChecks($msgs);
701 return("");
702 }else{
703 $this->dialogObject->save();
704 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Entry saved!");
705 $this->remove_lock();
706 $this->closeDialogs();
707 }
708 }
709 }
712 /*! \brief Save object modifications and keep dialogs opened.
713 * - Calls '::check' to validate the given input.
714 * - Calls '::save' to save back object modifications (e.g. to ldap).
715 */
716 protected function applyChanges()
717 {
718 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
719 $this->tabObject->save_object();
720 $msgs = $this->tabObject->check();
721 if(count($msgs)){
722 msg_dialog::displayChecks($msgs);
723 return("");
724 }else{
725 $this->tabObject->save();
726 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Modifications applied!");
727 $this->tabObject->re_init();
728 }
729 }
730 }
733 /*! \brief This method closes dialogs
734 * and cleans up the cached object info and the ui.
735 */
736 protected function closeDialogs()
737 {
738 $this->last_dn = $this->dn;
739 $this->last_dns = $this->dns;
740 $this->last_tabObject = $this->tabObject;
741 $this->last_dialogObject = $this->dialogObject;
742 $this->dn = "";
743 $this->dns = array();
744 $this->tabObject = null;
745 $this->dialogObject = null;
746 set_object_info();
747 }
750 /*! \brief Editing an object was caneled.
751 * Close dialogs/tabs and remove locks.
752 */
753 protected function cancelEdit()
754 {
755 $this->remove_lock();
756 $this->closeDialogs();
757 }
760 /*! \brief Every click in the list user interface sends an event
761 * here can we connect those events to a method.
762 * eg. ::registerEvent('new','createUser')
763 * When the action/event new is send, the method 'createUser'
764 * will be called.
765 */
766 function registerAction($action,$target)
767 {
768 $this->actions[$action] = $target;
769 }
772 /*! \brief Removes ldap object locks created by this class.
773 * Whenever an object is edited, we create locks to avoid
774 * concurrent modifications.
775 * This locks will automatically removed here.
776 */
777 function remove_lock()
778 {
779 if(!empty($this->dn) && $this->dn != "new"){
780 del_lock($this->dn);
781 }
782 if(count($this->dns)){
783 del_lock($this->dns);
784 }
785 }
788 /*! \brief This method is used to queue and process copy&paste actions.
789 * Allows to copy, cut and paste mutliple entries at once.
790 * @param String 'action' The name of the action which was the used as trigger.
791 * @param Array 'target' A list of object dns, which should be affected by this method.
792 * @param Array 'all' A combination of both 'action' and 'target'.
793 */
794 function copyPasteHandler($action="",$target=array(),$all=array(),
795 $altTabClass ="", $altTabType = "", $altAclCategory="",$altAclPlugin="")
796 {
797 // Return without any actions while copy&paste handler is disabled.
798 if(!is_object($this->cpHandler)) return("");
800 $tabType = $this->tabType;
801 $tabClass = $this->tabClass;
802 $aclCategory = $this->aclCategory;
803 $aclPlugin = $this->aclPlugin;
804 if(!empty($altTabClass)) $tabClass = $altTabClass;
805 if(!empty($altTabType)) $tabType = $altTabType;
806 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
807 if(!empty($altAclPlugin)) $aclPlugin = $altAclPlugin;
809 // Save user input
810 $this->cpHandler->save_object();
812 // Add entries to queue
813 if($action == "copy" || $action == "cut"){
814 $this->cpHandler->cleanup_queue();
815 foreach($target as $dn){
816 if($action == "copy" && $this->ui->is_copyable($dn,$aclCategory,$aclPlugin)){
817 $this->cpHandler->add_to_queue($dn,"copy",$tabClass,$tabType,$aclCategory,$this);
818 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry copied!");
819 }
820 if($action == "cut" && $this->ui->is_cutable($dn,$aclCategory,$aclPlugin)){
821 $this->cpHandler->add_to_queue($dn,"cut",$tabClass,$tabType,$aclCategory,$this);
822 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry cutted!");
823 }
824 }
825 }
827 // Initiate pasting
828 if($action == "paste"){
829 $this->cpPastingStarted = TRUE;
830 }
832 // Display any c&p dialogs, eg. object modifications required before pasting.
833 if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
834 $this->cpHandler->SetVar("base",$this->headpage->getBase());
835 $data = $this->cpHandler->execute();
836 if(!empty($data)){
837 return($data);
838 }
839 }
841 // Automatically disable pasting process since there is no entry left to paste.
842 if(!$this->cpHandler->entries_queued()){
843 $this->cpPastingStarted = FALSE;
844 }
845 return("");
846 }
849 function setFilter($str) {
850 $this->filter = $str;
851 }
853 }
855 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
856 ?>