Revert r86001: Brion says it's too scary :D will recommit in pieces
authorHappy-melon <happy-melon@users.mediawiki.org>
Wed, 13 Apr 2011 23:36:27 +0000 (23:36 +0000)
committerHappy-melon <happy-melon@users.mediawiki.org>
Wed, 13 Apr 2011 23:36:27 +0000 (23:36 +0000)
19 files changed:
docs/hooks.txt
includes/Action.php [deleted file]
includes/Article.php
includes/AutoLoader.php
includes/Credits.php [new file with mode: 0644]
includes/DefaultSettings.php
includes/EditPage.php
includes/FileDeleteForm.php
includes/ProtectionForm.php
includes/Setup.php
includes/Wiki.php
includes/actions/CreditsAction.php [deleted file]
includes/actions/DeleteAction.php [deleted file]
includes/actions/WatchAction.php [deleted file]
includes/api/ApiBase.php
includes/api/ApiDelete.php
includes/api/ApiWatch.php
includes/specials/SpecialMovepage.php
languages/messages/MessagesEn.php

index 1fe061c..9935299 100644 (file)
@@ -264,17 +264,6 @@ $reason: the reason for the move (added in 1.13)
 $user: the User object about to be created (read-only, incomplete)
 $message: out parameter: error message to display on abort
 
-'ActionBeforeFormDisplay': Modify the form shown for an action (added 1.18)
-$action: String
-$form: HTMLForm
-$page: Article
-
-'ActionModifyFormFields': Modify the descriptor array which will be used to create an
-action form
-$action: String
-$fields: Array
-$page: Article
-
 'AddNewAccount': after a user account is created
 $user: the User object that was created. (Parameter added in 1.7)
 $byEmail: true when account was created "by email" (added in 1.12)
@@ -395,6 +384,12 @@ the database
 $article: the article (object) being loaded from the database
 $content: the content (string) of the article
 
+'ArticleConfirmDelete': before writing the confirmation form for article
+       deletion
+$article: the article (object) being deleted
+$output: the OutputPage object ($wgOut)
+&$reason: the reason (string) the article is being deleted
+
 'ArticleContentOnDiff': before showing the article content below a diff.
 Use this to change the content in this area or how it is loaded.
  $diffEngine: the DifferenceEngine
diff --git a/includes/Action.php b/includes/Action.php
deleted file mode 100644 (file)
index 44fafca..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-<?php
-/**
- * Actions are things which can be done to pages (edit, delete, rollback, etc).  They
- * are distinct from Special Pages because an action must apply to exactly one page.
- *
- * To add an action in an extension, create a subclass of Action, and add the key to
- * $wgActions.  There is also the deprecated UnknownAction hook
- *
- *
- * 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
- */
-abstract class Action {
-
-       // Page on which we're performing the action
-       // @var Article
-       protected $page;
-
-       // RequestContext if specified; otherwise we'll use the Context from the Page
-       // @var RequestContext
-       protected $context;
-
-       // The fields used to create the HTMLForm
-       // @var Array
-       protected $fields;
-
-       /**
-        * 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
-        * @return bool|null|string
-        */
-       private final static function getClass( $action ){
-               global $wgActions;
-               $action = strtolower( $action );
-
-               if( !isset( $wgActions[$action] ) ){
-                       return null;
-               }
-
-               if( $wgActions[$action] === false ){
-                       return false;
-               }
-
-               elseif( $wgActions[$action] === true ){
-                       return ucfirst( $action ) . 'Action';
-               }
-
-               else {
-                       return $wgActions[$action];
-               }
-       }
-
-       /**
-        * Get an appropriate Action subclass for the given action
-        * @param $action String
-        * @param $page Article
-        * @return Action|false|null false if the action is disabled, null
-        *     if it is not recognised
-        */
-       public final static function factory( $action, Article $page ){
-               $class = self::getClass( $action );
-               if( $class ){
-                       $obj = new $class( $page );
-                       return $obj;
-               }
-               return null;
-       }
-
-       /**
-        * Check if a given action is recognised, even if it's disabled
-        *
-        * @param $name String: name of an action
-        * @return Bool
-        */
-       public final static function exists( $name ) {
-               return self::getClass( $name ) !== null;
-       }
-
-       /**
-        * Get the RequestContext in use here
-        * @return RequestContext
-        */
-       protected final function getContext(){
-               if( $this->context instanceof RequestContext ){
-                       return $this->context;
-               }
-               return $this->page->getContext();
-       }
-
-       /**
-        * Get the WebRequest being used for this instance
-        *
-        * @return WebRequest
-        */
-       protected final function getRequest() {
-               return $this->getContext()->request;
-       }
-
-       /**
-        * Get the OutputPage being used for this instance
-        *
-        * @return OutputPage
-        */
-       protected final function getOutput() {
-               return $this->getContext()->output;
-       }
-
-       /**
-        * Shortcut to get the skin being used for this instance
-        *
-        * @return User
-        */
-       protected final function getUser() {
-               return $this->getContext()->user;
-       }
-
-       /**
-        * Shortcut to get the skin being used for this instance
-        *
-        * @return Skin
-        */
-       protected final function getSkin() {
-               return $this->getContext()->skin;
-       }
-
-       /**
-        * Shortcut to get the Title object from the page
-        * @return Title
-        */
-       protected final function getTitle(){
-               return $this->page->getTitle();
-       }
-
-       /**
-        * Protected constructor: use Action::factory( $action, $page ) to actually build
-        * these things in the real world
-        * @param Article $page
-        */
-       protected function __construct( Article $page ){
-               $this->page = $page;
-       }
-
-       /**
-        * Return the name of the action this object responds to
-        * @return String lowercase
-        */
-       public abstract function getName();
-
-       /**
-        * Get the permission required to perform this action.  Often, but not always,
-        * the same as the action name
-        */
-       public abstract function getRestriction();
-
-       /**
-        * Checks if the given user (identified by an object) can perform this action.  Can be
-        * overridden by sub-classes with more complicated permissions schemes.  Failures here
-        * must throw subclasses of ErrorPageError
-        *
-        * @param $user User: the user to check, or null to use the context user
-        * @throws ErrorPageError
-        */
-       protected function checkCanExecute( User $user ) {
-               if( $this->requiresWrite() && wfReadOnly() ){
-                       throw new ReadOnlyError();
-               }
-
-               if( $this->getRestriction() !== null && !$user->isAllowed( $this->getRestriction() ) ){
-                       throw new PermissionsError( $this->getRestriction() );
-               }
-
-               if( $this->requiresUnblock() && $user->isBlocked() ){
-                       $block = $user->mBlock;
-                       throw new UserBlockedError( $block );
-               }
-       }
-
-       /**
-        * Whether this action requires the wiki not to be locked
-        * @return Bool
-        */
-       public function requiresWrite(){
-               return true;
-       }
-
-       /**
-        * Whether this action can still be executed by a blocked user
-        * @return Bool
-        */
-       public function requiresUnblock(){
-               return true;
-       }
-
-       /**
-        * Set output headers for noindexing etc.  This function will not be called through
-        * the execute() entry point, so only put UI-related stuff in here.
-        */
-       protected function setHeaders() {
-               $out = $this->getOutput();
-               $out->setRobotPolicy( "noindex,nofollow" );
-               $out->setPageTitle( $this->getTitle()->getPrefixedText() );
-               $this->getOutput()->setSubtitle( $this->getDescription() );
-               $out->setArticleRelated( true );
-       }
-
-       /**
-        * Returns the name that goes in the \<h1\> page title
-        *
-        * Derived classes can override this, but usually it is easier to keep the
-        * default behaviour. Messages can be added at run-time, see
-        * MessageCache.php.
-        *
-        * @return String
-        */
-       protected function getDescription() {
-               return wfMsg( strtolower( $this->getName() ) );
-       }
-
-       /**
-        * The basic pattern for actions is to display some sort of HTMLForm UI, maybe with
-        * some stuff underneath (history etc); to do some processing on submission of that
-        * form (delete, protect, etc) and to do something exciting on 'success', be that
-        * display something new or redirect to somewhere.  Some actions have more exotic
-        * behaviour, but that's what subclassing is for :D
-        */
-       public function show(){
-               $this->setHeaders();
-
-               // This will throw exceptions if there's a problem
-               $this->checkCanExecute( $this->getUser() );
-
-               $form = $this->getForm();
-               if( $form instanceof HTMLForm ){
-                       if( $form->show() ){
-                               $this->onSuccess();
-                       }
-               } else {
-                       // You're using the wrong type of Action
-                       throw new MWException( "Action::getFormFields() must produce a form.  Use GetAction if you don't want one." );
-               }
-       }
-
-       /**
-        * Execute the action in a silent fashion: do not display anything or release any errors.
-        * @param $data Array values that would normally be in the POST request
-        * @param $captureErrors Bool whether to catch exceptions and just return false
-        * @return Bool whether execution was successful
-        */
-       public function execute( array $data = null, $captureErrors = true ){
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->page->getContext();
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $form = $this->getForm();
-                       if( $form instanceof HTMLForm ){
-                               // Great, so there's a form.  Ignore it and go straight to the submission callback
-                               $fields = array();
-                               foreach( $this->fields as $key => $params ){
-                                       if( isset( $data[$key] ) ){
-                                               $fields[$key] = $data[$key];
-                                       } elseif( isset( $params['default'] ) ) {
-                                               $fields[$key] = $params['default'];
-                                       } else {
-                                               $fields[$key] = null;
-                                       }
-                               }
-                               $status = $this->onSubmit( $fields );
-                               if( $status === true ){
-                                       // This might do permanent stuff
-                                       $this->onSuccess();
-                                       return true;
-                               } else {
-                                       return false;
-                               }
-                       } else {
-                               // You're using the wrong type of Action
-                               throw new MWException( "Action::getFormFields() must produce a form.  Use GetAction if you don't want one." );
-                       }
-               }
-               catch ( ErrorPageError $e ){
-                       if( $captureErrors ){
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
-
-       /**
-        * Get an HTMLForm descriptor array, or false if you don't want a form
-        * @return Array
-        */
-       protected abstract function getFormFields();
-
-       /**
-        * Add pre- or post-text to the form
-        * @return String
-        */
-       protected function preText(){ return ''; }
-       protected function postText(){ return ''; }
-
-       /**
-        * Play with the HTMLForm if you need to more substantially
-        * @param &$form HTMLForm
-        */
-       protected function alterForm( HTMLForm &$form ){}
-
-       /**
-        * Get the HTMLForm to control behaviour
-        * @return HTMLForm|null
-        */
-       protected function getForm(){
-               $this->fields = $this->getFormFields();
-
-               // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) );
-
-               if( $this->fields === false ){
-                       return null;
-               }
-
-               $form = new HTMLForm( $this->fields, $this->getContext() );
-               $form->setSubmitCallback( array( $this, 'onSubmit' ) );
-               $form->addHiddenField( 'action', $this->getName() );
-
-               $form->addPreText( $this->preText() );
-               $form->addPostText( $this->postText() );
-               $this->alterForm( $form );
-
-               // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) );
-
-               return $form;
-       }
-
-       /**
-        * Process the form on POST submission.  If you return false from getFormFields(),
-        * this will obviously never be reached.  If you don't want to do anything with the
-        * form, just return false here
-        * @param  $data Array
-        * @return Bool|Array true for success, false for didn't-try, array of errors on failure
-        */
-       public abstract function onSubmit( $data );
-
-       /**
-        * Do something exciting on successful processing of the form.  This might be to show
-        * a confirmation message (watch, rollback, etc) or to redirect somewhere else (edit,
-        * protect, etc).
-        */
-       public abstract function onSuccess();
-
-}
-
-/**
- * Actions generally fall into two groups: the show-a-form-then-do-something-with-the-input
- * format (protect, delete, move, etc), and the just-do-something format (watch, rollback,
- * patrol, etc).
- */
-abstract class FormlessAction extends Action {
-
-       /**
-        * Show something on GET request. This is displayed as the postText() of the HTMLForm
-        * if there is one; you can always use alterForm() to add pre text if you need it.  If
-        * you call addPostText() from alterForm() as well as overriding this function, you
-        * might get strange ordering.
-        * @return String|null will be added to the HTMLForm if present, or just added to the
-        *     output if not.  Return null to not add anything
-        */
-       public abstract function onView();
-
-       /**
-        * We don't want an HTMLForm
-        */
-       protected function getFormFields(){
-               return false;
-       }
-
-       public function onSubmit( $data ){
-               return false;
-       }
-
-       public function onSuccess(){
-               return false;
-       }
-
-       public function show(){
-               $this->setHeaders();
-
-               // This will throw exceptions if there's a problem
-               $this->checkCanExecute( $this->getUser() );
-               $this->getOutput()->addHTML( $this->onView() );
-       }
-
-       /**
-        * Execute the action silently, not giving any output.  Since these actions don't have
-        * forms, they probably won't have any data, but some (eg rollback) may do
-        * @param $data Array values that would normally be in the GET request
-        * @param $captureErrors Bool whether to catch exceptions and just return false
-        * @return Bool whether execution was successful
-        */
-       public function execute( array $data = null, $captureErrors = true){
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->page->getContext();
-                       if( is_array( $data ) ){
-                               $this->context->setRequest( new FauxRequest( $data, false ) );
-                       }
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $this->onView();
-                       return true;
-               }
-               catch ( ErrorPageError $e ){
-                       if( $captureErrors ){
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
-}
\ No newline at end of file
index 97eb17b..b9288c2 100644 (file)
@@ -2345,10 +2345,27 @@ class Article {
 
        /**
         * User-interface handler for the "watch" action
-        * @deprecated since 1.18
         */
        public function watch() {
-               Action::factory( 'watch', $this )->show();
+               global $wgOut;
+
+               if ( $wgOut->getUser()->isAnon() ) {
+                       $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
+                       return;
+               }
+
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               if ( $this->doWatch() ) {
+                       $wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
+                       $wgOut->setRobotPolicy( 'noindex,nofollow' );
+                       $wgOut->addWikiMsg( 'addedwatchtext', $this->mTitle->getPrefixedText() );
+               }
+
+               $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
        }
 
        /**
@@ -2357,27 +2374,64 @@ class Article {
         * This is safe to be called multiple times
         *
         * @return bool true on successful watch operation
-        * @deprecated since 1.18
         */
        public function doWatch() {
-               return Action::factory( 'watch', $this )->execute();
+               global $wgUser;
+
+               if ( $wgUser->isAnon() ) {
+                       return false;
+               }
+
+               if ( wfRunHooks( 'WatchArticle', array( &$wgUser, &$this ) ) ) {
+                       $wgUser->addWatch( $this->mTitle );
+                       return wfRunHooks( 'WatchArticleComplete', array( &$wgUser, &$this ) );
+               }
+
+               return false;
        }
 
        /**
         * User interface handler for the "unwatch" action.
-        * @deprecated since 1.18
         */
        public function unwatch() {
-               Action::factory( 'unwatch', $this )->show();
+               global $wgOut;
+
+               if ( $wgOut->getUser()->isAnon() ) {
+                       $wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
+                       return;
+               }
+
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               if ( $this->doUnwatch() ) {
+                       $wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
+                       $wgOut->setRobotPolicy( 'noindex,nofollow' );
+                       $wgOut->addWikiMsg( 'removedwatchtext', $this->mTitle->getPrefixedText() );
+               }
+
+               $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
        }
 
        /**
         * Stop watching a page
         * @return bool true on successful unwatch
-        * @deprecated since 1.18
         */
        public function doUnwatch() {
-               return Action::factory( 'unwatch', $this )->execute();
+               global $wgUser;
+
+               if ( $wgUser->isAnon() ) {
+                       return false;
+               }
+
+               if ( wfRunHooks( 'UnwatchArticle', array( &$wgUser, &$this ) ) ) {
+                       $wgUser->removeWatch( $this->mTitle );
+                       return wfRunHooks( 'UnwatchArticleComplete', array( &$wgUser, &$this ) );
+               }
+
+               return false;
        }
 
        /**
@@ -2609,28 +2663,229 @@ class Article {
         * @param &$hasHistory Boolean: whether the page has a history
         * @return mixed String containing deletion reason or empty string, or boolean false
         *    if no revision occurred
-        * @deprecated since 1.18
         */
        public function generateReason( &$hasHistory ) {
-               return DeleteAction::getAutoReason( $this );
+               global $wgContLang;
+
+               $dbw = wfGetDB( DB_MASTER );
+               // Get the last revision
+               $rev = Revision::newFromTitle( $this->mTitle );
+
+               if ( is_null( $rev ) ) {
+                       return false;
+               }
+
+               // Get the article's contents
+               $contents = $rev->getText();
+               $blank = false;
+
+               // If the page is blank, use the text from the previous revision,
+               // which can only be blank if there's a move/import/protect dummy revision involved
+               if ( $contents == '' ) {
+                       $prev = $rev->getPrevious();
+
+                       if ( $prev )    {
+                               $contents = $prev->getText();
+                               $blank = true;
+                       }
+               }
+
+               // Find out if there was only one contributor
+               // Only scan the last 20 revisions
+               $res = $dbw->select( 'revision', 'rev_user_text',
+                       array( 'rev_page' => $this->getID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ),
+                       __METHOD__,
+                       array( 'LIMIT' => 20 )
+               );
+
+               if ( $res === false ) {
+                       // This page has no revisions, which is very weird
+                       return false;
+               }
+
+               $hasHistory = ( $res->numRows() > 1 );
+               $row = $dbw->fetchObject( $res );
+
+               if ( $row ) { // $row is false if the only contributor is hidden
+                       $onlyAuthor = $row->rev_user_text;
+                       // Try to find a second contributor
+                       foreach ( $res as $row ) {
+                               if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
+                                       $onlyAuthor = false;
+                                       break;
+                               }
+                       }
+               } else {
+                       $onlyAuthor = false;
+               }
+
+               // Generate the summary with a '$1' placeholder
+               if ( $blank ) {
+                       // The current revision is blank and the one before is also
+                       // blank. It's just not our lucky day
+                       $reason = wfMsgForContent( 'exbeforeblank', '$1' );
+               } else {
+                       if ( $onlyAuthor ) {
+                               $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
+                       } else {
+                               $reason = wfMsgForContent( 'excontent', '$1' );
+                       }
+               }
+
+               if ( $reason == '-' ) {
+                       // Allow these UI messages to be blanked out cleanly
+                       return '';
+               }
+
+               // Replace newlines with spaces to prevent uglyness
+               $contents = preg_replace( "/[\n\r]/", ' ', $contents );
+               // Calculate the maximum amount of chars to get
+               // Max content length = max comment length - length of the comment (excl. $1)
+               $maxLength = 255 - ( strlen( $reason ) - 2 );
+               $contents = $wgContLang->truncate( $contents, $maxLength );
+               // Remove possible unfinished links
+               $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
+               // Now replace the '$1' placeholder
+               $reason = str_replace( '$1', $contents, $reason );
+
+               return $reason;
        }
 
 
        /*
         * UI entry point for page deletion
-        * @deprecated since 1.18
         */
        public function delete() {
-               return Action::factory( 'delete', $this )->show();
+               global $wgOut, $wgRequest;
+
+               $confirm = $wgRequest->wasPosted() &&
+                               $wgOut->getUser()->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
+
+               $this->DeleteReasonList = $wgRequest->getText( 'wpDeleteReasonList', 'other' );
+               $this->DeleteReason = $wgRequest->getText( 'wpReason' );
+
+               $reason = $this->DeleteReasonList;
+
+               if ( $reason != 'other' && $this->DeleteReason != '' ) {
+                       // Entry from drop down menu + additional comment
+                       $reason .= wfMsgForContent( 'colon-separator' ) . $this->DeleteReason;
+               } elseif ( $reason == 'other' ) {
+                       $reason = $this->DeleteReason;
+               }
+
+               # Flag to hide all contents of the archived revisions
+               $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgOut->getUser()->isAllowed( 'suppressrevision' );
+
+               # This code desperately needs to be totally rewritten
+
+               # Read-only check...
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+
+                       return;
+               }
+
+               # Check permissions
+               $permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgOut->getUser() );
+
+               if ( count( $permission_errors ) > 0 ) {
+                       $wgOut->showPermissionsErrorPage( $permission_errors );
+
+                       return;
+               }
+
+               $wgOut->setPagetitle( wfMsg( 'delete-confirm', $this->mTitle->getPrefixedText() ) );
+
+               # Better double-check that it hasn't been deleted yet!
+               $dbw = wfGetDB( DB_MASTER );
+               $conds = $this->mTitle->pageCond();
+               $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
+               if ( $latest === false ) {
+                       $wgOut->showFatalError(
+                               Html::rawElement(
+                                       'div',
+                                       array( 'class' => 'error mw-error-cannotdelete' ),
+                                       wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                               )
+                       );
+                       $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
+                       LogEventsList::showLogExtract(
+                               $wgOut,
+                               'delete',
+                               $this->mTitle->getPrefixedText()
+                       );
+
+                       return;
+               }
+
+               # Hack for big sites
+               $bigHistory = $this->isBigDeletion();
+               if ( $bigHistory && !$this->mTitle->userCan( 'bigdelete' ) ) {
+                       global $wgLang, $wgDeleteRevisionsLimit;
+
+                       $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
+                               array( 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
+
+                       return;
+               }
+
+               if ( $confirm ) {
+                       $this->doDelete( $reason, $suppress );
+
+                       if ( $wgRequest->getCheck( 'wpWatch' ) && $wgOut->getUser()->isLoggedIn() ) {
+                               $this->doWatch();
+                       } elseif ( $this->mTitle->userIsWatching() ) {
+                               $this->doUnwatch();
+                       }
+
+                       return;
+               }
+
+               // Generate deletion reason
+               $hasHistory = false;
+               if ( !$reason ) {
+                       $reason = $this->generateReason( $hasHistory );
+               }
+
+               // If the page has a history, insert a warning
+               if ( $hasHistory && !$confirm ) {
+                       global $wgLang;
+
+                       $skin = $wgOut->getSkin();
+                       $revisions = $this->estimateRevisionCount();
+                       //FIXME: lego
+                       $wgOut->addHTML( '<strong class="mw-delete-warning-revisions">' .
+                               wfMsgExt( 'historywarning', array( 'parseinline' ), $wgLang->formatNum( $revisions ) ) .
+                               wfMsgHtml( 'word-separator' ) . $skin->link( $this->mTitle,
+                                       wfMsgHtml( 'history' ),
+                                       array( 'rel' => 'archives' ),
+                                       array( 'action' => 'history' ) ) .
+                               '</strong>'
+                       );
+
+                       if ( $bigHistory ) {
+                               global $wgDeleteRevisionsLimit;
+                               $wgOut->wrapWikiMsg( "<div class='error'>\n$1\n</div>\n",
+                                       array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
+                       }
+               }
+
+               return $this->confirmDelete( $reason );
        }
 
        /**
         * @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
-        * @deprecated since 1.18
         */
        public function isBigDeletion() {
                global $wgDeleteRevisionsLimit;
-               return $wgDeleteRevisionsLimit && $this->estimateRevisionCount() > $wgDeleteRevisionsLimit;
+
+               if ( $wgDeleteRevisionsLimit ) {
+                       $revCount = $this->estimateRevisionCount();
+
+                       return $revCount > $wgDeleteRevisionsLimit;
+               }
+
+               return false;
        }
 
        /**
@@ -2698,20 +2953,151 @@ class Article {
                return $authors;
        }
 
+       /**
+        * Output deletion confirmation dialog
+        * FIXME: Move to another file?
+        * @param $reason String: prefilled reason
+        */
+       public function confirmDelete( $reason ) {
+               global $wgOut;
+
+               wfDebug( "Article::confirmDelete\n" );
+
+               $deleteBackLink = $wgOut->getSkin()->linkKnown( $this->mTitle );
+               $wgOut->setSubtitle( wfMsgHtml( 'delete-backlink', $deleteBackLink ) );
+               $wgOut->setRobotPolicy( 'noindex,nofollow' );
+               $wgOut->addWikiMsg( 'confirmdeletetext' );
+
+               wfRunHooks( 'ArticleConfirmDelete', array( $this, $wgOut, &$reason ) );
+
+               if ( $wgOut->getUser()->isAllowed( 'suppressrevision' ) ) {
+                       $suppress = "<tr id=\"wpDeleteSuppressRow\">
+                                       <td></td>
+                                       <td class='mw-input'><strong>" .
+                                               Xml::checkLabel( wfMsg( 'revdelete-suppress' ),
+                                                       'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '4' ) ) .
+                                       "</strong></td>
+                               </tr>";
+               } else {
+                       $suppress = '';
+               }
+               $checkWatch = $wgOut->getUser()->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching();
+
+               $form = Xml::openElement( 'form', array( 'method' => 'post',
+                       'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
+                       Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
+                       Xml::tags( 'legend', null, wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ) .
+                       Xml::openElement( 'table', array( 'id' => 'mw-deleteconfirm-table' ) ) .
+                       "<tr id=\"wpDeleteReasonListRow\">
+                               <td class='mw-label'>" .
+                                       Xml::label( wfMsg( 'deletecomment' ), 'wpDeleteReasonList' ) .
+                               "</td>
+                               <td class='mw-input'>" .
+                                       Xml::listDropDown( 'wpDeleteReasonList',
+                                               wfMsgForContent( 'deletereason-dropdown' ),
+                                               wfMsgForContent( 'deletereasonotherlist' ), '', 'wpReasonDropDown', 1 ) .
+                               "</td>
+                       </tr>
+                       <tr id=\"wpDeleteReasonRow\">
+                               <td class='mw-label'>" .
+                                       Xml::label( wfMsg( 'deleteotherreason' ), 'wpReason' ) .
+                               "</td>
+                               <td class='mw-input'>" .
+                               Html::input( 'wpReason', $reason, 'text', array(
+                                       'size' => '60',
+                                       'maxlength' => '255',
+                                       'tabindex' => '2',
+                                       'id' => 'wpReason',
+                                       'autofocus'
+                               ) ) .
+                               "</td>
+                       </tr>";
+
+               # Disallow watching if user is not logged in
+               if ( $wgOut->getUser()->isLoggedIn() ) {
+                       $form .= "
+                       <tr>
+                               <td></td>
+                               <td class='mw-input'>" .
+                                       Xml::checkLabel( wfMsg( 'watchthis' ),
+                                               'wpWatch', 'wpWatch', $checkWatch, array( 'tabindex' => '3' ) ) .
+                               "</td>
+                       </tr>";
+               }
+
+               $form .= "
+                       $suppress
+                       <tr>
+                               <td></td>
+                               <td class='mw-submit'>" .
+                                       Xml::submitButton( wfMsg( 'deletepage' ),
+                                               array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '5' ) ) .
+                               "</td>
+                       </tr>" .
+                       Xml::closeElement( 'table' ) .
+                       Xml::closeElement( 'fieldset' ) .
+                       Html::hidden( 'wpEditToken', $wgOut->getUser()->editToken() ) .
+                       Xml::closeElement( 'form' );
+
+                       if ( $wgOut->getUser()->isAllowed( 'editinterface' ) ) {
+                               $skin = $wgOut->getSkin();
+                               $title = Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' );
+                               $link = $skin->link(
+                                       $title,
+                                       wfMsgHtml( 'delete-edit-reasonlist' ),
+                                       array(),
+                                       array( 'action' => 'edit' )
+                               );
+                               $form .= '<p class="mw-delete-editreasons">' . $link . '</p>';
+                       }
+
+               $wgOut->addHTML( $form );
+               $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
+               LogEventsList::showLogExtract( $wgOut, 'delete',
+                       $this->mTitle->getPrefixedText()
+               );
+       }
+
        /**
         * Perform a deletion and output success or failure messages
-        * @deprecated since 1.18
         */
        public function doDelete( $reason, $suppress = false ) {
-               return DeleteAction::doDeleteArticle(
-                       $this,
-                       $this->getContext(),
-                       array(
-                               'Suppress' => $suppress !== false,
-                               'Reason' => $reason,
-                       ),
-                       true
-               );
+               global $wgOut;
+
+               $id = $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE );
+
+               $error = '';
+               if ( $this->doDeleteArticle( $reason, $suppress, $id, $error ) ) {
+                       $deleted = $this->mTitle->getPrefixedText();
+
+                       $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+                       $wgOut->setRobotPolicy( 'noindex,nofollow' );
+
+                       $loglink = '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]';
+
+                       $wgOut->addWikiMsg( 'deletedtext', $deleted, $loglink );
+                       $wgOut->returnToMain( false );
+               } else {
+                       if ( $error == '' ) {
+                               $wgOut->showFatalError(
+                                       Html::rawElement(
+                                               'div',
+                                               array( 'class' => 'error mw-error-cannotdelete' ),
+                                               wfMsgExt( 'cannotdelete', array( 'parse' ), $this->mTitle->getPrefixedText() )
+                                       )
+                               );
+
+                               $wgOut->addHTML( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
+
+                               LogEventsList::showLogExtract(
+                                       $wgOut,
+                                       'delete',
+                                       $this->mTitle->getPrefixedText()
+                               );
+                       } else {
+                               $wgOut->showFatalError( $error );
+                       }
+               }
        }
 
        /**
@@ -2727,19 +3113,143 @@ class Article {
         * @param $id int article ID
         * @param $commit boolean defaults to true, triggers transaction end
         * @return boolean true if successful
-        *
-        * @deprecated since 1.18
         */
        public function doDeleteArticle( $reason, $suppress = false, $id = 0, $commit = true, &$error = '' ) {
-               return DeleteAction::doDeleteArticle(
-                       $this,
-                       $this->getContext(),
+               global $wgDeferredUpdateList, $wgUseTrackbacks;
+               global $wgUser;
+
+               wfDebug( __METHOD__ . "\n" );
+
+               if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$wgUser, &$reason, &$error ) ) ) {
+                       return false;
+               }
+               $dbw = wfGetDB( DB_MASTER );
+               $t = $this->mTitle->getDBkey();
+               $id = $id ? $id : $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE );
+
+               if ( $t === '' || $id == 0 ) {
+                       return false;
+               }
+
+               $u = new SiteStatsUpdate( 0, 1, - (int)$this->isCountable( $this->getRawText() ), -1 );
+               array_push( $wgDeferredUpdateList, $u );
+
+               // Bitfields to further suppress the content
+               if ( $suppress ) {
+                       $bitfield = 0;
+                       // This should be 15...
+                       $bitfield |= Revision::DELETED_TEXT;
+                       $bitfield |= Revision::DELETED_COMMENT;
+                       $bitfield |= Revision::DELETED_USER;
+                       $bitfield |= Revision::DELETED_RESTRICTED;
+               } else {
+                       $bitfield = 'rev_deleted';
+               }
+
+               $dbw->begin();
+               // For now, shunt the revision data into the archive table.
+               // Text is *not* removed from the text table; bulk storage
+               // is left intact to avoid breaking block-compression or
+               // immutable storage schemes.
+               //
+               // For backwards compatibility, note that some older archive
+               // table entries will have ar_text and ar_flags fields still.
+               //
+               // In the future, we may keep revisions and mark them with
+               // the rev_deleted field, which is reserved for this purpose.
+               $dbw->insertSelect( 'archive', array( 'page', 'revision' ),
                        array(
-                               'Suppress' => $suppress !== false,
-                               'Reason' => $reason,
-                       ),
-                       $commit
+                               'ar_namespace'  => 'page_namespace',
+                               'ar_title'      => 'page_title',
+                               'ar_comment'    => 'rev_comment',
+                               'ar_user'       => 'rev_user',
+                               'ar_user_text'  => 'rev_user_text',
+                               'ar_timestamp'  => 'rev_timestamp',
+                               'ar_minor_edit' => 'rev_minor_edit',
+                               'ar_rev_id'     => 'rev_id',
+                               'ar_text_id'    => 'rev_text_id',
+                               'ar_text'       => '\'\'', // Be explicit to appease
+                               'ar_flags'      => '\'\'', // MySQL's "strict mode"...
+                               'ar_len'        => 'rev_len',
+                               'ar_page_id'    => 'page_id',
+                               'ar_deleted'    => $bitfield
+                       ), array(
+                               'page_id' => $id,
+                               'page_id = rev_page'
+                       ), __METHOD__
                );
+
+               # Delete restrictions for it
+               $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
+
+               # Now that it's safely backed up, delete it
+               $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
+               $ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy
+
+               if ( !$ok ) {
+                       $dbw->rollback();
+                       return false;
+               }
+
+               # Fix category table counts
+               $cats = array();
+               $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
+
+               foreach ( $res as $row ) {
+                       $cats [] = $row->cl_to;
+               }
+
+               $this->updateCategoryCounts( array(), $cats );
+
+               # If using cascading deletes, we can skip some explicit deletes
+               if ( !$dbw->cascadingDeletes() ) {
+                       $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
+
+                       if ( $wgUseTrackbacks )
+                               $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
+
+                       # Delete outgoing links
+                       $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) );
+                       $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
+                       $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
+                       $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) );
+                       $dbw->delete( 'externallinks', array( 'el_from' => $id ) );
+                       $dbw->delete( 'langlinks', array( 'll_from' => $id ) );
+                       $dbw->delete( 'redirect', array( 'rd_from' => $id ) );
+               }
+
+               # If using cleanup triggers, we can skip some manual deletes
+               if ( !$dbw->cleanupTriggers() ) {
+                       # Clean up recentchanges entries...
+                       $dbw->delete( 'recentchanges',
+                               array( 'rc_type != ' . RC_LOG,
+                                       'rc_namespace' => $this->mTitle->getNamespace(),
+                                       'rc_title' => $this->mTitle->getDBkey() ),
+                               __METHOD__ );
+                       $dbw->delete( 'recentchanges',
+                               array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
+                               __METHOD__ );
+               }
+
+               # Clear caches
+               Article::onArticleDelete( $this->mTitle );
+
+               # Clear the cached article id so the interface doesn't act like we exist
+               $this->mTitle->resetArticleID( 0 );
+
+               # Log the deletion, if the page was suppressed, log it at Oversight instead
+               $logtype = $suppress ? 'suppress' : 'delete';
+               $log = new LogPage( $logtype );
+
+               # Make sure logging got through
+               $log->addEntry( 'delete', $this->mTitle, $reason, array() );
+
+               if ( $commit ) {
+                       $dbw->commit();
+               }
+
+               wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$wgUser, $reason, $id ) );
+               return true;
        }
 
        /**
index ccf3123..9ba9d86 100644 (file)
@@ -14,7 +14,6 @@ global $wgAutoloadLocalClasses;
 
 $wgAutoloadLocalClasses = array(
        # Includes
-       'Action' => 'includes/Action.php',
        'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
        'AjaxResponse' => 'includes/AjaxResponse.php',
        'AlphabeticPager' => 'includes/Pager.php',
@@ -52,6 +51,7 @@ $wgAutoloadLocalClasses = array(
        'ConfEditorToken' => 'includes/ConfEditor.php',
        'ConstantDependency' => 'includes/CacheDependency.php',
        'CreativeCommonsRdf' => 'includes/Metadata.php',
+       'Credits' => 'includes/Credits.php',
        'CSSJanus' => 'includes/libs/CSSJanus.php',
        'CSSMin' => 'includes/libs/CSSMin.php',
        'DependencyWrapper' => 'includes/CacheDependency.php',
@@ -274,12 +274,6 @@ $wgAutoloadLocalClasses = array(
        'ZhClient' => 'includes/ZhClient.php',
        'ZipDirectoryReader' => 'includes/ZipDirectoryReader.php',
 
-       # includes/actions
-       'CreditsAction' => 'includes/actions/CreditsAction.php',
-       'DeleteAction' => 'includes/actions/DeleteAction.php',
-       'UnwatchAction' => 'includes/actions/WatchAction.php',
-       'WatchAction' => 'includes/actions/WatchAction.php',
-
        # includes/api
        'ApiBase' => 'includes/api/ApiBase.php',
        'ApiBlock' => 'includes/api/ApiBlock.php',
diff --git a/includes/Credits.php b/includes/Credits.php
new file mode 100644 (file)
index 0000000..e4c8be5
--- /dev/null
@@ -0,0 +1,238 @@
+<?php
+/**
+ * Formats credits for articles
+ *
+ * Copyright 2004, Evan Prodromou <evan@wikitravel.org>.
+ *
+ * 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
+ * @author <evan@wikitravel.org>
+ */
+
+class Credits {
+       /**
+        * This is largely cadged from PageHistory::history
+        * @param $article Article object
+        */
+       public static function showPage( Article $article ) {
+               global $wgOut;
+
+               wfProfileIn( __METHOD__ );
+
+               $wgOut->setPageTitle( $article->mTitle->getPrefixedText() );
+               $wgOut->setSubtitle( wfMsg( 'creditspage' ) );
+               $wgOut->setArticleFlag( false );
+               $wgOut->setArticleRelated( true );
+               $wgOut->setRobotPolicy( 'noindex,nofollow' );
+
+               if ( $article->mTitle->getArticleID() == 0 ) {
+                       $s = wfMsg( 'nocredits' );
+               } else {
+                       $s = self::getCredits( $article, -1 );
+               }
+
+               $wgOut->addHTML( $s );
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Get a list of contributors of $article
+        * @param $article Article object
+        * @param $cnt Int: maximum list of contributors to show
+        * @param $showIfMax Bool: whether to contributors if there more than $cnt
+        * @return String: html
+        */
+       public static function getCredits( Article $article, $cnt, $showIfMax = true ) {
+               wfProfileIn( __METHOD__ );
+               $s = '';
+
+               if ( isset( $cnt ) && $cnt != 0 ) {
+                       $s = self::getAuthor( $article );
+                       if ( $cnt > 1 || $cnt < 0 ) {
+                               $s .= ' ' . self::getContributors( $article, $cnt - 1, $showIfMax );
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $s;
+       }
+
+       /**
+        * Get the last author with the last modification time
+        * @param $article Article object
+        */
+       protected static function getAuthor( Article $article ) {
+               global $wgLang;
+
+               $user = User::newFromId( $article->getUser() );
+
+               $timestamp = $article->getTimestamp();
+               if ( $timestamp ) {
+                       $d = $wgLang->date( $article->getTimestamp(), true );
+                       $t = $wgLang->time( $article->getTimestamp(), true );
+               } else {
+                       $d = '';
+                       $t = '';
+               }
+               return wfMsgExt( 'lastmodifiedatby', 'parsemag', $d, $t, self::userLink( $user ), $user->getName() );
+       }
+
+       /**
+        * Get a list of contributors of $article
+        * @param $article Article object
+        * @param $cnt Int: maximum list of contributors to show
+        * @param $showIfMax Bool: whether to contributors if there more than $cnt
+        * @return String: html
+        */
+       protected static function getContributors( Article $article, $cnt, $showIfMax ) {
+               global $wgLang, $wgHiddenPrefs;
+
+               $contributors = $article->getContributors();
+
+               $others_link = false;
+
+               # Hmm... too many to fit!
+               if ( $cnt > 0 && $contributors->count() > $cnt ) {
+                       $others_link = self::othersLink( $article );
+                       if ( !$showIfMax )
+                               return wfMsgExt( 'othercontribs', 'parsemag', $others_link, $contributors->count() );
+               }
+
+               $real_names = array();
+               $user_names = array();
+               $anon_ips = array();
+
+               # Sift for real versus user names
+               foreach ( $contributors as $user ) {
+                       $cnt--;
+                       if ( $user->isLoggedIn() ) {
+                               $link = self::link( $user );
+                               if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+                                       $real_names[] = $link;
+                               } else {
+                                       $user_names[] = $link;
+                               }
+                       } else {
+                               $anon_ips[] = self::link( $user );
+                       }
+
+                       if ( $cnt == 0 ) {
+                               break;
+                       }
+               }
+
+               if ( count( $real_names ) ) {
+                       $real = $wgLang->listToText( $real_names );
+               } else {
+                       $real = false;
+               }
+
+               # "ThisSite user(s) A, B and C"
+               if ( count( $user_names ) ) {
+                       $user = wfMsgExt(
+                               'siteusers',
+                               'parsemag',
+                               $wgLang->listToText( $user_names ), count( $user_names )
+                       );
+               } else {
+                       $user = false;
+               }
+
+               if ( count( $anon_ips ) ) {
+                       $anon = wfMsgExt(
+                               'anonusers',
+                               'parsemag',
+                               $wgLang->listToText( $anon_ips ), count( $anon_ips )
+                       );
+               } else {
+                       $anon = false;
+               }
+
+               # This is the big list, all mooshed together. We sift for blank strings
+               $fulllist = array();
+               foreach ( array( $real, $user, $anon, $others_link ) as $s ) {
+                       if ( $s ) {
+                               array_push( $fulllist, $s );
+                       }
+               }
+
+               # Make the list into text...
+               $creds = $wgLang->listToText( $fulllist );
+
+               # "Based on work by ..."
+               return strlen( $creds )
+                       ? wfMsgExt( 'othercontribs', 'parsemag', $creds, count( $fulllist ) )
+                       : '';
+       }
+
+       /**
+        * Get a link to $user's user page
+        * @param $user User object
+        * @return String: html
+        */
+       protected static function link( User $user ) {
+               global $wgUser, $wgHiddenPrefs;
+               if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) {
+                       $real = $user->getRealName();
+               } else {
+                       $real = false;
+               }
+
+               $skin = $wgUser->getSkin();
+               $page = $user->isAnon() ?
+                       SpecialPage::getTitleFor( 'Contributions', $user->getName() ) :
+                       $user->getUserPage();
+
+               return $skin->link( $page, htmlspecialchars( $real ? $real : $user->getName() ) );
+       }
+
+       /**
+        * Get a link to $user's user page
+        * @param $user User object
+        * @return String: html
+        */
+       protected static function userLink( User $user ) {
+               $link = self::link( $user );
+               if ( $user->isAnon() ) {
+                       return wfMsgExt( 'anonuser', array( 'parseinline', 'replaceafter' ), $link );
+               } else {
+                       global $wgHiddenPrefs;
+                       if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+                               return $link;
+                       } else {
+                               return wfMsgExt( 'siteuser', 'parsemag', $link, $user->getName() );
+                       }
+               }
+       }
+
+       /**
+        * Get a link to action=credits of $article page
+        * @param $article Article object
+        * @return String: html
+        */
+       protected static function othersLink( Article $article ) {
+               global $wgUser;
+               $skin = $wgUser->getSkin();
+               return $skin->link(
+                       $article->getTitle(),
+                       wfMsgHtml( 'others' ),
+                       array(),
+                       array( 'action' => 'credits' ),
+                       array( 'known' )
+               );
+       }
+}
index e447983..ba72d76 100644 (file)
@@ -27,10 +27,12 @@ if( !defined( 'MEDIAWIKI' ) ) {
 }
 
 # Create a site configuration object. Not used for much in a default install
-if ( !defined( 'MW_COMPILED' ) ) {
-       require_once( "$IP/includes/SiteConfiguration.php" );
+if ( !defined( 'MW_PHP4' ) ) {
+       if ( !defined( 'MW_COMPILED' ) ) {
+               require_once( "$IP/includes/SiteConfiguration.php" );
+       }
+       $wgConf = new SiteConfiguration;
 }
-$wgConf = new SiteConfiguration;
 /** @endcond */
 
 /** MediaWiki version number */
@@ -5021,38 +5023,6 @@ $wgMaxRedirectLinksRetrieved = 500;
 
 /** @} */ # end special pages }
 
-/*************************************************************************//**
- * @name   Actions
- * @{
- */
-
-/**
- * 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
- *     'foo' => false          The action is disabled; show an error message
- * Unsetting core actions will probably cause things to complain loudly.
- */
-$wgActions = array(
-       'credits' => true,
-       'delete' => true,
-       'unwatch' => true,
-       'watch' => true,
-);
-
-/**
- * Array of disabled article actions, e.g. view, edit, dublincore, delete, etc.
- * @deprecated since 1.18; just set $wgActions['action'] = false instead
- */
-$wgDisabledActions = array();
-
-/**
- * Allow the "info" action, very inefficient at the moment
- */
-$wgAllowPageInfo = false;
-
-/** @} */ # end actions }
-
 /*************************************************************************//**
  * @name   Robot (search engine crawler) policy
  * See also $wgNoFollowLinks.
@@ -5318,9 +5288,17 @@ $wgUpdateRowsPerQuery = 100;
  * @{
  */
 
+/** Allow the "info" action, very inefficient at the moment */
+$wgAllowPageInfo = false;
+
 /** Name of the external diff engine to use */
 $wgExternalDiffEngine = false;
 
+/**
+ * Array of disabled article actions, e.g. view, edit, dublincore, delete, etc.
+ */
+$wgDisabledActions = array();
+
 /**
  * Disable redirects to special pages and interwiki redirects, which use a 302
  * and have no "redirected from" link. Note this is only for articles with #Redirect
index fb6f2bc..cafb641 100644 (file)
@@ -1153,9 +1153,9 @@ class EditPage {
                        $dbw = wfGetDB( DB_MASTER );
                        $dbw->begin();
                        if ( $this->watchthis ) {
-                               Action::factory( 'watch', $this->mArticle )->execute();
+                               $this->mArticle->doWatch();
                        } else {
-                               Action::factory( 'watch', $this->mArticle )->execute();
+                               $this->mArticle->doUnwatch();
                        }
                        $dbw->commit();
                }
index 9101d6e..f77d697 100644 (file)
@@ -125,9 +125,9 @@ class FileDeleteForm {
                                if( $article->doDeleteArticle( $reason, $suppress, $id, false ) ) {
                                        global $wgRequest;
                                        if( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) {
-                                               Action::factory( 'watch', $article )->execute();
+                                               $article->doWatch();
                                        } elseif( $title->userIsWatching() ) {
-                                               Action::factory( 'unwatch', $article )->execute();
+                                               $article->doUnwatch();
                                        }
                                        $status = $file->delete( $reason, $suppress );
                                        if( $status->ok ) {
index 6f04e97..86aca3e 100644 (file)
@@ -317,9 +317,9 @@ class ProtectionForm {
                }
 
                if( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) {
-                       Action::factory( 'watch', $this->mArticle )->execute();
+                       $this->mArticle->doWatch();
                } elseif( $this->mTitle->userIsWatching() ) {
-                       Action::factory( 'unwatch', $this->mArticle )->execute();
+                       $this->mArticle->doUnwatch();
                }
                return $ok;
        }
index a7bf629..837740e 100644 (file)
@@ -270,14 +270,6 @@ if ( !$wgEnotifMinorEdits ) {
        $wgHiddenPrefs[] = 'enotifminoredits';
 }
 
-# $wgDisabledActions is deprecated as of 1.18
-foreach( $wgDisabledActions as $action ){
-       $wgActions[$action] = false;
-}
-if( !$wgAllowPageInfo ){
-       $wgActions['info'] = false;
-}
-
 if ( !$wgHtml5Version && $wgHtml5 && $wgAllowRdfaAttributes ) {
        # see http://www.w3.org/TR/rdfa-in-html/#document-conformance
        if ( $wgMimeType == 'application/xhtml+xml' ) {
index a095a36..f54e2b3 100644 (file)
@@ -471,16 +471,9 @@ class MediaWiki {
                        return;
                }
 
-               $act = $this->getAction();
+               $action = $this->getAction();
 
-               $action = Action::factory( $this->getAction(), $article );
-               if( $action instanceof Action ){
-                       $action->show();
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               switch( $act ) {
+               switch( $action ) {
                        case 'view':
                                $this->context->output->setSquidMaxage( $this->getVal( 'SquidMaxage' ) );
                                $article->view();
@@ -491,6 +484,9 @@ class MediaWiki {
                                $raw->view();
                                wfProfileOut( __METHOD__ . '-raw' );
                                break;
+                       case 'watch':
+                       case 'unwatch':
+                       case 'delete':
                        case 'revert':
                        case 'rollback':
                        case 'protect':
@@ -500,7 +496,7 @@ class MediaWiki {
                        case 'render':
                        case 'deletetrackback':
                        case 'purge':
-                               $article->$act();
+                               $article->$action();
                                break;
                        case 'print':
                                $article->view();
@@ -521,6 +517,9 @@ class MediaWiki {
                                        $rdf->show();
                                }
                                break;
+                       case 'credits':
+                               Credits::showPage( $article );
+                               break;
                        case 'submit':
                                if ( session_id() == '' ) {
                                        // Send a cookie so anons get talk message notifications
@@ -533,7 +532,7 @@ class MediaWiki {
                                        $external = $this->context->request->getVal( 'externaledit' );
                                        $section = $this->context->request->getVal( 'section' );
                                        $oldid = $this->context->request->getVal( 'oldid' );
-                                       if ( !$this->getVal( 'UseExternalEditor' ) || $act == 'submit' || $internal ||
+                                       if ( !$this->getVal( 'UseExternalEditor' ) || $action == 'submit' || $internal ||
                                           $section || $oldid || ( !$this->context->user->getOption( 'externaleditor' ) && !$external ) ) {
                                                $editor = new EditPage( $article );
                                                $editor->submit();
@@ -562,7 +561,7 @@ class MediaWiki {
                                $special->execute( '' );
                                break;
                        default:
-                               if ( wfRunHooks( 'UnknownAction', array( $act, $article ) ) ) {
+                               if ( wfRunHooks( 'UnknownAction', array( $action, $article ) ) ) {
                                        $this->context->output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
                                }
                }
diff --git a/includes/actions/CreditsAction.php b/includes/actions/CreditsAction.php
deleted file mode 100644 (file)
index 576834f..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-<?php
-/**
- * Formats credits for articles
- *
- * Copyright 2004, Evan Prodromou <evan@wikitravel.org>.
- *
- * 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 Actions
- * @author <evan@wikitravel.org>
- */
-
-class CreditsAction extends FormlessAction {
-
-       public function getName(){
-               return 'credits';
-       }
-
-       public function getRestriction(){
-               return null;
-       }
-
-       /**
-        * This is largely cadged from PageHistory::history
-        */
-       public function onView() {
-               wfProfileIn( __METHOD__ );
-
-               if ( $this->page->getID() == 0 ) {
-                       $s = wfMsg( 'nocredits' );
-               } else {
-                       $s = $this->getCredits( -1 );
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               return $s;
-       }
-
-       /**
-        * Get a list of contributors of $article
-        * @param $article Article object
-        * @param $cnt Int: maximum list of contributors to show
-        * @param $showIfMax Bool: whether to contributors if there more than $cnt
-        * @return String: html
-        */
-       protected function getCredits( $cnt, $showIfMax = true ) {
-               wfProfileIn( __METHOD__ );
-               $s = '';
-
-               if ( isset( $cnt ) && $cnt != 0 ) {
-                       $s = self::getAuthor( $this->page );
-                       if ( $cnt > 1 || $cnt < 0 ) {
-                               $s .= ' ' . $this->getContributors( $cnt - 1, $showIfMax );
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return $s;
-       }
-
-       /**
-        * Get the last author with the last modification time
-        * @param $article Article object
-        */
-       protected static function getAuthor( Article $article ) {
-               global $wgLang;
-
-               $user = User::newFromId( $article->getUser() );
-
-               $timestamp = $article->getTimestamp();
-               if ( $timestamp ) {
-                       $d = $wgLang->date( $article->getTimestamp(), true );
-                       $t = $wgLang->time( $article->getTimestamp(), true );
-               } else {
-                       $d = '';
-                       $t = '';
-               }
-               return wfMsgExt( 'lastmodifiedatby', 'parsemag', $d, $t, self::userLink( $user ), $user->getName() );
-       }
-
-       /**
-        * Get a list of contributors of $article
-        * @param $article Article object
-        * @param $cnt Int: maximum list of contributors to show
-        * @param $showIfMax Bool: whether to contributors if there more than $cnt
-        * @return String: html
-        */
-       protected function getContributors( $cnt, $showIfMax ) {
-               global $wgLang, $wgHiddenPrefs;
-
-               $contributors = $this->page->getContributors();
-
-               $others_link = false;
-
-               # Hmm... too many to fit!
-               if ( $cnt > 0 && $contributors->count() > $cnt ) {
-                       $others_link = $this->othersLink();
-                       if ( !$showIfMax )
-                               return wfMsgExt( 'othercontribs', 'parsemag', $others_link, $contributors->count() );
-               }
-
-               $real_names = array();
-               $user_names = array();
-               $anon_ips = array();
-
-               # Sift for real versus user names
-               foreach ( $contributors as $user ) {
-                       $cnt--;
-                       if ( $user->isLoggedIn() ) {
-                               $link = self::link( $user );
-                               if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
-                                       $real_names[] = $link;
-                               } else {
-                                       $user_names[] = $link;
-                               }
-                       } else {
-                               $anon_ips[] = self::link( $user );
-                       }
-
-                       if ( $cnt == 0 ) {
-                               break;
-                       }
-               }
-
-               if ( count( $real_names ) ) {
-                       $real = $wgLang->listToText( $real_names );
-               } else {
-                       $real = false;
-               }
-
-               # "ThisSite user(s) A, B and C"
-               if ( count( $user_names ) ) {
-                       $user = wfMsgExt(
-                               'siteusers',
-                               'parsemag',
-                               $wgLang->listToText( $user_names ), count( $user_names )
-                       );
-               } else {
-                       $user = false;
-               }
-
-               if ( count( $anon_ips ) ) {
-                       $anon = wfMsgExt(
-                               'anonusers',
-                               'parsemag',
-                               $wgLang->listToText( $anon_ips ), count( $anon_ips )
-                       );
-               } else {
-                       $anon = false;
-               }
-
-               # This is the big list, all mooshed together. We sift for blank strings
-               $fulllist = array();
-               foreach ( array( $real, $user, $anon, $others_link ) as $s ) {
-                       if ( $s ) {
-                               array_push( $fulllist, $s );
-                       }
-               }
-
-               # Make the list into text...
-               $creds = $wgLang->listToText( $fulllist );
-
-               # "Based on work by ..."
-               return strlen( $creds )
-                       ? wfMsgExt( 'othercontribs', 'parsemag', $creds, count( $fulllist ) )
-                       : '';
-       }
-
-       /**
-        * Get a link to $user's user page
-        * @param $user User object
-        * @return String: html
-        */
-       protected static function link( User $user ) {
-               global $wgUser, $wgHiddenPrefs;
-               if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) {
-                       $real = $user->getRealName();
-               } else {
-                       $real = false;
-               }
-
-               $page = $user->isAnon()
-                       ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
-                       : $user->getUserPage();
-
-               return Linker::link( $page, htmlspecialchars( $real ? $real : $user->getName() ) );
-       }
-
-       /**
-        * Get a link to $user's user page
-        * @param $user User object
-        * @return String: html
-        */
-       protected static function userLink( User $user ) {
-               $link = self::link( $user );
-               if ( $user->isAnon() ) {
-                       return wfMsgExt( 'anonuser', array( 'parseinline', 'replaceafter' ), $link );
-               } else {
-                       global $wgHiddenPrefs;
-                       if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
-                               return $link;
-                       } else {
-                               return wfMsgExt( 'siteuser', 'parsemag', $link, $user->getName() );
-                       }
-               }
-       }
-
-       /**
-        * Get a link to action=credits of $article page
-        * @param $article Article object
-        * @return String: html
-        */
-       protected function othersLink() {
-               global $wgUser;
-               return Linker::link(
-                       $this->getTitle(),
-                       wfMsgHtml( 'others' ),
-                       array(),
-                       array( 'action' => 'credits' ),
-                       array( 'known' )
-               );
-       }
-}
diff --git a/includes/actions/DeleteAction.php b/includes/actions/DeleteAction.php
deleted file mode 100644 (file)
index 3f8097f..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-<?php
-/**
- * Performs the watch and unwatch actions on a page
- *
- * 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 Actions
- */
-
-class DeleteAction extends Action {
-
-       public function getName(){
-               return 'delete';
-       }
-
-       public function getRestriction(){
-               return 'delete';
-       }
-
-       protected function getDescription(){
-               return wfMsg( 'delete-confirm', $this->getTitle()->getPrefixedText() );
-       }
-
-       /**
-        * Check that the deletion can be executed.  In addition to checking the user permissions,
-        * check that the page is not too big and has not already been deleted.
-        * @throws ErrorPageError
-        * @see Action::checkCanExecute
-        */
-       protected function checkCanExecute( User $user ){
-
-               // Check that the article hasn't already been deleted
-               $dbw = wfGetDB( DB_MASTER );
-               $conds = $this->getTitle()->pageCond();
-               $latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
-               if ( $latest === false ) {
-                       // Get the deletion log
-                       $log = '';
-                       LogEventsList::showLogExtract(
-                               $log,
-                               'delete',
-                               $this->getTitle()->getPrefixedText()
-                       );
-
-                       $msg = new Message( 'cannotdelete' );
-                       $msg->params( $this->getTitle()->getPrefixedText() ); // This parameter is parsed
-                       $msg->rawParams( $log ); // This is not
-
-                       throw new ErrorPageError( 'internalerror', $msg );
-               }
-
-               // Limit deletions of big pages
-               $bigHistory = $this->isBigDeletion();
-               if ( $bigHistory && !$user->isAllowed( 'bigdelete' ) ) {
-                       global $wgDeleteRevisionsLimit;
-                       throw new ErrorPageError(
-                               'internalerror',
-                               'delete-toobig',
-                               $this->getContext()->lang->formatNum( $wgDeleteRevisionsLimit )
-                       );
-               }
-
-               return parent::checkCanExecute( $user );
-       }
-
-       protected function getFormFields(){
-               // TODO: add more useful things here?
-               $infoText = Html::rawElement(
-                       'strong',
-                       array(),
-                       Linker::link( $this->getTitle(), $this->getTitle()->getText() )
-               );
-
-               $arr = array(
-                       'Page' => array(
-                               'type' => 'info',
-                               'raw' => true,
-                               'default' => $infoText,
-                       ),
-                       'Reason' => array(
-                               'type' => 'selectandother',
-                               'label-message' => 'deletecomment',
-                               'options-message' => 'deletereason-dropdown',
-                               'size' => '60',
-                               'maxlength' => '255',
-                               'default' => self::getAutoReason( $this->page),
-                       ),
-               );
-
-               if( $this->getUser()->isLoggedIn() ){
-                       $arr['Watch'] = array(
-                               'type' => 'check',
-                               'label-message' => 'watchthis',
-                               'default' => $this->getUser()->getBoolOption( 'watchdeletion' ) || $this->getTitle()->userIsWatching()
-                       );
-               }
-
-               if( $this->getUser()->isAllowed( 'suppressrevision' ) ){
-                       $arr['Suppress'] = array(
-                               'type' => 'check',
-                               'label-message' => 'revdelete-suppress',
-                               'default' => false,
-                       );
-               }
-
-               return $arr;
-       }
-
-       /**
-        * Text to go at the top of the form, before the opening fieldset
-        * @see Action::preText()
-        * @return String
-        */
-       protected function preText() {
-
-               // If the page has a history, insert a warning
-               if ( $this->page->estimateRevisionCount() ) {
-                       global $wgLang;
-
-                       $link = Linker::link(
-                               $this->getTitle(),
-                               wfMsgHtml( 'history' ),
-                               array( 'rel' => 'archives' ),
-                               array( 'action' => 'history' )
-                       );
-
-                       return Html::rawElement(
-                               'strong',
-                               array( 'class' => 'mw-delete-warning-revisions' ),
-                               wfMessage(
-                                       'historywarning',
-                                       $wgLang->formatNum( $this->page->estimateRevisionCount() )
-                               )->rawParams( $link )->parse()
-                       );
-               }
-       }
-
-       /**
-        * Text to go at the bottom of the form, below the closing fieldset
-        * @see Action::postText()
-        * @return string
-        */
-       protected function postText(){
-               $s = '';
-               LogEventsList::showLogExtract(
-                       $s,
-                       'delete',
-                       $this->getTitle()->getPrefixedText()
-               );
-               return Html::element( 'h2', array(), LogPage::logName( 'delete' ) ) . $s;
-       }
-
-       protected function alterForm( HTMLForm &$form ){
-               $form->setWrapperLegend( wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) );
-
-               if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
-                       $link = Linker::link(
-                               Title::makeTitle( NS_MEDIAWIKI, 'Deletereason-dropdown' ),
-                               wfMsgHtml( 'delete-edit-reasonlist' ),
-                               array(),
-                               array( 'action' => 'edit' )
-                       );
-                       $form->addHeaderText( '<p class="mw-delete-editreasons">' . $link . '</p>' );
-               }
-       }
-
-       /**
-        * Function called on form submission.  Privilege checks and validation have already been
-        * completed by this point; we just need to jump out to the heavy-lifting function,
-        * which is implemented as a static method so it can be called from other places
-        * TODO: make those other places call $action->execute() properly
-        * @see Action::onSubmit()
-        * @param  $data Array
-        * @return Array|Bool
-        */
-       public function onSubmit( $data ){
-               $status = self::doDeleteArticle( $this->page, $this->getContext(), $data, true );
-               return $status;
-       }
-
-       public function onSuccess(){
-               // Watch or unwatch, if requested
-               if( $this->getRequest()->getCheck( 'wpWatch' ) && $this->getUser()->isLoggedIn() ) {
-                       Action::factory( 'watch', $this->page )->execute();
-               } elseif ( $this->getTitle()->userIsWatching() ) {
-                       Action::factory( 'unwatch', $this->page )->execute();
-               }
-
-               $this->getOutput()->setPagetitle( wfMsg( 'actioncomplete' ) );
-               $this->getOutput()->addWikiMsg(
-                       'deletedtext',
-                       $this->getTitle()->getPrefixedText(),
-                       '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]'
-               );
-               $this->getOutput()->returnToMain( false );
-       }
-
-       /**
-        * @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
-        */
-       protected function isBigDeletion() {
-               global $wgDeleteRevisionsLimit;
-               return $wgDeleteRevisionsLimit && $this->page->estimateRevisionCount() > $wgDeleteRevisionsLimit;
-       }
-
-       /**
-        * Back-end article deletion
-        * Deletes the article with database consistency, writes logs, purges caches
-        *
-        * @param $commit boolean defaults to true, triggers transaction end
-        * @return Bool|Array true if successful, error array on failure
-        */
-       public static function doDeleteArticle( Article $page, RequestContext $context, array $data, $commit = true ) {
-               global $wgDeferredUpdateList, $wgUseTrackbacks;
-
-               wfDebug( __METHOD__ . "\n" );
-
-               // The normal syntax from HTMLSelectAndOtherField is for the reason to be in the form
-               // 'Reason' => array( <full reason>, <dropdown>, <custom> ), but it's reasonable for other
-               // functions to just pass 'Reason' => <reason>
-               $data['Reason'] = (array)$data['Reason'];
-
-               $error = null;
-               if ( !wfRunHooks( 'ArticleDelete', array( &$page, &$context->user, &$data['Reason'][0], &$error ) ) ) {
-                       return $error;
-               }
-
-               $title = $page->getTitle();
-               $id = $page->getID( Title::GAID_FOR_UPDATE );
-
-               if ( $title->getDBkey() === '' || $id == 0 ) {
-                       return false;
-               }
-
-               $updates = new SiteStatsUpdate( 0, 1, - (int)$page->isCountable( $page->getRawText() ), -1 );
-               array_push( $wgDeferredUpdateList, $updates );
-
-               // Bitfields to further suppress the content
-               if ( isset( $data['Suppress'] ) && $data['Suppress'] ) {
-                       $bitfield = 0;
-                       // This should be 15...
-                       $bitfield |= Revision::DELETED_TEXT;
-                       $bitfield |= Revision::DELETED_COMMENT;
-                       $bitfield |= Revision::DELETED_USER;
-                       $bitfield |= Revision::DELETED_RESTRICTED;
-
-                       $logtype = 'suppress';
-               } else {
-                       // Otherwise, leave it unchanged
-                       $bitfield = 'rev_deleted';
-                       $logtype = 'delete';
-               }
-
-               $dbw = wfGetDB( DB_MASTER );
-               $dbw->begin();
-               // For now, shunt the revision data into the archive table.
-               // Text is *not* removed from the text table; bulk storage
-               // is left intact to avoid breaking block-compression or
-               // immutable storage schemes.
-               //
-               // For backwards compatibility, note that some older archive
-               // table entries will have ar_text and ar_flags fields still.
-               //
-               // In the future, we may keep revisions and mark them with
-               // the rev_deleted field, which is reserved for this purpose.
-               $dbw->insertSelect(
-                       'archive',
-                       array( 'page', 'revision' ),
-                       array(
-                               'ar_namespace'  => 'page_namespace',
-                               'ar_title'      => 'page_title',
-                               'ar_comment'    => 'rev_comment',
-                               'ar_user'       => 'rev_user',
-                               'ar_user_text'  => 'rev_user_text',
-                               'ar_timestamp'  => 'rev_timestamp',
-                               'ar_minor_edit' => 'rev_minor_edit',
-                               'ar_rev_id'     => 'rev_id',
-                               'ar_text_id'    => 'rev_text_id',
-                               'ar_text'       => "''", // Be explicit to appease
-                               'ar_flags'      => "''", // MySQL's "strict mode"...
-                               'ar_len'        => 'rev_len',
-                               'ar_page_id'    => 'page_id',
-                               'ar_deleted'    => $bitfield
-                       ),
-                       array(
-                               'page_id' => $id,
-                               'page_id = rev_page'
-                       ),
-                       __METHOD__
-               );
-
-               // Delete restrictions for it
-               $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
-
-               // Now that it's safely backed up, delete it
-               $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
-
-               // getArticleId() uses slave, could be laggy
-               if ( $dbw->affectedRows() == 0 ) {
-                       $dbw->rollback();
-                       return false;
-               }
-
-               // Fix category table counts
-               $res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
-               $cats = array();
-               foreach ( $res as $row ) {
-                       $cats[] = $row->cl_to;
-               }
-               $page->updateCategoryCounts( array(), $cats );
-
-               // If using cascading deletes, we can skip some explicit deletes
-               if ( !$dbw->cascadingDeletes() ) {
-                       $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
-
-                       if ( $wgUseTrackbacks ){
-                               $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
-                       }
-
-                       // Delete outgoing links
-                       $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) );
-                       $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
-                       $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
-                       $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) );
-                       $dbw->delete( 'externallinks', array( 'el_from' => $id ) );
-                       $dbw->delete( 'langlinks', array( 'll_from' => $id ) );
-                       $dbw->delete( 'redirect', array( 'rd_from' => $id ) );
-               }
-
-               // If using cleanup triggers, we can skip some manual deletes
-               if ( !$dbw->cleanupTriggers() ) {
-                       // Clean up recentchanges entries...
-                       $dbw->delete( 'recentchanges',
-                               array(
-                                       'rc_type != ' . RC_LOG,
-                                       'rc_namespace' => $title->getNamespace(),
-                                       'rc_title' => $title->getDBkey() ),
-                               __METHOD__
-                       );
-                       $dbw->delete(
-                               'recentchanges',
-                               array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
-                               __METHOD__
-                       );
-               }
-
-               // Clear caches
-               // TODO: should this be in here or left in Article?
-               Article::onArticleDelete( $title );
-
-               // Clear the cached article id so the interface doesn't act like we exist
-               $title->resetArticleID( 0 );
-
-               // Log the deletion, if the page was suppressed, log it at Oversight instead
-               $log = new LogPage( $logtype );
-
-               // Make sure logging got through
-               $log->addEntry( 'delete', $title, $data['Reason'][0], array() );
-
-               if ( $commit ) {
-                       $dbw->commit();
-               }
-
-               wfRunHooks( 'ArticleDeleteComplete', array( &$page, &$context->user, $data['Reason'][0], $id ) );
-               return true;
-       }
-
-       /**
-        * Auto-generates a deletion reason.  Also sets $this->hasHistory if the page has old
-        * revisions.
-        *
-        * @return mixed String containing default reason or empty string, or boolean false
-        *    if no revision was found
-        */
-       public static function getAutoReason( Article $page ) {
-               global $wgContLang;
-
-               $dbw = wfGetDB( DB_MASTER );
-               // Get the last revision
-               $rev = Revision::newFromTitle( $page->getTitle() );
-
-               if ( is_null( $rev ) ) {
-                       return false;
-               }
-
-               // Get the article's contents
-               $contents = $rev->getText();
-               $blank = false;
-
-               // If the page is blank, use the text from the previous revision,
-               // which can only be blank if there's a move/import/protect dummy revision involved
-               if ( $contents == '' ) {
-                       $prev = $rev->getPrevious();
-
-                       if ( $prev )    {
-                               $contents = $prev->getText();
-                               $blank = true;
-                       }
-               }
-
-               // Find out if there was only one contributor
-               // Only scan the last 20 revisions
-               $res = $dbw->select( 'revision', 'rev_user_text',
-                       array(
-                               'rev_page' => $page->getID(),
-                               $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0'
-                       ),
-                       __METHOD__,
-                       array( 'LIMIT' => 20 )
-               );
-
-               if ( $res === false ) {
-                       // This page has no revisions, which is very weird
-                       return false;
-               }
-
-               $row = $dbw->fetchObject( $res );
-
-               if ( $row ) { // $row is false if the only contributor is hidden
-                       $onlyAuthor = $row->rev_user_text;
-                       // Try to find a second contributor
-                       foreach ( $res as $row ) {
-                               if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
-                                       $onlyAuthor = false;
-                                       break;
-                               }
-                       }
-               } else {
-                       $onlyAuthor = false;
-               }
-
-               // Generate the summary with a '$1' placeholder
-               if ( $blank ) {
-                       // The current revision is blank and the one before is also
-                       // blank. It's just not our lucky day
-                       $reason = wfMessage( 'exbeforeblank', '$1' )->inContentLanguage()->text();
-               } else {
-                       if ( $onlyAuthor ) {
-                               $reason = wfMessage( 'excontentauthor', '$1', $onlyAuthor )->inContentLanguage()->text();
-                       } else {
-                               $reason = wfMessage( 'excontent', '$1' )->inContentLanguage()->text();
-                       }
-               }
-
-               if ( $reason == '-' ) {
-                       // Allow these UI messages to be blanked out cleanly
-                       return '';
-               }
-
-               // Replace newlines with spaces to prevent uglyness
-               $contents = preg_replace( "/[\n\r]/", ' ', $contents );
-               // Calculate the maximum number of chars to get
-               // Max content length = max comment length - length of the comment (excl. $1)
-               $maxLength = 255 - ( strlen( $reason ) - 2 );
-               $contents = $wgContLang->truncate( $contents, $maxLength );
-               // Remove possible unfinished links
-               $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
-               // Now replace the '$1' placeholder
-               $reason = str_replace( '$1', $contents, $reason );
-
-               return $reason;
-       }
-}
diff --git a/includes/actions/WatchAction.php b/includes/actions/WatchAction.php
deleted file mode 100644 (file)
index e3fb31b..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-/**
- * Performs the watch and unwatch actions on a page
- *
- * 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 Actions
- */
-
-class WatchAction extends FormlessAction {
-
-       public function getName(){
-               return 'watch';
-       }
-
-       public function getRestriction(){
-               return 'read';
-       }
-
-       protected function getDescription(){
-               return wfMsg( 'addedwatch' );
-       }
-
-       protected function checkCanExecute( User $user ){
-               if ( $user->isAnon() ) {
-                       throw new ErrorPageError( 'watchnologin', 'watchnologintext' );
-               }
-               return parent::checkCanExecute( $user );
-       }
-
-       public function onView() {
-               wfProfileIn( __METHOD__ );
-
-               $user = $this->getUser();
-               if ( wfRunHooks( 'WatchArticle', array( &$user, &$this->page ) ) ) {
-                       $this->getUser()->addWatch( $this->getTitle() );
-                       wfRunHooks( 'WatchArticleComplete', array( &$user, &$this->page ) );
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               return wfMessage( 'addedwatchtext', $this->getTitle()->getPrefixedText() )->parse();
-       }
-}
-
-class UnwatchAction extends WatchAction {
-
-       public function getName(){
-               return 'unwatch';
-       }
-
-       protected function getDescription(){
-               return wfMsg( 'removedwatch' );
-       }
-
-       public function onView() {
-               wfProfileIn( __METHOD__ );
-
-               $user = $this->getUser();
-               if ( wfRunHooks( 'UnwatchArticle', array( &$user, &$this->page ) ) ) {
-                       $this->getUser()->removeWatch( $this->getTitle() );
-                       wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$this->page ) );
-               }
-
-               wfProfileOut( __METHOD__ );
-
-               return wfMessage( 'removedwatchtext', $this->getTitle()->getPrefixedText() )->parse();
-       }
-}
index fe6ce54..336bc79 100644 (file)
@@ -645,9 +645,9 @@ abstract class ApiBase {
 
                $articleObj = new Article( $titleObj );
                if ( $value ) {
-                       Action::factory( 'watch', $articleObj )->execute();
+                       $articleObj->doWatch();
                } else {
-                       Action::factory( 'unwatch', $articleObj )->execute();
+                       $articleObj->doUnwatch();
                }
        }
 
index 3a61ccd..0eba219 100644 (file)
@@ -123,6 +123,11 @@ class ApiDelete extends ApiBase {
         * @return Title::getUserPermissionsErrors()-like array
         */
        public static function delete( &$article, $token, &$reason = null ) {
+               global $wgUser;
+               if ( $article->isBigDeletion() && !$wgUser->isAllowed( 'bigdelete' ) ) {
+                       global $wgDeleteRevisionsLimit;
+                       return array( array( 'delete-toobig', $wgDeleteRevisionsLimit ) );
+               }
                $title = $article->getTitle();
                $errors = self::getPermissionsError( $title, $token );
                if ( count( $errors ) ) {
@@ -131,28 +136,21 @@ class ApiDelete extends ApiBase {
 
                // Auto-generate a summary, if necessary
                if ( is_null( $reason ) ) {
-                       $reason = DeleteAction::getAutoReason( $article );
+                       // Need to pass a throwaway variable because generateReason expects
+                       // a reference
+                       $hasHistory = false;
+                       $reason = $article->generateReason( $hasHistory );
                        if ( $reason === false ) {
                                return array( array( 'cannotdelete' ) );
                        }
                }
 
-               $action = Action::factory( 'delete', $article );
-               $data = array(
-                       'Reason' => $reason,
-                       'Suppress' => false, // The thought of people doing this through the API is scary...
-               );
-
-               try {
-                       $action->execute( $data, false );
-               }
-               catch ( ErrorPageError $e ){
-                       if( $e->msg == 'delete-toobig' ){
-                               global $wgDeleteRevisionsLimit;
-                               return array( array( 'delete-toobig', $wgDeleteRevisionsLimit ) );
-                       } else {
-                               array( array( 'cannotdelete', $article->mTitle->getPrefixedText() ) );
-                       }
+               $error = '';
+               // Luckily, Article.php provides a reusable delete function that does the hard work for us
+               if ( $article->doDeleteArticle( $reason, false, 0, true, $error ) ) {
+                       return array();
+               } else {
+                       return array( array( 'cannotdelete', $article->mTitle->getPrefixedText() ) );
                }
        }
 
index 685306d..fe52328 100644 (file)
@@ -59,11 +59,11 @@ class ApiWatch extends ApiBase {
                if ( $params['unwatch'] ) {
                        $res['unwatched'] = '';
                        $res['message'] = wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() );
-                       $success = Action::factory( 'unwatch', $article )->execute();
+                       $success = $article->doUnwatch();
                } else {
                        $res['watched'] = '';
                        $res['message'] = wfMsgExt( 'addedwatchtext', array( 'parse' ), $title->getPrefixedText() );
-                       $success = Action::factory( 'watch', $article )->execute();
+                       $success = $article->doWatch();
                }
                if ( !$success ) {
                        $this->dieUsageMsg( array( 'hookaborted' ) );
index f6259c2..2be33d0 100644 (file)
@@ -359,11 +359,8 @@ class MovePageForm extends UnlistedSpecialPage {
                        $article = new Article( $nt );
 
                        # Disallow deletions of big articles
-                       global $wgDeleteRevisionsLimit;
-                       if ( $wgDeleteRevisionsLimit
-                                       && $this->estimateRevisionCount() > $wgDeleteRevisionsLimit
-                                       && !$nt->userCan( 'bigdelete' ) )
-                       {
+                       $bigHistory = $article->isBigDeletion();
+                       if( $bigHistory && !$nt->userCan( 'bigdelete' ) ) {
                                global $wgDeleteRevisionsLimit;
                                $this->showForm( array('delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
                                return;
@@ -376,10 +373,7 @@ class MovePageForm extends UnlistedSpecialPage {
                        }
 
                        // This may output an error message and exit
-                       Action::factory( 'delete', $article )->execute(
-                               array( 'Reason' => wfMsgForContent( 'delete_and_move_reason' ) ),
-                               false // Do not capture exceptions
-                       );
+                       $article->doDelete( wfMsgForContent( 'delete_and_move_reason' ) );
                }
 
                # don't allow moving to pages with # in
index 5239e65..d00d960 100644 (file)
@@ -998,9 +998,8 @@ Please report this to an [[Special:ListUsers/sysop|administrator]], making note
 'unexpected'           => 'Unexpected value: "$1"="$2".',
 'formerror'            => 'Error: could not submit form',
 'badarticleerror'      => 'This action cannot be performed on this page.',
-'cannotdelete'         => 'The page or file "$1" could not be deleted.  It may have already been deleted by someone else.  The deletion log is provided below for convenience.
-
-$2',
+'cannotdelete'         => 'The page or file "$1" could not be deleted.
+It may have already been deleted by someone else.',
 'badtitle'             => 'Bad title',
 'badtitletext'         => 'The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title.
 It may contain one or more characters which cannot be used in titles.',
@@ -2784,7 +2783,7 @@ Feedback and further assistance:
 'delete-confirm'         => 'Delete "$1"',
 'delete-backlink'        => '← $1', # only translate this message to other languages if you have to change it
 'delete-legend'          => 'Delete',
-'historywarning'         => "'''Warning:''' The page you are about to delete has a $2 with approximately $1 {{PLURAL:$1|revision|revisions}}:",
+'historywarning'         => "'''Warning:''' The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:",
 'confirmdeletetext'      => 'You are about to delete a page along with all of its history.
 Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].',
 'actioncomplete'         => 'Action complete',