MediaWiki  master
SpecialDoubleRedirects.php
Go to the documentation of this file.
1 <?php
29 
37 
40 
43 
46 
48  private $dbr;
49 
56  public function __construct(
61  ) {
62  parent::__construct( 'DoubleRedirects' );
63  $this->permissionManager = $permissionManager;
64  $this->contentHandlerFactory = $contentHandlerFactory;
65  $this->linkBatchFactory = $linkBatchFactory;
66  $this->setDBLoadBalancer( $loadBalancer );
68  }
69 
70  public function isExpensive() {
71  return true;
72  }
73 
74  public function isSyndicated() {
75  return false;
76  }
77 
78  protected function sortDescending() {
79  return false;
80  }
81 
82  protected function getPageHeader() {
83  return $this->msg( 'doubleredirectstext' )->parseAsBlock();
84  }
85 
86  private function reallyGetQueryInfo( $namespace = null, $title = null ) {
87  $limitToTitle = !( $namespace === null && $title === null );
88  $retval = [
89  'tables' => [
90  'ra' => 'redirect',
91  'rb' => 'redirect',
92  'pa' => 'page',
93  'pb' => 'page'
94  ],
95  'fields' => [
96  'namespace' => 'pa.page_namespace',
97  'title' => 'pa.page_title',
98 
99  'b_namespace' => 'pb.page_namespace',
100  'b_title' => 'pb.page_title',
101 
102  // Select fields from redirect instead of page. Because there may
103  // not actually be a page table row for this target (e.g. for interwiki redirects)
104  'c_namespace' => 'rb.rd_namespace',
105  'c_title' => 'rb.rd_title',
106  'c_fragment' => 'rb.rd_fragment',
107  'c_interwiki' => 'rb.rd_interwiki',
108  ],
109  'conds' => [
110  'ra.rd_from = pa.page_id',
111 
112  // Filter out redirects where the target goes interwiki (T42353).
113  // This isn't an optimization, it is required for correct results,
114  // otherwise a non-double redirect like Bar -> w:Foo will show up
115  // like "Bar -> Foo -> w:Foo".
116 
117  // Need to check both NULL and "" for some reason,
118  // apparently either can be stored for non-iw entries.
119  'ra.rd_interwiki IS NULL OR ra.rd_interwiki = ' . $this->dbr->addQuotes( '' ),
120 
121  'pb.page_namespace = ra.rd_namespace',
122  'pb.page_title = ra.rd_title',
123 
124  'rb.rd_from = pb.page_id',
125  ]
126  ];
127 
128  if ( $limitToTitle ) {
129  $retval['conds']['pa.page_namespace'] = $namespace;
130  $retval['conds']['pa.page_title'] = $title;
131  }
132 
133  return $retval;
134  }
135 
136  public function getQueryInfo() {
137  return $this->reallyGetQueryInfo();
138  }
139 
140  protected function getOrderFields() {
141  return [ 'ra.rd_namespace', 'ra.rd_title' ];
142  }
143 
149  public function formatResult( $skin, $result ) {
150  // If no Title B or C is in the query, it means this came from
151  // querycache (which only saves the 3 columns for title A).
152  // That does save the bulk of the query cost, but now we need to
153  // get a little more detail about each individual entry quickly
154  // using the filter of reallyGetQueryInfo.
155  $deep = false;
156  if ( $result ) {
157  if ( isset( $result->b_namespace ) ) {
158  $deep = $result;
159  } else {
160  $qi = $this->reallyGetQueryInfo(
161  $result->namespace,
162  $result->title
163  );
164  $deep = $this->dbr->selectRow(
165  $qi['tables'],
166  $qi['fields'],
167  $qi['conds'],
168  __METHOD__
169  );
170  }
171  }
172 
173  $titleA = Title::makeTitle( $result->namespace, $result->title );
174 
175  $linkRenderer = $this->getLinkRenderer();
176  if ( !$deep ) {
177  return '<del>' . $linkRenderer->makeLink( $titleA, null, [], [ 'redirect' => 'no' ] ) . '</del>';
178  }
179 
180  // if the page is editable, add an edit link
181  if (
182  // check user permissions
183  $this->permissionManager->userHasRight( $this->getUser(), 'edit' ) &&
184  // check, if the content model is editable through action=edit
185  $this->contentHandlerFactory->getContentHandler( $titleA->getContentModel() )
186  ->supportsDirectEditing()
187  ) {
188  $edit = $linkRenderer->makeKnownLink(
189  $titleA,
190  $this->msg( 'parentheses', $this->msg( 'editlink' )->text() )->text(),
191  [],
192  [ 'action' => 'edit' ]
193  );
194  } else {
195  $edit = '';
196  }
197 
198  $linkA = $linkRenderer->makeKnownLink(
199  $titleA,
200  null,
201  [],
202  [ 'redirect' => 'no' ]
203  );
204 
205  $titleB = Title::makeTitle( $deep->b_namespace, $deep->b_title );
206  $linkB = $linkRenderer->makeKnownLink(
207  $titleB,
208  null,
209  [],
210  [ 'redirect' => 'no' ]
211  );
212 
213  $titleC = Title::makeTitle(
214  $deep->c_namespace,
215  $deep->c_title,
216  $deep->c_fragment,
217  $deep->c_interwiki
218  );
219  $linkC = $linkRenderer->makeKnownLink( $titleC, $titleC->getFullText() );
220 
221  $lang = $this->getLanguage();
222  $arr = $lang->getArrow() . $lang->getDirMark();
223 
224  return ( "{$linkA} {$edit} {$arr} {$linkB} {$arr} {$linkC}" );
225  }
226 
227  public function execute( $par ) {
228  $this->addHelpLink( 'Help:Redirects' );
229  parent::execute( $par );
230  }
231 
238  public function preprocessResults( $db, $res ) {
239  if ( !$res->numRows() ) {
240  return;
241  }
242 
243  $batch = $this->linkBatchFactory->newLinkBatch();
244  foreach ( $res as $row ) {
245  $batch->add( $row->namespace, $row->title );
246  if ( isset( $row->b_namespace ) ) {
247  // lazy loaded when using cached results
248  $batch->add( $row->b_namespace, $row->b_title );
249  }
250  if ( isset( $row->c_interwiki ) && !$row->c_interwiki ) {
251  // lazy loaded when using cached result, not added when interwiki link
252  $batch->add( $row->c_namespace, $row->c_title );
253  }
254  }
255  $batch->execute();
256 
257  // Back to start for display
258  $res->seek( 0 );
259  }
260 
261  protected function getGroupName() {
262  return 'maintenance';
263  }
264 }
SpecialPage\$linkRenderer
LinkRenderer null $linkRenderer
Definition: SpecialPage.php:79
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:900
SpecialDoubleRedirects\getQueryInfo
getQueryInfo()
Subclasses return an SQL query here, formatted as an array with the following keys: tables => Table(s...
Definition: SpecialDoubleRedirects.php:136
SpecialDoubleRedirects\isSyndicated
isSyndicated()
Sometime we don't want to build rss / atom feeds.
Definition: SpecialDoubleRedirects.php:74
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
SpecialDoubleRedirects\$linkBatchFactory
LinkBatchFactory $linkBatchFactory
Definition: SpecialDoubleRedirects.php:45
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:818
$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:41
Wikimedia\Rdbms\ILoadBalancer\getConnectionRef
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)
Get a live database handle reference for a real or virtual (DB_MASTER/DB_REPLICA) server index.
SpecialDoubleRedirects\preprocessResults
preprocessResults( $db, $res)
Cache page content model and gender distinction for performance.
Definition: SpecialDoubleRedirects.php:238
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
SpecialDoubleRedirects\reallyGetQueryInfo
reallyGetQueryInfo( $namespace=null, $title=null)
Definition: SpecialDoubleRedirects.php:86
SpecialDoubleRedirects\$dbr
IDatabase $dbr
Definition: SpecialDoubleRedirects.php:48
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:936
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
SpecialDoubleRedirects
A special page listing redirects to redirecting page.
Definition: SpecialDoubleRedirects.php:36
SpecialDoubleRedirects\$permissionManager
PermissionManager $permissionManager
Definition: SpecialDoubleRedirects.php:39
MediaWiki\Cache\LinkBatchFactory
Definition: LinkBatchFactory.php:38
SpecialDoubleRedirects\formatResult
formatResult( $skin, $result)
Definition: SpecialDoubleRedirects.php:149
$title
$title
Definition: testCompression.php:38
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:591
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:140
MediaWiki\Permissions\PermissionManager
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Definition: PermissionManager.php:50
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
QueryPage\setDBLoadBalancer
setDBLoadBalancer(ILoadBalancer $loadBalancer)
Definition: QueryPage.php:873
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:70
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:1016
SpecialDoubleRedirects\sortDescending
sortDescending()
Override to sort by increasing values.
Definition: SpecialDoubleRedirects.php:78
SpecialDoubleRedirects\__construct
__construct(PermissionManager $permissionManager, IContentHandlerFactory $contentHandlerFactory, LinkBatchFactory $linkBatchFactory, ILoadBalancer $loadBalancer)
Definition: SpecialDoubleRedirects.php:56
SpecialDoubleRedirects\getPageHeader
getPageHeader()
The content returned by this function will be output before any result.
Definition: SpecialDoubleRedirects.php:82
SpecialDoubleRedirects\execute
execute( $par)
This is the actual workhorse.
Definition: SpecialDoubleRedirects.php:227
SpecialDoubleRedirects\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialDoubleRedirects.php:261
QueryPage\$loadBalancer
ILoadBalancer null $loadBalancer
Definition: QueryPage.php:71
SpecialDoubleRedirects\$contentHandlerFactory
IContentHandlerFactory $contentHandlerFactory
Definition: SpecialDoubleRedirects.php:42
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81