Completed
Branch master (420c52)
by
unknown
26:22
created

SearchApi::buildCommonApiParams()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 48
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 31
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 48
rs 8.7396
1
<?php
2
use MediaWiki\MediaWikiServices;
3
4
/**
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @since 1.28
22
 */
23
24
/**
25
 * Traits for API components that use a SearchEngine.
26
 * @ingroup API
27
 */
28
trait SearchApi {
29
30
	/**
31
	 * When $wgSearchType is null, $wgSearchAlternatives[0] is null. Null isn't
32
	 * a valid option for an array for PARAM_TYPE, so we'll use a fake name
33
	 * that can't possibly be a class name and describes what the null behavior
34
	 * does
35
	 */
36
	private static $BACKEND_NULL_PARAM = 'database-backed';
37
38
	/**
39
	 * The set of api parameters that are shared between api calls that
40
	 * call the SearchEngine. Primarily this defines parameters that
41
	 * are utilized by self::buildSearchEngine().
42
	 *
43
	 * @param bool $isScrollable True if the api offers scrolling
44
	 * @return array
45
	 */
46
	public function buildCommonApiParams( $isScrollable = true ) {
47
		$params = [
48
			'search' => [
49
				ApiBase::PARAM_TYPE => 'string',
50
				ApiBase::PARAM_REQUIRED => true,
51
			],
52
			'namespace' => [
53
				ApiBase::PARAM_DFLT => NS_MAIN,
54
				ApiBase::PARAM_TYPE => 'namespace',
55
				ApiBase::PARAM_ISMULTI => true,
56
			],
57
			'limit' => [
58
				ApiBase::PARAM_DFLT => 10,
59
				ApiBase::PARAM_TYPE => 'limit',
60
				ApiBase::PARAM_MIN => 1,
61
				ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
62
				ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
63
			],
64
		];
65
		if ( $isScrollable ) {
66
			$params['offset'] = [
67
				ApiBase::PARAM_DFLT => 0,
68
				ApiBase::PARAM_TYPE => 'integer',
69
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
70
			];
71
		}
72
73
		$searchConfig = MediaWikiServices::getInstance()->getSearchEngineConfig();
74
		$alternatives = $searchConfig->getSearchTypes();
75
		if ( count( $alternatives ) > 1 ) {
76
			if ( $alternatives[0] === null ) {
77
				$alternatives[0] = self::$BACKEND_NULL_PARAM;
78
			}
79
			$this->allowedParams['backend'] = [
0 ignored issues
show
Bug introduced by
The property allowedParams 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...
80
				ApiBase::PARAM_DFLT => $searchConfig->getSearchType(),
81
				ApiBase::PARAM_TYPE => $alternatives,
82
			];
83
			// @todo: support profile selection when multiple
84
			// backends are available. The solution could be to
85
			// merge all possible profiles and let ApiBase
86
			// subclasses do the check. Making ApiHelp and ApiSandbox
87
			// comprehensive might be more difficult.
88
		} else {
89
			$params += $this->buildProfileApiParam();
90
		}
91
92
		return $params;
93
	}
94
95
	/**
96
	 * Build the profile api param definitions. Makes bold assumption only one search
97
	 * engine is available, ensure that is true before calling.
98
	 *
99
	 * @return array array containing available additional api param definitions.
100
	 *  Empty if profiles are not supported by the searchEngine implementation.
101
	 */
102
	private function buildProfileApiParam() {
103
		$configs = $this->getSearchProfileParams();
104
		$searchEngine = MediaWikiServices::getInstance()->newSearchEngine();
105
		$params = [];
106
		foreach ( $configs as $paramName => $paramConfig ) {
107
			$profiles = $searchEngine->getProfiles( $paramConfig['profile-type'] );
108
			if ( !$profiles ) {
109
				continue;
110
			}
111
112
			$types = [];
113
			$helpMessages = [];
114
			$defaultProfile = null;
115
			foreach ( $profiles as $profile ) {
116
				$types[] = $profile['name'];
117
				if ( isset ( $profile['desc-message'] ) ) {
118
					$helpMessages[$profile['name']] = $profile['desc-message'];
119
				}
120
				if ( !empty( $profile['default'] ) ) {
121
					$defaultProfile = $profile['name'];
122
				}
123
			}
124
125
			$params[$paramName] = [
126
				ApiBase::PARAM_TYPE => $types,
127
				ApiBase::PARAM_HELP_MSG => $paramConfig['help-message'],
128
				ApiBase::PARAM_HELP_MSG_PER_VALUE => $helpMessages,
129
				ApiBase::PARAM_DFLT => $defaultProfile,
130
			];
131
		}
132
133
		return $params;
134
	}
135
136
	/**
137
	 * Build the search engine to use.
138
	 * If $params is provided then the following searchEngine options
139
	 * will be set:
140
	 *  - backend: which search backend to use
141
	 *  - limit: mandatory
142
	 *  - offset: optional, if set limit will be incremented by
143
	 *    one ( to support the continue parameter )
144
	 *  - namespace: mandatory
145
	 *  - search engine profiles defined by SearchApi::getSearchProfileParams()
146
	 * @param string[]|null API request params (must be sanitized by
147
	 * ApiBase::extractRequestParams() before)
148
	 * @return SearchEngine the search engine
149
	 */
150
	public function buildSearchEngine( array $params = null ) {
151
		if ( $params != null ) {
152
			$type = isset( $params['backend'] ) ? $params['backend'] : null;
153
			if ( $type === self::$BACKEND_NULL_PARAM ) {
154
				$type = null;
155
			}
156
			$searchEngine = MediaWikiServices::getInstance()->getSearchEngineFactory()->create( $type );
157
			$limit = $params['limit'];
158
			$searchEngine->setNamespaces( $params['namespace'] );
159
			$offset = null;
160
			if ( isset( $params['offset'] ) ) {
161
				// If the API supports offset then it probably
162
				// wants to fetch limit+1 so it can check if
163
				// more results are available to properly set
164
				// the continue param
165
				$offset = $params['offset'];
166
				$limit += 1;
167
			}
168
			$searchEngine->setLimitOffset( $limit, $offset );
169
170
			// Initialize requested search profiles.
171
			$configs = $this->getSearchProfileParams();
172
			foreach ( $configs as $paramName => $paramConfig ) {
173
				if ( isset( $params[$paramName] ) ) {
174
					$searchEngine->setFeatureData(
175
						$paramConfig['profile-type'],
176
						$params[$paramName]
177
					);
178
				}
179
			}
180
		} else {
181
			$searchEngine = MediaWikiServices::getInstance()->newSearchEngine();
182
		}
183
		return $searchEngine;
184
	}
185
186
	/**
187
	 * @return array[] array of arrays mapping from parameter name to a two value map
188
	 *  containing 'help-message' and 'profile-type' keys.
189
	 */
190
	abstract public function getSearchProfileParams();
191
}
192