* Changed action=revert to use a subclass of Action
authorAlexandre Emsenhuber <ialex@users.mediawiki.org>
Fri, 1 Jul 2011 20:07:21 +0000 (20:07 +0000)
committerAlexandre Emsenhuber <ialex@users.mediawiki.org>
Fri, 1 Jul 2011 20:07:21 +0000 (20:07 +0000)
* Added WikiPage::getActionOverrides() to be able to execute different actions depending on the namespace (obviously needed for action=revert). This is only used when the value of $wgActions for the corresponding action is true; so extension can still override this.
* Added Action::getDescription() to ease the change of the page header and the <title> element

includes/Action.php
includes/Article.php
includes/AutoLoader.php
includes/DefaultSettings.php
includes/FileRevertForm.php [deleted file]
includes/ImagePage.php
includes/Wiki.php
includes/WikiFilePage.php
includes/WikiPage.php
includes/actions/RevertAction.php [new file with mode: 0644]

index dcdd4b3..ff0ce69 100644 (file)
@@ -47,9 +47,10 @@ abstract class Action {
         * Get the Action subclass which should be used to handle this action, false if
         * the action is disabled, or null if it's not recognised
         * @param $action String
+        * @param $overrides Array
         * @return bool|null|string
         */
-       private final static function getClass( $action ) {
+       private final static function getClass( $action, array $overrides ) {
                global $wgActions;
                $action = strtolower( $action );
 
@@ -59,6 +60,8 @@ abstract class Action {
 
                if ( $wgActions[$action] === false ) {
                        return false;
+               } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
+                       return $overrides[$action];
                } elseif ( $wgActions[$action] === true ) {
                        return ucfirst( $action ) . 'Action';
                } else {
@@ -74,7 +77,7 @@ abstract class Action {
         *     if it is not recognised
         */
        public final static function factory( $action, Page $page ) {
-               $class = self::getClass( $action );
+               $class = self::getClass( $action, $page->getActionOverrides() );
                if ( $class ) {
                        $obj = new $class( $page );
                        return $obj;
@@ -223,7 +226,7 @@ abstract class Action {
        protected function setHeaders() {
                $out = $this->getOutput();
                $out->setRobotPolicy( "noindex,nofollow" );
-               $out->setPageTitle( $this->getTitle()->getPrefixedText() );
+               $out->setPageTitle( $this->getPageTitle() );
                $this->getOutput()->setSubtitle( $this->getDescription() );
                $out->setArticleRelated( true );
        }
@@ -233,6 +236,15 @@ abstract class Action {
         *
         * @return String
         */
+       protected function getPageTitle() {
+               return $this->getTitle()->getPrefixedText();
+       }
+
+       /**
+        * Returns the description that goes below the \<h1\> tag
+        *
+        * @return String
+        */
        protected function getDescription() {
                return wfMsg( strtolower( $this->getName() ) );
        }
index 5340935..76d419e 100644 (file)
@@ -1232,6 +1232,14 @@ class Article extends Page {
                Action::factory( 'info', $this )->show();
        }
 
+       /**
+        * Overriden by ImagePage class, only present here to avoid a fatal error
+        * Called for ?action=revert
+        */
+       public function revert() {
+               Action::factory( 'revert', $this )->show();
+       }
+
        /**
         * Output a redirect back to the article.
         * This is typically used after an edit.
@@ -1905,15 +1913,6 @@ class Article extends Page {
 
        /**#@-*/
 
-       /**
-        * Overriden by ImagePage class, only present here to avoid a fatal error
-        * Called for ?action=revert
-        */
-       public function revert() {
-               global $wgOut;
-               $wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
-       }
-
        /**
         * Add the primary page-view wikitext to the output buffer
         * Saves the text into the parser cache if possible.
index b24fa40..c493484 100644 (file)
@@ -83,7 +83,6 @@ $wgAutoloadLocalClasses = array(
        'FeedItem' => 'includes/Feed.php',
        'FeedUtils' => 'includes/FeedUtils.php',
        'FileDeleteForm' => 'includes/FileDeleteForm.php',
-       'FileRevertForm' => 'includes/FileRevertForm.php',
        'ForkController' => 'includes/ForkController.php',
        'FormlessAction' => 'includes/Action.php',
        'FormAction' => 'includes/Action.php',
@@ -259,6 +258,8 @@ $wgAutoloadLocalClasses = array(
        'InfoAction' => 'includes/actions/InfoAction.php',
        'MarkpatrolledAction' => 'includes/actions/MarkpatrolledAction.php',
        'PurgeAction' => 'includes/actions/PurgeAction.php',
+       'RevertAction' => 'includes/actions/RevertAction.php',
+       'RevertFileAction' => 'includes/actions/RevertAction.php',
        'RevisiondeleteAction' => 'includes/actions/RevisiondeleteAction.php',
        'UnwatchAction' => 'includes/actions/WatchAction.php',
        'WatchAction' => 'includes/actions/WatchAction.php',
index debae38..35d1d01 100644 (file)
@@ -5049,6 +5049,9 @@ $wgMaxRedirectLinksRetrieved = 500;
  * Array of allowed values for the title=foo&action=<action> parameter. Syntax is:
  *     'foo' => 'ClassName'    Load the specified class which subclasses Action
  *     'foo' => true           Load the class FooAction which subclasses Action
+ *                             If something is specified in the getActionOverrides()
+ *                             of the relevant Page object it will be used
+ *                             instead of the default class.
  *     'foo' => false          The action is disabled; show an error message
  * Unsetting core actions will probably cause things to complain loudly.
  */
@@ -5058,6 +5061,7 @@ $wgActions = array(
        'info' => true,
        'markpatrolled' => true,
        'purge' => true,
+       'revert' => true,
        'revisiondelete' => true,
        'unwatch' => true,
        'watch' => true,
diff --git a/includes/FileRevertForm.php b/includes/FileRevertForm.php
deleted file mode 100644 (file)
index 47084aa..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-<?php
-
-/**
- * File reversion user interface
- *
- * @ingroup Media
- * @author Rob Church <robchur@gmail.com>
- */
-class FileRevertForm {
-
-       protected $title = null;
-       protected $file = null;
-       protected $archiveName = '';
-       protected $timestamp = false;
-       protected $oldFile;
-
-       /**
-        * Constructor
-        *
-        * @param $file File we're reverting
-        */
-       public function __construct( $file ) {
-               $this->title = $file->getTitle();
-               $this->file = $file;
-       }
-
-       /**
-        * Fulfil the request; shows the form or reverts the file,
-        * pending authentication, confirmation, etc.
-        */
-       public function execute() {
-               global $wgOut, $wgRequest, $wgUser, $wgLang;
-               $this->setHeaders();
-
-               if( wfReadOnly() ) {
-                       $wgOut->readOnlyPage();
-                       return;
-               } elseif( !$wgUser->isLoggedIn() ) {
-                       $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' );
-                       return;
-               } elseif( !$this->title->userCan( 'edit' ) || !$this->title->userCan( 'upload' ) ) {
-                       // The standard read-only thing doesn't make a whole lot of sense
-                       // here; surely it should show the image or something? -- RC
-                       $article = new Article( $this->title );
-                       $wgOut->readOnlyPage( $article->getContent(), true );
-                       return;
-               } elseif( $wgUser->isBlocked() ) {
-                       $wgOut->blockedPage();
-                       return;
-               }
-
-               $this->archiveName = $wgRequest->getText( 'oldimage' );
-               $token = $wgRequest->getText( 'wpEditToken' );
-               if( !$this->isValidOldSpec() ) {
-                       $wgOut->showUnexpectedValueError( 'oldimage', htmlspecialchars( $this->archiveName ) );
-                       return;
-               }
-
-               if( !$this->haveOldVersion() ) {
-                       $wgOut->addHTML( wfMsgExt( 'filerevert-badversion', 'parse' ) );
-                       $wgOut->returnToMain( false, $this->title );
-                       return;
-               }
-
-               // Perform the reversion if appropriate
-               if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $token, $this->archiveName ) ) {
-                       $source = $this->file->getArchiveVirtualUrl( $this->archiveName );
-                       $comment = $wgRequest->getText( 'wpComment' );
-                       // TODO: Preserve file properties from database instead of reloading from file
-                       $status = $this->file->upload( $source, $comment, $comment );
-                       if( $status->isGood() ) {
-                               $wgOut->addHTML( wfMsgExt( 'filerevert-success', 'parse', $this->title->getText(),
-                                       $wgLang->date( $this->getTimestamp(), true ),
-                                       $wgLang->time( $this->getTimestamp(), true ),
-                                       wfExpandUrl( $this->file->getArchiveUrl( $this->archiveName ) ) ) );
-                               $wgOut->returnToMain( false, $this->title );
-                       } else {
-                               $wgOut->addWikiText( $status->getWikiText() );
-                       }
-                       return;
-               }
-
-               // Show the form
-               $this->showForm();
-       }
-
-       /**
-        * Show the confirmation form
-        */
-       protected function showForm() {
-               global $wgOut, $wgUser, $wgLang, $wgContLang;
-               $timestamp = $this->getTimestamp();
-
-               $form  = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getAction() ) );
-               $form .= Html::hidden( 'wpEditToken', $wgUser->editToken( $this->archiveName ) );
-               $form .= '<fieldset><legend>' . wfMsgHtml( 'filerevert-legend' ) . '</legend>';
-               $form .= wfMsgExt( 'filerevert-intro', 'parse', $this->title->getText(),
-                       $wgLang->date( $timestamp, true ), $wgLang->time( $timestamp, true ),
-                       wfExpandUrl( $this->file->getArchiveUrl( $this->archiveName ) ) );
-               $form .= '<p>' . Xml::inputLabel( wfMsg( 'filerevert-comment' ), 'wpComment', 'wpComment',
-                       60, wfMsgForContent( 'filerevert-defaultcomment',
-                       $wgContLang->date( $timestamp, false, false ), $wgContLang->time( $timestamp, false, false ) ) ) . '</p>';
-               $form .= '<p>' . Xml::submitButton( wfMsg( 'filerevert-submit' ) ) . '</p>';
-               $form .= '</fieldset>';
-               $form .= '</form>';
-
-               $wgOut->addHTML( $form );
-       }
-
-       /**
-        * Set headers, titles and other bits
-        */
-       protected function setHeaders() {
-               global $wgOut, $wgUser;
-               $wgOut->setPageTitle( wfMsg( 'filerevert', $this->title->getText() ) );
-               $wgOut->setRobotPolicy( 'noindex,nofollow' );
-               $wgOut->setSubtitle( wfMsg(
-                       'filerevert-backlink',
-                       $wgUser->getSkin()->link(
-                               $this->title,
-                               null,
-                               array(),
-                               array(),
-                               array( 'known', 'noclasses' )
-                       )
-               ) );
-       }
-
-       /**
-        * Is the provided `oldimage` value valid?
-        *
-        * @return bool
-        */
-       protected function isValidOldSpec() {
-               return strlen( $this->archiveName ) >= 16
-                       && strpos( $this->archiveName, '/' ) === false
-                       && strpos( $this->archiveName, '\\' ) === false;
-       }
-
-       /**
-        * Does the provided `oldimage` value correspond
-        * to an existing, local, old version of this file?
-        *
-        * @return bool
-        */
-       protected function haveOldVersion() {
-               return $this->getOldFile()->exists();
-       }
-
-       /**
-        * Prepare the form action
-        *
-        * @return string
-        */
-       protected function getAction() {
-               $q = array();
-               $q[] = 'action=revert';
-               $q[] = 'oldimage=' . urlencode( $this->archiveName );
-               return $this->title->getLocalUrl( implode( '&', $q ) );
-       }
-
-       /**
-        * Extract the timestamp of the old version
-        *
-        * @return string
-        */
-       protected function getTimestamp() {
-               if( $this->timestamp === false ) {
-                       $this->timestamp = $this->getOldFile()->getTimestamp();
-               }
-               return $this->timestamp;
-       }
-
-       protected function getOldFile() {
-               if ( !isset( $this->oldFile ) ) {
-                       $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->title, $this->archiveName );
-               }
-               return $this->oldFile;
-       }
-}
index ebbe36c..ce1cbdd 100644 (file)
@@ -786,15 +786,6 @@ EOT
                $deleter->execute();
        }
 
-       /**
-        * Revert the file to an earlier version
-        */
-       public function revert() {
-               $this->loadFile();
-               $reverter = new FileRevertForm( $this->mPage->getFile() );
-               $reverter->execute();
-       }
-
        /**
         * Override handling of action=purge
         */
index f6d0546..251d1db 100644 (file)
@@ -464,7 +464,6 @@ class MediaWiki {
                                wfProfileOut( __METHOD__ . '-raw' );
                                break;
                        case 'delete':
-                       case 'revert':
                        case 'rollback':
                        case 'protect':
                        case 'unprotect':
index e4ad0e2..6727a8c 100644 (file)
@@ -16,6 +16,10 @@ class WikiFilePage extends WikiPage {
                $this->mRepo = null;
        }
 
+       public function getActionOverrides() {
+               return array( 'revert' => 'RevertFileAction' );
+       }
+
        /**
         * @param $file File:
         * @return void
index eb99928..656bce8 100644 (file)
@@ -61,6 +61,18 @@ class WikiPage extends Page {
                # return $t == null ? null : new static( $t ); // PHP 5.3
        }
 
+       /**
+        * Returns overrides for action handlers.
+        * Classes listed here will be used instead of the default one when
+        * (and only when) $wgActions[$action] === true. This allows subclasses
+        * to override the default behavior.
+        *
+        * @return Array
+        */
+       public function getActionOverrides() {
+               return array();
+       }
+
        /**
         * If this page is a redirect, get its target
         *
diff --git a/includes/actions/RevertAction.php b/includes/actions/RevertAction.php
new file mode 100644 (file)
index 0000000..815606d
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/**
+ * File reversion user interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * @file
+ * @ingroup Action
+ * @ingroup Media
+ * @author Alexandre Emsenhuber
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+/**
+ * Dummy class for pages not in NS_FILE
+ *
+ * @ingroup Action
+ */
+class RevertAction extends Action {
+
+       public function getName() {
+               return 'revert';
+       }
+
+       public function getRestriction() {
+               return 'read';
+       }
+
+       public function show() {
+               $this->getOutput()->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
+       }
+
+       public function execute() {}
+}
+
+/**
+ * Class for pages in NS_FILE
+ *
+ * @ingroup Action
+ */
+class RevertFileAction extends FormAction {
+       protected $oldFile;
+
+       public function getName() {
+               return 'revert';
+       }
+
+       public function getRestriction() {
+               return 'upload';
+       }
+
+       protected function checkCanExecute( User $user ) {
+               parent::checkCanExecute( $user );
+
+               $oldimage = $this->getRequest()->getText( 'oldimage' );
+               if ( strlen( $oldimage ) < 16
+                       || strpos( $oldimage, '/' ) !== false
+                       || strpos( $oldimage, '\\' ) !== false )
+               {
+                       throw new ErrorPageError( 'internalerror', 'unexpected', array( 'oldimage', $oldimage ) );
+               }
+
+               $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->getTitle(), $oldimage );
+               if ( !$this->oldFile->exists() ) {
+                       throw new ErrorPageError( '', 'filerevert-badversion' );
+               }
+       }
+
+       protected function alterForm( HTMLForm $form ) {
+               $form->setWrapperLegend( wfMsgHtml( 'filerevert-legend' ) );
+               $form->setSubmitText( wfMsg( 'filerevert-submit' ) );
+               $form->addHiddenField( 'oldimage', $this->getRequest()->getText( 'oldimage' ) );
+       }
+
+       protected function getFormFields() {
+               global $wgContLang;
+
+               $timestamp = $this->oldFile->getTimestamp();
+
+               return array(
+                       'intro' => array(
+                               'type' => 'info',
+                               'vertical-label' => true,
+                               'raw' => true,
+                               'default' => wfMsgExt( 'filerevert-intro', 'parse', $this->getTitle()->getText(),
+                                       $this->getLang()->date( $timestamp, true ), $this->getLang()->time( $timestamp, true ),
+                                       wfExpandUrl( $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ) ) )
+                       ),
+                       'comment' => array(
+                               'type' => 'text',
+                               'label-message' => 'filerevert-comment',
+                               'default' => wfMsgForContent( 'filerevert-defaultcomment',
+                                       $wgContLang->date( $timestamp, false, false ), $wgContLang->time( $timestamp, false, false ) ),
+                       )
+               );
+       }
+
+       public function onSubmit( $data ) {
+               $source = $this->page->getFile()->getArchiveVirtualUrl( $this->getRequest()->getText( 'oldimage' ) );
+               $comment = $data['comment'];
+               // TODO: Preserve file properties from database instead of reloading from file
+               return $this->page->getFile()->upload( $source, $comment, $comment );
+       }
+
+       public function onSuccess() {
+               $timestamp = $this->oldFile->getTimestamp();
+               $this->getOutput()->addHTML( wfMsgExt( 'filerevert-success', 'parse', $this->getTitle()->getText(),
+                       $this->getLang()->date( $timestamp, true ),
+                       $this->getLang()->time( $timestamp, true ),
+                       wfExpandUrl( $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ) ) ) );
+               $this->getOutput()->returnToMain( false, $this->getTitle() );
+       }
+
+       protected function getPageTitle() {
+               return wfMsg( 'filerevert', $this->getTitle()->getText() );
+       }
+       
+       protected function getDescription() {
+               return wfMsg(
+                       'filerevert-backlink',
+                       Linker::linkKnown( $this->getTitle() )
+               );
+       }
+}