Completed
Push — master ( b1a829...012708 )
by Christoph
08:19
created

AppConfig::getApps()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Bart Visscher <[email protected]>
7
 * @author Jakob Sack <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Robin McCorkell <[email protected]>
13
 *
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
30
namespace OC;
31
32
use OC\DB\OracleConnection;
33
use OCP\IAppConfig;
34
use OCP\IConfig;
35
use OCP\IDBConnection;
36
37
/**
38
 * This class provides an easy way for apps to store config values in the
39
 * database.
40
 */
41
class AppConfig implements IAppConfig {
42
43
	/** @var array[] */
44
	protected $sensitiveValues = [
45
		'user_ldap' => [
46
			'ldap_agent_password',
47
		],
48
	];
49
50
	/** @var \OCP\IDBConnection */
51
	protected $conn;
52
53
	/** @var array[] */
54
	private $cache = [];
55
56
	/** @var bool */
57
	private $configLoaded = false;
58
59
	/**
60
	 * @param IDBConnection $conn
61
	 */
62
	public function __construct(IDBConnection $conn) {
63
		$this->conn = $conn;
64
		$this->configLoaded = false;
65
	}
66
67
	/**
68
	 * @param string $app
69
	 * @return array
70
	 */
71
	private function getAppValues($app) {
72
		$this->loadConfigValues();
73
74
		if (isset($this->cache[$app])) {
75
			return $this->cache[$app];
76
		}
77
78
		return [];
79
	}
80
81
	/**
82
	 * Get all apps using the config
83
	 *
84
	 * @return array an array of app ids
85
	 *
86
	 * This function returns a list of all apps that have at least one
87
	 * entry in the appconfig table.
88
	 */
89
	public function getApps() {
90
		$this->loadConfigValues();
91
92
		return $this->getSortedKeys($this->cache);
93
	}
94
95
	/**
96
	 * Get the available keys for an app
97
	 *
98
	 * @param string $app the app we are looking for
99
	 * @return array an array of key names
100
	 * @deprecated 8.0.0 use method getAppKeys of \OCP\IConfig
101
	 *
102
	 * This function gets all keys of an app. Please note that the values are
103
	 * not returned.
104
	 */
105
	public function getKeys($app) {
106
		$this->loadConfigValues();
107
108
		if (isset($this->cache[$app])) {
109
			return $this->getSortedKeys($this->cache[$app]);
110
		}
111
112
		return [];
113
	}
114
115
	public function getSortedKeys($data) {
116
		$keys = array_keys($data);
117
		sort($keys);
118
		return $keys;
119
	}
120
121
	/**
122
	 * Gets the config value
123
	 *
124
	 * @param string $app app
125
	 * @param string $key key
126
	 * @param string $default = null, default value if the key does not exist
127
	 * @return string the value or $default
128
	 * @deprecated 8.0.0 use method getAppValue of \OCP\IConfig
129
	 *
130
	 * This function gets a value from the appconfig table. If the key does
131
	 * not exist the default value will be returned
132
	 */
133
	public function getValue($app, $key, $default = null) {
134
		$this->loadConfigValues();
135
136
		if ($this->hasKey($app, $key)) {
137
			return $this->cache[$app][$key];
138
		}
139
140
		return $default;
141
	}
142
143
	/**
144
	 * check if a key is set in the appconfig
145
	 *
146
	 * @param string $app
147
	 * @param string $key
148
	 * @return bool
149
	 */
150
	public function hasKey($app, $key) {
151
		$this->loadConfigValues();
152
153
		return isset($this->cache[$app][$key]);
154
	}
155
156
	/**
157
	 * Sets a value. If the key did not exist before it will be created.
158
	 *
159
	 * @param string $app app
160
	 * @param string $key key
161
	 * @param string|float|int $value value
162
	 * @return bool True if the value was inserted or updated, false if the value was the same
163
	 * @deprecated 8.0.0 use method setAppValue of \OCP\IConfig
164
	 */
165
	public function setValue($app, $key, $value) {
166
		if (!$this->hasKey($app, $key)) {
167
			$inserted = (bool) $this->conn->insertIfNotExist('*PREFIX*appconfig', [
168
				'appid' => $app,
169
				'configkey' => $key,
170
				'configvalue' => $value,
171
			], [
172
				'appid',
173
				'configkey',
174
			]);
175
176 View Code Duplication
			if ($inserted) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
177
				if (!isset($this->cache[$app])) {
178
					$this->cache[$app] = [];
179
				}
180
181
				$this->cache[$app][$key] = $value;
182
				return true;
183
			}
184
		}
185
186
		$sql = $this->conn->getQueryBuilder();
187
		$sql->update('appconfig')
188
			->set('configvalue', $sql->createParameter('configvalue'))
189
			->where($sql->expr()->eq('appid', $sql->createParameter('app')))
190
			->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
191
			->setParameter('configvalue', $value)
192
			->setParameter('app', $app)
193
			->setParameter('configkey', $key);
194
195
		/*
196
		 * Only limit to the existing value for non-Oracle DBs:
197
		 * http://docs.oracle.com/cd/E11882_01/server.112/e26088/conditions002.htm#i1033286
198
		 * > Large objects (LOBs) are not supported in comparison conditions.
199
		 */
200
		if (!($this->conn instanceof OracleConnection)) {
201
			// Only update the value when it is not the same
202
			$sql->andWhere($sql->expr()->neq('configvalue', $sql->createParameter('configvalue')))
203
				->setParameter('configvalue', $value);
204
		}
205
206
		$changedRow = (bool) $sql->execute();
207
208
		$this->cache[$app][$key] = $value;
209
210
		return $changedRow;
211
	}
212
213
	/**
214
	 * Deletes a key
215
	 *
216
	 * @param string $app app
217
	 * @param string $key key
218
	 * @return boolean
219
	 * @deprecated 8.0.0 use method deleteAppValue of \OCP\IConfig
220
	 */
221
	public function deleteKey($app, $key) {
222
		$this->loadConfigValues();
223
224
		$sql = $this->conn->getQueryBuilder();
225
		$sql->delete('appconfig')
226
			->where($sql->expr()->eq('appid', $sql->createParameter('app')))
227
			->andWhere($sql->expr()->eq('configkey', $sql->createParameter('configkey')))
228
			->setParameter('app', $app)
229
			->setParameter('configkey', $key);
230
		$sql->execute();
231
232
		unset($this->cache[$app][$key]);
233
		return false;
234
	}
235
236
	/**
237
	 * Remove app from appconfig
238
	 *
239
	 * @param string $app app
240
	 * @return boolean
241
	 * @deprecated 8.0.0 use method deleteAppValue of \OCP\IConfig
242
	 *
243
	 * Removes all keys in appconfig belonging to the app.
244
	 */
245 View Code Duplication
	public function deleteApp($app) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
		$this->loadConfigValues();
247
248
		$sql = $this->conn->getQueryBuilder();
249
		$sql->delete('appconfig')
250
			->where($sql->expr()->eq('appid', $sql->createParameter('app')))
251
			->setParameter('app', $app);
252
		$sql->execute();
253
254
		unset($this->cache[$app]);
255
		return false;
256
	}
257
258
	/**
259
	 * get multiple values, either the app or key can be used as wildcard by setting it to false
260
	 *
261
	 * @param string|false $app
262
	 * @param string|false $key
263
	 * @return array|false
264
	 */
265
	public function getValues($app, $key) {
266
		if (($app !== false) === ($key !== false)) {
267
			return false;
268
		}
269
270
		if ($key === false) {
271
			return $this->getAppValues($app);
0 ignored issues
show
Bug introduced by
It seems like $app defined by parameter $app on line 265 can also be of type false; however, OC\AppConfig::getAppValues() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
272
		} else {
273
			$appIds = $this->getApps();
274
			$values = array_map(function($appId) use ($key) {
275
				return isset($this->cache[$appId][$key]) ? $this->cache[$appId][$key] : null;
276
			}, $appIds);
277
			$result = array_combine($appIds, $values);
278
279
			return array_filter($result);
280
		}
281
	}
282
283
	/**
284
	 * get all values of the app or and filters out sensitive data
285
	 *
286
	 * @param string $app
287
	 * @return array
288
	 */
289
	public function getFilteredValues($app) {
290
		$values = $this->getValues($app, false);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression $this->getValues($app, false); of type false|array adds false to the return on line 298 which is incompatible with the return type declared by the interface OCP\IAppConfig::getFilteredValues of type array. It seems like you forgot to handle an error condition.
Loading history...
291
292
		foreach ($this->sensitiveValues[$app] as $sensitiveKey) {
293
			if (isset($values[$sensitiveKey])) {
294
				$values[$sensitiveKey] = IConfig::SENSITIVE_VALUE;
295
			}
296
		}
297
298
		return $values;
299
	}
300
301
	/**
302
	 * Load all the app config values
303
	 */
304
	protected function loadConfigValues() {
305
		if ($this->configLoaded) {
306
			return;
307
		}
308
309
		$this->cache = [];
310
311
		$sql = $this->conn->getQueryBuilder();
312
		$sql->select('*')
313
			->from('appconfig');
314
		$result = $sql->execute();
315
316
		// we are going to store the result in memory anyway
317
		$rows = $result->fetchAll();
318
		foreach ($rows as $row) {
319
			if (!isset($this->cache[$row['appid']])) {
320
				$this->cache[$row['appid']] = [];
321
			}
322
323
			$this->cache[$row['appid']][$row['configkey']] = $row['configvalue'];
324
		}
325
		$result->closeCursor();
326
327
		$this->configLoaded = true;
328
	}
329
}
330