MediaWiki  master
SearchNearMatcher.php
Go to the documentation of this file.
1 <?php
2 
7 
16  protected $config;
17 
22  private $language;
23 
29 
33  private $hookRunner;
34 
39 
46  public function __construct( Config $config, Language $lang, HookContainer $hookContainer ) {
47  $this->config = $config;
48  $this->language = $lang;
49  $services = MediaWikiServices::getInstance();
50  $this->languageConverter = $services->getLanguageConverterFactory()
51  ->getLanguageConverter( $lang );
52  $this->wikiPageFactory = $services->getWikiPageFactory();
53  $this->hookRunner = new HookRunner( $hookContainer );
54  }
55 
63  public function getNearMatch( $searchterm ) {
64  $title = $this->getNearMatchInternal( $searchterm );
65 
66  $this->hookRunner->onSearchGetNearMatchComplete( $searchterm, $title );
67  return $title;
68  }
69 
77  public function getNearMatchResultSet( $searchterm ) {
78  return new SearchNearMatchResultSet( $this->getNearMatch( $searchterm ) );
79  }
80 
86  protected function getNearMatchInternal( $searchterm ) {
87  $allSearchTerms = [ $searchterm ];
88 
89  if ( $this->languageConverter->hasVariants() ) {
90  $allSearchTerms = array_unique( array_merge(
91  $allSearchTerms,
92  $this->languageConverter->autoConvertToAllVariants( $searchterm )
93  ) );
94  }
95 
96  $titleResult = null;
97  if ( !$this->hookRunner->onSearchGetNearMatchBefore( $allSearchTerms, $titleResult ) ) {
98  return $titleResult;
99  }
100 
101  // Most of our handling here deals with finding a valid title for the search term,
102  // but almost anything starting with '#' is "valid" and points to Main_Page#searchterm.
103  // Rather than doing something completely wrong, do nothing.
104  if ( $searchterm === '' || $searchterm[0] === '#' ) {
105  return null;
106  }
107 
108  foreach ( $allSearchTerms as $term ) {
109  # Exact match? No need to look further.
110  $title = Title::newFromText( $term );
111  if ( $title === null ) {
112  return null;
113  }
114 
115  # Try files if searching in the Media: namespace
116  if ( $title->getNamespace() === NS_MEDIA ) {
117  $title = Title::makeTitle( NS_FILE, $title->getText() );
118  }
119 
120  if ( $title->isSpecialPage() || $title->isExternal() || $title->exists() ) {
121  return $title;
122  }
123 
124  # See if it still otherwise has content is some sane sense
125  $page = $this->wikiPageFactory->newFromTitle( $title );
126  if ( $page->hasViewableContent() ) {
127  return $title;
128  }
129 
130  if ( !$this->hookRunner->onSearchAfterNoDirectMatch( $term, $title ) ) {
131  return $title;
132  }
133 
134  # Now try all lower case (i.e. first letter capitalized)
135  $title = Title::newFromText( $this->language->lc( $term ) );
136  if ( $title && $title->exists() ) {
137  return $title;
138  }
139 
140  # Now try capitalized string
141  $title = Title::newFromText( $this->language->ucwords( $term ) );
142  if ( $title && $title->exists() ) {
143  return $title;
144  }
145 
146  # Now try all upper case
147  $title = Title::newFromText( $this->language->uc( $term ) );
148  if ( $title && $title->exists() ) {
149  return $title;
150  }
151 
152  # Now try Word-Caps-Breaking-At-Word-Breaks, for hyphenated names etc
153  $title = Title::newFromText( $this->language->ucwordbreaks( $term ) );
154  if ( $title && $title->exists() ) {
155  return $title;
156  }
157 
158  // Give hooks a chance at better match variants
159  $title = null;
160  if ( !$this->hookRunner->onSearchGetNearMatch( $term, $title ) ) {
161  return $title;
162  }
163  }
164 
165  $title = Title::newFromText( $searchterm );
166 
167  # Entering an IP address goes to the contributions page
168  if ( $this->config->get( 'EnableSearchContributorsByIP' ) ) {
169  if ( ( $title->getNamespace() === NS_USER && User::isIP( $title->getText() ) )
170  || User::isIP( trim( $searchterm ) ) ) {
171  return SpecialPage::getTitleFor( 'Contributions', $title->getDBkey() );
172  }
173  }
174 
175  # Entering a user goes to the user page whether it's there or not
176  if ( $title->getNamespace() === NS_USER ) {
177  return $title;
178  }
179 
180  # Go to images that exist even if there's no local page.
181  # There may have been a funny upload, or it may be on a shared
182  # file repository such as Wikimedia Commons.
183  if ( $title->getNamespace() === NS_FILE ) {
184  $image = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $title );
185  if ( $image ) {
186  return $title;
187  }
188  }
189 
190  # MediaWiki namespace? Page may be "implied" if not customized.
191  # Just return it, with caps forced as the message system likes it.
192  if ( $title->getNamespace() === NS_MEDIAWIKI ) {
193  return Title::makeTitle( NS_MEDIAWIKI, $this->language->ucfirst( $title->getText() ) );
194  }
195 
196  # Quoted term? Try without the quotes...
197  $matches = [];
198  if ( preg_match( '/^"([^"]+)"$/', $searchterm, $matches ) ) {
199  return $this->getNearMatch( $matches[1] );
200  }
201 
202  return null;
203  }
204 }
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:361
SearchNearMatcher\$hookRunner
HookRunner $hookRunner
Definition: SearchNearMatcher.php:33
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:71
SearchNearMatcher\getNearMatchInternal
getNearMatchInternal( $searchterm)
Really find the title match.
Definition: SearchNearMatcher.php:86
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:166
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SearchNearMatcher\$languageConverter
ILanguageConverter $languageConverter
Current language converter.
Definition: SearchNearMatcher.php:28
SearchNearMatcher\getNearMatch
getNearMatch( $searchterm)
If an exact title match can be found, or a very slightly close match, return the title.
Definition: SearchNearMatcher.php:63
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:106
Config
Interface for configuration instances.
Definition: Config.php:30
SearchNearMatcher
Implementation of near match title search.
Definition: SearchNearMatcher.php:12
$matches
$matches
Definition: NoLocalSettings.php:24
User\isIP
static isIP( $name)
Does the string match an anonymous IP address?
Definition: User.php:968
SearchNearMatchResultSet
A ISearchResultSet wrapper for SearchNearMatcher.
Definition: SearchNearMatchResultSet.php:5
Page\WikiPageFactory
Definition: WikiPageFactory.php:19
SearchNearMatcher\getNearMatchResultSet
getNearMatchResultSet( $searchterm)
Do a near match (see SearchEngine::getNearMatch) and wrap it into a ISearchResultSet.
Definition: SearchNearMatcher.php:77
$title
$title
Definition: testCompression.php:38
SearchNearMatcher\$language
Language $language
Current language.
Definition: SearchNearMatcher.php:22
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:624
NS_MEDIA
const NS_MEDIA
Definition: Defines.php:51
ILanguageConverter
The shared interface for all language converters.
Definition: ILanguageConverter.php:28
NS_USER
const NS_USER
Definition: Defines.php:65
SearchNearMatcher\$config
Config $config
Definition: SearchNearMatcher.php:16
SearchNearMatcher\__construct
__construct(Config $config, Language $lang, HookContainer $hookContainer)
SearchNearMatcher constructor.
Definition: SearchNearMatcher.php:46
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:571
NS_FILE
const NS_FILE
Definition: Defines.php:69
SearchNearMatcher\$wikiPageFactory
WikiPageFactory $wikiPageFactory
Definition: SearchNearMatcher.php:38
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42