MediaWiki  master
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 
44  private $userNameUtils;
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 }
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:385
SearchNearMatcher\$hookRunner
HookRunner $hookRunner
Definition: SearchNearMatcher.php:34
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:72
SearchNearMatcher\getNearMatchInternal
getNearMatchInternal( $searchterm)
Really find the title match.
Definition: SearchNearMatcher.php:92
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:180
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SearchNearMatcher\$userNameUtils
UserNameUtils $userNameUtils
Definition: SearchNearMatcher.php:44
SearchNearMatcher\$languageConverter
ILanguageConverter $languageConverter
Current language converter.
Definition: SearchNearMatcher.php:29
SearchNearMatcher\getNearMatch
getNearMatch( $searchterm)
If an exact title match can be found, or a very slightly close match, return the title.
Definition: SearchNearMatcher.php:69
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:107
Config
Interface for configuration instances.
Definition: Config.php:30
SearchNearMatcher
Implementation of near match title search.
Definition: SearchNearMatcher.php:13
$matches
$matches
Definition: NoLocalSettings.php:24
SearchNearMatchResultSet
A ISearchResultSet wrapper for SearchNearMatcher.
Definition: SearchNearMatchResultSet.php:5
Page\WikiPageFactory
Definition: WikiPageFactory.php:20
SearchNearMatcher\getNearMatchResultSet
getNearMatchResultSet( $searchterm)
Do a near match (see SearchEngine::getNearMatch) and wrap it into a ISearchResultSet.
Definition: SearchNearMatcher.php:83
$title
$title
Definition: testCompression.php:38
SearchNearMatcher\$language
Language $language
Current language.
Definition: SearchNearMatcher.php:23
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:650
NS_MEDIA
const NS_MEDIA
Definition: Defines.php:52
ILanguageConverter
The shared interface for all language converters.
Definition: ILanguageConverter.php:29
NS_USER
const NS_USER
Definition: Defines.php:66
SearchNearMatcher\$config
Config $config
Definition: SearchNearMatcher.php:17
MediaWiki\User\UserNameUtils
UserNameUtils service.
Definition: UserNameUtils.php:42
SearchNearMatcher\__construct
__construct(Config $config, Language $lang, HookContainer $hookContainer)
Definition: SearchNearMatcher.php:51
MediaWiki\HookContainer\HookContainer
HookContainer class.
Definition: HookContainer.php:45
MediaWiki\HookContainer\HookRunner
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:558
NS_FILE
const NS_FILE
Definition: Defines.php:70
SearchNearMatcher\$wikiPageFactory
WikiPageFactory $wikiPageFactory
Definition: SearchNearMatcher.php:39
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42