MediaWiki REL1_35
SpecialDoubleRedirects.php
Go to the documentation of this file.
1<?php
27
35 public function __construct( $name = 'DoubleRedirects' ) {
36 parent::__construct( $name );
37 }
38
39 public function isExpensive() {
40 return true;
41 }
42
43 public function isSyndicated() {
44 return false;
45 }
46
47 protected function sortDescending() {
48 return false;
49 }
50
51 protected function getPageHeader() {
52 return $this->msg( 'doubleredirectstext' )->parseAsBlock();
53 }
54
55 private function reallyGetQueryInfo( $namespace = null, $title = null ) {
56 $limitToTitle = !( $namespace === null && $title === null );
58 $retval = [
59 'tables' => [
60 'ra' => 'redirect',
61 'rb' => 'redirect',
62 'pa' => 'page',
63 'pb' => 'page'
64 ],
65 'fields' => [
66 'namespace' => 'pa.page_namespace',
67 'title' => 'pa.page_title',
68
69 'b_namespace' => 'pb.page_namespace',
70 'b_title' => 'pb.page_title',
71
72 // Select fields from redirect instead of page. Because there may
73 // not actually be a page table row for this target (e.g. for interwiki redirects)
74 'c_namespace' => 'rb.rd_namespace',
75 'c_title' => 'rb.rd_title',
76 'c_fragment' => 'rb.rd_fragment',
77 'c_interwiki' => 'rb.rd_interwiki',
78 ],
79 'conds' => [
80 'ra.rd_from = pa.page_id',
81
82 // Filter out redirects where the target goes interwiki (T42353).
83 // This isn't an optimization, it is required for correct results,
84 // otherwise a non-double redirect like Bar -> w:Foo will show up
85 // like "Bar -> Foo -> w:Foo".
86
87 // Need to check both NULL and "" for some reason,
88 // apparently either can be stored for non-iw entries.
89 'ra.rd_interwiki IS NULL OR ra.rd_interwiki = ' . $dbr->addQuotes( '' ),
90
91 'pb.page_namespace = ra.rd_namespace',
92 'pb.page_title = ra.rd_title',
93
94 'rb.rd_from = pb.page_id',
95 ]
96 ];
97
98 if ( $limitToTitle ) {
99 $retval['conds']['pa.page_namespace'] = $namespace;
100 $retval['conds']['pa.page_title'] = $title;
101 }
102
103 return $retval;
104 }
105
106 public function getQueryInfo() {
107 return $this->reallyGetQueryInfo();
108 }
109
110 protected function getOrderFields() {
111 return [ 'ra.rd_namespace', 'ra.rd_title' ];
112 }
113
119 public function formatResult( $skin, $result ) {
120 // If no Title B or C is in the query, it means this came from
121 // querycache (which only saves the 3 columns for title A).
122 // That does save the bulk of the query cost, but now we need to
123 // get a little more detail about each individual entry quickly
124 // using the filter of reallyGetQueryInfo.
125 $deep = false;
126 if ( $result ) {
127 if ( isset( $result->b_namespace ) ) {
128 $deep = $result;
129 } else {
131 $qi = $this->reallyGetQueryInfo(
132 $result->namespace,
133 $result->title
134 );
135 $res = $dbr->select(
136 $qi['tables'],
137 $qi['fields'],
138 $qi['conds'],
139 __METHOD__
140 );
141
142 if ( $res ) {
143 $deep = $dbr->fetchObject( $res ) ?: false;
144 }
145 }
146 }
147
148 $titleA = Title::makeTitle( $result->namespace, $result->title );
149
151 if ( !$deep ) {
152 return '<del>' . $linkRenderer->makeLink( $titleA, null, [], [ 'redirect' => 'no' ] ) . '</del>';
153 }
154
155 // if the page is editable, add an edit link
156 if (
157 // check user permissions
158 MediaWikiServices::getInstance()
160 ->userHasRight( $this->getUser(), 'edit' ) &&
161 // check, if the content model is editable through action=edit
162 MediaWikiServices::getInstance()
163 ->getContentHandlerFactory()
164 ->getContentHandler( $titleA->getContentModel() )
165 ->supportsDirectEditing()
166 ) {
167 $edit = $linkRenderer->makeKnownLink(
168 $titleA,
169 $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->text(),
170 [],
171 [ 'action' => 'edit' ]
172 );
173 } else {
174 $edit = '';
175 }
176
177 $linkA = $linkRenderer->makeKnownLink(
178 $titleA,
179 null,
180 [],
181 [ 'redirect' => 'no' ]
182 );
183
184 $titleB = Title::makeTitle( $deep->b_namespace, $deep->b_title );
185 $linkB = $linkRenderer->makeKnownLink(
186 $titleB,
187 null,
188 [],
189 [ 'redirect' => 'no' ]
190 );
191
192 $titleC = Title::makeTitle(
193 $deep->c_namespace,
194 $deep->c_title,
195 $deep->c_fragment,
196 $deep->c_interwiki
197 );
198 $linkC = $linkRenderer->makeKnownLink( $titleC, $titleC->getFullText() );
199
200 $lang = $this->getLanguage();
201 $arr = $lang->getArrow() . $lang->getDirMark();
202
203 return ( "{$linkA} {$edit} {$arr} {$linkB} {$arr} {$linkC}" );
204 }
205
206 public function execute( $par ) {
207 $this->addHelpLink( 'Help:Redirects' );
208 parent::execute( $par );
209 }
210
217 public function preprocessResults( $db, $res ) {
218 if ( !$res->numRows() ) {
219 return;
220 }
221
222 $batch = new LinkBatch;
223 foreach ( $res as $row ) {
224 $batch->add( $row->namespace, $row->title );
225 if ( isset( $row->b_namespace ) ) {
226 // lazy loaded when using cached results
227 $batch->add( $row->b_namespace, $row->b_title );
228 }
229 if ( isset( $row->c_interwiki ) && !$row->c_interwiki ) {
230 // lazy loaded when using cached result, not added when interwiki link
231 $batch->add( $row->c_namespace, $row->c_title );
232 }
233 }
234 $batch->execute();
235
236 // Back to start for display
237 $res->seek( 0 );
238 }
239
240 protected function getGroupName() {
241 return 'maintenance';
242 }
243}
getPermissionManager()
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:35
add( $ns, $dbkey)
MediaWikiServices is the service locator for the application scope of MediaWiki.
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:39
A special page listing redirects to redirecting page.
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
preprocessResults( $db, $res)
Cache page content model and gender distinction for performance.
execute( $par)
This is the actual workhorse.
sortDescending()
Override to sort by increasing values.
isExpensive()
Is this query expensive (for some definition of expensive)? Then we don't let it run in miser mode.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
reallyGetQueryInfo( $namespace=null, $title=null)
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.
isSyndicated()
Sometime we don't want to build rss / atom feeds.
getUser()
Shortcut to get the User executing this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
MediaWiki Linker LinkRenderer null $linkRenderer
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.
const DB_REPLICA
Definition defines.php:25
if(!isset( $args[0])) $lang