Passed
Push — master ( 0da822...e25a62 )
by Morris
13:45 queued 10s
created

Setting::checkInput()   D

Complexity

Conditions 19
Paths 10

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 19
nc 10
nop 1
dl 0
loc 31
rs 4.5166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Kim Brose <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
26
namespace OC\Core\Command\User;
27
28
use OC\Core\Command\Base;
29
use OCP\IConfig;
30
use OCP\IDBConnection;
31
use OCP\IUser;
32
use OCP\IUserManager;
33
use Symfony\Component\Console\Input\InputArgument;
34
use Symfony\Component\Console\Input\InputInterface;
35
use Symfony\Component\Console\Input\InputOption;
36
use Symfony\Component\Console\Output\OutputInterface;
37
38
class Setting extends Base {
39
	/** @var IUserManager */
40
	protected $userManager;
41
42
	/** @var IConfig */
43
	protected $config;
44
45
	/** @var IDBConnection */
46
	protected $connection;
47
48
	/**
49
	 * @param IUserManager $userManager
50
	 * @param IConfig $config
51
	 * @param IDBConnection $connection
52
	 */
53
	public function __construct(IUserManager $userManager, IConfig $config, IDBConnection $connection) {
54
		parent::__construct();
55
		$this->userManager = $userManager;
56
		$this->config = $config;
57
		$this->connection = $connection;
58
	}
59
60
	protected function configure() {
61
		parent::configure();
62
		$this
63
			->setName('user:setting')
64
			->setDescription('Read and modify user settings')
65
			->addArgument(
66
				'uid',
67
				InputArgument::REQUIRED,
68
				'User ID used to login'
69
			)
70
			->addArgument(
71
				'app',
72
				InputArgument::OPTIONAL,
73
				'Restrict the settings to a given app',
74
				''
75
			)
76
			->addArgument(
77
				'key',
78
				InputArgument::OPTIONAL,
79
				'Setting key to set, get or delete',
80
				''
81
			)
82
			->addOption(
83
				'ignore-missing-user',
84
				null,
85
				InputOption::VALUE_NONE,
86
				'Use this option to ignore errors when the user does not exist'
87
			)
88
89
			// Get
90
			->addOption(
91
				'default-value',
92
				null,
93
				InputOption::VALUE_REQUIRED,
94
				'(Only applicable on get) If no default value is set and the config does not exist, the command will exit with 1'
95
			)
96
97
			// Set
98
			->addArgument(
99
				'value',
100
				InputArgument::OPTIONAL,
101
				'The new value of the setting',
102
				null
103
			)
104
			->addOption(
105
				'update-only',
106
				null,
107
				InputOption::VALUE_NONE,
108
				'Only updates the value, if it is not set before, it is not being added'
109
			)
110
111
			// Delete
112
			->addOption(
113
				'delete',
114
				null,
115
				InputOption::VALUE_NONE,
116
				'Specify this option to delete the config'
117
			)
118
			->addOption(
119
				'error-if-not-exists',
120
				null,
121
				InputOption::VALUE_NONE,
122
				'Checks whether the setting exists before deleting it'
123
			)
124
		;
125
	}
126
127
	protected function checkInput(InputInterface $input) {
128
		$uid = $input->getArgument('uid');
129
		if (!$input->getOption('ignore-missing-user') && !$this->userManager->userExists($uid)) {
130
			throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.');
0 ignored issues
show
Bug introduced by
Are you sure $uid of type null|string|string[] can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

130
			throw new \InvalidArgumentException('The user "' . /** @scrutinizer ignore-type */ $uid . '" does not exist.');
Loading history...
131
		}
132
133
		if ($input->getArgument('key') === '' && $input->hasParameterOption('--default-value')) {
134
			throw new \InvalidArgumentException('The "default-value" option can only be used when specifying a key.');
135
		}
136
137
		if ($input->getArgument('key') === '' && $input->getArgument('value') !== null) {
138
			throw new \InvalidArgumentException('The value argument can only be used when specifying a key.');
139
		}
140
		if ($input->getArgument('value') !== null && $input->hasParameterOption('--default-value')) {
141
			throw new \InvalidArgumentException('The value argument can not be used together with "default-value".');
142
		}
143
		if ($input->getOption('update-only') && $input->getArgument('value') === null) {
144
			throw new \InvalidArgumentException('The "update-only" option can only be used together with "value".');
145
		}
146
147
		if ($input->getArgument('key') === '' && $input->getOption('delete')) {
148
			throw new \InvalidArgumentException('The "delete" option can only be used when specifying a key.');
149
		}
150
		if ($input->getOption('delete') && $input->hasParameterOption('--default-value')) {
151
			throw new \InvalidArgumentException('The "delete" option can not be used together with "default-value".');
152
		}
153
		if ($input->getOption('delete') && $input->getArgument('value') !== null) {
154
			throw new \InvalidArgumentException('The "delete" option can not be used together with "value".');
155
		}
156
		if ($input->getOption('error-if-not-exists') && !$input->getOption('delete')) {
157
			throw new \InvalidArgumentException('The "error-if-not-exists" option can only be used together with "delete".');
158
		}
159
	}
160
161
	protected function execute(InputInterface $input, OutputInterface $output): int {
162
		try {
163
			$this->checkInput($input);
164
		} catch (\InvalidArgumentException $e) {
165
			$output->writeln('<error>' . $e->getMessage() . '</error>');
166
			return 1;
167
		}
168
169
		$uid = $input->getArgument('uid');
170
		$app = $input->getArgument('app');
171
		$key = $input->getArgument('key');
172
173
		if ($key !== '') {
174
			$value = $this->config->getUserValue($uid, $app, $key, null);
175
			if ($input->getArgument('value') !== null) {
176
				if ($input->hasParameterOption('--update-only') && $value === null) {
0 ignored issues
show
introduced by
The condition $value === null is always false.
Loading history...
177
					$output->writeln('<error>The setting does not exist for user "' . $uid . '".</error>');
178
					return 1;
179
				}
180
181
				if ($app === 'settings' && in_array($key , ['email', 'display_name'])) {
182
					$user = $this->userManager->get($uid);
183
					if ($user instanceof IUser) {
184
						if ($key === 'email') {
185
							$user->setEMailAddress($input->getArgument('value'));
186
						} elseif ($key === 'display_name') {
187
							if (!$user->setDisplayName($input->getArgument('value'))) {
188
								if ($user->getDisplayName() === $input->getArgument('value')) {
189
									$output->writeln('<error>New and old display name are the same</error>');
190
								} elseif ($input->getArgument('value') === '') {
191
									$output->writeln('<error>New display name can\'t be empty</error>');
192
								} else {
193
									$output->writeln('<error>Could not set display name</error>');
194
								}
195
								return 1;
196
							}
197
						}
198
						// setEmailAddress and setDisplayName both internally set the value
199
						return 0;
200
					}
201
				}
202
203
				$this->config->setUserValue($uid, $app, $key, $input->getArgument('value'));
204
				return 0;
205
			} elseif ($input->hasParameterOption('--delete')) {
206
				if ($input->hasParameterOption('--error-if-not-exists') && $value === null) {
0 ignored issues
show
introduced by
The condition $value === null is always false.
Loading history...
207
					$output->writeln('<error>The setting does not exist for user "' . $uid . '".</error>');
208
					return 1;
209
				}
210
211
				if ($app === 'settings' && in_array($key , ['email', 'display_name'])) {
212
					$user = $this->userManager->get($uid);
213
					if ($user instanceof IUser) {
214
						if ($key === 'email') {
215
							$user->setEMailAddress('');
216
							// setEmailAddress already deletes the value
217
							return 0;
218
						} elseif ($key === 'display_name') {
219
							$output->writeln('<error>Display name can\'t be deleted.</error>');
220
							return 1;
221
						}
222
					}
223
				}
224
225
				$this->config->deleteUserValue($uid, $app, $key);
226
				return 0;
227
			} elseif ($value !== null) {
0 ignored issues
show
introduced by
The condition $value !== null is always true.
Loading history...
228
				$output->writeln($value);
229
				return 0;
230
			} elseif ($input->hasParameterOption('--default-value')) {
231
				$output->writeln($input->getOption('default-value'));
232
				return 0;
233
			} else {
234
				if ($app === 'settings' && $key === 'display_name') {
235
					$user = $this->userManager->get($uid);
236
					$output->writeln($user->getDisplayName());
237
					return 0;
238
				}
239
				$output->writeln('<error>The setting does not exist for user "' . $uid . '".</error>');
240
				return 1;
241
			}
242
		} else {
243
			$settings = $this->getUserSettings($uid, $app);
244
			$this->writeArrayInOutputFormat($input, $output, $settings);
245
			return 0;
246
		}
247
	}
248
249
	protected function getUserSettings($uid, $app) {
250
		$query = $this->connection->getQueryBuilder();
251
		$query->select('*')
252
			->from('preferences')
253
			->where($query->expr()->eq('userid', $query->createNamedParameter($uid)));
254
255
		if ($app !== '') {
256
			$query->andWhere($query->expr()->eq('appid', $query->createNamedParameter($app)));
257
		}
258
259
		$result = $query->execute();
260
		$settings = [];
261
		while ($row = $result->fetch()) {
262
			$settings[$row['appid']][$row['configkey']] = $row['configvalue'];
263
		}
264
265
		$user = $this->userManager->get($uid);
266
		$settings['settings']['display_name'] = $user->getDisplayName();
267
268
		$result->closeCursor();
269
270
		return $settings;
271
	}
272
}
273