r90750 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r90749‎ | r90750 | r90751 >
Date:02:55, 25 June 2011
Author:reedy
Status:ok
Tags:
Comment:
Followup r86198 per Happy-melon comment on CR, delete DeleteAction as it's unreferenced/ooold
Modified paths:
  • /trunk/phase3/includes/actions/DeleteAction.php (deleted) (history)

Diff [purge]

Index: trunk/phase3/includes/actions/DeleteAction.php
@@ -1,484 +0,0 @@
2 -<?php
3 -/**
4 - * Performs the delete action on a page
5 - *
6 - * This program is free software; you can redistribute it and/or modify
7 - * it under the terms of the GNU General Public License as published by
8 - * the Free Software Foundation; either version 2 of the License, or
9 - * (at your option) any later version.
10 - *
11 - * This program is distributed in the hope that it will be useful,
12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 - * GNU General Public License for more details.
15 - *
16 - * You should have received a copy of the GNU General Public License
17 - * along with this program; if not, write to the Free Software
18 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 - *
20 - * @file
21 - * @ingroup Actions
22 - */
23 -
24 -class DeleteAction extends Action {
25 -
26 - public function getName(){
27 - return 'delete';
28 - }
29 -
30 - public function getRestriction(){
31 - return 'delete';
32 - }
33 -
34 - protected function getDescription(){
35 - return wfMsg( 'delete-confirm', $this->getTitle()->getPrefixedText() );
36 - }
37 -
38 - /**
39 - * Check that the deletion can be executed. In addition to checking the user permissions,
40 - * check that the page is not too big and has not already been deleted.
41 - * @throws ErrorPageError
42 - * @see Action::checkCanExecute
43 - *
44 - * @param $user User
45 - */
46 - protected function checkCanExecute( User $user ){
47 -
48 - // Check that the article hasn't already been deleted
49 - $dbw = wfGetDB( DB_MASTER );
50 - $conds = $this->getTitle()->pageCond();
51 - $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
52 - if ( $latest === false ) {
53 - // Get the deletion log
54 - $log = '';
55 - LogEventsList::showLogExtract(
56 - $log,
57 - 'delete',
58 - $this->getTitle()->getPrefixedText()
59 - );
60 -
61 - $msg = new Message( 'cannotdelete' );
62 - $msg->params( $this->getTitle()->getPrefixedText() ); // This parameter is parsed
63 - $msg->rawParams( $log ); // This is not
64 -
65 - throw new ErrorPageError( 'internalerror', $msg );
66 - }
67 -
68 - // Limit deletions of big pages
69 - $bigHistory = $this->isBigDeletion();
70 - if ( $bigHistory && !$user->isAllowed( 'bigdelete' ) ) {
71 - global $wgDeleteRevisionsLimit;
72 - throw new ErrorPageError(
73 - 'internalerror',
74 - 'delete-toobig',
75 - $this->getContext()->lang->formatNum( $wgDeleteRevisionsLimit )
76 - );
77 - }
78 -
79 - return parent::checkCanExecute( $user );
80 - }
81 -
82 - protected function getFormFields(){
83 - // TODO: add more useful things here?
84 - $infoText = Html::rawElement(
85 - 'strong',
86 - array(),
87 - Linker::link( $this->getTitle(), $this->getTitle()->getText() )
88 - );
89 -
90 - $arr = array(
91 - 'Page' => array(
92 - 'type' => 'info',
93 - 'raw' => true,
94 - 'default' => $infoText,
95 - ),
96 - 'Reason' => array(
97 - 'type' => 'selectandother',
98 - 'label-message' => 'deletecomment',
99 - 'options-message' => 'deletereason-dropdown',
100 - 'size' => '60',
101 - 'maxlength' => '255',
102 - 'default' => self::getAutoReason( $this->page),
103 - ),
104 - );
105 -
106 - if( $this->getUser()->isLoggedIn() ){
107 - $arr['Watch'] = array(
108 - 'type' => 'check',
109 - 'label-message' => 'watchthis',
110 - 'default' => $this->getUser()->getBoolOption( 'watchdeletion' ) || $this->getTitle()->userIsWatching()
111 - );
112 - }
113 -
114 - if( $this->getUser()->isAllowed( 'suppressrevision' ) ){
115 - $arr['Suppress'] = array(
116 - 'type' => 'check',
117 - 'label-message' => 'revdelete-suppress',
118 - 'default' => false,
119 - );
120 - }
121 -
122 - return $arr;
123 - }
124 -
125 - /**
126 - * Text to go at the top of the form, before the opening fieldset
127 - * @see Action::preText()
128 - * @return String
129 - */
130 - protected function preText() {
131 -
132 - // If the page has a history, insert a warning
133 - if ( $this->page->estimateRevisionCount() ) {
134 - global $wgLang;
135 -
136 - $link = Linker::link(
137 - $this->getTitle(),
138 - wfMsgHtml( 'history' ),
139 - array( 'rel' => 'archives' ),
140 - array( 'action' => 'history' )
141 - );
142 -
143 - return Html::rawElement(
144 - 'strong',
145 - array( 'class' => 'mw-delete-warning-revisions' ),
146 - wfMessage(
147 - 'historywarning',
148 - $wgLang->formatNum( $this->page->estimateRevisionCount() )
149 - )->rawParams( $link )->parse()
150 - );
151 - }
152 - }
153 -
154 - /**
155 - * Text to go at the bottom of the form, below the closing fieldset
156 - * @see Action::postText()
157 - * @return string
158 - */
159 - protected function postText(){
160 - $s = '';
161 - LogEventsList::showLogExtract(
162 - $s,
163 - 'delete',
164 - $this->getTitle()->getPrefixedText()
165 - );
166 - return Html::element( 'h2', array(), LogPage::logName( 'delete' ) ) . $s;
167 - }
168 -
169 - protected function alterForm( HTMLForm &$form ){
170 - $form->setWrapperLegend( wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) );
171 -
172 - if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
173 - $link = Linker::link(
174 - Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' ),
175 - wfMsgHtml( 'delete-edit-reasonlist' ),
176 - array(),
177 - array( 'action' => 'edit' )
178 - );
179 - $form->addHeaderText( '<p class="mw-delete-editreasons">' . $link . '</p>' );
180 - }
181 - }
182 -
183 - /**
184 - * Function called on form submission. Privilege checks and validation have already been
185 - * completed by this point; we just need to jump out to the heavy-lifting function,
186 - * which is implemented as a static method so it can be called from other places
187 - * TODO: make those other places call $action->execute() properly
188 - * @see Action::onSubmit()
189 - * @param $data Array
190 - * @return Array|Bool
191 - */
192 - public function onSubmit( $data ){
193 - $status = self::doDeleteArticle( $this->page, $this->getContext(), $data, true );
194 - return $status;
195 - }
196 -
197 - public function onSuccess(){
198 - // Watch or unwatch, if requested
199 - if( $this->getRequest()->getCheck( 'wpWatch' ) && $this->getUser()->isLoggedIn() ) {
200 - WatchAction::doWatch( $this->getTitle(), $this->getUser() );
201 - } elseif ( $this->getTitle()->userIsWatching() ) {
202 - WatchAction::doUnwatch( $this->getTitle(), $this->getUser() );
203 - }
204 -
205 - $this->getOutput()->setPagetitle( wfMsg( 'actioncomplete' ) );
206 - $this->getOutput()->addWikiMsg(
207 - 'deletedtext',
208 - wfEscapeWikiText( $this->getTitle()->getPrefixedText() ),
209 - '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]'
210 - );
211 - $this->getOutput()->returnToMain( false );
212 - }
213 -
214 - /**
215 - * @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
216 - */
217 - protected function isBigDeletion() {
218 - global $wgDeleteRevisionsLimit;
219 - return $wgDeleteRevisionsLimit && $this->page->estimateRevisionCount() > $wgDeleteRevisionsLimit;
220 - }
221 -
222 - /**
223 - * Back-end article deletion
224 - * Deletes the article with database consistency, writes logs, purges caches
225 - *
226 - * @param $commit boolean defaults to true, triggers transaction end
227 - * @return Bool|Array true if successful, error array on failure
228 - */
229 - public static function doDeleteArticle( Article $page, RequestContext $context, array $data, $commit = true ) {
230 - global $wgDeferredUpdateList, $wgUseTrackbacks;
231 -
232 - wfDebug( __METHOD__ . "\n" );
233 -
234 - // The normal syntax from HTMLSelectAndOtherField is for the reason to be in the form
235 - // 'Reason' => array( <full reason>, <dropdown>, <custom> ), but it's reasonable for other
236 - // functions to just pass 'Reason' => <reason>
237 - $data['Reason'] = (array)$data['Reason'];
238 -
239 - $error = null;
240 - if ( !wfRunHooks( 'ArticleDelete', array( &$page, $context->getUser(), &$data['Reason'][0], &$error ) ) ) {
241 - return $error;
242 - }
243 -
244 - $title = $page->getTitle();
245 - $id = $page->getID( Title::GAID_FOR_UPDATE );
246 -
247 - if ( $title->getDBkey() === '' || $id == 0 ) {
248 - return false;
249 - }
250 -
251 - $updates = new SiteStatsUpdate( 0, 1, - (int)$page->isCountable(), -1 );
252 - array_push( $wgDeferredUpdateList, $updates );
253 -
254 - // Bitfields to further suppress the content
255 - if ( isset( $data['Suppress'] ) && $data['Suppress'] ) {
256 - $bitfield = 0;
257 - // This should be 15...
258 - $bitfield |= Revision::DELETED_TEXT;
259 - $bitfield |= Revision::DELETED_COMMENT;
260 - $bitfield |= Revision::DELETED_USER;
261 - $bitfield |= Revision::DELETED_RESTRICTED;
262 -
263 - $logtype = 'suppress';
264 - } else {
265 - // Otherwise, leave it unchanged
266 - $bitfield = 'rev_deleted';
267 - $logtype = 'delete';
268 - }
269 -
270 - $dbw = wfGetDB( DB_MASTER );
271 - $dbw->begin();
272 - // For now, shunt the revision data into the archive table.
273 - // Text is *not* removed from the text table; bulk storage
274 - // is left intact to avoid breaking block-compression or
275 - // immutable storage schemes.
276 - //
277 - // For backwards compatibility, note that some older archive
278 - // table entries will have ar_text and ar_flags fields still.
279 - //
280 - // In the future, we may keep revisions and mark them with
281 - // the rev_deleted field, which is reserved for this purpose.
282 - $dbw->insertSelect(
283 - 'archive',
284 - array( 'page', 'revision' ),
285 - array(
286 - 'ar_namespace' => 'page_namespace',
287 - 'ar_title' => 'page_title',
288 - 'ar_comment' => 'rev_comment',
289 - 'ar_user' => 'rev_user',
290 - 'ar_user_text' => 'rev_user_text',
291 - 'ar_timestamp' => 'rev_timestamp',
292 - 'ar_minor_edit' => 'rev_minor_edit',
293 - 'ar_rev_id' => 'rev_id',
294 - 'ar_text_id' => 'rev_text_id',
295 - 'ar_text' => "''", // Be explicit to appease
296 - 'ar_flags' => "''", // MySQL's "strict mode"...
297 - 'ar_len' => 'rev_len',
298 - 'ar_page_id' => 'page_id',
299 - 'ar_deleted' => $bitfield
300 - ),
301 - array(
302 - 'page_id' => $id,
303 - 'page_id = rev_page'
304 - ),
305 - __METHOD__
306 - );
307 -
308 - // Delete restrictions for it
309 - $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
310 -
311 - // Now that it's safely backed up, delete it
312 - $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
313 -
314 - // getArticleId() uses slave, could be laggy
315 - if ( $dbw->affectedRows() == 0 ) {
316 - $dbw->rollback();
317 - return false;
318 - }
319 -
320 - // Fix category table counts
321 - $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
322 - $cats = array();
323 - foreach ( $res as $row ) {
324 - $cats[] = $row->cl_to;
325 - }
326 - $page->updateCategoryCounts( array(), $cats );
327 -
328 - // If using cascading deletes, we can skip some explicit deletes
329 - if ( !$dbw->cascadingDeletes() ) {
330 - $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
331 -
332 - if ( $wgUseTrackbacks ){
333 - $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
334 - }
335 -
336 - // Delete outgoing links
337 - $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) );
338 - $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
339 - $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
340 - $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) );
341 - $dbw->delete( 'externallinks', array( 'el_from' => $id ) );
342 - $dbw->delete( 'langlinks', array( 'll_from' => $id ) );
343 - $dbw->delete( 'redirect', array( 'rd_from' => $id ) );
344 - }
345 -
346 - // If using cleanup triggers, we can skip some manual deletes
347 - if ( !$dbw->cleanupTriggers() ) {
348 - // Clean up recentchanges entries...
349 - $dbw->delete( 'recentchanges',
350 - array(
351 - 'rc_type != ' . RC_LOG,
352 - 'rc_namespace' => $title->getNamespace(),
353 - 'rc_title' => $title->getDBkey() ),
354 - __METHOD__
355 - );
356 - $dbw->delete(
357 - 'recentchanges',
358 - array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
359 - __METHOD__
360 - );
361 - }
362 -
363 - // Clear caches
364 - // TODO: should this be in here or left in Article?
365 - Article::onArticleDelete( $title );
366 -
367 - // Clear the cached article id so the interface doesn't act like we exist
368 - $title->resetArticleID( 0 );
369 -
370 - // Log the deletion, if the page was suppressed, log it at Oversight instead
371 - $log = new LogPage( $logtype );
372 -
373 - // Make sure logging got through
374 - $log->addEntry( 'delete', $title, $data['Reason'][0], array() );
375 -
376 - if ( $commit ) {
377 - $dbw->commit();
378 - }
379 -
380 - wfRunHooks( 'ArticleDeleteComplete', array( &$page, $context->getUser(), $data['Reason'][0], $id ) );
381 - return true;
382 - }
383 -
384 - /**
385 - * Auto-generates a deletion reason. Also sets $this->hasHistory if the page has old
386 - * revisions.
387 - *
388 - * @return mixed String containing default reason or empty string, or boolean false
389 - * if no revision was found
390 - */
391 - public static function getAutoReason( Article $page ) {
392 - global $wgContLang;
393 -
394 - $dbw = wfGetDB( DB_MASTER );
395 - // Get the last revision
396 - $rev = Revision::newFromTitle( $page->getTitle() );
397 -
398 - if ( is_null( $rev ) ) {
399 - return false;
400 - }
401 -
402 - // Get the article's contents
403 - $contents = $rev->getText();
404 - $blank = false;
405 -
406 - // If the page is blank, use the text from the previous revision,
407 - // which can only be blank if there's a move/import/protect dummy revision involved
408 - if ( $contents == '' ) {
409 - $prev = $rev->getPrevious();
410 -
411 - if ( $prev ) {
412 - $contents = $prev->getText();
413 - $blank = true;
414 - }
415 - }
416 -
417 - // Find out if there was only one contributor
418 - // Only scan the last 20 revisions
419 - $res = $dbw->select( 'revision', 'rev_user_text',
420 - array(
421 - 'rev_page' => $page->getID(),
422 - $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0'
423 - ),
424 - __METHOD__,
425 - array( 'LIMIT' => 20 )
426 - );
427 -
428 - if ( $res === false ) {
429 - // This page has no revisions, which is very weird
430 - return false;
431 - }
432 -
433 - $row = $dbw->fetchObject( $res );
434 -
435 - if ( $row ) { // $row is false if the only contributor is hidden
436 - $onlyAuthor = $row->rev_user_text;
437 - // Try to find a second contributor
438 - foreach ( $res as $row ) {
439 - if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
440 - $onlyAuthor = false;
441 - break;
442 - }
443 - }
444 - } else {
445 - $onlyAuthor = false;
446 - }
447 -
448 - // Generate the summary with a '$1' placeholder
449 - if ( $blank ) {
450 - // The current revision is blank and the one before is also
451 - // blank. It's just not our lucky day
452 - $reason = wfMessage( 'exbeforeblank', '$1' )->inContentLanguage()->text();
453 - } else {
454 - if ( $onlyAuthor ) {
455 - $reason = wfMessage( 'excontentauthor', '$1', $onlyAuthor )->inContentLanguage()->text();
456 - } else {
457 - $reason = wfMessage( 'excontent', '$1' )->inContentLanguage()->text();
458 - }
459 - }
460 -
461 - if ( $reason == '-' ) {
462 - // Allow these UI messages to be blanked out cleanly
463 - return '';
464 - }
465 -
466 - // Replace newlines with spaces to prevent uglyness
467 - $contents = preg_replace( "/[\n\r]/", ' ', $contents );
468 - // Calculate the maximum number of chars to get
469 - // Max content length = max comment length - length of the comment (excl. $1)
470 - $maxLength = 255 - ( strlen( $reason ) - 2 );
471 - $contents = $wgContLang->truncate( $contents, $maxLength );
472 - // Remove possible unfinished links
473 - $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
474 - // Now replace the '$1' placeholder
475 - $reason = str_replace( '$1', $contents, $reason );
476 -
477 - return $reason;
478 - }
479 -
480 - public function show() {
481 - }
482 -
483 - public function execute(){
484 - }
485 -}

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r86198Fix missing abstract methods, logging against r86001reedy11:25, 16 April 2011

Status & tagging log