MediaWiki REL1_34
SearchExactMatchRescorer.php
Go to the documentation of this file.
1<?php
42 public function rescore( $search, $namespaces, $srchres, $limit ) {
43 // Pick namespace (based on PrefixSearch::defaultSearchBackend)
44 $ns = in_array( NS_MAIN, $namespaces ) ? NS_MAIN : reset( $namespaces );
45 $t = Title::newFromText( $search, $ns );
46 if ( !$t || !$t->exists() ) {
47 // No exact match so just return the search results
48 return $srchres;
49 }
50 $string = $t->getPrefixedText();
51 $key = array_search( $string, $srchres );
52 if ( $key !== false ) {
53 // Exact match was in the results so just move it to the front
54 return $this->pullFront( $key, $srchres );
55 }
56 // Exact match not in the search results so check for some redirect handling cases
57 if ( $t->isRedirect() ) {
58 $target = $this->getRedirectTarget( $t );
59 $key = array_search( $target, $srchres );
60 if ( $key !== false ) {
61 // Exact match is a redirect to one of the returned matches so pull the
62 // returned match to the front. This might look odd but the alternative
63 // is to put the redirect in front and drop the match. The name of the
64 // found match is often more descriptive/better formed than the name of
65 // the redirect AND by definition they share a prefix. Hopefully this
66 // choice is less confusing and more helpful. But it might not be. But
67 // it is the choice we're going with for now.
68 return $this->pullFront( $key, $srchres );
69 }
70 $redirectTargetsToRedirect = $this->redirectTargetsToRedirect( $srchres );
71 if ( isset( $redirectTargetsToRedirect[$target] ) ) {
72 // The exact match and something in the results list are both redirects
73 // to the same thing! In this case we'll pull the returned match to the
74 // top following the same logic above. Again, it might not be a perfect
75 // choice but it'll do.
76 return $this->pullFront( $redirectTargetsToRedirect[$target], $srchres );
77 }
78 } else {
79 $redirectTargetsToRedirect = $this->redirectTargetsToRedirect( $srchres );
80 if ( isset( $redirectTargetsToRedirect[$string] ) ) {
81 // The exact match is the target of a redirect already in the results list so remove
82 // the redirect from the results list and push the exact match to the front
83 array_splice( $srchres, $redirectTargetsToRedirect[$string], 1 );
84 array_unshift( $srchres, $string );
85 return $srchres;
86 }
87 }
88
89 // Exact match is totally unique from the other results so just add it to the front
90 array_unshift( $srchres, $string );
91 // And roll one off the end if the results are too long
92 if ( count( $srchres ) > $limit ) {
93 array_pop( $srchres );
94 }
95 return $srchres;
96 }
97
103 private function redirectTargetsToRedirect( array $titles ) {
104 $result = [];
105 foreach ( $titles as $key => $titleText ) {
106 $title = Title::newFromText( $titleText );
107 if ( !$title || !$title->isRedirect() ) {
108 continue;
109 }
110 $target = $this->getRedirectTarget( $title );
111 if ( !$target ) {
112 continue;
113 }
114 $result[$target] = $key;
115 }
116 return $result;
117 }
118
125 private function pullFront( $key, array $array ) {
126 $cut = array_splice( $array, $key, 1 );
127 array_unshift( $array, $cut[0] );
128 return $array;
129 }
130
136 private function getRedirectTarget( $title ) {
137 $page = WikiPage::factory( $title );
138 if ( !$page->exists() ) {
139 return null;
140 }
141 $redir = $page->getRedirectTarget();
142 return $redir ? $redir->getPrefixedText() : null;
143 }
144}
An utility class to rescore search results by looking for an exact match in the db and add the page f...
getRedirectTarget( $title)
Get a redirect's destination from a title.
rescore( $search, $namespaces, $srchres, $limit)
Default search backend does proper prefix searching, but custom backends may sort based on other algo...
pullFront( $key, array $array)
Returns an array where the element of $array at index $key becomes the first element.
const NS_MAIN
Definition Defines.php:69