Completed
Pull Request — master (#94)
by Maxence
02:28
created

CirclesService::leaveCircle()   A

Complexity

Conditions 3
Paths 16

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 21
rs 9.3142
cc 3
eloc 14
nc 16
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
namespace OCA\Circles\Service;
28
29
30
use OCA\Circles\Db\CirclesMapper;
31
use OCA\Circles\Db\CirclesRequest;
32
use OCA\Circles\Db\MembersMapper;
33
use OCA\Circles\Db\MembersRequest;
34
use OCA\Circles\Exceptions\CircleTypeDisabledException;
35
use OCA\Circles\Exceptions\FederatedCircleNotAllowedException;
36
use OCA\Circles\Exceptions\MemberDoesNotExistException;
37
use OCA\Circles\Exceptions\MemberIsNotOwnerException;
38
use \OCA\Circles\Model\Circle;
39
use \OCA\Circles\Model\Member;
40
use OCP\IL10N;
41
42
class CirclesService {
43
44
	/** @var string */
45
	private $userId;
46
47
	/** @var IL10N */
48
	private $l10n;
49
50
	/** @var ConfigService */
51
	private $configService;
52
53
	/** @var CirclesRequest */
54
	private $circlesRequest;
55
56
	/** @var MembersRequest */
57
	private $membersRequest;
58
59
	/** @var CirclesMapper */
60
	private $dbCircles;
61
62
	/** @var MembersMapper */
63
	private $dbMembers;
64
65
	/** @var EventsService */
66
	private $eventsService;
67
68
	/** @var MiscService */
69
	private $miscService;
70
71
72
	/**
73
	 * CirclesService constructor.
74
	 *
75
	 * @param $userId
76
	 * @param IL10N $l10n
77
	 * @param ConfigService $configService
78
	 * @param CirclesRequest $circlesRequest
79
	 * @param MembersRequest $membersRequest
80
	 * @param DatabaseService $databaseService
81
	 * @param EventsService $eventsService
82
	 * @param MiscService $miscService
83
	 */
84 View Code Duplication
	public function __construct(
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...
85
		$userId,
86
		IL10N $l10n,
87
		ConfigService $configService,
88
		CirclesRequest $circlesRequest,
89
		MembersRequest $membersRequest,
90
		DatabaseService $databaseService,
91
		EventsService $eventsService,
92
		MiscService $miscService
93
	) {
94
		$this->userId = $userId;
95
		$this->l10n = $l10n;
96
		$this->configService = $configService;
97
		$this->circlesRequest = $circlesRequest;
98
		$this->membersRequest = $membersRequest;
99
		$this->eventsService = $eventsService;
100
		$this->miscService = $miscService;
101
102
		$this->dbCircles = $databaseService->getCirclesMapper();
103
		$this->dbMembers = $databaseService->getMembersMapper();
104
	}
105
106
107
	/**
108
	 * Create circle using this->userId as owner
109
	 *
110
	 * @param int $type
111
	 * @param string $name
112
	 *
113
	 * @return Circle
114
	 * @throws CircleTypeDisabledException
115
	 * @throws \Exception
116
	 */
117
	public function createCircle($type, $name) {
118
		self::convertTypeStringToBitValue($type);
119
120
		if ($type === "") {
121
			throw new CircleTypeDisabledException(
122
				$this->l10n->t('You need a specify a type of circle')
123
			);
124
		}
125
126
		if (!$this->configService->isCircleAllowed($type)) {
127
			throw new CircleTypeDisabledException(
128
				$this->l10n->t('You cannot create this type of circle')
129
			);
130
		}
131
132
		$circle = new Circle($this->l10n, $type, $name);
133
		$owner = new Member($this->l10n, $this->userId);
134
		$circle->setOwner($owner);
135
		$circle->setUser($owner);
136
137
		try {
138
			$this->dbCircles->create($circle);
139
			$circle->getOwner()
140
				   ->setCircleId($circle->getId())
141
				   ->setLevel(Member::LEVEL_OWNER)
142
				   ->setStatus(Member::STATUS_MEMBER);
143
			$this->dbMembers->add($circle->getOwner());
144
		} catch (\Exception $e) {
145
			$this->dbCircles->destroy($circle->getId());
146
			throw $e;
147
		}
148
149
		$this->eventsService->onCircleCreation($circle);
150
151
		return $circle;
152
	}
153
154
155
	/**
156
	 * list Circles depends on type (or all) and name (parts) and minimum level.
157
	 *
158
	 * @param $type
159
	 * @param string $name
160
	 * @param int $level
161
	 *
162
	 * @return Circle[]
163
	 * @throws CircleTypeDisabledException
164
	 */
165
	public function listCircles($type, $name = '', $level = 0) {
166
		self::convertTypeStringToBitValue($type);
167
168
		if (!$this->configService->isCircleAllowed((int)$type)) {
169
			throw new CircleTypeDisabledException(
170
				$this->l10n->t('You cannot display this type of circle')
171
			);
172
		}
173
174
		$data = [];
175
		$result = $this->dbCircles->findCirclesByUser($this->userId, $type, $name, $level);
176
		foreach ($result as $item) {
177
			$data[] = $item;
178
		}
179
180
		return $data;
181
	}
182
183
184
	/**
185
	 * returns details on circle and its members if this->userId is a member itself.
186
	 *
187
	 * @param $circleId
188
	 *
189
	 * @return Circle
190
	 * @throws \Exception
191
]	 */
192
	public function detailsCircle($circleId) {
193
194
		try {
195
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
196
			if ($circle->getUser()
197
					   ->isLevel(Member::LEVEL_MEMBER)
198
			) {
199
				$members = $this->dbMembers->getMembersFromCircle($circleId, $circle->getUser());
200
				$circle->setMembers($members);
201
202
				$this->detailsCircleLinkedGroups($circle);
203
				$this->detailsCircleFederatedCircles($circle);
204
			}
205
		} catch (\Exception $e) {
206
			throw $e;
207
		}
208
209
		return $circle;
210
	}
211
212
	private function detailsCircleLinkedGroups(Circle &$circle) {
213
		$groups = [];
214
		if ($this->configService->isLinkedGroupsAllowed()) {
215
			$groups = $this->membersRequest->getGroups($circle->getId(), $circle->getUser());
216
		}
217
218
		$circle->setGroups($groups);
219
	}
220
221
222
	private function detailsCircleFederatedCircles(Circle &$circle) {
223
		$links = [];
224
225
		try {
226
			if ($this->configService->isFederatedCirclesAllowed()) {
227
				$circle->hasToBeFederated();
228
				$links = $this->circlesRequest->getLinksFromCircle($circle->getId());
229
			}
230
		} catch (FederatedCircleNotAllowedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
231
		}
232
233
		$circle->setLinks($links);
234
	}
235
236
237
	/**
238
	 * save new settings if current user is admin.
239
	 *
240
	 * @param $circleId
241
	 * @param array $settings
242
	 *
243
	 * @return Circle
244
	 * @throws \Exception
245
	 */
246
	public function settingsCircle($circleId, $settings) {
247
248
		try {
249
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
250
			$circle->getUser()
251
				   ->hasToBeOwner();
252
253
			$ak = array_keys($settings);
254
			foreach ($ak AS $k) {
255
				$circle->setSetting($k, $settings[$k]);
256
			}
257
258
			$this->circlesRequest->updateCircle($circle);
259
		} catch (\Exception $e) {
260
			throw $e;
261
		}
262
263
		return $circle;
264
	}
265
266
267
	/**
268
	 * Join a circle.
269
	 *
270
	 * @param $circleId
271
	 *
272
	 * @return null|Member
273
	 * @throws \Exception
274
	 */
275 View Code Duplication
	public function joinCircle($circleId) {
276
277
		try {
278
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
279
280
			try {
281
				$member = $this->dbMembers->getMemberFromCircle($circle->getId(), $this->userId);
282
			} catch (MemberDoesNotExistException $m) {
283
				$member = new Member($this->l10n, $this->userId, $circle->getId());
284
				$this->dbMembers->add($member);
285
			}
286
287
			$member->hasToBeAbleToJoinTheCircle();
288
			$member->joinCircle($circle->getType());
289
			$this->dbMembers->editMember($member);
290
			$this->eventsService->onMemberNew($circle, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem...getId(), $this->userId) on line 281 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...
291
		} catch (\Exception $e) {
292
			throw $e;
293
		}
294
295
		return $member;
296
	}
297
298
299
	/**
300
	 * Leave a circle.
301
	 *
302
	 * @param $circleId
303
	 *
304
	 * @return null|Member
305
	 * @throws \Exception
306
	 */
307
	public function leaveCircle($circleId) {
308
309
		try {
310
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
311
			$member = $this->dbMembers->getMemberFromCircle($circle->getId(), $this->userId, false);
312
313
			if (!$member->isAlmostMember()) {
314
				$member->hasToBeMember();
315
			}
316
317
			$member->cantBeOwner();
318
			$member->setStatus(Member::STATUS_NONMEMBER);
319
			$member->setLevel(Member::LEVEL_NONE);
320
			$this->dbMembers->editMember($member);
321
			$this->eventsService->onMemberLeaving($circle, $member);
0 ignored issues
show
Bug introduced by
It seems like $member defined by $this->dbMembers->getMem..., $this->userId, false) on line 311 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...
322
		} catch (\Exception $e) {
323
			throw $e;
324
		}
325
326
		return $member;
327
	}
328
329
330
	/**
331
	 * destroy a circle.
332
	 *
333
	 * @param int $circleId
334
	 *
335
	 * @throws MemberIsNotOwnerException
336
	 */
337
	public function removeCircle($circleId) {
338
339
		try {
340
			$member = $this->dbMembers->getMemberFromCircle($circleId, $this->userId, false);
341
			$member->hasToBeOwner();
342
343
			$circle = $this->dbCircles->getDetailsFromCircle($circleId, $this->userId);
344
			$this->eventsService->onCircleDestruction($circle);
345
346
			$this->dbMembers->removeAllFromCircle($circleId);
347
			$this->dbCircles->destroy($circleId);
348
349
		} catch (MemberIsNotOwnerException $e) {
350
			throw $e;
351
		}
352
	}
353
354
355
	/**
356
	 * @param $circleName
357
	 *
358
	 * @return Circle|null
359
	 */
360
	public function infoCircleByName($circleName) {
361
		return $this->dbCircles->getDetailsFromCircleByName($circleName);
362
	}
363
364
	/**
365
	 * Convert a Type in String to its Bit Value
366
	 *
367
	 * @param $type
368
	 *
369
	 * @return int
370
	 */
371
	public static function convertTypeStringToBitValue(& $type) {
372
		if (strtolower($type) === 'personal') {
373
			$type = Circle::CIRCLES_PERSONAL;
374
		}
375
		if (strtolower($type) === 'hidden') {
376
			$type = Circle::CIRCLES_HIDDEN;
377
		}
378
		if (strtolower($type) === 'private') {
379
			$type = Circle::CIRCLES_PRIVATE;
380
		}
381
		if (strtolower($type) === 'public') {
382
			$type = Circle::CIRCLES_PUBLIC;
383
		}
384
		if (strtolower($type) === 'all') {
385
			$type = Circle::CIRCLES_ALL;
386
		}
387
388
		return 0;
389
	}
390
391
392
	/**
393
	 * getCircleIcon()
394
	 *
395
	 * Return the right imagePath for a type of circle.
396
	 *
397
	 * @param string $type
398
	 * @param bool $png
399
	 *
400
	 * @return string
401
	 */
402
	public static function getCircleIcon($type, $png = false) {
403
404
		$ext = '.svg';
405
		if ($png === true) {
406
			$ext = '.png';
407
		}
408
409
		$urlGen = \OC::$server->getURLGenerator();
410
		switch ($type) {
411
			case Circle::CIRCLES_PERSONAL:
412
				return $urlGen->getAbsoluteURL(
413
					$urlGen->imagePath('circles', 'personal' . $ext)
414
				);
415
			case Circle::CIRCLES_PRIVATE:
416
				return $urlGen->getAbsoluteURL(
417
					$urlGen->imagePath('circles', 'private' . $ext)
418
				);
419
			case Circle::CIRCLES_HIDDEN:
420
				return $urlGen->getAbsoluteURL(
421
					$urlGen->imagePath('circles', 'hidden' . $ext)
422
				);
423
			case Circle::CIRCLES_PUBLIC:
424
				return $urlGen->getAbsoluteURL(
425
					$urlGen->imagePath('circles', 'public' . $ext)
426
				);
427
		}
428
429
		return $urlGen->getAbsoluteURL($urlGen->imagePath('circles', 'black_circle' . $ext));
430
	}
431
432
}