Completed
Push — stable8.2 ( 5bbf8e...95c815 )
by Roeland
59:14
created

Group   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 258
Duplicated Lines 8.53 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 87.02%
Metric Value
wmc 50
lcom 1
cbo 4
dl 22
loc 258
ccs 114
cts 131
cp 0.8702
rs 8.6206

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getGID() 0 3 1
A inGroup() 0 12 4
A searchUsers() 11 11 4
A count() 0 14 4
A searchDisplayName() 11 11 4
A __construct() 0 6 1
A getUsers() 0 20 4
B addUser() 0 21 7
B delete() 0 21 7
A getVerifiedUsers() 0 13 4
D removeUser() 0 25 10

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Group often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Group, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin Appelman <[email protected]>
9
 * @author Robin McCorkell <[email protected]>
10
 *
11
 * @copyright Copyright (c) 2015, ownCloud, Inc.
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
28
namespace OC\Group;
29
30
use OCP\IGroup;
31
32
class Group implements IGroup {
33
	/**
34
	 * @var string $id
35
	 */
36
	private $gid;
37
38
	/**
39
	 * @var \OC\User\User[] $users
40
	 */
41
	private $users = array();
42
43
	/**
44
	 * @var bool $usersLoaded
45
	 */
46
	private $usersLoaded;
47
48
	/**
49
	 * @var \OC_Group_Backend[]|\OC_Group_Database[] $backend
50
	 */
51
	private $backends;
52
53
	/**
54
	 * @var \OC\Hooks\PublicEmitter $emitter
55
	 */
56
	private $emitter;
57
58
	/**
59
	 * @var \OC\User\Manager $userManager
60
	 */
61
	private $userManager;
62
63
	/**
64
	 * @param string $gid
65
	 * @param \OC_Group_Backend[] $backends
66
	 * @param \OC\User\Manager $userManager
67
	 * @param \OC\Hooks\PublicEmitter $emitter
68
	 */
69 470
	public function __construct($gid, $backends, $userManager, $emitter = null) {
70 470
		$this->gid = $gid;
71 470
		$this->backends = $backends;
72 470
		$this->userManager = $userManager;
73 470
		$this->emitter = $emitter;
74 470
	}
75
76 477
	public function getGID() {
77 477
		return $this->gid;
78
	}
79
80
	/**
81
	 * get all users in the group
82
	 *
83
	 * @return \OC\User\User[]
84
	 */
85 4
	public function getUsers() {
86 4
		if ($this->usersLoaded) {
87
			return $this->users;
88
		}
89
90 4
		$userIds = array();
91 4
		foreach ($this->backends as $backend) {
92 4
			$diff = array_diff(
93 4
				$backend->usersInGroup($this->gid),
94
				$userIds
95 4
			);
96 4
			if ($diff) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $diff of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
97 4
				$userIds = array_merge($userIds, $diff);
98 4
			}
99 4
		}
100
101 4
		$this->users = $this->getVerifiedUsers($userIds);
102 4
		$this->usersLoaded = true;
103 4
		return $this->users;
104
	}
105
106
	/**
107
	 * check if a user is in the group
108
	 *
109
	 * @param \OC\User\User $user
110
	 * @return bool
111
	 */
112 435
	public function inGroup($user) {
113 435
		if (isset($this->users[$user->getUID()])) {
114 4
			return true;
115
		}
116 435
		foreach ($this->backends as $backend) {
117 435
			if ($backend->inGroup($user->getUID(), $this->gid)) {
118 20
				$this->users[$user->getUID()] = $user;
119 20
				return true;
120
			}
121 432
		}
122 431
		return false;
123
	}
124
125
	/**
126
	 * add a user to the group
127
	 *
128
	 * @param \OC\User\User $user
129
	 */
130 420
	public function addUser($user) {
131 420
		if ($this->inGroup($user)) {
132 3
			return;
133
		}
134
135 419
		if ($this->emitter) {
136 418
			$this->emitter->emit('\OC\Group', 'preAddUser', array($this, $user));
137 418
		}
138 419
		foreach ($this->backends as $backend) {
139 419
			if ($backend->implementsActions(\OC_Group_Backend::ADD_TO_GROUP)) {
140 419
				$backend->addToGroup($user->getUID(), $this->gid);
141 419
				if ($this->users) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->users of type OC\User\User[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
142
					$this->users[$user->getUID()] = $user;
143
				}
144 419
				if ($this->emitter) {
145 418
					$this->emitter->emit('\OC\Group', 'postAddUser', array($this, $user));
146 418
				}
147 419
				return;
148
			}
149
		}
150
	}
151
152
	/**
153
	 * remove a user from the group
154
	 *
155
	 * @param \OC\User\User $user
156
	 */
157 410
	public function removeUser($user) {
158 410
		$result = false;
159 410
		if ($this->emitter) {
160 407
			$this->emitter->emit('\OC\Group', 'preRemoveUser', array($this, $user));
161 407
		}
162 410
		foreach ($this->backends as $backend) {
163 410
			if ($backend->implementsActions(\OC_Group_Backend::REMOVE_FROM_GOUP) and $backend->inGroup($user->getUID(), $this->gid)) {
164 409
				$backend->removeFromGroup($user->getUID(), $this->gid);
165 409
				$result = true;
166 409
			}
167 410
		}
168 410
		if ($result) {
169 409
			if ($this->emitter) {
170 407
				$this->emitter->emit('\OC\Group', 'postRemoveUser', array($this, $user));
171 407
			}
172 409
			if ($this->users) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->users of type OC\User\User[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
173 7
				foreach ($this->users as $index => $groupUser) {
174 7
					if ($groupUser->getUID() === $user->getUID()) {
175 7
						unset($this->users[$index]);
176 7
						return;
177
					}
178
				}
179
			}
180 403
		}
181 404
	}
182
183
	/**
184
	 * search for users in the group by userid
185
	 *
186
	 * @param string $search
187
	 * @param int $limit
188
	 * @param int $offset
189
	 * @return \OC\User\User[]
190
	 */
191 36 View Code Duplication
	public function searchUsers($search, $limit = null, $offset = null) {
192 36
		$users = array();
193 36
		foreach ($this->backends as $backend) {
194 36
			$userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
195 36
			$users += $this->getVerifiedUsers($userIds);
196 36
			if (!is_null($limit) and $limit <= 0) {
197 30
				return array_values($users);
198
			}
199 6
		}
200 6
		return array_values($users);
201
	}
202
203
	/**
204
	 * returns the number of users matching the search string
205
	 *
206
	 * @param string $search
207
	 * @return int|bool
208
	 */
209 3
	public function count($search = '') {
210 3
		$users = false;
211 3
		foreach ($this->backends as $backend) {
212 3
			if($backend->implementsActions(\OC_Group_Backend::COUNT_USERS)) {
213 2
				if($users === false) {
214
					//we could directly add to a bool variable, but this would
215
					//be ugly
216 2
					$users = 0;
217 2
				}
218 2
				$users += $backend->countUsersInGroup($this->gid, $search);
0 ignored issues
show
Bug introduced by
The method countUsersInGroup() does not exist on OC_Group_Backend. Did you maybe mean inGroup()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
219 2
			}
220 3
		}
221 3
		return $users;
0 ignored issues
show
Bug Compatibility introduced by
The expression return $users; of type integer|double|false is incompatible with the return type declared by the interface OCP\IGroup::count of type integer|boolean as it can also be of type double which is not included in this return type.
Loading history...
222
	}
223
224
	/**
225
	 * search for users in the group by displayname
226
	 *
227
	 * @param string $search
228
	 * @param int $limit
229
	 * @param int $offset
230
	 * @return \OC\User\User[]
231
	 */
232 View Code Duplication
	public function searchDisplayName($search, $limit = null, $offset = null) {
233
		$users = array();
234
		foreach ($this->backends as $backend) {
235
			$userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
236
			$users = $this->getVerifiedUsers($userIds);
237
			if (!is_null($limit) and $limit <= 0) {
238
				return array_values($users);
239
			}
240
		}
241
		return array_values($users);
242
	}
243
244
	/**
245
	 * delete the group
246
	 *
247
	 * @return bool
248
	 */
249 458
	public function delete() {
250
		// Prevent users from deleting group admin
251 458
		if ($this->getGID() === 'admin') {
252 87
			return false;
253
		}
254
255 397
		$result = false;
256 397
		if ($this->emitter) {
257 396
			$this->emitter->emit('\OC\Group', 'preDelete', array($this));
258 396
		}
259 397
		foreach ($this->backends as $backend) {
260 397
			if ($backend->implementsActions(\OC_Group_Backend::DELETE_GROUP)) {
261 397
				$result = true;
262 397
				$backend->deleteGroup($this->gid);
263 397
			}
264 397
		}
265 397
		if ($result and $this->emitter) {
266 396
			$this->emitter->emit('\OC\Group', 'postDelete', array($this));
267 396
		}
268 397
		return $result;
269
	}
270
271
	/**
272
	 * returns all the Users from an array that really exists
273
	 * @param string[] $userIds an array containing user IDs
274
	 * @return \OC\User\User[] an Array with the userId as Key and \OC\User\User as value
275
	 */
276 40
	private function getVerifiedUsers($userIds) {
277 40
		if (!is_array($userIds)) {
278
			return array();
279
		}
280 40
		$users = array();
281 40
		foreach ($userIds as $userId) {
282 40
			$user = $this->userManager->get($userId);
283 40
			if (!is_null($user)) {
284 40
				$users[$userId] = $user;
285 40
			}
286 40
		}
287 40
		return $users;
288
	}
289
}
290