]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/PrefixSearch.php
MediaWiki 1.17.1
[autoinstallsdev/mediawiki.git] / includes / PrefixSearch.php
1 <?php
2 /**
3  * PrefixSearch - Handles searching prefixes of titles and finding any page
4  * names that match. Used largely by the OpenSearch implementation.
5  *
6  * @ingroup Search
7  */
8
9 class PrefixSearch {
10         /**
11          * Do a prefix search of titles and return a list of matching page names.
12          *
13          * @param $search String
14          * @param $limit Integer
15          * @param $namespaces Array: used if query is not explicitely prefixed
16          * @return Array of strings
17          */
18         public static function titleSearch( $search, $limit, $namespaces=array() ) {
19                 $search = trim( $search );
20                 if( $search == '' ) {
21                         return array(); // Return empty result
22                 }
23                 $namespaces = self::validateNamespaces( $namespaces );
24
25                 // Find a Title which is not an interwiki and is in NS_MAIN
26                 $title = Title::newFromText( $search );
27                 if( $title && $title->getInterwiki() == '' ) {
28                         $ns = array($title->getNamespace());
29                         if($ns[0] == NS_MAIN)
30                                 $ns = $namespaces; // no explicit prefix, use default namespaces
31                         return self::searchBackend(
32                                 $ns, $title->getText(), $limit );
33                 }
34
35                 // Is this a namespace prefix?
36                 $title = Title::newFromText( $search . 'Dummy' );
37                 if( $title && $title->getText() == 'Dummy'
38                         && $title->getNamespace() != NS_MAIN
39                         && $title->getInterwiki() == '' ) {
40                         return self::searchBackend(
41                                 array($title->getNamespace()), '', $limit );
42                 }
43
44                 return self::searchBackend( $namespaces, $search, $limit );
45         }
46
47
48         /**
49          * Do a prefix search of titles and return a list of matching page names.
50          * @param $namespaces Array
51          * @param $search String
52          * @param $limit Integer
53          * @return Array of strings
54          */
55         protected static function searchBackend( $namespaces, $search, $limit ) {
56                 if( count($namespaces) == 1 ){
57                         $ns = $namespaces[0];
58                         if( $ns == NS_MEDIA ) {
59                                 $namespaces = array(NS_FILE);
60                         } elseif( $ns == NS_SPECIAL ) {
61                                 return self::specialSearch( $search, $limit );
62                         }
63                 }
64                 $srchres = array();
65                 if( wfRunHooks( 'PrefixSearchBackend', array( $namespaces, $search, $limit, &$srchres ) ) ) {
66                         return self::defaultSearchBackend( $namespaces, $search, $limit );
67                 }
68                 return $srchres;
69         }
70
71         /**
72          * Prefix search special-case for Special: namespace.
73          *
74          * @param $search String: term
75          * @param $limit Integer: max number of items to return
76          * @return Array
77          */
78         protected static function specialSearch( $search, $limit ) {
79                 global $wgContLang;
80
81                 # normalize searchKey, so aliases with spaces can be found - bug 25675
82                 $search = str_replace( ' ', '_', $search );
83
84                 $searchKey = $wgContLang->caseFold( $search );
85
86                 // Unlike SpecialPage itself, we want the canonical forms of both
87                 // canonical and alias title forms...
88                 SpecialPage::initList();
89                 SpecialPage::initAliasList();
90                 $keys = array();
91                 foreach( array_keys( SpecialPage::$mList ) as $page ) {
92                         $keys[$wgContLang->caseFold( $page )] = $page;
93                 }
94
95                 foreach( $wgContLang->getSpecialPageAliases() as $page => $aliases ) {
96                         if( !array_key_exists( $page, SpecialPage::$mList ) ) {# bug 20885
97                                 continue;
98                         }
99
100                         foreach( $aliases as $alias ) {
101                                 $keys[$wgContLang->caseFold( $alias )] = $alias;
102                         }
103                 }
104                 ksort( $keys );
105
106                 $srchres = array();
107                 foreach( $keys as $pageKey => $page ) {
108                         if( $searchKey === '' || strpos( $pageKey, $searchKey ) === 0 ) {
109                                 wfSuppressWarnings();
110                                 // bug 27671: Don't use SpecialPage::getTitleFor() here because it
111                                 // localizes its input leading to searches for e.g. Special:All
112                                 // returning Spezial:MediaWiki-Systemnachrichten and returning
113                                 // Spezial:Alle_Seiten twice when $wgLanguageCode == 'de'
114                                 $srchres[] = Title::makeTitleSafe( NS_SPECIAL, $page )->getPrefixedText();
115                                 wfRestoreWarnings();
116                         }
117
118                         if( count( $srchres ) >= $limit ) {
119                                 break;
120                         }
121                 }
122
123                 return $srchres;
124         }
125
126         /**
127          * Unless overridden by PrefixSearchBackend hook...
128          * This is case-sensitive (First character may
129          * be automatically capitalized by Title::secureAndSpit()
130          * later on depending on $wgCapitalLinks)
131          *
132          * @param $namespaces Array: namespaces to search in
133          * @param $search String: term
134          * @param $limit Integer: max number of items to return
135          * @return Array of title strings
136          */
137         protected static function defaultSearchBackend( $namespaces, $search, $limit ) {
138                 $ns = array_shift($namespaces); // support only one namespace
139                 if( in_array(NS_MAIN,$namespaces))
140                         $ns = NS_MAIN; // if searching on many always default to main
141
142                 // Prepare nested request
143                 $req = new FauxRequest(array (
144                         'action' => 'query',
145                         'list' => 'allpages',
146                         'apnamespace' => $ns,
147                         'aplimit' => $limit,
148                         'apprefix' => $search
149                 ));
150
151                 // Execute
152                 $module = new ApiMain($req);
153                 $module->execute();
154
155                 // Get resulting data
156                 $data = $module->getResultData();
157
158                 // Reformat useful data for future printing by JSON engine
159                 $srchres = array ();
160                 foreach ((array)$data['query']['allpages'] as $pageinfo) {
161                         // Note: this data will no be printable by the xml engine
162                         // because it does not support lists of unnamed items
163                         $srchres[] = $pageinfo['title'];
164                 }
165
166                 return $srchres;
167         }
168
169         /**
170          * Validate an array of numerical namespace indexes
171          *
172          * @param $namespaces Array
173          * @return Array (default: contains only NS_MAIN)
174          */
175         protected static function validateNamespaces($namespaces){
176                 global $wgContLang;
177
178                 // We will look at each given namespace against wgContLang namespaces
179                 $validNamespaces = $wgContLang->getNamespaces();
180                 if( is_array($namespaces) && count($namespaces)>0 ){
181                         $valid = array();
182                         foreach ($namespaces as $ns){
183                                 if( is_numeric($ns) && array_key_exists($ns, $validNamespaces) )
184                                         $valid[] = $ns;
185                         }
186                         if( count($valid) > 0 ) {
187                                 return $valid;
188                         }
189                 }
190
191                 return array( NS_MAIN );
192         }
193 }