r89462 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r89461‎ | r89462 | r89463 >
Date:11:41, 4 June 2011
Author:nikerabbit
Status:deferred
Tags:
Comment:
Added a special page that allows deleting translatable pages or parts of them.
Actual deletion is not tested.
Modified paths:
  • /trunk/extensions/Translate/PageTranslation.i18n.php (modified) (history)
  • /trunk/extensions/Translate/Translate.alias.php (modified) (history)
  • /trunk/extensions/Translate/Translate.php (modified) (history)
  • /trunk/extensions/Translate/_autoload.php (modified) (history)
  • /trunk/extensions/Translate/tag/DeleteJob.php (added) (history)
  • /trunk/extensions/Translate/tag/PageTranslationHooks.php (modified) (history)
  • /trunk/extensions/Translate/tag/SpecialPageTranslationDeletePage.php (added) (history)

Diff [purge]

Index: trunk/extensions/Translate/tag/SpecialPageTranslationDeletePage.php
@@ -0,0 +1,355 @@
 2+<?php
 3+/**
 4+ * Special page which enables deleting translations of translatable pages
 5+ *
 6+ * @file
 7+ * @author Niklas Laxström
 8+ * @copyright Copyright © 2011, Niklas Laxström
 9+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 10+ */
 11+
 12+/**
 13+ * Special page which enables deleting translations of translatable pages
 14+ *
 15+ * @ingroup SpecialPage
 16+ * @ingroup PageTranslation
 17+ */
 18+class SpecialPageTranslationDeletePage extends SpecialPage {
 19+ // Basic form parameters both as text and as titles
 20+ protected $text, $title;
 21+
 22+ // Other form parameters
 23+ /// 'check' or 'perform'
 24+ protected $subaction;
 25+
 26+ /// There must be reason for everything.
 27+ protected $reason;
 28+
 29+ /// Allow skipping non-translation subpages.
 30+ protected $doSubpages = false;
 31+
 32+
 33+ /// TranslatablePage instance.
 34+ protected $page;
 35+ /// Contains the language code if we are working with translation page
 36+ protected $code;
 37+
 38+ /// User instance.
 39+ protected $user;
 40+
 41+ public function __construct() {
 42+ parent::__construct( 'PageTranslationDeletePage' );
 43+ }
 44+
 45+ public function execute( $par ) {
 46+ global $wgOut, $wgRequest, $wgUser;
 47+
 48+ // Yes, the use of getVal() and getText() is wanted, see bug 20365
 49+ $this->text = $wgRequest->getVal( 'wpTitle', $par );
 50+ $this->title = Title::newFromText( $this->text );
 51+ $this->reason = $wgRequest->getText( 'reason' );
 52+ // Checkboxes that default being checked are tricky
 53+ $this->doSubpages = $wgRequest->getBool( 'subpages', !$wgRequest->wasPosted() );
 54+
 55+ $this->user = $wgUser;
 56+
 57+ if ( $this->doBasicChecks() !== true ) {
 58+ return;
 59+ }
 60+
 61+ // Real stuff starts here
 62+ if ( TranslatablePage::isSourcePage( $this->title ) ) {
 63+ $wgOut->setPagetitle( wfMsg( 'pt-deletepage-full-title', $this->title->getPrefixedText() ) );
 64+
 65+ $this->code = '';
 66+ $this->page = TranslatablePage::newFromTitle( $this->title );
 67+ } else {
 68+ $page = TranslatablePage::isTranslationPage( $this->title );
 69+ if ( $page ) {
 70+ $wgOut->setPagetitle( wfMsg( 'pt-deletepage-lang-title', $this->title->getPrefixedText() ) );
 71+
 72+ list( , $this->code ) = TranslateUtils::figureMessage( $this->title->getText() );
 73+ $this->page = $page;
 74+ } else {
 75+ $wgOut->showErrorPage( 'pt-deletepage-invalid-title', 'pt-deletepage-invalid-text' );
 76+ return;
 77+ }
 78+ }
 79+
 80+ if ( !$this->user->isAllowed( 'pagetranslation' ) ) {
 81+ $wgOut->permissionRequired( 'pagetranslation' );
 82+ return;
 83+ }
 84+
 85+ // Is there really no better way to do this?
 86+ $subactionText = $wgRequest->getText( 'subaction' );
 87+ switch ( $subactionText ) {
 88+ case wfMsg( 'pt-deletepage-action-check' ):
 89+ $subaction = 'check'; break;
 90+ case wfMsg( 'pt-deletepage-action-perform' ):
 91+ $subaction = 'perform'; break;
 92+ case wfMsg( 'pt-deletepage-action-other' ):
 93+ $subaction = ''; break;
 94+ default:
 95+ $subaction = '';
 96+ }
 97+
 98+ if ( $subaction === 'check' && $this->checkToken() && $wgRequest->wasPosted() ) {
 99+ $this->showConfirmation();
 100+ } elseif ( $subaction === 'perform' && $this->checkToken() && $wgRequest->wasPosted() ) {
 101+ $this->performAction();
 102+ } else {
 103+ $this->showForm();
 104+ }
 105+
 106+ }
 107+
 108+ /**
 109+ * Do the basic checks whether moving is possible and whether
 110+ * the input looks anywhere near sane.
 111+ */
 112+ protected function doBasicChecks() {
 113+ global $wgOut;
 114+ # Check for database lock
 115+ if ( wfReadOnly() ) {
 116+ $wgOut->readOnlyPage();
 117+ return;
 118+ }
 119+
 120+ if ( !$this->title->exists() ) {
 121+ $wgOut->showErrorPage( 'nopagetitle', 'nopagetext' );
 122+ return;
 123+ }
 124+
 125+ # Check rights
 126+ $permErrors = $this->title->getUserPermissionsErrors( 'delete', $this->user );
 127+ if ( !empty( $permErrors ) ) {
 128+ $wgOut->showPermissionsErrorPage( $permErrors );
 129+ return;
 130+ }
 131+
 132+ // Let the caller know it's safe to continue
 133+ return true;
 134+ }
 135+
 136+ /**
 137+ * Checks token. Use before real actions happen. Have to use wpEditToken
 138+ * for compatibility for SpecialMovepage.php.
 139+ */
 140+ protected function checkToken() {
 141+ global $wgRequest;
 142+ return $this->user->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
 143+ }
 144+
 145+ /**
 146+ * The query form.
 147+ */
 148+ protected function showForm() {
 149+ global $wgOut;
 150+
 151+ $wgOut->addWikiMsg( 'pt-deletepage-intro' );
 152+
 153+ $br = Html::element( 'br' );
 154+ $subaction = array( 'name' => 'subaction' );
 155+ $formParams = array( 'method' => 'post', 'action' => $this->getTitle( $this->text )->getLocalURL() );
 156+
 157+ $form = array();
 158+ $form[] = Xml::fieldset( wfMsg( 'pt-deletepage-any-legend' ) );
 159+ $form[] = Html::openElement( 'form', $formParams );
 160+ $form[] = Html::hidden( 'wpEditToken', $this->user->editToken() );
 161+ $this->addInputLabel( $form, wfMsg( 'pt-deletepage-current' ), 'wpTitle', 30, $this->text );
 162+ $this->addInputLabel( $form, wfMsg( 'pt-deletepage-reason' ), 'reason', 60, $this->reason );
 163+ $form[] = Xml::submitButton( wfMsg( 'pt-deletepage-action-check' ), $subaction );
 164+ $form[] = Xml::closeElement( 'form' );
 165+ $form[] = Xml::closeElement( 'fieldset' );
 166+ $wgOut->addHTML( implode( "\n", $form ) );
 167+ }
 168+
 169+ /**
 170+ * Shortcut for keeping the code at least a bit readable. Adds label and input into $form array.
 171+ * @param $form \list{String} Array where input element and label is appended.
 172+ * @param $label \string Label text.
 173+ * @param $name \string Name attribute.
 174+ * @param $size \int Size attribute of the input element. Default false.
 175+ * @param $text \string Text of the value attribute. Default false.
 176+ * @param $attribs \array Extra attributes. Default empty array.
 177+ */
 178+ protected function addInputLabel( &$form, $label, $name, $size = false , $text = false, $attribs = array() ) {
 179+ $br = Html::element( 'br' );
 180+ list( $label, $input ) = Xml::inputLabelSep( $label, $name, $name, $size, $text, $attribs );
 181+ $form[] = $label . $br;
 182+ $form[] = $input . $br;
 183+ }
 184+
 185+ /**
 186+ * The second form, which still allows changing some things.
 187+ * Lists all the action which would take place.
 188+ */
 189+ protected function showConfirmation() {
 190+ global $wgOut, $wgLang;
 191+
 192+ $wgOut->addWikiMsg( 'pt-deletepage-intro' );
 193+
 194+ $base = $this->title->getPrefixedText();
 195+ $target = $this->title;
 196+ $count = 1; // Base page
 197+
 198+ $wgOut->wrapWikiMsg( '== $1 ==', 'pt-deletepage-list-pages' );
 199+ if ( !$this->singleLanguage() ) {
 200+ $this->printChangeLine( $this->title );
 201+ }
 202+
 203+ $wgOut->wrapWikiMsg( '=== $1 ===', 'pt-deletepage-list-translation' );
 204+ $translationPages = $this->getTranslationPages();
 205+ foreach ( $translationPages as $old ) {
 206+ $count++;
 207+ $this->printChangeLine( $old );
 208+ }
 209+
 210+ $wgOut->wrapWikiMsg( '=== $1 ===', 'pt-deletepage-list-section' );
 211+ $sectionPages = $this->getSectionPages( $target );
 212+ foreach ( $sectionPages as $old ) {
 213+ $count++;
 214+ $this->printChangeLine( $old );
 215+ }
 216+
 217+ $wgOut->wrapWikiMsg( '=== $1 ===', 'pt-deletepage-list-other' );
 218+ $subpages = $this->getSubpages();
 219+ foreach ( $subpages as $old ) {
 220+ if ( TranslatablePage::isTranslationPage( $old ) ) continue;
 221+ if ( $this->doSubpages ) { $count++; }
 222+ $this->printChangeLine( $old, $this->doSubpages );
 223+ }
 224+
 225+ $wgOut->addWikiText( "----\n" );
 226+ $wgOut->addWikiMsg( 'pt-deletepage-list-count', $wgLang->formatNum( $count ) );
 227+
 228+ $br = Html::element( 'br' );
 229+ $readonly = array( 'readonly' => 'readonly' );
 230+
 231+ $subaction = array( 'name' => 'subaction' );
 232+ $formParams = array( 'method' => 'post', 'action' => $this->getTitle( $this->text )->getLocalURL() );
 233+
 234+ $form = array();
 235+ if ( $this->singleLanguage() ) {
 236+ $form[] = Xml::fieldset( wfMsg( 'pt-deletepage-lang-legend' ) );
 237+ } else {
 238+ $form[] = Xml::fieldset( wfMsg( 'pt-deletepage-full-legend' ) );
 239+ }
 240+ $form[] = Html::openElement( 'form', $formParams );
 241+ $form[] = Html::hidden( 'wpEditToken', $this->user->editToken() );
 242+ $this->addInputLabel( $form, wfMsg( 'pt-deletepage-current' ), 'wpTitle', 30, $this->text, $readonly );
 243+ $this->addInputLabel( $form, wfMsg( 'pt-deletepage-reason' ), 'reason', 60, $this->reason );
 244+ $form[] = Xml::checkLabel( wfMsg( 'pt-deletepage-subpages' ), 'subpages', 'mw-subpages', $this->doSubpages, $readonly ) . $br;
 245+ $form[] = Xml::submitButton( wfMsg( 'pt-deletepage-action-perform' ), $subaction );
 246+ $form[] = Xml::submitButton( wfMsg( 'pt-deletepage-action-other' ), $subaction );
 247+ $form[] = Xml::closeElement( 'form' );
 248+ $form[] = Xml::closeElement( 'fieldset' );
 249+ $wgOut->addHTML( implode( "\n", $form ) );
 250+ }
 251+
 252+ protected function printChangeLine( $title, $enabled = true ) {
 253+ global $wgOut;
 254+ if ( $enabled ) {
 255+ $wgOut->addWikiText( '* ' . $title->getPrefixedText() );
 256+ } else {
 257+ $wgOut->addWikiText( '* <s>' . $title->getPrefixedText() . '</s>' );
 258+ }
 259+ }
 260+
 261+ protected function performAction() {
 262+ $jobs = array();
 263+ $target = $this->title;
 264+
 265+ $translationPages = $this->getTranslationPages();
 266+ foreach ( $translationPages as $old ) {
 267+ $jobs[$old->getPrefixedText()] = DeleteJob::newJob( $old, !$this->singleLanguage(), $this->user );
 268+ }
 269+
 270+ $sectionPages = $this->getSectionPages();
 271+ foreach ( $sectionPages as $old ) {
 272+ $to = $this->newPageTitle( $base, $old, $target );
 273+ $jobs[$old->getPrefixedText()] = DeleteJob::newJob( $old, !$this->singleLanguage(), $this->user );
 274+ }
 275+
 276+ if ( !$this->doSubpages ) {
 277+ $subpages = $this->getSubpages();
 278+ foreach ( $subpages as $old ) {
 279+ if ( TranslatablePage::isTranslationPage( $old ) ) {
 280+ continue;
 281+ }
 282+
 283+ $to = $this->newPageTitle( $base, $old, $target );
 284+ $jobs[$old->getPrefixedText()] = DeleteJob::newJob( $old, !$this->singleLanguage(), $this->user );
 285+ }
 286+ }
 287+
 288+ Job::batchInsert( $jobs );
 289+
 290+ global $wgMemc;
 291+ $wgMemc->set( wfMemcKey( 'pt-base', $base ), array_keys( $jobs ), 60 * 60 * 6 );
 292+
 293+
 294+ if ( !$this->singleLanguage() ) {
 295+ $this->page->removeTags();
 296+ }
 297+
 298+ MessageGroups::clearCache();
 299+ // TODO: defer or make faster
 300+ MessageIndexRebuilder::execute();
 301+
 302+ global $wgOut;
 303+ $wgOut->addWikiMsg( 'pt-deletepage-started' );
 304+ }
 305+
 306+ /**
 307+ * Returns all section pages, including those which are currently not active.
 308+ * @return TitleArray.
 309+ */
 310+ protected function getSectionPages() {
 311+ if ( !isset( $this->sectionPages ) ) {
 312+ $base = $this->page->getTitle()->getPrefixedDBKey();
 313+
 314+ $dbw = wfGetDB( DB_MASTER );
 315+ if ( $this->singleLanguage() ) {
 316+ $like = $dbw->buildLike( "$base/", $dbw->anyString(), "/{$this->code}" );
 317+ } else {
 318+ $like = $dbw->buildLike( "$base/", $dbw->anyString() );
 319+ }
 320+
 321+ $fields = array( 'page_namespace', 'page_title' );
 322+ $titleCond = 'page_title ' . $like;
 323+ $conds = array( 'page_namespace' => NS_TRANSLATIONS, $titleCond );
 324+ $result = $dbw->select( 'page', $fields, $conds, __METHOD__ );
 325+ $this->sectionPages = TitleArray::newFromResult( $result );
 326+ }
 327+ return $this->sectionPages;
 328+ }
 329+
 330+ /**
 331+ * Returns only translation subpages.
 332+ * @return Array of titles.
 333+ */
 334+ protected function getTranslationPages() {
 335+ if ( $this->singleLanguage() ) {
 336+ return array( $this->title );
 337+ }
 338+
 339+ if ( !isset( $this->translationPages ) ) {
 340+ $this->translationPages = $this->page->getTranslationPages();
 341+ }
 342+ return $this->translationPages;
 343+ }
 344+
 345+ /**
 346+ * Returns all subpages, if the namespace has them enabled.
 347+ * @return Empty array or TitleArray
 348+ */
 349+ protected function getSubpages() {
 350+ return $this->title->getSubpages();
 351+ }
 352+
 353+ protected function singleLanguage() {
 354+ return $this->code !== '';
 355+ }
 356+}
Property changes on: trunk/extensions/Translate/tag/SpecialPageTranslationDeletePage.php
___________________________________________________________________
Added: svn:eol-style
1357 + native
Index: trunk/extensions/Translate/tag/DeleteJob.php
@@ -0,0 +1,163 @@
 2+<?php
 3+/**
 4+ * Contains class with job for deleting translatable and translation pages.
 5+ *
 6+ * @file
 7+ * @author Niklas Laxström
 8+ * @copyright Copyright © 2008-2011, Niklas Laxström
 9+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
 10+ */
 11+
 12+/**
 13+ * Contains class with job for deleting translatable and translation pages.
 14+ *
 15+ * @ingroup PageTranslation JobQueue
 16+ * @todo Get rid of direct reference to $wgMemc.
 17+ */
 18+class DeleteJob extends Job {
 19+ public static function newJob( Title $target, $full, /*User*/ $performer ) {
 20+ global $wgTranslateFuzzyBotName;
 21+
 22+ $job = new self( $target );
 23+ $job->setUser( $wgTranslateFuzzyBotName );
 24+ $job->setFull( $full );
 25+ $msg = $this->getFull() ? 'pt-deletepage-full-logreason' : 'pt-deletepage-lang-logreason';
 26+ $job->setSummary( wfMsgForContent( 'pt-deletepage-logreason', $target->getPrefixedText() ) );
 27+ $job->setPerformer( $performer );
 28+ $job->lock();
 29+ return $job;
 30+ }
 31+
 32+ function __construct( $title, $params = array(), $id = 0 ) {
 33+ parent::__construct( __CLASS__, $title, $params, $id );
 34+ }
 35+
 36+ function run() {
 37+ global $wgUser;
 38+
 39+ // Initialization
 40+ $title = $this->title;
 41+ // Other stuff
 42+ $user = $this->getUser();
 43+ $summary = $this->getSummary();
 44+ $target = $this->getTarget();
 45+
 46+ PageTranslationHooks::$allowTargetEdit = true;
 47+ $oldUser = $wgUser;
 48+ $wgUser = $user;
 49+
 50+ $error = '';
 51+ $ok = new Article( $title, 0 )->doDeleteArticle( $summary, false, 0, true, $error );
 52+ if ( !$ok ) {
 53+ $logger = new LogPage( 'pagetranslation' );
 54+ $params = array(
 55+ 'user' => $this->getPerformer(),
 56+ 'target' => $target->getPrefixedText(),
 57+ 'error' => base64_encode( serialize( $ok ) ), // This is getting ridiculous
 58+ );
 59+ $doer = User::newFromName( $this->getPerformer() );
 60+ $msg = $this->getFull() ? 'deletefnok' : 'deletelnok';
 61+ $logger->addEntry( $msg, $title, null, array( serialize( $params ) ), $doer );
 62+ }
 63+
 64+ PageTranslationHooks::$allowTargetEdit = false;
 65+
 66+ global $wgMemc;
 67+ $pages = (array) $wgMemc->get( wfMemcKey( 'pt-base', $title->getPrefixedText() ) );
 68+ $last = true;
 69+
 70+ foreach ( $pages as $page ) {
 71+ if ( $wgMemc->get( wfMemcKey( 'pt-lock', $page ) ) === true ) {
 72+ $last = false;
 73+ break;
 74+ }
 75+ }
 76+
 77+ if ( $last ) {
 78+ $wgMemc->delete( wfMemcKey( 'pt-base', $title->getPrefixedText() ) );
 79+ $logger = new LogPage( 'pagetranslation' );
 80+ $params = array( 'user' => $this->getPerformer() );
 81+ $doer = User::newFromName( $this->getPerformer() );
 82+ $msg = $this->getFull() ? 'deletefok' : 'deletelok';
 83+ $logger->addEntry( $msg, $title, null, array( serialize( $params ) ), $doer );
 84+ }
 85+
 86+ $wgUser = $oldUser;
 87+
 88+ return true;
 89+ }
 90+
 91+ public function setSummary( $summary ) {
 92+ $this->params['summary'] = $summary;
 93+ }
 94+
 95+ public function getSummary() {
 96+ return $this->params['summary'];
 97+ }
 98+
 99+ public function setFull( $full ) {
 100+ $this->params['full'] = $full;
 101+ }
 102+
 103+ public function getFull() {
 104+ return $this->params['full'];
 105+ }
 106+
 107+ public function setPerformer( $performer ) {
 108+ if ( is_object( $performer ) ) {
 109+ $this->params['performer'] = $performer->getName();
 110+ } else {
 111+ $this->params['performer'] = $performer;
 112+ }
 113+ }
 114+
 115+ public function getPerformer() {
 116+ return $this->params['performer'];
 117+ }
 118+
 119+ public function setUser( $user ) {
 120+ if ( is_object( $user ) ) {
 121+ $this->params['user'] = $user->getName();
 122+ } else {
 123+ $this->params['user'] = $user;
 124+ }
 125+ }
 126+
 127+ /**
 128+ * Get a user object for doing edits.
 129+ */
 130+ public function getUser() {
 131+ return User::newFromName( $this->params['user'], false );
 132+ }
 133+
 134+ /**
 135+ * Adapted from wfSuppressWarnings to allow not leaving redirects.
 136+ */
 137+ public static function forceRedirects( $end = false ) {
 138+ static $suppressCount = 0;
 139+ static $originalLevel = null;
 140+
 141+ global $wgGroupPermissions;
 142+ global $wgUser;
 143+
 144+ if ( $end ) {
 145+ if ( $suppressCount ) {
 146+ --$suppressCount;
 147+ if ( !$suppressCount ) {
 148+ if ( $originalLevel === null ) {
 149+ unset( $wgGroupPermissions['*']['suppressredirect'] );
 150+ } else {
 151+ $wgGroupPermissions['*']['suppressredirect'] = $originalLevel;
 152+ }
 153+ }
 154+ }
 155+ } else {
 156+ if ( !$suppressCount ) {
 157+ $originalLevel = isset( $wgGroupPermissions['*']['suppressredirect'] ) ? $wgGroupPermissions['*']['suppressredirect'] : null;
 158+ $wgGroupPermissions['*']['suppressredirect'] = true;
 159+ }
 160+ ++$suppressCount;
 161+ }
 162+ $wgUser->clearInstanceCache();
 163+ }
 164+}
Property changes on: trunk/extensions/Translate/tag/DeleteJob.php
___________________________________________________________________
Added: svn:eol-style
1165 + native
Index: trunk/extensions/Translate/tag/PageTranslationHooks.php
@@ -357,7 +357,7 @@
358358 /// Prevent editing of translation pages directly
359359 public static function preventDirectEditing( $title, $user, $action, &$result ) {
360360 $page = TranslatablePage::isTranslationPage( $title );
361 - if ( $page !== false ) {
 361+ if ( $page !== false && $action !== 'delete' ) {
362362 if ( self::$allowTargetEdit ) {
363363 return true;
364364 }
@@ -372,17 +372,19 @@
373373
374374 return false;
375375 }
376 - } elseif ( $action === 'delete' ) {
377 - $page = TranslatablePage::newFromTitle( $title );
378 - if ( $page->getMarkedTag() ) {
379 - $result = array( 'tpt-delete-impossible' );
380 - return false;
381 - }
382376 }
383377
384378 return true;
385379 }
386380
 381+ public static function disableDelete( $article, $wgOut, &$reason ) {
 382+ if ( TranslatablePage::isSourcePage( $article->mTitle ) || TranslatablePage::isTranslationPage( $article->mTitle ) ) {
 383+ $new = SpecialPage::getTitleFor( 'PageTranslationDeletePage', $article->mTitle->getPrefixedText() );
 384+ $wgOut->redirect( $new->getFullUrl() );
 385+ }
 386+ return true;
 387+ }
 388+
387389 public static function schemaUpdates( $updater = null ) {
388390 $dir = dirname( __FILE__ ) . '/..';
389391
@@ -550,6 +552,14 @@
551553 return wfMsgExt( 'pt-log-moveok', $opts, $title->getPrefixedText(), $user );
552554 } elseif ( $action === 'movenok' ) {
553555 return wfMsgExt( 'pt-log-movenok', $opts, $title->getPrefixedText(), $user, $_['target'] );
 556+ } elseif ( $action === 'deletefnok' ) {
 557+ return wfMsgExt( 'pt-log-delete-full-nok', $opts, $title->getPrefixedText(), $user, $_['target'] );
 558+ } elseif ( $action === 'deletelnok' ) {
 559+ return wfMsgExt( 'pt-log-delete-lang-nok', $opts, $title->getPrefixedText(), $user, $_['target'] );
 560+ } elseif ( $action === 'deletelok' ) {
 561+ return wfMsgExt( 'pt-log-delete-full-ok', $opts, $title->getPrefixedText(), $user );
 562+ } elseif ( $action === 'deletefok' ) {
 563+ return wfMsgExt( 'pt-log-delete-lang-ok', $opts, $title->getPrefixedText(), $user );
554564 }
555565 }
556566
Index: trunk/extensions/Translate/Translate.php
@@ -8,7 +8,7 @@
99 *
1010 * @author Niklas Laxström
1111 * @author Siebrand Mazeland
12 - * @copyright Copyright © 2006-2010, Niklas Laxström, Siebrand Mazeland
 12+ * @copyright Copyright © 2006-2011, Niklas Laxström, Siebrand Mazeland
1313 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
1414 */
1515
@@ -541,6 +541,8 @@
542542 global $wgSpecialPages, $wgAvailableRights, $wgSpecialPageGroups;
543543 $wgSpecialPages['PageTranslation'] = 'SpecialPageTranslation';
544544 $wgSpecialPageGroups['PageTranslation'] = 'pagetools';
 545+ $wgSpecialPages['PageTranslationDeletePage'] = 'SpecialPageTranslationDeletePage';
 546+ $wgSpecialPageGroups['PageTranslationDeletePage'] = 'pagetools';
545547 $wgAvailableRights[] = 'pagetranslation';
546548
547549 global $wgLogNames, $wgLogActionsHandlers, $wgLogTypes, $wgLogHeaders;
@@ -621,6 +623,9 @@
622624
623625 // Replace subpage logic behaviour
624626 $wgHooks['SkinSubPageSubtitle'][] = 'PageTranslationHooks::replaceSubtitle';
 627+
 628+ // Disable action=delete
 629+ $wgHooks['ArticleConfirmDelete'][] = 'PageTranslationHooks::disableDelete';
625630 }
626631 }
627632
Index: trunk/extensions/Translate/_autoload.php
@@ -4,7 +4,7 @@
55 *
66 * @file
77 * @author Niklas Laxström
8 - * @copyright Copyright © 2008-2010, Niklas Laxström
 8+ * @copyright Copyright © 2008-2011, Niklas Laxström
99 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
1010 */
1111
@@ -115,7 +115,6 @@
116116
117117 $wgAutoloadClasses['MessageHandle'] = $dir . 'utils/MessageHandle.php';
118118
119 -
120119 /**@}*/
121120
122121 /**
@@ -150,8 +149,10 @@
151150 $wgAutoloadClasses['TPSection'] = $dir . 'tag/TPSection.php';
152151 $wgAutoloadClasses['SpecialPageTranslation'] = $dir . 'tag/SpecialPageTranslation.php';
153152 $wgAutoloadClasses['SpecialPageTranslationMovePage'] = $dir . 'tag/SpecialPageTranslationMovePage.php';
 153+$wgAutoloadClasses['SpecialPageTranslationDeletePage'] = $dir . 'tag/SpecialPageTranslationDeletePage.php';
154154 $wgAutoloadClasses['RenderJob'] = $dir . 'tag/RenderJob.php';
155155 $wgAutoloadClasses['MoveJob'] = $dir . 'tag/MoveJob.php';
 156+$wgAutoloadClasses['DeleteJob'] = $dir . 'tag/MoveJob.php';
156157 /**@}*/
157158
158159 /**
Index: trunk/extensions/Translate/PageTranslation.i18n.php
@@ -77,7 +77,6 @@
7878 This page is a translation of page [[$1]] and the translation can be updated using [$2 the translation tool].',
7979 'tpt-unknown-page' => 'This namespace is reserved for content page translations.
8080 The page you are trying to edit does not seem to correspond any page marked for translation.',
81 - 'tpt-delete-impossible' => 'Deleting pages marked for translation is not yet possible.',
8281
8382 'tpt-install' => 'Run php maintenance/update.php or web install to enable page translation feature.',
8483
@@ -104,6 +103,10 @@
105104 'pt-log-unmark' => '{{GENDER:$2|removed}} page "[[:$1]]" from translation',
106105 'pt-log-moveok' => '{{GENDER:$2|completed}} renaming of translatable page $1 to a new name',
107106 'pt-log-movenok' => '{{GENDER:$2|encountered}} a problem while moving [[:$1]] to [[:$3]]',
 107+ 'pt-log-delete-full-ok' => '{{GENDER:$2|completed}} deletion of translatable page $1',
 108+ 'pt-log-delete-full-nok' => '{{GENDER:$2|encountered}} a problem while deleting translatable page [[:$1]]',
 109+ 'pt-log-delete-lang-ok' => '{{GENDER:$2|completed}} deletion of translation page $e',
 110+ 'pt-log-delete-lang-nok' => '{{GENDER:$2|encountered}} a problem while deleting translation page [[:$1]]',
108111
109112
110113 # move page replacement
@@ -144,6 +147,39 @@
145148 Please check the [[Special:Log/pagetranslation|page translation log]] for errors and completion message.',
146149
147150 'pt-locked-page' => 'This page is locked because the translatable page is currently being moved.',
 151+
 152+
 153+ 'pt-deletepage-lang-title' => 'Deleting translation page $1.',
 154+ 'pt-deletepage-full-title' => 'Deleting translatable page $1.',
 155+
 156+ 'pt-deletepage-invalid-title' => 'The specified page is not valid.',
 157+ 'pt-deletepage-invalid-text' => 'The specified page is not a translatable page nor translation of it.',
 158+
 159+ 'pt-deletepage-action-check' => 'List pages to be deleted',
 160+ 'pt-deletepage-action-perform' => 'Do the deletion',
 161+ 'pt-deletepage-action-other' => 'Change target',
 162+
 163+ 'pt-deletepage-lang-legend' => 'Delete translation page',
 164+ 'pt-deletepage-full-legend' => 'Delete translatable page',
 165+ 'pt-deletepage-any-legend' => 'Delete translatable page or translation of translatable page',
 166+ 'pt-deletepage-current' => 'Page name:',
 167+ 'pt-deletepage-reason' => 'Reason:',
 168+ 'pt-deletepage-subpages' => 'Delete all subpages',
 169+
 170+ 'pt-deletepage-list-pages' => 'List of pages to delete',
 171+ 'pt-deletepage-list-translation' => 'Translation pages',
 172+ 'pt-deletepage-list-section' => 'Section pages',
 173+ 'pt-deletepage-list-other' => 'Other subpages',
 174+ 'pt-deletepage-list-count' => 'In total $1 {{PLURAL:$1|page|pages}} to delete.',
 175+
 176+ 'pt-deletepage-full-logreason' => 'Part of translatable page $1.',
 177+ 'pt-deletepage-lang-logreason' => 'Part of translation page $1.',
 178+ 'pt-deletepage-started' => 'Please check the [[Special:Log/pagetranslation|page translation log]] for errors and completion message.',
 179+
 180+ 'pt-deletepage-intro' => 'This special page allows you delete whole translatable pages or translations into one language.
 181+The delete action will not be instant, because many pages will need to be deleted.
 182+Failures will be logged in the [[Special:Log/pagetranslation|page translation log]] and they need to be repaired by hand.',
 183+
148184 );
149185
150186 /** Message documentation (Message documentation)
Index: trunk/extensions/Translate/Translate.alias.php
@@ -22,6 +22,7 @@
2323 'FirstSteps' => array( 'FirstSteps' ),
2424 'SupportedLanguages' => array( 'SupportedLanguages' ),
2525 'MyLanguage' => array( 'MyLanguage' ),
 26+ 'PageTranslationDeletePage' => array( 'PageTranslationDeletePage' ),
2627 );
2728
2829 /** Afrikaans (Afrikaans) */

Status & tagging log