MediaWiki  master
SpecialDoubleRedirects.php
Go to the documentation of this file.
1 <?php
27 
35  function __construct( $name = 'DoubleRedirects' ) {
36  parent::__construct( $name );
37  }
38 
39  public function isExpensive() {
40  return true;
41  }
42 
43  function isSyndicated() {
44  return false;
45  }
46 
47  function sortDescending() {
48  return false;
49  }
50 
51  function getPageHeader() {
52  return $this->msg( 'doubleredirectstext' )->parseAsBlock();
53  }
54 
55  function reallyGetQueryInfo( $namespace = null, $title = null ) {
56  $limitToTitle = !( $namespace === null && $title === null );
57  $dbr = wfGetDB( DB_REPLICA );
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  function getOrderFields() {
111  return [ 'ra.rd_namespace', 'ra.rd_title' ];
112  }
113 
119  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 {
130  $dbr = wfGetDB( DB_REPLICA );
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 
150  $linkRenderer = $this->getLinkRenderer();
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  ContentHandler::getForTitle( $titleA )->supportsDirectEditing()
163  ) {
164  $edit = $linkRenderer->makeKnownLink(
165  $titleA,
166  $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->text(),
167  [],
168  [ 'action' => 'edit' ]
169  );
170  } else {
171  $edit = '';
172  }
173 
174  $linkA = $linkRenderer->makeKnownLink(
175  $titleA,
176  null,
177  [],
178  [ 'redirect' => 'no' ]
179  );
180 
181  $titleB = Title::makeTitle( $deep->b_namespace, $deep->b_title );
182  $linkB = $linkRenderer->makeKnownLink(
183  $titleB,
184  null,
185  [],
186  [ 'redirect' => 'no' ]
187  );
188 
189  $titleC = Title::makeTitle(
190  $deep->c_namespace,
191  $deep->c_title,
192  $deep->c_fragment,
193  $deep->c_interwiki
194  );
195  $linkC = $linkRenderer->makeKnownLink( $titleC, $titleC->getFullText() );
196 
197  $lang = $this->getLanguage();
198  $arr = $lang->getArrow() . $lang->getDirMark();
199 
200  return ( "{$linkA} {$edit} {$arr} {$linkB} {$arr} {$linkC}" );
201  }
202 
203  public function execute( $par ) {
204  $this->addHelpLink( 'Help:Redirects' );
205  parent::execute( $par );
206  }
207 
214  function preprocessResults( $db, $res ) {
215  if ( !$res->numRows() ) {
216  return;
217  }
218 
219  $batch = new LinkBatch;
220  foreach ( $res as $row ) {
221  $batch->add( $row->namespace, $row->title );
222  if ( isset( $row->b_namespace ) ) {
223  // lazy loaded when using cached results
224  $batch->add( $row->b_namespace, $row->b_title );
225  }
226  if ( isset( $row->c_interwiki ) && !$row->c_interwiki ) {
227  // lazy loaded when using cached result, not added when interwiki link
228  $batch->add( $row->c_namespace, $row->c_title );
229  }
230  }
231  $batch->execute();
232 
233  // Back to start for display
234  $res->seek( 0 );
235  }
236 
237  protected function getGroupName() {
238  return 'maintenance';
239  }
240 }
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:792
SpecialDoubleRedirects\getQueryInfo
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
Definition: SpecialDoubleRedirects.php:106
SpecialDoubleRedirects\isSyndicated
isSyndicated()
Sometime we don't want to build rss / atom feeds.
Definition: SpecialDoubleRedirects.php:43
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:35
LinkBatch\add
add( $ns, $dbkey)
Definition: LinkBatch.php:130
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:35
ContentHandler\getForTitle
static getForTitle(Title $title)
Returns the appropriate ContentHandler singleton for the given title.
Definition: ContentHandler.php:201
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:749
$res
$res
Definition: testCompression.php:54
QueryPage
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:36
SpecialDoubleRedirects\preprocessResults
preprocessResults( $db, $res)
Cache page content model and gender distinction for performance.
Definition: SpecialDoubleRedirects.php:214
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
$dbr
$dbr
Definition: testCompression.php:52
SpecialDoubleRedirects\reallyGetQueryInfo
reallyGetQueryInfo( $namespace=null, $title=null)
Definition: SpecialDoubleRedirects.php:55
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:828
SpecialDoubleRedirects\__construct
__construct( $name='DoubleRedirects')
Definition: SpecialDoubleRedirects.php:35
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
getPermissionManager
getPermissionManager()
SpecialDoubleRedirects
A special page listing redirects to redirecting page.
Definition: SpecialDoubleRedirects.php:34
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2562
SpecialDoubleRedirects\formatResult
formatResult( $skin, $result)
Definition: SpecialDoubleRedirects.php:119
$title
$title
Definition: testCompression.php:36
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:729
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:584
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
SpecialDoubleRedirects\getOrderFields
getOrderFields()
Subclasses return an array of fields to order by here.
Definition: SpecialDoubleRedirects.php:110
SpecialDoubleRedirects\isExpensive
isExpensive()
Is this query expensive (for some definition of expensive)? Then we don't let it run in miser mode.
Definition: SpecialDoubleRedirects.php:39
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:904
SpecialDoubleRedirects\sortDescending
sortDescending()
Override to sort by increasing values.
Definition: SpecialDoubleRedirects.php:47
SpecialDoubleRedirects\getPageHeader
getPageHeader()
The content returned by this function will be output before any result.
Definition: SpecialDoubleRedirects.php:51
SpecialDoubleRedirects\execute
execute( $par)
This is the actual workhorse.
Definition: SpecialDoubleRedirects.php:203
SpecialDoubleRedirects\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialDoubleRedirects.php:237
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:67