|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* EGroupware API - Preferences |
|
4
|
|
|
* |
|
5
|
|
|
* @link http://www.egroupware.org |
|
6
|
|
|
* @author Joseph Engo <[email protected]> |
|
7
|
|
|
* @author Mark Peters <[email protected]> |
|
8
|
|
|
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> merging prefs on runtime, session prefs and reworked the class |
|
9
|
|
|
* Copyright (C) 2000, 2001 Joseph Engo |
|
10
|
|
|
* @license http://opensource.org/licenses/lgpl-license.php LGPL - GNU Lesser General Public License |
|
11
|
|
|
* @package api |
|
12
|
|
|
* @version $Id$ |
|
13
|
|
|
*/ |
|
14
|
|
|
|
|
15
|
|
|
namespace EGroupware\Api; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* preferences class used for setting application preferences |
|
19
|
|
|
* |
|
20
|
|
|
* preferences are read into following arrays: |
|
21
|
|
|
* - $data effective prefs used everywhere in EGroupware |
|
22
|
|
|
* Effective prefs are merged together in following precedence from: |
|
23
|
|
|
* - $forced forced preferences set by the admin, they take precedence over user or default prefs |
|
24
|
|
|
* - $session temporary prefs eg. language set on login just for session |
|
25
|
|
|
* - $user the stored user prefs, only used for manipulating and storeing the user prefs |
|
26
|
|
|
* - $group the stored prefs of all group-memberships of current user, can NOT be deleted or stored directly! |
|
27
|
|
|
* - $default the default preferences, always used when the user has no own preference set |
|
28
|
|
|
* |
|
29
|
|
|
* To update the prefs of a certain group, not just the primary group of the user, you have to |
|
30
|
|
|
* create a new instance of preferences class, with the given id of the group. This takes into |
|
31
|
|
|
* account the offset of DEFAULT_ID, we are using currently for groups (as -1, and -2) are already |
|
32
|
|
|
* taken! |
|
33
|
|
|
* |
|
34
|
|
|
* Preferences get now json-encoded and no longer PHP serialized and addslashed, |
|
35
|
|
|
* thought they only change when they get updated. |
|
36
|
|
|
*/ |
|
37
|
|
|
class Preferences |
|
38
|
|
|
{ |
|
39
|
|
|
/** |
|
40
|
|
|
* account_id for default prefs |
|
41
|
|
|
*/ |
|
42
|
|
|
const DEFAULT_ID = -2; |
|
43
|
|
|
/** |
|
44
|
|
|
* account_id for forced prefs |
|
45
|
|
|
*/ |
|
46
|
|
|
const FORCED_ID = -1; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* account the class is instanciated for |
|
50
|
|
|
* @var int |
|
51
|
|
|
*/ |
|
52
|
|
|
var $account_id; |
|
53
|
|
|
/** |
|
54
|
|
|
* account-type u or g |
|
55
|
|
|
* @var string |
|
56
|
|
|
*/ |
|
57
|
|
|
var $account_type; |
|
58
|
|
|
/** |
|
59
|
|
|
* effectiv user prefs, used by all apps |
|
60
|
|
|
* @var array |
|
61
|
|
|
*/ |
|
62
|
|
|
var $data = array(); |
|
63
|
|
|
/** |
|
64
|
|
|
* set user prefs for saveing (no defaults/forced prefs merged) |
|
65
|
|
|
* @var array |
|
66
|
|
|
*/ |
|
67
|
|
|
var $user = array(); |
|
68
|
|
|
/** |
|
69
|
|
|
* primary group prefs |
|
70
|
|
|
* @var array |
|
71
|
|
|
*/ |
|
72
|
|
|
var $group = array(); |
|
73
|
|
|
/** |
|
74
|
|
|
* default prefs |
|
75
|
|
|
* @var array |
|
76
|
|
|
*/ |
|
77
|
|
|
var $default = array(); |
|
78
|
|
|
/** |
|
79
|
|
|
* forced prefs |
|
80
|
|
|
* @var array |
|
81
|
|
|
*/ |
|
82
|
|
|
var $forced = array(); |
|
83
|
|
|
/** |
|
84
|
|
|
* session / tempory prefs |
|
85
|
|
|
* @var array |
|
86
|
|
|
*/ |
|
87
|
|
|
var $session = array(); |
|
88
|
|
|
/** |
|
89
|
|
|
* @var Db |
|
90
|
|
|
*/ |
|
91
|
|
|
var $db; |
|
92
|
|
|
/** |
|
93
|
|
|
* table-name |
|
94
|
|
|
*/ |
|
95
|
|
|
const TABLE = 'egw_preferences'; |
|
96
|
|
|
var $table = self::TABLE; |
|
97
|
|
|
|
|
98
|
|
|
var $values,$vars; // standard notify substitues, will be set by standard_substitues() |
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* Contstructor |
|
102
|
|
|
* |
|
103
|
|
|
* @param int|string $account_id ='' |
|
104
|
|
|
* @return preferences |
|
105
|
|
|
*/ |
|
106
|
|
|
function __construct($account_id = '') |
|
107
|
|
|
{ |
|
108
|
|
|
if (isset($GLOBALS['egw']->db)) |
|
109
|
|
|
{ |
|
110
|
|
|
$this->db = $GLOBALS['egw']->db; |
|
111
|
|
|
} |
|
112
|
|
|
else |
|
113
|
|
|
{ |
|
114
|
|
|
$this->db = $GLOBALS['egw_setup']->db; |
|
115
|
|
|
$this->table = $GLOBALS['egw_setup']->prefs_table; |
|
116
|
|
|
} |
|
117
|
|
|
$this->set_account_id($account_id); |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
/** |
|
121
|
|
|
* Set account_id for class |
|
122
|
|
|
* |
|
123
|
|
|
* Takes care of offset for groups. |
|
124
|
|
|
* |
|
125
|
|
|
* @param int|string $account_id numeric account_id, "default", "forced" to load default or forced preferences |
|
126
|
|
|
* or account_lid (only if !== "default" or "forced"!) |
|
127
|
|
|
*/ |
|
128
|
|
|
function set_account_id($account_id) |
|
129
|
|
|
{ |
|
130
|
|
|
if ($account_id === 'default') |
|
131
|
|
|
{ |
|
132
|
|
|
$this->account_id = self::DEFAULT_ID; |
|
133
|
|
|
} |
|
134
|
|
|
elseif ($account_id === 'forced') |
|
135
|
|
|
{ |
|
136
|
|
|
$this->account_id = self::FORCED_ID; |
|
137
|
|
|
} |
|
138
|
|
|
// if we got instancated for a group, need to set offset of DEFAULT_ID! |
|
139
|
|
|
elseif ($account_id < 0 || !is_numeric($account_id) && ($account_id = get_account_id($account_id)) < 0) |
|
140
|
|
|
{ |
|
141
|
|
|
$this->account_id = $account_id + self::DEFAULT_ID; |
|
142
|
|
|
} |
|
143
|
|
|
else |
|
144
|
|
|
{ |
|
145
|
|
|
$this->account_id = $account_id; |
|
|
|
|
|
|
146
|
|
|
} |
|
147
|
|
|
//error_log(__METHOD__."($account_id) setting this->account_id to $this->account_id"); |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Return account_id class is instanciated for or "default" or "forced" |
|
152
|
|
|
* |
|
153
|
|
|
* Takes care of offset for groups. |
|
154
|
|
|
* |
|
155
|
|
|
* @return string|int |
|
156
|
|
|
*/ |
|
157
|
|
|
function get_account_id() |
|
158
|
|
|
{ |
|
159
|
|
|
switch ($this->account_id) |
|
160
|
|
|
{ |
|
161
|
|
|
case self::DEFAULT_ID: |
|
162
|
|
|
return 'default'; |
|
163
|
|
|
case self::FORCED_ID: |
|
164
|
|
|
return 'forced'; |
|
165
|
|
|
} |
|
166
|
|
|
return $this->account_id < self::DEFAULT_ID ? $this->account_id-self::DEFAULT_ID : $this->account_id; |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Magic function to avoid storing perferences in session, as they get re-read on each request by egw_session::verify() |
|
171
|
|
|
* |
|
172
|
|
|
* @return array with class vars to store |
|
173
|
|
|
*/ |
|
174
|
|
|
function __sleep() |
|
175
|
|
|
{ |
|
176
|
|
|
$vars = array_keys(get_object_vars($this)); |
|
177
|
|
|
|
|
178
|
|
|
return array_diff($vars, array('data', 'user', 'group', 'default', 'forced', 'session')); |
|
179
|
|
|
} |
|
180
|
|
|
|
|
181
|
|
|
/** |
|
182
|
|
|
* Lifetime in seconds of cached items 1d |
|
183
|
|
|
*/ |
|
184
|
|
|
const CACHE_LIFETIME = 86400; |
|
185
|
|
|
|
|
186
|
|
|
/** |
|
187
|
|
|
* Read preferences of requested id(s) |
|
188
|
|
|
* |
|
189
|
|
|
* @param int|array $ids |
|
190
|
|
|
* @return array id => app => preference data |
|
191
|
|
|
*/ |
|
192
|
|
|
function cache_read($ids) |
|
193
|
|
|
{ |
|
194
|
|
|
$prefs = Cache::getInstance(__CLASS__, $ids); |
|
195
|
|
|
$db_read = array(); |
|
196
|
|
|
foreach((array)$ids as $id) |
|
197
|
|
|
{ |
|
198
|
|
|
// if prefs are not returned, null or not an array, read them from db |
|
199
|
|
|
if (!isset($prefs[$id]) && !is_array($prefs[$id])) $db_read[] = $id; |
|
200
|
|
|
} |
|
201
|
|
|
if ($db_read) |
|
202
|
|
|
{ |
|
203
|
|
|
foreach($this->db->select($this->table,'*',array('preference_owner' => $db_read),__LINE__,__FILE__) as $row) |
|
204
|
|
|
{ |
|
205
|
|
|
// The following replacement is required for PostgreSQL to work |
|
206
|
|
|
$app = trim($row['preference_app']); |
|
207
|
|
|
|
|
208
|
|
|
$prefs[$row['preference_owner']][$app] = self::unserialize($row['preference_value']); |
|
209
|
|
|
} |
|
210
|
|
|
foreach($db_read as $id) |
|
211
|
|
|
{ |
|
212
|
|
|
if (!isset($prefs[$id])) $prefs[$id] = array(); |
|
213
|
|
|
Cache::setInstance(__CLASS__, $id, $prefs[$id]); |
|
214
|
|
|
} |
|
215
|
|
|
} |
|
216
|
|
|
//error_log(__METHOD__.'('.array2string($ids).') read-from-db='.array2string($db_read)); |
|
217
|
|
|
return $prefs; |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
|
|
/** |
|
221
|
|
|
* parses a notify and replaces the substitutes |
|
222
|
|
|
* |
|
223
|
|
|
* @param string $msg message to parse / substitute |
|
224
|
|
|
* @param array $values =array() extra vars to replace in addition to $this->values, vars are in an array with \ |
|
225
|
|
|
* $key => $value pairs, $key does not include the $'s and is the *untranslated* name |
|
226
|
|
|
* @param boolean $use_standard_values =true should the standard values are used |
|
227
|
|
|
* @return string with parsed notify-msg |
|
228
|
|
|
*/ |
|
229
|
|
|
function parse_notify($msg,$values=array(),$use_standard_values=True) |
|
230
|
|
|
{ |
|
231
|
|
|
$vals = $values ? $values : array(); |
|
232
|
|
|
|
|
233
|
|
|
if ($use_standard_values && is_array($this->values)) |
|
234
|
|
|
{ |
|
235
|
|
|
$vals += $this->values; |
|
236
|
|
|
} |
|
237
|
|
|
$replace = $with = array(); |
|
238
|
|
|
foreach($vals as $key => $val) |
|
239
|
|
|
{ |
|
240
|
|
|
if ($this->debug) error_log(__METHOD__." replacing \$\$$key\$\$ with $val "); |
|
|
|
|
|
|
241
|
|
|
$replace[] = '$$'.$key.'$$'; |
|
242
|
|
|
$with[] = $val; |
|
243
|
|
|
} |
|
244
|
|
|
return str_replace($replace,$with,$msg); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
/** |
|
248
|
|
|
* replaces the english key's with translated ones, or if $un_lang the opposite |
|
249
|
|
|
* |
|
250
|
|
|
* @param string $msg message to translate |
|
251
|
|
|
* @param array $vals =array() extra vars to replace in addition to $this->values, vars are in an array with \ |
|
252
|
|
|
* $key => $value pairs, $key does not include the $'s and is the *untranslated* name |
|
253
|
|
|
* @param boolean $un_lang =false if true translate back |
|
254
|
|
|
* @return string |
|
255
|
|
|
*/ |
|
256
|
|
|
function lang_notify($msg,$vals=array(),$un_lang=False) |
|
257
|
|
|
{ |
|
258
|
|
|
foreach(array_keys($vals) as $key) |
|
259
|
|
|
{ |
|
260
|
|
|
$lname = ($lname = lang($key)) == $key.'*' ? $key : $lname; |
|
261
|
|
|
if ($un_lang) |
|
262
|
|
|
{ |
|
263
|
|
|
$langs[$lname] = '$$'.$key.'$$'; |
|
264
|
|
|
} |
|
265
|
|
|
else |
|
266
|
|
|
{ |
|
267
|
|
|
$langs[$key] = '$$'.$lname.'$$'; |
|
268
|
|
|
} |
|
269
|
|
|
} |
|
270
|
|
|
return $this->parse_notify($msg,$langs,False); |
|
|
|
|
|
|
271
|
|
|
} |
|
272
|
|
|
|
|
273
|
|
|
/** |
|
274
|
|
|
* define some standard substitues-values and use them on the prefs, if needed |
|
275
|
|
|
*/ |
|
276
|
|
|
function standard_substitutes() |
|
277
|
|
|
{ |
|
278
|
|
|
if ($this->debug) error_log(__METHOD__." is called "); |
|
|
|
|
|
|
279
|
|
|
if (!is_array(@$GLOBALS['egw_info']['user']['preferences'])) |
|
280
|
|
|
{ |
|
281
|
|
|
$GLOBALS['egw_info']['user']['preferences'] = $this->data; // else no lang() |
|
282
|
|
|
} |
|
283
|
|
|
// we cant use egw_info/user/fullname, as it's not set when we run |
|
284
|
|
|
$this->values = array( // standard notify replacements |
|
285
|
|
|
'fullname' => Accounts::id2name($this->account_id, 'account_fullname'), |
|
286
|
|
|
'firstname' => Accounts::id2name($this->account_id, 'account_firstname'), |
|
287
|
|
|
'lastname' => Accounts::id2name($this->account_id, 'account_lastname'), |
|
288
|
|
|
'domain' => $GLOBALS['egw_info']['server']['mail_suffix'], |
|
289
|
|
|
'email' => $this->email_address($this->account_id), |
|
290
|
|
|
'date' => DateTime::to('now',$GLOBALS['egw_info']['user']['preferences']['common']['dateformat']), |
|
291
|
|
|
); |
|
292
|
|
|
// do this first, as it might be already contain some substitues |
|
293
|
|
|
// |
|
294
|
|
|
$this->values['email'] = $this->parse_notify($this->values['email']); |
|
295
|
|
|
|
|
296
|
|
|
$this->vars = array( // langs have to be in common !!! |
|
297
|
|
|
'fullname' => lang('name of the user, eg. "%1"',$this->values['fullname']), |
|
|
|
|
|
|
298
|
|
|
'firstname' => lang('first name of the user, eg. "%1"',$this->values['firstname']), |
|
299
|
|
|
'lastname' => lang('last name of the user, eg. "%1"',$this->values['lastname']), |
|
300
|
|
|
'domain' => lang('domain name for mail-address, eg. "%1"',$this->values['domain']), |
|
301
|
|
|
'email' => lang('email-address of the user, eg. "%1"',$this->values['email']), |
|
302
|
|
|
'date' => lang('todays date, eg. "%1"',$this->values['date']), |
|
303
|
|
|
); |
|
304
|
|
|
if ($this->debug) error_log(__METHOD__.print_r($this->vars,true)); |
|
305
|
|
|
// do the substituetion in the effective prefs (data) |
|
306
|
|
|
// |
|
307
|
|
|
foreach($this->data as $app => $data) |
|
308
|
|
|
{ |
|
309
|
|
|
if(!is_array($data)) continue; |
|
310
|
|
|
foreach($data as $key => $val) |
|
311
|
|
|
{ |
|
312
|
|
|
if (!is_array($val) && strpos($val,'$$') !== False) |
|
313
|
|
|
{ |
|
314
|
|
|
$this->data[$app][$key] = $this->parse_notify($val); |
|
315
|
|
|
} |
|
316
|
|
|
elseif (is_array($val)) |
|
317
|
|
|
{ |
|
318
|
|
|
foreach($val as $k => $v) |
|
319
|
|
|
{ |
|
320
|
|
|
if (!is_array($v) && strpos($v,'$$') !== False) |
|
321
|
|
|
{ |
|
322
|
|
|
$this->data[$app][$key][$k] = $this->parse_notify($v); |
|
323
|
|
|
} |
|
324
|
|
|
} |
|
325
|
|
|
} |
|
326
|
|
|
} |
|
327
|
|
|
} |
|
328
|
|
|
} |
|
329
|
|
|
|
|
330
|
|
|
/** |
|
331
|
|
|
* Unserialize data from either json_encode or PHP serialize and addslashes |
|
332
|
|
|
* |
|
333
|
|
|
* @param string $str serialized prefs |
|
334
|
|
|
* @return array |
|
335
|
|
|
*/ |
|
336
|
|
|
protected static function unserialize($str) |
|
337
|
|
|
{ |
|
338
|
|
|
// handling of new json-encoded prefs |
|
339
|
|
|
if ($str[0] != 'a' && $str[1] != ':') |
|
340
|
|
|
{ |
|
341
|
|
|
return json_decode($str, true); |
|
342
|
|
|
} |
|
343
|
|
|
// handling of old PHP serialized and addslashed prefs |
|
344
|
|
|
$data = php_safe_unserialize($str); |
|
345
|
|
|
if($data === false) |
|
346
|
|
|
{ |
|
347
|
|
|
// manually retrieve the string lengths of the serialized array if unserialize failed |
|
348
|
|
|
$data = php_safe_unserialize(preg_replace_callback('!s:(\d+):"(.*?)";!s', function($matches) |
|
349
|
|
|
{ |
|
350
|
|
|
return 's:'.mb_strlen($matches[2],'8bit').':"'.$matches[2].'";'; |
|
351
|
|
|
}, $str)); |
|
352
|
|
|
} |
|
353
|
|
|
self::unquote($data); |
|
354
|
|
|
return $data; |
|
355
|
|
|
} |
|
356
|
|
|
|
|
357
|
|
|
/** |
|
358
|
|
|
* unquote (stripslashes) recursivly the whole array |
|
359
|
|
|
* |
|
360
|
|
|
* @param array &$arr array to unquote (var-param!) |
|
361
|
|
|
*/ |
|
362
|
|
|
protected static function unquote(&$arr) |
|
363
|
|
|
{ |
|
364
|
|
|
if (!is_array($arr)) |
|
|
|
|
|
|
365
|
|
|
{ |
|
366
|
|
|
$arr = stripslashes($arr); |
|
367
|
|
|
return; |
|
368
|
|
|
} |
|
369
|
|
|
foreach($arr as $key => $value) |
|
370
|
|
|
{ |
|
371
|
|
|
if (is_array($value)) |
|
372
|
|
|
{ |
|
373
|
|
|
self::unquote($arr[$key]); |
|
374
|
|
|
} |
|
375
|
|
|
else |
|
376
|
|
|
{ |
|
377
|
|
|
$arr[$key] = stripslashes($value); |
|
378
|
|
|
} |
|
379
|
|
|
} |
|
380
|
|
|
} |
|
381
|
|
|
|
|
382
|
|
|
/** |
|
383
|
|
|
* read preferences from the repository |
|
384
|
|
|
* |
|
385
|
|
|
* the function ready all 3 prefs user/default/forced and merges them to the effective ones |
|
386
|
|
|
* |
|
387
|
|
|
* @param boolean $use_session =true should the session prefs get used (default true) or not (false) |
|
388
|
|
|
* @return array with effective prefs ($this->data) |
|
389
|
|
|
*/ |
|
390
|
|
|
function read_repository($use_session=true) |
|
391
|
|
|
{ |
|
392
|
|
|
$this->session = $use_session ? Cache::getSession('preferences','preferences') : array(); |
|
393
|
|
|
if (!is_array($this->session)) |
|
394
|
|
|
{ |
|
395
|
|
|
$this->session = array(); |
|
396
|
|
|
} |
|
397
|
|
|
$this->forced = $this->default = $this->user = $this->group = array(); |
|
398
|
|
|
$to_read = array(self::DEFAULT_ID,self::FORCED_ID,$this->account_id); |
|
399
|
|
|
if ($this->account_id > 0) |
|
400
|
|
|
{ |
|
401
|
|
|
$primary_group = Accounts::id2name($this->account_id, 'account_primary_group'); |
|
402
|
|
|
foreach((array)$GLOBALS['egw']->accounts->memberships($this->account_id, true) as $gid) |
|
403
|
|
|
{ |
|
404
|
|
|
if ($gid != $primary_group) $to_read[] = $gid + self::DEFAULT_ID; // need to offset it with DEFAULT_ID = -2! |
|
405
|
|
|
} |
|
406
|
|
|
$to_read[] = $primary_group + self::DEFAULT_ID; |
|
407
|
|
|
} |
|
408
|
|
|
foreach($this->cache_read($to_read) as $id => $values) |
|
409
|
|
|
{ |
|
410
|
|
|
switch($id) |
|
411
|
|
|
{ |
|
412
|
|
|
case self::FORCED_ID: |
|
413
|
|
|
$this->forced = $values; |
|
414
|
|
|
break; |
|
415
|
|
|
case self::DEFAULT_ID: |
|
416
|
|
|
$this->default = $values; |
|
417
|
|
|
break; |
|
418
|
|
|
case $this->account_id: // user |
|
419
|
|
|
$this->user = $values; |
|
420
|
|
|
break; |
|
421
|
|
|
default: |
|
422
|
|
|
foreach($values as $app => $vals) |
|
423
|
|
|
{ |
|
424
|
|
|
$this->group[$app] = (array)$vals + (array)$this->group[$app]; |
|
425
|
|
|
} |
|
426
|
|
|
break; |
|
427
|
|
|
} |
|
428
|
|
|
} |
|
429
|
|
|
$this->data = $this->user; |
|
430
|
|
|
|
|
431
|
|
|
// let the (temp.) session prefs. override the user prefs. |
|
432
|
|
|
// |
|
433
|
|
|
foreach($this->session as $app => $values) |
|
434
|
|
|
{ |
|
435
|
|
|
foreach($values as $var => $value) |
|
436
|
|
|
{ |
|
437
|
|
|
$this->data[$app][$var] = $value; |
|
438
|
|
|
} |
|
439
|
|
|
} |
|
440
|
|
|
|
|
441
|
|
|
// now use (primary) group defaults if needed (user-value unset or empty) |
|
442
|
|
|
// |
|
443
|
|
|
foreach((array)$this->group as $app => $values) |
|
444
|
|
|
{ |
|
445
|
|
|
foreach((array)$values as $var => $value) |
|
446
|
|
|
{ |
|
447
|
|
|
if (!isset($this->data[$app][$var]) || $this->data[$app][$var] === '') |
|
448
|
|
|
{ |
|
449
|
|
|
$this->data[$app][$var] = $value; |
|
450
|
|
|
} |
|
451
|
|
|
} |
|
452
|
|
|
} |
|
453
|
|
|
// now use defaults if needed (user-value unset or empty) |
|
454
|
|
|
// |
|
455
|
|
|
foreach((array)$this->default as $app => $values) |
|
456
|
|
|
{ |
|
457
|
|
|
foreach((array)$values as $var => $value) |
|
458
|
|
|
{ |
|
459
|
|
|
if (!isset($this->data[$app][$var]) || $this->data[$app][$var] === '') |
|
460
|
|
|
{ |
|
461
|
|
|
//if ($var=='remote_application_url') error_log(__METHOD__.__LINE__.' default for '.$var.' with '.$value); |
|
462
|
|
|
$this->data[$app][$var] = $value; |
|
463
|
|
|
} |
|
464
|
|
|
} |
|
465
|
|
|
} |
|
466
|
|
|
// now set/force forced values |
|
467
|
|
|
// |
|
468
|
|
|
foreach((array)$this->forced as $app => $values) |
|
469
|
|
|
{ |
|
470
|
|
|
foreach((array)$values as $var => $value) |
|
471
|
|
|
{ |
|
472
|
|
|
$this->data[$app][$var] = $value; |
|
473
|
|
|
} |
|
474
|
|
|
} |
|
475
|
|
|
// setup the standard substitutes and substitutes the data in $this->data |
|
476
|
|
|
// |
|
477
|
|
|
if ($GLOBALS['egw_info']['flags']['load_translations'] !== false) |
|
478
|
|
|
{ |
|
479
|
|
|
$this->standard_substitutes(); |
|
480
|
|
|
} |
|
481
|
|
|
// This is to supress warnings during login |
|
482
|
|
|
if (is_array($this->data)) |
|
483
|
|
|
{ |
|
484
|
|
|
reset($this->data); |
|
485
|
|
|
} |
|
486
|
|
|
if (isset($this->debug) && substr($GLOBALS['egw_info']['flags']['currentapp'],0,3) != 'log') |
|
487
|
|
|
{ |
|
488
|
|
|
echo 'user<pre>'; print_r($this->user); echo "</pre>\n"; |
|
489
|
|
|
echo 'forced<pre>'; print_r($this->forced); echo "</pre>\n"; |
|
490
|
|
|
echo 'default<pre>'; print_r($this->default); echo "</pre>\n"; |
|
491
|
|
|
echo 'group<pre>'; print_r($this->group); echo "</pre>\n"; |
|
492
|
|
|
echo 'effectiv<pre>'; print_r($this->data); echo "</pre>\n"; |
|
493
|
|
|
} |
|
494
|
|
|
$this->check_set_tz_offset(); |
|
495
|
|
|
|
|
496
|
|
|
return $this->data; |
|
497
|
|
|
} |
|
498
|
|
|
|
|
499
|
|
|
/** |
|
500
|
|
|
* Get default preferences (also taking forced preferences into account!) |
|
501
|
|
|
* |
|
502
|
|
|
* @param string $app =null |
|
503
|
|
|
* @param string $name =null |
|
504
|
|
|
* @return mixed |
|
505
|
|
|
*/ |
|
506
|
|
|
function default_prefs($app=null,$name=null) |
|
507
|
|
|
{ |
|
508
|
|
|
// Etemplate::complete_array_merge() is identical to PHP >= 5.3 array_replace_recursive() |
|
509
|
|
|
$default = Etemplate::complete_array_merge($this->default, $this->forced); |
|
510
|
|
|
|
|
511
|
|
|
if ($app) $default = $default[$app]; |
|
512
|
|
|
|
|
513
|
|
|
if ($name && is_array($default)) $default = $default[$name]; |
|
514
|
|
|
|
|
515
|
|
|
return $default; |
|
516
|
|
|
} |
|
517
|
|
|
|
|
518
|
|
|
/** |
|
519
|
|
|
* Checking new timezone ('tz') pref and setting old tz_offset pref from it |
|
520
|
|
|
* |
|
521
|
|
|
*/ |
|
522
|
|
|
function check_set_tz_offset() |
|
523
|
|
|
{ |
|
524
|
|
|
$prefs =& $this->data['common']; |
|
525
|
|
|
|
|
526
|
|
|
if (!empty($prefs['tz'])) |
|
527
|
|
|
{ |
|
528
|
|
|
DateTime::setUserPrefs($prefs['tz'],$prefs['dateformat'],$prefs['timeformat']); |
|
529
|
|
|
// set the old preference for compatibilty with old code |
|
530
|
|
|
$prefs['tz_offset'] = DateTime::tz_offset_s()/3600; |
|
531
|
|
|
} |
|
532
|
|
|
} |
|
533
|
|
|
|
|
534
|
|
|
/** |
|
535
|
|
|
* Set user timezone, if we get restored from session |
|
536
|
|
|
* |
|
537
|
|
|
*/ |
|
538
|
|
|
function __wakeup() |
|
539
|
|
|
{ |
|
540
|
|
|
$this->check_set_tz_offset(); |
|
541
|
|
|
} |
|
542
|
|
|
|
|
543
|
|
|
/** |
|
544
|
|
|
* read preferences from repository and stores in an array |
|
545
|
|
|
* |
|
546
|
|
|
* @return array containing the effective user preferences |
|
547
|
|
|
*/ |
|
548
|
|
|
function read() |
|
549
|
|
|
{ |
|
550
|
|
|
if (count($this->data) == 0) |
|
551
|
|
|
{ |
|
552
|
|
|
$this->read_repository(); |
|
553
|
|
|
} |
|
554
|
|
|
reset ($this->data); |
|
555
|
|
|
return $this->data; |
|
556
|
|
|
} |
|
557
|
|
|
|
|
558
|
|
|
/** |
|
559
|
|
|
* add preference to $app_name a particular app |
|
560
|
|
|
* |
|
561
|
|
|
* the effective prefs ($this->data) are updated to reflect the change |
|
562
|
|
|
* |
|
563
|
|
|
* @param string $app_name name of the app |
|
564
|
|
|
* @param string $var name of preference to be stored |
|
565
|
|
|
* @param mixed $value ='##undef##' value of the preference, if not given $GLOBALS[$var] is used |
|
566
|
|
|
* @param string $type ='user' of preference to set: forced, default, user |
|
567
|
|
|
* @return array with new effective prefs (even when forced or default prefs are set !) |
|
568
|
|
|
*/ |
|
569
|
|
|
function add($app_name,$var,$value = '##undef##',$type='user') |
|
570
|
|
|
{ |
|
571
|
|
|
//echo "<p>add('$app_name','$var','$value')</p>\n"; |
|
572
|
|
|
if ($value === '##undef##') |
|
573
|
|
|
{ |
|
574
|
|
|
$value = $GLOBALS[$var]; |
|
575
|
|
|
} |
|
576
|
|
|
|
|
577
|
|
|
switch ($type) |
|
578
|
|
|
{ |
|
579
|
|
|
case 'session': |
|
580
|
|
|
if (!isset($this->forced[$app_name][$var]) || $this->forced[$app_name][$var] === '') |
|
581
|
|
|
{ |
|
582
|
|
|
$this->session[$app_name][$var] = $this->data[$app_name][$var] = $value; |
|
583
|
|
|
Cache::setSession('preferences','preferences',$this->session); |
|
584
|
|
|
if (method_exists($GLOBALS['egw'],'invalidate_session_cache')) // egw object in setup is limited |
|
585
|
|
|
{ |
|
586
|
|
|
$GLOBALS['egw']->invalidate_session_cache(); // in case with cache the egw_info array in the session |
|
587
|
|
|
} |
|
588
|
|
|
} |
|
589
|
|
|
break; |
|
590
|
|
|
|
|
591
|
|
|
case 'forced': |
|
592
|
|
|
$this->data[$app_name][$var] = $this->forced[$app_name][$var] = $value; |
|
593
|
|
|
break; |
|
594
|
|
|
|
|
595
|
|
|
case 'default': |
|
596
|
|
|
$this->default[$app_name][$var] = $value; |
|
597
|
|
|
if ((!isset($this->forced[$app_name][$var]) || $this->forced[$app_name][$var] === '') && |
|
598
|
|
|
(!isset($this->user[$app_name][$var]) || $this->user[$app_name][$var] === '')) |
|
599
|
|
|
{ |
|
600
|
|
|
$this->data[$app_name][$var] = $value; |
|
601
|
|
|
} |
|
602
|
|
|
break; |
|
603
|
|
|
|
|
604
|
|
|
case 'user': |
|
605
|
|
|
default: |
|
606
|
|
|
$this->user[$app_name][$var] = $value; |
|
607
|
|
|
if (!isset($this->forced[$app_name][$var]) || $this->forced[$app_name][$var] === '') |
|
608
|
|
|
{ |
|
609
|
|
|
$this->data[$app_name][$var] = $value; |
|
610
|
|
|
} |
|
611
|
|
|
break; |
|
612
|
|
|
} |
|
613
|
|
|
reset($this->data); |
|
614
|
|
|
return $this->data; |
|
615
|
|
|
} |
|
616
|
|
|
|
|
617
|
|
|
/** |
|
618
|
|
|
* delete preference from $app_name |
|
619
|
|
|
* |
|
620
|
|
|
* the effektive prefs ($this->data) are updated to reflect the change |
|
621
|
|
|
* |
|
622
|
|
|
* @param string $app_name name of app |
|
623
|
|
|
* @param string $var =false variable to be deleted |
|
624
|
|
|
* @param string $type ='user' of preference to set: forced, default, user |
|
625
|
|
|
* @return array with new effective prefs (even when forced or default prefs are deleted!) |
|
626
|
|
|
*/ |
|
627
|
|
|
function delete($app_name, $var = False,$type = 'user') |
|
628
|
|
|
{ |
|
629
|
|
|
//echo "<p>delete('$app_name','$var','$type')</p>\n"; |
|
630
|
|
|
$set_via = array( |
|
631
|
|
|
'forced' => array('user','default'), |
|
632
|
|
|
'default' => array('forced','user'), |
|
633
|
|
|
'user' => array('forced','group','default'), |
|
634
|
|
|
'group' => array('forced'), |
|
635
|
|
|
); |
|
636
|
|
|
if (!isset($set_via[$type])) |
|
637
|
|
|
{ |
|
638
|
|
|
$type = 'user'; |
|
639
|
|
|
} |
|
640
|
|
|
$pref = &$this->$type; |
|
641
|
|
|
|
|
642
|
|
|
if (($all = empty($var))) // to check if $var is regarded as empty (false, 0, '', null, array() should do the trick |
|
643
|
|
|
{ |
|
644
|
|
|
unset($pref[$app_name]); |
|
645
|
|
|
unset($this->data[$app_name]); |
|
646
|
|
|
} |
|
647
|
|
|
else |
|
648
|
|
|
{ |
|
649
|
|
|
unset($pref[$app_name][$var]); |
|
650
|
|
|
unset($this->data[$app_name][$var]); |
|
651
|
|
|
} |
|
652
|
|
|
// set the effectiv pref again if needed |
|
653
|
|
|
// |
|
654
|
|
|
foreach ($set_via[$type] as $set_from) |
|
655
|
|
|
{ |
|
656
|
|
|
$arr = &$this->$set_from; |
|
657
|
|
|
if ($all) |
|
658
|
|
|
{ |
|
659
|
|
|
if (isset($arr[$app_name])) |
|
660
|
|
|
{ |
|
661
|
|
|
$this->data[$app_name] = $arr[$app_name]; |
|
662
|
|
|
break; |
|
663
|
|
|
} |
|
664
|
|
|
} |
|
665
|
|
|
else |
|
666
|
|
|
{ |
|
667
|
|
|
if($var && @isset($arr[$app_name][$var]) && $arr[$app_name][$var] !== '') |
|
668
|
|
|
{ |
|
669
|
|
|
$this->data[$app_name][$var] = $arr[$app_name][$var]; |
|
670
|
|
|
break; |
|
671
|
|
|
} |
|
672
|
|
|
} |
|
673
|
|
|
unset($arr); |
|
674
|
|
|
} |
|
675
|
|
|
reset ($this->data); |
|
676
|
|
|
return $this->data; |
|
677
|
|
|
} |
|
678
|
|
|
|
|
679
|
|
|
/** |
|
680
|
|
|
* delete all prefs of a given user |
|
681
|
|
|
* |
|
682
|
|
|
* @param int $accountid |
|
683
|
|
|
*/ |
|
684
|
|
|
function delete_user($accountid) |
|
685
|
|
|
{ |
|
686
|
|
|
if ($accountid > 0) |
|
687
|
|
|
{ |
|
688
|
|
|
$this->db->delete($this->table,array('preference_owner' => $accountid),__LINE__,__FILE__); |
|
689
|
|
|
|
|
690
|
|
|
Cache::unsetInstance(__CLASS__, $accountid); |
|
691
|
|
|
} |
|
692
|
|
|
} |
|
693
|
|
|
|
|
694
|
|
|
/** |
|
695
|
|
|
* delete all prefs of a given group |
|
696
|
|
|
* |
|
697
|
|
|
* @param int $accountid |
|
698
|
|
|
*/ |
|
699
|
|
|
function delete_group($accountid) |
|
700
|
|
|
{ |
|
701
|
|
|
if ($accountid < 0) |
|
702
|
|
|
{ |
|
703
|
|
|
$this->db->delete($this->table,array('preference_owner' => $accountid+self::DEFAULT_ID),__LINE__,__FILE__); |
|
704
|
|
|
|
|
705
|
|
|
Cache::unsetInstance(__CLASS__, $accountid+self::DEFAULT_ID); |
|
706
|
|
|
} |
|
707
|
|
|
} |
|
708
|
|
|
|
|
709
|
|
|
/** |
|
710
|
|
|
* Change single value in preferences of all users (incl. groups, default and forced) |
|
711
|
|
|
* |
|
712
|
|
|
* @param string $app app-name or null for all apps |
|
713
|
|
|
* @param string $name attribute name or regular expression (enclosed in /) to match attribute-name eg. '/^favorite_/' |
|
714
|
|
|
* @param string|callable $value new value to set, or null or '' to delete it or callable returning new value: function($attr, $old_value, $owner, $prefs) |
|
715
|
|
|
* @param string $old_value if given, only change if that's current value |
|
716
|
|
|
* @param string $type if given limit to "user", "forced", "default", "group" |
|
717
|
|
|
*/ |
|
718
|
|
|
public static function change_preference($app, $name, $value, $old_value=null, $type=null) |
|
719
|
|
|
{ |
|
720
|
|
|
$db = isset($GLOBALS['egw_setup']->db) ? $GLOBALS['egw_setup']->db : $GLOBALS['egw']->db; |
|
721
|
|
|
|
|
722
|
|
|
$where = array(); |
|
723
|
|
|
if ($app) $where['preference_app'] = $app; |
|
724
|
|
|
|
|
725
|
|
|
switch($type) |
|
726
|
|
|
{ |
|
727
|
|
|
case 'forced': |
|
728
|
|
|
$where['preference_owner'] = self::FORCED_ID; |
|
729
|
|
|
break; |
|
730
|
|
|
case 'default': |
|
731
|
|
|
$where['preference_owner'] = self::DEFAULT_ID; |
|
732
|
|
|
break; |
|
733
|
|
|
case 'user': |
|
734
|
|
|
$where[] = 'preference_owner > 0'; |
|
735
|
|
|
break; |
|
736
|
|
|
case 'group': |
|
737
|
|
|
$where[] = 'preference_owner < '.self::DEFAULT_ID; |
|
738
|
|
|
break; |
|
739
|
|
|
} |
|
740
|
|
|
foreach($db->select(self::TABLE, '*', $where, __LINE__, __FILE__) as $row) |
|
741
|
|
|
{ |
|
742
|
|
|
$prefs = self::unserialize($row['preference_value']); |
|
743
|
|
|
if (!is_array($prefs)) $prefs = array(); // would stall update otherwise |
|
744
|
|
|
|
|
745
|
|
|
if ($name[0] == '/' && substr($name, -1) == '/') |
|
746
|
|
|
{ |
|
747
|
|
|
$attrs = array_filter(array_keys($prefs), function($n) use ($name) |
|
748
|
|
|
{ |
|
749
|
|
|
return preg_match($name, $n); |
|
750
|
|
|
}); |
|
751
|
|
|
} |
|
752
|
|
|
else |
|
753
|
|
|
{ |
|
754
|
|
|
$attrs = array($name); |
|
755
|
|
|
} |
|
756
|
|
|
|
|
757
|
|
|
$updated = false; |
|
758
|
|
|
foreach($attrs as $attr) |
|
759
|
|
|
{ |
|
760
|
|
|
if (isset($old_value) && $prefs[$attr] != $old_value) continue; |
|
761
|
|
|
|
|
762
|
|
|
$val = is_callable($value) ? call_user_func($value, $attr, $prefs[$attr], $row['preference_owner'], $prefs) : $value; |
|
763
|
|
|
if ($val === $prefs[$attr]) continue; |
|
764
|
|
|
|
|
765
|
|
|
$updated = true; |
|
766
|
|
|
if ((string)$val !== '') |
|
767
|
|
|
{ |
|
768
|
|
|
$prefs[$attr] = $val; |
|
769
|
|
|
} |
|
770
|
|
|
else |
|
771
|
|
|
{ |
|
772
|
|
|
unset($prefs[$attr]); |
|
773
|
|
|
} |
|
774
|
|
|
} |
|
775
|
|
|
// if somethings changed or old row was php-serialized --> store it again json-encoded |
|
776
|
|
|
if ($updated || $row['preference_value'][0] == 'a' && $row['preference_value'][1] == ':') |
|
777
|
|
|
{ |
|
778
|
|
|
$db->update(self::TABLE, array( |
|
779
|
|
|
'preference_value' => json_encode($prefs), |
|
780
|
|
|
), array( |
|
781
|
|
|
'preference_owner' => $row['preference_owner'], |
|
782
|
|
|
'preference_app' => $row['preference_app'], |
|
783
|
|
|
), __LINE__, __FILE__); |
|
784
|
|
|
|
|
785
|
|
|
// update instance-wide cache |
|
786
|
|
|
$cached = Cache::getInstance(__CLASS__, $row['preference_owner']); |
|
787
|
|
|
if($cached && $cached[$row['preference_app']]) |
|
788
|
|
|
{ |
|
789
|
|
|
$cached[$row['preference_app']] = $prefs; |
|
790
|
|
|
Cache::setInstance(__CLASS__, $row['preference_owner'], $cached); |
|
791
|
|
|
} |
|
792
|
|
|
} |
|
793
|
|
|
} |
|
794
|
|
|
} |
|
795
|
|
|
|
|
796
|
|
|
/** |
|
797
|
|
|
* Completely delete the specified preference name from all users |
|
798
|
|
|
* |
|
799
|
|
|
* @param string $app Application name |
|
800
|
|
|
* @param string $name Preference name |
|
801
|
|
|
* @param string $type ='user' of preference to set: forced, default, user |
|
802
|
|
|
*/ |
|
803
|
|
|
public static function delete_preference($app, $name, $type='user') |
|
804
|
|
|
{ |
|
805
|
|
|
self::change_preference($app, $name, null, null, $type); |
|
806
|
|
|
} |
|
807
|
|
|
|
|
808
|
|
|
/** |
|
809
|
|
|
* Copy preferences from one app to an other |
|
810
|
|
|
* |
|
811
|
|
|
* @param string $from_app |
|
812
|
|
|
* @param string $to_app |
|
813
|
|
|
* @param array $names =null array of names to copy or null for all |
|
814
|
|
|
*/ |
|
815
|
|
|
public static function copy_preferences($from_app, $to_app, array $names=null) |
|
816
|
|
|
{ |
|
817
|
|
|
//error_log(__METHOD__."('$from_app', '$to_app', ".array2string($names).')'); |
|
818
|
|
|
$db = isset($GLOBALS['egw_setup']->db) ? $GLOBALS['egw_setup']->db : $GLOBALS['egw']->db; |
|
819
|
|
|
|
|
820
|
|
|
foreach($db->select(self::TABLE, '*', array('preference_app' => $from_app), __LINE__, __FILE__) as $row) |
|
821
|
|
|
{ |
|
822
|
|
|
$prefs = self::unserialize($row['preference_value']); |
|
823
|
|
|
|
|
824
|
|
|
if ($names) |
|
825
|
|
|
{ |
|
826
|
|
|
$prefs = array_intersect_key($prefs, array_flip($names)); |
|
827
|
|
|
} |
|
828
|
|
|
if (!$prefs) continue; // nothing to change, as nothing set |
|
|
|
|
|
|
829
|
|
|
|
|
830
|
|
|
$row['preference_app'] = $to_app; |
|
831
|
|
|
unset($row['preference_value']); |
|
832
|
|
|
|
|
833
|
|
|
if (($values = $db->select(self::TABLE, 'preference_value', $row, __LINE__, __FILE__)->fetchColumn())) |
|
834
|
|
|
{ |
|
835
|
|
|
$prefs = array_merge(self::unserialize($values), $prefs); |
|
836
|
|
|
} |
|
837
|
|
|
unset($row['preference_id']); |
|
838
|
|
|
//error_log(__LINE__.': '.__METHOD__."() inserting app=$row[preference_app], owner=$row[preference_owner]: ".array2string($prefs)); |
|
839
|
|
|
$db->insert(self::TABLE, array( |
|
840
|
|
|
'preference_value' => json_encode($prefs) |
|
841
|
|
|
), $row, __LINE__, __FILE__); |
|
842
|
|
|
|
|
843
|
|
|
// update instance-wide cache |
|
844
|
|
|
if (($cached = Cache::getInstance(__CLASS__, $row['prefences_owner']))) |
|
845
|
|
|
{ |
|
846
|
|
|
$cached[$from_app] = $prefs; |
|
847
|
|
|
Cache::setInstance(__CLASS__, $row['preference_owner'], $cached); |
|
848
|
|
|
} |
|
849
|
|
|
} |
|
850
|
|
|
} |
|
851
|
|
|
|
|
852
|
|
|
/** |
|
853
|
|
|
* Save the the preferences to the repository |
|
854
|
|
|
* |
|
855
|
|
|
* User prefs for saveing are in $this->user not in $this->data, which are the effectiv prefs only! |
|
856
|
|
|
* |
|
857
|
|
|
* @param boolean $update_session_info =false old param, seems not to be used (not used anymore) |
|
858
|
|
|
* @param string $type ='user' which prefs to update: user/default/forced |
|
859
|
|
|
* @param boolean $invalid_cache =true should we invalidate the cache, default true (not used anymore) |
|
860
|
|
|
* @return array with new effective prefs (even when forced or default prefs are deleted!) |
|
861
|
|
|
*/ |
|
862
|
|
|
function save_repository($update_session_info = False,$type='user',$invalid_cache=true) |
|
863
|
|
|
{ |
|
864
|
|
|
unset($update_session_info, $invalid_cache); // no longer used |
|
865
|
|
|
|
|
866
|
|
|
switch($type) |
|
867
|
|
|
{ |
|
868
|
|
|
case 'forced': |
|
869
|
|
|
$account_id = self::FORCED_ID; |
|
870
|
|
|
$prefs = &$this->forced; |
|
871
|
|
|
break; |
|
872
|
|
|
case 'default': |
|
873
|
|
|
$account_id = self::DEFAULT_ID; |
|
874
|
|
|
$prefs = &$this->default; |
|
875
|
|
|
break; |
|
876
|
|
|
case 'group': |
|
877
|
|
|
throw new Exception\WrongParameter("Can NOT save group preferences, as they are from multiple groups!"); |
|
878
|
|
|
|
|
879
|
|
|
default: |
|
880
|
|
|
$account_id = (int)$this->account_id; |
|
881
|
|
|
$prefs = &$this->user; // we use the user-array as data contains default values too |
|
882
|
|
|
break; |
|
883
|
|
|
} |
|
884
|
|
|
//echo "<p>preferences::save_repository(,$type): account_id=$account_id, prefs="; print_r($prefs); echo "</p>\n"; |
|
885
|
|
|
|
|
886
|
|
|
if (isset($GLOBALS['egw_setup']) || !$GLOBALS['egw']->acl->check('session_only_preferences',1,'preferences') && |
|
887
|
|
|
(!($old_prefs = $this->cache_read($account_id)) || $old_prefs != $prefs)) |
|
888
|
|
|
{ |
|
889
|
|
|
//error_log(__METHOD__."(type=$type) saved, because old_prefs[$account_id] != prefs=".array2string($prefs)); |
|
890
|
|
|
$changed = 0; |
|
891
|
|
|
foreach($prefs as $app => $value) |
|
892
|
|
|
{ |
|
893
|
|
|
// check if app preferences have changed, if not no need to save them |
|
894
|
|
|
if ($old_prefs && $old_prefs[$app] == $value) continue; |
|
895
|
|
|
|
|
896
|
|
|
if (!$changed++) $this->db->transaction_begin(); |
|
897
|
|
|
|
|
898
|
|
|
if (!is_array($value) || !$value) |
|
|
|
|
|
|
899
|
|
|
{ |
|
900
|
|
|
$this->db->delete($this->table, array( |
|
901
|
|
|
'preference_owner' => $account_id, |
|
902
|
|
|
'preference_app' => $app, |
|
903
|
|
|
), __LINE__, __FILE__); |
|
904
|
|
|
unset($prefs[$app]); |
|
905
|
|
|
} |
|
906
|
|
|
else |
|
907
|
|
|
{ |
|
908
|
|
|
$this->db->insert($this->table,array( |
|
909
|
|
|
'preference_value' => json_encode($value), |
|
910
|
|
|
),array( |
|
911
|
|
|
'preference_owner' => $account_id, |
|
912
|
|
|
'preference_app' => $app, |
|
913
|
|
|
),__LINE__,__FILE__); |
|
914
|
|
|
} |
|
915
|
|
|
} |
|
916
|
|
|
if ($changed) |
|
917
|
|
|
{ |
|
918
|
|
|
$this->db->transaction_commit(); |
|
919
|
|
|
|
|
920
|
|
|
// update instance-wide cache |
|
921
|
|
|
Cache::setInstance(__CLASS__, $account_id, $prefs); |
|
922
|
|
|
} |
|
923
|
|
|
} |
|
924
|
|
|
//else error_log(__METHOD__."(type=$type) NOT saved because old_prefs[$account_id] == prefs=".array2string($prefs)); |
|
925
|
|
|
return $this->data; |
|
926
|
|
|
} |
|
927
|
|
|
|
|
928
|
|
|
/** |
|
929
|
|
|
* returns the custom email-address (if set) or generates a default one |
|
930
|
|
|
* |
|
931
|
|
|
* This will generate the appropriate email address used as the "From:" |
|
932
|
|
|
* email address when the user sends email, the localpert * part. The "personal" |
|
933
|
|
|
* part is generated elsewhere. |
|
934
|
|
|
* In the absence of a custom ['email']['address'], this function should be used to set it. |
|
935
|
|
|
* |
|
936
|
|
|
* @access public |
|
937
|
|
|
* @param int $account_id as determined in and/or passed to "create_email_preferences" |
|
938
|
|
|
* @return string with email-address |
|
939
|
|
|
*/ |
|
940
|
|
|
function email_address($account_id='') |
|
941
|
|
|
{ |
|
942
|
|
|
if (isset($this->data['email']['address'])) |
|
943
|
|
|
{ |
|
944
|
|
|
return $this->data['email']['address']; |
|
945
|
|
|
} |
|
946
|
|
|
// if email-address is set in the account, return it |
|
947
|
|
|
if (($email = Accounts::id2name($account_id,'account_email'))) |
|
948
|
|
|
{ |
|
949
|
|
|
return $email; |
|
950
|
|
|
} |
|
951
|
|
|
$prefs_email_address = Accounts::id2name($account_id); |
|
952
|
|
|
if ($prefs_email_address && strpos($prefs_email_address,'@') === False) |
|
953
|
|
|
{ |
|
954
|
|
|
$prefs_email_address .= '@' . $GLOBALS['egw_info']['server']['mail_suffix']; |
|
955
|
|
|
} |
|
956
|
|
|
return $prefs_email_address; |
|
957
|
|
|
} |
|
958
|
|
|
|
|
959
|
|
|
/** |
|
960
|
|
|
* Try to guess and set a locale supported by the server, with fallback to 'en_EN' and 'C' |
|
961
|
|
|
* |
|
962
|
|
|
* This method uses the language and nationalty set in the users common prefs. |
|
963
|
|
|
* |
|
964
|
|
|
* @param $category =LC_MESSAGES category to set, see setlocal function |
|
|
|
|
|
|
965
|
|
|
* @param $charset =null default system charset |
|
966
|
|
|
* @return string the local (or best estimate) set |
|
967
|
|
|
*/ |
|
968
|
|
|
static function setlocale($category=LC_MESSAGES,$charset=null) |
|
969
|
|
|
{ |
|
970
|
|
|
$lang = $GLOBALS['egw_info']['user']['preferences']['common']['lang']; |
|
971
|
|
|
$country = $GLOBALS['egw_info']['user']['preferences']['common']['country']; |
|
972
|
|
|
|
|
973
|
|
|
if (strlen($lang) == 2) |
|
974
|
|
|
{ |
|
975
|
|
|
$country_from_lang = strtoupper($lang); |
|
976
|
|
|
} |
|
977
|
|
|
else |
|
978
|
|
|
{ |
|
979
|
|
|
list($lang,$lang2) = explode('-',$lang); |
|
980
|
|
|
$country_from_lang = strtoupper($lang2); |
|
981
|
|
|
} |
|
982
|
|
|
if (is_null($charset)) $charset = Translation::charset(); |
|
983
|
|
|
|
|
984
|
|
|
foreach(array( |
|
985
|
|
|
$lang.'_'.$country, |
|
986
|
|
|
$lang.'_'.$country_from_lang, |
|
987
|
|
|
$lang.'_'.$country.'.utf8', |
|
988
|
|
|
$lang.'_'.$country_from_lang.'.utf8', |
|
989
|
|
|
$lang, |
|
990
|
|
|
'en_US', |
|
991
|
|
|
'C', |
|
992
|
|
|
) as $local) |
|
993
|
|
|
{ |
|
994
|
|
|
if (($ret = setlocale($category,$local.'.'.$charset)) || |
|
995
|
|
|
($ret = setlocale($category,$local.'@'.$charset)) || |
|
996
|
|
|
($ret = setlocale($category,$local))) |
|
997
|
|
|
{ |
|
998
|
|
|
//error_log(__METHOD__."($category,$charset) lang=$lang, country=$country, country_from_lang=$country_from_lang: returning '$ret'"); |
|
999
|
|
|
return $ret; |
|
1000
|
|
|
} |
|
1001
|
|
|
} |
|
1002
|
|
|
error_log(__METHOD__."($category,$charset) lang=$lang, country=$country, country_from_lang=$country_from_lang: Could not set local!"); |
|
1003
|
|
|
return false; // should not happen, as the 'C' local should at least be available everywhere |
|
1004
|
|
|
} |
|
1005
|
|
|
|
|
1006
|
|
|
/** |
|
1007
|
|
|
* Get preferences by calling various hooks to supply them |
|
1008
|
|
|
* |
|
1009
|
|
|
* @param string $_appname appname or 'common' |
|
1010
|
|
|
* @param string $type ='user' 'default', 'forced', 'user' or 'group' |
|
1011
|
|
|
* @param int|string $account_id =null account_id for user or group prefs, or "forced" or "default" |
|
1012
|
|
|
* @return array |
|
1013
|
|
|
*/ |
|
1014
|
|
|
public static function settings($_appname, $type='user', $account_id=null) |
|
1015
|
|
|
{ |
|
1016
|
|
|
$all_settings = []; |
|
1017
|
|
|
$appname = $_appname == 'common' ? 'preferences' : $_appname; |
|
1018
|
|
|
|
|
1019
|
|
|
// make type available, to hooks from applications can use it, eg. activesync |
|
1020
|
|
|
$hook_data = array( |
|
1021
|
|
|
'location' => 'settings', |
|
1022
|
|
|
'type' => $type, |
|
1023
|
|
|
'account_id' => $account_id, |
|
1024
|
|
|
); |
|
1025
|
|
|
$GLOBALS['type'] = $type; // old global variable |
|
1026
|
|
|
|
|
1027
|
|
|
// calling app specific settings hook |
|
1028
|
|
|
$settings = Hooks::single($hook_data, $appname); |
|
1029
|
|
|
// it either returns the settings or save it in $GLOBALS['settings'] (deprecated!) |
|
1030
|
|
|
if (isset($settings) && is_array($settings) && $settings) |
|
1031
|
|
|
{ |
|
1032
|
|
|
$all_settings = array_merge($all_settings, $settings); |
|
1033
|
|
|
} |
|
1034
|
|
|
elseif(isset($GLOBALS['settings']) && is_array($GLOBALS['settings']) && $GLOBALS['settings']) |
|
1035
|
|
|
{ |
|
1036
|
|
|
$all_settings = array_merge($all_settings, $GLOBALS['settings']); |
|
1037
|
|
|
} |
|
1038
|
|
|
else |
|
1039
|
|
|
{ |
|
1040
|
|
|
return False; // no settings returned |
|
1041
|
|
|
} |
|
1042
|
|
|
|
|
1043
|
|
|
// calling settings hook all apps can answer (for a specific app) |
|
1044
|
|
|
$hook_data['location'] = 'settings_'.$appname; |
|
1045
|
|
|
foreach(Hooks::process($hook_data, $appname,true) as $settings) |
|
1046
|
|
|
{ |
|
1047
|
|
|
if (isset($settings) && is_array($settings) && $settings) |
|
|
|
|
|
|
1048
|
|
|
{ |
|
1049
|
|
|
$all_settings = array_merge($all_settings,$settings); |
|
1050
|
|
|
} |
|
1051
|
|
|
} |
|
1052
|
|
|
return $all_settings; |
|
1053
|
|
|
} |
|
1054
|
|
|
} |
|
1055
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.