Passed
Push — master ( 34c7ea...03778d )
by John
11:13 queued 11s
created

ContactsSearchProvider::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2020, Georg Ehrke
7
 *
8
 * @author Georg Ehrke <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
namespace OCA\DAV\Search;
26
27
use OCA\DAV\CardDAV\CardDavBackend;
28
use OCP\App\IAppManager;
29
use OCP\IL10N;
30
use OCP\IURLGenerator;
31
use OCP\IUser;
32
use OCP\Search\IProvider;
33
use OCP\Search\ISearchQuery;
34
use OCP\Search\SearchResult;
35
use Sabre\VObject\Component\VCard;
36
use Sabre\VObject\Reader;
37
38
class ContactsSearchProvider implements IProvider {
39
40
	/** @var IAppManager */
41
	private $appManager;
42
43
	/** @var IL10N */
44
	private $l10n;
45
46
	/** @var IURLGenerator */
47
	private $urlGenerator;
48
49
	/** @var CardDavBackend */
50
	private $backend;
51
52
	/**
53
	 * @var string[]
54
	 */
55
	private static $searchProperties = [
56
		'N',
57
		'FN',
58
		'NICKNAME',
59
		'EMAIL',
60
		'ADR',
61
	];
62
63
	/**
64
	 * ContactsSearchProvider constructor.
65
	 *
66
	 * @param IAppManager $appManager
67
	 * @param IL10N $l10n
68
	 * @param IURLGenerator $urlGenerator
69
	 * @param CardDavBackend $backend
70
	 */
71
	public function __construct(IAppManager $appManager,
72
								IL10N $l10n,
73
								IURLGenerator $urlGenerator,
74
								CardDavBackend $backend) {
75
		$this->appManager = $appManager;
76
		$this->l10n = $l10n;
77
		$this->urlGenerator = $urlGenerator;
78
		$this->backend = $backend;
79
	}
80
81
	/**
82
	 * @inheritDoc
83
	 */
84
	public function getId(): string {
85
		return 'contacts-dav';
86
	}
87
88
	/**
89
	 * @inheritDoc
90
	 */
91
	public function getName(): string {
92
		return $this->l10n->t('Contacts');
93
	}
94
95
	/**
96
	 * @inheritDoc
97
	 */
98
	public function search(IUser $user, ISearchQuery $query): SearchResult {
99
		if (!$this->appManager->isEnabledForUser('contacts', $user)) {
100
			return SearchResult::complete($this->getName(), []);
101
		}
102
103
		$principalUri = 'principals/users/' . $user->getUID();
104
		$addressBooks = $this->backend->getAddressBooksForUser($principalUri);
105
		$addressBooksById = [];
106
		foreach ($addressBooks as $addressBook) {
107
			$addressBooksById[(int) $addressBook['id']] = $addressBook;
108
		}
109
110
		$searchResults = $this->backend->searchPrincipalUri(
111
			$principalUri,
112
			$query->getTerm(),
113
			self::$searchProperties,
114
			[
115
				'limit' => $query->getLimit(),
116
				'offset' => $query->getCursor(),
117
			]
118
		);
119
		$formattedResults = \array_map(function (array $contactRow) use ($addressBooksById):ContactsSearchResultEntry {
120
			$addressBook = $addressBooksById[$contactRow['addressbookid']];
121
122
			/** @var VCard $vCard */
123
			$vCard = Reader::read($contactRow['carddata']);
124
			$thumbnailUrl = '';
125
			if ($vCard->PHOTO) {
126
				$thumbnailUrl = $this->getDavUrlForContact($addressBook['principaluri'], $addressBook['uri'], $contactRow['uri']) . '?photo';
127
			}
128
129
			$title = (string)$vCard->FN;
130
			$subline = $this->generateSubline($vCard);
131
			$resourceUrl = $this->getDeepLinkToContactsApp($addressBook['uri'], (string) $vCard->UID);
132
133
			return new ContactsSearchResultEntry($thumbnailUrl, $title, $subline, $resourceUrl, 'icon-contacts-dark', true);
134
		}, $searchResults);
135
136
		return SearchResult::paginated(
137
			$this->getName(),
138
			$formattedResults,
139
			$query->getCursor() + count($formattedResults)
140
		);
141
	}
142
143
	/**
144
	 * @param string $principalUri
145
	 * @param string $addressBookUri
146
	 * @param string $contactsUri
147
	 * @return string
148
	 */
149
	protected function getDavUrlForContact(string $principalUri,
150
										   string $addressBookUri,
151
										   string $contactsUri): string {
152
		[, $principalType, $principalId] = explode('/', $principalUri, 3);
153
154
		return $this->urlGenerator->getAbsoluteURL(
155
			$this->urlGenerator->linkTo('', 'remote.php') . '/dav/addressbooks/'
156
				. $principalType . '/'
157
				. $principalId . '/'
158
				. $addressBookUri . '/'
159
				. $contactsUri
160
		);
161
	}
162
163
	/**
164
	 * @param string $addressBookUri
165
	 * @param string $contactUid
166
	 * @return string
167
	 */
168
	protected function getDeepLinkToContactsApp(string $addressBookUri,
169
												string $contactUid): string {
170
		return $this->urlGenerator->getAbsoluteURL(
171
			$this->urlGenerator->linkToRoute('contacts.contacts.direct', [
172
				'contact' => $contactUid . '~' . $addressBookUri
173
			])
174
		);
175
	}
176
177
	/**
178
	 * @param VCard $vCard
179
	 * @return string
180
	 */
181
	protected function generateSubline(VCard $vCard): string {
182
		$emailAddresses = $vCard->select('EMAIL');
183
		if (!is_array($emailAddresses) || empty($emailAddresses)) {
0 ignored issues
show
introduced by
The condition is_array($emailAddresses) is always true.
Loading history...
184
			return '';
185
		}
186
187
		return (string)$emailAddresses[0];
188
	}
189
}
190