Passed
Pull Request — master (#1038)
by René
04:02
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\InvalidUsernameException;
29
use OCA\Polls\Exceptions\InvalidEmailAddress;
30
31
use OCP\IGroupManager;
32
use OCP\IUserManager;
33
use OCA\Polls\Db\Share;
34
use OCA\Polls\Db\ShareMapper;
35
use OCA\Polls\Db\VoteMapper;
36
37
class SystemService {
38
39
	/** @var IGroupManager */
40
	private $groupManager;
41
42
	/** @var IUserManager */
43
	private $userManager;
44
45
	/** @var VoteMapper */
46
	private $voteMapper;
47
48
	/** @var ShareMapper */
49
	private $shareMapper;
50
51
	/**
52
	 * SystemService constructor.
53
	 * @param IGroupManager $groupManager
54
	 * @param IUserManager $userManager
55
	 * @param VoteMapper $voteMapper
56
	 * @param ShareMapper $shareMapper
57
	 */
58
	public function __construct(
59
		IGroupManager $groupManager,
60
		IUserManager $userManager,
61
		VoteMapper $voteMapper,
62
		ShareMapper $shareMapper
63
	) {
64
		$this->groupManager = $groupManager;
65
		$this->userManager = $userManager;
66
		$this->voteMapper = $voteMapper;
67
		$this->shareMapper = $shareMapper;
68
	}
69
70
	/**
71
	 * Validate string as email address
72
	 * @NoAdminRequired
73
	 * @param string $emailAddress
74
	 * @return bool
75
	 */
76
	private function isValidEmail($emailAddress) {
77
		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,}))$/', $emailAddress)) ? false : true;
78
	}
79
80
81
	/**
82
	 * Get a list of users
83
	 * @NoAdminRequired
84
	 * @param string $query
85
	 * @param array $skip - usernames to skip in return array
86
	 * @return Array
87
	 */
88
	public function getSiteUsers($query = '', $skip = []) {
89
		$users = [];
90
		foreach ($this->userManager->searchDisplayName($query) as $user) {
91
			if (!in_array($user->getUID(), $skip) && $user->isEnabled()) {
92
				$users[] = [
93
					'id' => $user->getUID(),
94
					'user' => $user->getUID(),
95
					'displayName' => $user->getDisplayName(),
96
					'organisation' => '',
97
					'emailAddress' => $user->getEMailAddress(),
98
					'desc' => 'User',
99
					'type' => 'user',
100
					'icon' => 'icon-user',
101
					'avatarURL' => '',
102
					'avatar' => '',
103
					'lastLogin' => $user->getLastLogin(),
104
					'cloudId' => $user->getCloudId()
105
				];
106
			}
107
		}
108
		return $users;
109
	}
110
111
	/**
112
	 * Get a list of user groups
113
	 * @NoAdminRequired
114
	 * @param string $query
115
	 * @param array $skip - group names to skip in return array
116
	 * @return Array
117
	 */
118
	public function getSiteGroups($query = '', $skip = []) {
119
		$groups = [];
120
		foreach ($this->groupManager->search($query) as $group) {
121
			if (!in_array($group->getGID(), $skip)) {
122
				try {
123
					// seems to work only from NC19 on
124
					$displayName = $group->getDisplayName();
125
				} catch (\Exception $e) {
126
					// fallback
127
					$displayName = $group->getGID();
128
				}
129
130
				$groups[] = [
131
					'id' => $group->getGID(),
132
					'user' => $group->getGID(),
133
					'organisation' => '',
134
					'displayName' => $displayName,
135
					'emailAddress' => '',
136
					'desc' => 'Group',
137
					'type' => 'group',
138
					'icon' => 'icon-group',
139
					'avatarURL' => '',
140
					'avatar' => '',
141
					'lastLogin' => '',
142
					'cloudId' => ''
143
144
				];
145
			}
146
		}
147
		return $groups;
148
	}
149
150
	/**
151
	 * Get a list of contacts
152
	 * @NoAdminRequired
153
	 * @param string $query
154
	 * @return Array
155
	 */
156
	public function getContacts($query = '') {
157
		$contacts = [];
158
		foreach (\OC::$server->getContactsManager()->search($query, ['FN', 'EMAIL', 'ORG', 'CATEGORIES']) as $contact) {
159
			if (!array_key_exists('isLocalSystemBook', $contact) && array_key_exists('EMAIL', $contact)) {
160
				$emailAdresses = $contact['EMAIL'];
161
162
				if (!is_array($emailAdresses)) {
163
					$emailAdresses = [$emailAdresses];
164
				} else {
165
					// take the first eMail address for now
166
					$emailAdresses = [$emailAdresses[0]];
167
				}
168
169
				foreach ($emailAdresses as $emailAddress) {
170
					$contacts[] = [
171
						'id' => $contact['UID'],
172
						'user' => $contact['FN'],
173
						'displayName' => $contact['FN'],
174
						'organisation' => isset($contact['ORG']) ? $contact['ORG'] : '',
175
						'emailAddress' => $emailAddress,
176
						'desc' => 'Contact',
177
						'type' => 'contact',
178
						'icon' => 'icon-mail',
179
						'avatarURL' => '',
180
						'avatar' => '',
181
						'lastLogin' => '',
182
						'cloudId' => '',
183
					];
184
				}
185
			}
186
		}
187
		return $contacts;
188
	}
189
190
	/**
191
	 * Get a list of contacts
192
	 * @NoAdminRequired
193
	 * @param string $query
194
	 * @return Array
195
	 */
196
	public function getContactsGroupMembers($query = '') {
197
		$contacts = [];
198
		foreach (\OC::$server->getContactsManager()->search($query, ['CATEGORIES']) as $contact) {
199
			if (
200
				   !array_key_exists('isLocalSystemBook', $contact)
201
				&& array_key_exists('EMAIL', $contact)
202
				&& in_array($query, explode(',', $contact['CATEGORIES']))
203
			) {
204
				$emailAdresses = $contact['EMAIL'];
205
206
				if (!is_array($emailAdresses)) {
207
					$emailAdresses = [$emailAdresses];
208
				} else {
209
					// take the first eMail address for now
210
					$emailAdresses = [$emailAdresses[0]];
211
				}
212
213
				foreach ($emailAdresses as $emailAddress) {
214
					$contacts[] = [
215
						'id' => $contact['UID'],
216
						'user' => $contact['FN'],
217
						'displayName' => $contact['FN'],
218
						'organisation' => isset($contact['ORG']) ? $contact['ORG'] : '',
219
						'emailAddress' => $emailAddress,
220
						'desc' => 'Contact',
221
						'type' => 'contact',
222
						'icon' => 'icon-mail',
223
						'avatarURL' => '',
224
						'avatar' => '',
225
						'lastLogin' => '',
226
						'cloudId' => '',
227
					];
228
				}
229
			}
230
		}
231
		return $contacts;
232
	}
233
234
	/**
235
	 * Get a list of contact groups
236
	 * @NoAdminRequired
237
	 * @param string $query
238
	 * @return Array
239
	 */
240
	public function getContactsGroups($query = '') {
241
		$contactGroups = [];
242
		$foundContacts = [];
243
244
		foreach (\OC::$server->getContactsManager()->search($query, ['CATEGORIES']) as $contact) {
245
			foreach (explode(',', $contact['CATEGORIES']) as $contactGroup) {
246
				if (strpos($contactGroup, $query) === 0 && !in_array($contactGroup, $foundContacts)) {
247
					$foundContacts[] = $contactGroup;
248
					$contactGroups[] = [
249
						'id' => 'contactgroup_' +$contactGroup,
250
						'user' => $contactGroup,
251
						'displayName' => $contactGroup,
252
						'organisation' => '',
253
						'emailAddress' => '',
254
						'desc' => 'Contact Group',
255
						'type' => 'contactGroup',
256
						'icon' => 'icon-group',
257
						'avatarURL' => '',
258
						'avatar' => '',
259
						'lastLogin' => '',
260
						'cloudId' => '',
261
					];
262
				};
263
			}
264
		}
265
		return $contactGroups;
266
	}
267
268
269
	/**
270
	 * Get a combined list of NC users, groups and contacts
271
	 * @NoAdminRequired
272
	 * @param string $query
273
	 * @param bool $getGroups - search in groups
274
	 * @param bool $getUsers - search in site users
275
	 * @param bool $getContacts - search in contacs
276
	 * @param bool $getContactGroups - search in contacs
277
	 * @param array $skipGroups - group names to skip in return array
278
	 * @param array $skipUsers - user names to skip in return array
279
	 * @return Array
280
	 */
281
	public function getSiteUsersAndGroups(
282
		$query = '',
283
		$getGroups = true,
284
		$getUsers = true,
285
		$getContacts = true,
286
		$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

286
		/** @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...
287
		$getMail = false,
288
		$skipGroups = [],
289
		$skipUsers = []
290
	) {
291
		$list = [];
292
293
		if ($getMail && $this->isValidEmail($query)) {
294
			$list[] = [
295
				'id' => '',
296
				'user' => '',
297
				'organisation' => '',
298
				'displayName' => '',
299
				'emailAddress' => $query,
300
				'desc' => $query,
301
				'type' => 'email',
302
				'icon' => 'icon-mail',
303
				'avatarURL' => '',
304
				'avatar' => '',
305
				'lastLogin' => '',
306
				'cloudId' => ''
307
308
			];
309
		}
310
		if ($getGroups) {
311
			$list = array_merge($list, $this->getSiteGroups($query, $skipGroups));
312
		}
313
314
		if ($getUsers) {
315
			$list = array_merge($list, $this->getSiteUsers($query, $skipUsers));
316
		}
317
318
		if (\OC::$server->getContactsManager()->isEnabled()) {
319
			if ($getContacts) {
320
				$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

320
				$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...
321
			}
322
323
			if ($getContacts) {
324
				$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

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