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

Database   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 355
Duplicated Lines 15.49 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 55
loc 355
rs 10
c 0
b 0
f 0
wmc 28
lcom 1
cbo 6

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A fixDI() 0 5 2
A createGroup() 0 13 1
B deleteGroup() 0 26 1
A inGroup() 16 16 2
A addToGroup() 0 15 2
A removeFromGroup() 0 11 1
B getUserGroups() 0 24 4
B getGroups() 5 26 3
A groupExists() 0 22 3
B usersInGroup() 5 27 3
B countUsersInGroup() 5 26 3
B countDisabledInGroup() 24 24 2

How to fix   Duplicated Code   

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:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Aaron Wood <[email protected]>
6
 * @author Loki3000 <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 * @author John Molakvoæ <[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
 *
27
 * The following SQL statement is just a help for developers and will not be
28
 * executed!
29
 *
30
 * CREATE TABLE `groups` (
31
 *   `gid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
32
 *   PRIMARY KEY (`gid`)
33
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
34
 *
35
 * CREATE TABLE `group_user` (
36
 *   `gid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
37
 *   `uid` varchar(64) COLLATE utf8_unicode_ci NOT NULL
38
 * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
39
 *
40
 */
41
42
namespace OC\Group;
43
44
use OCP\DB\QueryBuilder\IQueryBuilder;
45
use OCP\Group\Backend\ABackend;
46
use OCP\Group\Backend\IAddToGroupBackend;
47
use OCP\Group\Backend\ICountDisabledInGroup;
48
use OCP\Group\Backend\ICountUsersBackend;
49
use OCP\Group\Backend\ICreateGroupBackend;
50
use OCP\Group\Backend\IDeleteGroupBackend;
51
use OCP\Group\Backend\IRemoveFromGroupBackend;
52
use OCP\IDBConnection;
53
54
/**
55
 * Class for group management in a SQL Database (e.g. MySQL, SQLite)
56
 */
57
class Database extends ABackend
0 ignored issues
show
Coding Style introduced by
Expected 0 spaces between "ABackend" and comma; 1 found
Loading history...
58
	implements IAddToGroupBackend,
0 ignored issues
show
Coding Style introduced by
The implements keyword must be on the same line as the class name
Loading history...
Coding Style introduced by
The first item in a multi-line implements list must be on the line following the implements keyword
Loading history...
59
	           ICountDisabledInGroup,
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 12 found
Loading history...
60
	           ICountUsersBackend,
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 12 found
Loading history...
61
	           ICreateGroupBackend,
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 12 found
Loading history...
62
	           IDeleteGroupBackend,
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 12 found
Loading history...
63
	           IRemoveFromGroupBackend {
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 12 found
Loading history...
64
65
	/** @var string[] */
66
	private $groupCache = [];
67
68
	/** @var IDBConnection */
69
	private $dbConn;
70
71
	/**
72
	 * \OC\Group\Database constructor.
73
	 *
74
	 * @param IDBConnection|null $dbConn
75
	 */
76
	public function __construct(IDBConnection $dbConn = null) {
77
		$this->dbConn = $dbConn;
78
	}
79
80
	/**
81
	 * FIXME: This function should not be required!
82
	 */
83
	private function fixDI() {
84
		if ($this->dbConn === null) {
85
			$this->dbConn = \OC::$server->getDatabaseConnection();
86
		}
87
	}
88
89
	/**
90
	 * Try to create a new group
91
	 * @param string $gid The name of the group to create
92
	 * @return bool
93
	 *
94
	 * Tries to create a new group. If the group name already exists, false will
95
	 * be returned.
96
	 */
97
	public function createGroup(string $gid): bool {
98
		$this->fixDI();
99
100
		// Add group
101
		$result = $this->dbConn->insertIfNotExist('*PREFIX*groups', [
102
			'gid' => $gid,
103
		]);
104
105
		// Add to cache
106
		$this->groupCache[$gid] = $gid;
107
108
		return $result === 1;
109
	}
110
111
	/**
112
	 * delete a group
113
	 * @param string $gid gid of the group to delete
114
	 * @return bool
115
	 *
116
	 * Deletes a group and removes it from the group_user-table
117
	 */
118
	public function deleteGroup(string $gid): bool {
119
		$this->fixDI();
120
121
		// Delete the group
122
		$qb = $this->dbConn->getQueryBuilder();
123
		$qb->delete('groups')
124
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
125
			->execute();
126
127
		// Delete the group-user relation
128
		$qb = $this->dbConn->getQueryBuilder();
129
		$qb->delete('group_user')
130
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
131
			->execute();
132
133
		// Delete the group-groupadmin relation
134
		$qb = $this->dbConn->getQueryBuilder();
135
		$qb->delete('group_admin')
136
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
137
			->execute();
138
139
		// Delete from cache
140
		unset($this->groupCache[$gid]);
141
142
		return true;
143
	}
144
145
	/**
146
	 * is user in group?
147
	 * @param string $uid uid of the user
148
	 * @param string $gid gid of the group
149
	 * @return bool
150
	 *
151
	 * Checks whether the user is member of a group or not.
152
	 */
153 View Code Duplication
	public function inGroup( $uid, $gid ) {
154
		$this->fixDI();
155
156
		// check
157
		$qb = $this->dbConn->getQueryBuilder();
158
		$cursor = $qb->select('uid')
159
			->from('group_user')
160
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
161
			->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
162
			->execute();
163
164
		$result = $cursor->fetch();
165
		$cursor->closeCursor();
166
167
		return $result ? true : false;
168
	}
169
170
	/**
171
	 * Add a user to a group
172
	 * @param string $uid Name of the user to add to group
173
	 * @param string $gid Name of the group in which add the user
174
	 * @return bool
175
	 *
176
	 * Adds a user to a group.
177
	 */
178
	public function addToGroup(string $uid, string $gid): bool {
179
		$this->fixDI();
180
181
		// No duplicate entries!
182
		if( !$this->inGroup( $uid, $gid )) {
183
			$qb = $this->dbConn->getQueryBuilder();
184
			$qb->insert('group_user')
185
				->setValue('uid', $qb->createNamedParameter($uid))
186
				->setValue('gid', $qb->createNamedParameter($gid))
187
				->execute();
188
			return true;
189
		}else{
190
			return false;
191
		}
192
	}
193
194
	/**
195
	 * Removes a user from a group
196
	 * @param string $uid Name of the user to remove from group
197
	 * @param string $gid Name of the group from which remove the user
198
	 * @return bool
199
	 *
200
	 * removes the user from a group.
201
	 */
202
	public function removeFromGroup(string $uid, string $gid): bool {
203
		$this->fixDI();
204
205
		$qb = $this->dbConn->getQueryBuilder();
206
		$qb->delete('group_user')
207
			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
208
			->andWhere($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
209
			->execute();
210
211
		return true;
212
	}
213
214
	/**
215
	 * Get all groups a user belongs to
216
	 * @param string $uid Name of the user
217
	 * @return array an array of group names
218
	 *
219
	 * This function fetches all groups a user belongs to. It does not check
220
	 * if the user exists at all.
221
	 */
222
	public function getUserGroups( $uid ) {
223
		//guests has empty or null $uid
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
224
		if ($uid === null || $uid === '') {
225
			return [];
226
		}
227
228
		$this->fixDI();
229
230
		// No magic!
231
		$qb = $this->dbConn->getQueryBuilder();
232
		$cursor = $qb->select('gid')
233
			->from('group_user')
234
			->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
235
			->execute();
236
237
		$groups = [];
238
		while( $row = $cursor->fetch()) {
239
			$groups[] = $row['gid'];
240
			$this->groupCache[$row['gid']] = $row['gid'];
241
		}
242
		$cursor->closeCursor();
243
244
		return $groups;
245
	}
246
247
	/**
248
	 * get a list of all groups
249
	 * @param string $search
250
	 * @param int $limit
251
	 * @param int $offset
252
	 * @return array an array of group names
253
	 *
254
	 * Returns a list with all groups
255
	 */
256
	public function getGroups($search = '', $limit = null, $offset = null) {
257
		$this->fixDI();
258
259
		$query = $this->dbConn->getQueryBuilder();
260
		$query->select('gid')
261
			->from('groups')
262
			->orderBy('gid', 'ASC');
263
264 View Code Duplication
		if ($search !== '') {
265
			$query->where($query->expr()->iLike('gid', $query->createNamedParameter(
266
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
267
			)));
268
		}
269
270
		$query->setMaxResults($limit)
271
			->setFirstResult($offset);
272
		$result = $query->execute();
273
274
		$groups = [];
275
		while ($row = $result->fetch()) {
276
			$groups[] = $row['gid'];
277
		}
278
		$result->closeCursor();
279
280
		return $groups;
281
	}
282
283
	/**
284
	 * check if a group exists
285
	 * @param string $gid
286
	 * @return bool
287
	 */
288
	public function groupExists($gid) {
289
		$this->fixDI();
290
291
		// Check cache first
292
		if (isset($this->groupCache[$gid])) {
293
			return true;
294
		}
295
296
		$qb = $this->dbConn->getQueryBuilder();
297
		$cursor = $qb->select('gid')
298
			->from('groups')
299
			->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid)))
300
			->execute();
301
		$result = $cursor->fetch();
302
		$cursor->closeCursor();
303
304
		if ($result !== false) {
305
			$this->groupCache[$gid] = $gid;
306
			return true;
307
		}
308
		return false;
309
	}
310
311
	/**
312
	 * get a list of all users in a group
313
	 * @param string $gid
314
	 * @param string $search
315
	 * @param int $limit
316
	 * @param int $offset
317
	 * @return array an array of user ids
318
	 */
319
	public function usersInGroup($gid, $search = '', $limit = null, $offset = null) {
320
		$this->fixDI();
321
322
		$query = $this->dbConn->getQueryBuilder();
323
		$query->select('uid')
324
			->from('group_user')
325
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
326
			->orderBy('uid', 'ASC');
327
328 View Code Duplication
		if ($search !== '') {
329
			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
330
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
331
			)));
332
		}
333
334
		$query->setMaxResults($limit)
335
			->setFirstResult($offset);
336
		$result = $query->execute();
337
338
		$users = [];
339
		while ($row = $result->fetch()) {
340
			$users[] = $row['uid'];
341
		}
342
		$result->closeCursor();
343
344
		return $users;
345
	}
346
347
	/**
348
	 * get the number of all users matching the search string in a group
349
	 * @param string $gid
350
	 * @param string $search
351
	 * @return int
352
	 */
353
	public function countUsersInGroup(string $gid, string $search = ''): int {
354
		$this->fixDI();
355
356
		$query = $this->dbConn->getQueryBuilder();
357
		$query->selectAlias($query->createFunction('COUNT(*)'), 'num_users')
358
			->from('group_user')
359
			->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
360
361 View Code Duplication
		if ($search !== '') {
362
			$query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
363
				'%' . $this->dbConn->escapeLikeParameter($search) . '%'
364
			)));
365
		}
366
367
		$result = $query->execute();
368
		$count = $result->fetchColumn();
369
		$result->closeCursor();
370
371
		if ($count !== false) {
372
			$count = (int)$count;
373
		} else {
374
			$count = 0;
375
		}
376
377
		return $count;
378
	}
379
380
	/**
381
	 * get the number of disabled users in a group
382
	 *
383
	 * @param string $search
0 ignored issues
show
Bug introduced by
There is no parameter named $search. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
384
	 * @return int|bool
385
	 */
386 View Code Duplication
	public function countDisabledInGroup(string $gid): int {
387
		$this->fixDI();
388
		
389
		$query = $this->dbConn->getQueryBuilder();
390
		$query->select($query->createFunction('COUNT(Distinct uid)'))
391
			->from('preferences', 'p')
392
			->innerJoin('p', 'group_user', 'g', 'p.userid = g.uid')
393
			->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
394
			->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
395
			->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
396
			->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
397
		
398
		$result = $query->execute();
399
		$count = $result->fetchColumn();
400
		$result->closeCursor();
401
		
402
		if ($count !== false) {
403
			$count = (int)$count;
404
		} else {
405
			$count = 0;
406
		}
407
408
		return $count;
409
	}
410
411
}
412