MediaWiki REL1_37
SearchNearMatcher.php
Go to the documentation of this file.
1<?php
2
8
17 protected $config;
18
23 private $language;
24
30
34 private $hookRunner;
35
40
45
51 public function __construct( Config $config, Language $lang, HookContainer $hookContainer ) {
52 $this->config = $config;
53 $this->language = $lang;
54 $services = MediaWikiServices::getInstance();
55 $this->languageConverter = $services->getLanguageConverterFactory()
56 ->getLanguageConverter( $lang );
57 $this->wikiPageFactory = $services->getWikiPageFactory();
58 $this->hookRunner = new HookRunner( $hookContainer );
59 $this->userNameUtils = $services->getUserNameUtils();
60 }
61
69 public function getNearMatch( $searchterm ) {
70 $title = $this->getNearMatchInternal( $searchterm );
71
72 $this->hookRunner->onSearchGetNearMatchComplete( $searchterm, $title );
73 return $title;
74 }
75
83 public function getNearMatchResultSet( $searchterm ) {
84 return new SearchNearMatchResultSet( $this->getNearMatch( $searchterm ) );
85 }
86
92 protected function getNearMatchInternal( $searchterm ) {
93 $allSearchTerms = [ $searchterm ];
94
95 if ( $this->languageConverter->hasVariants() ) {
96 $allSearchTerms = array_unique( array_merge(
97 $allSearchTerms,
98 $this->languageConverter->autoConvertToAllVariants( $searchterm )
99 ) );
100 }
101
102 $titleResult = null;
103 if ( !$this->hookRunner->onSearchGetNearMatchBefore( $allSearchTerms, $titleResult ) ) {
104 return $titleResult;
105 }
106
107 // Most of our handling here deals with finding a valid title for the search term,
108 // but almost anything starting with '#' is "valid" and points to Main_Page#searchterm.
109 // Rather than doing something completely wrong, do nothing.
110 if ( $searchterm === '' || $searchterm[0] === '#' ) {
111 return null;
112 }
113
114 foreach ( $allSearchTerms as $term ) {
115 # Exact match? No need to look further.
116 $title = Title::newFromText( $term );
117 if ( $title === null ) {
118 return null;
119 }
120
121 # Try files if searching in the Media: namespace
122 if ( $title->getNamespace() === NS_MEDIA ) {
123 $title = Title::makeTitle( NS_FILE, $title->getText() );
124 }
125
126 if ( $title->isSpecialPage() || $title->isExternal() || $title->exists() ) {
127 return $title;
128 }
129
130 # See if it still otherwise has content is some sane sense
131 if ( $title->canExist() ) {
132 $page = $this->wikiPageFactory->newFromTitle( $title );
133 if ( $page->hasViewableContent() ) {
134 return $title;
135 }
136 }
137
138 if ( !$this->hookRunner->onSearchAfterNoDirectMatch( $term, $title ) ) {
139 return $title;
140 }
141
142 # Now try all lower case (i.e. first letter capitalized)
143 $title = Title::newFromText( $this->language->lc( $term ) );
144 if ( $title && $title->exists() ) {
145 return $title;
146 }
147
148 # Now try capitalized string
149 $title = Title::newFromText( $this->language->ucwords( $term ) );
150 if ( $title && $title->exists() ) {
151 return $title;
152 }
153
154 # Now try all upper case
155 $title = Title::newFromText( $this->language->uc( $term ) );
156 if ( $title && $title->exists() ) {
157 return $title;
158 }
159
160 # Now try Word-Caps-Breaking-At-Word-Breaks, for hyphenated names etc
161 $title = Title::newFromText( $this->language->ucwordbreaks( $term ) );
162 if ( $title && $title->exists() ) {
163 return $title;
164 }
165
166 // Give hooks a chance at better match variants
167 $title = null;
168 if ( !$this->hookRunner->onSearchGetNearMatch( $term, $title ) ) {
169 return $title;
170 }
171 }
172
173 $title = Title::newFromText( $searchterm );
174
175 # Entering an IP address goes to the contributions page
176 if ( $this->config->get( 'EnableSearchContributorsByIP' ) ) {
177 if ( ( $title->getNamespace() === NS_USER && $this->userNameUtils->isIP( $title->getText() ) )
178 || $this->userNameUtils->isIP( trim( $searchterm ) ) ) {
179 return SpecialPage::getTitleFor( 'Contributions', $title->getDBkey() );
180 }
181 }
182
183 # Entering a user goes to the user page whether it's there or not
184 if ( $title->getNamespace() === NS_USER ) {
185 return $title;
186 }
187
188 # Go to images that exist even if there's no local page.
189 # There may have been a funny upload, or it may be on a shared
190 # file repository such as Wikimedia Commons.
191 if ( $title->getNamespace() === NS_FILE ) {
192 $image = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $title );
193 if ( $image ) {
194 return $title;
195 }
196 }
197
198 # MediaWiki namespace? Page may be "implied" if not customized.
199 # Just return it, with caps forced as the message system likes it.
200 if ( $title->getNamespace() === NS_MEDIAWIKI ) {
201 return Title::makeTitle( NS_MEDIAWIKI, $this->language->ucfirst( $title->getText() ) );
202 }
203
204 # Quoted term? Try without the quotes...
205 $matches = [];
206 if ( preg_match( '/^"([^"]+)"$/', $searchterm, $matches ) ) {
207 return $this->getNearMatch( $matches[1] );
208 }
209
210 return null;
211 }
212}
const NS_USER
Definition Defines.php:66
const NS_FILE
Definition Defines.php:70
const NS_MEDIAWIKI
Definition Defines.php:72
const NS_MEDIA
Definition Defines.php:52
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition Language.php:42
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
MediaWikiServices is the service locator for the application scope of MediaWiki.
UserNameUtils service.
A ISearchResultSet wrapper for SearchNearMatcher.
Implementation of near match title search.
getNearMatch( $searchterm)
If an exact title match can be found, or a very slightly close match, return the title.
ILanguageConverter $languageConverter
Current language converter.
Language $language
Current language.
UserNameUtils $userNameUtils
getNearMatchInternal( $searchterm)
Really find the title match.
__construct(Config $config, Language $lang, HookContainer $hookContainer)
getNearMatchResultSet( $searchterm)
Do a near match (see SearchEngine::getNearMatch) and wrap it into a ISearchResultSet.
WikiPageFactory $wikiPageFactory
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Interface for configuration instances.
Definition Config.php:30
The shared interface for all language converters.
if(!isset( $args[0])) $lang