Completed
Pull Request — master (#384)
by Tortue
02:31
created

Member   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 227
Duplicated Lines 23.35 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 0
Metric Value
wmc 43
lcom 2
cbo 10
dl 53
loc 227
rs 8.96
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A inviteToCircle() 0 12 3
A hasToBeModerator() 0 7 2
A hasToBeHigherLevel() 0 8 2
A hasToBeMember() 0 7 2
A hasToBeMemberOrAlmost() 0 7 3
A cantBeOwner() 0 7 2
A alreadyExistOrJoining() 0 6 3
A broadcasting() 0 3 1
A isBroadcasting() 0 3 1
A levelHasToBeEditable() 0 7 2
A hasToBeAbleToJoinTheCircle() 14 14 3
A hasToBeInviteAble() 14 14 3
A joinCircle() 0 14 5
A addMemberToCircle() 0 8 3
A joinClosedCircle() 13 13 4
A inviteIntoClosedCircle() 12 12 4

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 Member 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 Member, and based on these observations, apply Extract Interface, too.

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
namespace OCA\Circles\Model;
28
29
use OCA\Circles\Exceptions\CircleTypeNotValidException;
30
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
31
use OCA\Circles\Exceptions\MemberCantJoinCircleException;
32
use OCA\Circles\Exceptions\MemberDoesNotExistException;
33
use OCA\Circles\Exceptions\MemberIsBlockedException;
34
use OCA\Circles\Exceptions\MemberIsNotAdminException;
35
use OCA\Circles\Exceptions\MemberIsNotModeratorException;
36
use OCA\Circles\Exceptions\MemberIsNotOwnerException;
37
use OCA\Circles\Exceptions\MemberIsOwnerException;
38
use OCA\Circles\Exceptions\MemberTypeCantEditLevelException;
39
use OCA\Circles\Exceptions\ModeratorIsNotHighEnoughException;
40
41
class Member extends BaseMember {
42
43
44
	public function inviteToCircle($circleType) {
45
46
		if ($circleType === 0) {
47
			throw new CircleTypeNotValidException('Invalid circle type');
48
		}
49
50
		if ($circleType === Circle::CIRCLES_CLOSED) {
51
			return $this->inviteIntoClosedCircle();
52
		}
53
54
		return $this->addMemberToCircle();
55
	}
56
57
58
	/**
59
	 * @param int $circleType
60
	 *
61
	 * @throws MemberCantJoinCircleException
62
	 */
63
	public function joinCircle($circleType) {
64
65
		switch ($circleType) {
66
			case Circle::CIRCLES_PERSONAL:
67
			case Circle::CIRCLES_SECRET:
68
			case Circle::CIRCLES_PUBLIC:
69
				return $this->addMemberToCircle();
70
71
			case Circle::CIRCLES_CLOSED:
72
				return $this->joinClosedCircle();
73
		}
74
75
		throw new MemberCantJoinCircleException($this->l10n->t('You cannot join this circle'));
76
	}
77
78
79
	/**
80
	 * Update status of member like he joined a public circle.
81
	 */
82
	public function addMemberToCircle() {
83
84
		if ($this->getStatus() === Member::STATUS_NONMEMBER
85
			|| $this->getStatus() === Member::STATUS_KICKED
86
		) {
87
			$this->setAsAMember(Member::LEVEL_MEMBER);
88
		}
89
	}
90
91
92
	/**
93
	 * Update status of member like he joined a closed circle
94
	 * (invite/request)
95
	 */
96 View Code Duplication
	private function joinClosedCircle() {
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...
97
98
		switch ($this->getStatus()) {
99
			case Member::STATUS_NONMEMBER:
100
			case Member::STATUS_KICKED:
101
				$this->setStatus(Member::STATUS_REQUEST);
102
				break;
103
104
			case Member::STATUS_INVITED:
105
				$this->setAsAMember(Member::LEVEL_MEMBER);
106
				break;
107
		}
108
	}
109
110
111 View Code Duplication
	private function inviteIntoClosedCircle() {
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...
112
		switch ($this->getStatus()) {
113
			case Member::STATUS_NONMEMBER:
114
			case Member::STATUS_KICKED:
115
				$this->setStatus(Member::STATUS_INVITED);
116
				break;
117
118
			case Member::STATUS_REQUEST:
119
				$this->setAsAMember(Member::LEVEL_MEMBER);
120
				break;
121
		}
122
	}
123
124
125
	/**
126
	 * @throws MemberIsNotModeratorException
127
	 */
128
	public function hasToBeModerator() {
129
		if ($this->getLevel() < self::LEVEL_MODERATOR) {
130
			throw new MemberIsNotModeratorException(
131
				$this->l10n->t('This member is not a moderator')
132
			);
133
		}
134
	}
135
136
137
	/**
138
	 * @param $level
139
	 *
140
	 * @throws ModeratorIsNotHighEnoughException
141
	 */
142
	public function hasToBeHigherLevel($level) {
143
144
		if ($this->getLevel() <= $level) {
145
			throw new ModeratorIsNotHighEnoughException(
146
				$this->l10n->t('Insufficient privileges')
147
			);
148
		}
149
	}
150
151
152
	/**
153
	 * @throws MemberDoesNotExistException
154
	 */
155
	public function hasToBeMember() {
156
		if ($this->getLevel() < self::LEVEL_MEMBER) {
157
			throw new MemberDoesNotExistException($this->l10n->t('This member does not exist'));
158
		}
159
160
		return true;
161
	}
162
163
164
	/**
165
	 * @throws MemberDoesNotExistException
166
	 */
167
	public function hasToBeMemberOrAlmost() {
168
		if ($this->isAlmostMember() || $this->hasToBeMember()) {
169
			return true;
170
		}
171
172
		throw new MemberDoesNotExistException($this->l10n->t('This member does not exist'));
173
	}
174
175
176
	/**
177
	 * @throws MemberIsOwnerException
178
	 */
179
	public function cantBeOwner() {
180
		if ($this->getLevel() === self::LEVEL_OWNER) {
181
			throw new MemberIsOwnerException(
182
				$this->l10n->t('This member is the owner of the circle')
183
			);
184
		}
185
	}
186
187
188
	/**
189
	 * return if member already exists
190
	 *
191
	 * @return bool
192
	 */
193
	public function alreadyExistOrJoining() {
194
		return ($this->getLevel() > Member::LEVEL_NONE
195
				|| ($this->getStatus() !== Member::STATUS_NONMEMBER
196
					&& $this->getStatus() !== Member::STATUS_REQUEST)
197
		);
198
	}
199
200
201
	/**
202
	 * @param bool $able
203
	 */
204
	public function broadcasting($able) {
205
		$this->broadcasting = $able;
206
	}
207
208
209
	/**
210
	 * @return bool
211
	 */
212
	public function isBroadcasting() {
213
		return $this->broadcasting;
214
	}
215
216
217
	/**
218
	 * @throws MemberTypeCantEditLevelException
219
	 */
220
	public function levelHasToBeEditable() {
221
		if ($this->getType() !== self::TYPE_USER) {
222
			throw new MemberTypeCantEditLevelException(
223
				$this->l10n->t('Level cannot be changed for this type of member')
224
			);
225
		}
226
	}
227
228
229
	/**
230
	 * @throws MemberAlreadyExistsException
231
	 * @throws MemberIsBlockedException
232
	 */
233 View Code Duplication
	public function hasToBeAbleToJoinTheCircle() {
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...
234
235
		if ($this->getLevel() > 0) {
236
			throw new MemberAlreadyExistsException(
237
				$this->l10n->t("You are already a member of this circle")
238
			);
239
		}
240
241
		if ($this->getStatus() === Member::STATUS_BLOCKED) {
242
			throw new MemberIsBlockedException(
243
				$this->l10n->t("You have been blocked from this circle")
244
			);
245
		}
246
	}
247
248
249
	/**
250
	 * @throws MemberAlreadyExistsException
251
	 */
252 View Code Duplication
	public function hasToBeInviteAble() {
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...
253
254
		if ($this->getLevel() > 0) {
255
			throw new MemberAlreadyExistsException(
256
				$this->l10n->t("The user is already a member of this circle")
257
			);
258
		}
259
260
		if ($this->getStatus() === Member::STATUS_INVITED) {
261
			throw new MemberAlreadyExistsException(
262
				$this->l10n->t("The user has already been invited into this circle")
263
			);
264
		}
265
	}
266
267
}
268