From a7441773160b76c3f193b6c8daf3e76d3c78bdc9 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 18 Mar 2014 15:10:57 +0000 Subject: [PATCH] add/edit accounts via extra tab in addressbook edit dialog --- addressbook/inc/class.addressbook_bo.inc.php | 2 +- .../inc/class.addressbook_hooks.inc.php | 16 ---- addressbook/inc/class.addressbook_so.inc.php | 2 +- addressbook/inc/class.addressbook_ui.inc.php | 59 ++++++++++++- addressbook/setup/setup.inc.php | 1 - admin/inc/class.admin_account.inc.php | 86 ++++++++++++++++++- admin/inc/class.admin_cmd.inc.php | 6 +- admin/inc/class.admin_cmd_edit_user.inc.php | 8 +- admin/inc/class.admin_ui.inc.php | 27 +++--- admin/templates/default/account.xet | 15 ++-- 10 files changed, 179 insertions(+), 43 deletions(-) diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php index 20a3f6dac7..9a55d20c92 100755 --- a/addressbook/inc/class.addressbook_bo.inc.php +++ b/addressbook/inc/class.addressbook_bo.inc.php @@ -706,7 +706,7 @@ class addressbook_bo extends addressbook_so */ function photo_src($id,$jpeg,$default='',$etag=null) { - error_log(__METHOD__."($id, ..., etag=$etag) ". function_backtrace()); + //error_log(__METHOD__."($id, ..., etag=$etag) ". function_backtrace()); return $jpeg ? array( 'menuaction' => 'addressbook.addressbook_ui.photo', 'contact_id' => $id, diff --git a/addressbook/inc/class.addressbook_hooks.inc.php b/addressbook/inc/class.addressbook_hooks.inc.php index 6740708e82..b5aed80a33 100644 --- a/addressbook/inc/class.addressbook_hooks.inc.php +++ b/addressbook/inc/class.addressbook_hooks.inc.php @@ -344,22 +344,6 @@ class addressbook_hooks return $settings; } - /** - * add an Addressbook tab to Admin >> Edit user - */ - static function edit_user() - { - global $menuData; - - $menuData[] = array( - 'description' => 'Addressbook', - 'url' => '/index.php', - 'extradata' => 'menuaction=addressbook.addressbook_ui.edit', - 'options' => "onclick=\"egw_openWindowCentered2(this,'_blank',870,440,'yes'); return false;\"". - ' title="'.htmlspecialchars(lang('Edit extra account-data in the addressbook')).'"', - ); - } - /** * Hook called by link-class to include calendar in the appregistry of the linkage * diff --git a/addressbook/inc/class.addressbook_so.inc.php b/addressbook/inc/class.addressbook_so.inc.php index b126d4b889..e73c60ce48 100755 --- a/addressbook/inc/class.addressbook_so.inc.php +++ b/addressbook/inc/class.addressbook_so.inc.php @@ -345,7 +345,7 @@ class addressbook_so { $grants[0] = EGW_ACL_READ; // admins always have read-access if (!$GLOBALS['egw']->acl->check('account_access',16,'admin')) $grants[0] |= EGW_ACL_EDIT; - // no add at the moment if (!$GLOBALS['egw']->acl->check('account_access',4,'admin')) $this->grants[0] |= EGW_ACL_ADD; + if (!$GLOBALS['egw']->acl->check('account_access',4,'admin')) $grants[0] |= EGW_ACL_ADD; if (!$GLOBALS['egw']->acl->check('account_access',32,'admin')) $grants[0] |= EGW_ACL_DELETE; } // allow certain groups to edit contact-data of accounts diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php index e0e3e59a8b..04f44f0a69 100644 --- a/addressbook/inc/class.addressbook_ui.inc.php +++ b/addressbook/inc/class.addressbook_ui.inc.php @@ -1693,9 +1693,47 @@ window.egw_LAB.wait(function() { $content[$c_prefix.'_countrycode'] = null; } } - if ($this->save($content)) + $content['msg'] = ''; + $this->error = false; + foreach((array)$content['pre_save_callbacks'] as $callback) { - $content['msg'] = lang('Contact saved'); + try { + if (($success_msg = call_user_func_array($callback, array(&$content)))) + { + $content['msg'] .= ($content['msg'] ? ', ' : '').$success_msg; + } + } + catch (Exception $ex) { + $content['msg'] .= ($content['msg'] ? ', ' : '').$ex->getMessage(); + $button = 'apply'; // do not close dialog + $this->error = true; + break; + } + } + if ($this->error) + { + // error in pre_save_callbacks + } + elseif ($this->save($content)) + { + $content['msg'] .= ($content['msg'] ? ', ' : '').lang('Contact saved'); + + foreach((array)$content['post_save_callbacks'] as $callback) + { + try { + if (($success_msg = call_user_func_array($callback, array(&$content)))) + { + $content['msg'] .= ', '.$success_msg; + } + } + catch (Exception $ex) { + $content['msg'] .= ', '.$ex->getMessage(); + $button = 'apply'; // do not close dialog + $this->error = true; + break; + } + } + if ($content['change_org'] && $old_org_entry && ($changed = $this->changed_fields($old_org_entry,$content,true)) && ($members = $this->org_similar($old_org_entry['org_name'],$changed))) { @@ -1732,12 +1770,17 @@ window.egw_LAB.wait(function() { { egw_link::link('addressbook',$content['id'],$links); } - $currentApp = $GLOBALS['egw']->currentapp; - egw_framework::refresh_opener($content['msg'], 'addressbook',$content['id'], ($content['id'] ? 'update' : 'add')); + egw_framework::refresh_opener($content['msg'], 'addressbook', $content['id'], $content['id'] ? 'update' : 'add', + null, null, null, $this->error ? 'error' : 'success'); if ($button == 'save') { egw_framework::window_close(); } + else + { + egw_framework::message($content['msg'], $this->error ? 'error' : 'success'); + unset($content['msg']); + } $content['link_to']['to_id'] = $content['id']; break; @@ -2030,6 +2073,14 @@ window.egw_LAB.wait(function() { { $readonlys = array_merge($readonlys, $extra_tab['readonlys']); } + if (!empty($extra_tab['pre_save_callback'])) + { + $preserve['pre_save_callbacks'][] = $extra_tab['pre_save_callback']; + } + if (!empty($extra_tab['post_save_callback'])) + { + $preserve['post_save_callbacks'][] = $extra_tab['post_save_callback']; + } } } return $this->tmpl->exec('addressbook.addressbook_ui.edit', $content, $sel_options, $readonlys, $preserve, 2); diff --git a/addressbook/setup/setup.inc.php b/addressbook/setup/setup.inc.php index 4211b72ccb..a253f27a00 100755 --- a/addressbook/setup/setup.inc.php +++ b/addressbook/setup/setup.inc.php @@ -42,7 +42,6 @@ $setup_info['addressbook']['hooks']['deletegroup'] = 'addressbook.addressbook_bo $setup_info['addressbook']['hooks']['delete_category'] = 'addressbook.addressbook_bo.delete_category'; $setup_info['addressbook']['hooks']['search_link'] = 'addressbook_hooks::search_link'; $setup_info['addressbook']['hooks']['calendar_resources'] = 'addressbook_hooks::calendar_resources'; -$setup_info['addressbook']['hooks']['edit_user'] = 'addressbook_hooks::edit_user'; $setup_info['addressbook']['hooks'][] = 'config'; $setup_info['addressbook']['hooks']['group_acl'] = 'addressbook_hooks::group_acl'; $setup_info['addressbook']['hooks']['not_enum_group_acls'] = 'addressbook_hooks::not_enum_group_acls'; diff --git a/admin/inc/class.admin_account.inc.php b/admin/inc/class.admin_account.inc.php index 30d21eaf9a..5bbe640704 100644 --- a/admin/inc/class.admin_account.inc.php +++ b/admin/inc/class.admin_account.inc.php @@ -17,8 +17,14 @@ class admin_account { public function addressbook_edit(array $content) { - if ((string)$content['owner'] === '0') + if ((string)$content['owner'] === '0' && $GLOBALS['egw_info']['user']['apps']['admin']) { + $deny_edit = $content['account_id'] ? $GLOBALS['egw']->acl->check('account_access', 16, 'admin') : + $GLOBALS['egw']->acl->check('account_access', 4, 'admin'); + //error_log(__METHOD__."() contact_id=$content[contact_id], account_id=$content[account_id], deny_edit=".array2string($deny_edit)); + + if (!$content['account_id'] && $deny_edit) return; // no right to add new accounts, should not happen by AB ACL + // load our translations translation::add_app('admin'); @@ -49,17 +55,91 @@ class admin_account 'account_status' => 'A', 'memberships' => array(), 'anonymous' => false, - 'changepassword' => (bool)$GLOBALS['egw_info']['server']['change_pwd_every_x_days'], + 'changepassword' => true, //old default: (bool)$GLOBALS['egw_info']['server']['change_pwd_every_x_days'], 'mustchangepassword' => false, + 'account_primary_group' => $GLOBALS['egw']->accounts->name2id('Default'), ); } + $readonlys = array(); + + if ($deny_edit) + { + foreach(array_keys($account) as $key) + { + $readonlys[$key] = true; + } + $readonlys['account_passwd'] = $readonlys['account_passwd2'] = true; + } return array( 'name' => 'admin.account?'.filemtime(EGW_SERVER_ROOT.'/admin/templates/default/account.xet'), 'prepend' => true, 'label' => 'Account', 'data' => $account, - 'callback' => 'admin_account::addressbook_save', + 'readonlys' => $readonlys, + 'pre_save_callback' => $deny_edit ? null : 'admin_account::addressbook_pre_save', ); } } + + /** + * Hook called by addressbook prior to saving addressbook data + * + * @param array &$content + * @throws Exception for errors + * @return string Success message + */ + public static function addressbook_pre_save(&$content) + { + //error_log(__METHOD__."(".array2string($content).")"); + $account = array(); + foreach(array( + // need to copy/rename some fields named different in account and contact + 'n_given' => 'account_firstname', + 'n_family' => 'account_lastname', + 'email' => 'account_email', + 'memberships' => 'account_groups', + // copy following fields to account + 'account_lid', 'account_id', + 'changepassword', 'anonymous', 'mustchangepassword', + 'account_passwd', 'account_passwd2', + 'account_primary_group', + 'account_expires', 'account_status', + ) as $c_name => $a_name) + { + if (is_int($c_name)) $c_name = $a_name; + + switch($a_name) + { + case 'account_expires': + $account[$a_name] = $content[$c_name] ? $content[$c_name] : 'never'; + break; + + case 'changepassword': // boolean values: admin_cmd_edit_user understands '' as NOT set + case 'anonymous': + case 'mustchangepassword': + $account[$a_name] = (boolean)$content[$c_name]; + break; + + default: + $account[$a_name] = $content[$c_name]; + break; + } + } + + $cmd = new admin_cmd_edit_user((int)$content['account_id'], $account); + $cmd->run(); + + // for a new account a new contact was created, need to merge that data with $content + if (!$content['account_id']) + { + $content['account_id'] = $cmd->account; + $addressbook_bo = new addressbook_bo(); + if (!($content['id'] = accounts::id2name($cmd->account, 'person_id')) || + !($contact = $addressbook_bo->read($content['id']))) + { + throw new egw_exception_assertion_failed("Can't find contact of just created account!"); + } + $content = array_merge($contact, $content); + } + } } diff --git a/admin/inc/class.admin_cmd.inc.php b/admin/inc/class.admin_cmd.inc.php index e1b20d3624..aa027b614a 100644 --- a/admin/inc/class.admin_cmd.inc.php +++ b/admin/inc/class.admin_cmd.inc.php @@ -652,13 +652,17 @@ abstract class admin_cmd /** * Parse a boolean value * - * @param string $value + * @param string|boolean|int $value * @param boolean $default=null * @return boolean * @throws egw_exception_wrong_userinput(lang('Invalid value "%1" use yes or no!',$value),998); */ static function parse_boolean($value,$default=null) { + if (is_bool($value) || is_int($value)) + { + return (boolean)$value; + } if (is_null($value) || (string)$value === '') { return $default; diff --git a/admin/inc/class.admin_cmd_edit_user.inc.php b/admin/inc/class.admin_cmd_edit_user.inc.php index 917291e6ef..8b25b331b8 100644 --- a/admin/inc/class.admin_cmd_edit_user.inc.php +++ b/admin/inc/class.admin_cmd_edit_user.inc.php @@ -27,6 +27,7 @@ class admin_cmd_edit_user extends admin_cmd_change_pw { if (!is_array($account)) { + //error_log(__METHOD__."(".array2string($account).', '.array2string($set).", ...)"); $account = array( 'account' => $account, 'set' => $set, @@ -59,6 +60,8 @@ class admin_cmd_edit_user extends admin_cmd_change_pw if ($this->account) // existing account { $data['account_id'] = admin_cmd::parse_account($this->account); + //error_log(__METHOD__."($check_only) this->account=".array2string($this->account).', data[account_id]='.array2string($data['account_id']).", ...)"); + $data['old_loginid'] = admin_cmd::$accounts->id2name($data['account_id']); } if (!$data['account_lid'] && (!$this->account || !is_null($data['account_lid']))) @@ -77,7 +80,7 @@ class admin_cmd_edit_user extends admin_cmd_change_pw throw new egw_exception_wrong_userinput(lang('You must enter a lastname'),9); } if (!is_null($data['account_lid']) && ($id = admin_cmd::$accounts->name2id($data['account_lid'],'account_lid','u')) && - $id !== $data['account_id']) + (string)$id !== (string)$data['account_id']) { throw new egw_exception_wrong_userinput(lang('That loginid has already been taken'),999); } @@ -140,6 +143,9 @@ class admin_cmd_edit_user extends admin_cmd_change_pw //_debug_array($data); throw new egw_exception_db(lang("Error saving account!"),11); } + // make new account_id available to caller + if (!$this->account) $this->account = $data['account_id']; + if ($data['account_groups']) { admin_cmd::$accounts->set_memberships($data['account_groups'],$data['account_id']); diff --git a/admin/inc/class.admin_ui.inc.php b/admin/inc/class.admin_ui.inc.php index 30caf498ec..2081b0e977 100644 --- a/admin/inc/class.admin_ui.inc.php +++ b/admin/inc/class.admin_ui.inc.php @@ -133,22 +133,16 @@ class admin_ui 'caption' => 'Open', 'default' => true, 'allowOnMultiple' => false, - 'url' => 'menuaction=admin.uiaccounts.edit_user&account_id=$id', + 'popup' => egw_link::is_popup('addressbook', 'edit'), + 'url' => '', 'group' => $group=0, - 'onExecute' => 'javaScript:app.admin.iframe_location', - ), - 'view' => array( - 'caption' => 'View', - 'allowOnMultiple' => false, - 'url' => 'menuaction=admin.uiaccounts.view_user&account_id=$id', - 'group' => $group, - 'onExecute' => 'javaScript:app.admin.iframe_location', ), 'add' => array( 'caption' => 'Add user', 'url' => 'menuaction=admin.uiaccounts.edit_user', 'group' => $group, - 'onExecute' => 'javaScript:app.admin.iframe_location', + 'popup' => egw_link::is_popup('addressbook', 'add'), + 'url' => '', ), 'acl' => array( 'caption' => 'Access control', @@ -159,6 +153,19 @@ class admin_ui 'icon' => 'lock', ), ); + // generate urls for add/edit accounts via addressbook + $edit = egw_link::get_registry('addressbook', 'edit'); + $edit['account_id'] = '$id'; + foreach($edit as $name => $val) + { + $actions['edit']['url'] .= ($actions['edit']['url'] ? '&' : '').$name.'='.$val; + } + unset($edit['account_id']); + $edit['owner'] = 0; + foreach($edit as $name => $val) + { + $actions['add']['url'] .= ($actions['edit']['url'] ? '&' : '').$name.'='.$val; + } ++$group; // supporting both old way using $GLOBALS['menuData'] and new just returning data in hook $apps = array_unique(array_merge(array('admin'), $GLOBALS['egw']->hooks->hook_implemented('edit_user'))); diff --git a/admin/templates/default/account.xet b/admin/templates/default/account.xet index 29c0ee592e..54ab764e52 100644 --- a/admin/templates/default/account.xet +++ b/admin/templates/default/account.xet @@ -26,10 +26,10 @@ - + - + @@ -42,14 +42,19 @@ - - - + + + + + + + +