Completed
Pull Request — master (#347)
by Maxence
02:49
created

DavService::manageContact()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 2
nc 3
nop 1
1
<?php
2
3
4
/**
5
 * Circles - Bring cloud-users closer together.
6
 *
7
 * This file is licensed under the Affero General Public License version 3 or
8
 * later. See the COPYING file.
9
 *
10
 * @author Maxence Lange <[email protected]>
11
 * @copyright 2017
12
 * @license GNU AGPL version 3 or any later version
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
 *
27
 */
28
29
30
namespace OCA\Circles\Service;
31
32
33
use OCA\Circles\Db\CirclesRequest;
34
use OCA\Circles\Db\MembersRequest;
35
use OCA\Circles\Exceptions\CircleAlreadyExistsException;
36
use OCA\Circles\Exceptions\CircleDoesNotExistException;
37
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
38
use OCA\Circles\Exceptions\MemberDoesNotExistException;
39
use OCA\Circles\Exceptions\NotLocalMemberException;
40
use OCA\Circles\Model\Circle;
41
use OCA\Circles\Model\DavCard;
42
use OCA\Circles\Model\Member;
43
use OCP\IUserManager;
44
use Symfony\Component\EventDispatcher\GenericEvent;
45
46
47
/**
48
 * Class DavService
49
 *
50
 * @package OCA\Circles\Service
51
 */
52
class DavService {
53
54
55
	/** @var string */
56
	private $userId;
57
58
	/** @var IUserManager */
59
	private $userManager;
60
61
	/** @var CirclesRequest */
62
	private $circlesRequest;
63
64
	/** @var MembersRequest */
65
	private $membersRequest;
66
67
	/** @var ConfigService */
68
	private $configService;
69
70
	/** @var MiscService */
71
	private $miscService;
72
73
74
	/**
75
	 * TimezoneService constructor.
76
	 *
77
	 * @param string $userId
78
	 * @param IUserManager $userManager
79
	 * @param CirclesRequest $circlesRequest
80
	 * @param MembersRequest $membersRequest
81
	 * @param ConfigService $configService
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, IUserManager $userManager, CirclesRequest $circlesRequest, MembersRequest $membersRequest,
86
		ConfigService $configService, MiscService $miscService
87
	) {
88
		$this->userId = $userId;
89
		$this->userManager = $userManager;
90
		$this->circlesRequest = $circlesRequest;
91
		$this->membersRequest = $membersRequest;
92
		$this->configService = $configService;
93
		$this->miscService = $miscService;
94
	}
95
96
97
	/**
98
	 * @param GenericEvent $event
99
	 */
100
	public function onCreateCard(GenericEvent $event) {
101
		$davCard = $this->generateDavCard($event);
102
		$this->updateDavCard($davCard);
103
	}
104
105
106
	/**
107
	 * @param GenericEvent $event
108
	 */
109
	public function onUpdateCard(GenericEvent $event) {
110
		$davCard = $this->generateDavCard($event);
111
		$this->updateDavCard($davCard);
112
	}
113
114
115
	/**
116
	 * @param GenericEvent $event
117
	 */
118
	public function onDeleteCard(GenericEvent $event) {
119
		$addressBookId = $event->getArgument('addressBookId');
0 ignored issues
show
Unused Code introduced by
$addressBookId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
120
		$cardUri = $event->getArgument('cardUri');
0 ignored issues
show
Unused Code introduced by
$cardUri is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
121
	}
122
123
124
	/**
125
	 * @param GenericEvent $event
126
	 *
127
	 * @return DavCard
128
	 */
129
	private function generateDavCard(GenericEvent $event): DavCard {
130
		$addressBookId = $event->getArgument('addressBookId');
131
		$cardUri = $event->getArgument('cardUri');
132
		$cardData = $event->getArgument('cardData');
133
134
		$davCard = new DavCard();
135
		// TODO: set owner based on Address Book owner
136
		$davCard->setOwner($this->userId);
137
		$davCard->importFromDav($cardData);
138
		$davCard->setAddressBookId($addressBookId);
139
		$davCard->setCardUri($cardUri);
140
141
		return $davCard;
142
	}
143
144
145
	/**
146
	 * @param DavCard $davCard
147
	 */
148
	private function updateDavCard(DavCard $davCard) {
149
		$this->miscService->log('Updating Card: ' . json_encode($davCard));
150
		$this->manageCircles($davCard);
151
		$this->manageContact($davCard);
152
	}
153
154
155
	/**
156
	 * @param DavCard $davCard
157
	 */
158
	private function manageContact(DavCard $davCard) {
159
		$circles = array_map(
160
			function(Circle $circle) {
161
				return $circle->getUniqueId();
162
			}, $davCard->getCircles()
163
		);
164
165
		try {
166
			$userId = $this->isLocalMember($davCard);
167
168
			$this->manageLocalContact($circles, $davCard, $userId);
169
		} catch (NotLocalMemberException $e) {
170
			$this->manageRemoteContact($circles, $davCard);
171
		}
172
	}
173
174
175
	/**
176
	 * @param array $circles
177
	 * @param DavCard $davCard
178
	 * @param string $userId
179
	 */
180
	private function manageLocalContact(array $circles, DavCard $davCard, string $userId) {
0 ignored issues
show
Unused Code introduced by
The parameter $circles is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
181
		foreach ($davCard->getCircles() as $circle) {
182
			$this->manageMember($circle, $davCard, Member::TYPE_USER, $userId);
183
		}
184
185
	}
186
187
188
	/**
189
	 * @param array $circles
190
	 * @param DavCard $davCard
191
	 */
192
	private function manageRemoteContact(array $circles, DavCard $davCard) {
0 ignored issues
show
Unused Code introduced by
The parameter $circles is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
193
		foreach ($davCard->getCircles() as $circle) {
194
			$this->manageMember($circle, $davCard, Member::TYPE_CONTACT);
195
		}
196
	}
197
198
199
	/**
200
	 * @param Circle $circle
201
	 * @param DavCard $davCard
202
	 * @param int $type
203
	 * @param string $userId
204
	 */
205
	private function manageMember(Circle $circle, DavCard $davCard, int $type, string $userId = '') {
206
		if ($userId === '') {
207
			$userId = $davCard->getOwner() . ':' . $davCard->getContactId();
208
		}
209
210
		try {
211
			$member =
212
				$this->membersRequest->getContactMember($circle->getUniqueId(), $davCard->getContactId());
213
214
			if ($member->getType() !== $type) {
215
				$this->membersRequest->removeMember($member);
216
				throw new MemberDoesNotExistException();
217
			}
218
		} catch (MemberDoesNotExistException $e) {
219
			$member = new Member();
220
			$member->setLevel(Member::LEVEL_MEMBER);
221
			$member->setStatus(Member::STATUS_MEMBER);
222
			$member->setContactId($davCard->getContactId());
223
			$member->setType($type);
224
			$member->setCircleId($circle->getUniqueId());
225
			$member->setUserId($userId);
226
227
			try {
228
				$this->membersRequest->createMember($member);
229
			} catch (MemberAlreadyExistsException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
230
			}
231
		}
232
	}
233
234
235
	/**
236
	 * @param DavCard $davCard
237
	 *
238
	 * @return string
239
	 * @throws NotLocalMemberException
240
	 */
241
	private function isLocalMember(DavCard $davCard): string {
242
		foreach ($davCard->getEmails() as $email) {
243
			if (strpos($email, '@') === false) {
244
				continue;
245
			}
246
247
			list ($username, $domain) = explode('@', $email);
248
			if (in_array($domain, $this->configService->getAvailableHosts())) {
249
				$user = $this->userManager->get($username);
250
				if ($user !== null) {
251
					return $user->getUID();
252
				}
253
			}
254
		}
255
256
		throw new NotLocalMemberException();
257
	}
258
259
260
	/**
261
	 * @param DavCard $davCard
262
	 */
263
	private function manageCircles(DavCard $davCard) {
264
		$fromCard = $davCard->getGroups();
265
		$current = array_map(
266
			function(Circle $circle) {
267
				return $circle->getContactGroupName();
268
			}, $this->getCirclesFromBook($davCard->getAddressBookId())
269
		);
270
271
		$this->manageNewCircles($davCard, $fromCard, $current);
272
		$this->manageDeprecatedCircles($fromCard, $current);
0 ignored issues
show
Unused Code introduced by
The call to the method OCA\Circles\Service\DavS...nageDeprecatedCircles() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
273
274
		$this->assignCirclesToCard($davCard);
275
	}
276
277
278
	/**
279
	 * @param DavCard $davCard
280
	 * @param array $fromCard
281
	 * @param array $current
282
	 */
283
	private function manageNewCircles(DavCard $davCard, array $fromCard, array $current) {
284
		foreach ($fromCard as $group) {
285
			if (in_array($group, $current)) {
286
				continue;
287
			}
288
289
			$circle = new Circle(Circle::CIRCLES_PUBLIC, $group . ' - ' . $this->uuid(5));
0 ignored issues
show
Deprecated Code introduced by
The method OCA\Circles\Service\DavService::uuid() has been deprecated.

This method has been deprecated.

Loading history...
290
			$circle->setContactAddressBook($davCard->getAddressBookId());
291
			$circle->setContactGroupName($group);
292
293
			try {
294
				$this->circlesRequest->createCircle($circle, $davCard->getOwner());
295
				$member = new Member($davCard->getOwner(), Member::TYPE_USER, $circle->getUniqueId());
296
				$member->setLevel(Member::LEVEL_OWNER);
297
				$member->setStatus(Member::STATUS_MEMBER);
298
299
				try {
300
					$this->membersRequest->createMember($member);
301
				} catch (MemberAlreadyExistsException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
302
				}
303
			} catch (CircleAlreadyExistsException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
304
			}
305
306
		}
307
	}
308
309
310
	/**
311
	 * // TODO: Get all group from an addressbook
312
	 * // TODO: remove deprecated circles
313
	 *
314
	 * @param array $fromCard
315
	 * @param array $current
316
	 */
317
	private function manageDeprecatedCircles(array $fromCard, array $current) {
0 ignored issues
show
Unused Code introduced by
The parameter $fromCard is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $current is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
318
	}
319
320
321
	/**
322
	 * @param DavCard $davCard
323
	 */
324
	private function assignCirclesToCard(DavCard $davCard) {
325
		foreach ($davCard->getGroups() as $group) {
326
			try {
327
				$davCard->addCircle(
328
					$this->circlesRequest->getFromContactGroup($davCard->getAddressBookId(), $group)
329
				);
330
			} catch (CircleDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
331
			}
332
		}
333
	}
334
335
336
	/**
337
	 * @param int $addressBookId
338
	 *
339
	 * @return Circle[]
340
	 */
341
	private function getCirclesFromBook(int $addressBookId): array {
342
		return $this->circlesRequest->getFromBook($addressBookId);
343
	}
344
345
346
	/**
347
	 * @param int $length
348
	 *
349
	 * @return string
350
	 * @deprecated
351
	 */
352
	protected function uuid(int $length = 0): string {
353
		$uuid = sprintf(
354
			'%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
355
			mt_rand(0, 0xffff), mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
356
			mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
357
		);
358
359
		if ($length > 0) {
360
			if ($length <= 16) {
361
				$uuid = str_replace('-', '', $uuid);
362
			}
363
364
			$uuid = substr($uuid, 0, $length);
365
		}
366
367
		return $uuid;
368
	}
369
370
371
}
372
373
374