Passed
Push — master ( 058135...a4d511 )
by John
13:28 queued 12s
created

ContactsSearchProvider::getOrder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
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 OCP\Search\SearchResultEntry;
36
use Sabre\VObject\Component\VCard;
37
use Sabre\VObject\Reader;
38
39
class ContactsSearchProvider implements IProvider {
40
41
	/** @var IAppManager */
42
	private $appManager;
43
44
	/** @var IL10N */
45
	private $l10n;
46
47
	/** @var IURLGenerator */
48
	private $urlGenerator;
49
50
	/** @var CardDavBackend */
51
	private $backend;
52
53
	/**
54
	 * @var string[]
55
	 */
56
	private static $searchProperties = [
57
		'N',
58
		'FN',
59
		'NICKNAME',
60
		'EMAIL',
61
		'ADR',
62
	];
63
64
	/**
65
	 * ContactsSearchProvider constructor.
66
	 *
67
	 * @param IAppManager $appManager
68
	 * @param IL10N $l10n
69
	 * @param IURLGenerator $urlGenerator
70
	 * @param CardDavBackend $backend
71
	 */
72
	public function __construct(IAppManager $appManager,
73
								IL10N $l10n,
74
								IURLGenerator $urlGenerator,
75
								CardDavBackend $backend) {
76
		$this->appManager = $appManager;
77
		$this->l10n = $l10n;
78
		$this->urlGenerator = $urlGenerator;
79
		$this->backend = $backend;
80
	}
81
82
	/**
83
	 * @inheritDoc
84
	 */
85
	public function getId(): string {
86
		return 'contacts-dav';
87
	}
88
89
	/**
90
	 * @inheritDoc
91
	 */
92
	public function getName(): string {
93
		return $this->l10n->t('Contacts');
94
	}
95
96
	/**
97
	 * @inheritDoc
98
	 */
99
	public function getOrder(): int {
100
		return 7;
101
	}
102
103
	/**
104
	 * @inheritDoc
105
	 */
106
	public function search(IUser $user, ISearchQuery $query): SearchResult {
107
		if (!$this->appManager->isEnabledForUser('contacts', $user)) {
108
			return SearchResult::complete($this->getName(), []);
109
		}
110
111
		$principalUri = 'principals/users/' . $user->getUID();
112
		$addressBooks = $this->backend->getAddressBooksForUser($principalUri);
113
		$addressBooksById = [];
114
		foreach ($addressBooks as $addressBook) {
115
			$addressBooksById[(int) $addressBook['id']] = $addressBook;
116
		}
117
118
		$searchResults = $this->backend->searchPrincipalUri(
119
			$principalUri,
120
			$query->getTerm(),
121
			self::$searchProperties,
122
			[
123
				'limit' => $query->getLimit(),
124
				'offset' => $query->getCursor(),
125
			]
126
		);
127
		$formattedResults = \array_map(function (array $contactRow) use ($addressBooksById):SearchResultEntry {
128
			$addressBook = $addressBooksById[$contactRow['addressbookid']];
129
130
			/** @var VCard $vCard */
131
			$vCard = Reader::read($contactRow['carddata']);
132
			$thumbnailUrl = '';
133
			if ($vCard->PHOTO) {
134
				$thumbnailUrl = $this->getDavUrlForContact($addressBook['principaluri'], $addressBook['uri'], $contactRow['uri']) . '?photo';
135
			}
136
137
			$title = (string)$vCard->FN;
138
			$subline = $this->generateSubline($vCard);
139
			$resourceUrl = $this->getDeepLinkToContactsApp($addressBook['uri'], (string) $vCard->UID);
140
141
			return new SearchResultEntry($thumbnailUrl, $title, $subline, $resourceUrl, 'icon-contacts-dark', true);
142
		}, $searchResults);
143
144
		return SearchResult::paginated(
145
			$this->getName(),
146
			$formattedResults,
147
			$query->getCursor() + count($formattedResults)
148
		);
149
	}
150
151
	/**
152
	 * @param string $principalUri
153
	 * @param string $addressBookUri
154
	 * @param string $contactsUri
155
	 * @return string
156
	 */
157
	protected function getDavUrlForContact(string $principalUri,
158
										   string $addressBookUri,
159
										   string $contactsUri): string {
160
		[, $principalType, $principalId] = explode('/', $principalUri, 3);
161
162
		return $this->urlGenerator->getAbsoluteURL(
163
			$this->urlGenerator->linkTo('', 'remote.php') . '/dav/addressbooks/'
164
				. $principalType . '/'
165
				. $principalId . '/'
166
				. $addressBookUri . '/'
167
				. $contactsUri
168
		);
169
	}
170
171
	/**
172
	 * @param string $addressBookUri
173
	 * @param string $contactUid
174
	 * @return string
175
	 */
176
	protected function getDeepLinkToContactsApp(string $addressBookUri,
177
												string $contactUid): string {
178
		return $this->urlGenerator->getAbsoluteURL(
179
			$this->urlGenerator->linkToRoute('contacts.contacts.direct', [
180
				'contact' => $contactUid . '~' . $addressBookUri
181
			])
182
		);
183
	}
184
185
	/**
186
	 * @param VCard $vCard
187
	 * @return string
188
	 */
189
	protected function generateSubline(VCard $vCard): string {
190
		$emailAddresses = $vCard->select('EMAIL');
191
		if (!is_array($emailAddresses) || empty($emailAddresses)) {
0 ignored issues
show
introduced by
The condition is_array($emailAddresses) is always true.
Loading history...
192
			return '';
193
		}
194
195
		return (string)$emailAddresses[0];
196
	}
197
}
198