Completed
Push — master ( 97a159...fc6227 )
by Maxence
29s
created

MembersRequest::updateMember()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2017
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
28
namespace OCA\Circles\Db;
29
30
31
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
32
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
33
use OCA\Circles\Exceptions\MemberDoesNotExistException;
34
use OCA\Circles\Model\Member;
35
use OCP\IGroup;
36
37
class MembersRequest extends MembersRequestBuilder {
38
39
40
	/**
41
	 * Returns information about a member.
42
	 *
43
	 * WARNING: This function does not filters data regarding the current user/viewer.
44
	 *          In case of interaction with users, Please use MembersService->getMember() instead.
45
	 *
46
	 * @param string $circleUniqueId
47
	 * @param string $userId
48
	 * @param $type
49
	 *
50
	 * @return Member
51
	 * @throws MemberDoesNotExistException
52
	 */
53 View Code Duplication
	public function forceGetMember($circleUniqueId, $userId, $type) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
54
		$qb = $this->getMembersSelectSql();
55
56
		$this->limitToUserId($qb, $userId);
57
		$this->limitToUserType($qb, $type);
58
		$this->limitToCircleId($qb, $circleUniqueId);
59
60
		$cursor = $qb->execute();
61
		$data = $cursor->fetch();
62
		$cursor->closeCursor();
63
64
		if ($data === false) {
65
			throw new MemberDoesNotExistException($this->l10n->t('This member does not exist'));
66
		}
67
68
		$member = $this->parseMembersSelectSql($data);
69
70
		return $member;
71
	}
72
73
74
	/**
75
	 * Returns members list of a circle, based on their level.
76
	 *
77
	 * WARNING: This function does not filters data regarding the current user/viewer.
78
	 *          In case of interaction with users, Please use getMembers() instead.
79
	 *
80
	 * @param string $circleUniqueId
81
	 * @param int $level
82
	 * @param bool $includeGroupMembers
83
	 *
84
	 * @return Member[]
85
	 */
86
	public function forceGetMembers(
87
		$circleUniqueId, $level = Member::LEVEL_MEMBER, $includeGroupMembers = false
88
	) {
89
90
		$qb = $this->getMembersSelectSql();
91
92
		$this->limitToMembersAndAlmost($qb);
93
		$this->limitToLevel($qb, $level);
94
		$this->limitToCircleId($qb, $circleUniqueId);
95
96
		$members = [];
97
		$cursor = $qb->execute();
98
		while ($data = $cursor->fetch()) {
99
			$members[] = $this->parseMembersSelectSql($data);
100
		}
101
		$cursor->closeCursor();
102
103
		if ($this->configService->isLinkedGroupsAllowed() && $includeGroupMembers === true) {
104
			$this->includeGroupMembers($members, $circleUniqueId, $level);
105
		}
106
107
		return $members;
108
	}
109
110
111
	/**
112
	 * @param string $circleUniqueId
113
	 * @param Member $viewer
114
	 *
115
	 * @return Member[]
116
	 * @throws \Exception
117
	 */
118
	public function getMembers($circleUniqueId, Member $viewer) {
119
		try {
120
			$viewer->hasToBeMember();
121
122
			$members = $this->forceGetMembers($circleUniqueId, Member::LEVEL_NONE);
123
			if (!$viewer->isLevel(Member::LEVEL_MODERATOR)) {
124
				array_map(
125
					function(Member $m) {
126
						$m->setNote('');
127
					}, $members
128
				);
129
			}
130
131
			return $members;
132
		} catch (\Exception $e) {
133
			return [];
134
		}
135
	}
136
137
138
	/**
139
	 * forceGetGroup();
140
	 *
141
	 * returns group information as a member within a Circle.
142
	 *
143
	 * WARNING: This function does not filters data regarding the current user/viewer.
144
	 *          In case of interaction with users, Please use getGroup() instead.
145
	 *
146
	 * @param string $circleUniqueId
147
	 * @param string $groupId
148
	 *
149
	 * @return Member
150
	 * @throws MemberDoesNotExistException
151
	 */
152 View Code Duplication
	public function forceGetGroup($circleUniqueId, $groupId) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
		$qb = $this->getGroupsSelectSql();
154
155
		$this->limitToGroupId($qb, $groupId);
156
		$this->limitToCircleId($qb, $circleUniqueId);
157
158
		$cursor = $qb->execute();
159
		$data = $cursor->fetch();
160
		if ($data === false) {
161
			throw new MemberDoesNotExistException($this->l10n->t('This member does not exist'));
162
		}
163
164
		$group = $this->parseGroupsSelectSql($data);
165
		$cursor->closeCursor();
166
167
		return $group;
168
	}
169
170
171
	/**
172
	 * includeGroupMembers();
173
	 *
174
	 * This function will get members of a circle throw NCGroups and fill the result an existing
175
	 * Members List. In case of duplicate, higher level will be kept.
176
	 *
177
	 * @param Member[] $members
178
	 * @param string $circleUniqueId
179
	 * @param int $level
180
	 */
181
	private function includeGroupMembers(array &$members, $circleUniqueId, $level) {
182
183
		$groupMembers = $this->forceGetGroupMembers($circleUniqueId, $level);
184
		$this->avoidDuplicateMembers($members, $groupMembers);
185
	}
186
187
188
	/**
189
	 * avoidDuplicateMembers();
190
	 *
191
	 * Use this function to add members to the list (1st argument), keeping the higher level in case
192
	 * of duplicate
193
	 *
194
	 * @param Member[] $members
195
	 * @param Member[] $groupMembers
196
	 */
197
	public function avoidDuplicateMembers(array &$members, array $groupMembers) {
198
		foreach ($groupMembers as $member) {
199
			$index = $this->indexOfMember($members, $member->getUserId());
200
			if ($index === -1) {
201
				array_push($members, $member);
202
			} else if ($members[$index]->getLevel() < $member->getLevel()) {
203
				$members[$index] = $member;
204
			}
205
		}
206
	}
207
208
209
	/**
210
	 * returns the index of a specific UserID in a Members List
211
	 *
212
	 * @param array $members
213
	 * @param $userId
214
	 *
215
	 * @return int
216
	 */
217
	private function indexOfMember(array $members, $userId) {
218
219
		foreach ($members as $k => $member) {
220
			if ($member->getUserId() === $userId) {
221
				return intval($k);
222
			}
223
		}
224
225
		return -1;
226
	}
227
228
229
	/**
230
	 * Check if a fresh member can be generated (by addMember/joinCircle)
231
	 *
232
	 * @param string $circleUniqueId
233
	 * @param string $name
234
	 * @param $type
235
	 *
236
	 * @return Member
237
	 * @throws MemberAlreadyExistsException
238
	 * @throws \Exception
239
	 */
240
	public function getFreshNewMember($circleUniqueId, $name, $type) {
241
242
		try {
243
244
			$member = $this->forceGetMember($circleUniqueId, $name, $type);
245
246
		} catch (MemberDoesNotExistException $e) {
247
			$member = new Member($name, $type, $circleUniqueId);
248
			$this->createMember($member);
249
		}
250
251
//		if ($member->alreadyExistOrJoining()) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
252
//			throw new MemberAlreadyExistsException(
253
//				$this->l10n->t('This user is already a member of the circle')
254
//			);
255
//		}
256
257
		return $member;
258
	}
259
260
261
	/**
262
	 * Returns members list of all Group Members of a Circle. The Level of the linked group will be
263
	 * assigned to each entry
264
	 *
265
	 * NOTE: Can contains duplicate.
266
	 *
267
	 * WARNING: This function does not filters data regarding the current user/viewer.
268
	 *          Do not use in case of direct interaction with users.
269
	 *
270
	 * @param string $circleUniqueId
271
	 * @param int $level
272
	 *
273
	 * @return Member[]
274
	 */
275
	public function forceGetGroupMembers($circleUniqueId, $level = Member::LEVEL_MEMBER) {
276
		$qb = $this->getGroupsSelectSql();
277
278
		$this->limitToLevel($qb, $level);
279
		$this->limitToCircleId($qb, $circleUniqueId);
280
		$this->limitToNCGroupUser($qb);
281
282
		$members = [];
283
		$cursor = $qb->execute();
284
		while ($data = $cursor->fetch()) {
285
			$members[] = $this->parseGroupsSelectSql($data);
286
		}
287
		$cursor->closeCursor();
288
289
		return $members;
290
	}
291
292
293
	/**
294
	 * returns all users from a Group as a list of Members.
295
	 *
296
	 * @param Member $group
297
	 *
298
	 * @return Member[]
299
	 */
300
	public function getGroupMemberMembers(Member $group) {
301
		/** @var IGroup $grp */
302
		$grp = $this->groupManager->get($group->getUserId());
303
		if ($grp === null) {
304
			return [];
305
		}
306
307
		$members = [];
308
		$users = $grp->getUsers();
309
		foreach ($users as $user) {
310
			$member = clone $group;
311
			//Member::fromJSON($this->l10n, json_encode($group));
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
312
			$member->setType(Member::TYPE_USER);
313
			$member->setUserId($user->getUID());
314
			$members[] = $member;
315
		}
316
317
		return $members;
318
	}
319
320
321
	/**
322
	 * return the higher level group linked to a circle, that include the userId.
323
	 *
324
	 * WARNING: This function does not filters data regarding the current user/viewer.
325
	 *          In case of direct interaction with users, Please don't use this.
326
	 *
327
	 * @param string $circleUniqueId
328
	 * @param string $userId
329
	 *
330
	 * @return Member
331
	 */
332
	public function forceGetHigherLevelGroupFromUser($circleUniqueId, $userId) {
333
		$qb = $this->getGroupsSelectSql();
334
335
		$this->limitToCircleId($qb, $circleUniqueId);
336
		$this->limitToNCGroupUser($qb, $userId);
337
338
		/** @var Member $group */
339
		$group = null;
340
341
		$cursor = $qb->execute();
342
		while ($data = $cursor->fetch()) {
343
			$entry = $this->parseGroupsSelectSql($data);
344
			if ($group === null || $entry->getLevel() > $group->getLevel()) {
345
				$group = $entry;
346
			}
347
		}
348
		$cursor->closeCursor();
349
350
		return $group;
351
	}
352
353
354
	/**
355
	 * Insert Member into database.
356
	 *
357
	 * @param Member $member
358
	 *
359
	 * @throws MemberAlreadyExistsException
360
	 */
361
	public function createMember(Member $member) {
362
363
		try {
364
			$qb = $this->getMembersInsertSql();
365
			$qb->setValue('circle_id', $qb->createNamedParameter($member->getCircleId()))
366
			   ->setValue('user_id', $qb->createNamedParameter($member->getUserId()))
367
			   ->setValue('user_type', $qb->createNamedParameter($member->getType()))
368
			   ->setValue('level', $qb->createNamedParameter($member->getLevel()))
369
			   ->setValue('status', $qb->createNamedParameter($member->getStatus()))
370
			   ->setValue('note', $qb->createNamedParameter($member->getNote()));
371
372
			$qb->execute();
373
		} catch (UniqueConstraintViolationException $e) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Exception\...raintViolationException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
374
			throw new MemberAlreadyExistsException(
375
				$this->l10n->t('This user is already a member of the circle')
376
			);
377
		}
378
	}
379
380
381
	/**
382
	 * @param string $circleUniqueId
383
	 * @param Member $viewer
384
	 *
385
	 * @return Member[]
386
	 * @throws MemberDoesNotExistException
387
	 */
388
	public function getGroupsFromCircle($circleUniqueId, Member $viewer) {
389
390
		if ($viewer->getLevel() < Member::LEVEL_MEMBER) {
391
			return [];
392
		}
393
394
		$qb = $this->getGroupsSelectSql();
395
		$this->limitToCircleId($qb, $circleUniqueId);
396
		$this->limitToLevel($qb, Member::LEVEL_MEMBER);
397
398
		$cursor = $qb->execute();
399
		$groups = [];
400
		while ($data = $cursor->fetch()) {
401
			if ($viewer->getLevel() < Member::LEVEL_MODERATOR) {
402
				$data['note'] = '';
403
			}
404
			$groups[] = $this->parseGroupsSelectSql($data);
405
		}
406
		$cursor->closeCursor();
407
408
		return $groups;
409
	}
410
411
412
	/**
413
	 * Insert Member into database.
414
	 *
415
	 * @param Member $member
416
	 *
417
	 * @throws MemberAlreadyExistsException
418
	 */
419
	public function insertGroup(Member $member) {
420
		try {
421
			$qb = $this->getGroupsInsertSql();
422
			$qb->setValue('circle_id', $qb->createNamedParameter($member->getCircleId()))
423
			   ->setValue('group_id', $qb->createNamedParameter($member->getUserId()))
424
			   ->setValue('level', $qb->createNamedParameter($member->getLevel()))
425
			   ->setValue('note', $qb->createNamedParameter($member->getNote()));
426
427
			$qb->execute();
428
		} catch (UniqueConstraintViolationException $e) {
429
			throw new MemberAlreadyExistsException(
430
				$this->l10n->t('This user is already a member of the circle')
431
			);
432
		}
433
	}
434
435
436
	/**
437
	 * update database entry for a specific Member.
438
	 *
439
	 * @param Member $member
440
	 */
441
	public function updateMember(Member $member) {
442
		$qb = $this->getMembersUpdateSql($member->getCircleId(), $member);
443
		$qb->set('level', $qb->createNamedParameter($member->getLevel()))
444
		   ->set('status', $qb->createNamedParameter($member->getStatus()));
445
446
		$qb->execute();
447
	}
448
449
450
	/**
451
	 * removeAllFromCircle();
452
	 *
453
	 * Remove All members from a Circle. Used when deleting a Circle.
454
	 *
455
	 * @param string $uniqueCircleId
456
	 */
457
	public function removeAllFromCircle($uniqueCircleId) {
458
		$qb = $this->getMembersDeleteSql($uniqueCircleId);
459
		$qb->execute();
460
	}
461
462
463
	/**
464
	 * removeAllFromUser();
465
	 *
466
	 * remove All membership from a User. Used when removing a User from the Cloud.
467
	 *
468
	 * @param $userId
469
	 */
470
	public function removeAllFromUser($userId) {
471
		if ($userId === '') {
472
			return;
473
		}
474
475
		$qb = $this->getMembersDeleteSql('', Member::TYPE_USER, $userId);
476
		$qb->execute();
477
	}
478
479
480
	/**
481
	 * update database entry for a specific Group.
482
	 *
483
	 * @param Member $member
484
	 *
485
	 * @return bool
486
	 */
487
	public function updateGroup(Member $member) {
488
489
		$qb = $this->getGroupsUpdateSql($member->getCircleId(), $member->getUserId());
490
		$qb->set('level', $qb->createNamedParameter($member->getLevel()));
491
		$qb->execute();
492
493
		return true;
494
	}
495
496
497
	public function unlinkAllFromGroup($groupId) {
498
		$qb = $this->getGroupsDeleteSql($groupId);
499
		$qb->execute();
500
	}
501
502
}