Completed
Push — activities ( f6cb6d...dc96a4 )
by Maxence
02:54
created

MembersService::editMemberLevel()   A

Complexity

Conditions 2
Paths 9

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 2
eloc 12
nc 9
nop 3
1
<?php
2
/**
3
 * Circles - bring cloud-users closer
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
namespace OCA\Circles\Service;
28
29
30
use OC\User\NoUserException;
31
use OCA\Circles\Db\CirclesMapper;
32
use OCA\Circles\Db\MembersMapper;
33
use OCA\Circles\Exceptions\CircleTypeNotValid;
34
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
35
use OCA\Circles\Exceptions\MemberDoesNotExistException;
36
use OCA\Circles\Model\Circle;
37
use \OCA\Circles\Model\Member;
38
use OCP\IL10N;
39
use OCP\IUserManager;
40
41
class MembersService {
42
43
	/** @var string */
44
	private $userId;
45
46
	/** @var IL10N */
47
	private $l10n;
48
49
	/** @var IUserManager */
50
	private $userManager;
51
52
	/** @var ConfigService */
53
	private $configService;
54
55
	/** @var CirclesMapper */
56
	private $dbCircles;
57
58
	/** @var MembersMapper */
59
	private $dbMembers;
60
61
	/** @var EventsService */
62
	private $eventsService;
63
64
	/** @var MiscService */
65
	private $miscService;
66
67 View Code Duplication
	public function __construct(
68
		$userId,
69
		IL10N $l10n,
70
		IUserManager $userManager,
71
		ConfigService $configService,
72
		DatabaseService $databaseService,
73
		EventsService $eventsService,
74
		MiscService $miscService
75
	) {
76
		$this->userId = $userId;
77
		$this->l10n = $l10n;
78
		$this->userManager = $userManager;
79
		$this->configService = $configService;
80
		$this->eventsService = $eventsService;
81
		$this->miscService = $miscService;
82
83
		$this->dbCircles = $databaseService->getCirclesMapper();
84
		$this->dbMembers = $databaseService->getMembersMapper();
85
	}
86
87
88
	/**
89
	 * @param $circleId
90
	 * @param $name
91
	 *
92
	 * @return array
93
	 * @throws \Exception
94
	 */
95 View Code Duplication
	public function addMember($circleId, $name) {
96
97
		try {
98
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
99
			$this->dbMembers->getMemberFromCircle($circleId, $this->userId)
100
							->hasToBeModerator();
101
		} catch (\Exception $e) {
102
			throw $e;
103
		}
104
105
		try {
106
			$member = $this->getFreshNewMember($circleId, $name);
107
		} catch (\Exception $e) {
108
			throw $e;
109
		}
110
		$member->inviteToCircle($circle->getType());
111
		$this->dbMembers->editMember($member);
112
113
		$this->eventsService->onMemberNew($circle, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->getFreshNewMember($circleId, $name) on line 106 can be null; however, OCA\Circles\Service\EventsService::onMemberNew() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
114
115
		return $this->dbMembers->getMembersFromCircle($circleId, $circle->getUser());
116
	}
117
118
119
	/**
120
	 * getMember();
121
	 *
122
	 * Will return any data of a user related to a circle (as a Member). User can be a 'non-member'
123
	 *
124
	 * @param $circleId
125
	 * @param $userId
126
	 *
127
	 * @return Member
0 ignored issues
show
Documentation introduced by
Should the return type not be Member|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
128
	 * @throws \Exception
129
	 */
130
	public function getMember($circleId, $userId) {
131
132
		try {
133
			$this->dbMembers->getMemberFromCircle($circleId, $this->userId)
134
							->hasToBeMember();
135
			$member = $this->dbMembers->getMemberFromCircle($circleId, $userId);
136
		} catch (\Exception $e) {
137
			throw $e;
138
		}
139
140
		return $member;
141
	}
142
143
144
	/**
145
	 * Check if a fresh member can be generated (by addMember)
146
	 *
147
	 * @param $circleId
148
	 * @param $name
149
	 *
150
	 * @return null|Member
151
	 * @throws MemberAlreadyExistsException
152
	 * @throws NoUserException
153
	 */
154
	private function getFreshNewMember($circleId, $name) {
155
156
		if (!$this->userManager->userExists($name)) {
157
			throw new NoUserException($this->l10n->t("This user does not exist"));
158
		}
159
160
		try {
161
			$member = $this->dbMembers->getMemberFromCircle($circleId, $name);
162
163
		} catch (MemberDoesNotExistException $e) {
164
			$member = new Member($this->l10n, $name, $circleId);
165
			$this->dbMembers->add($member);
166
		}
167
168
		if ($this->memberAlreadyExist($member)) {
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem...ircle($circleId, $name) on line 161 can be null; however, OCA\Circles\Service\Memb...e::memberAlreadyExist() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
169
			throw new MemberAlreadyExistsException(
170
				$this->l10n->t('This user is already a member of the circle')
171
			);
172
		}
173
174
		return $member;
175
	}
176
177
178
	/**
179
	 * return if member already exists
180
	 *
181
	 * @param Member $member
182
	 *
183
	 * @return bool
184
	 */
185
	private function memberAlreadyExist($member) {
186
		return ($member->getLevel() > Member::LEVEL_NONE
187
				|| ($member->getStatus() !== Member::STATUS_NONMEMBER
188
					&& $member->getStatus() !== Member::STATUS_REQUEST)
189
		);
190
	}
191
192
193
	/**
194
	 * @param $circleId
195
	 * @param $name
196
	 * @param $level
197
	 *
198
	 * @return array
199
	 * @throws \Exception
200
	 */
201
	public function levelMember($circleId, $name, $level) {
202
203
		try {
204
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
205
			if ($circle->getType() === Circle::CIRCLES_PERSONAL) {
206
				throw new CircleTypeNotValid(
207
					$this->l10n->t('You cannot edit level in a personal circle')
208
				);
209
			}
210
211
			$member = $this->dbMembers->getMemberFromCircle($circle->getId(), $name);
212
			if ($member->getLevel() !== $level) {
213
				if ((int)$level === Member::LEVEL_OWNER) {
214
					$this->switchOwner($circle, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem...circle->getId(), $name) on line 211 can be null; however, OCA\Circles\Service\MembersService::switchOwner() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
215
				} else {
216
					$this->editMemberLevel($circle, $member, $level);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem...circle->getId(), $name) on line 211 can be null; however, OCA\Circles\Service\Memb...vice::editMemberLevel() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
217
				}
218
219
				$this->eventsService->onMemberLevel($circle, $member);
220
			}
221
222
			return $this->dbMembers->getMembersFromCircle($circleId, $circle->getUser());
223
		} catch (\Exception $e) {
224
			throw $e;
225
		}
226
227
	}
228
229
230
	/**
231
	 * @param Circle $circle
232
	 * @param Member $member
233
	 * @param $level
234
	 *
235
	 * @throws \Exception
236
	 */
237
	private function editMemberLevel(Circle $circle, Member &$member, $level) {
238
		try {
239
			$isMod = $this->dbMembers->getMemberFromCircle($circle->getId(), $this->userId);
240
			$isMod->hasToBeModerator();
241
			$isMod->hasToBeHigherLevel($level);
242
243
			$member->hasToBeMember();
244
			$member->cantBeOwner();
245
			$isMod->hasToBeHigherLevel($member->getLevel());
246
247
			$member->setLevel($level);
248
			$this->dbMembers->editMember($member);
249
		} catch (\Exception $e) {
250
			throw $e;
251
		}
252
253
	}
254
255
	/**
256
	 * @param Circle $circle
257
	 * @param Member $member
258
	 *
259
	 * @throws \Exception
260
	 */
261
	public function switchOwner(Circle $circle, Member &$member) {
262
		try {
263
			$isMod = $this->dbMembers->getMemberFromCircle($circle->getId(), $this->userId);
264
			$isMod->hasToBeOwner();
265
266
			$member->setLevel(Member::LEVEL_OWNER);
267
			$this->dbMembers->editMember($member);
268
269
			$isMod->setLevel(Member::LEVEL_ADMIN);
270
			$this->dbMembers->editMember($isMod);
271
272
		} catch (\Exception $e) {
273
			throw $e;
274
		}
275
	}
276
277
278
	/**
279
	 * @param $circleId
280
	 * @param $name
281
	 *
282
	 * @return array
283
	 * @throws \Exception
284
	 */
285
	public function removeMember($circleId, $name) {
286
287
		try {
288
			$isMod = $this->dbMembers->getMemberFromCircle($circleId, $this->userId);
289
			$isMod->hasToBeModerator();
290
291
			$member = $this->dbMembers->getMemberFromCircle($circleId, $name);
292
			$member->cantBeOwner();
293
294
			$isMod->hasToBeHigherLevel($member->getLevel());
295
		} catch (\Exception $e) {
296
			throw $e;
297
		}
298
299
		$member->setStatus(Member::STATUS_NONMEMBER);
300
		$member->setLevel(Member::LEVEL_NONE);
301
		$this->dbMembers->editMember($member);
302
303
		$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
304
		$this->eventsService->onMemberLeaving($circle, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem...ircle($circleId, $name) on line 291 can be null; however, OCA\Circles\Service\Even...vice::onMemberLeaving() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
305
306
		return $this->dbMembers->getMembersFromCircle($circleId, $circle->getUser());
307
	}
308
309
310
	/**
311
	 * When a user is removed, remove him from all Circles
312
	 *
313
	 * @param $userId
314
	 */
315
	public function removeUser($userId) {
316
		$this->dbMembers->removeAllFromUserId($userId);
317
	}
318
319
320
}