Passed
Push — master ( 902adb...3cf321 )
by Christoph
10:44 queued 11s
created

ContactInteractionListener::handle()   C

Complexity

Conditions 12
Paths 44

Size

Total Lines 61
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 43
c 1
b 0
f 0
nc 44
nop 1
dl 0
loc 61
rs 6.9666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright 2020 Christoph Wurst <[email protected]>
7
 *
8
 * @author 2020 Christoph Wurst <[email protected]>
9
 *
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
namespace OCA\ContactsInteraction\Listeners;
27
28
use OCA\ContactsInteraction\Db\CardSearchDao;
29
use OCA\ContactsInteraction\Db\RecentContact;
30
use OCA\ContactsInteraction\Db\RecentContactMapper;
31
use OCP\AppFramework\Utility\ITimeFactory;
32
use OCP\Contacts\Events\ContactInteractedWithEvent;
33
use OCP\EventDispatcher\Event;
34
use OCP\EventDispatcher\IEventListener;
35
use OCP\IL10N;
36
use OCP\ILogger;
37
use OCP\IUserManager;
38
use Sabre\VObject\Component\VCard;
39
use Sabre\VObject\Reader;
40
use Sabre\VObject\UUIDUtil;
41
use Throwable;
42
43
class ContactInteractionListener implements IEventListener {
44
45
	/** @var RecentContactMapper */
46
	private $mapper;
47
48
	/** @var CardSearchDao */
49
	private $cardSearchDao;
50
51
	/** @var IUserManager */
52
	private $userManager;
53
54
	/** @var ITimeFactory */
55
	private $timeFactory;
56
57
	/** @var IL10N */
58
	private $l10n;
59
60
	/** @var ILogger */
61
	private $logger;
62
63
	public function __construct(RecentContactMapper $mapper,
64
								CardSearchDao $cardSearchDao,
65
								IUserManager $userManager,
66
								ITimeFactory $timeFactory,
67
								IL10N $l10nFactory,
68
								ILogger $logger) {
69
		$this->mapper = $mapper;
70
		$this->cardSearchDao = $cardSearchDao;
71
		$this->userManager = $userManager;
72
		$this->timeFactory = $timeFactory;
73
		$this->l10n = $l10nFactory;
74
		$this->logger = $logger;
75
	}
76
77
	public function handle(Event $event): void {
78
		if (!($event instanceof ContactInteractedWithEvent)) {
79
			return;
80
		}
81
82
		if ($event->getUid() === null && $event->getEmail() === null && $event->getFederatedCloudId() === null) {
83
			$this->logger->warning("Contact interaction event has no user identifier set");
84
			return;
85
		}
86
87
		$existing = $this->mapper->findMatch(
88
			$event->getActor(),
89
			$event->getUid(),
90
			$event->getEmail(),
91
			$event->getFederatedCloudId()
92
		);
93
		if (!empty($existing)) {
94
			$now = $this->timeFactory->getTime();
95
			foreach ($existing as $c) {
96
				$c->setLastContact($now);
97
				$this->mapper->update($c);
98
			}
99
100
			return;
101
		}
102
103
		$contact = new RecentContact();
104
		$contact->setActorUid($event->getActor()->getUID());
105
		if ($event->getUid() !== null) {
106
			$contact->setUid($event->getUid());
107
		}
108
		if ($event->getEmail() !== null) {
109
			$contact->setEmail($event->getEmail());
110
		}
111
		if ($event->getFederatedCloudId() !== null) {
112
			$contact->setFederatedCloudId($event->getFederatedCloudId());
113
		}
114
		$contact->setLastContact($this->timeFactory->getTime());
115
116
		$copy = $this->cardSearchDao->findExisting(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $copy is correct as $this->cardSearchDao->fi...>getFederatedCloudId()) targeting OCA\ContactsInteraction\...archDao::findExisting() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
117
			$event->getActor(),
118
			$event->getUid(),
119
			$event->getEmail(),
120
			$event->getFederatedCloudId()
121
		);
122
		if ($copy !== null) {
0 ignored issues
show
introduced by
The condition $copy !== null is always false.
Loading history...
123
			try {
124
				$parsed = Reader::read($copy, Reader::OPTION_FORGIVING);
125
				$parsed->CATEGORIES = $this->l10n->t('Recently contacted');
126
				$contact->setCard($parsed->serialize());
127
			} catch (Throwable $e) {
128
				$this->logger->logException($e, [
129
					'message' => 'Could not parse card to add recent category: ' . $e->getMessage(),
130
					'level' => ILogger::WARN,
131
				]);
132
				$contact->setCard($copy);
133
			}
134
		} else {
135
			$contact->setCard($this->generateCard($contact));
136
		}
137
		$this->mapper->insert($contact);
138
	}
139
140
	private function getDisplayName(?string $uid): ?string {
141
		if ($uid === null) {
142
			return null;
143
		}
144
		if (($user = $this->userManager->get($uid)) === null) {
145
			return null;
146
		}
147
148
		return $user->getDisplayName();
149
	}
150
151
	private function generateCard(RecentContact $contact): string {
152
		$props = [
153
			'URI' => UUIDUtil::getUUID(),
154
			'FN' => $this->getDisplayName($contact->getUid()) ?? $contact->getEmail() ?? $contact->getFederatedCloudId(),
155
			'CATEGORIES' => $this->l10n->t('Recently contacted'),
156
		];
157
158
		if ($contact->getUid() !== null) {
159
			$props['X-NEXTCLOUD-UID'] = $contact->getUid();
160
		}
161
		if ($contact->getEmail() !== null) {
162
			$props['EMAIL'] = $contact->getEmail();
163
		}
164
		if ($contact->getFederatedCloudId() !== null) {
165
			$props['CLOUD'] = $contact->getFederatedCloudId();
166
		}
167
168
		return (new VCard($props))->serialize();
169
	}
170
171
}
172