MediaWiki REL1_31
SpecialDoubleRedirects.php
Go to the documentation of this file.
1<?php
26
34 function __construct( $name = 'DoubleRedirects' ) {
35 parent::__construct( $name );
36 }
37
38 public function isExpensive() {
39 return true;
40 }
41
42 function isSyndicated() {
43 return false;
44 }
45
46 function sortDescending() {
47 return false;
48 }
49
50 function getPageHeader() {
51 return $this->msg( 'doubleredirectstext' )->parseAsBlock();
52 }
53
54 function reallyGetQueryInfo( $namespace = null, $title = null ) {
55 $limitToTitle = !( $namespace === null && $title === null );
57 $retval = [
58 'tables' => [
59 'ra' => 'redirect',
60 'rb' => 'redirect',
61 'pa' => 'page',
62 'pb' => 'page'
63 ],
64 'fields' => [
65 'namespace' => 'pa.page_namespace',
66 'title' => 'pa.page_title',
67
68 'b_namespace' => 'pb.page_namespace',
69 'b_title' => 'pb.page_title',
70
71 // Select fields from redirect instead of page. Because there may
72 // not actually be a page table row for this target (e.g. for interwiki redirects)
73 'c_namespace' => 'rb.rd_namespace',
74 'c_title' => 'rb.rd_title',
75 'c_fragment' => 'rb.rd_fragment',
76 'c_interwiki' => 'rb.rd_interwiki',
77 ],
78 'conds' => [
79 'ra.rd_from = pa.page_id',
80
81 // Filter out redirects where the target goes interwiki (T42353).
82 // This isn't an optimization, it is required for correct results,
83 // otherwise a non-double redirect like Bar -> w:Foo will show up
84 // like "Bar -> Foo -> w:Foo".
85
86 // Need to check both NULL and "" for some reason,
87 // apparently either can be stored for non-iw entries.
88 'ra.rd_interwiki IS NULL OR ra.rd_interwiki = ' . $dbr->addQuotes( '' ),
89
90 'pb.page_namespace = ra.rd_namespace',
91 'pb.page_title = ra.rd_title',
92
93 'rb.rd_from = pb.page_id',
94 ]
95 ];
96
97 if ( $limitToTitle ) {
98 $retval['conds']['pa.page_namespace'] = $namespace;
99 $retval['conds']['pa.page_title'] = $title;
100 }
101
102 return $retval;
103 }
104
105 public function getQueryInfo() {
106 return $this->reallyGetQueryInfo();
107 }
108
109 function getOrderFields() {
110 return [ 'ra.rd_namespace', 'ra.rd_title' ];
111 }
112
118 function formatResult( $skin, $result ) {
119 // If no Title B or C is in the query, it means this came from
120 // querycache (which only saves the 3 columns for title A).
121 // That does save the bulk of the query cost, but now we need to
122 // get a little more detail about each individual entry quickly
123 // using the filter of reallyGetQueryInfo.
124 $deep = false;
125 if ( $result ) {
126 if ( isset( $result->b_namespace ) ) {
127 $deep = $result;
128 } else {
130 $qi = $this->reallyGetQueryInfo(
131 $result->namespace,
132 $result->title
133 );
134 $res = $dbr->select(
135 $qi['tables'],
136 $qi['fields'],
137 $qi['conds'],
138 __METHOD__
139 );
140
141 if ( $res ) {
142 $deep = $dbr->fetchObject( $res ) ?: false;
143 }
144 }
145 }
146
147 $titleA = Title::makeTitle( $result->namespace, $result->title );
148
150 if ( !$deep ) {
151 return '<del>' . $linkRenderer->makeLink( $titleA, null, [], [ 'redirect' => 'no' ] ) . '</del>';
152 }
153
154 // if the page is editable, add an edit link
155 if (
156 // check user permissions
157 $this->getUser()->isAllowed( 'edit' ) &&
158 // check, if the content model is editable through action=edit
159 ContentHandler::getForTitle( $titleA )->supportsDirectEditing()
160 ) {
161 $edit = $linkRenderer->makeKnownLink(
162 $titleA,
163 $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->text(),
164 [],
165 [ 'action' => 'edit' ]
166 );
167 } else {
168 $edit = '';
169 }
170
171 $linkA = $linkRenderer->makeKnownLink(
172 $titleA,
173 null,
174 [],
175 [ 'redirect' => 'no' ]
176 );
177
178 $titleB = Title::makeTitle( $deep->b_namespace, $deep->b_title );
179 $linkB = $linkRenderer->makeKnownLink(
180 $titleB,
181 null,
182 [],
183 [ 'redirect' => 'no' ]
184 );
185
186 $titleC = Title::makeTitle(
187 $deep->c_namespace,
188 $deep->c_title,
189 $deep->c_fragment,
190 $deep->c_interwiki
191 );
192 $linkC = $linkRenderer->makeKnownLink( $titleC, $titleC->getFullText() );
193
194 $lang = $this->getLanguage();
195 $arr = $lang->getArrow() . $lang->getDirMark();
196
197 return ( "{$linkA} {$edit} {$arr} {$linkB} {$arr} {$linkC}" );
198 }
199
206 function preprocessResults( $db, $res ) {
207 if ( !$res->numRows() ) {
208 return;
209 }
210
211 $batch = new LinkBatch;
212 foreach ( $res as $row ) {
213 $batch->add( $row->namespace, $row->title );
214 if ( isset( $row->b_namespace ) ) {
215 // lazy loaded when using cached results
216 $batch->add( $row->b_namespace, $row->b_title );
217 }
218 if ( isset( $row->c_interwiki ) && !$row->c_interwiki ) {
219 // lazy loaded when using cached result, not added when interwiki link
220 $batch->add( $row->c_namespace, $row->c_title );
221 }
222 }
223 $batch->execute();
224
225 // Back to start for display
226 $res->seek( 0 );
227 }
228
229 protected function getGroupName() {
230 return 'maintenance';
231 }
232}
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
A special page listing redirects to redirecting page.
reallyGetQueryInfo( $namespace=null, $title=null)
isSyndicated()
Sometime we don't want to build rss / atom feeds.
preprocessResults( $db, $res)
Cache page content model and gender distinction for performance.
sortDescending()
Override to sort by increasing values.
getPageHeader()
The content returned by this function will be output before any result.
__construct( $name='DoubleRedirects')
getOrderFields()
Subclasses return an array of fields to order by here.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
isExpensive()
Is this query expensive (for some definition of expensive)? Then we don't let it run in miser mode.
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:34
add( $ns, $dbkey)
Definition LinkBatch.php:80
This is a class for doing query pages; since they're almost all the same, we factor out some of the f...
Definition QueryPage.php:34
getUser()
Shortcut to get the User executing this instance.
msg( $key)
Wrapper around wfMessage that sets the current context.
getLanguage()
Shortcut to get user's language.
MediaWiki Linker LinkRenderer null $linkRenderer
$res
Definition database.txt:21
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
namespace being checked & $result
Definition hooks.txt:2323
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account incomplete not yet checked for validity & $retval
Definition hooks.txt:266
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:964
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:38
Result wrapper for grabbing data queried from an IDatabase object.
$batch
Definition linkcache.txt:23
const DB_REPLICA
Definition defines.php:25
if(!isset( $args[0])) $lang