Completed
Pull Request — master (#551)
by Maxence
84:52
created

MemberAdd::getUnknownShares()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18

Duplication

Lines 18
Ratio 100 %

Importance

Changes 0
Metric Value
dl 18
loc 18
rs 9.6666
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\FederatedItems;
33
34
35
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
36
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
37
use daita\MySmallPhpTools\Exceptions\SignatoryException;
38
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21Logger;
39
use daita\MySmallPhpTools\Traits\TStringTools;
40
use Exception;
41
use OC\User\NoUserException;
42
use OCA\Circles\Db\MemberRequest;
43
use OCA\Circles\Exceptions\CircleNotFoundException;
44
use OCA\Circles\Exceptions\FederatedUserException;
45
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
46
use OCA\Circles\Exceptions\InvalidIdException;
47
use OCA\Circles\Exceptions\MemberAlreadyExistsException;
48
use OCA\Circles\Exceptions\MemberNotFoundException;
49
use OCA\Circles\Exceptions\MembersLimitException;
50
use OCA\Circles\Exceptions\MemberTypeNotFoundException;
51
use OCA\Circles\Exceptions\OwnerNotFoundException;
52
use OCA\Circles\Exceptions\RemoteInstanceException;
53
use OCA\Circles\Exceptions\RemoteNotFoundException;
54
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
55
use OCA\Circles\Exceptions\TokenDoesNotExistException;
56
use OCA\Circles\Exceptions\UnknownRemoteException;
57
use OCA\Circles\Exceptions\UserTypeNotFoundException;
58
use OCA\Circles\IFederatedItem;
59
use OCA\Circles\IFederatedItemAsync;
60
use OCA\Circles\IFederatedItemMemberCheckNotRequired;
61
use OCA\Circles\IFederatedItemMemberRequired;
62
use OCA\Circles\IFederatedUser;
63
use OCA\Circles\Model\DeprecatedCircle;
64
use OCA\Circles\Model\DeprecatedMember;
65
use OCA\Circles\Model\Federated\FederatedEvent;
66
use OCA\Circles\Model\FederatedUser;
67
use OCA\Circles\Model\Helpers\MemberHelper;
68
use OCA\Circles\Model\ManagedModel;
69
use OCA\Circles\Model\Member;
70
use OCA\Circles\Model\SharesToken;
71
use OCA\Circles\Service\CircleService;
72
use OCA\Circles\Service\ConfigService;
73
use OCA\Circles\Service\FederatedUserService;
74
use OCP\IUser;
75
use OCP\IUserManager;
76
use OCP\Mail\IEMailTemplate;
77
use OCP\Util;
78
79
80
/**
81
 * Class MemberAdd
82
 *
83
 * @package OCA\Circles\GlobalScale
84
 */
85
class MemberAdd implements
86
	IFederatedItem,
87
	IFederatedItemAsync,
88
	IFederatedItemMemberRequired,
89
	IFederatedItemMemberCheckNotRequired {
90
91
92
	use TStringTools;
93
	use TNC21Logger;
94
95
96
	/** @var IUserManager */
97
	private $userManager;
98
99
	/** @var FederatedUserService */
100
	private $federatedUserService;
101
102
	/** @var MemberRequest */
103
	private $memberRequest;
104
105
	/** @var CircleService */
106
	private $circleService;
107
108
	/** @var ConfigService */
109
	private $configService;
110
111
112
	/**
113
	 * MemberAdd constructor.
114
	 *
115
	 * @param IUserManager $userManager
116
	 * @param FederatedUserService $federatedUserService
117
	 * @param MemberRequest $memberRequest
118
	 * @param CircleService $circleService
119
	 * @param ConfigService $configService
120
	 */
121 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...
122
		IUserManager $userManager, FederatedUserService $federatedUserService, MemberRequest $memberRequest,
123
		CircleService $circleService, ConfigService $configService
124
	) {
125
		$this->userManager = $userManager;
126
		$this->federatedUserService = $federatedUserService;
127
		$this->memberRequest = $memberRequest;
128
		$this->circleService = $circleService;
129
		$this->configService = $configService;
130
	}
131
132
133
	/**
134
	 * @param FederatedEvent $event
135
	 *
136
	 * @throws CircleNotFoundException
137
	 * @throws FederatedUserException
138
	 * @throws FederatedUserNotFoundException
139
	 * @throws InvalidIdException
140
	 * @throws InvalidItemException
141
	 * @throws MemberAlreadyExistsException
142
	 * @throws MembersLimitException
143
	 * @throws OwnerNotFoundException
144
	 * @throws RemoteInstanceException
145
	 * @throws RemoteNotFoundException
146
	 * @throws RemoteResourceNotFoundException
147
	 * @throws RequestNetworkException
148
	 * @throws SignatoryException
149
	 * @throws UnknownRemoteException
150
	 * @throws UserTypeNotFoundException
151
	 * @throws MemberNotFoundException
152
	 */
153
	public function verify(FederatedEvent $event): void {
154
		$member = $event->getMember();
155
		$circle = $event->getCircle();
156
		$initiator = $circle->getInitiator();
157
158
		$member->setCircleId($circle->getId());
159
160
		$initiatorHelper = new MemberHelper($initiator);
161
		$initiatorHelper->mustBeModerator();
162
163
		$federatedId = $member->getUserId() . '@' . $member->getInstance();
164
		try {
165
			$federatedUser =
166
				$this->federatedUserService->getFederatedUser($federatedId, $member->getUserType());
167
		} catch (MemberNotFoundException $e) {
168
			throw new MemberNotFoundException(
169
				ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' %s not found',
170
				['member' => $member->getUserId() . '@' . $member->getInstance()]
171
			);
172
		}
173
		$member->importFromIFederatedUser($federatedUser);
174
175
		try {
176
			$knownMember = $this->memberRequest->searchMember($member);
0 ignored issues
show
Unused Code introduced by
$knownMember 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...
177
			// TODO: maybe member is requesting access
178
			throw new MemberAlreadyExistsException(
179
				ucfirst(Member::$DEF_TYPE[$member->getUserType()]) . ' %s is already a member',
180
				['member' => $member->getUserId() . '@' . $member->getInstance()]
181
			);
182
		} catch (MemberNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
183
		}
184
185
		$member->setId($this->uuid(ManagedModel::ID_LENGTH));
186
187
		// TODO: check Config on Circle to know if we set Level to 1 or just send an invitation
188
		$member->setLevel(Member::LEVEL_MEMBER);
189
		$member->setStatus(Member::STATUS_MEMBER);
190
		$event->setDataOutcome(['member' => $member]);
191
192
		// TODO: Managing cached name
193
		//		$member->setCachedName($eventMember->getCachedName());
194
		$this->circleService->confirmCircleNotFull($circle);
195
196
		// TODO: check if it is a member or a mail or a circle and fix the returned message
197
		$event->setReadingOutcome('Member %s have been added to Circle', ['userId' => $member->getUserId()]);
198
199
		return;
200
201
202
//		$member = $this->membersRequest->getFreshNewMember(
203
//			$circle->getUniqueId(), $ident, $eventMember->getType(), $eventMember->getInstance()
204
//		);
205
//		$member->hasToBeInviteAble()
206
//
207
//		$this->membersService->addMemberBasedOnItsType($circle, $member);
208
//
209
//		$password = '';
210
//		$sendPasswordByMail = false;
211
//		if ($this->configService->enforcePasswordProtection($circle)) {
212
//			if ($circle->getSetting('password_single_enabled') === 'true') {
213
//				$password = $circle->getPasswordSingle();
214
//			} else {
215
//				$sendPasswordByMail = true;
216
//				$password = $this->miscService->token(15);
217
//			}
218
//		}
219
//
220
//		$event->setData(
221
//			new SimpleDataStore(
222
//				[
223
//					'password'       => $password,
224
//					'passwordByMail' => $sendPasswordByMail
225
//				]
226
//			)
227
//		);
228
	}
229
230
231
	/**
232
	 * @param FederatedEvent $event
233
	 *
234
	 * @throws InvalidIdException
235
	 */
236
	public function manage(FederatedEvent $event): void {
237
		$member = $event->getMember();
238
239
		try {
240
			$this->memberRequest->getMember($member->getId());
241
242
			return;
243
		} catch (MemberNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
244
		}
245
246
		try {
247
			$federatedUser = new FederatedUser();
248
			$federatedUser->importFromIFederatedUser($member);
249
			$this->federatedUserService->confirmLocalSingleId($federatedUser);
250
		} catch (FederatedUserException $e) {
251
			$this->e($e, ['member' => $member]);
252
253
			return;
254
		}
255
256
		$this->memberRequest->save($member);
257
258
//
259
//		//
260
//		// TODO: verifiez comment se passe le cached name sur un member_add
261
//		//
262
//		$cachedName = $member->getCachedName();
263
//		$password = $event->getData()
264
//						  ->g('password');
265
//
266
//		$shares = $this->generateUnknownSharesLinks($circle, $member, $password);
267
//		$result = [
268
//			'unknownShares' => $shares,
269
//			'cachedName'    => $cachedName
270
//		];
271
//
272
//		if ($member->getType() === DeprecatedMember::TYPE_CONTACT
273
//			&& $this->configService->isLocalInstance($member->getInstance())) {
274
//			$result['contact'] = $this->miscService->getInfosFromContact($member);
275
//		}
276
//
277
//		$event->setResult(new SimpleDataStore($result));
278
//		$this->eventsService->onMemberNew($circle, $member);
279
	}
280
281
282
	/**
283
	 * @param FederatedEvent[] $events
284
	 *
285
	 * @throws Exception
286
	 */
287
	public function result(array $events): void {
288
//		$password = $cachedName = '';
289
//		$circle = $member = null;
290
//		$links = [];
291
//		$recipients = [];
292
//		foreach ($events as $event) {
293
//			$data = $event->getData();
294
//			if ($data->gBool('passwordByMail') !== false) {
295
//				$password = $data->g('password');
296
//			}
297
//			$circle = $event->getDeprecatedCircle();
298
//			$member = $event->getMember();
299
//			$result = $event->getResult();
300
//			if ($result->g('cachedName') !== '') {
301
//				$cachedName = $result->g('cachedName');
302
//			}
303
//
304
//			$links = array_merge($links, $result->gArray('unknownShares'));
305
//			$contact = $result->gArray('contact');
306
//			if (!empty($contact)) {
307
//				$recipients = $contact['emails'];
308
//			}
309
//		}
310
//
311
//		if (empty($links) || $circle === null || $member === null) {
312
//			return;
313
//		}
314
//
315
//		if ($cachedName !== '') {
316
//			$member->setCachedName($cachedName);
317
//			$this->membersService->updateMember($member);
318
//		}
319
//
320
//		if ($member->getType() === DeprecatedMember::TYPE_MAIL
321
//			|| $member->getType() === DeprecatedMember::TYPE_CONTACT) {
322
//			if ($member->getType() === DeprecatedMember::TYPE_MAIL) {
323
//				$recipients = [$member->getUserId()];
324
//			}
325
//
326
//			foreach ($recipients as $recipient) {
327
//				$this->memberIsMailbox($circle, $recipient, $links, $password);
328
//			}
329
//		}
330
	}
331
332
333
	/**
334
	 * confirm the validity of a UserId, based on UserType.
335
	 *
336
	 * @param IFederatedUser $member
337
	 *
338
	 * @throws FederatedUserException
339
	 * @throws InvalidIdException
340
	 * @throws UserTypeNotFoundException
341
	 * @throws CircleNotFoundException
342
	 * @throws FederatedUserNotFoundException
343
	 * @throws OwnerNotFoundException
344
	 * @throws RemoteInstanceException
345
	 * @throws RemoteNotFoundException
346
	 * @throws RemoteResourceNotFoundException
347
	 * @throws UnknownRemoteException
348
	 * @throws InvalidItemException
349
	 * @throws RequestNetworkException
350
	 * @throws SignatoryException
351
	 */
352
	private function confirmMember(IFederatedUser $member): void {
353
354
		// TODO: confirm SingleId ???
355
//		switch ($member->getUserType()) {
356
//			case Member::TYPE_USER:
357
		$this->federatedUserService->getFederatedUser($member->getUserId(), $member->getUserType());
358
//				break;
359
//
360
//			// TODO: confirm other UserType
361
//			default:
362
//				break;
363
////				throw new UserTypeNotFoundException();
364
//		}
365
	}
366
367
368
	/**
369
	 * @param IFederatedUser $member
370
	 *
371
	 * @throws NoUserException
372
	 */
373
	private function confirmMemberTypeUser(IFederatedUser $member): void {
374
		if ($this->configService->isLocalInstance($member->getInstance())) {
375
			$user = $this->userManager->get($member->getUserId());
376
			if ($user === null) {
377
				throw new NoUserException('user not found');
378
			}
379
380
			$member->setUserId($user->getUID());
381
382
			return;
383
		}
384
385
		// TODO #M002: request the remote instance and check that user exists
386
	}
387
388
//	/**
389
//	 * Verify if a local account is valid.
390
//	 *
391
//	 * @param $ident
392
//	 * @param $type
393
//	 *
394
//	 * @param string $instance
395
//	 *
396
//	 * @throws NoUserException
397
//	 */
398
//	private function verifyIdentLocalMember(&$ident, $type, string $instance = '') {
399
//		if ($type !== DeprecatedMember::TYPE_USER) {
400
//			return;
401
//		}
402
//
403
//		if ($instance === '') {
404
//			try {
405
//				$ident = $this->miscService->getRealUserId($ident);
406
//			} catch (NoUserException $e) {
407
//				throw new NoUserException($this->l10n->t("This user does not exist"));
408
//			}
409
//		}
410
//	}
411
//
412
//
413
//	/**
414
//	 * Verify if a mail have a valid format.
415
//	 *
416
//	 * @param string $ident
417
//	 * @param int $type
418
//	 *
419
//	 * @throws EmailAccountInvalidFormatException
420
//	 */
421
//	private function verifyIdentEmailAddress(string $ident, int $type) {
422
//		if ($type !== DeprecatedMember::TYPE_MAIL) {
423
//			return;
424
//		}
425
//
426
//		if ($this->configService->isAccountOnly()) {
427
//			throw new EmailAccountInvalidFormatException(
428
//				$this->l10n->t('You cannot add a mail address as member of your Circle')
429
//			);
430
//		}
431
//
432
//		if (!filter_var($ident, FILTER_VALIDATE_EMAIL)) {
433
//			throw new EmailAccountInvalidFormatException(
434
//				$this->l10n->t('Email format is not valid')
435
//			);
436
//		}
437
//	}
438
//
439
//
440
//	/**
441
//	 * Verify if a contact exist in current user address books.
442
//	 *
443
//	 * @param $ident
444
//	 * @param $type
445
//	 *
446
//	 * @throws NoUserException
447
//	 * @throws EmailAccountInvalidFormatException
448
//	 */
449
//	private function verifyIdentContact(&$ident, $type) {
450
//		if ($type !== DeprecatedMember::TYPE_CONTACT) {
451
//			return;
452
//		}
453
//
454
//		if ($this->configService->isAccountOnly()) {
455
//			throw new EmailAccountInvalidFormatException(
456
//				$this->l10n->t('You cannot add a contact as member of your Circle')
457
//			);
458
//		}
459
//
460
//		$tmpContact = $this->userId . ':' . $ident;
461
//		$result = MiscService::getContactData($tmpContact);
462
//		if (empty($result)) {
463
//			throw new NoUserException($this->l10n->t("This contact is not available"));
464
//		}
465
//
466
//		$ident = $tmpContact;
467
//	}
468
469
470
	/**
471
	 * @param DeprecatedCircle $circle
472
	 * @param string $recipient
473
	 * @param array $links
474
	 * @param string $password
475
	 */
476 View Code Duplication
	private function memberIsMailbox(
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...
477
		DeprecatedCircle $circle, string $recipient, array $links, string $password
478
	) {
479
		if ($circle->getViewer() === null) {
480
			$author = $circle->getOwner()
481
							 ->getUserId();
482
		} else {
483
			$author = $circle->getViewer()
484
							 ->getUserId();
485
		}
486
487
		try {
488
			$template = $this->generateMailExitingShares($author, $circle->getName());
489
			$this->fillMailExistingShares($template, $links);
490
			$this->sendMailExistingShares($template, $author, $recipient);
491
			$this->sendPasswordExistingShares($author, $recipient, $password);
492
		} catch (Exception $e) {
493
			$this->miscService->log('Failed to send mail about existing share ' . $e->getMessage());
0 ignored issues
show
Bug introduced by
The property miscService does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
494
		}
495
	}
496
497
498
	/**
499
	 * @param DeprecatedCircle $circle
500
	 * @param DeprecatedMember $member
501
	 * @param string $password
502
	 *
503
	 * @return array
504
	 */
505 View Code Duplication
	private function generateUnknownSharesLinks(
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...
506
		DeprecatedCircle $circle, DeprecatedMember $member, string $password
0 ignored issues
show
Unused Code introduced by
The parameter $circle 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...
507
	): array {
508
		$unknownShares = $this->getUnknownShares($member);
509
510
		$data = [];
511
		foreach ($unknownShares as $share) {
512
			try {
513
				$data[] = $this->getMailLinkFromShare($share, $member, $password);
514
			} catch (TokenDoesNotExistException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
515
			}
516
		}
517
518
		return $data;
519
	}
520
521
522
	/**
523
	 * @param DeprecatedMember $member
524
	 *
525
	 * @return array
526
	 */
527 View Code Duplication
	private function getUnknownShares(DeprecatedMember $member): array {
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...
528
		$allShares = $this->sharesRequest->getSharesForCircle($member->getCircleId());
0 ignored issues
show
Bug introduced by
The property sharesRequest does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
529
		$knownShares = array_map(
530
			function(SharesToken $shareToken) {
531
				return $shareToken->getShareId();
532
			},
533
			$this->tokensRequest->getTokensFromMember($member)
0 ignored issues
show
Bug introduced by
The property tokensRequest does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
534
		);
535
536
		$unknownShares = [];
537
		foreach ($allShares as $share) {
538
			if (!in_array($share['id'], $knownShares)) {
539
				$unknownShares[] = $share;
540
			}
541
		}
542
543
		return $unknownShares;
544
	}
545
546
547
	/**
548
	 * @param array $share
549
	 * @param DeprecatedMember $member
550
	 * @param string $password
551
	 *
552
	 * @return array
553
	 * @throws TokenDoesNotExistException
554
	 */
555 View Code Duplication
	private function getMailLinkFromShare(array $share, DeprecatedMember $member, string $password = '') {
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...
556
		$sharesToken = $this->tokensRequest->generateTokenForMember($member, (int)$share['id'], $password);
557
		$link = $this->urlGenerator->linkToRouteAbsolute(
0 ignored issues
show
Bug introduced by
The property urlGenerator does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
558
			'files_sharing.sharecontroller.showShare',
559
			['token' => $sharesToken->getToken()]
560
		);
561
		$author = $share['uid_initiator'];
562
		$filename = basename($share['file_target']);
563
564
		return [
565
			'author'   => $author,
566
			'link'     => $link,
567
			'filename' => $filename
568
		];
569
	}
570
571
572
	/**
573
	 * @param string $author
574
	 * @param string $circleName
575
	 *
576
	 * @return IEMailTemplate
577
	 */
578 View Code Duplication
	private function generateMailExitingShares(string $author, string $circleName): IEMailTemplate {
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...
579
		$emailTemplate = $this->mailer->createEMailTemplate('circles.ExistingShareNotification', []);
0 ignored issues
show
Bug introduced by
The property mailer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
580
		$emailTemplate->addHeader();
581
582
		$text = $this->l10n->t('%s shared multiple files with \'%s\'.', [$author, $circleName]);
0 ignored issues
show
Bug introduced by
The property l10n does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
583
		$emailTemplate->addBodyText(htmlspecialchars($text), $text);
584
585
		return $emailTemplate;
586
	}
587
588
	/**
589
	 * @param IEMailTemplate $emailTemplate
590
	 * @param array $links
591
	 */
592 View Code Duplication
	private function fillMailExistingShares(IEMailTemplate $emailTemplate, array $links) {
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...
593
		foreach ($links as $item) {
594
			$emailTemplate->addBodyButton(
595
				$this->l10n->t('Open »%s«', [htmlspecialchars($item['filename'])]), $item['link']
596
			);
597
		}
598
	}
599
600
601
	/**
602
	 * @param IEMailTemplate $emailTemplate
603
	 * @param string $author
604
	 * @param string $recipient
605
	 *
606
	 * @throws Exception
607
	 */
608 View Code Duplication
	private function sendMailExistingShares(IEMailTemplate $emailTemplate, string $author, string $recipient
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...
609
	) {
610
		$subject = $this->l10n->t('%s shared multiple files with you.', [$author]);
611
612
		$instanceName = $this->defaults->getName();
0 ignored issues
show
Bug introduced by
The property defaults does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
613
		$senderName = $this->l10n->t('%s on %s', [$author, $instanceName]);
614
615
		$message = $this->mailer->createMessage();
616
617
		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
618
		$message->setSubject($subject);
619
		$message->setPlainBody($emailTemplate->renderText());
620
		$message->setHtmlBody($emailTemplate->renderHtml());
621
		$message->setTo([$recipient]);
622
623
		$this->mailer->send($message);
624
	}
625
626
627
	/**
628
	 * @param string $author
629
	 * @param string $email
630
	 * @param string $password
631
	 *
632
	 * @throws Exception
633
	 */
634
	protected function sendPasswordExistingShares(string $author, string $email, string $password) {
635
		if ($password === '') {
636
			return;
637
		}
638
639
		$message = $this->mailer->createMessage();
640
641
		$authorUser = $this->userManager->get($author);
642
		$authorName = ($authorUser instanceof IUser) ? $authorUser->getDisplayName() : $author;
0 ignored issues
show
Bug introduced by
The class OCP\IUser does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
643
		$authorEmail = ($authorUser instanceof IUser) ? $authorUser->getEMailAddress() : null;
0 ignored issues
show
Bug introduced by
The class OCP\IUser does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
644
645
		$this->miscService->log("Sending password mail about existing files to '" . $email . "'", 0);
646
647
		$plainBodyPart = $this->l10n->t(
648
			"%1\$s shared multiple files with you.\nYou should have already received a separate mail with a link to access them.\n",
649
			[$authorName]
650
		);
651
		$htmlBodyPart = $this->l10n->t(
652
			'%1$s shared multiple files with you. You should have already received a separate mail with a link to access them.',
653
			[$authorName]
654
		);
655
656
		$emailTemplate = $this->mailer->createEMailTemplate(
657
			'sharebymail.RecipientPasswordNotification', [
658
														   'password' => $password,
659
														   'author'   => $author
660
													   ]
661
		);
662
663
		$emailTemplate->setSubject(
664
			$this->l10n->t(
665
				'Password to access files shared to you by %1$s', [$authorName]
666
			)
667
		);
668
		$emailTemplate->addHeader();
669
		$emailTemplate->addHeading($this->l10n->t('Password to access files'), false);
670
		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
671
		$emailTemplate->addBodyText($this->l10n->t('It is protected with the following password:'));
672
		$emailTemplate->addBodyText($password);
673
674
		// The "From" contains the sharers name
675
		$instanceName = $this->defaults->getName();
676
		$senderName = $this->l10n->t(
677
			'%1$s via %2$s',
678
			[
679
				$authorName,
680
				$instanceName
681
			]
682
		);
683
684
		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
685
		if ($authorEmail !== null) {
686
			$message->setReplyTo([$authorEmail => $authorName]);
687
			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
688
		} else {
689
			$emailTemplate->addFooter();
690
		}
691
692
		$message->setTo([$email]);
693
		$message->useTemplate($emailTemplate);
694
		$this->mailer->send($message);
695
	}
696
697
}
698