diff --git a/preferences/inc/class.preferences_settings.inc.php b/preferences/inc/class.preferences_settings.inc.php index 339b8d9116..c3154aa9f0 100644 --- a/preferences/inc/class.preferences_settings.inc.php +++ b/preferences/inc/class.preferences_settings.inc.php @@ -46,7 +46,7 @@ class preferences_settings $tpl = new etemplate_old('preferences.settings'); if (!is_array($content)) { - $appname = isset($_GET['appname']) ? $_GET['appname'] : 'preferences'; + $appname = isset($_GET['appname']) && $_GET['appname'] != 'preferences' ? $_GET['appname'] : 'common'; $type = 'user'; $account_id = $GLOBALS['egw_info']['user']['account_id']; if ($GLOBALS['egw_info']['user']['apps']['admin'] && @@ -60,9 +60,6 @@ class preferences_settings else { //_debug_array($content); - $appname = $content['appname'] ? $content['appname'] : 'preferences'; - list($type,$account_id) = explode(':', $content['type']); - $prefs = array_merge($content['tab1'], $content['tab2'], $content['tab3'], $content['tab4']); if ($content['button']) { list($button) = each($content['button']); @@ -71,16 +68,36 @@ class preferences_settings case 'save': case 'apply': // ToDo: save preferences - - $msg = lang('Preferences saved.').array2string($prefs); + $appname = $content['old_appname'] ? $content['old_appname'] : 'common'; + list($type,$account_id) = explode(':', $content['old_type']); + $prefs = array_merge($content['tab1'], $content['tab2'], $content['tab3'], $content['tab4']); + if ($account_id && $account_id != $GLOBALS['egw']->preferences->account_id) + { + $GLOBALS['egw']->preferences->account_id = $account_id; + $GLOBALS['egw']->preferences->read_repository(); + } + $attribute = $type == 'group' ? 'user' : $type; + if (!($msg=$this->process_array($GLOBALS['egw']->preferences->$attribute, $prefs, null, $appname, $attribute))) + { + $msg = lang('Preferences saved.'); //.array2string($prefs); + } if ($button == 'apply') break; // fall throught case 'cancel': egw::redirect_link('/preferences/index.php'); } } + $appname = $content['appname'] ? $content['appname'] : 'common'; + list($type,$account_id) = explode(':', $content['type']); //_debug_array($prefs); } + // if not just saved, call validation before, to be able to show failed validation of current prefs + if (!isset($button)) + { + $attribute = $type == 'group' ? 'user' : $type; + $msg = $this->process_array($GLOBALS['egw']->preferences->$attribute, + $GLOBALS['egw']->preferences->{$attribute}[$appname], null, $appname, $attribute, true); + } if ($account_id && $account_id != $GLOBALS['egw']->preferences->account_id) { $GLOBALS['egw']->preferences->account_id = $account_id; @@ -92,13 +109,134 @@ class preferences_settings $tpl->exec('preferences.preferences_settings.index', $content, $sel_options, $readonlys, array( 'appname' => $content['appname'], 'type' => $content['type'], + 'old_appname' => $content['appname'], + 'old_type' => $content['type'], )); } + /** + * Verify and save preferences + * + * @param array &$repository + * @param array $values + * @param array $notifies + * @param string $appname appname or 'common' + * @param string $type + * @param boolean $only_verify=false + * @return string with verification error or null on success + */ + function process_array(&$repository, $values, $notifies, $appname, $type, $only_verify=false) + { + //_debug_array($repository); + $prefs = &$repository[$appname]; + + unset($prefs['']); + //_debug_array($values);exit; + foreach($values as $var => $value) + { + if(isset($value) && $value !== '' && $value !== '**NULL**') + { + if (is_array($value)) + { + if (isset($value['pw'])) + { + $value = $value['pw']; + if(empty($value)) + { + continue; // dont write empty password-fields + } + } + elseif(isset($value[$vfs_type='vfs_file']) || isset($value[$vfs_type='vfs_dir']) || isset($value[$vfs_type='vfs_dirs'])) + { + $value = $value[$vfs_type]; + if ($value === '') + { + // empty is always allowed + + // If forced, empty == not set + if($type == 'forced') + { + unset($prefs[$var]); + // need to call preferences::delete, to also set affective prefs! + if (!$only_verify) $GLOBALS['egw']->preferences->delete($appname, $var, $type); + continue; + } + } + elseif ($vfs_type == 'vfs_file') + { + if ($value[0] != '/' || !egw_vfs::stat($value)) + { + $error = lang('%1 is no existing vfs file!',htmlspecialchars($value)); + } + } + else + { + // split multiple comma or whitespace separated directories + // to still allow space or comma in dirnames, we also use the trailing slash of all pathes to split + foreach($vfs_type == 'vfs_dir' ? array($value) : preg_split('/[,\s]+\//', $value) as $n => $dir) + { + if ($n) $dir = '/'.$dir; // re-adding trailing slash removed by split + if ($dir[0] != '/' || !egw_vfs::stat($dir) || !egw_vfs::is_dir($dir)) + { + $error .= ($error ? ' ' : '').lang('%1 is no existing vfs directory!',$dir); + } + } + } + } + else + { + $value = implode(',',$value); // multiselect + } + } + $prefs[$var] = $value; + + if(is_array($notifies) && isset($notifies[$var])) // need to translate the key-words back + { + $prefs[$var] = $GLOBALS['egw']->preferences->lang_notify($prefs[$var],$notifies[$var],True); + } + // need to call preferences::add, to also set affective prefs! + if (!$only_verify) $GLOBALS['egw']->preferences->add($appname, $var, $prefs[$var], $type); + } + else + { + unset($prefs[$var]); + // need to call preferences::delete, to also set affective prefs! + if (!$only_verify) $GLOBALS['egw']->preferences->delete($appname, $var, $type); + } + } + //echo "prefix='$prefix', prefs=
"; print_r($repository[$appname]); echo "\n"; + + // the following hook can be used to verify the prefs + // if you return something else than False, it is treated as an error-msg and + // displayed to the user (the prefs are not saved) + // + if(($error .= $GLOBALS['egw']->hooks->single(array( + 'location' => 'verify_settings', + 'prefs' => $repository[$appname], + 'prefix' => $prefix, + 'type' => $type + ), + $appname + ))) + { + return $error; + } + + if (!$only_verify) $GLOBALS['egw']->preferences->save_repository(True,$type); + + // certain common prefs (language, template, ...) require the session to be re-created + if ($appname == 'common' && !$only_verify) + { + egw::invalidate_session_cache(); + } + + return null; + } + /** * Get content, sel_options and readonlys for given appname and type * - * @param string $appname + * @param string $appname appname or 'common' * @param string $type * @param array &$sel_options * @param array &$readonlys @@ -110,9 +248,8 @@ class preferences_settings { if (!$this->call_hook($appname, $type)) { - throw new egw_exception_wrong_parameter("Could not find settings for application: ".$_GET['appname']); + throw new egw_exception_wrong_parameter("Could not find settings for application: ".$appname); } - if ($appname == 'preferences') $appname = 'common'; $attribute = $type == 'group' ? 'user' : $type; //error_log(__METHOD__."('$appname', '$type' ) attribute='$attribute', preferences->account_id=".$GLOBALS['egw']->preferences->account_id); @@ -141,11 +278,13 @@ class preferences_settings case 'subsection': // is in old code, but never seen it used continue 2; + case 'password': case 'vfs_file': case 'vfs_dir': case 'vfs_dirs': case 'notify': // ToDo: implementation ... + error_log(__METHOD__."('$appname', '$type') NOT implemented settings type '$old_type'!"); // handle as input for now case 'input': $setting['type'] = 'textbox'; @@ -177,8 +316,12 @@ class preferences_settings case 'user': $setting['values'] = array('' => lang('Use default'))+$setting['values']; break; + case 'default': + case 'group': + $setting['values'] = array('' => lang('No default'))+$setting['values']; + break; case 'forced'; - $setting['values'] = array('' => lang('Users choice'))+$setting['values']; + $setting['values'] = array('**NULL**' => lang('Users choice'))+$setting['values']; break; } } @@ -234,13 +377,13 @@ class preferences_settings } natcasesort($sel_options['appname']); + $sel_options['type'] = array( + 'user' => 'Your preferences', + 'default' => 'Default preferences', + 'forced' => 'Forced preferences', + ); if ($GLOBALS['egw_info']['apps']['admin']) { - $sel_options['type'] = array( - 'user' => 'Your preferences', - 'default' => 'Default preferences', - 'forced' => 'Forced preferences', - ); $content['type'] = $type; if ($GLOBALS['egw']->preferences->account_id != $GLOBALS['egw_info']['user']['account_id']) { @@ -249,12 +392,13 @@ class preferences_settings } foreach($GLOBALS['egw']->accounts->search(array('type' => 'groups', 'sort' => 'account_lid')) as $account_id => $group) { - $sel_options['type']['group:'.$account_id] = common::display_fullname($group['account_lid'], '', '', $account_id); + $sel_options['type']['group:'.$account_id] = lang('Preferences').' '.common::display_fullname($group['account_lid'], '', '', $account_id); } } else { $content['type'] = 'user'; + $readonlys['type'] = true; } //_debug_array($content); exit; //_debug_array($sel_options); //exit; @@ -266,12 +410,13 @@ class preferences_settings * * Sets $this->appname and $this->settings * - * @param string $appname + * @param string $appname appname or 'common' + * @param string $type='user' 'default' or 'forced' * @return boolean */ protected function call_hook($appname, $type='user') { - $this->appname = $appname; + $this->appname = $appname == 'common' ? 'preferences' : $appname; translation::add_app($this->appname); if($this->appname != 'preferences') @@ -332,7 +477,6 @@ class preferences_settings // check if we have a default/forced value from the settings hook, // which is NOT stored as default currently // --> store it as default, to allow to propagate defaults to existing installations - if ($appname == 'preferences') $appname = 'common'; foreach ($this->settings as $name => $data) { // only set not yet set default prefs, so user is able to unset it again with "" diff --git a/preferences/setup/etemplates.inc.php b/preferences/setup/etemplates.inc.php index e946ebfebd..8926fbbf28 100644 --- a/preferences/setup/etemplates.inc.php +++ b/preferences/setup/etemplates.inc.php @@ -2,7 +2,7 @@ /** * EGroupware - eTemplates for Application preferences * http://www.egroupware.org - * generated by soetemplate::dump4setup() 2013-05-03 15:06 + * generated by soetemplate::dump4setup() 2013-05-03 17:22 * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package preferences @@ -12,7 +12,7 @@ $templ_version=1; -$templ_data[] = array('name' => 'preferences.settings','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:5:{i:0;a:3:{s:4:"name";s:3:"msg";s:4:"type";s:5:"label";s:4:"span";s:10:",redItalic";}i:1;a:3:{s:4:"type";s:6:"select";s:4:"name";s:4:"type";s:8:"onchange";i:1;}i:2;a:5:{s:4:"type";s:6:"select";s:4:"name";s:7:"appname";s:4:"size";s:18:"Common preferences";s:5:"label";s:11:"Application";s:8:"onchange";i:1;}i:3;a:3:{s:4:"name";s:29:"tabs=tab1|tab2|tab3|tab4|tab5";s:4:"type";s:3:"tab";s:5:"label";s:29:"Tab 1|Tab 2|Tab 3|Tab 4|Tab 5";}i:4;a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:3:{s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";s:4:"type";s:6:"button";}i:2;a:3:{s:5:"label";s:5:"Apply";s:4:"name";s:13:"button[apply]";s:4:"type";s:6:"button";}i:3;a:3:{s:5:"label";s:6:"Cancel";s:4:"name";s:14:"button[cancel]";s:4:"type";s:6:"button";}}}','size' => '','style' => '','modified' => '1367564824',); +$templ_data[] = array('name' => 'preferences.settings','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:5:{i:0;a:3:{s:4:"name";s:3:"msg";s:4:"type";s:5:"label";s:4:"span";s:10:",redItalic";}i:1;a:4:{s:4:"type";s:6:"select";s:4:"name";s:4:"type";s:8:"onchange";i:1;s:4:"span";s:9:",prefType";}i:2;a:5:{s:4:"type";s:6:"select";s:4:"name";s:7:"appname";s:4:"size";s:18:"Common preferences";s:8:"onchange";i:1;s:4:"span";s:8:",prefApp";}i:3;a:3:{s:4:"name";s:29:"tabs=tab1|tab2|tab3|tab4|tab5";s:4:"type";s:3:"tab";s:5:"label";s:29:"Tab 1|Tab 2|Tab 3|Tab 4|Tab 5";}i:4;a:5:{s:4:"type";s:4:"hbox";s:4:"size";s:1:"3";i:1;a:3:{s:5:"label";s:4:"Save";s:4:"name";s:12:"button[save]";s:4:"type";s:6:"button";}i:2;a:3:{s:5:"label";s:5:"Apply";s:4:"name";s:13:"button[apply]";s:4:"type";s:6:"button";}i:3;a:3:{s:5:"label";s:6:"Cancel";s:4:"name";s:14:"button[cancel]";s:4:"type";s:6:"button";}}}','size' => '','style' => '','modified' => '1367564824',); $templ_data[] = array('name' => 'preferences.settings.general','template' => '','lang' => '','group' => '0','version' => '1.9.001','data' => 'a:1:{i:0;a:7:{s:4:"type";s:4:"grid";s:4:"name";s:7:"general";s:4:"data";a:2:{i:0;a:2:{s:1:"A";s:3:"50%";s:2:"c1";s:7:"prefRow";}i:1;a:2:{s:1:"A";a:5:{s:4:"type";s:3:"box";s:4:"size";s:1:"2";s:4:"span";s:9:",prefName";i:1;a:2:{s:4:"name";s:13:"${row}[label]";s:4:"type";s:5:"label";}i:2;a:3:{s:4:"name";s:12:"${row}[help]";s:4:"type";s:5:"label";s:4:"span";s:9:",prefHelp";}}s:1:"B";a:4:{s:4:"name";s:13:"${row}[value]";s:4:"type";s:4:"text";s:4:"span";s:10:",prefValue";s:4:"size";s:13:"@${row}[size]";}}}s:4:"cols";i:2;s:4:"rows";i:1;s:4:"size";s:16:"100%,,,prefTable";s:7:"options";a:2:{i:3;s:9:"prefTable";i:0;s:4:"100%";}}}','size' => '100%,,,prefTable','style' => '','modified' => '1367140794',); diff --git a/preferences/templates/default/app.css b/preferences/templates/default/app.css index 18a021572b..bd756dd10a 100644 --- a/preferences/templates/default/app.css +++ b/preferences/templates/default/app.css @@ -37,3 +37,8 @@ tr.prefRow:hover .prefHelp { .prefValue { margin-right: 5px; } +.prefType, .prefApp { + font-size: 150%; + display: inline-block; + padding-bottom: 5px; +} \ No newline at end of file diff --git a/preferences/templates/default/settings.xet b/preferences/templates/default/settings.xet index eb0e14180b..d32fae578f 100644 --- a/preferences/templates/default/settings.xet +++ b/preferences/templates/default/settings.xet @@ -104,10 +104,10 @@