preferences.php 9.17 KB
Newer Older
1
<?php
2
3
4
5
6
/**
 * ownCloud
 *
 * @author Frank Karlitschek
 * @author Jakob Sack
Frank Karlitschek's avatar
Frank Karlitschek committed
7
 * @copyright 2012 Frank Karlitschek frank@owncloud.org
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 *
 * 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 ,
31
32
 * `configkey` VARCHAR( 255 ) NOT NULL ,
 * `configvalue` VARCHAR( 255 ) NOT NULL
33
34
35
36
 * )
 *
 */

37
38
namespace OC;

39
use OCP\IDBConnection;
40
41


42
43
44
/**
 * This class provides an easy way for storing user preferences.
 */
45
class Preferences {
Robin Appelman's avatar
Robin Appelman committed
46
47
48
	/**
	 * @var \OC\DB\Connection
	 */
49
50
	protected $conn;

Robin Appelman's avatar
Robin Appelman committed
51
	/**
Robin Appelman's avatar
Robin Appelman committed
52
53
54
55
56
57
58
	 * 3 dimensional array with the following structure:
	 * [ $userId =>
	 *     [ $appId =>
	 *         [ $key => $value ]
	 *     ]
	 * ]
	 *
Robin Appelman's avatar
Robin Appelman committed
59
60
61
62
63
	 * @var array $cache
	 */
	protected $cache = array();

	/**
64
	 * @param \OCP\IDBConnection $conn
Robin Appelman's avatar
Robin Appelman committed
65
	 */
66
	public function __construct(IDBConnection $conn) {
67
68
69
		$this->conn = $conn;
	}

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	/**
	 * Get all users using the preferences
	 * @return array an array of user ids
	 *
	 * This function returns a list of all users that have at least one entry
	 * in the preferences table.
	 */
	public function getUsers() {
		$query = 'SELECT DISTINCT `userid` FROM `*PREFIX*preferences`';
		$result = $this->conn->executeQuery($query);

		$users = array();
		while ($userid = $result->fetchColumn()) {
			$users[] = $userid;
		}

		return $users;
	}

Robin Appelman's avatar
Robin Appelman committed
89
90
	/**
	 * @param string $user
Robin Appelman's avatar
Robin Appelman committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
	 * @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;
	}

111
112
113
114
115
116
117
118
119
120
121
122
123
	/**
	 * Get all apps of an user
	 * @param string $user user
	 * @return integer[] with app ids
	 *
	 * This function returns a list of all apps of the user that have at least
	 * one entry in the preferences table.
	 */
	public function getApps($user) {
		$data = $this->getUserValues($user);
		return array_keys($data);
	}

124
	/**
125
	 * Get the available keys for an app
Robin Appelman's avatar
Robin Appelman committed
126
127
	 * @param string $user user
	 * @param string $app the app we are looking for
128
	 * @return array an array of key names
129
130
131
132
	 *
	 * This function gets all keys of an app of an user. Please note that the
	 * values are not returned.
	 */
Robin Appelman's avatar
Robin Appelman committed
133
134
135
136
137
138
	public function getKeys($user, $app) {
		$data = $this->getUserValues($user);
		if (isset($data[$app])) {
			return array_keys($data[$app]);
		} else {
			return array();
139
		}
140
141
142
	}

	/**
143
	 * Gets the preference
Robin Appelman's avatar
Robin Appelman committed
144
145
146
147
148
	 * @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
149
	 *
Robin Appelman's avatar
Robin Appelman committed
150
151
	 * This function gets a value from the preferences table. If the key does
	 * not exist the default value will be returned
152
	 */
Robin Appelman's avatar
Robin Appelman committed
153
154
155
156
	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];
157
		} else {
158
159
			return $default;
		}
160
161
162
	}

	/**
163
	 * sets a value in the preferences
Robin Appelman's avatar
Robin Appelman committed
164
165
166
167
	 * @param string $user user
	 * @param string $app app
	 * @param string $key key
	 * @param string $value value
168
169
	 * @param string $preCondition only set value if the key had a specific value before
	 * @return bool true if value was set, otherwise false
170
171
172
	 *
	 * Adds a value to the preferences. If the key did not exist before, it
	 * will be added automagically.
173
	 */
174
	public function setValue($user, $app, $key, $value, $preCondition = null) {
175
		// Check if the key does exist
Arthur Schiwon's avatar
Arthur Schiwon committed
176
		$query = 'SELECT `configvalue` FROM `*PREFIX*preferences`'
Robin Appelman's avatar
Robin Appelman committed
177
			. ' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
Arthur Schiwon's avatar
Arthur Schiwon committed
178
179
		$oldValue = $this->conn->fetchColumn($query, array($user, $app, $key));
		$exists = $oldValue !== false;
180

Arthur Schiwon's avatar
Arthur Schiwon committed
181
182
183
184
185
		if($oldValue === strval($value)) {
			// no changes
			return true;
		}
		
186
187
188
		$affectedRows = 0;

		if (!$exists && $preCondition === null) {
189
190
191
192
193
194
			$data = array(
				'userid' => $user,
				'appid' => $app,
				'configkey' => $key,
				'configvalue' => $value,
			);
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
			$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);
211
		}
Robin Appelman's avatar
Robin Appelman committed
212
213

		// only add to the cache if we already loaded data for the user
214
		if ($affectedRows > 0 && isset($this->cache[$user])) {
Robin Appelman's avatar
Robin Appelman committed
215
216
217
218
219
			if (!isset($this->cache[$user][$app])) {
				$this->cache[$user][$app] = array();
			}
			$this->cache[$user][$app][$key] = $value;
		}
220
221
222

		return ($affectedRows > 0) ? true : false;

223
224
	}

225
226
227
228
229
230
231
232
	/**
	 * 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) {
Joas Schilling's avatar
Joas Schilling committed
233
234
235
		if (empty($users) || !is_array($users)) {
			return array();
		}
236
237
238
239
240
241
242
243
244
245

		$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);

246
			$placeholders = (sizeof($chunk) == 50) ? $placeholders_50 : implode(',', array_fill(0, sizeof($chunk), '?'));
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

			$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;
	}

262
263
264
265
266
267
268
269
270
271
272
273
	/**
	 * 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` '
274
275
276
277
278
279
280
281
282
			. ' 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`)= ?';
		} else {
			$query .= ' `configvalue` = ?';
		}

283
284
285
286
287
288
289
290
291
		$result = $this->conn->executeQuery($query, array($app, $key, $value));

		while ($row = $result->fetch()) {
			$users[] = $row['userid'];
		}

		return $users;
	}

292
	/**
293
	 * Deletes a key
Robin Appelman's avatar
Robin Appelman committed
294
295
296
	 * @param string $user user
	 * @param string $app app
	 * @param string $key key
297
298
299
	 *
	 * Deletes a key.
	 */
Robin Appelman's avatar
Robin Appelman committed
300
	public function deleteKey($user, $app, $key) {
301
302
303
304
305
306
		$where = array(
			'userid' => $user,
			'appid' => $app,
			'configkey' => $key,
		);
		$this->conn->delete('*PREFIX*preferences', $where);
Robin Appelman's avatar
Robin Appelman committed
307

Robin Appelman's avatar
Robin Appelman committed
308
		if (isset($this->cache[$user]) and isset($this->cache[$user][$app])) {
Robin Appelman's avatar
Robin Appelman committed
309
310
			unset($this->cache[$user][$app][$key]);
		}
311
312
313
	}

	/**
314
	 * Remove app of user from preferences
Robin Appelman's avatar
Robin Appelman committed
315
316
	 * @param string $user user
	 * @param string $app app
317
	 *
318
	 * Removes all keys in preferences belonging to the app and the user.
319
	 */
Robin Appelman's avatar
Robin Appelman committed
320
	public function deleteApp($user, $app) {
321
322
323
324
325
		$where = array(
			'userid' => $user,
			'appid' => $app,
		);
		$this->conn->delete('*PREFIX*preferences', $where);
Robin Appelman's avatar
Robin Appelman committed
326

Robin Appelman's avatar
Robin Appelman committed
327
		if (isset($this->cache[$user])) {
Robin Appelman's avatar
Robin Appelman committed
328
329
			unset($this->cache[$user][$app]);
		}
330
331
332
	}

	/**
333
	 * Remove user from preferences
Robin Appelman's avatar
Robin Appelman committed
334
	 * @param string $user user
335
	 *
336
	 * Removes all keys in preferences belonging to the user.
337
	 */
Robin Appelman's avatar
Robin Appelman committed
338
	public function deleteUser($user) {
339
340
341
342
		$where = array(
			'userid' => $user,
		);
		$this->conn->delete('*PREFIX*preferences', $where);
Robin Appelman's avatar
Robin Appelman committed
343

Robin Appelman's avatar
Robin Appelman committed
344
		unset($this->cache[$user]);
345
346
347
	}

	/**
348
	 * Remove app from all users
Robin Appelman's avatar
Robin Appelman committed
349
	 * @param string $app app
350
351
352
	 *
	 * Removes all keys in preferences belonging to the app.
	 */
Robin Appelman's avatar
Robin Appelman committed
353
	public function deleteAppFromAllUsers($app) {
354
355
356
357
		$where = array(
			'appid' => $app,
		);
		$this->conn->delete('*PREFIX*preferences', $where);
Robin Appelman's avatar
Robin Appelman committed
358
359
360
361

		foreach ($this->cache as &$userCache) {
			unset($userCache[$app]);
		}
362
363
	}
}
364

Robin Appelman's avatar
Robin Appelman committed
365
require_once __DIR__ . '/legacy/' . basename(__FILE__);