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 public $dn = ""; // this is public due to some compatibility problems with class plugin..
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 $aclPlugin = ""; // e.g. generic
50 protected $aclCategory = ""; // e.g. users
51 protected $objectName = ""; // e.g. users
53 // The opened object.
54 protected $tabObject = null;
55 protected $dialogObject = null;
57 // The last opened object.
58 protected $last_tabObject = null;
59 protected $last_dialogObject = null;
61 // Whether to display the apply button or not
62 protected $displayApplyBtn = FALSE;
64 // Whether to display a header or not.
65 protected $skipHeader = false;
67 // Whether to display a footer or not.
68 protected $skipFooter = false;
70 // Copy&Paste handler
71 protected $cpHandler = null;
73 // Indicates that we want to paste objects right now.
74 protected $cpPastingStarted = FALSE;
76 // The Snapshot handler class.
77 protected $snapHandler = null;
79 // The listing handlers
80 private $headpage = null;
81 private $filter = null;
83 // A list of configured actions/events
84 protected $actions = array();
86 // Attributes managed by this plugin, can be used in post events;
87 public $attributes = array();
89 function __construct(&$config,$ui,$plugname, $headpage)
90 {
91 $this->plugname = $plugname;
92 $this->headpage = $headpage;
93 $this->ui = $ui;
94 $this->config = $config;
95 $this->initTime = microtime(TRUE);
97 // Create statistic table entry
98 stats::log('management', $class = get_class($this), $this->getAclCategories(), $action = 'open',
99 $amount = 1, $duration = (microtime(TRUE) - $this->initTime));
101 if($this->cpHandler) $this->headpage->setCopyPasteHandler($this->cpHandler);
102 if($this->snapHandler) $this->headpage->setSnapshotHandler($this->snapHandler);
104 if(empty($this->plIcon)){
105 $this->plIcon = "plugins/".$plugname."/images/plugin.png";
106 }
108 // Register default actions
109 $this->registerAction("new", "newEntry");
110 $this->registerAction("edit", "editEntry");
111 $this->registerAction("apply", "applyChanges");
112 $this->registerAction("save", "saveChanges");
113 $this->registerAction("cancel", "cancelEdit");
114 $this->registerAction("cancelDelete", "cancelEdit");
115 $this->registerAction("remove", "removeEntryRequested");
116 $this->registerAction("removeConfirmed", "removeEntryConfirmed");
118 $this->registerAction("copy", "copyPasteHandler");
119 $this->registerAction("cut", "copyPasteHandler");
120 $this->registerAction("paste", "copyPasteHandler");
122 $this->registerAction("snapshot", "createSnapshotDialog");
123 $this->registerAction("restore", "restoreSnapshotDialog");
124 $this->registerAction("saveSnapshot","saveSnapshot");
125 $this->registerAction("restoreSnapshot","restoreSnapshot");
126 $this->registerAction("removeSnapshotConfirmed","removeSnapshotConfirmed");
127 $this->registerAction("cancelSnapshot","closeDialogs");
129 $this->registerAction("config-filter","editFilter");
130 $this->registerAction("saveFilter","saveFilter");
131 $this->registerAction("cancelFilter","cancelFilter");
133 // To temporay disable the filter caching UNcomment this line.
134 #session::global_un_set(get_class($this)."_filter");
135 }
138 /*! \brief Returns an array with all ACL-Categories we are responsible for.
139 */
140 function getAclCategories()
141 {
142 $ret= $this->aclCategory;
143 if(!is_array($ret)) $ret = array($ret);
144 return($ret);
145 }
148 /*! \brief Execute this plugin
149 * Handle actions/events, locking, snapshots, dialogs, tabs,...
150 */
151 function execute()
152 {
153 // Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog.
154 $vars = array('/^act$/','/^listing/','/^PID$/','/^FILTER_PID$/');
155 session::set('LOCK_VARS_TO_USE',$vars);
157 pathNavigator::registerPlugin($this);
159 /* Display the copy & paste dialog, if it is currently open */
160 $ret = $this->copyPasteHandler("",array());
161 if($ret){
162 return($this->getHeader().$ret);
163 }
165 // Update filter
166 if ($this->filter) {
167 $this->filter->update();
168 session::global_set(get_class($this)."_filter", $this->filter);
169 session::set('autocomplete', $this->filter);
170 }
172 // Handle actions (POSTs and GETs)
173 $str = $this->handleActions($this->detectPostActions());
174 if($str) return($this->getHeader().$str);
176 // Open single dialog objects
177 if(is_object($this->dialogObject)){
178 if(method_exists($this->dialogObject,'save_object')) $this->dialogObject->save_object();
179 if(method_exists($this->dialogObject,'execute')){
180 $display = $this->dialogObject->execute();
181 $display.= $this->_getTabFooter();
182 return($this->getHeader().$display);
183 }
184 }
186 // Display tab object.
187 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
188 # $this->tabObject->save_object();
189 $display = $this->tabObject->execute();
190 $display.= $this->_getTabFooter();
191 return($this->getHeader().$display);
192 }
194 // Set current restore base for snapshot handling.
195 if(is_object($this->snapHandler)){
196 $bases = array();
197 foreach($this->storagePoints as $sp){
198 $bases[] = $sp.$this->headpage->getBase();
199 }
201 // No bases specified? Try base
202 if(!count($bases)) $bases[] = $this->headpage->getBase();
204 $this->snapHandler->setSnapshotBases($bases);
205 }
207 // Display list
208 return($this->renderList());
209 }
211 function editFilter()
212 {
213 $this->dialogObject = new userFilter($this->config,$this->getHeadpage());
214 }
216 function renderList()
217 {
218 $this->headpage->update();
219 $display = $this->headpage->render();
220 return($this->getHeader().$display);
221 }
223 function getHeadpage()
224 {
225 return($this->headpage);
226 }
228 function getFilter()
229 {
230 return($this->filter);
231 }
233 /*! \brief Generates the plugin header which is displayed whenever a tab object is
234 * opened.
235 */
236 protected function getHeader()
237 {
238 // We do not display any headers right now.
239 if(1 || $this->skipHeader) return("");
240 }
243 /*! \brief Generates the footer which is used whenever a tab object is
244 * displayed.
245 */
246 protected function _getTabFooter()
247 {
248 // Do not display tab footer for non tab objects
249 if(!($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug)){
250 return("");
251 }
253 // Check if there is a dialog opened - We don't need any buttons in this case.
254 if($this->tabObject->by_object[$this->tabObject->current]){
255 $current = $this->tabObject->by_object[$this->tabObject->current];
256 if(isset($current->dialog) && (is_object($current->dialog) || $current->dialog)){
257 return("");
258 }
259 }
261 // Skip footer if requested;
262 if($this->skipFooter) return("");
264 // In case an of locked entry, we may have opened a read-only tab.
265 $str = "";
266 if(isset($this->tabObject->read_only) && $this->tabObject->read_only == TRUE){
267 $str.= "
268 <p style=\"text-align:right\">
269 <button type=submit name=\"edit_cancel\">".msgPool::cancelButton()."</button>
270 </p>";
271 return($str);
272 }else{
274 // Display ok, (apply) and cancel buttons
275 $str.= "<p style=\"text-align:right\">\n";
276 $str.= "<button type=\"submit\" name=\"edit_finish\">".msgPool::okButton()."</button>\n";
277 $str.= " \n";
278 if($this->displayApplyBtn){
279 $str.= "<button type=\"submit\" name=\"edit_apply\">".msgPool::applyButton()."</button>\n";
280 $str.= " \n";
281 }
282 $str.= "<button type=\"submit\" name=\"edit_cancel\">".msgPool::cancelButton()."</button>\n";
283 $str.= "</p>";
284 }
285 return($str);
286 }
289 /*! \brief Initiates the removal for the given entries
290 * and displays a confirmation dialog.
291 *
292 * @param String 'action' The name of the action which was the used as trigger.
293 * @param Array 'target' A list of object dns, which should be affected by this method.
294 * @param Array 'all' A combination of both 'action' and 'target'.
295 */
296 protected function removeEntryRequested($action="",$target=array(),$all=array())
297 {
298 // Close dialogs and remove locks for currently handled dns
299 $this->cancelEdit();
301 $disallowed = array();
302 $this->dns = array();
304 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel requested!");
306 // Check permissons for each target
307 $h = $this->getHeadpage();
308 $oTypes = array_reverse($h->objectTypes);
309 foreach($target as $dn){
310 $entry = $h->getEntry($dn);
311 $obj = $h->getObjectType($oTypes, $entry['objectClass']);
312 $acl = $this->ui->get_permissions($dn, $obj['category']."/".$obj['class']);
313 if(preg_match("/d/",$acl)){
314 $this->dns[] = $dn;
315 }else{
316 $disallowed[] = $dn;
317 }
318 }
319 if(count($disallowed)){
320 msg_dialog::display(_("Permission"),msgPool::permDelete($disallowed),INFO_DIALOG);
321 }
323 // We've at least one entry to delete.
324 if(count($this->dns)){
326 // check locks
327 if ($user= get_multiple_locks($this->dns)){
328 return(gen_locked_message($user,$this->dns));
329 }
331 // Add locks
332 $dns_names = array();
333 $types = array();
335 // Build list of object -labels
336 foreach($h->objectTypes as $type){
337 $map[$type['objectClass']]= $type['label'];
338 }
340 foreach($this->dns as $dn){
341 $tmp = $h->getType($dn);
342 if(isset($map[$tmp])){
343 $dns_names[LDAP::fix($dn)] = _($map[$tmp]);
344 }else{
345 $dns_names[] =LDAP::fix($dn);
346 }
347 }
348 add_lock ($this->dns, $this->ui->dn);
350 // Display confirmation dialog.
351 $smarty = get_smarty();
352 $smarty->assign("info", msgPool::deleteInfo($dns_names));
353 $smarty->assign("multiple", true);
354 return($smarty->fetch(get_template_path('removeEntries.tpl')));
355 }
356 }
359 /*! \brief Object removal was confirmed, now remove the requested entries.
360 *
361 * @param String 'action' The name of the action which was the used as trigger.
362 * @param Array 'target' A list of object dns, which should be affected by this method.
363 * @param Array 'all' A combination of both 'action' and 'target'.
364 */
365 function removeEntryConfirmed($action="",$target=array(),$all=array(),
366 $altTabClass="",$altTabType="", $altAclCategory="",$altAclPlugin="")
367 {
368 $tabType = $this->tabType;
369 $tabClass = $this->tabClass;
370 $aclCategory = $this->aclCategory;
371 $aclPlugin = $this->aclPlugin;
372 if(!empty($altTabClass)) $tabClass = $altTabClass;
373 if(!empty($altTabType)) $tabType = $altTabType;
374 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
375 if(!empty($altAclPlugin)) $aclPlugin = $altAclPlugin;
377 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Entry removel confirmed!");
379 // Check permissons for each target
380 $h = $this->getHeadpage();
381 $oTypes = array_reverse($h->objectTypes);
382 foreach($this->dns as $key => $dn){
383 $entry = $h->getEntry($dn);
384 $obj = $h->getObjectType($oTypes, $entry['objectClass']);
385 $acl = $this->ui->get_permissions($dn, $obj['category']."/".$obj['class']);
387 // Check permissions, are we allowed to remove this object?
388 if(preg_match("/d/",$acl)){
390 // Delete the object
391 $this->dn = $dn;
392 $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$tabType], $this->dn,
393 $aclCategory, true, true);
394 $this->tabObject->set_acl_base($this->dn);
395 $this->tabObject->parent = &$this;
396 $this->tabObject->delete ();
398 // Remove the lock for the current object.
399 del_lock($this->dn);
400 } else {
401 msg_dialog::display(_("Permission error"), msgPool::permDelete(), ERROR_DIALOG);
402 new log("security","groups/".get_class($this),$dn,array(),"Tried to trick deletion.");
403 }
404 }
406 // Cleanup
407 $this->remove_lock();
408 $this->closeDialogs();
409 }
412 /*! \brief Detects actions/events send by the ui
413 * and the corresponding targets.
414 */
415 function detectPostActions()
416 {
417 if(!is_object($this->headpage)){
418 trigger_error("No valid headpage given....!");
419 return(array());
420 }
421 $action= $this->headpage->getAction();
422 if(isset($_POST['edit_apply'])) $action['action'] = "apply";
423 if(isset($_POST['edit_finish'])) $action['action'] = "save";
424 if(isset($_POST['edit_cancel'])) $action['action'] = "cancel";
425 if(isset($_POST['delete_confirmed'])) $action['action'] = "removeConfirmed";
426 if(isset($_POST['delete_snapshot_confirm'])) $action['action'] = "removeSnapshotConfirmed";
427 if(isset($_POST['delete_cancel'])) $action['action'] = "cancelDelete";
428 if(isset($_POST['saveFilter'])) $action['action'] = "saveFilter";
429 if(isset($_POST['cancelFilter'])) $action['action'] = "cancelFilter";
431 // Detect Snapshot actions
432 if(isset($_POST['CreateSnapshot'])) $action['action'] = "saveSnapshot";
433 if(isset($_POST['CancelSnapshot'])) $action['action'] = "cancelSnapshot";
434 foreach($_POST as $name => $value){
435 $once =TRUE;
436 if(preg_match("/^RestoreSnapShot_/",$name) && $once){
437 $once = FALSE;
438 $entry = base64_decode(preg_replace("/^RestoreSnapShot_(.*)$/i","\\1",$name));
439 $action['action'] = "restoreSnapshot";
440 $action['targets'] = array($entry);
441 }
442 }
444 return($action);
445 }
448 /*! \brief Calls the registered method for a given action/event.
449 */
450 function handleActions($action)
451 {
452 // Start action
453 if(isset($this->actions[$action['action']])){
454 $func = $this->actions[$action['action']];
455 if(!isset($action['targets']))$action['targets']= array();
457 // Create statistic table entry
458 stats::log('management', $class = get_class($this), $this->getAclCategories(), $action['action'],
459 $amount = count($action['targets']), $duration = (microtime(TRUE) - $this->initTime));
461 return($this->$func($action['action'],$action['targets'],$action));
462 }
463 }
466 /*! \brief Opens the snapshot creation dialog for the given target.
467 *
468 * @param String 'action' The name of the action which was the used as trigger.
469 * @param Array 'target' A list of object dns, which should be affected by this method.
470 * @param Array 'all' A combination of both 'action' and 'target'.
471 */
472 function createSnapshotDialog($action="",$target=array(),$all=array())
473 {
474 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$target,"Snaptshot creation initiated!");
476 foreach($target as $entry){
477 if(!empty($entry) && $this->ui->allow_snapshot_create($entry,$this->aclCategory)){
478 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
479 $this->dialogObject->aclCategories = array($this->aclCategory);
480 $this->dialogObject->parent = &$this;
482 }else{
483 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to create a snapshot for %s!"), bold($entry)),
484 ERROR_DIALOG);
485 }
486 }
487 }
490 /*! \brief Creates a snapshot new entry - This method is called when the somebody
491 * clicks 'save' in the "Create snapshot dialog" (see ::createSnapshotDialog).
492 *
493 * @param String 'action' The name of the action which was the used as trigger.
494 * @param Array 'target' A list of object dns, which should be affected by this method.
495 * @param Array 'all' A combination of both 'action' and 'target'.
496 */
497 function saveSnapshot($action="",$target=array(),$all=array())
498 {
499 if(!is_object($this->dialogObject)) return;
500 $this->dialogObject->save_object();
501 $msgs = $this->dialogObject->check();
502 if(count($msgs)){
503 foreach($msgs as $msg){
504 msg_dialog::display(_("Error"), $msg, ERROR_DIALOG);
505 }
506 }else{
507 $this->dn = $this->dialogObject->dn;
508 $this->snapHandler->create_snapshot( $this->dn,$this->dialogObject->CurrentDescription);
509 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Snaptshot created!");
510 $this->closeDialogs();
511 }
512 }
515 /*! \brief Restores a snapshot object.
516 * The dn of the snapshot entry has to be given as ['target'] parameter.
517 *
518 * @param String 'action' The name of the action which was the used as trigger.
519 * @param Array 'target' A list of object dns, which should be affected by this method.
520 * @param Array 'all' A combination of both 'action' and 'target'.
521 */
522 function restoreSnapshot($action="",$target=array(),$all=array())
523 {
524 $entry = array_pop($target);
525 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
526 $this->snapHandler->restore_snapshot($entry);
527 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Snaptshot restored!");
528 $this->closeDialogs();
529 }else{
530 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s!"), bold($entry)),
531 ERROR_DIALOG);
532 }
533 }
536 /*! \brief Removes a snapshot object.
537 */
538 function removeSnapshotConfirmed($action="",$target=array(),$all=array())
539 {
540 $entry = $this->dialogObject->del_dn;
541 if(!empty($entry) && $this->ui->allow_snapshot_create($entry,$this->aclCategory)){
542 $this->snapHandler->remove_snapshot($entry);
543 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry,"Snaptshot removed!");
544 }else{
545 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to remove a snapshot for %s!"), bold($entry)),
546 ERROR_DIALOG);
547 }
548 }
551 /*! \brief Displays the "Restore snapshot dialog" for a given target.
552 * If no target is specified, open the restore removed object
553 * dialog.
554 * @param String 'action' The name of the action which was the used as trigger.
555 * @param Array 'target' A list of object dns, which should be affected by this method.
556 * @param Array 'all' A combination of both 'action' and 'target'.
557 */
558 function restoreSnapshotDialog($action="",$target=array(),$all=array())
559 {
560 // Set current restore base for snapshot handling.
561 if(is_object($this->snapHandler)){
562 $bases = array();
563 foreach($this->storagePoints as $sp){
564 $bases[] = $sp.$this->headpage->getBase();
565 }
566 }
568 // No bases specified? Try base
569 if(!count($bases)) $bases[] = $this->headpage->getBase();
571 // No target, open the restore removed object dialog.
572 if(!count($target)){
573 $entry = $this->headpage->getBase();
574 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
575 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry,"Snaptshot restoring initiated!");
576 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
577 $this->dialogObject->set_snapshot_bases($bases);
578 $this->dialogObject->display_all_removed_objects = true;
579 $this->dialogObject->display_restore_dialog = true;
580 $this->dialogObject->parent = &$this;
581 }else{
582 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s!"), bold($entry)),
583 ERROR_DIALOG);
584 }
585 }else{
587 // Display the restore points for a given object.
588 $entry = array_pop($target);
589 if(!empty($entry) && $this->ui->allow_snapshot_restore($entry,$this->aclCategory)){
590 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$entry,"Snaptshot restoring initiated!");
591 $this->dialogObject = new SnapShotDialog($this->config,$entry,$this);
592 $this->dialogObject->set_snapshot_bases($bases);
593 $this->dialogObject->display_restore_dialog = true;
594 $this->dialogObject->parent = &$this;
595 }else{
596 msg_dialog::display(_("Permission"),sprintf(_("You are not allowed to restore a snapshot for %s!"), bold($entry)),
597 ERROR_DIALOG);
598 }
599 }
600 }
603 /*! \brief This method intiates the object creation.
604 *
605 * @param String 'action' The name of the action which was the used as trigger.
606 * @param Array 'target' A list of object dns, which should be affected by this method.
607 * @param Array 'all' A combination of both 'action' and 'target'.
608 */
609 function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
610 {
611 /* To handle mutliple object types overload this method.
612 * ...
613 * registerAction('newUser', 'newEntry');
614 * registerAction('newGroup','newEntry');
615 * ...
616 *
617 * function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
618 * {
619 * switch($action){
620 * case 'newUser' : {
621 * mangement::newEntry($action,$target,$all,"usertabs","USERTABS","users");
622 * }
623 * case 'newGroup' : {
624 * mangement::newEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
625 * }
626 * }
627 * }
628 **/
629 $tabType = $this->tabType;
630 $tabClass = $this->tabClass;
631 $aclCategory = $this->aclCategory;
632 if(!empty($altTabClass)) $tabClass = $altTabClass;
633 if(!empty($altTabType)) $tabType = $altTabType;
634 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
636 // Check locking & lock entry if required
637 $this->displayApplyBtn = FALSE;
638 $this->dn = "new";
639 $this->is_new = TRUE;
640 $this->is_single_edit = FALSE;
641 $this->is_multiple_edit = FALSE;
643 set_object_info($this->dn);
645 // Open object.
646 if(empty($tabClass) || empty($tabType)){
647 // No tab type defined
648 }else{
650 if (isset($this->config->data['TABS'][$tabType])) {
652 // Check if the base plugin is available - it is mostly responsible for object creation and removal.
653 $first = $this->config->data['TABS'][$tabType][0];
654 if(!class_available($first['CLASS'])){
655 msg_dialog::display(_("Internal error"),
656 sprintf(_("Cannot instantiate tabbed-plug-in, the base plugin (%s) is not available!"), $first['CLASS']),
657 ERROR_DIALOG);
658 }else{
659 $this->tabObject= new $tabClass($this->config,$this->config->data['TABS'][$tabType], $this->dn, $aclCategory);
660 $this->tabObject->set_acl_base($this->headpage->getBase());
661 $this->tabObject->parent = &$this;
662 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Create new entry initiated!");
663 }
664 } else {
665 msg_dialog::display(_("Error"), sprintf(_("No tab definition for %s found in configuration file: cannot create plugin instance!"), bold($tabType)), ERROR_DIALOG);
666 }
667 }
668 }
671 /*! \brief This method opens an existing object or a list of existing objects to be edited.
672 *
673 *
674 * @param String 'action' The name of the action which was the used as trigger.
675 * @param Array 'target' A list of object dns, which should be affected by this method.
676 * @param Array 'all' A combination of both 'action' and 'target'.
677 */
678 function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="")
679 {
680 /* To handle mutliple object types overload this method.
681 * ...
682 * registerAction('editUser', 'editEntry');
683 * registerAction('editGroup','editEntry');
684 * ...
685 *
686 * function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory)
687 * {
688 * switch($action){
689 * case 'editUser' : {
690 * mangement::editEntry($action,$target,$all,"usertabs","USERTABS","users");
691 * }
692 * case 'editGroup' : {
693 * mangement::editEntry($action,$target,$all,"grouptabs","GROUPTABS","groups");
694 * }
695 * }
696 * }
697 **/
699 // Do not create a new tabObject while there is already one opened,
700 // the user may have just pressed F5 to reload the page.
701 if(is_object($this->tabObject)){
702 return;
703 }
705 $tabType = $this->tabType;
706 $tabClass = $this->tabClass;
707 $aclCategory = $this->aclCategory;
708 if(!empty($altTabClass)) $tabClass = $altTabClass;
709 if(!empty($altTabType)) $tabType = $altTabType;
710 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
712 $this->displayApplyBtn = count($target) == 1;
714 // Single edit - we only got one object dn.
715 if(count($target) == 1){
716 $this->is_new = FALSE;
717 $this->is_single_edit = TRUE;
718 $this->is_multiple_edit = FALSE;
720 // Get the dn of the object and creates lock
721 $this->dn = array_pop($target);
722 set_object_info($this->dn);
723 $user = get_lock($this->dn);
724 if ($user != ""){
725 return(gen_locked_message ($user, array($this->dn),TRUE));
726 }
727 add_lock ($this->dn, $this->ui->dn);
729 // Open object.
730 if(empty($tabClass) || empty($tabType)){
731 trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
732 }else{
734 $tab = $tabClass;
736 // Check if the base plugin is available - it is mostly responsible for object creation and removal.
737 $first = $this->config->data['TABS'][$tabType][0];
738 if(!class_available($first['CLASS'])){
739 msg_dialog::display(_("Internal error"),
740 sprintf(_("Cannot instantiate tabbed-plug-in, the base plugin (%s) is not available!"), $first['CLASS']),
741 ERROR_DIALOG);
742 }else{
743 $this->tabObject= new $tab($this->config,$this->config->data['TABS'][$tabType], $this->dn,$aclCategory);
744 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dn,"Edit entry initiated!");
745 $this->tabObject->set_acl_base($this->dn);
746 $this->tabObject->parent = &$this;
747 }
748 }
749 }else{
751 // We've multiple entries to edit.
752 $this->is_new = FALSE;
753 $this->is_singel_edit = FALSE;
754 $this->is_multiple_edit = TRUE;
756 // Open multiple edit handler.
757 if(empty($tabClass) || empty($tabType)){
758 trigger_error("We can't edit any object(s). 'tabClass' or 'tabType' is empty!");
759 }else{
760 $this->dns = $target;
761 $tmp = new multi_plug($this->config,$tabClass,$this->config->data['TABS'][$tabType],
762 $this->dns,$this->headpage->getBase(),$aclCategory);
764 // Check for locked entries
765 if ($tmp->entries_locked()){
766 return($tmp->display_lock_message());
767 }
769 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Edit entry initiated!");
771 // Now lock entries.
772 if($tmp->multiple_available()){
773 $tmp->lock_entries($this->ui->dn);
774 $this->tabObject = $tmp;
775 set_object_info($this->tabObject->get_object_info());
776 }
777 }
778 }
779 }
782 /*! \brief Close filter dialog
783 */
784 protected function cancelFilter()
785 {
786 if($this->dialogObject instanceOf userFilter){
787 $this->remove_lock();
788 $this->closeDialogs();
789 }
790 }
793 /*! \brief Save filter modifcations.
794 */
795 protected function saveFilter()
796 {
797 if($this->dialogObject instanceOf userFilter){
798 $msgs = $this->dialogObject->check();
799 if(count($msgs)){
800 msg_dialog::displayChecks($msgs);
801 return("");
802 }else{
803 $this->dialogObject->save();
804 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Entry saved!");
805 $this->remove_lock();
806 $this->closeDialogs();
808 // Ask filter to reload information
809 $this->filter->reloadFilters();
810 }
811 }
812 }
815 /*! \brief Save object modifications and closes dialogs (returns to object listing).
816 * - Calls '::check' to validate the given input.
817 * - Calls '::save' to save back object modifications (e.g. to ldap).
818 * - Calls '::remove_locks' to remove eventually created locks.
819 * - Calls '::closeDialogs' to return to the object listing.
820 */
821 protected function saveChanges()
822 {
823 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
824 $this->tabObject->save_object();
825 $msgs = $this->tabObject->check();
826 if(count($msgs)){
827 msg_dialog::displayChecks($msgs);
828 return("");
829 }else{
830 $this->tabObject->save();
831 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Entry saved!");
832 $this->remove_lock();
833 $this->closeDialogs();
834 }
835 }elseif($this->dialogObject instanceOf plugin){
836 $this->dialogObject->save_object();
837 $msgs = $this->dialogObject->check();
838 if(count($msgs)){
839 msg_dialog::displayChecks($msgs);
840 return("");
841 }else{
842 $this->dialogObject->save();
843 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Entry saved!");
844 $this->remove_lock();
845 $this->closeDialogs();
846 }
847 }
848 }
851 /*! \brief Save object modifications and keep dialogs opened.
852 * - Calls '::check' to validate the given input.
853 * - Calls '::save' to save back object modifications (e.g. to ldap).
854 */
855 protected function applyChanges()
856 {
857 if($this->tabObject instanceOf tabs || $this->tabObject instanceOf multi_plug){
858 $this->tabObject->save_object();
859 $msgs = $this->tabObject->check();
860 if(count($msgs)){
861 msg_dialog::displayChecks($msgs);
862 return("");
863 }else{
864 $this->tabObject->save();
865 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$this->dns,"Modifications applied!");
866 $this->tabObject->re_init();
867 }
868 }
869 }
872 /*! \brief This method closes dialogs
873 * and cleans up the cached object info and the ui.
874 */
875 protected function closeDialogs()
876 {
877 $this->last_dn = $this->dn;
878 $this->last_dns = $this->dns;
879 $this->last_tabObject = $this->tabObject;
880 $this->last_dialogObject = $this->dialogObject;
881 $this->dn = "";
882 $this->dns = array();
883 $this->tabObject = null;
884 $this->dialogObject = null;
885 $this->skipFooter = FALSE;
886 set_object_info();
887 }
890 /*! \brief Editing an object was caneled.
891 * Close dialogs/tabs and remove locks.
892 */
893 protected function cancelEdit()
894 {
895 $this->remove_lock();
896 $this->closeDialogs();
897 }
900 /*! \brief Every click in the list user interface sends an event
901 * here can we connect those events to a method.
902 * eg. ::registerEvent('new','createUser')
903 * When the action/event new is send, the method 'createUser'
904 * will be called.
905 */
906 function registerAction($action,$target)
907 {
908 $this->actions[$action] = $target;
909 }
912 /*! \brief Removes ldap object locks created by this class.
913 * Whenever an object is edited, we create locks to avoid
914 * concurrent modifications.
915 * This locks will automatically removed here.
916 */
917 function remove_lock()
918 {
919 if(!empty($this->dn) && $this->dn != "new"){
920 del_lock($this->dn);
921 }
922 if(count($this->dns)){
923 del_lock($this->dns);
924 }
925 }
928 /*! \brief This method is used to queue and process copy&paste actions.
929 * Allows to copy, cut and paste mutliple entries at once.
930 * @param String 'action' The name of the action which was the used as trigger.
931 * @param Array 'target' A list of object dns, which should be affected by this method.
932 * @param Array 'all' A combination of both 'action' and 'target'.
933 */
934 function copyPasteHandler($action="",$target=array(),$all=array(),
935 $altTabClass ="", $altTabType = "", $altAclCategory="",$altAclPlugin="")
936 {
937 // Return without any actions while copy&paste handler is disabled.
938 if(!is_object($this->cpHandler)) return("");
940 $tabType = $this->tabType;
941 $tabClass = $this->tabClass;
942 $aclCategory = $this->aclCategory;
943 $aclPlugin = $this->aclPlugin;
944 if(!empty($altTabClass)) $tabClass = $altTabClass;
945 if(!empty($altTabType)) $tabType = $altTabType;
946 if(!empty($altAclCategory)) $aclCategory = $altAclCategory;
947 if(!empty($altAclPlugin)) $aclPlugin = $altAclPlugin;
949 // Save user input
950 $this->cpHandler->save_object();
952 // Add entries to queue
953 if($action == "copy" || $action == "cut"){
954 $this->cpHandler->cleanup_queue();
955 foreach($target as $dn){
956 if($action == "copy" && $this->ui->is_copyable($dn,$aclCategory,$aclPlugin)){
957 $this->cpHandler->add_to_queue($dn,"copy",$tabClass,$tabType,$aclCategory,$this);
958 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry copied!");
959 }
960 if($action == "cut" && $this->ui->is_cutable($dn,$aclCategory,$aclPlugin)){
961 $this->cpHandler->add_to_queue($dn,"cut",$tabClass,$tabType,$aclCategory,$this);
962 @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry cutted!");
963 }
964 }
965 }
967 // Initiate pasting
968 if($action == "paste"){
969 $this->cpPastingStarted = TRUE;
970 }
972 // Display any c&p dialogs, eg. object modifications required before pasting.
973 if($this->cpPastingStarted && $this->cpHandler->entries_queued()){
974 $this->cpHandler->SetVar("base",$this->headpage->getBase());
975 $data = $this->cpHandler->execute();
976 if(!empty($data)){
977 return($data);
978 }
979 }
981 // Automatically disable pasting process since there is no entry left to paste.
982 if(!$this->cpHandler->entries_queued()){
983 $this->cpPastingStarted = FALSE;
984 }
985 return("");
986 }
989 function setFilter($str) {
990 $this->filter = $str;
991 }
994 function postcreate() {
995 $this->handle_post_events('add');
996 }
997 function postmodify(){
998 $this->handle_post_events('modify');
999 }
1000 function postremove(){
1001 $this->handle_post_events('remove');
1002 }
1004 function is_modal_dialog()
1005 {
1006 return(is_object($this->tabObject) || is_object($this->dialogObject));
1007 }
1010 /*! \brief Forward command execution request
1011 * to the correct method.
1012 */
1013 function handle_post_events($mode, $addAttrs= array())
1014 {
1015 if(!in_array($mode, array('add','remove','modify'))){
1016 trigger_error(sprintf("Invalid post event type given %s! Valid types are [add,modify,remove].", bold($mode)));
1017 return;
1018 }
1019 switch ($mode){
1020 case "add":
1021 plugin::callHook($this,"POSTCREATE", $addAttrs);
1022 break;
1024 case "modify":
1025 plugin::callHook($this,"POSTMODIFY", $addAttrs);
1026 break;
1028 case "remove":
1029 plugin::callHook($this,"POSTREMOVE", $addAttrs);
1030 break;
1031 }
1032 }
1033 }
1035 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1036 ?>