Blame view

sources/lib/private/preferences.php 9.17 KB
03e52840d   Kload   Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  <?php
  /**
   * ownCloud
   *
   * @author Frank Karlitschek
   * @author Jakob Sack
   * @copyright 2012 Frank Karlitschek frank@owncloud.org
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  /*
   *
   * The following SQL statement is just a help for developers and will not be
   * executed!
   *
   * CREATE TABLE  `preferences` (
   * `userid` VARCHAR( 255 ) NOT NULL ,
   * `appid` VARCHAR( 255 ) NOT NULL ,
   * `configkey` VARCHAR( 255 ) NOT NULL ,
   * `configvalue` VARCHAR( 255 ) NOT NULL
   * )
   *
   */
31b7f2792   Kload   Upgrade to ownclo...
36
37
38
  namespace OC;
  
  use \OC\DB\Connection;
03e52840d   Kload   Init
39
40
41
  /**
   * This class provides an easy way for storing user preferences.
   */
31b7f2792   Kload   Upgrade to ownclo...
42
  class Preferences {
6d9380f96   Cédric Dupont   Update sources OC...
43
44
45
  	/**
  	 * @var \OC\DB\Connection
  	 */
31b7f2792   Kload   Upgrade to ownclo...
46
  	protected $conn;
6d9380f96   Cédric Dupont   Update sources OC...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  	/**
  	 * 3 dimensional array with the following structure:
  	 * [ $userId =>
  	 *     [ $appId =>
  	 *         [ $key => $value ]
  	 *     ]
  	 * ]
  	 *
  	 * @var array $cache
  	 */
  	protected $cache = array();
  
  	/**
  	 * @param \OC\DB\Connection $conn
  	 */
31b7f2792   Kload   Upgrade to ownclo...
62
63
64
  	public function __construct(Connection $conn) {
  		$this->conn = $conn;
  	}
03e52840d   Kload   Init
65
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
66
67
  	 * Get all users using the preferences
  	 * @return array an array of user ids
03e52840d   Kload   Init
68
69
70
71
  	 *
  	 * This function returns a list of all users that have at least one entry
  	 * in the preferences table.
  	 */
31b7f2792   Kload   Upgrade to ownclo...
72
73
  	public function getUsers() {
  		$query = 'SELECT DISTINCT `userid` FROM `*PREFIX*preferences`';
6d9380f96   Cédric Dupont   Update sources OC...
74
  		$result = $this->conn->executeQuery($query);
03e52840d   Kload   Init
75
76
  
  		$users = array();
6d9380f96   Cédric Dupont   Update sources OC...
77
  		while ($userid = $result->fetchColumn()) {
31b7f2792   Kload   Upgrade to ownclo...
78
  			$users[] = $userid;
03e52840d   Kload   Init
79
80
81
82
83
84
  		}
  
  		return $users;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  	 * @param string $user
  	 * @return array[]
  	 */
  	protected function getUserValues($user) {
  		if (isset($this->cache[$user])) {
  			return $this->cache[$user];
  		}
  		$data = array();
  		$query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
  		$result = $this->conn->executeQuery($query, array($user));
  		while ($row = $result->fetch()) {
  			$app = $row['appid'];
  			if (!isset($data[$app])) {
  				$data[$app] = array();
  			}
  			$data[$app][$row['configkey']] = $row['configvalue'];
  		}
  		$this->cache[$user] = $data;
  		return $data;
  	}
  
  	/**
  	 * Get all apps of an user
03e52840d   Kload   Init
108
  	 * @param string $user user
6d9380f96   Cédric Dupont   Update sources OC...
109
  	 * @return integer[] with app ids
03e52840d   Kload   Init
110
111
112
113
  	 *
  	 * This function returns a list of all apps of the user that have at least
  	 * one entry in the preferences table.
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
114
115
116
  	public function getApps($user) {
  		$data = $this->getUserValues($user);
  		return array_keys($data);
03e52840d   Kload   Init
117
118
119
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
120
  	 * Get the available keys for an app
03e52840d   Kload   Init
121
122
  	 * @param string $user user
  	 * @param string $app the app we are looking for
6d9380f96   Cédric Dupont   Update sources OC...
123
  	 * @return array an array of key names
03e52840d   Kload   Init
124
125
126
127
  	 *
  	 * This function gets all keys of an app of an user. Please note that the
  	 * values are not returned.
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
128
129
130
131
132
133
  	public function getKeys($user, $app) {
  		$data = $this->getUserValues($user);
  		if (isset($data[$app])) {
  			return array_keys($data[$app]);
  		} else {
  			return array();
03e52840d   Kload   Init
134
  		}
03e52840d   Kload   Init
135
136
137
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
138
  	 * Gets the preference
03e52840d   Kload   Init
139
140
141
142
143
144
145
146
147
  	 * @param string $user user
  	 * @param string $app app
  	 * @param string $key key
  	 * @param string $default = null, default value if the key does not exist
  	 * @return string the value or $default
  	 *
  	 * This function gets a value from the preferences table. If the key does
  	 * not exist the default value will be returned
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
148
149
150
151
  	public function getValue($user, $app, $key, $default = null) {
  		$data = $this->getUserValues($user);
  		if (isset($data[$app]) and isset($data[$app][$key])) {
  			return $data[$app][$key];
31b7f2792   Kload   Upgrade to ownclo...
152
  		} else {
03e52840d   Kload   Init
153
154
155
156
157
  			return $default;
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
158
  	 * sets a value in the preferences
03e52840d   Kload   Init
159
160
161
162
  	 * @param string $user user
  	 * @param string $app app
  	 * @param string $key key
  	 * @param string $value value
6d9380f96   Cédric Dupont   Update sources OC...
163
164
  	 * @param string $preCondition only set value if the key had a specific value before
  	 * @return bool true if value was set, otherwise false
03e52840d   Kload   Init
165
166
167
168
  	 *
  	 * Adds a value to the preferences. If the key did not exist before, it
  	 * will be added automagically.
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
169
  	public function setValue($user, $app, $key, $value, $preCondition = null) {
03e52840d   Kload   Init
170
  		// Check if the key does exist
6d9380f96   Cédric Dupont   Update sources OC...
171
172
173
174
  		$query = 'SELECT `configvalue` FROM `*PREFIX*preferences`'
  			. ' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
  		$oldValue = $this->conn->fetchColumn($query, array($user, $app, $key));
  		$exists = $oldValue !== false;
03e52840d   Kload   Init
175

6d9380f96   Cédric Dupont   Update sources OC...
176
177
178
179
180
181
182
183
  		if($oldValue === strval($value)) {
  			// no changes
  			return true;
  		}
  		
  		$affectedRows = 0;
  
  		if (!$exists && $preCondition === null) {
31b7f2792   Kload   Upgrade to ownclo...
184
185
186
187
188
189
  			$data = array(
  				'userid' => $user,
  				'appid' => $app,
  				'configkey' => $key,
  				'configvalue' => $value,
  			);
6d9380f96   Cédric Dupont   Update sources OC...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  			$affectedRows = $this->conn->insert('*PREFIX*preferences', $data);
  		} elseif ($exists) {
  			$data = array($value, $user, $app, $key);
  			$sql  = "UPDATE `*PREFIX*preferences` SET `configvalue` = ?"
  					. " WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?";
  
  			if ($preCondition !== null) {
  				if (\OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') {
  					//oracle hack: need to explicitly cast CLOB to CHAR for comparison
  					$sql .= " AND to_char(`configvalue`) = ?";
  				} else {
  					$sql .= " AND `configvalue` = ?";
  				}
  				$data[] = $preCondition;
  			}
  			$affectedRows = $this->conn->executeUpdate($sql, $data);
  		}
  
  		// only add to the cache if we already loaded data for the user
  		if ($affectedRows > 0 && isset($this->cache[$user])) {
  			if (!isset($this->cache[$user][$app])) {
  				$this->cache[$user][$app] = array();
  			}
  			$this->cache[$user][$app][$key] = $value;
  		}
  
  		return ($affectedRows > 0) ? true : false;
  
  	}
  
  	/**
  	 * Gets the preference for an array of users
  	 * @param string $app
  	 * @param string $key
  	 * @param array $users
  	 * @return array Mapped values: userid => value
  	 */
  	public function getValueForUsers($app, $key, $users) {
  		if (empty($users) || !is_array($users)) {
  			return array();
  		}
  
  		$chunked_users = array_chunk($users, 50, true);
  		$placeholders_50 = implode(',', array_fill(0, 50, '?'));
  
  		$userValues = array();
  		foreach ($chunked_users as $chunk) {
  			$queryParams = $chunk;
  			array_unshift($queryParams, $key);
  			array_unshift($queryParams, $app);
  
  			$placeholders = (sizeof($chunk) == 50) ? $placeholders_50 : implode(',', array_fill(0, sizeof($chunk), '?'));
  
  			$query = 'SELECT `userid`, `configvalue` '
  				. ' FROM `*PREFIX*preferences` '
  				. ' WHERE `appid` = ? AND `configkey` = ?'
  				. ' AND `userid` IN (' . $placeholders . ')';
  			$result = $this->conn->executeQuery($query, $queryParams);
  
  			while ($row = $result->fetch()) {
  				$userValues[$row['userid']] = $row['configvalue'];
  			}
  		}
  
  		return $userValues;
  	}
  
  	/**
  	 * Gets the users for a preference
  	 * @param string $app
  	 * @param string $key
  	 * @param string $value
  	 * @return array
  	 */
  	public function getUsersForValue($app, $key, $value) {
  		$users = array();
  
  		$query = 'SELECT `userid` '
  			. ' FROM `*PREFIX*preferences` '
  			. ' WHERE `appid` = ? AND `configkey` = ? AND ';
  
  		if (\OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') {
  			//FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison
  			$query .= ' to_char(`configvalue`)= ?';
31b7f2792   Kload   Upgrade to ownclo...
274
  		} else {
6d9380f96   Cédric Dupont   Update sources OC...
275
  			$query .= ' `configvalue` = ?';
03e52840d   Kload   Init
276
  		}
6d9380f96   Cédric Dupont   Update sources OC...
277
278
279
280
281
282
283
284
  
  		$result = $this->conn->executeQuery($query, array($app, $key, $value));
  
  		while ($row = $result->fetch()) {
  			$users[] = $row['userid'];
  		}
  
  		return $users;
03e52840d   Kload   Init
285
286
287
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
288
  	 * Deletes a key
03e52840d   Kload   Init
289
290
291
  	 * @param string $user user
  	 * @param string $app app
  	 * @param string $key key
03e52840d   Kload   Init
292
293
294
  	 *
  	 * Deletes a key.
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
295
  	public function deleteKey($user, $app, $key) {
31b7f2792   Kload   Upgrade to ownclo...
296
297
298
299
300
301
  		$where = array(
  			'userid' => $user,
  			'appid' => $app,
  			'configkey' => $key,
  		);
  		$this->conn->delete('*PREFIX*preferences', $where);
6d9380f96   Cédric Dupont   Update sources OC...
302
303
304
305
  
  		if (isset($this->cache[$user]) and isset($this->cache[$user][$app])) {
  			unset($this->cache[$user][$app][$key]);
  		}
03e52840d   Kload   Init
306
307
308
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
309
  	 * Remove app of user from preferences
03e52840d   Kload   Init
310
311
  	 * @param string $user user
  	 * @param string $app app
03e52840d   Kload   Init
312
  	 *
31b7f2792   Kload   Upgrade to ownclo...
313
  	 * Removes all keys in preferences belonging to the app and the user.
03e52840d   Kload   Init
314
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
315
  	public function deleteApp($user, $app) {
31b7f2792   Kload   Upgrade to ownclo...
316
317
318
319
320
  		$where = array(
  			'userid' => $user,
  			'appid' => $app,
  		);
  		$this->conn->delete('*PREFIX*preferences', $where);
6d9380f96   Cédric Dupont   Update sources OC...
321
322
323
324
  
  		if (isset($this->cache[$user])) {
  			unset($this->cache[$user][$app]);
  		}
03e52840d   Kload   Init
325
326
327
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
328
  	 * Remove user from preferences
03e52840d   Kload   Init
329
  	 * @param string $user user
03e52840d   Kload   Init
330
  	 *
31b7f2792   Kload   Upgrade to ownclo...
331
  	 * Removes all keys in preferences belonging to the user.
03e52840d   Kload   Init
332
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
333
  	public function deleteUser($user) {
31b7f2792   Kload   Upgrade to ownclo...
334
335
336
337
  		$where = array(
  			'userid' => $user,
  		);
  		$this->conn->delete('*PREFIX*preferences', $where);
6d9380f96   Cédric Dupont   Update sources OC...
338
339
  
  		unset($this->cache[$user]);
03e52840d   Kload   Init
340
341
342
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
343
  	 * Remove app from all users
03e52840d   Kload   Init
344
  	 * @param string $app app
03e52840d   Kload   Init
345
346
347
  	 *
  	 * Removes all keys in preferences belonging to the app.
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
348
  	public function deleteAppFromAllUsers($app) {
31b7f2792   Kload   Upgrade to ownclo...
349
350
351
352
  		$where = array(
  			'appid' => $app,
  		);
  		$this->conn->delete('*PREFIX*preferences', $where);
6d9380f96   Cédric Dupont   Update sources OC...
353
354
355
356
  
  		foreach ($this->cache as &$userCache) {
  			unset($userCache[$app]);
  		}
03e52840d   Kload   Init
357
358
  	}
  }
31b7f2792   Kload   Upgrade to ownclo...
359

6d9380f96   Cédric Dupont   Update sources OC...
360
  require_once __DIR__ . '/legacy/' . basename(__FILE__);