Completed
Push — master ( 397c2e...5232e6 )
by
unknown
02:26
created

CirclesService   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 310
Duplicated Lines 4.19 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 36
lcom 1
cbo 15
dl 13
loc 310
rs 8.0666
c 3
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 13 13 1
B createCircle() 0 36 4
B listCircles() 0 20 5
B detailsCircle() 0 24 3
C joinCircle() 0 69 11
B leaveCircle() 0 40 5
A removeCircle() 0 6 1
B convertTypeStringToBitValue() 0 17 6

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
 * 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\Service;
28
29
30
use OCA\Circles\Exceptions\CircleAlreadyExistsException;
31
use OCA\Circles\Exceptions\CircleCreationException;
32
use OCA\Circles\Exceptions\CircleDoesNotExistException;
33
use OCA\Circles\Exceptions\CircleTypeDisabledException;
34
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
35
use OCA\Circles\Exceptions\MemberDoesNotExistException;
36
use OCA\Circles\Exceptions\MemberIsBlockedException;
37
use OCA\Circles\Exceptions\MemberIsNotInvitedException;
38
use OCA\Circles\Exceptions\MemberIsOwnerException;
39
use \OCA\Circles\Model\Circle;
40
use \OCA\Circles\Model\Member;
41
use OCP\IL10N;
42
43
class CirclesService {
44
45
	private $userId;
46
	private $l10n;
47
	private $configService;
48
	private $databaseService;
49
	private $miscService;
50
51 View Code Duplication
	public function __construct(
1 ignored issue
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...
52
		$userId,
53
		IL10N $l10n,
54
		ConfigService $configService,
55
		DatabaseService $databaseService,
56
		MiscService $miscService
57
	) {
58
		$this->userId = $userId;
59
		$this->l10n = $l10n;
60
		$this->configService = $configService;
61
		$this->databaseService = $databaseService;
62
		$this->miscService = $miscService;
63
	}
64
65
66
	/**
67
	 * Create circle using this->userId as owner
68
	 *
69
	 * @param $type
70
	 * @param $name
71
	 *
72
	 * @return Circle
73
	 * @throws CircleTypeDisabledException
74
	 * @throws CircleAlreadyExistsException
75
	 * @throws CircleCreationException
76
	 */
77
	public function createCircle($type, $name) {
78
79
		self::convertTypeStringToBitValue($type);
80
81
		if (!$this->configService->isCircleAllowed((int)$type)) {
82
			throw new CircleTypeDisabledException();
83
		}
84
85
		$owner = new Member();
86
		$owner->setUserId($this->userId)
87
			  ->setStatus(Member::STATUS_MEMBER);
88
89
		$circle = new Circle();
90
		$circle->setName($name)
91
			   ->setType($type)
92
			   ->setMembers([$owner]);
93
94
		try {
95
			$this->databaseService->getCirclesMapper()
96
								  ->create($circle, $owner);
97
			$this->databaseService->getMembersMapper()
98
								  ->add($owner);
99
100
101
		} catch (CircleAlreadyExistsException $e) {
102
			$this->databaseService->getCirclesMapper()
103
								  ->destroy($circle);
104
			throw $e;
105
		} catch (CircleCreationException $e) {
106
			$this->databaseService->getCirclesMapper()
107
								  ->destroy($circle);
108
			throw $e;
109
		}
110
111
		return $circle;
112
	}
113
114
115
	/**
116
	 * list Circles depends on type (or all) and name (parts) and minimum level.
117
	 *
118
	 * @param $type
119
	 * @param string $name
120
	 * @param int $level
121
	 *
122
	 * @return array
123
	 * @throws CircleTypeDisabledException
124
	 */
125
	public function listCircles($type, $name = '', $level = 0) {
126
127
		self::convertTypeStringToBitValue($type);
128
129
		if (!$this->configService->isCircleAllowed((int)$type)) {
130
			throw new CircleTypeDisabledException();
131
		}
132
133
		$result = $this->databaseService->getCirclesMapper()
134
										->findCirclesByUser($this->userId, $type, $name, $level);
135
136
		$data = [];
137
		foreach ($result as $item) {
0 ignored issues
show
Bug introduced by
The expression $result of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
138
			if ($name === '' || stripos($item->getName(), $name) !== false) {
139
				$data[] = $item;
140
			}
141
		}
142
143
		return $data;
144
	}
145
146
147
	/**
148
	 * returns details on circle and its members if this->userId is a member itself.
149
	 *
150
	 * @param $circleId
151
	 *
152
	 * @return Circle
153
	 * @throws CircleDoesNotExistException
154
	 * @internal param $circleId
155
	 * @internal param string $iError
156
	 */
157
	public function detailsCircle($circleId) {
158
159
		try {
160
			$circle = $this->databaseService->getCirclesMapper()
161
											->getDetailsFromCircle($this->userId, $circleId);
162
163
			if ($circle->getUser()
164
					   ->getLevel() >= Member::LEVEL_MEMBER
165
			) {
166
				$members = $this->databaseService->getMembersMapper()
167
												 ->getMembersFromCircle(
168
													 $circleId, ($circle->getUser()
169
																		->getLevel()
170
																 >= Member::LEVEL_MODERATOR)
171
												 );
172
				$circle->setMembers($members);
173
			}
174
		} catch (CircleDoesNotExistException $e) {
175
			throw $e;
176
		}
177
178
		return $circle;
179
180
	}
181
182
	/**
183
	 * Join a circle.
184
	 *
185
	 * @param $circleId
186
	 *
187
	 * @return null|Member
188
	 * @throws CircleDoesNotExistException
189
	 * @throws MemberAlreadyExistsException
190
	 * @throws MemberIsBlockedException
191
	 * @throws MemberIsNotInvitedException
192
	 */
193
	public function joinCircle($circleId) {
194
195
		try {
196
197
			$circle = $this->databaseService->getCirclesMapper()
198
											->getDetailsFromCircle(
199
												$this->userId, $circleId
200
											);
201
202
			try {
203
				$member = $this->databaseService->getMembersMapper()
204
												->getMemberFromCircle(
205
													$circle->getId(), $this->userId,
206
													($circle->getUser()
207
															->getLevel()
208
													 >= Member::LEVEL_MODERATOR)
209
												);
210
211
			} catch (MemberDoesNotExistException $m) {
212
				$member = new Member();
213
				$member->setCircleId($circle->getId());
214
				$member->setUserId($this->userId);
215
				$member->setLevel(Member::LEVEL_NONE);
216
				$member->setStatus(Member::STATUS_NONMEMBER);
217
218
				$this->databaseService->getMembersMapper()
219
									  ->add($member);
220
			}
221
222
223
			if ($member->getLevel() > 0) {
224
				throw new MemberAlreadyExistsException("You are already a member of this circle");
225
			}
226
227
228
			if ($member->getStatus() === Member::STATUS_BLOCKED) {
229
				throw new MemberIsBlockedException("You are blocked from this circle");
230
			}
231
232
233
			if ($member->getStatus() === Member::STATUS_NONMEMBER
234
				|| $member->getStatus() === Member::STATUS_KICKED
235
			) {
236
				if ($circle->getType() === Circle::CIRCLES_HIDDEN
237
					|| $circle->getType() === Circle::CIRCLES_PUBLIC
238
				) {
239
					$member->setStatus(Member::STATUS_MEMBER);
240
					$member->setLevel(Member::LEVEL_MEMBER);
241
				} else if ($circle->getType() === Circle::CIRCLES_PRIVATE) {
242
					$member->setStatus(Member::STATUS_REQUEST);
243
				} else {
244
					throw new MemberIsNotInvitedException("You are not invited into this circle");
245
				}
246
			}
247
248
			if ($member->getStatus() === Member::STATUS_INVITED) {
249
				$member->setStatus(Member::STATUS_MEMBER);
250
				$member->setLevel(Member::LEVEL_MEMBER);
251
			}
252
253
			$this->databaseService->getMembersMapper()
254
								  ->editMember($member);
255
256
		} catch (CircleDoesNotExistException $e) {
257
			throw $e;
258
		}
259
260
		return $member;
261
	}
262
263
264
	/**
265
	 * Leave a circle.
266
	 *
267
	 * @param $circleId
268
	 *
269
	 * @return null|Member
270
	 * @throws CircleDoesNotExistException
271
	 * @throws MemberDoesNotExistException
272
	 * @throws MemberIsOwnerException
273
	 */
274
	public function leaveCircle($circleId) {
275
276
		try {
277
			$circle = $this->databaseService->getCirclesMapper()
278
											->getDetailsFromCircle(
279
												$this->userId, $circleId
280
											);
281
282
			$member = $this->databaseService->getMembersMapper()
283
											->getMemberFromCircle(
284
												$circle->getId(), $this->userId,
285
												($circle->getUser()
286
														->getLevel()
287
												 >= Member::LEVEL_MODERATOR)
288
											);
289
290
			if ($member === null || $member->getLevel() === 0) {
291
				throw new MemberDoesNotExistException("You are not member of this circle");
292
			}
293
294
295
			if ($member->getLevel() === Member::LEVEL_OWNER) {
296
				throw new MemberIsOwnerException("As the owner, you cannot leave this circle");
297
			}
298
299
300
			$member->setStatus(Member::STATUS_NONMEMBER);
301
			$member->setLevel(Member::LEVEL_NONE);
302
303
			$this->databaseService->getMembersMapper()
304
								  ->editMember(
305
									  $member
306
								  );
307
308
		} catch (CircleDoesNotExistException $e) {
309
			throw $e;
310
		}
311
312
		return $member;
313
	}
314
315
316
	/**
317
	 * destroy a circle.
318
	 *
319
	 * @param $circle
320
	 */
321
	public function removeCircle($circle) {
322
		$this->databaseService->getMembersMapper()
323
							  ->removeAllFromCircle($circle);
324
		$this->databaseService->getCirclesMapper()
325
							  ->destroy($circle);
326
	}
327
328
329
	/**
330
	 * Convert a Type in String to its Bit Value
331
	 *
332
	 * @param $type
333
	 */
334
	public static function convertTypeStringToBitValue(&$type) {
335
		if (strtolower($type) === 'personal') {
336
			$type = Circle::CIRCLES_PERSONAL;
337
		}
338
		if (strtolower($type) === 'hidden') {
339
			$type = Circle::CIRCLES_HIDDEN;
340
		}
341
		if (strtolower($type) === 'private') {
342
			$type = Circle::CIRCLES_PRIVATE;
343
		}
344
		if (strtolower($type) === 'public') {
345
			$type = Circle::CIRCLES_PUBLIC;
346
		}
347
		if (strtolower($type) === 'all') {
348
			$type = Circle::CIRCLES_ALL;
349
		}
350
	}
351
352
}