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.
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.
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
24 use MediaWiki\MediaWikiServices
;
27 * @todo FIXME: This class is horribly factored. It would probably be better to
28 * have a useful base class to which you pass some standard information, then
29 * let the fancy self-highlighters extend that.
37 protected $mRevision = null;
42 protected $mImage = null;
57 protected $searchEngine;
60 * A function returning a set of extension data.
63 protected $extensionData;
66 * Return a new SearchResult and initializes it with a title.
69 * @param ISearchResultSet|null $parentSet
70 * @return SearchResult
72 public static function newFromTitle( $title, ISearchResultSet
$parentSet = null ) {
73 $result = new static();
74 $result->initFromTitle( $title );
76 $parentSet->augmentResult( $result );
82 * Initialize from a Title and if possible initializes a corresponding
87 protected function initFromTitle( $title ) {
88 $this->mTitle
= $title;
89 $services = MediaWikiServices
::getInstance();
90 if ( !is_null( $this->mTitle
) ) {
92 Hooks
::run( 'SearchResultInitFromTitle', [ $title, &$id ] );
93 $this->mRevision
= Revision
::newFromTitle(
94 $this->mTitle
, $id, Revision
::READ_NORMAL
);
95 if ( $this->mTitle
->getNamespace() === NS_FILE
) {
96 $this->mImage
= $services->getRepoGroup()->findFile( $this->mTitle
);
99 $this->searchEngine
= $services->newSearchEngine();
103 * Check if this is result points to an invalid title
107 public function isBrokenTitle() {
108 return is_null( $this->mTitle
);
112 * Check if target page is missing, happens when index is out of date
116 public function isMissingRevision() {
117 return !$this->mRevision
&& !$this->mImage
;
123 public function getTitle() {
124 return $this->mTitle
;
128 * Get the file for this page, if one exists
131 public function getFile() {
132 return $this->mImage
;
136 * Lazy initialization of article text from DB
138 protected function initText() {
139 if ( !isset( $this->mText
) ) {
140 if ( $this->mRevision
!= null ) {
141 $content = $this->mRevision
->getContent();
142 $this->mText
= $content !== null ?
$content->getTextForSearchIndex() : '';
143 } else { // TODO: can we fetch raw wikitext for commons images?
150 * @param string[] $terms Terms to highlight (this parameter is deprecated and ignored)
151 * @return string Highlighted text snippet, null (and not '') if not supported
153 public function getTextSnippet( $terms = [] ) {
158 * @return string Highlighted title, '' if not supported
160 public function getTitleSnippet() {
165 * @return string Highlighted redirect name (redirect to this page), '' if none or not supported
167 public function getRedirectSnippet() {
172 * @return Title|null Title object for the redirect to this page, null if none or not supported
174 public function getRedirectTitle() {
179 * @return string Highlighted relevant section name, null if none or not supported
181 public function getSectionSnippet() {
186 * @return Title|null Title object (pagename+fragment) for the section,
187 * null if none or not supported
189 public function getSectionTitle() {
194 * @return string Highlighted relevant category name or '' if none or not supported
196 public function getCategorySnippet() {
201 * @return string Timestamp
203 public function getTimestamp() {
204 if ( $this->mRevision
) {
205 return $this->mRevision
->getTimestamp();
206 } elseif ( $this->mImage
) {
207 return $this->mImage
->getTimestamp();
213 * @return int Number of words
215 public function getWordCount() {
217 return str_word_count( $this->mText
);
221 * @return int Size in bytes
223 public function getByteSize() {
225 return strlen( $this->mText
);
229 * @return string Interwiki prefix of the title (return iw even if title is broken)
231 public function getInterwikiPrefix() {
236 * @return string Interwiki namespace of the title (since we likely can't resolve it locally)
238 public function getInterwikiNamespaceText() {
243 * Did this match file contents (eg: PDF/DJVU)?
246 public function isFileMatch() {
251 * Get the extension data as:
252 * augmentor name => data
255 public function getExtensionData() {
256 if ( $this->extensionData
) {
257 return call_user_func( $this->extensionData
);
264 * Set extension data for this result.
266 * augmentor name => data
267 * @param Closure|array $extensionData Takes no arguments, returns
268 * either array of extension data or null.
270 public function setExtensionData( $extensionData ) {
271 if ( $extensionData instanceof Closure
) {
272 $this->extensionData
= $extensionData;
273 } elseif ( is_array( $extensionData ) ) {
274 wfDeprecated( __METHOD__
. ' with array argument', '1.32' );
275 $this->extensionData
= function () use ( $extensionData ) {
276 return $extensionData;
279 $type = is_object( $extensionData )
280 ?
get_class( $extensionData )
281 : gettype( $extensionData );
282 throw new \
InvalidArgumentException(
283 __METHOD__
. " must be called with Closure|array, but received $type" );