MediaWiki master
SpecialBrokenRedirects.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
27use Skin;
31
41
42 private IContentHandlerFactory $contentHandlerFactory;
43
49 public function __construct(
50 IContentHandlerFactory $contentHandlerFactory,
51 IConnectionProvider $dbProvider,
52 LinkBatchFactory $linkBatchFactory
53 ) {
54 parent::__construct( 'BrokenRedirects' );
55 $this->contentHandlerFactory = $contentHandlerFactory;
56 $this->setDatabaseProvider( $dbProvider );
57 $this->setLinkBatchFactory( $linkBatchFactory );
58 }
59
60 public function isExpensive() {
61 return true;
62 }
63
64 public function isSyndicated() {
65 return false;
66 }
67
68 protected function sortDescending() {
69 return false;
70 }
71
72 protected function getPageHeader() {
73 return $this->msg( 'brokenredirectstext' )->parseAsBlock();
74 }
75
76 public function getQueryInfo() {
77 $dbr = $this->getDatabaseProvider()->getReplicaDatabase();
78
79 return [
80 'tables' => [
81 'redirect',
82 'p1' => 'page',
83 'p2' => 'page',
84 ],
85 'fields' => [
86 'namespace' => 'p1.page_namespace',
87 'title' => 'p1.page_title',
88 'rd_namespace',
89 'rd_title',
90 'rd_fragment',
91 ],
92 'conds' => [
93 // Exclude pages that don't exist locally as wiki pages, but aren't "broken" either: special
94 // pages and interwiki links.
95 $dbr->expr( 'rd_namespace', '>=', 0 ),
96 'rd_interwiki' => '',
97 'p2.page_namespace' => null,
98 ],
99 'join_conds' => [
100 'p1' => [ 'JOIN', [
101 'rd_from=p1.page_id',
102 ] ],
103 'p2' => [ 'LEFT JOIN', [
104 'rd_namespace=p2.page_namespace',
105 'rd_title=p2.page_title'
106 ] ],
107 ],
108 ];
109 }
110
114 protected function getOrderFields() {
115 return [ 'rd_namespace', 'rd_title', 'rd_from' ];
116 }
117
123 public function formatResult( $skin, $result ) {
124 $fromObj = Title::makeTitle( $result->namespace, $result->title );
125 if ( isset( $result->rd_title ) ) {
126 $toObj = Title::makeTitle(
127 $result->rd_namespace,
128 $result->rd_title,
129 $result->rd_fragment
130 );
131 } else {
132 $toObj = false;
133 }
134
135 $linkRenderer = $this->getLinkRenderer();
136
137 // $toObj may very easily be false if the $result list is cached
138 if ( !is_object( $toObj ) ) {
139 return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
140 }
141
142 $from = $linkRenderer->makeKnownLink(
143 $fromObj,
144 null,
145 [],
146 [ 'redirect' => 'no' ]
147 );
148 $links = [];
149 // if the page is editable, add an edit link
150 if (
151 // check user permissions
152 $this->getAuthority()->isAllowed( 'edit' ) &&
153 // check, if the content model is editable through action=edit
154 $this->contentHandlerFactory->getContentHandler( $fromObj->getContentModel() )
155 ->supportsDirectEditing()
156 ) {
157 $links[] = $linkRenderer->makeKnownLink(
158 $fromObj,
159 $this->msg( 'brokenredirects-edit' )->text(),
160 [],
161 [ 'action' => 'edit' ]
162 );
163 }
164 $to = $linkRenderer->makeBrokenLink( $toObj, $toObj->getFullText() );
165 $arr = $this->getLanguage()->getArrow();
166
167 $out = $from . $this->msg( 'word-separator' )->escaped();
168
169 if ( $this->getAuthority()->isAllowed( 'delete' ) ) {
170 $links[] = $linkRenderer->makeKnownLink(
171 $fromObj,
172 $this->msg( 'brokenredirects-delete' )->text(),
173 [],
174 [
175 'action' => 'delete',
176 'wpReason' => $this->msg( 'brokenredirects-delete-reason' )
177 ->inContentLanguage()
178 ->text()
179 ]
180 );
181 }
182
183 if ( $links ) {
184 $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
185 ->pipeList( $links ) )->escaped();
186 }
187 $out .= " {$arr} {$to}";
188
189 return $out;
190 }
191
192 public function execute( $par ) {
193 $this->addHelpLink( 'Help:Redirects' );
194 parent::execute( $par );
195 }
196
203 public function preprocessResults( $db, $res ) {
204 $this->executeLBFromResultWrapper( $res );
205 }
206
207 protected function getGroupName() {
208 return 'maintenance';
209 }
210}
211
213class_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:87
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.
List of redirects to non-existent pages.
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:78
The base class for all skins.
Definition Skin.php:64
Provide primary and replica IDatabase connections.
Interface to a relational database.
Definition IDatabase.php:48
Result wrapper for grabbing data queried from an IDatabase object.