MediaWiki  master
SpecialBrokenRedirects.php
Go to the documentation of this file.
1 <?php
24 namespace MediaWiki\Specials;
25 
29 use QueryPage;
30 use Skin;
34 
42 
44  private $contentHandlerFactory;
45 
51  public function __construct(
52  IContentHandlerFactory $contentHandlerFactory,
53  IConnectionProvider $dbProvider,
54  LinkBatchFactory $linkBatchFactory
55  ) {
56  parent::__construct( 'BrokenRedirects' );
57  $this->contentHandlerFactory = $contentHandlerFactory;
58  $this->setDatabaseProvider( $dbProvider );
59  $this->setLinkBatchFactory( $linkBatchFactory );
60  }
61 
62  public function isExpensive() {
63  return true;
64  }
65 
66  public function isSyndicated() {
67  return false;
68  }
69 
70  protected function sortDescending() {
71  return false;
72  }
73 
74  protected function getPageHeader() {
75  return $this->msg( 'brokenredirectstext' )->parseAsBlock();
76  }
77 
78  public function getQueryInfo() {
79  $dbr = $this->getDatabaseProvider()->getReplicaDatabase();
80 
81  return [
82  'tables' => [
83  'redirect',
84  'p1' => 'page',
85  'p2' => 'page',
86  ],
87  'fields' => [
88  'namespace' => 'p1.page_namespace',
89  'title' => 'p1.page_title',
90  'rd_namespace',
91  'rd_title',
92  'rd_fragment',
93  ],
94  'conds' => [
95  // Exclude pages that don't exist locally as wiki pages,
96  // but aren't "broken" either.
97  // Special pages and interwiki links
98  'rd_namespace >= 0',
99  'rd_interwiki IS NULL OR rd_interwiki = ' . $dbr->addQuotes( '' ),
100  'p2.page_namespace IS NULL',
101  ],
102  'join_conds' => [
103  'p1' => [ 'JOIN', [
104  'rd_from=p1.page_id',
105  ] ],
106  'p2' => [ 'LEFT JOIN', [
107  'rd_namespace=p2.page_namespace',
108  'rd_title=p2.page_title'
109  ] ],
110  ],
111  ];
112  }
113 
117  protected function getOrderFields() {
118  return [ 'rd_namespace', 'rd_title', 'rd_from' ];
119  }
120 
126  public function formatResult( $skin, $result ) {
127  $fromObj = Title::makeTitle( $result->namespace, $result->title );
128  if ( isset( $result->rd_title ) ) {
129  $toObj = Title::makeTitle(
130  $result->rd_namespace,
131  $result->rd_title,
132  $result->rd_fragment ?? ''
133  );
134  } else {
135  $blinks = $fromObj->getBrokenLinksFrom(); # TODO: check for redirect, not for links
136  if ( $blinks ) {
137  $toObj = $blinks[0];
138  } else {
139  $toObj = false;
140  }
141  }
142 
143  $linkRenderer = $this->getLinkRenderer();
144 
145  // $toObj may very easily be false if the $result list is cached
146  if ( !is_object( $toObj ) ) {
147  return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
148  }
149 
150  $from = $linkRenderer->makeKnownLink(
151  $fromObj,
152  null,
153  [],
154  [ 'redirect' => 'no' ]
155  );
156  $links = [];
157  // if the page is editable, add an edit link
158  if (
159  // check user permissions
160  $this->getAuthority()->isAllowed( 'edit' ) &&
161  // check, if the content model is editable through action=edit
162  $this->contentHandlerFactory->getContentHandler( $fromObj->getContentModel() )
163  ->supportsDirectEditing()
164  ) {
165  $links[] = $linkRenderer->makeKnownLink(
166  $fromObj,
167  $this->msg( 'brokenredirects-edit' )->text(),
168  [],
169  [ 'action' => 'edit' ]
170  );
171  }
172  $to = $linkRenderer->makeBrokenLink( $toObj, $toObj->getFullText() );
173  $arr = $this->getLanguage()->getArrow();
174 
175  $out = $from . $this->msg( 'word-separator' )->escaped();
176 
177  if ( $this->getAuthority()->isAllowed( 'delete' ) ) {
178  $links[] = $linkRenderer->makeKnownLink(
179  $fromObj,
180  $this->msg( 'brokenredirects-delete' )->text(),
181  [],
182  [
183  'action' => 'delete',
184  'wpReason' => $this->msg( 'brokenredirects-delete-reason' )
185  ->inContentLanguage()
186  ->text()
187  ]
188  );
189  }
190 
191  if ( $links ) {
192  $out .= $this->msg( 'parentheses' )->rawParams( $this->getLanguage()
193  ->pipeList( $links ) )->escaped();
194  }
195  $out .= " {$arr} {$to}";
196 
197  return $out;
198  }
199 
200  public function execute( $par ) {
201  $this->addHelpLink( 'Help:Redirects' );
202  parent::execute( $par );
203  }
204 
211  public function preprocessResults( $db, $res ) {
213  }
214 
215  protected function getGroupName() {
216  return 'maintenance';
217  }
218 }
219 
223 class_alias( SpecialBrokenRedirects::class, 'SpecialBrokenRedirects' );
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:82
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:693
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:65
setDatabaseProvider(IConnectionProvider $databaseProvider)
Definition: QueryPage.php:964
executeLBFromResultWrapper(IResultWrapper $res, $ns=null)
Creates a new LinkBatch object, adds all pages from the passed result wrapper (MUST include title and...
Definition: QueryPage.php:925
setLinkBatchFactory(LinkBatchFactory $linkBatchFactory)
Definition: QueryPage.php:162
getDatabaseProvider()
Definition: QueryPage.php:972
The main skin class which provides methods and properties for all other skins.
Definition: Skin.php:57
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.
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.