MediaWiki 1.41.2
SpecialBrokenRedirects.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Specials;
25
30use Skin;
34
42
43 private IContentHandlerFactory $contentHandlerFactory;
44
50 public function __construct(
51 IContentHandlerFactory $contentHandlerFactory,
52 IConnectionProvider $dbProvider,
53 LinkBatchFactory $linkBatchFactory
54 ) {
55 parent::__construct( 'BrokenRedirects' );
56 $this->contentHandlerFactory = $contentHandlerFactory;
57 $this->setDatabaseProvider( $dbProvider );
58 $this->setLinkBatchFactory( $linkBatchFactory );
59 }
60
61 public function isExpensive() {
62 return true;
63 }
64
65 public function isSyndicated() {
66 return false;
67 }
68
69 protected function sortDescending() {
70 return false;
71 }
72
73 protected function getPageHeader() {
74 return $this->msg( 'brokenredirectstext' )->parseAsBlock();
75 }
76
77 public function getQueryInfo() {
78 $dbr = $this->getDatabaseProvider()->getReplicaDatabase();
79
80 return [
81 'tables' => [
82 'redirect',
83 'p1' => 'page',
84 'p2' => 'page',
85 ],
86 'fields' => [
87 'namespace' => 'p1.page_namespace',
88 'title' => 'p1.page_title',
89 'rd_namespace',
90 'rd_title',
91 'rd_fragment',
92 ],
93 'conds' => [
94 // Exclude pages that don't exist locally as wiki pages,
95 // but aren't "broken" either.
96 // Special pages and interwiki links
97 'rd_namespace >= 0',
98 'rd_interwiki' => [ null, '' ],
99 'p2.page_namespace' => null,
100 ],
101 'join_conds' => [
102 'p1' => [ 'JOIN', [
103 'rd_from=p1.page_id',
104 ] ],
105 'p2' => [ 'LEFT JOIN', [
106 'rd_namespace=p2.page_namespace',
107 'rd_title=p2.page_title'
108 ] ],
109 ],
110 ];
111 }
112
116 protected function getOrderFields() {
117 return [ 'rd_namespace', 'rd_title', 'rd_from' ];
118 }
119
125 public function formatResult( $skin, $result ) {
126 $fromObj = Title::makeTitle( $result->namespace, $result->title );
127 if ( isset( $result->rd_title ) ) {
128 $toObj = Title::makeTitle(
129 $result->rd_namespace,
130 $result->rd_title,
131 $result->rd_fragment ?? ''
132 );
133 } else {
134 $blinks = $fromObj->getBrokenLinksFrom(); # TODO: check for redirect, not for links
135 if ( $blinks ) {
136 $toObj = $blinks[0];
137 } else {
138 $toObj = false;
139 }
140 }
141
142 $linkRenderer = $this->getLinkRenderer();
143
144 // $toObj may very easily be false if the $result list is cached
145 if ( !is_object( $toObj ) ) {
146 return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
147 }
148
149 $from = $linkRenderer->makeKnownLink(
150 $fromObj,
151 null,
152 [],
153 [ 'redirect' => 'no' ]
154 );
155 $links = [];
156 // if the page is editable, add an edit link
157 if (
158 // check user permissions
159 $this->getAuthority()->isAllowed( 'edit' ) &&
160 // check, if the content model is editable through action=edit
161 $this->contentHandlerFactory->getContentHandler( $fromObj->getContentModel() )
162 ->supportsDirectEditing()
163 ) {
164 $links[] = $linkRenderer->makeKnownLink(
165 $fromObj,
166 $this->msg( 'brokenredirects-edit' )->text(),
167 [],
168 [ 'action' => 'edit' ]
169 );
170 }
171 $to = $linkRenderer->makeBrokenLink( $toObj, $toObj->getFullText() );
172 $arr = $this->getLanguage()->getArrow();
173
174 $out = $from . $this->msg( 'word-separator' )->escaped();
175
176 if ( $this->getAuthority()->isAllowed( 'delete' ) ) {
177 $links[] = $linkRenderer->makeKnownLink(
178 $fromObj,
179 $this->msg( 'brokenredirects-delete' )->text(),
180 [],
181 [
182 'action' => 'delete',
183 'wpReason' => $this->msg( 'brokenredirects-delete-reason' )
184 ->inContentLanguage()
185 ->text()
186 ]
187 );
188 }
189
190 if ( $links ) {
191 $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
192 ->pipeList( $links ) )->escaped();
193 }
194 $out .= " {$arr} {$to}";
195
196 return $out;
197 }
198
199 public function execute( $par ) {
200 $this->addHelpLink( 'Help:Redirects' );
201 parent::execute( $par );
202 }
203
210 public function preprocessResults( $db, $res ) {
211 $this->executeLBFromResultWrapper( $res );
212 }
213
214 protected function getGroupName() {
215 return 'maintenance';
216 }
217}
218
222class_alias( SpecialBrokenRedirects::class, 'SpecialBrokenRedirects' );
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:88
setDatabaseProvider(IConnectionProvider $databaseProvider)
executeLBFromResultWrapper(IResultWrapper $res, $ns=null)
Creates a new LinkBatch object, adds all pages from the passed result wrapper (MUST include title and...
setLinkBatchFactory(LinkBatchFactory $linkBatchFactory)
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getAuthority()
Shortcut to get the Authority executing this instance.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
A special page listing redirects to non existent 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 for performance.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
isExpensive()
Should this query page only be updated offline on large wikis?
__construct(IContentHandlerFactory $contentHandlerFactory, IConnectionProvider $dbProvider, LinkBatchFactory $linkBatchFactory)
isSyndicated()
Sometimes we don't want to build rss / atom feeds.
sortDescending()
Override to sort by increasing values.
getPageHeader()
The content returned by this function will be output before any result.
execute( $par)
This is the actual workhorse.
Represents a title within MediaWiki.
Definition Title.php:76
The base class for all skins.
Definition Skin.php:60
Provide primary and replica IDatabase connections.
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:36
Result wrapper for grabbing data queried from an IDatabase object.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...