Subversion Repositories Applications.papyrus

Rev

Rev 1372 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1173 jp_milcent 1
<?php
2
require_once("DB.php");
3
 
4
/**
5
 * A simple preference manager, takes userid, preference name pairs and returns the value
6
 * of that preference.
7
 *
8
 * CREATE TABLE `preferences` (
9
 * `user_id` varchar( 255 ) NOT NULL default '',
10
 * `pref_id` varchar( 32 ) NOT NULL default '',
11
 * `pref_value` longtext NOT NULL ,
12
 * 	PRIMARY KEY ( `user_id` , `pref_id` )
13
 * )
14
 *
15
 * @author Jon Wood <jon@jellybob.co.uk>
16
 * @package Auth_PrefManager
17
 * @category Authentication
18
 */
19
class Auth_PrefManager
20
{
21
    /**
22
     * The database object.
23
     * @var object
24
     * @access private
25
     */
26
    var $_db;
27
 
28
    /**
29
     * The user name to get preferences from if the user specified doesn't
30
     * have that preference set.
31
     * @var string
32
     * @access private
33
     */
34
    var $_defaultUser = "__default__";
35
 
36
    /**
37
     * Should we search for default values, or just fail when we find out that
38
     * the specified user didn't have it set.
39
     *
40
     * @var bool
41
     * @access private
42
     */
43
    var $_returnDefaults = true;
44
 
45
    /**
46
     * The table containing the preferences.
47
     * @var string
48
     * @access private
49
     */
50
    var $_table = "preferences";
51
 
52
    /**
53
     * The column containing user ids.
54
     * @var string
55
     * @access private
56
     */
57
    var $_userColumn = "user_id";
58
 
59
    /**
60
     * The column containing preference names.
61
     * @var string
62
     * @access private
63
     */
64
    var $_nameColumn = "pref_id";
65
 
66
    /**
67
     * The column containing preference values.
68
     * @var string
69
     * @access private
70
     */
71
    var $_valueColumn = "pref_value";
72
 
73
	/**
74
	 * The quoted value column.
75
	 * @var string
76
	 * @access private
77
	 */
78
	var $_valueColumnQuoted = "pref_value";
79
 
80
    /**
81
     * The session variable that the cache array is stored in.
82
     * @var string
83
     * @access private
84
     */
85
     var $_cacheName = "prefCache";
86
 
87
    /**
88
     * The last error given.
89
     * @var string
90
     * @access private
91
     */
92
    var $_lastError;
93
 
94
    /**
95
     * Defines whether the cache should be used or not.
96
     * @var bool
97
     * @access private
98
     */
99
    var $_useCache = true;
100
 
101
    /**
102
     * Defines whether values should be serialized before saving.
103
     * @var bool
104
     * @access private
105
     */
106
    var $_serialize = false;
107
 
108
    /**
109
     * Constructor
110
     *
111
     * Options:
112
     *  table: The table to get prefs from. [preferences]
113
     *  userColumn: The field name to search for userid's [user_id]
114
     *  nameColumn: The field name to search for preference names [pref_name]
115
     *  valueColumn: The field name to search for preference values [pref_value]
116
     *  defaultUser: The userid assigned to default values [__default__]
117
     *  cacheName: The name of cache in the session variable ($_SESSION[cacheName]) [prefsCache]
118
     *  useCache: Whether or not values should be cached.
119
     *  serialize: Should preference values be serialzed before saving?
120
     *
121
     * @param string $dsn The DSN of the database connection to make, or a DB object.
122
     * @param array $properties An array of properties to set.
123
     * @param string $defaultUser The default user to manage for.
124
     * @return bool Success or failure.
125
     * @access public
126
     */
127
    function Auth_PrefManager($dsn, $properties = NULL)
128
    {
129
        // Connect to the database.
130
        if (isset($dsn)) {
131
            if (is_string($dsn)) {
132
				$this->_db = DB::Connect($dsn);
133
                if (DB::isError($this->_db)) {
134
                    $this->_lastError = "DB Error: ".$this->_db->getMessage();
135
                }
136
			} else if (is_subclass_of($dsn, 'db_common')) {
137
                $this->_db = &$dsn;
138
            } else {
139
				$this->_lastError = "Invalid DSN specified.";
140
				return false;
141
            }
142
        } else {
143
            $this->_lastError = "No DSN specified.";
144
            return false;
145
        }
146
 
147
        if (is_array($properties)) {
148
            if (isset($properties["table"]))        { $this->_table = $this->_db->quoteIdentifier($properties["table"]); }
149
            if (isset($properties["userColumn"]))   { $this->_userColumn = $this->_db->quoteIdentifier($properties["userColumn"]); }
150
            if (isset($properties["nameColumn"]))   { $this->_nameColumn = $this->_db->quoteIdentifier($properties["nameColumn"]); }
151
            if (isset($properties["valueColumn"]))  { $this->_valueColumn = $properties["valueColumn"]; }
152
			if (isset($properties["valueColumn"]))  { $this->_valueColumnQuoted = $this->_db->quoteIdentifier($properties["valueColumn"]); }
153
            if (isset($properties["defaultUser"]))  { $this->_defaultUser = $properties["defaultUser"]; }
154
            if (isset($properties["cacheName"]))    { $this->_cacheName = $properties["cacheName"]; }
155
	        if (isset($properties["useCache"]))     { $this->_useCache = $properties["useCache"]; }
156
            if (isset($properties["serialize"]))    { $this->_serialize = $properties["serialize"]; }
157
        }
158
 
159
        return true;
160
    }
161
 
162
    function setReturnDefaults($returnDefaults = true)
163
    {
164
        if (is_bool($returnDefaults)) {
165
            $this->_returnDefaults = $returnDefaults;
166
        }
167
    }
168
 
169
    /**
170
     * Sets whether the cache should be used.
171
     *
172
     * @param bool $use Should the cache be used.
173
     * @access public
174
     */
175
    function useCache($use = true)
176
    {
177
        $this->_useCache = $use;
178
    }
179
 
180
    /**
181
     * Cleans out the cache.
182
     *
183
     * @access public
184
     */
185
    function clearCache()
186
    {
187
        unset($_SESSION[$this->_cacheName]);
188
    }
189
 
190
    /**
191
     * Get a preference for the specified user, or, if returning default values
192
     * is enabled, the default.
193
     *
194
     * @param string $user_id The user to get the preference for.
195
     * @param string $pref_id The preference to get.
196
     * @param bool $showDefaults Should default values be searched (overrides the global setting).
197
     * @return mixed The value if it's found, or NULL if it isn't.
198
     * @access public
199
     */
200
    function getPref($user_id, $pref_id, $showDefaults = true)
201
    {
202
        if (isset($_SESSION[$this->_cacheName][$user_id][$pref_id]) && $this->_useCache) {
203
            // Value is cached for the specified user, so give them the cached copy.
204
            return $_SESSION[$this->_cacheName][$user_id][$pref_id];
205
        } else {
206
            // Not cached, search the database for this user's preference.
207
            $query = sprintf("SELECT * FROM %s WHERE %s=%s AND %s=%s", $this->_table,
208
	                                                               $this->_userColumn,
209
                                                                       $this->_db->quote($user_id),
210
                                                                       $this->_nameColumn,
211
                                                                       $this->_db->quote($pref_id));
212
            $result = $this->_db->query($query);
213
            if (DB::isError($result)) {
214
                // Ouch! The query failed!
215
                $this->_lastError = "DB Error: ".$result->getMessage();
216
                return NULL;
217
            } else if ($result->numRows()) {
218
                // The query found a value, so we can cache that, and then return it.
219
                $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
220
                $_SESSION[$this->_cacheName][$user_id][$pref_id] = $this->_unpack($row[$this->_valueColumn]);
221
                return $_SESSION[$this->_cacheName][$user_id][$pref_id];
222
            } else if ($this->_returnDefaults && $showDefaults) {
223
                // I was doing this with a call to getPref again, but it threw things into an
224
                // infinite loop if the default value didn't exist. If you can fix that, it would
225
                // be great ;)
226
                if (isset($_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id]) && $this->_useCache) {
227
                    $_SESSION[$this->_cacheName][$user_id][$pref_id] = $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id];
228
                    return $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id];
229
                } else {
230
                    $query = sprintf("SELECT * FROM %s WHERE %s=%s AND %s=%s", $this->_table,
231
                                                                               $this->_userColumn,
232
                                                                               $this->_db->quote($this->_defaultUser),
233
                                                                               $this->_nameColumn,
234
                                                                               $this->_db->quote($pref_id));
235
                    $result = $this->_db->query($query);
236
                    if (DB::isError($result)) {
237
                        $this->_lastError = "DB Error: ".$result->getMessage();
238
                        return NULL;
239
                    } else {
240
                        if ($result->numRows()) {
241
                            $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
242
                            $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id] = $this->_unpack($row[$this->_valueColumn]);
243
                            $_SESSION[$this->_cacheName][$user_id][$pref_id] = $_SESSION[$this->_cacheName][$this->_defaultUser][$pref_id];
244
                            return $_SESSION[$this->_cacheName][$user_id][$pref_id];
245
                        } else {
246
                            return NULL;
247
                        }
248
                    }
249
                }
250
            } else {
251
                // We've used up all the resources we're allowed to search, so return a NULL.
252
                return NULL;
253
            }
254
        }
255
    }
256
 
257
    /**
258
    * A shortcut function for getPref($this->_defaultUser, $pref_id, $value),
259
    * useful if you have a logged in user, but want to get defaults anyway.
260
    *
261
    * @param string $pref_id The name of the preference to get.
262
    * @return mixed The value if it's found, or NULL if it isn't.
263
    * @access public
264
    */
265
    function getDefaultPref($pref_id)
266
    {
267
        return $this->getPref($this->_defaultUser, $pref_id);
268
    }
269
 
270
    /**
271
     * Set a preference for the specified user.
272
     *
273
     * @param string $user_id The user to set for.
274
     * @param string $pref_id The preference to set.
275
     * @param mixed $value The value it should be set to.
276
     * @return bool Sucess or failure.
277
     * @access public
278
     */
279
    function setPref($user_id, $pref_id, $value)
280
    {
281
        // Start off by checking if the preference is already set (if it is we need to do
282
        // an UPDATE, if not, it's an INSERT.
283
        if ($this->_exists($user_id, $pref_id, false)) {
284
            $query = sprintf("UPDATE %s SET %s=%s WHERE %s=%s AND %s=%s", $this->_table,
285
                                                                          $this->_valueColumnQuoted,
286
                                                                          $this->_db->quote($this->_pack($value)),
287
                                                                          $this->_userColumn,
288
                                                                          $this->_db->quote($user_id),
289
                                                                          $this->_nameColumn,
290
                                                                          $this->_db->quote($pref_id));
291
        } else {
292
            $query = sprintf("INSERT INTO %s (%s, %s, %s) VALUES(%s, %s, %s)", $this->_table,
293
                                                                               $this->_userColumn,
294
                                                                               $this->_nameColumn,
295
                                                                               $this->_valueColumnQuoted,
296
                                                                               $this->_db->quote($user_id),
297
                                                                               $this->_db->quote($pref_id),
298
                                                                               $this->_db->quote($this->_pack($value)));
299
        }
300
        $result = $this->_db->query($query);
301
        if (DB::isError($result)) {
302
            $this->_lastError = "DB Error: ".$result->getMessage();
303
            return false;
304
        } else {
305
	    if ($this->_useCache) {
306
	        $_SESSION[$this->_cacheName][$user_id][$pref_id] = $value;
307
	    }
308
            return true;
309
        }
310
    }
311
 
312
    /**
313
    * A shortcut function for setPref($this->_defaultUser, $pref_id, $value)
314
    *
315
    * @param string $pref_id The name of the preference to set.
316
    * @param mixed $value The value to set it to.
317
    * @return bool Sucess or failure.
318
    * @access public
319
    */
320
    function setDefaultPref($pref_id, $value)
321
    {
322
        return $this->setPref($this->_defaultUser, $pref_id, $value);
323
    }
324
 
325
    /**
326
    * Deletes a preference for the specified user.
327
    *
328
    * @param string $user_id The userid of the user to delete from.
329
    * @param string $pref_id The preference to delete.
330
    * @return bool Success/Failure
331
    * @access public
332
    */
333
    function deletePref($user_id, $pref_id)
334
    {
335
        if ($this->getPref($user_id, $pref_id) == NULL) {
336
            // The user doesn't have this variable anyway ;)
337
            return true;
338
        } else {
339
            $query = sprintf("DELETE FROM %s WHERE %s=%s AND %s=%s", $this->_table,
340
                                                                     $this->_userColumn,
341
                                                                     $this->_db->quote($user_id),
342
                                                                     $this->_nameColumn,
343
                                                                     $this->_db->quote($pref_id));
344
            $result = $this->_db->query($query);
345
            if (DB::isError($result)) {
346
                $this->_lastError = "DB Error: ".$result->getMessage();
347
                return false;
348
            } else {
349
				if ($this->_useCache) {
350
				    unset($_SESSION[$this->_cacheName][$user_id][$pref_id]);
351
				}
352
                return true;
353
            }
354
        }
355
    }
356
 
357
    /**
358
    * Deletes a preference for the default user.
359
    *
360
    * @param string $pref_id The preference to delete.
361
    * @return bool Success/Failure
362
    * @access public
363
    */
364
    function deleteDefaultPref($pref_id)
365
    {
366
        return $this->deletePref($this->_defaultUser, $pref_id);
367
    }
368
 
369
    /**
370
     * Checks if a preference exists in the database.
371
     *
372
     * @param string $user_id The userid of the preference owner.
373
     * @param string $pref_id The preference to check for.
374
     * @return bool True if the preference exists.
375
     * @access private
376
     */
377
    function _exists($user_id, $pref_id)
378
    {
379
        $query = sprintf("SELECT COUNT(%s) FROM %s WHERE %s=%s AND %s=%s", $this->_nameColumn,
380
                                                                           $this->_table,
381
                                                                           $this->_userColumn,
382
                                                                           $this->_db->quoteSmart($user_id),
383
                                                                           $this->_nameColumn,
384
                                                                           $this->_db->quote($pref_id));
385
        $result = $this->_db->getOne($query);
386
        if (DB::isError($result)) {
387
            $this->_lastError = "DB Error: ".$result->getMessage();
388
            return false;
389
        } else {
390
            return (bool)$result;
391
        }
392
    }
393
 
394
    /**
395
     * Does anything needed to prepare a value for saving in the database.
396
     *
397
     * @param mixed $value The value to be saved.
398
     * @return string The value in a format valid for saving to the database.
399
     * @access private
400
     */
401
    function _pack($value)
402
    {
403
        if ($this->_serialize) {
404
            return serialize($value);
405
        } else {
406
            return $value;
407
        }
408
    }
409
 
410
    /**
411
     * Does anything needed to create a value of the preference, such as unserializing.
412
     *
413
     * @param string $value The value of the preference.
414
     * @return mixed The unpacked version of the preference.
415
     * @access private
416
     */
417
    function _unpack($value)
418
    {
419
        if ($this->_serialize) {
420
            return unserialize($value);
421
        } else {
422
            return $value;
423
        }
424
    }
425
}
426
?>