2013-04-28 16:52:41 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* EGroupware: Preferences app UI for settings/preferences
|
|
|
|
*
|
|
|
|
* @link http://www.egroupware.org
|
|
|
|
* @author Ralf Becker <rb@stylite.de>
|
|
|
|
* @package preferences
|
2016-04-30 19:16:36 +02:00
|
|
|
* @copyright (c) 2013-16 by Ralf Becker <rb@stylite.de>
|
2013-04-28 16:52:41 +02:00
|
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
|
|
* @version $Id$
|
|
|
|
*/
|
|
|
|
|
2016-04-30 19:16:36 +02:00
|
|
|
use EGroupware\Api;
|
|
|
|
use EGroupware\Api\Framework;
|
|
|
|
use EGroupware\Api\Egw;
|
|
|
|
use EGroupware\Api\Vfs;
|
|
|
|
use EGroupware\Api\Etemplate;
|
|
|
|
|
2013-04-28 16:52:41 +02:00
|
|
|
/**
|
2016-04-30 19:16:36 +02:00
|
|
|
* UI for settings / Api\Preferences
|
2013-04-28 16:52:41 +02:00
|
|
|
*/
|
|
|
|
class preferences_settings
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Methods callable via menuaction
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
public $public_functions = array(
|
|
|
|
'index' => true,
|
|
|
|
);
|
|
|
|
/**
|
|
|
|
* App we work on
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $appname = 'preferences';
|
|
|
|
/**
|
|
|
|
* Preferences read by call_hook
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
public $settings = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edit preferences
|
|
|
|
*
|
2014-10-21 11:15:42 +02:00
|
|
|
* @param array $content =null
|
|
|
|
* @param string $msg =''
|
2013-04-28 16:52:41 +02:00
|
|
|
*/
|
|
|
|
function index(array $content=null, $msg='')
|
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
$tpl = new Etemplate('preferences.settings');
|
2013-04-28 16:52:41 +02:00
|
|
|
if (!is_array($content))
|
|
|
|
{
|
2013-12-06 01:02:16 +01:00
|
|
|
$appname = isset($_GET['appname']) && $_GET['appname'] != 'preferences' &&
|
|
|
|
isset($GLOBALS['egw_info']['user']['apps'][$_GET['appname']]) ? $_GET['appname'] : 'common';
|
2013-05-03 15:08:08 +02:00
|
|
|
$type = 'user';
|
|
|
|
$account_id = $GLOBALS['egw_info']['user']['account_id'];
|
|
|
|
if ($GLOBALS['egw_info']['user']['apps']['admin'] &&
|
|
|
|
isset($_GET['account_id']) && (int)$_GET['account_id'] &&
|
|
|
|
$GLOBALS['egw']->accounts->exists((int)$_GET['account_id']))
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
$account_id = (int)$_GET['account_id'];
|
|
|
|
$type = $_GET['account_id'] < 0 ? 'group' : 'user';
|
2018-08-21 14:42:44 +02:00
|
|
|
$is_admin = true;
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
2013-12-06 01:02:16 +01:00
|
|
|
$content['current_app'] = isset($GLOBALS['egw_info']['user']['apps'][$_GET['current_app']]) ? $_GET['current_app'] : $appname;
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-08-21 14:42:44 +02:00
|
|
|
$is_admin = $content['is_admin'];
|
2013-05-09 12:41:38 +02:00
|
|
|
//error_log(__METHOD__."(".array2string($content).")");
|
2013-05-03 15:08:08 +02:00
|
|
|
if ($content['button'])
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
list($button) = each($content['button']);
|
2013-12-02 18:38:15 +01:00
|
|
|
$appname = $content['old_appname'] ? $content['old_appname'] : 'common';
|
2013-05-03 15:08:08 +02:00
|
|
|
switch($button)
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
case 'save':
|
|
|
|
case 'apply':
|
2014-07-13 12:27:46 +02:00
|
|
|
// check if user has rights to store preferences for $type and $account_id
|
|
|
|
if ($content['old_type'] !== 'user' && !$GLOBALS['egw_info']['user']['apps']['admin'])
|
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
throw new Api\Exception\NoPermission\Admin;
|
2014-07-13 12:27:46 +02:00
|
|
|
}
|
2013-05-03 17:25:11 +02:00
|
|
|
list($type,$account_id) = explode(':', $content['old_type']);
|
2013-05-10 09:50:30 +02:00
|
|
|
// merge prefs of all tabs together again
|
|
|
|
$prefs = array();
|
|
|
|
foreach($content as $name => $val)
|
|
|
|
{
|
|
|
|
if (is_array($val) && strpos($name, 'tab') === 0)
|
|
|
|
{
|
|
|
|
$prefs = array_merge($prefs, $val);
|
|
|
|
}
|
|
|
|
}
|
2013-05-10 19:22:14 +02:00
|
|
|
//error_log(__METHOD__."() button=$button, content=".array2string($content).' --> prefs='.array2string($prefs));;;
|
|
|
|
if ($account_id && $account_id != $GLOBALS['egw']->preferences->get_account_id())
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 19:22:14 +02:00
|
|
|
$GLOBALS['egw']->preferences->set_account_id($account_id);
|
2013-05-03 17:25:11 +02:00
|
|
|
$GLOBALS['egw']->preferences->read_repository();
|
|
|
|
}
|
2014-04-03 12:25:21 +02:00
|
|
|
// name of common preferences which require reload of framework, if there values change
|
2014-12-18 12:02:42 +01:00
|
|
|
$require_reload = array('template_set', 'theme', 'lang', 'template_color', 'template_custom_color');
|
2014-04-03 12:25:21 +02:00
|
|
|
$old_values = array_intersect_key($GLOBALS['egw_info']['user']['preferences']['common'], array_flip($require_reload));
|
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
$attribute = $type == 'group' ? 'user' : $type;
|
2018-08-21 14:42:44 +02:00
|
|
|
if (!($msg=$this->process_array($GLOBALS['egw']->preferences->$attribute, $prefs, $content['types'], $appname, $attribute, $content)))
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-10-03 11:23:18 +02:00
|
|
|
$msg_type = 'success';
|
|
|
|
$msg = lang('Preferences saved.');
|
2014-04-03 12:25:21 +02:00
|
|
|
|
|
|
|
// do we need to reload whole framework
|
|
|
|
if ($appname == 'common')
|
|
|
|
{
|
|
|
|
if ($account_id && $GLOBALS['egw']->preferences->get_account_id() != $GLOBALS['egw_info']['user']['account_id'])
|
|
|
|
{
|
|
|
|
$GLOBALS['egw']->preferences->set_account_id($GLOBALS['egw_info']['user']['account_id']);
|
|
|
|
}
|
|
|
|
$GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository();
|
|
|
|
$new_values = array_intersect_key($GLOBALS['egw_info']['user']['preferences']['common'], array_flip($require_reload));
|
|
|
|
//error_log(__METHOD__."() ".__LINE__.": old_values=".array2string($old_values).", new_values=".array2string($new_values));
|
|
|
|
if ($old_values != $new_values)
|
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
Framework::refresh_opener($msg, null, null, null, null, null, null, $msg_type);
|
2014-04-03 12:25:21 +02:00
|
|
|
}
|
|
|
|
}
|
2013-05-03 17:25:11 +02:00
|
|
|
}
|
2016-04-30 19:16:36 +02:00
|
|
|
// update client-side Api\Preferences in response
|
|
|
|
Framework::ajax_get_preference($appname);
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
2013-12-06 01:02:16 +01:00
|
|
|
if (in_array($button, array('save','cancel')))
|
2013-12-02 18:38:15 +01:00
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
Api\Json\Response::get()->call('egw.message', $msg, $msg_type);
|
|
|
|
Framework::window_close();
|
2013-12-02 18:38:15 +01:00
|
|
|
}
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
2013-05-03 17:25:11 +02:00
|
|
|
$appname = $content['appname'] ? $content['appname'] : 'common';
|
|
|
|
list($type,$account_id) = explode(':', $content['type']);
|
2013-05-03 15:08:08 +02:00
|
|
|
//_debug_array($prefs);
|
|
|
|
}
|
2013-05-10 19:22:14 +02:00
|
|
|
if ($account_id && $account_id != $GLOBALS['egw']->preferences->get_account_id())
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2013-05-10 19:22:14 +02:00
|
|
|
$GLOBALS['egw']->preferences->set_account_id($account_id);
|
2013-05-03 15:08:08 +02:00
|
|
|
$GLOBALS['egw']->preferences->read_repository();
|
|
|
|
}
|
2013-05-10 20:00:33 +02:00
|
|
|
$preserve = array('types' => array());
|
2013-07-25 18:07:41 +02:00
|
|
|
// preserv open tab, if appname is not chanaged
|
|
|
|
if (!isset($content['old_appname']) || $content['old_appname'] == $content['appname'] ||
|
|
|
|
$content['old_appname'] == 'common' && !$content['appname'])
|
|
|
|
{
|
|
|
|
$old_tab = $content['tabs'];
|
|
|
|
}
|
2013-12-06 01:02:16 +01:00
|
|
|
// we need to run under calling app, to be able to restore it to it's index page after
|
2014-04-01 17:49:08 +02:00
|
|
|
$preserve['current_app'] = $content['current_app'];
|
|
|
|
$GLOBALS['egw_info']['flags']['currentapp'] = $content['current_app'] == 'common' ?
|
|
|
|
'preferences' : $content['current_app'];
|
2016-04-30 19:16:36 +02:00
|
|
|
Framework::includeCSS('preferences','app');
|
2013-12-06 01:02:16 +01:00
|
|
|
|
2013-05-10 09:50:30 +02:00
|
|
|
// 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,
|
2018-08-21 14:42:44 +02:00
|
|
|
(array)$GLOBALS['egw']->preferences->{$attribute}[$appname], $preserve['types'], $appname, $attribute, $content, true);
|
2013-05-10 09:50:30 +02:00
|
|
|
}
|
2014-05-28 12:03:57 +02:00
|
|
|
|
|
|
|
$sel_options = $readonlys = null;
|
2014-10-21 11:15:42 +02:00
|
|
|
$data = $this->get_content($appname, $type, $sel_options, $readonlys, $preserve['types'], $tpl);
|
|
|
|
$preserve['appname'] = $preserve['old_appname'] = $data['appname'];
|
|
|
|
$preserve['type'] = $preserve['old_type'] = $data['type'];
|
2018-08-21 14:42:44 +02:00
|
|
|
$preserve['is_admin'] = $is_admin;
|
2018-08-22 12:26:56 +02:00
|
|
|
|
|
|
|
// preserve the old values since we need them for admin cmd data comparison
|
|
|
|
$preserve['old_values'] = array ();
|
|
|
|
foreach($data as $key => $val)
|
|
|
|
{
|
|
|
|
if (is_array($val) && strpos($key, 'tab') === 0)
|
|
|
|
{
|
|
|
|
foreach ($val as $k => $v)
|
|
|
|
{
|
|
|
|
if (!is_int($k)) $preserve['old_values'][$k] = $v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-21 11:15:42 +02:00
|
|
|
if (isset($old_tab)) $data['tabs'] = $old_tab;
|
2014-05-28 12:03:57 +02:00
|
|
|
|
2016-04-30 19:16:36 +02:00
|
|
|
if ($msg) Framework::message($msg, $msg_type ? $msg_type : 'error');
|
2013-05-10 09:50:30 +02:00
|
|
|
|
2014-10-21 11:15:42 +02:00
|
|
|
$tpl->exec('preferences.preferences_settings.index', $data, $sel_options, $readonlys, $preserve, 2);
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
|
|
|
|
2018-08-21 14:42:44 +02:00
|
|
|
/**
|
|
|
|
* run admin command instance
|
|
|
|
*
|
|
|
|
* @param array $content
|
|
|
|
* @param array $values
|
|
|
|
* @param string $account_id
|
|
|
|
*/
|
2018-08-22 12:26:56 +02:00
|
|
|
static function admin_cmd_run($content, $values, $account_id)
|
2018-08-21 14:42:44 +02:00
|
|
|
{
|
2018-08-22 12:26:56 +02:00
|
|
|
$changes = array_udiff_assoc($values, $content['old_values'], function($a, $b){
|
|
|
|
return (int) $a !== $b;
|
|
|
|
});
|
|
|
|
$old = array_intersect_key($content['old_values'], $changes);
|
2018-08-21 14:42:44 +02:00
|
|
|
$cmd = new admin_cmd_edit_preferences(array(
|
|
|
|
'account' => $account_id,
|
|
|
|
'set' => $changes,
|
|
|
|
'old' =>$old
|
|
|
|
)+(array)$content['admin_cmd']);
|
|
|
|
$cmd->run();
|
|
|
|
}
|
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
/**
|
|
|
|
* Verify and save preferences
|
|
|
|
*
|
2013-05-10 09:50:30 +02:00
|
|
|
* @param array &$repository values get updated here
|
|
|
|
* @param array $values new values
|
|
|
|
* @param array $types setting-name => type
|
2013-05-03 17:25:11 +02:00
|
|
|
* @param string $appname appname or 'common'
|
2013-05-10 09:50:30 +02:00
|
|
|
* @param string $type 'user', 'default', 'forced'
|
2018-08-21 14:42:44 +02:00
|
|
|
* @param array $content
|
2014-10-21 11:15:42 +02:00
|
|
|
* @param boolean $only_verify =false
|
2013-05-03 17:25:11 +02:00
|
|
|
* @return string with verification error or null on success
|
|
|
|
*/
|
2018-08-21 14:42:44 +02:00
|
|
|
function process_array(array &$repository, array $values, array $types, $appname, $type, $content, $only_verify=false)
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2017-01-23 16:01:23 +01:00
|
|
|
//fetch application specific settings from a hook
|
|
|
|
$settings = Api\Hooks::single(array(
|
|
|
|
'account_id'=>$GLOBALS['egw']->preferences->get_account_id(),
|
|
|
|
'location'=>'settings',
|
|
|
|
'type' => $type), $appname);
|
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
//_debug_array($repository);
|
|
|
|
$prefs = &$repository[$appname];
|
|
|
|
|
|
|
|
unset($prefs['']);
|
2018-08-22 12:26:56 +02:00
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
//_debug_array($values);exit;
|
|
|
|
foreach($values as $var => $value)
|
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
// type specific validation
|
|
|
|
switch((string)$types[$var])
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
case 'password': // dont write empty password-fields
|
|
|
|
if (empty($value)) continue 2;
|
|
|
|
break;
|
|
|
|
case 'vfs_file':
|
|
|
|
case 'vfs_dir':
|
|
|
|
case 'vfs_dirs':
|
|
|
|
if ($value === '')
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
// empty is always allowed
|
|
|
|
|
|
|
|
// If forced, empty == not set
|
|
|
|
if($type == 'forced')
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
unset($prefs[$var]);
|
|
|
|
// need to call preferences::delete, to also set affective prefs!
|
|
|
|
if (!$only_verify) $GLOBALS['egw']->preferences->delete($appname, $var, $type);
|
|
|
|
continue 2;
|
2013-05-03 17:25:11 +02:00
|
|
|
}
|
|
|
|
}
|
2013-05-10 09:50:30 +02:00
|
|
|
elseif ($types[$var] == 'vfs_file')
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
if ($value[0] != '/' || !Vfs::stat($value) || Vfs::is_dir($value))
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
$error = lang('%1 is no existing vfs file!',htmlspecialchars($value));
|
2013-05-03 17:25:11 +02:00
|
|
|
}
|
2013-05-10 09:50:30 +02:00
|
|
|
}
|
|
|
|
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($types[$var] == 'vfs_dir' ? array($value) : preg_split('/[,\s]+\//', $value) as $n => $dir)
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
if ($n) $dir = '/'.$dir; // re-adding trailing slash removed by split
|
2016-04-30 19:16:36 +02:00
|
|
|
if ($dir[0] != '/' || !Vfs::stat($dir) || !Vfs::is_dir($dir))
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2013-05-10 09:50:30 +02:00
|
|
|
$error .= ($error ? ' ' : '').lang('%1 is no existing vfs directory!',$dir);
|
2013-05-03 17:25:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-10 09:50:30 +02:00
|
|
|
break;
|
2013-05-10 17:56:35 +02:00
|
|
|
case 'Array': // notify
|
2016-09-19 11:06:58 +02:00
|
|
|
// Make sure the application translation is loaded
|
|
|
|
Api\Translation::add_app($appname);
|
2013-05-10 09:50:30 +02:00
|
|
|
$value = $GLOBALS['egw']->preferences->lang_notify($value, $types[$var], True);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-01-20 18:51:46 +01:00
|
|
|
if (isset($value) && $value !== '' && $value !== '**NULL**' && $value !== array())
|
2013-05-10 09:50:30 +02:00
|
|
|
{
|
2017-01-23 16:01:23 +01:00
|
|
|
if (is_array($value) && !$settings[$var]['no_sel_options']) $value = implode(',',$value); // multiselect
|
2013-05-10 09:50:30 +02:00
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
$prefs[$var] = $value;
|
|
|
|
|
|
|
|
// 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]);
|
2013-05-10 09:50:30 +02:00
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
// need to call preferences::delete, to also set affective prefs!
|
|
|
|
if (!$only_verify) $GLOBALS['egw']->preferences->delete($appname, $var, $type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
//
|
2016-04-30 19:16:36 +02:00
|
|
|
if(($error .= Api\Hooks::single(array(
|
2014-01-28 11:16:24 +01:00
|
|
|
'location' => 'verify_settings',
|
2014-05-28 12:03:57 +02:00
|
|
|
'prefs' => &$repository[$appname],
|
|
|
|
'type' => $type,
|
|
|
|
'preprocess' => $only_verify,
|
2013-05-03 17:25:11 +02:00
|
|
|
),
|
|
|
|
$appname
|
|
|
|
)))
|
|
|
|
{
|
|
|
|
return $error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-21 14:42:44 +02:00
|
|
|
if (!$only_verify)
|
2013-05-03 17:25:11 +02:00
|
|
|
{
|
2018-08-21 14:42:44 +02:00
|
|
|
if ($content['is_admin'])
|
|
|
|
{
|
2018-08-22 12:26:56 +02:00
|
|
|
self::admin_cmd_run($content, $content['old_values'], $values, $GLOBALS['egw']->preferences->get_account_id());
|
2018-08-21 14:42:44 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$GLOBALS['egw']->preferences->save_repository(True,$type);
|
|
|
|
}
|
|
|
|
|
|
|
|
// certain common prefs (language, template, ...) require the session to be re-created
|
|
|
|
if ($appname == 'common')
|
|
|
|
{
|
|
|
|
Egw::invalidate_session_cache();
|
|
|
|
}
|
2013-05-03 17:25:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-05-03 15:08:08 +02:00
|
|
|
/**
|
|
|
|
* Get content, sel_options and readonlys for given appname and type
|
|
|
|
*
|
2013-05-03 17:25:11 +02:00
|
|
|
* @param string $appname appname or 'common'
|
2013-05-03 15:08:08 +02:00
|
|
|
* @param string $type
|
|
|
|
* @param array &$sel_options
|
|
|
|
* @param array &$readonlys
|
2013-05-10 09:50:30 +02:00
|
|
|
* @param array &$types on return setting-name => setting-type
|
2013-05-03 15:08:08 +02:00
|
|
|
* @param etemplate $tpl
|
2016-04-30 19:16:36 +02:00
|
|
|
* @throws Api\Exception\WrongParameter
|
2013-05-03 15:08:08 +02:00
|
|
|
* @return array content
|
|
|
|
*/
|
2013-05-10 09:50:30 +02:00
|
|
|
function get_content($appname, $type, &$sel_options, &$readonlys, &$types, $tpl)
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2014-07-18 13:46:10 +02:00
|
|
|
if (!$this->call_hook($appname, $type, $GLOBALS['egw']->preferences->get_account_id()))
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
throw new Api\Exception\WrongParameter("Could not find settings for application: ".$appname);
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
|
|
|
$attribute = $type == 'group' ? 'user' : $type;
|
2013-05-10 19:22:14 +02:00
|
|
|
//error_log(__METHOD__."('$appname', '$type' ) attribute='$attribute', preferences->account_id=".$GLOBALS['egw']->preferences->get_account_id());
|
2013-05-03 15:08:08 +02:00
|
|
|
|
|
|
|
//_debug_array($this->settings); exit;
|
|
|
|
$sel_options = $readonlys = $content = $tabs = array();
|
|
|
|
// disable all but first tab and name current tab "tab1", for apps not using sections
|
|
|
|
$tab = 'tab1';
|
|
|
|
foreach($this->settings as $setting)
|
|
|
|
{
|
|
|
|
if (!is_array($setting)) continue;
|
2014-01-20 12:07:36 +01:00
|
|
|
if ($type != 'forced' && (string)$GLOBALS['egw']->preferences->forced[$appname][$setting['name']] !== '')
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
|
|
|
continue; // forced preferences are not displayed, unless we edit them
|
|
|
|
}
|
2013-05-10 09:50:30 +02:00
|
|
|
$types[$setting['name']] = $old_type = $setting['type'];
|
|
|
|
|
|
|
|
switch($old_type)
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
|
|
|
case 'section':
|
|
|
|
$tab = 'tab'.(1+count($tabs));
|
2013-05-09 11:38:12 +02:00
|
|
|
$tabs[] = array(
|
|
|
|
'id' => $tab,
|
|
|
|
'template' => 'preferences.settings.tab1',
|
|
|
|
'label' => $setting['title'],
|
|
|
|
);
|
2013-05-03 15:08:08 +02:00
|
|
|
// fall through
|
|
|
|
case 'subsection': // is in old code, but never seen it used
|
|
|
|
continue 2;
|
2013-04-28 16:52:41 +02:00
|
|
|
|
2013-05-10 09:50:30 +02:00
|
|
|
case 'notify':
|
2013-05-10 17:56:35 +02:00
|
|
|
$vars = $GLOBALS['egw']->preferences->vars;
|
|
|
|
if (is_array($setting['values'])) $vars += $setting['values'];
|
|
|
|
$GLOBALS['egw']->preferences->{$attribute}[$appname][$setting['name']] =
|
|
|
|
$GLOBALS['egw']->preferences->lang_notify($GLOBALS['egw']->preferences->{$attribute}[$appname][$setting['name']], $vars);
|
|
|
|
$types[$setting['name']] = $vars; // store vars for re-translation, instead type "notify"
|
2013-05-10 18:39:42 +02:00
|
|
|
if ($setting['help'] && ($setting['run_lang'] || !isset($setting['run_lang'])))
|
2013-05-10 17:56:35 +02:00
|
|
|
{
|
|
|
|
$setting['help'] = lang($setting['help']);
|
|
|
|
}
|
|
|
|
$setting['help'] .= '<p><b>'.lang('Substitutions and their meanings:').'</b>';
|
|
|
|
foreach($vars as $var => $var_help)
|
|
|
|
{
|
|
|
|
$lname = ($lname = lang($var)) == $var.'*' ? $var : $lname;
|
|
|
|
$setting['help'] .= "<br>\n".'<b>$$'.$lname.'$$</b>: '.$var_help;
|
|
|
|
}
|
|
|
|
$setting['help'] .= "</p>\n";
|
2013-05-10 18:39:42 +02:00
|
|
|
$setting['run_lang'] = false; // already done now
|
2013-05-10 17:56:35 +02:00
|
|
|
// handle as textarea
|
2013-05-10 09:50:30 +02:00
|
|
|
case 'textarea':
|
2014-03-23 10:34:18 +01:00
|
|
|
$setting['type'] = is_a($tpl, 'etemplate') ? 'textarea' : 'textbox';
|
2013-05-10 09:50:30 +02:00
|
|
|
$tpl->setElementAttribute($tab.'['.$setting['name'].']', 'multiline', 'true');
|
2015-02-26 16:03:20 +01:00
|
|
|
$tpl->setElementAttribute($tab. '[' . $setting['name'] . ']','width', '99%' );
|
2013-05-10 10:24:15 +02:00
|
|
|
// anyway setting via css: width: 99%, height: 5em
|
|
|
|
// for old eT use size attribute
|
2014-03-23 10:34:18 +01:00
|
|
|
if (is_a($tpl, 'etemplate') && (!empty($setting['cols']) || !empty($setting['rows'])))
|
2013-05-10 10:24:15 +02:00
|
|
|
{
|
|
|
|
$setting['size'] = $setting['rows'].','.$setting['cols'];
|
|
|
|
}
|
2013-05-10 09:50:30 +02:00
|
|
|
break;
|
2013-05-03 17:25:11 +02:00
|
|
|
case 'password':
|
2013-05-03 15:08:08 +02:00
|
|
|
case 'vfs_file':
|
|
|
|
case 'vfs_dir':
|
|
|
|
case 'vfs_dirs':
|
|
|
|
case 'input':
|
|
|
|
$setting['type'] = 'textbox';
|
|
|
|
break;
|
|
|
|
case 'check':
|
|
|
|
$setting['type'] = 'select';
|
|
|
|
$setting['values'] = array('1' => lang('yes'), '0' => lang('no'));
|
|
|
|
break;
|
|
|
|
case 'multiselect':
|
|
|
|
$setting['type'] = 'select';
|
2013-06-11 16:34:28 +02:00
|
|
|
$tpl->setElementAttribute($tab.'['.$setting['name'].']', 'rows', 5);
|
2013-05-03 15:08:08 +02:00
|
|
|
if (!isset($setting['size'])) $setting['size'] = '5'; // old eT
|
|
|
|
break;
|
|
|
|
case 'color':
|
|
|
|
$setting['type'] = 'colorpicker';
|
|
|
|
break;
|
2014-06-06 13:59:20 +02:00
|
|
|
case 'date-duration':
|
|
|
|
if (!isset($setting['size'])) $setting['size'] = 'm,dhm,24,1';
|
|
|
|
$attrs = explode(',', $setting['size']);
|
|
|
|
foreach(array("data_format","display_format", "hours_per_day", "empty_not_0", "short_labels") as $n => $name)
|
|
|
|
{
|
|
|
|
if ((string)$attrs[$n] !== '') $tpl->setElementAttribute($tab.'['.$setting['name'].']', $name, $attrs[$n]);
|
|
|
|
}
|
|
|
|
break;
|
2017-01-13 15:13:44 +01:00
|
|
|
case 'taglist':
|
|
|
|
if ($setting['no_sel_options'])
|
|
|
|
{
|
|
|
|
$tpl->setElementAttribute ($tab.'['.$setting['name'].']', 'autocomplete_url', '');
|
|
|
|
}
|
|
|
|
break;
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
|
|
|
// move values/options to sel_options array
|
2017-01-12 12:27:46 +01:00
|
|
|
if (isset($setting['values']) && is_array($setting['values']) && !$setting['no_sel_options'])
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2013-05-10 17:56:35 +02:00
|
|
|
if ($old_type != 'multiselect' && $old_type != 'notify')
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
|
|
|
switch($type)
|
|
|
|
{
|
|
|
|
case 'user':
|
|
|
|
$setting['values'] = array('' => lang('Use default'))+$setting['values'];
|
|
|
|
break;
|
2013-05-03 17:25:11 +02:00
|
|
|
case 'default':
|
|
|
|
case 'group':
|
|
|
|
$setting['values'] = array('' => lang('No default'))+$setting['values'];
|
|
|
|
break;
|
2013-05-03 15:08:08 +02:00
|
|
|
case 'forced';
|
2013-05-03 17:25:11 +02:00
|
|
|
$setting['values'] = array('**NULL**' => lang('Users choice'))+$setting['values'];
|
2013-05-03 15:08:08 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$sel_options[$setting['name']] = $setting['values'];
|
|
|
|
}
|
|
|
|
if ($type == 'user')
|
|
|
|
{
|
2013-05-10 19:22:14 +02:00
|
|
|
$default = $GLOBALS['egw']->preferences->group[$appname][$setting['name']] ?
|
|
|
|
$GLOBALS['egw']->preferences->group[$appname][$setting['name']] :
|
|
|
|
$GLOBALS['egw']->preferences->default[$appname][$setting['name']];
|
|
|
|
|
2014-01-10 10:08:40 +01:00
|
|
|
// replace default value(s) for selectboxes with selectbox labels
|
|
|
|
if (isset($setting['values']) && is_array($setting['values']))
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2014-01-10 10:08:40 +01:00
|
|
|
$default = self::get_default_label($default, $setting['values']);
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
2013-05-10 18:39:42 +02:00
|
|
|
if (is_array($types[$setting['name']])) // translate the substitution names
|
|
|
|
{
|
|
|
|
$default = $GLOBALS['egw']->preferences->lang_notify($default, $types[$setting['name']]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($setting['help'] && ($setting['run_lang'] || !isset($setting['run_lang'])))
|
|
|
|
{
|
|
|
|
$setting['help'] = lang($setting['help']);
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
2013-05-03 15:08:08 +02:00
|
|
|
$content[$tab][] = array(
|
2013-05-10 09:50:30 +02:00
|
|
|
'name' => $setting['name'],
|
|
|
|
'type' => $setting['type'],
|
|
|
|
'label' => preg_replace('|<br[ /]*>|i', "\n", $setting['label']),
|
2013-05-10 17:56:35 +02:00
|
|
|
'help' => lang($setting['help']), // is html
|
2017-10-10 18:46:18 +02:00
|
|
|
'default' => (string)$default !== '' ? lang('Default').': '.$default : null,
|
2013-05-10 09:50:30 +02:00
|
|
|
'onchange' => $setting['onchange'],
|
2018-06-27 17:40:26 +02:00
|
|
|
'attributes' => $setting['attributes']
|
2013-05-03 15:08:08 +02:00
|
|
|
);
|
2013-05-10 20:00:33 +02:00
|
|
|
//error_log("appname=$appname, attribute=$attribute, setting=".array2string($setting));
|
2013-05-03 15:08:08 +02:00
|
|
|
$content[$tab][$setting['name']] = $GLOBALS['egw']->preferences->{$attribute}[$appname][$setting['name']];
|
|
|
|
//if ($old_type == 'multiselect') $content[$tab][$setting['name']] = explode(',', $content[$tab][$setting['name']]);
|
|
|
|
}
|
2013-05-09 11:38:12 +02:00
|
|
|
// defining used tabs on run-time
|
2014-04-22 18:09:26 +02:00
|
|
|
if ($tabs)
|
|
|
|
{
|
|
|
|
$tpl->setElementAttribute('tabs', 'tabs', $tabs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Modifications are kept in the request, so reset to just one
|
|
|
|
$tpl->setElementAttribute('tabs', 'tabs', array(array(
|
|
|
|
'id' => 'tab1',
|
|
|
|
'template' => 'preferences.settings.tab1',
|
|
|
|
'label' => 'general settings'
|
|
|
|
)));
|
|
|
|
}
|
2013-05-03 15:08:08 +02:00
|
|
|
|
|
|
|
$content['appname'] = $appname;
|
|
|
|
$sel_options['appname'] = array();
|
2016-04-30 19:16:36 +02:00
|
|
|
foreach(Api\Hooks::implemented('settings') as $app)
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2014-10-21 11:15:42 +02:00
|
|
|
if ($app != 'preferences' && $GLOBALS['egw_info']['user']['apps'][$app])
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
|
|
|
$sel_options['appname'][$app] = $GLOBALS['egw_info']['apps'][$app]['title'];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
natcasesort($sel_options['appname']);
|
|
|
|
|
2013-05-03 17:25:11 +02:00
|
|
|
$sel_options['type'] = array(
|
|
|
|
'user' => 'Your preferences',
|
|
|
|
'default' => 'Default preferences',
|
|
|
|
'forced' => 'Forced preferences',
|
|
|
|
);
|
2014-07-13 12:27:46 +02:00
|
|
|
if ($GLOBALS['egw_info']['user']['apps']['admin'])
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
|
|
|
$content['type'] = $type;
|
2013-05-10 19:22:14 +02:00
|
|
|
if (($id = $GLOBALS['egw']->preferences->get_account_id()) != $GLOBALS['egw_info']['user']['account_id'])
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2013-05-10 19:22:14 +02:00
|
|
|
$content['type'] .= ':'.$id;
|
2016-04-30 19:16:36 +02:00
|
|
|
$sel_options['type'][$content['type']] = Api\Accounts::username($GLOBALS['egw']->preferences->account_id);
|
2013-10-03 11:23:18 +02:00
|
|
|
|
2013-09-17 18:26:45 +02:00
|
|
|
// Restrict app list to apps the user has access to
|
|
|
|
$user_apps = $GLOBALS['egw']->acl->get_user_applications($id);
|
|
|
|
$sel_options['appname'] = array_intersect_key($sel_options['appname'], $user_apps);
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
2014-01-21 19:06:07 +01:00
|
|
|
foreach($GLOBALS['egw']->accounts->search(array('type' => 'groups', 'order' => 'account_lid')) as $account_id => $group)
|
2013-05-03 15:08:08 +02:00
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
$sel_options['type']['group:'.$account_id] = lang('Preferences').' '.Api\Accounts::format_username($group['account_lid'], '', '', $account_id);
|
2013-05-03 15:08:08 +02:00
|
|
|
}
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
$content['type'] = 'user';
|
2013-05-03 17:25:11 +02:00
|
|
|
$readonlys['type'] = true;
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
2013-05-03 15:08:08 +02:00
|
|
|
//_debug_array($content); exit;
|
|
|
|
//_debug_array($sel_options); //exit;
|
|
|
|
return $content;
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
|
|
|
|
2014-01-10 10:08:40 +01:00
|
|
|
/**
|
|
|
|
* Get label for given default value(s)
|
|
|
|
*
|
|
|
|
* @param string|array $default default value(s) to get label for
|
|
|
|
* @param array $values values optional including optgroups
|
2014-10-21 11:15:42 +02:00
|
|
|
* @param boolean $lang =true
|
2014-01-10 10:08:40 +01:00
|
|
|
* @return string comma-separated and translated labels
|
|
|
|
*/
|
|
|
|
protected static function get_default_label($default, array $values, $lang=true)
|
|
|
|
{
|
|
|
|
// explode comma-separated multiple default values
|
|
|
|
if (!is_array($default) && !isset($values[$default]) && strpos($default, ',') !== false)
|
|
|
|
{
|
|
|
|
$labels = explode(',', $default);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$labels = (array)$default;
|
|
|
|
}
|
|
|
|
foreach($labels as &$def)
|
|
|
|
{
|
|
|
|
if (isset($values[$def]))
|
|
|
|
{
|
|
|
|
$def = is_array($values[$def]) ? $values[$def]['label'] : $values[$def];
|
|
|
|
}
|
|
|
|
else // value could be in an optgroup
|
|
|
|
{
|
|
|
|
foreach($values as $value)
|
|
|
|
{
|
|
|
|
if (is_array($value) && !isset($value['label']) && isset($value[$def]))
|
|
|
|
{
|
|
|
|
$def = is_array($value[$def]) ? $value[$def]['label'] : $value[$def];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($lang) $def = lang($def);
|
|
|
|
}
|
|
|
|
$label = implode(', ', $labels);
|
|
|
|
//error_log(__METHOD__."(".array2string($default).', '.array2string($values).") returning $label");
|
|
|
|
return $label;
|
|
|
|
}
|
|
|
|
|
2013-04-28 16:52:41 +02:00
|
|
|
/**
|
|
|
|
* Get preferences by calling various hooks to supply them
|
|
|
|
*
|
|
|
|
* Sets $this->appname and $this->settings
|
|
|
|
*
|
2013-05-03 17:25:11 +02:00
|
|
|
* @param string $appname appname or 'common'
|
2014-10-21 11:15:42 +02:00
|
|
|
* @param string $type ='user' 'default', 'forced', 'user' or 'group'
|
|
|
|
* @param int|string $account_id =null account_id for user or group prefs, or "forced" or "default"
|
2013-04-28 16:52:41 +02:00
|
|
|
* @return boolean
|
|
|
|
*/
|
2014-07-18 13:46:10 +02:00
|
|
|
protected function call_hook($appname, $type='user', $account_id=null)
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
2013-05-03 17:25:11 +02:00
|
|
|
$this->appname = $appname == 'common' ? 'preferences' : $appname;
|
2013-04-28 16:52:41 +02:00
|
|
|
|
2013-11-26 18:55:51 +01:00
|
|
|
// Set framework here to make sure we get the right settings for user's [newly] selected template
|
|
|
|
$GLOBALS['egw_info']['server']['template_set'] = $GLOBALS['egw']->preferences->data['common']['template_set'];
|
2016-04-30 19:16:36 +02:00
|
|
|
Api\Translation::add_app($this->appname);
|
2013-04-28 16:52:41 +02:00
|
|
|
if($this->appname != 'preferences')
|
|
|
|
{
|
2016-04-30 19:16:36 +02:00
|
|
|
Api\Translation::add_app('preferences'); // we need the prefs translations too
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
|
|
|
|
2016-04-30 19:16:36 +02:00
|
|
|
// make type available, to hooks from Egw\Applications can use it, eg. activesync
|
2014-07-18 13:46:10 +02:00
|
|
|
$hook_data = array(
|
|
|
|
'location' => 'settings',
|
|
|
|
'type' => $type,
|
|
|
|
'account_id' => $account_id,
|
|
|
|
);
|
|
|
|
$GLOBALS['type'] = $type; // old global variable
|
2013-05-03 15:08:08 +02:00
|
|
|
|
2013-04-28 16:52:41 +02:00
|
|
|
// calling app specific settings hook
|
2016-04-30 19:16:36 +02:00
|
|
|
$settings = Api\Hooks::single($hook_data, $this->appname);
|
2013-04-28 16:52:41 +02:00
|
|
|
// it either returns the settings or save it in $GLOBALS['settings'] (deprecated!)
|
|
|
|
if (isset($settings) && is_array($settings) && $settings)
|
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
$this->settings = array_merge($this->settings, $settings);
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
|
|
|
elseif(isset($GLOBALS['settings']) && is_array($GLOBALS['settings']) && $GLOBALS['settings'])
|
|
|
|
{
|
2013-05-03 15:08:08 +02:00
|
|
|
$this->settings = array_merge($this->settings, $GLOBALS['settings']);
|
2013-04-28 16:52:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return False; // no settings returned
|
|
|
|
}
|
|
|
|
|
|
|
|
// calling settings hook all apps can answer (for a specific app)
|
2014-07-18 13:46:10 +02:00
|
|
|
$hook_data['location'] = 'settings_'.$this->appname;
|
2016-04-30 19:16:36 +02:00
|
|
|
foreach(Api\Hooks::process($hook_data, $this->appname,true) as $settings)
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
|
|
|
if (isset($settings) && is_array($settings) && $settings)
|
|
|
|
{
|
|
|
|
$this->settings = array_merge($this->settings,$settings);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Remove ui-only settings */
|
|
|
|
if($this->xmlrpc)
|
|
|
|
{
|
|
|
|
foreach($this->settings as $key => $valarray)
|
|
|
|
{
|
|
|
|
if(!$valarray['xmlrpc'])
|
|
|
|
{
|
|
|
|
unset($this->settings[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Here we include the settings hook file for the current template, if it exists.
|
|
|
|
This is not handled by the hooks class and is only valid if not using xml-rpc.
|
|
|
|
*/
|
|
|
|
$tmpl_settings = EGW_SERVER_ROOT.$GLOBALS['egw']->framework->template_dir.'/hook_settings.inc.php';
|
|
|
|
if($this->appname == 'preferences' && file_exists($tmpl_settings))
|
|
|
|
{
|
|
|
|
include($tmpl_settings);
|
|
|
|
$this->settings = array_merge($this->settings,$GLOBALS['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
|
|
|
|
foreach ($this->settings as $name => $data)
|
|
|
|
{
|
|
|
|
// only set not yet set default prefs, so user is able to unset it again with ""
|
|
|
|
// (only works with type vfs_*, other types delete empty values!)
|
|
|
|
if (!isset($GLOBALS['egw']->preferences->default[$appname][$name]) &&
|
2014-07-24 11:53:04 +02:00
|
|
|
((string)$data['default'] !== '' || (string)$data['forced'] !== ''))
|
2013-04-28 16:52:41 +02:00
|
|
|
{
|
|
|
|
$default = (string)$data['forced'] !== '' ? $data['forced'] : $data['default'];
|
|
|
|
//echo "<p>".__METHOD__."($appname) $this->appname/$appname/$name=$default NOT yet set!</p>\n";
|
|
|
|
$GLOBALS['egw']->preferences->default[$appname][$name] = $default;
|
|
|
|
$need_update = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($need_update)
|
|
|
|
{
|
|
|
|
$GLOBALS['egw']->preferences->save_repository(false,'default',true);
|
|
|
|
}
|
|
|
|
if($this->debug)
|
|
|
|
{
|
|
|
|
_debug_array($this->settings);
|
|
|
|
}
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
}
|