Completed
Push — master ( d4a0af...760b28 )
by Blizzz
25:12 queued 24:34
created

Group::delete()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 13
nop 0
dl 0
loc 21
rs 7.551
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 Lukas Reschke <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Robin McCorkell <[email protected]>
11
 * @author Roeland Jago Douma <[email protected]>
12
 * @author Vincent Petry <[email protected]>
13
 * @author John Molakvoæ <[email protected]>
14
 *
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OC\Group;
32
33
use OCP\IGroup;
34
use OCP\IUser;
35
use OCP\Group\Backend\ICountDisabledInGroup;
36
37
class Group implements IGroup {
38
	/** @var null|string  */
39
	protected $displayName;
40
41
	/**
42
	 * @var string $id
43
	 */
44
	private $gid;
45
46
	/**
47
	 * @var \OC\User\User[] $users
48
	 */
49
	private $users = array();
50
51
	/**
52
	 * @var bool $usersLoaded
53
	 */
54
	private $usersLoaded;
55
56
	/**
57
	 * @var \OC\Group\Backend[]|\OC\Group\Database[] $backend
58
	 */
59
	private $backends;
60
61
	/**
62
	 * @var \OC\Hooks\PublicEmitter $emitter
63
	 */
64
	private $emitter;
65
66
	/**
67
	 * @var \OC\User\Manager $userManager
68
	 */
69
	private $userManager;
70
71
	/**
72
	 * @param string $gid
73
	 * @param \OC\Group\Backend[] $backends
74
	 * @param \OC\User\Manager $userManager
75
	 * @param \OC\Hooks\PublicEmitter $emitter
76
	 * @param string $displayName
77
	 */
78
	public function __construct($gid, $backends, $userManager, $emitter = null, $displayName = null) {
79
		$this->gid = $gid;
80
		$this->backends = $backends;
81
		$this->userManager = $userManager;
82
		$this->emitter = $emitter;
83
		$this->displayName = $displayName;
84
	}
85
86
	public function getGID() {
87
		return $this->gid;
88
	}
89
90
	public function getDisplayName() {
91
		if (is_null($this->displayName)) {
92
			return $this->gid;
93
		}
94
		return $this->displayName;
95
	}
96
97
	/**
98
	 * get all users in the group
99
	 *
100
	 * @return \OC\User\User[]
101
	 */
102
	public function getUsers() {
103
		if ($this->usersLoaded) {
104
			return $this->users;
105
		}
106
107
		$userIds = array();
108
		foreach ($this->backends as $backend) {
109
			$diff = array_diff(
110
				$backend->usersInGroup($this->gid),
111
				$userIds
112
			);
113
			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...
114
				$userIds = array_merge($userIds, $diff);
115
			}
116
		}
117
118
		$this->users = $this->getVerifiedUsers($userIds);
119
		$this->usersLoaded = true;
120
		return $this->users;
121
	}
122
123
	/**
124
	 * check if a user is in the group
125
	 *
126
	 * @param IUser $user
127
	 * @return bool
128
	 */
129
	public function inGroup(IUser $user) {
130
		if (isset($this->users[$user->getUID()])) {
131
			return true;
132
		}
133
		foreach ($this->backends as $backend) {
134
			if ($backend->inGroup($user->getUID(), $this->gid)) {
135
				$this->users[$user->getUID()] = $user;
136
				return true;
137
			}
138
		}
139
		return false;
140
	}
141
142
	/**
143
	 * add a user to the group
144
	 *
145
	 * @param IUser $user
146
	 */
147
	public function addUser(IUser $user) {
148
		if ($this->inGroup($user)) {
149
			return;
150
		}
151
152
		if ($this->emitter) {
153
			$this->emitter->emit('\OC\Group', 'preAddUser', array($this, $user));
154
		}
155
		foreach ($this->backends as $backend) {
156
			if ($backend->implementsActions(\OC\Group\Backend::ADD_TO_GROUP)) {
157
				$backend->addToGroup($user->getUID(), $this->gid);
0 ignored issues
show
Bug introduced by
The method addToGroup() does not seem to exist on object<OC\Group\Backend>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
158
				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...
159
					$this->users[$user->getUID()] = $user;
160
				}
161
				if ($this->emitter) {
162
					$this->emitter->emit('\OC\Group', 'postAddUser', array($this, $user));
163
				}
164
				return;
165
			}
166
		}
167
	}
168
169
	/**
170
	 * remove a user from the group
171
	 *
172
	 * @param \OC\User\User $user
173
	 */
174
	public function removeUser($user) {
175
		$result = false;
176
		if ($this->emitter) {
177
			$this->emitter->emit('\OC\Group', 'preRemoveUser', array($this, $user));
178
		}
179
		foreach ($this->backends as $backend) {
180
			if ($backend->implementsActions(\OC\Group\Backend::REMOVE_FROM_GOUP) and $backend->inGroup($user->getUID(), $this->gid)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
181
				$backend->removeFromGroup($user->getUID(), $this->gid);
0 ignored issues
show
Bug introduced by
The method removeFromGroup() does not seem to exist on object<OC\Group\Backend>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
182
				$result = true;
183
			}
184
		}
185
		if ($result) {
186
			if ($this->emitter) {
187
				$this->emitter->emit('\OC\Group', 'postRemoveUser', array($this, $user));
188
			}
189
			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...
190
				foreach ($this->users as $index => $groupUser) {
191
					if ($groupUser->getUID() === $user->getUID()) {
192
						unset($this->users[$index]);
193
						return;
194
					}
195
				}
196
			}
197
		}
198
	}
199
200
	/**
201
	 * search for users in the group by userid
202
	 *
203
	 * @param string $search
204
	 * @param int $limit
205
	 * @param int $offset
206
	 * @return \OC\User\User[]
207
	 */
208 View Code Duplication
	public function searchUsers($search, $limit = null, $offset = null) {
209
		$users = array();
210
		foreach ($this->backends as $backend) {
211
			$userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
212
			$users += $this->getVerifiedUsers($userIds);
213
			if (!is_null($limit) and $limit <= 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
214
				return array_values($users);
215
			}
216
		}
217
		return array_values($users);
218
	}
219
220
	/**
221
	 * returns the number of users matching the search string
222
	 *
223
	 * @param string $search
224
	 * @return int|bool
225
	 */
226
	public function count($search = '') {
227
		$users = false;
228
		foreach ($this->backends as $backend) {
229
			if($backend->implementsActions(\OC\Group\Backend::COUNT_USERS)) {
230
				if($users === false) {
231
					//we could directly add to a bool variable, but this would
232
					//be ugly
233
					$users = 0;
234
				}
235
				$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...
236
			}
237
		}
238
		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...
239
	}
240
241
	/**
242
	 * returns the number of disabled users
243
	 *
244
	 * @return int|bool
245
	 */
246 View Code Duplication
	public function countDisabled() {
247
		$users = false;
248
		foreach ($this->backends as $backend) {
249
			if($backend instanceOf ICountDisabledInGroup) {
250
				if($users === false) {
251
					//we could directly add to a bool variable, but this would
252
					//be ugly
253
					$users = 0;
254
				}
255
				$users += $backend->countDisabledInGroup($this->gid);
256
			}
257
		}
258
		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::countDisabled of type integer|boolean as it can also be of type double which is not included in this return type.
Loading history...
259
	}
260
261
	/**
262
	 * search for users in the group by displayname
263
	 *
264
	 * @param string $search
265
	 * @param int $limit
266
	 * @param int $offset
267
	 * @return \OC\User\User[]
268
	 */
269 View Code Duplication
	public function searchDisplayName($search, $limit = null, $offset = null) {
270
		$users = array();
271
		foreach ($this->backends as $backend) {
272
			$userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
273
			$users = $this->getVerifiedUsers($userIds);
274
			if (!is_null($limit) and $limit <= 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
275
				return array_values($users);
276
			}
277
		}
278
		return array_values($users);
279
	}
280
281
	/**
282
	 * delete the group
283
	 *
284
	 * @return bool
285
	 */
286
	public function delete() {
287
		// Prevent users from deleting group admin
288
		if ($this->getGID() === 'admin') {
289
			return false;
290
		}
291
292
		$result = false;
293
		if ($this->emitter) {
294
			$this->emitter->emit('\OC\Group', 'preDelete', array($this));
295
		}
296
		foreach ($this->backends as $backend) {
297
			if ($backend->implementsActions(\OC\Group\Backend::DELETE_GROUP)) {
298
				$result = true;
299
				$backend->deleteGroup($this->gid);
0 ignored issues
show
Bug introduced by
The method deleteGroup() does not seem to exist on object<OC\Group\Backend>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
300
			}
301
		}
302
		if ($result and $this->emitter) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
303
			$this->emitter->emit('\OC\Group', 'postDelete', array($this));
304
		}
305
		return $result;
306
	}
307
308
	/**
309
	 * returns all the Users from an array that really exists
310
	 * @param string[] $userIds an array containing user IDs
311
	 * @return \OC\User\User[] an Array with the userId as Key and \OC\User\User as value
312
	 */
313
	private function getVerifiedUsers($userIds) {
314
		if (!is_array($userIds)) {
315
			return array();
316
		}
317
		$users = array();
318
		foreach ($userIds as $userId) {
319
			$user = $this->userManager->get($userId);
320
			if (!is_null($user)) {
321
				$users[$userId] = $user;
322
			}
323
		}
324
		return $users;
325
	}
326
}
327