MediaWiki master
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, but aren't "broken" either: special
95 // pages and interwiki links.
96 'rd_namespace >= 0',
97 'rd_interwiki' => '',
98 'p2.page_namespace' => null,
99 ],
100 'join_conds' => [
101 'p1' => [ 'JOIN', [
102 'rd_from=p1.page_id',
103 ] ],
104 'p2' => [ 'LEFT JOIN', [
105 'rd_namespace=p2.page_namespace',
106 'rd_title=p2.page_title'
107 ] ],
108 ],
109 ];
110 }
111
115 protected function getOrderFields() {
116 return [ 'rd_namespace', 'rd_title', 'rd_from' ];
117 }
118
124 public function formatResult( $skin, $result ) {
125 $fromObj = Title::makeTitle( $result->namespace, $result->title );
126 if ( isset( $result->rd_title ) ) {
127 $toObj = Title::makeTitle(
128 $result->rd_namespace,
129 $result->rd_title,
130 $result->rd_fragment
131 );
132 } else {
133 $toObj = false;
134 }
135
136 $linkRenderer = $this->getLinkRenderer();
137
138 // $toObj may very easily be false if the $result list is cached
139 if ( !is_object( $toObj ) ) {
140 return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
141 }
142
143 $from = $linkRenderer->makeKnownLink(
144 $fromObj,
145 null,
146 [],
147 [ 'redirect' => 'no' ]
148 );
149 $links = [];
150 // if the page is editable, add an edit link
151 if (
152 // check user permissions
153 $this->getAuthority()->isAllowed( 'edit' ) &&
154 // check, if the content model is editable through action=edit
155 $this->contentHandlerFactory->getContentHandler( $fromObj->getContentModel() )
156 ->supportsDirectEditing()
157 ) {
158 $links[] = $linkRenderer->makeKnownLink(
159 $fromObj,
160 $this->msg( 'brokenredirects-edit' )->text(),
161 [],
162 [ 'action' => 'edit' ]
163 );
164 }
165 $to = $linkRenderer->makeBrokenLink( $toObj, $toObj->getFullText() );
166 $arr = $this->getLanguage()->getArrow();
167
168 $out = $from . $this->msg( 'word-separator' )->escaped();
169
170 if ( $this->getAuthority()->isAllowed( 'delete' ) ) {
171 $links[] = $linkRenderer->makeKnownLink(
172 $fromObj,
173 $this->msg( 'brokenredirects-delete' )->text(),
174 [],
175 [
176 'action' => 'delete',
177 'wpReason' => $this->msg( 'brokenredirects-delete-reason' )
178 ->inContentLanguage()
179 ->text()
180 ]
181 );
182 }
183
184 if ( $links ) {
185 $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
186 ->pipeList( $links ) )->escaped();
187 }
188 $out .= " {$arr} {$to}";
189
190 return $out;
191 }
192
193 public function execute( $par ) {
194 $this->addHelpLink( 'Help:Redirects' );
195 parent::execute( $par );
196 }
197
204 public function preprocessResults( $db, $res ) {
205 $this->executeLBFromResultWrapper( $res );
206 }
207
208 protected function getGroupName() {
209 return 'maintenance';
210 }
211}
212
214class_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:89
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:78
The base class for all skins.
Definition Skin.php:59
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...