MediaWiki  master
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 );
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  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 {
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  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 }
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:828
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:154
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:774
$res
$res
Definition: testCompression.php:57
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:39
SpecialDoubleRedirects\preprocessResults
preprocessResults( $db, $res)
Cache page content model and gender distinction for performance.
Definition: SpecialDoubleRedirects.php:217
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
$dbr
$dbr
Definition: testCompression.php:54
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:864
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:2467
SpecialDoubleRedirects\formatResult
formatResult( $skin, $result)
Definition: SpecialDoubleRedirects.php:119
$title
$title
Definition: testCompression.php:38
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:754
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:592
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:944
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:206
SpecialDoubleRedirects\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialDoubleRedirects.php:240
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:71