Completed
Pull Request — master (#1038)
by René
06:20
created

SystemService::getSiteUsersAndGroups()   B

Complexity

Conditions 8
Paths 40

Size

Total Lines 48
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 25
c 1
b 0
f 1
dl 0
loc 48
ccs 0
cts 42
cp 0
rs 8.4444
cc 8
nc 40
nop 8
crap 72

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
4
 *
5
 * @author René Gieling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Polls\Service;
25
26
use OCA\Polls\Exceptions\NotAuthorizedException;
27
use OCA\Polls\Exceptions\TooShortException;
28
use OCA\Polls\Exceptions\UsernameInvalidException;
29
30
use OCP\IGroupManager;
31
use OCP\IUserManager;
32
use OCA\Polls\Db\Share;
33
use OCA\Polls\Db\ShareMapper;
34
use OCA\Polls\Db\VoteMapper;
35
36
class SystemService {
37
38
	/** @var IGroupManager */
39
	private $groupManager;
40
41
	/** @var IUserManager */
42
	private $userManager;
43
44
	/** @var VoteMapper */
45
	private $voteMapper;
46
47
	/** @var ShareMapper */
48
	private $shareMapper;
49
50
	/**
51
	 * SystemService constructor.
52
	 * @param IGroupManager $groupManager
53
	 * @param IUserManager $userManager
54
	 * @param VoteMapper $voteMapper
55
	 * @param ShareMapper $shareMapper
56
	 */
57
	public function __construct(
58
		IGroupManager $groupManager,
59
		IUserManager $userManager,
60
		VoteMapper $voteMapper,
61
		ShareMapper $shareMapper
62
	) {
63
		$this->groupManager = $groupManager;
64
		$this->userManager = $userManager;
65
		$this->voteMapper = $voteMapper;
66
		$this->shareMapper = $shareMapper;
67
	}
68
69
	/**
70
	 * Validate string as email address
71
	 * @NoAdminRequired
72
	 * @param string $query
73
	 * @return bool
74
	 */
75
	private function isValidEmail($email) {
76
		return (!preg_match('/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/', $email)) ? false : true;
77
	}
78
79
80
	/**
81
	 * Get a list of users
82
	 * @NoAdminRequired
83
	 * @param string $query
84
	 * @param array $skip - usernames to skip in return array
85
	 * @return Array
86
	 */
87
	public function getSiteUsers($query = '', $skip = []) {
88
		$users = [];
89
		foreach ($this->userManager->searchDisplayName($query) as $user) {
90
			if (!in_array($user->getUID(), $skip) && $user->isEnabled()) {
91
				$users[] = [
92
					'id' => $user->getUID(),
93
					'user' => $user->getUID(),
94
					'displayName' => $user->getDisplayName(),
95
					'organisation' => '',
96
					'emailAddress' => $user->getEMailAddress(),
97
					'desc' => 'User',
98
					'type' => 'user',
99
					'icon' => 'icon-user',
100
					'avatarURL' => '',
101
					'avatar' => '',
102
					'lastLogin' => $user->getLastLogin(),
103
					'cloudId' => $user->getCloudId()
104
				];
105
			}
106
		}
107
		return $users;
108
	}
109
110
	/**
111
	 * Get a list of user groups
112
	 * @NoAdminRequired
113
	 * @param string $query
114
	 * @param array $skip - group names to skip in return array
115
	 * @return Array
116
	 */
117
	public function getSiteGroups($query = '', $skip = []) {
118
		$groups = [];
119
		foreach ($this->groupManager->search($query) as $group) {
120
			if (!in_array($group->getGID(), $skip)) {
121
				try {
122
					// seems to work only from NC19 on
123
					$displayName = $group->getDisplayName();
124
				} catch (\Exception $e) {
125
					// fallback
126
					$displayName = $group->getGID();
127
				}
128
129
				$groups[] = [
130
					'id' => $group->getGID(),
131
					'user' => $group->getGID(),
132
					'organisation' => '',
133
					'displayName' => $displayName,
134
					'emailAddress' => '',
135
					'desc' => 'Group',
136
					'type' => 'group',
137
					'icon' => 'icon-group',
138
					'avatarURL' => '',
139
					'avatar' => '',
140
					'lastLogin' => '',
141
					'cloudId' => ''
142
143
				];
144
			}
145
		}
146
		return $groups;
147
	}
148
149
	/**
150
	 * Get a list of contacts
151
	 * @NoAdminRequired
152
	 * @param string $query
153
	 * @return Array
154
	 */
155
	public function getContacts($query = '') {
156
		$contacts = [];
157
		foreach (\OC::$server->getContactsManager()->search($query, ['FN', 'EMAIL', 'ORG', 'CATEGORIES']) as $contact) {
158
			if (!array_key_exists('isLocalSystemBook', $contact) && array_key_exists('EMAIL', $contact)) {
159
				$emailAdresses = $contact['EMAIL'];
160
161
				if (!is_array($emailAdresses)) {
162
					$emailAdresses = [$emailAdresses];
163
				} else {
164
					// take the first eMail address for now
165
					$emailAdresses = [$emailAdresses[0]];
166
				}
167
168
				foreach ($emailAdresses as $emailAddress) {
169
					$contacts[] = [
170
						'id' => $contact['UID'],
171
						'user' => $contact['FN'],
172
						'displayName' => $contact['FN'],
173
						'organisation' => isset($contact['ORG']) ? $contact['ORG'] : '',
174
						'emailAddress' => $emailAddress,
175
						'desc' => 'Contact',
176
						'type' => 'contact',
177
						'icon' => 'icon-mail',
178
						'avatarURL' => '',
179
						'avatar' => '',
180
						'lastLogin' => '',
181
						'cloudId' => '',
182
					];
183
				}
184
			}
185
		}
186
		return $contacts;
187
	}
188
189
	/**
190
	 * Get a list of contacts
191
	 * @NoAdminRequired
192
	 * @param string $query
193
	 * @return Array
194
	 */
195
	public function getContactsGroupMembers($query = '') {
196
		$contacts = [];
197
		foreach (\OC::$server->getContactsManager()->search($query, ['CATEGORIES']) as $contact) {
198
			if (
199
				   !array_key_exists('isLocalSystemBook', $contact)
200
				&& array_key_exists('EMAIL', $contact)
201
				&& in_array($query, explode(',', $contact['CATEGORIES']))
202
			) {
203
				$emailAdresses = $contact['EMAIL'];
204
205
				if (!is_array($emailAdresses)) {
206
					$emailAdresses = [$emailAdresses];
207
				} else {
208
					// take the first eMail address for now
209
					$emailAdresses = [$emailAdresses[0]];
210
				}
211
212
				foreach ($emailAdresses as $emailAddress) {
213
					$contacts[] = [
214
						'id' => $contact['UID'],
215
						'user' => $contact['FN'],
216
						'displayName' => $contact['FN'],
217
						'organisation' => isset($contact['ORG']) ? $contact['ORG'] : '',
218
						'emailAddress' => $emailAddress,
219
						'desc' => 'Contact',
220
						'type' => 'contact',
221
						'icon' => 'icon-mail',
222
						'avatarURL' => '',
223
						'avatar' => '',
224
						'lastLogin' => '',
225
						'cloudId' => '',
226
					];
227
				}
228
			}
229
		}
230
		return $contacts;
231
	}
232
233
	/**
234
	 * Get a list of contact groups
235
	 * @NoAdminRequired
236
	 * @param string $query
237
	 * @return Array
238
	 */
239
	public function getContactsGroups($query = '') {
240
		$contactGroups = [];
241
		$foundContacts = [];
242
243
		foreach (\OC::$server->getContactsManager()->search($query, ['CATEGORIES']) as $contact) {
244
			foreach (explode(',', $contact['CATEGORIES']) as $contactGroup) {
245
				if (strpos($contactGroup, $query) === 0 && !in_array($contactGroup, $foundContacts)) {
246
					$foundContacts[] = $contactGroup;
247
					$contactGroups[] = [
248
						'id' => 'contactgroup_' +$contactGroup,
249
						'user' => $contactGroup,
250
						'displayName' => $contactGroup,
251
						'organisation' => '',
252
						'emailAddress' => '',
253
						'desc' => 'Contact Group',
254
						'type' => 'contactGroup',
255
						'icon' => 'icon-group',
256
						'avatarURL' => '',
257
						'avatar' => '',
258
						'lastLogin' => '',
259
						'cloudId' => '',
260
					];
261
				};
262
			}
263
		}
264
		return $contactGroups;
265
	}
266
267
268
	/**
269
	 * Get a combined list of NC users, groups and contacts
270
	 * @NoAdminRequired
271
	 * @param string $query
272
	 * @param bool $getGroups - search in groups
273
	 * @param bool $getUsers - search in site users
274
	 * @param bool $getContacts - search in contacs
275
	 * @param bool $getContactGroups - search in contacs
276
	 * @param array $skipGroups - group names to skip in return array
277
	 * @param array $skipUsers - user names to skip in return array
278
	 * @return Array
279
	 */
280
	public function getSiteUsersAndGroups(
281
		$query = '',
282
		$getGroups = true,
283
		$getUsers = true,
284
		$getContacts = true,
285
		$getContactGroups = true,
0 ignored issues
show
Unused Code introduced by
The parameter $getContactGroups is not used and could be removed. ( Ignorable by Annotation )

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

285
		/** @scrutinizer ignore-unused */ $getContactGroups = true,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
286
		$getMail = false,
287
		$skipGroups = [],
288
		$skipUsers = []
289
	) {
290
		$list = [];
291
292
		if ($getMail && $this->isValidEmail($query)) {
293
			$list[] = [
294
				'id' => '',
295
				'user' => '',
296
				'organisation' => '',
297
				'displayName' => '',
298
				'emailAddress' => $query,
299
				'desc' => $query,
300
				'type' => 'email',
301
				'icon' => 'icon-mail',
302
				'avatarURL' => '',
303
				'avatar' => '',
304
				'lastLogin' => '',
305
				'cloudId' => ''
306
307
			];
308
		}
309
		if ($getGroups) {
310
			$list = array_merge($list, $this->getSiteGroups($query, $skipGroups));
311
		}
312
313
		if ($getUsers) {
314
			$list = array_merge($list, $this->getSiteUsers($query, $skipUsers));
315
		}
316
317
		if (\OC::$server->getContactsManager()->isEnabled()) {
318
			if ($getContacts) {
319
				$list = array_merge($list, $this->getContacts($query, $skipUsers));
0 ignored issues
show
Unused Code introduced by
The call to OCA\Polls\Service\SystemService::getContacts() has too many arguments starting with $skipUsers. ( Ignorable by Annotation )

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

319
				$list = array_merge($list, $this->/** @scrutinizer ignore-call */ getContacts($query, $skipUsers));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
320
			}
321
322
			if ($getContacts) {
323
				$list = array_merge($list, $this->getContactsGroups($query, $skipGroups));
0 ignored issues
show
Unused Code introduced by
The call to OCA\Polls\Service\System...ce::getContactsGroups() has too many arguments starting with $skipGroups. ( Ignorable by Annotation )

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

323
				$list = array_merge($list, $this->/** @scrutinizer ignore-call */ getContactsGroups($query, $skipGroups));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
324
			}
325
		}
326
327
		return $list;
328
	}
329
330
	/**
331
	 * Validate it the user name is reservrd
332
	 * return false, if this username already exists as a user or as
333
	 * a participant of the poll
334
	 * @NoAdminRequired
335
	 * @return Boolean
336
	 * @throws NotAuthorizedException
337
	 * @throws TooShortException
338
	 * @throws UsernameInvalidException
339
	 */
340
	public function validatePublicUsername($pollId, $userName, $token) {
341
342
		// return forbidden, if $pollId does not match the share's pollId, force int compare
343
		if (intval($this->shareMapper->findByToken($token)->getPollId()) !== intVal($pollId)) {
344
			throw new NotAuthorizedException;
345
		}
346
347
		// return forbidden, if the length of the userame is lower than 3 characters
348
		if (strlen(trim($userName)) < 3) {
349
			return new TooShortException('Username must have at least 3 characters');
350
		}
351
352
		$list = [];
353
354
		// get all groups
355
		$groups = $this->groupManager->search('');
356
		foreach ($groups as $group) {
357
			$list[] = [
358
				'id' => $group->getGID(),
359
				'user' => $group->getGID(),
360
				'type' => 'group',
361
				'displayName' => $group->getGID(),
362
			];
363
		}
364
365
		// get all users
366
		$users = $this->userManager->searchDisplayName('');
367
		foreach ($users as $user) {
368
			$list[] = [
369
				'id' => $user->getUID(),
370
				'user' => $user->getUID(),
371
				'type' => 'user',
372
				'displayName' => $user->getDisplayName(),
373
			];
374
		}
375
376
		// get all participants
377
		$votes = $this->voteMapper->findParticipantsByPoll($pollId);
378
		foreach ($votes as $vote) {
379
			if ($vote->getUserId() !== '' && $vote->getUserId() !== null) {
380
				$list[] = [
381
					'id' => $vote->getUserId(),
382
					'user' => $vote->getUserId(),
383
					'type' => 'participant',
384
					'displayName' => $vote->getUserId(),
385
				];
386
			}
387
		}
388
389
		// get all shares for this poll
390
		$shares = $this->shareMapper->findByPoll($pollId);
391
		foreach ($shares as $share) {
392
			if ($share->getUserId() !== '' && $share->getUserId() !== null) {
393
				$list[] = [
394
					'id' => $share->getUserId(),
395
					'user' => $share->getUserId(),
396
					'type' => 'share',
397
					'displayName' => $share->getUserId(),
398
				];
399
			}
400
		}
401
402
		// check if the username is contained inside the generated list
403
		// return forbidden, if list contains requested username
404
		foreach ($list as $element) {
405
			if (strtolower(trim($userName)) === strtolower(trim($element['id'])) || strtolower(trim($userName)) === strtolower(trim($element['displayName']))) {
406
				throw new UsernameInvalidException;
407
			}
408
		}
409
410
		// return true, if username is allowed
411
		return true;
412
	}
413
}
414