Index: trunk/phase3/docs/hooks.txt |
— | — | @@ -1665,6 +1665,18 @@ |
1666 | 1666 | 'SpecialSearchProfiles': allows modification of search profiles |
1667 | 1667 | &$profiles: profiles, which can be modified. |
1668 | 1668 | |
| 1669 | +'SpecialSearchProfileForm': allows modification of search profile forms |
| 1670 | +$search: special page object |
| 1671 | +&$form: String: form html |
| 1672 | +$profile: String: current search profile |
| 1673 | +$term: String: search term |
| 1674 | +$opts: Array: key => value of hidden options for inclusion in custom forms |
| 1675 | + |
| 1676 | +'SpecialSearchSetupEngine': allows passing custom data to search engine |
| 1677 | +$search: special page object |
| 1678 | +$profile: String: current search profile |
| 1679 | +$engine: the search engine |
| 1680 | + |
1669 | 1681 | 'SpecialSearchResults': called before search result display when there |
1670 | 1682 | are matches |
1671 | 1683 | $term: string of search term |
Index: trunk/phase3/includes/search/SearchEngine.php |
— | — | @@ -22,6 +22,9 @@ |
23 | 23 | var $namespaces = array( NS_MAIN ); |
24 | 24 | var $showRedirects = false; |
25 | 25 | |
| 26 | + /// Feature values |
| 27 | + protected $features = array(); |
| 28 | + |
26 | 29 | /** |
27 | 30 | * @var DatabaseBase |
28 | 31 | */ |
— | — | @@ -59,12 +62,41 @@ |
60 | 63 | return null; |
61 | 64 | } |
62 | 65 | |
63 | | - /** If this search backend can list/unlist redirects */ |
| 66 | + /** |
| 67 | + * If this search backend can list/unlist redirects |
| 68 | + * @deprecated Call supports( 'list-redirects' ); |
| 69 | + */ |
64 | 70 | function acceptListRedirects() { |
65 | | - return true; |
| 71 | + return $this->supports( 'list-redirects' ); |
66 | 72 | } |
67 | 73 | |
68 | 74 | /** |
| 75 | + * @since 1.18 |
| 76 | + * @param $feature String |
| 77 | + * @return Boolean |
| 78 | + */ |
| 79 | + public function supports( $feature ) { |
| 80 | + switch( $feature ) { |
| 81 | + case 'list-redirects': |
| 82 | + return true; |
| 83 | + case 'title-suffix-filter': |
| 84 | + default: |
| 85 | + return false; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + /** |
| 90 | + * Way to pass custom data for engines |
| 91 | + * @since 1.18 |
| 92 | + * @param $feature String |
| 93 | + * @param $data Mixed |
| 94 | + * @return Noolean |
| 95 | + */ |
| 96 | + public function setFeatureData( $feature, $data ) { |
| 97 | + $this->features[$feature] = $data; |
| 98 | + } |
| 99 | + |
| 100 | + /** |
69 | 101 | * When overridden in derived class, performs database-specific conversions |
70 | 102 | * on text to be used for searching or updating search index. |
71 | 103 | * Default implementation does nothing (simply returns $string). |
Index: trunk/phase3/includes/search/SearchMySQL.php |
— | — | @@ -199,15 +199,28 @@ |
200 | 200 | return new MySQLSearchResultSet( $resultSet, $this->searchTerms, $total ); |
201 | 201 | } |
202 | 202 | |
| 203 | + public function supports( $feature ) { |
| 204 | + switch( $feature ) { |
| 205 | + case 'list-redirects': |
| 206 | + case 'title-suffix-filter': |
| 207 | + return true; |
| 208 | + default: |
| 209 | + return false; |
| 210 | + } |
| 211 | + } |
203 | 212 | |
204 | 213 | /** |
205 | | - * Add redirect conditions |
| 214 | + * Add special conditions |
206 | 215 | * @param $query Array |
207 | | - * @since 1.18 (changed) |
| 216 | + * @since 1.18 |
208 | 217 | */ |
209 | | - function queryRedirect( &$query ) { |
210 | | - if( !$this->showRedirects ) { |
211 | | - $query['conds']['page_is_redirect'] = 0; |
| 218 | + protected function queryFeatures( &$query ) { |
| 219 | + foreach ( $this->features as $feature => $value ) { |
| 220 | + if ( $feature === 'list-redirects' && !$value ) { |
| 221 | + $query['conds']['page_is_redirect'] = 0; |
| 222 | + } elseif( $feature === 'title-suffix-filter' && $value ) { |
| 223 | + $query['conds'][] = 'page_title' . $this->db->buildLike( $this->db->anyString(), $value ); |
| 224 | + } |
212 | 225 | } |
213 | 226 | } |
214 | 227 | |
— | — | @@ -253,7 +266,7 @@ |
254 | 267 | ); |
255 | 268 | |
256 | 269 | $this->queryMain( $query, $filteredTerm, $fulltext ); |
257 | | - $this->queryRedirect( $query ); |
| 270 | + $this->queryFeatures( $query ); |
258 | 271 | $this->queryNamespaces( $query ); |
259 | 272 | $this->limitResult( $query ); |
260 | 273 | |
— | — | @@ -301,7 +314,7 @@ |
302 | 315 | 'joins' => array(), |
303 | 316 | ); |
304 | 317 | |
305 | | - $this->queryRedirect( $query ); |
| 318 | + $this->queryFeatures( $query ); |
306 | 319 | $this->queryNamespaces( $query ); |
307 | 320 | |
308 | 321 | return $query; |
Index: trunk/phase3/includes/specials/SpecialSearch.php |
— | — | @@ -28,7 +28,14 @@ |
29 | 29 | * @ingroup SpecialPage |
30 | 30 | */ |
31 | 31 | class SpecialSearch extends SpecialPage { |
| 32 | + /// Current search profile |
| 33 | + protected $profile; |
32 | 34 | |
| 35 | + /// Search engine |
| 36 | + protected $searchEngine; |
| 37 | + |
| 38 | + const NAMESPACES_CURRENT = 'sense'; |
| 39 | + |
33 | 40 | public function __construct() { |
34 | 41 | parent::__construct( 'Search' ); |
35 | 42 | } |
— | — | @@ -75,14 +82,40 @@ |
76 | 83 | public function load( &$request, &$user ) { |
77 | 84 | list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' ); |
78 | 85 | $this->mPrefix = $request->getVal('prefix', ''); |
79 | | - # Extract requested namespaces |
80 | | - $this->namespaces = $this->powerSearch( $request ); |
81 | | - if( empty( $this->namespaces ) ) { |
82 | | - $this->namespaces = SearchEngine::userNamespaces( $user ); |
| 86 | + |
| 87 | + |
| 88 | + # Extract manually requested namespaces |
| 89 | + $nslist = $this->powerSearch( $request ); |
| 90 | + $this->profile = $profile = $request->getVal( 'profile', null ); |
| 91 | + $profiles = $this->getSearchProfiles(); |
| 92 | + if ( $profile === null) { |
| 93 | + // BC with old request format |
| 94 | + $this->profile = 'advanced'; |
| 95 | + if ( count( $nslist ) ) { |
| 96 | + foreach( $profiles as $key => $data ) { |
| 97 | + if ( $nslist === $data['namespaces'] && $key !== 'advanced') { |
| 98 | + $this->profile = $key; |
| 99 | + } |
| 100 | + } |
| 101 | + $this->namespaces = $nslist; |
| 102 | + } else { |
| 103 | + $this->namespaces = SearchEngine::userNamespaces( $user ); |
| 104 | + } |
| 105 | + } elseif ( $profile === 'advanced' ) { |
| 106 | + $this->namespaces = $nslist; |
| 107 | + } else { |
| 108 | + if ( isset( $profiles[$profile]['namespaces'] ) ) { |
| 109 | + $this->namespaces = $profiles[$profile]['namespaces']; |
| 110 | + } else { |
| 111 | + // Unknown profile requested |
| 112 | + $this->profile = 'default'; |
| 113 | + $this->namespaces = $profiles['default']['namespaces']; |
| 114 | + } |
83 | 115 | } |
84 | | - $this->searchRedirects = $request->getCheck( 'redirs' ); |
85 | | - $this->searchAdvanced = $request->getVal( 'advanced' ); |
86 | | - $this->active = 'advanced'; |
| 116 | + |
| 117 | + // Redirects defaults to true, but we don't know whether it was ticked of or just missing |
| 118 | + $default = $request->getBool( 'profile' ) ? 0 : 1; |
| 119 | + $this->searchRedirects = $request->getBool( 'redirs', $default ) ? 1 : 0; |
87 | 120 | $this->sk = $user->getSkin(); |
88 | 121 | $this->didYouMeanHtml = ''; # html of did you mean... link |
89 | 122 | $this->fulltext = $request->getVal('fulltext'); |
— | — | @@ -139,14 +172,16 @@ |
140 | 173 | |
141 | 174 | $sk = $wgUser->getSkin(); |
142 | 175 | |
143 | | - $this->searchEngine = SearchEngine::create(); |
144 | | - $search =& $this->searchEngine; |
| 176 | + $search = $this->getSearchEngine(); |
145 | 177 | $search->setLimitOffset( $this->limit, $this->offset ); |
146 | 178 | $search->setNamespaces( $this->namespaces ); |
147 | | - $search->showRedirects = $this->searchRedirects; |
| 179 | + $search->showRedirects = $this->searchRedirects; // BC |
| 180 | + $search->setFeatureData( 'list-redirects', $this->searchRedirects ); |
148 | 181 | $search->prefix = $this->mPrefix; |
149 | 182 | $term = $search->transformSearchTerm($term); |
150 | 183 | |
| 184 | + wfRunHooks( 'SpecialSearchSetupEngine', array( $this, $this->profile, $search ) ); |
| 185 | + |
151 | 186 | $this->setupPage( $term ); |
152 | 187 | |
153 | 188 | if( $wgDisableTextSearch ) { |
— | — | @@ -216,7 +251,7 @@ |
217 | 252 | Xml::openElement( |
218 | 253 | 'form', |
219 | 254 | array( |
220 | | - 'id' => ( $this->searchAdvanced ? 'powersearch' : 'search' ), |
| 255 | + 'id' => ( $this->profile === 'advanced' ? 'powersearch' : 'search' ), |
221 | 256 | 'method' => 'get', |
222 | 257 | 'action' => $wgScript |
223 | 258 | ) |
— | — | @@ -225,7 +260,7 @@ |
226 | 261 | $wgOut->addHtml( |
227 | 262 | Xml::openElement( 'table', array( 'id'=>'mw-search-top-table', 'border'=>0, 'cellpadding'=>0, 'cellspacing'=>0 ) ) . |
228 | 263 | Xml::openElement( 'tr' ) . |
229 | | - Xml::openElement( 'td' ) . "\n" . |
| 264 | + Xml::openElement( 'td' ) . "\n" . |
230 | 265 | $this->shortDialog( $term ) . |
231 | 266 | Xml::closeElement('td') . |
232 | 267 | Xml::closeElement('tr') . |
— | — | @@ -241,10 +276,8 @@ |
242 | 277 | |
243 | 278 | $filePrefix = $wgContLang->getFormattedNsText(NS_FILE).':'; |
244 | 279 | if( trim( $term ) === '' || $filePrefix === trim( $term ) ) { |
245 | | - $wgOut->addHTML( $this->formHeader($term, 0, 0)); |
246 | | - if( $this->searchAdvanced ) { |
247 | | - $wgOut->addHTML( $this->powerSearchBox( $term ) ); |
248 | | - } |
| 280 | + $wgOut->addHTML( $this->formHeader( $term, 0, 0 ) ); |
| 281 | + $wgOut->addHtml( $this->getProfileForm( $this->profile, $term ) ); |
249 | 282 | $wgOut->addHTML( '</form>' ); |
250 | 283 | // Empty query -- straight view of search form |
251 | 284 | wfProfileOut( __METHOD__ ); |
— | — | @@ -271,11 +304,10 @@ |
272 | 305 | $totalRes += $textMatches->getTotalHits(); |
273 | 306 | |
274 | 307 | // show number of results and current offset |
275 | | - $wgOut->addHTML( $this->formHeader($term, $num, $totalRes)); |
276 | | - if( $this->searchAdvanced ) { |
277 | | - $wgOut->addHTML( $this->powerSearchBox( $term ) ); |
278 | | - } |
| 308 | + $wgOut->addHTML( $this->formHeader( $term, $num, $totalRes ) ); |
| 309 | + $wgOut->addHtml( $this->getProfileForm( $this->profile, $term ) ); |
279 | 310 | |
| 311 | + |
280 | 312 | $wgOut->addHtml( Xml::closeElement( 'form' ) ); |
281 | 313 | $wgOut->addHtml( "<div class='searchresults'>" ); |
282 | 314 | |
— | — | @@ -361,21 +393,10 @@ |
362 | 394 | */ |
363 | 395 | protected function setupPage( $term ) { |
364 | 396 | global $wgOut; |
365 | | - // Figure out the active search profile header |
366 | | - if( $this->searchAdvanced ) { |
367 | | - $this->active = 'advanced'; |
368 | | - } else { |
369 | | - $profiles = $this->getSearchProfiles(); |
370 | 397 | |
371 | | - foreach( $profiles as $key => $data ) { |
372 | | - if ( $this->namespaces == $data['namespaces'] && $key != 'advanced') |
373 | | - $this->active = $key; |
374 | | - } |
375 | | - |
376 | | - } |
377 | 398 | # Should advanced UI be used? |
378 | | - $this->searchAdvanced = ($this->active === 'advanced'); |
379 | | - if( !empty( $term ) ) { |
| 399 | + $this->searchAdvanced = ($this->profile === 'advanced'); |
| 400 | + if( strval( $term ) !== '' ) { |
380 | 401 | $wgOut->setPageTitle( wfMsg( 'searchresults') ); |
381 | 402 | $wgOut->setHTMLTitle( wfMsg( 'pagetitle', wfMsg( 'searchresults-title', $term ) ) ); |
382 | 403 | } |
— | — | @@ -398,6 +419,7 @@ |
399 | 420 | $arr[] = $ns; |
400 | 421 | } |
401 | 422 | } |
| 423 | + |
402 | 424 | return $arr; |
403 | 425 | } |
404 | 426 | |
— | — | @@ -412,8 +434,8 @@ |
413 | 435 | $opt['ns' . $n] = 1; |
414 | 436 | } |
415 | 437 | $opt['redirs'] = $this->searchRedirects ? 1 : 0; |
416 | | - if( $this->searchAdvanced ) { |
417 | | - $opt['advanced'] = $this->searchAdvanced; |
| 438 | + if( $this->profile ) { |
| 439 | + $opt['profile'] = $this->profile; |
418 | 440 | } |
419 | 441 | return $opt; |
420 | 442 | } |
— | — | @@ -744,14 +766,28 @@ |
745 | 767 | return $out; |
746 | 768 | } |
747 | 769 | |
| 770 | + protected function getProfileForm( $profile, $term ) { |
| 771 | + // Hidden stuff |
| 772 | + $opts = array(); |
| 773 | + $opts['redirs'] = $this->searchRedirects; |
| 774 | + $opts['profile'] = $this->profile; |
748 | 775 | |
| 776 | + if ( $profile === 'advanced' ) { |
| 777 | + return $this->powerSearchBox( $term, $opts ); |
| 778 | + } else { |
| 779 | + $form = ''; |
| 780 | + wfRunHooks( 'SpecialSearchProfileForm', array( $this, &$form, $profile, $term, $opts ) ); |
| 781 | + return $form; |
| 782 | + } |
| 783 | + } |
| 784 | + |
749 | 785 | /** |
750 | | - * Generates the power search box at bottom of [[Special:Search]] |
| 786 | + * Generates the power search box at [[Special:Search]] |
751 | 787 | * |
752 | 788 | * @param $term String: search term |
753 | 789 | * @return String: HTML form |
754 | 790 | */ |
755 | | - protected function powerSearchBox( $term ) { |
| 791 | + protected function powerSearchBox( $term, $opts ) { |
756 | 792 | // Groups namespaces into rows according to subject |
757 | 793 | $rows = array(); |
758 | 794 | foreach( SearchEngine::searchableNamespaces() as $namespace => $name ) { |
— | — | @@ -793,14 +829,16 @@ |
794 | 830 | } |
795 | 831 | // Show redirects check only if backend supports it |
796 | 832 | $redirects = ''; |
797 | | - if( $this->searchEngine->acceptListRedirects() ) { |
| 833 | + if( $this->getSearchEngine()->supports( 'list-redirects' ) ) { |
798 | 834 | $redirects = |
799 | | - Xml::check( |
800 | | - 'redirs', $this->searchRedirects, array( 'value' => '1', 'id' => 'redirs' ) |
801 | | - ) . |
802 | | - ' ' . |
803 | | - Xml::label( wfMsg( 'powersearch-redir' ), 'redirs' ); |
| 835 | + Xml::checkLabel( wfMsg( 'powersearch-redir' ), 'redirs', 'redirs', $this->searchRedirects ); |
804 | 836 | } |
| 837 | + |
| 838 | + $hidden = ''; |
| 839 | + unset( $opts['redirs'] ); |
| 840 | + foreach( $opts as $key => $value ) { |
| 841 | + $hidden .= Html::hidden( $key, $value ); |
| 842 | + } |
805 | 843 | // Return final output |
806 | 844 | return |
807 | 845 | Xml::openElement( |
— | — | @@ -835,10 +873,7 @@ |
836 | 874 | Xml::element( 'div', array( 'class' => 'divider' ), '', false ) . |
837 | 875 | $namespaceTables . |
838 | 876 | Xml::element( 'div', array( 'class' => 'divider' ), '', false ) . |
839 | | - $redirects . |
840 | | - Html::hidden( 'title', SpecialPage::getTitleFor( 'Search' )->getPrefixedText() ) . |
841 | | - Html::hidden( 'advanced', $this->searchAdvanced ) . |
842 | | - Html::hidden( 'fulltext', 'Advanced search' ) . |
| 877 | + $redirects . $hidden . |
843 | 878 | Xml::closeElement( 'fieldset' ); |
844 | 879 | } |
845 | 880 | |
— | — | @@ -876,15 +911,15 @@ |
877 | 912 | 'advanced' => array( |
878 | 913 | 'message' => 'searchprofile-advanced', |
879 | 914 | 'tooltip' => 'searchprofile-advanced-tooltip', |
880 | | - 'namespaces' => $this->namespaces, |
881 | | - 'parameters' => array( 'advanced' => 1 ), |
| 915 | + 'namespaces' => self::NAMESPACES_CURRENT, |
882 | 916 | ) |
883 | 917 | ); |
884 | 918 | |
885 | 919 | wfRunHooks( 'SpecialSearchProfiles', array( &$profiles ) ); |
886 | 920 | |
887 | 921 | foreach( $profiles as &$data ) { |
888 | | - sort($data['namespaces']); |
| 922 | + if ( !is_array( $data['namespaces'] ) ) continue; |
| 923 | + sort( $data['namespaces'] ); |
889 | 924 | } |
890 | 925 | |
891 | 926 | return $profiles; |
— | — | @@ -907,19 +942,24 @@ |
908 | 943 | $out .= Xml::openElement( 'div', array( 'class' => 'search-types' ) ); |
909 | 944 | $out .= Xml::openElement( 'ul' ); |
910 | 945 | foreach ( $profiles as $id => $profile ) { |
| 946 | + if ( !isset( $profile['parameters'] ) ) { |
| 947 | + $profile['parameters'] = array(); |
| 948 | + } |
| 949 | + $profile['parameters']['profile'] = $id; |
| 950 | + |
911 | 951 | $tooltipParam = isset( $profile['namespace-messages'] ) ? |
912 | 952 | $wgLang->commaList( $profile['namespace-messages'] ) : null; |
913 | 953 | $out .= Xml::tags( |
914 | 954 | 'li', |
915 | 955 | array( |
916 | | - 'class' => $this->active == $id ? 'current' : 'normal' |
| 956 | + 'class' => $this->profile === $id ? 'current' : 'normal' |
917 | 957 | ), |
918 | 958 | $this->makeSearchLink( |
919 | 959 | $bareterm, |
920 | | - $profile['namespaces'], |
| 960 | + array(), |
921 | 961 | wfMsg( $profile['message'] ), |
922 | 962 | wfMsg( $profile['tooltip'], $tooltipParam ), |
923 | | - isset( $profile['parameters'] ) ? $profile['parameters'] : array() |
| 963 | + $profile['parameters'] |
924 | 964 | ) |
925 | 965 | ); |
926 | 966 | } |
— | — | @@ -949,24 +989,14 @@ |
950 | 990 | $out .= Xml::element( 'div', array( 'style' => 'clear:both' ), '', false ); |
951 | 991 | $out .= Xml::closeElement('div'); |
952 | 992 | |
953 | | - // Adds hidden namespace fields |
954 | | - if ( !$this->searchAdvanced ) { |
955 | | - foreach( $this->namespaces as $ns ) { |
956 | | - $out .= Html::hidden( "ns{$ns}", '1' ); |
957 | | - } |
958 | | - } |
959 | | - |
960 | 993 | return $out; |
961 | 994 | } |
962 | 995 | |
963 | 996 | protected function shortDialog( $term ) { |
964 | | - $searchTitle = SpecialPage::getTitleFor( 'Search' ); |
965 | | - $out = Html::hidden( 'title', $searchTitle->getPrefixedText() ) . "\n"; |
966 | | - // Keep redirect setting |
967 | | - $out .= Html::hidden( "redirs", (int)$this->searchRedirects ) . "\n"; |
| 997 | + $out = Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n"; |
968 | 998 | // Term box |
969 | 999 | $out .= Html::input( 'search', $term, 'search', array( |
970 | | - 'id' => $this->searchAdvanced ? 'powerSearchText' : 'searchText', |
| 1000 | + 'id' => $this->profile === 'advanced' ? 'powerSearchText' : 'searchText', |
971 | 1001 | 'size' => '50', |
972 | 1002 | 'autofocus' |
973 | 1003 | ) ) . "\n"; |
— | — | @@ -979,20 +1009,19 @@ |
980 | 1010 | * Make a search link with some target namespaces |
981 | 1011 | * |
982 | 1012 | * @param $term String |
983 | | - * @param $namespaces Array |
| 1013 | + * @param $namespaces Array ignored |
984 | 1014 | * @param $label String: link's text |
985 | 1015 | * @param $tooltip String: link's tooltip |
986 | 1016 | * @param $params Array: query string parameters |
987 | 1017 | * @return String: HTML fragment |
988 | 1018 | */ |
989 | | - protected function makeSearchLink( $term, $namespaces, $label, $tooltip, $params=array() ) { |
| 1019 | + protected function makeSearchLink( $term, $namespaces, $label, $tooltip, $params = array() ) { |
990 | 1020 | $opt = $params; |
991 | 1021 | foreach( $namespaces as $n ) { |
992 | 1022 | $opt['ns' . $n] = 1; |
993 | 1023 | } |
994 | | - $opt['redirs'] = $this->searchRedirects ? 1 : 0; |
| 1024 | + $opt['redirs'] = $this->searchRedirects; |
995 | 1025 | |
996 | | - $st = SpecialPage::getTitleFor( 'Search' ); |
997 | 1026 | $stParams = array_merge( |
998 | 1027 | array( |
999 | 1028 | 'search' => $term, |
— | — | @@ -1004,7 +1033,7 @@ |
1005 | 1034 | return Xml::element( |
1006 | 1035 | 'a', |
1007 | 1036 | array( |
1008 | | - 'href' => $st->getLocalURL( $stParams ), |
| 1037 | + 'href' => $this->getTitle()->getLocalURL( $stParams ), |
1009 | 1038 | 'title' => $tooltip, |
1010 | 1039 | 'onmousedown' => 'mwSearchHeaderClick(this);', |
1011 | 1040 | 'onkeydown' => 'mwSearchHeaderClick(this);'), |
— | — | @@ -1044,4 +1073,14 @@ |
1045 | 1074 | } |
1046 | 1075 | return false; |
1047 | 1076 | } |
| 1077 | + |
| 1078 | + /** |
| 1079 | + * @since 1.18 |
| 1080 | + */ |
| 1081 | + public function getSearchEngine() { |
| 1082 | + if ( $this->searchEngine === null ) { |
| 1083 | + $this->searchEngine = SearchEngine::create(); |
| 1084 | + } |
| 1085 | + return $this->searchEngine; |
| 1086 | + } |
1048 | 1087 | } |
Index: trunk/extensions/Translate/TranslateEditAddons.php |
— | — | @@ -498,4 +498,64 @@ |
499 | 499 | $profiles = wfArrayInsertAfter( $profiles, $insert, 'help' ); |
500 | 500 | return true; |
501 | 501 | } |
| 502 | + |
| 503 | + public static function searchProfileForm( $search, &$form, $profile, $term, $opts ) { |
| 504 | + if ( $profile !== 'translation' ) { |
| 505 | + return true; |
| 506 | + } |
| 507 | + |
| 508 | + if( !$search->getSearchEngine()->supports( 'title-suffix-filter' ) ) { |
| 509 | + return false; |
| 510 | + } |
| 511 | + |
| 512 | + $hidden = ''; |
| 513 | + foreach( $opts as $key => $value ) { |
| 514 | + $hidden .= Html::hidden( $key, $value ); |
| 515 | + } |
| 516 | + |
| 517 | + $context = $search->getContext(); |
| 518 | + $code = $context->getLang()->getCode(); |
| 519 | + $selected = $context->getRequest()->getVal( 'languagefilter' ); |
| 520 | + |
| 521 | + if ( is_callable( array( 'LanguageNames', 'getNames' ) ) ) { |
| 522 | + $languages = LanguageNames::getNames( $code, |
| 523 | + LanguageNames::FALLBACK_NORMAL, |
| 524 | + LanguageNames::LIST_MW |
| 525 | + ); |
| 526 | + } else { |
| 527 | + $languages = Language::getLanguageNames( false ); |
| 528 | + } |
| 529 | + |
| 530 | + ksort( $languages ); |
| 531 | + |
| 532 | + $selector = new HTMLSelector( 'languagefilter', 'languagefilter', $selected ); |
| 533 | + $selector->addOption( wfMessage( 'translate-search-nofilter' ), '-' ); |
| 534 | + foreach ( $languages as $code => $name ) { |
| 535 | + $selector->addOption( "$code - $name", $code ); |
| 536 | + } |
| 537 | + |
| 538 | + $selector = $selector->getHTML(); |
| 539 | + |
| 540 | + $label = Xml::label( wfMessage( 'translate-search-languagefilter' ), 'languagefilter' ) . ' '; |
| 541 | + $params = array( 'id' => 'mw-searchoptions' ); |
| 542 | + |
| 543 | + $form = Xml::fieldset( false, false, $params ) . |
| 544 | + $hidden . $label . $selector . |
| 545 | + Html::closeElement( 'fieldset' ); |
| 546 | + return false; |
| 547 | + } |
| 548 | + |
| 549 | + public static function searchProfileSetupEngine( $search, $profile, $engine ) { |
| 550 | + if ( $profile !== 'translation' ) { |
| 551 | + return true; |
| 552 | + } |
| 553 | + |
| 554 | + $context = $search->getContext(); |
| 555 | + $selected = $context->getRequest()->getVal( 'languagefilter' ); |
| 556 | + if ( $selected !== '-' && $selected ) { |
| 557 | + $engine->setFeatureData( 'title-suffix-filter', "/$selected" ); |
| 558 | + } |
| 559 | + return true; |
| 560 | + } |
| 561 | + |
502 | 562 | } |
Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -113,6 +113,8 @@ |
114 | 114 | |
115 | 115 | // Search profile |
116 | 116 | $wgHooks['SpecialSearchProfiles'][] = 'TranslateEditAddons::searchProfile'; |
| 117 | +$wgHooks['SpecialSearchProfileForm'][] = 'TranslateEditAddons::searchProfileForm'; |
| 118 | +$wgHooks['SpecialSearchSetupEngine'][] = 'TranslateEditAddons::searchProfileSetupEngine'; |
117 | 119 | |
118 | 120 | // New rights |
119 | 121 | $wgAvailableRights[] = 'translate'; |
Index: trunk/extensions/Translate/Translate.i18n.php |
— | — | @@ -361,6 +361,8 @@ |
362 | 362 | // Search profile hook |
363 | 363 | 'translate-searchprofile' => 'Translations', |
364 | 364 | 'translate-searchprofile-tooltip' => 'Search from all translations', |
| 365 | + 'translate-search-languagefilter' => 'Filter by language:', |
| 366 | + 'translate-search-nofilter' => 'No filtering', |
365 | 367 | ); |
366 | 368 | |
367 | 369 | /** Message documentation (Message documentation) |