Passed
Push — master ( 9d1e2c...943229 )
by Morris
16:38 queued 56s
created

Search::dropMailSharesWhereRemoteShareIsPossible()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 16
nc 13
nop 1
dl 0
loc 26
rs 8.4444
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Arthur Schiwon <[email protected]>
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Christoph Wurst <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author onehappycat <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 *
11
 * @license GNU AGPL version 3 or any later version
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License as
15
 * published by the Free Software Foundation, either version 3 of the
16
 * License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License
24
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 */
27
28
namespace OC\Collaboration\Collaborators;
29
30
use OCP\Collaboration\Collaborators\ISearch;
31
use OCP\Collaboration\Collaborators\ISearchPlugin;
32
use OCP\Collaboration\Collaborators\ISearchResult;
33
use OCP\Collaboration\Collaborators\SearchResultType;
34
use OCP\IContainer;
35
use OCP\Share;
36
37
class Search implements ISearch {
38
	/** @var IContainer */
39
	private $c;
40
41
	protected $pluginList = [];
42
43
	public function __construct(IContainer $c) {
44
		$this->c = $c;
45
	}
46
47
	/**
48
	 * @param string $search
49
	 * @param array $shareTypes
50
	 * @param bool $lookup
51
	 * @param int|null $limit
52
	 * @param int|null $offset
53
	 * @return array
54
	 * @throws \OCP\AppFramework\QueryException
55
	 */
56
	public function search($search, array $shareTypes, $lookup, $limit, $offset) {
57
		$hasMoreResults = false;
58
59
		// Trim leading and trailing whitespace characters, e.g. when query is copy-pasted
60
		$search = trim($search);
61
62
		/** @var ISearchResult $searchResult */
63
		$searchResult = $this->c->resolve(SearchResult::class);
64
65
		foreach ($shareTypes as $type) {
66
			if (!isset($this->pluginList[$type])) {
67
				continue;
68
			}
69
			foreach ($this->pluginList[$type] as $plugin) {
70
				/** @var ISearchPlugin $searchPlugin */
71
				$searchPlugin = $this->c->resolve($plugin);
72
				$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
73
			}
74
		}
75
76
		// Get from lookup server, not a separate share type
77
		if ($lookup) {
78
			$searchPlugin = $this->c->resolve(LookupPlugin::class);
79
			$hasMoreResults = $searchPlugin->search($search, $limit, $offset, $searchResult) || $hasMoreResults;
0 ignored issues
show
Bug introduced by
The method search() does not exist on stdClass. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
			$hasMoreResults = $searchPlugin->/** @scrutinizer ignore-call */ search($search, $limit, $offset, $searchResult) || $hasMoreResults;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
		}
81
82
		// sanitizing, could go into the plugins as well
83
84
		// if we have an exact match, either for the federated cloud id or for the
85
		// email address, we only return the exact match. It is highly unlikely
86
		// that the exact same email address and federated cloud id exists
87
		$emailType = new SearchResultType('emails');
88
		$remoteType = new SearchResultType('remotes');
89
		if ($searchResult->hasExactIdMatch($emailType) && !$searchResult->hasExactIdMatch($remoteType)) {
90
			$searchResult->unsetResult($remoteType);
91
		} elseif (!$searchResult->hasExactIdMatch($emailType) && $searchResult->hasExactIdMatch($remoteType)) {
92
			$searchResult->unsetResult($emailType);
93
		}
94
95
		$this->dropMailSharesWhereRemoteShareIsPossible($searchResult);
96
97
		// if we have an exact local user match with an email-a-like query,
98
		// there is no need to show the remote and email matches.
99
		$userType = new SearchResultType('users');
100
		if (strpos($search, '@') !== false && $searchResult->hasExactIdMatch($userType)) {
101
			$searchResult->unsetResult($remoteType);
102
			$searchResult->unsetResult($emailType);
103
		}
104
105
		return [$searchResult->asArray(), $hasMoreResults];
106
	}
107
108
	public function registerPlugin(array $pluginInfo) {
109
		$shareType = constant(Share::class . '::' . $pluginInfo['shareType']);
110
		if ($shareType === null) {
111
			throw new \InvalidArgumentException('Provided ShareType is invalid');
112
		}
113
		$this->pluginList[$shareType][] = $pluginInfo['class'];
114
	}
115
116
	protected function dropMailSharesWhereRemoteShareIsPossible(ISearchResult $searchResult): void {
117
		$allResults = $searchResult->asArray();
118
119
		$emailType = new SearchResultType('emails');
120
		$remoteType = new SearchResultType('remotes');
121
122
		if (!isset($allResults[$remoteType->getLabel()])
123
			|| !isset($allResults[$emailType->getLabel()])) {
124
			return;
125
		}
126
127
		$mailIdMap = [];
128
		foreach ($allResults[$emailType->getLabel()] as $mailRow) {
129
			// sure, array_reduce looks nicer, but foreach needs less resources and is faster
130
			if (!isset($mailRow['uuid'])) {
131
				continue;
132
			}
133
			$mailIdMap[$mailRow['uuid']] = $mailRow['value']['shareWith'];
134
		}
135
136
		foreach ($allResults[$remoteType->getLabel()] as $resultRow) {
137
			if (!isset($resultRow['uuid'])) {
138
				continue;
139
			}
140
			if (isset($mailIdMap[$resultRow['uuid']])) {
141
				$searchResult->removeCollaboratorResult($emailType, $mailIdMap[$resultRow['uuid']]);
142
			}
143
		}
144
	}
145
}
146