summaryrefslogtreecommitdiff
path: root/includes/actions
diff options
context:
space:
mode:
Diffstat (limited to 'includes/actions')
-rw-r--r--includes/actions/Action.php386
-rw-r--r--includes/actions/CachedAction.php23
-rw-r--r--includes/actions/CreditsAction.php51
-rw-r--r--includes/actions/DeleteAction.php10
-rw-r--r--includes/actions/EditAction.php38
-rw-r--r--includes/actions/FormAction.php123
-rw-r--r--includes/actions/FormlessAction.php45
-rw-r--r--includes/actions/HistoryAction.php218
-rw-r--r--includes/actions/InfoAction.php97
-rw-r--r--includes/actions/MarkpatrolledAction.php1
-rw-r--r--includes/actions/ProtectAction.php29
-rw-r--r--includes/actions/RawAction.php97
-rw-r--r--includes/actions/RenderAction.php3
-rw-r--r--includes/actions/RevertAction.php61
-rw-r--r--includes/actions/RevisiondeleteAction.php1
-rw-r--r--includes/actions/RollbackAction.php27
-rw-r--r--includes/actions/SubmitAction.php42
-rw-r--r--includes/actions/UnprotectAction.php43
-rw-r--r--includes/actions/UnwatchAction.php57
-rw-r--r--includes/actions/ViewAction.php1
-rw-r--r--includes/actions/WatchAction.php59
21 files changed, 1074 insertions, 338 deletions
diff --git a/includes/actions/Action.php b/includes/actions/Action.php
new file mode 100644
index 00000000..8d11d901
--- /dev/null
+++ b/includes/actions/Action.php
@@ -0,0 +1,386 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ */
+
+/**
+ * @defgroup Actions Action done on pages
+ */
+
+/**
+ * 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
+ *
+ * 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). The FormAction and FormlessAction classes represent these two groups.
+ */
+abstract class Action {
+
+ /**
+ * Page on which we're performing the action
+ * @since 1.17
+ * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
+ */
+ protected $page;
+
+ /**
+ * IContextSource if specified; otherwise we'll use the Context from the Page
+ * @since 1.17
+ * @var IContextSource $context
+ */
+ protected $context;
+
+ /**
+ * The fields used to create the HTMLForm
+ * @since 1.17
+ * @var array $fields
+ */
+ 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 string $action
+ * @param array $overrides
+ * @return bool|null|string|callable
+ */
+ final private static function getClass( $action, array $overrides ) {
+ global $wgActions;
+ $action = strtolower( $action );
+
+ if ( !isset( $wgActions[$action] ) ) {
+ return null;
+ }
+
+ if ( $wgActions[$action] === false ) {
+ return false;
+ } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
+ return $overrides[$action];
+ } elseif ( $wgActions[$action] === true ) {
+ return ucfirst( $action ) . 'Action';
+ } else {
+ return $wgActions[$action];
+ }
+ }
+
+ /**
+ * Get an appropriate Action subclass for the given action
+ * @since 1.17
+ * @param string $action
+ * @param Page $page
+ * @param IContextSource $context
+ * @return Action|bool|null False if the action is disabled, null
+ * if it is not recognised
+ */
+ final public static function factory( $action, Page $page, IContextSource $context = null ) {
+ $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
+
+ if ( is_string( $classOrCallable ) ) {
+ $obj = new $classOrCallable( $page, $context );
+ return $obj;
+ }
+
+ if ( is_callable( $classOrCallable ) ) {
+ return call_user_func_array( $classOrCallable, array( $page, $context ) );
+ }
+
+ return $classOrCallable;
+ }
+
+ /**
+ * Get the action that will be executed, not necessarily the one passed
+ * passed through the "action" request parameter. Actions disabled in
+ * $wgActions will be replaced by "nosuchaction".
+ *
+ * @since 1.19
+ * @param IContextSource $context
+ * @return string Action name
+ */
+ final public static function getActionName( IContextSource $context ) {
+ global $wgActions;
+
+ $request = $context->getRequest();
+ $actionName = $request->getVal( 'action', 'view' );
+
+ // Check for disabled actions
+ if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
+ $actionName = 'nosuchaction';
+ }
+
+ // Workaround for bug #20966: inability of IE to provide an action dependent
+ // on which submit button is clicked.
+ if ( $actionName === 'historysubmit' ) {
+ if ( $request->getBool( 'revisiondelete' ) ) {
+ $actionName = 'revisiondelete';
+ } else {
+ $actionName = 'view';
+ }
+ } elseif ( $actionName == 'editredlink' ) {
+ $actionName = 'edit';
+ }
+
+ // Trying to get a WikiPage for NS_SPECIAL etc. will result
+ // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
+ // For SpecialPages et al, default to action=view.
+ if ( !$context->canUseWikiPage() ) {
+ return 'view';
+ }
+
+ $action = Action::factory( $actionName, $context->getWikiPage(), $context );
+ if ( $action instanceof Action ) {
+ return $action->getName();
+ }
+
+ return 'nosuchaction';
+ }
+
+ /**
+ * Check if a given action is recognised, even if it's disabled
+ * @since 1.17
+ *
+ * @param string $name Name of an action
+ * @return bool
+ */
+ final public static function exists( $name ) {
+ return self::getClass( $name, array() ) !== null;
+ }
+
+ /**
+ * Get the IContextSource in use here
+ * @since 1.17
+ * @return IContextSource
+ */
+ final public function getContext() {
+ if ( $this->context instanceof IContextSource ) {
+ return $this->context;
+ } elseif ( $this->page instanceof Article ) {
+ // NOTE: $this->page can be a WikiPage, which does not have a context.
+ wfDebug( __METHOD__ . ": no context known, falling back to Article's context.\n" );
+ return $this->page->getContext();
+ }
+
+ wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
+ return RequestContext::getMain();
+ }
+
+ /**
+ * Get the WebRequest being used for this instance
+ * @since 1.17
+ *
+ * @return WebRequest
+ */
+ final public function getRequest() {
+ return $this->getContext()->getRequest();
+ }
+
+ /**
+ * Get the OutputPage being used for this instance
+ * @since 1.17
+ *
+ * @return OutputPage
+ */
+ final public function getOutput() {
+ return $this->getContext()->getOutput();
+ }
+
+ /**
+ * Shortcut to get the User being used for this instance
+ * @since 1.17
+ *
+ * @return User
+ */
+ final public function getUser() {
+ return $this->getContext()->getUser();
+ }
+
+ /**
+ * Shortcut to get the Skin being used for this instance
+ * @since 1.17
+ *
+ * @return Skin
+ */
+ final public function getSkin() {
+ return $this->getContext()->getSkin();
+ }
+
+ /**
+ * Shortcut to get the user Language being used for this instance
+ *
+ * @return Language
+ */
+ final public function getLanguage() {
+ return $this->getContext()->getLanguage();
+ }
+
+ /**
+ * Shortcut to get the Title object from the page
+ * @since 1.17
+ *
+ * @return Title
+ */
+ final public function getTitle() {
+ return $this->page->getTitle();
+ }
+
+ /**
+ * Get a Message object with context set
+ * Parameters are the same as wfMessage()
+ *
+ * @return Message
+ */
+ final public function msg() {
+ $params = func_get_args();
+ return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
+ }
+
+ /**
+ * Constructor.
+ *
+ * Only public since 1.21
+ *
+ * @param Page $page
+ * @param IContextSource $context
+ */
+ public function __construct( Page $page, IContextSource $context = null ) {
+ if ( $context === null ) {
+ wfWarn( __METHOD__ . ' called without providing a Context object.' );
+ // NOTE: We could try to initialize $context using $page->getContext(),
+ // if $page is an Article. That however seems to not work seamlessly.
+ }
+
+ $this->page = $page;
+ $this->context = $context;
+ }
+
+ /**
+ * Return the name of the action this object responds to
+ * @since 1.17
+ *
+ * @return string Lowercase name
+ */
+ abstract public function getName();
+
+ /**
+ * Get the permission required to perform this action. Often, but not always,
+ * the same as the action name
+ * @since 1.17
+ *
+ * @return string|null
+ */
+ public function getRestriction() {
+ return null;
+ }
+
+ /**
+ * 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
+ * @since 1.17
+ *
+ * @param User $user The user to check, or null to use the context user
+ * @throws UserBlockedError|ReadOnlyError|PermissionsError
+ */
+ protected function checkCanExecute( User $user ) {
+ $right = $this->getRestriction();
+ if ( $right !== null ) {
+ $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
+ if ( count( $errors ) ) {
+ throw new PermissionsError( $right, $errors );
+ }
+ }
+
+ if ( $this->requiresUnblock() && $user->isBlocked() ) {
+ $block = $user->getBlock();
+ throw new UserBlockedError( $block );
+ }
+
+ // This should be checked at the end so that the user won't think the
+ // error is only temporary when he also don't have the rights to execute
+ // this action
+ if ( $this->requiresWrite() && wfReadOnly() ) {
+ throw new ReadOnlyError();
+ }
+ }
+
+ /**
+ * Whether this action requires the wiki not to be locked
+ * @since 1.17
+ *
+ * @return bool
+ */
+ public function requiresWrite() {
+ return true;
+ }
+
+ /**
+ * Whether this action can still be executed by a blocked user
+ * @since 1.17
+ *
+ * @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.
+ * @since 1.17
+ */
+ protected function setHeaders() {
+ $out = $this->getOutput();
+ $out->setRobotPolicy( "noindex,nofollow" );
+ $out->setPageTitle( $this->getPageTitle() );
+ $out->setSubtitle( $this->getDescription() );
+ $out->setArticleRelated( true );
+ }
+
+ /**
+ * Returns the name that goes in the \<h1\> page title
+ *
+ * @return string
+ */
+ protected function getPageTitle() {
+ return $this->getTitle()->getPrefixedText();
+ }
+
+ /**
+ * Returns the description that goes below the \<h1\> tag
+ * @since 1.17
+ *
+ * @return string
+ */
+ protected function getDescription() {
+ return $this->msg( strtolower( $this->getName() ) )->escaped();
+ }
+
+ /**
+ * The main action entry point. Do all output for display and send it to the context
+ * output. Do not use globals $wgOut, $wgRequest, etc, in implementations; use
+ * $this->getOutput(), etc.
+ * @since 1.17
+ *
+ * @throws ErrorPageError
+ */
+ abstract public function show();
+}
diff --git a/includes/actions/CachedAction.php b/includes/actions/CachedAction.php
index bfdda7b9..bc4df349 100644
--- a/includes/actions/CachedAction.php
+++ b/includes/actions/CachedAction.php
@@ -58,7 +58,7 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
* If the cache is enabled or not.
*
* @since 1.20
- * @var boolean
+ * @var bool
*/
protected $cacheEnabled = true;
@@ -66,7 +66,7 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
* Sets if the cache should be enabled or not.
*
* @since 1.20
- * @param boolean $cacheEnabled
+ * @param bool $cacheEnabled
*/
public function setCacheEnabled( $cacheEnabled ) {
$this->cacheHelper->setCacheEnabled( $cacheEnabled );
@@ -78,8 +78,8 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
*
* @since 1.20
*
- * @param integer|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
- * @param boolean|null $cacheEnabled Sets if the cache should be enabled or not.
+ * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
+ * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
*/
public function startCache( $cacheExpiry = null, $cacheEnabled = null ) {
$this->cacheHelper = new CacheHelper();
@@ -110,7 +110,7 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
*
* @since 1.20
*
- * @param {function} $computeFunction
+ * @param callable $computeFunction
* @param array|mixed $args
* @param string|null $key
*
@@ -128,12 +128,13 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
*
* @since 1.20
*
- * @param {function} $computeFunction
+ * @param callable $computeFunction
* @param array $args
* @param string|null $key
*/
public function addCachedHTML( $computeFunction, $args = array(), $key = null ) {
- $this->getOutput()->addHTML( $this->cacheHelper->getCachedValue( $computeFunction, $args, $key ) );
+ $html = $this->cacheHelper->getCachedValue( $computeFunction, $args, $key );
+ $this->getOutput()->addHTML( $html );
}
/**
@@ -147,11 +148,12 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
}
/**
- * Sets the time to live for the cache, in seconds or a unix timestamp indicating the point of expiry.
+ * Sets the time to live for the cache, in seconds or a unix timestamp
+ * indicating the point of expiry.
*
* @since 1.20
*
- * @param integer $cacheExpiry
+ * @param int $cacheExpiry
*/
public function setExpiry( $cacheExpiry ) {
$this->cacheHelper->setExpiry( $cacheExpiry );
@@ -177,12 +179,11 @@ abstract class CachedAction extends FormlessAction implements ICacheHelper {
*
* @since 1.20
*
- * @param boolean $hasCached
+ * @param bool $hasCached
*/
public function onCacheInitialized( $hasCached ) {
if ( $hasCached ) {
$this->getOutput()->setSubtitle( $this->cacheHelper->getCachedNotice( $this->getContext() ) );
}
}
-
}
diff --git a/includes/actions/CreditsAction.php b/includes/actions/CreditsAction.php
index 0a2bf306..e064aab4 100644
--- a/includes/actions/CreditsAction.php
+++ b/includes/actions/CreditsAction.php
@@ -39,7 +39,7 @@ class CreditsAction extends FormlessAction {
/**
* This is largely cadged from PageHistory::history
*
- * @return String HTML
+ * @return string HTML
*/
public function onView() {
wfProfileIn( __METHOD__ );
@@ -58,9 +58,9 @@ class CreditsAction extends FormlessAction {
/**
* Get a list of contributors
*
- * @param int $cnt maximum list of contributors to show
- * @param bool $showIfMax whether to contributors if there more than $cnt
- * @return String: html
+ * @param int $cnt Maximum list of contributors to show
+ * @param bool $showIfMax Whether to contributors if there more than $cnt
+ * @return string Html
*/
public function getCredits( $cnt, $showIfMax = true ) {
wfProfileIn( __METHOD__ );
@@ -74,13 +74,14 @@ class CreditsAction extends FormlessAction {
}
wfProfileOut( __METHOD__ );
+
return $s;
}
/**
* Get the last author with the last modification time
* @param Page $page
- * @return String HTML
+ * @return string HTML
*/
protected function getAuthor( Page $page ) {
$user = User::newFromName( $page->getUserText(), false );
@@ -94,19 +95,29 @@ class CreditsAction extends FormlessAction {
$d = '';
$t = '';
}
+
return $this->msg( 'lastmodifiedatby', $d, $t )->rawParams(
$this->userLink( $user ) )->params( $user->getName() )->escaped();
}
/**
+ * Whether we can display the user's real name (not a hidden pref)
+ *
+ * @since 1.24
+ * @return bool
+ */
+ protected function canShowRealUserName() {
+ $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
+ return !in_array( 'realname', $hiddenPrefs );
+ }
+
+ /**
* Get a list of contributors of $article
- * @param int $cnt maximum list of contributors to show
- * @param bool $showIfMax whether to contributors if there more than $cnt
- * @return String: html
+ * @param int $cnt Maximum list of contributors to show
+ * @param bool $showIfMax Whether to contributors if there more than $cnt
+ * @return string Html
*/
protected function getContributors( $cnt, $showIfMax ) {
- global $wgHiddenPrefs;
-
$contributors = $this->page->getContributors();
$others_link = false;
@@ -125,11 +136,12 @@ class CreditsAction extends FormlessAction {
$anon_ips = array();
# Sift for real versus user names
+ /** @var $user User */
foreach ( $contributors as $user ) {
$cnt--;
if ( $user->isLoggedIn() ) {
$link = $this->link( $user );
- if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+ if ( $this->canShowRealUserName() && $user->getRealName() ) {
$real_names[] = $link;
} else {
$user_names[] = $link;
@@ -175,6 +187,7 @@ class CreditsAction extends FormlessAction {
}
$count = count( $fulllist );
+
# "Based on work by ..."
return $count
? $this->msg( 'othercontribs' )->rawParams(
@@ -184,12 +197,11 @@ class CreditsAction extends FormlessAction {
/**
* Get a link to $user's user page
- * @param $user User object
- * @return String: html
+ * @param User $user
+ * @return string Html
*/
protected function link( User $user ) {
- global $wgHiddenPrefs;
- if ( !in_array( 'realname', $wgHiddenPrefs ) && !$user->isAnon() ) {
+ if ( $this->canShowRealUserName() && !$user->isAnon() ) {
$real = $user->getRealName();
} else {
$real = false;
@@ -204,16 +216,15 @@ class CreditsAction extends FormlessAction {
/**
* Get a link to $user's user page
- * @param $user User object
- * @return String: html
+ * @param User $user
+ * @return string Html
*/
protected function userLink( User $user ) {
$link = $this->link( $user );
if ( $user->isAnon() ) {
return $this->msg( 'anonuser' )->rawParams( $link )->parse();
} else {
- global $wgHiddenPrefs;
- if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+ if ( $this->canShowRealUserName() && $user->getRealName() ) {
return $link;
} else {
return $this->msg( 'siteuser' )->rawParams( $link )->params( $user->getName() )->escaped();
@@ -223,7 +234,7 @@ class CreditsAction extends FormlessAction {
/**
* Get a link to action=credits of $article page
- * @return String: HTML link
+ * @return string HTML link
*/
protected function othersLink() {
return Linker::linkKnown(
diff --git a/includes/actions/DeleteAction.php b/includes/actions/DeleteAction.php
index db7123db..12f0dff0 100644
--- a/includes/actions/DeleteAction.php
+++ b/includes/actions/DeleteAction.php
@@ -41,9 +41,13 @@ class DeleteAction extends FormlessAction {
}
public function show() {
-
+ if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+ $out = $this->getOutput();
+ $out->addModuleStyles( array(
+ 'mediawiki.ui.input',
+ 'mediawiki.ui.checkbox',
+ ) );
+ }
$this->page->delete();
-
}
-
}
diff --git a/includes/actions/EditAction.php b/includes/actions/EditAction.php
index 3dd4c483..88767244 100644
--- a/includes/actions/EditAction.php
+++ b/includes/actions/EditAction.php
@@ -1,6 +1,6 @@
<?php
/**
- * action=edit / action=submit handler
+ * action=edit handler
*
* Copyright © 2012 Timo Tijhof
*
@@ -26,8 +26,7 @@
/**
* Page edition handler
*
- * This is a wrapper that will call the EditPage class, or ExternalEdit
- * if $wgUseExternalEditor is set to true and requested by the user.
+ * This is a wrapper that will call the EditPage class or a custom editor from an extension.
*
* @ingroup Actions
*/
@@ -42,6 +41,13 @@ class EditAction extends FormlessAction {
}
public function show() {
+ if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+ $out = $this->getOutput();
+ $out->addModuleStyles( array(
+ 'mediawiki.ui.input',
+ 'mediawiki.ui.checkbox',
+ ) );
+ }
$page = $this->page;
$user = $this->getUser();
@@ -49,31 +55,5 @@ class EditAction extends FormlessAction {
$editor = new EditPage( $page );
$editor->edit();
}
-
}
-
-}
-
-/**
- * Edit submission handler
- *
- * This is the same as EditAction; except that it sets the session cookie.
- *
- * @ingroup Actions
- */
-class SubmitAction extends EditAction {
-
- public function getName() {
- return 'submit';
- }
-
- public function show() {
- if ( session_id() == '' ) {
- // Send a cookie so anons get talk message notifications
- wfSetupSession();
- }
-
- parent::show();
- }
-
}
diff --git a/includes/actions/FormAction.php b/includes/actions/FormAction.php
new file mode 100644
index 00000000..4c9e85dd
--- /dev/null
+++ b/includes/actions/FormAction.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ */
+
+/**
+ * An action which shows a form and does something based on the input from the form
+ *
+ * @ingroup Actions
+ */
+abstract class FormAction extends Action {
+
+ /**
+ * Get an HTMLForm descriptor array
+ * @return array
+ */
+ abstract protected function getFormFields();
+
+ /**
+ * Add pre- or post-text to the form
+ * @return string HTML which will be sent to $form->addPreText()
+ */
+ protected function preText() {
+ return '';
+ }
+
+ /**
+ * @return string
+ */
+ protected function postText() {
+ return '';
+ }
+
+ /**
+ * Play with the HTMLForm if you need to more substantially
+ * @param HTMLForm $form
+ */
+ protected function alterForm( HTMLForm $form ) {
+ }
+
+ /**
+ * Get the HTMLForm to control behavior
+ * @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 ) );
+
+ $form = new HTMLForm( $this->fields, $this->getContext(), $this->getName() );
+ $form->setSubmitCallback( array( $this, 'onSubmit' ) );
+
+ // Retain query parameters (uselang etc)
+ $form->addHiddenField( 'action', $this->getName() ); // Might not be the same as the query string
+ $params = array_diff_key(
+ $this->getRequest()->getQueryValues(),
+ array( 'action' => null, 'title' => null )
+ );
+ $form->addHiddenField( 'redirectparams', wfArrayToCgi( $params ) );
+
+ $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 array $data
+ * @return bool|array True for success, false for didn't-try, array of errors on failure
+ */
+ abstract public 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).
+ */
+ abstract public function onSuccess();
+
+ /**
+ * 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
+ * behavior, 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->show() ) {
+ $this->onSuccess();
+ }
+ }
+}
diff --git a/includes/actions/FormlessAction.php b/includes/actions/FormlessAction.php
new file mode 100644
index 00000000..a6f1e295
--- /dev/null
+++ b/includes/actions/FormlessAction.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ */
+
+/**
+ * An action which just does something, without showing a form first.
+ *
+ * @ingroup Actions
+ */
+abstract class FormlessAction extends Action {
+
+ /**
+ * Show something on GET request.
+ * @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
+ */
+ abstract public function onView();
+
+ public function show() {
+ $this->setHeaders();
+
+ // This will throw exceptions if there's a problem
+ $this->checkCanExecute( $this->getUser() );
+
+ $this->getOutput()->addHTML( $this->onView() );
+ }
+}
diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php
index e58791ea..8522e560 100644
--- a/includes/actions/HistoryAction.php
+++ b/includes/actions/HistoryAction.php
@@ -37,6 +37,9 @@ class HistoryAction extends FormlessAction {
const DIR_PREV = 0;
const DIR_NEXT = 1;
+ /** @var array Array of message keys and strings */
+ public $message;
+
public function getName() {
return 'history';
}
@@ -89,8 +92,6 @@ class HistoryAction extends FormlessAction {
* Print the history page for an article.
*/
function onView() {
- global $wgScript, $wgUseFileCache;
-
$out = $this->getOutput();
$request = $this->getRequest();
@@ -104,10 +105,12 @@ class HistoryAction extends FormlessAction {
wfProfileIn( __METHOD__ );
$this->preCacheMessages();
+ $config = $this->context->getConfig();
# Fill in the file cache if not set already
- if ( $wgUseFileCache && HTMLFileCache::useFileCache( $this->getContext() ) ) {
- $cache = HTMLFileCache::newFromTitle( $this->getTitle(), 'history' );
+ $useFileCache = $config->get( 'UseFileCache' );
+ if ( $useFileCache && HTMLFileCache::useFileCache( $this->getContext() ) ) {
+ $cache = new HTMLFileCache( $this->getTitle(), 'history' );
if ( !$cache->isCacheGood( /* Assume up to date */ ) ) {
ob_start( array( &$cache, 'saveToFileCache' ) );
}
@@ -116,12 +119,20 @@ class HistoryAction extends FormlessAction {
// Setup page variables.
$out->setFeedAppendQuery( 'action=history' );
$out->addModules( 'mediawiki.action.history' );
+ if ( $config->get( 'UseMediaWikiUIEverywhere' ) ) {
+ $out = $this->getOutput();
+ $out->addModuleStyles( array(
+ 'mediawiki.ui.input',
+ 'mediawiki.ui.checkbox',
+ ) );
+ }
// Handle atom/RSS feeds.
$feedType = $request->getVal( 'feed' );
if ( $feedType ) {
$this->feed( $feedType );
wfProfileOut( __METHOD__ );
+
return;
}
@@ -141,6 +152,7 @@ class HistoryAction extends FormlessAction {
)
);
wfProfileOut( __METHOD__ );
+
return;
}
@@ -162,13 +174,13 @@ class HistoryAction extends FormlessAction {
}
if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
$checkDeleted = Xml::checkLabel( $this->msg( 'history-show-deleted' )->text(),
- 'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
+ 'deleted', 'mw-show-deleted-only', $request->getBool( 'deleted' ) ) . "\n";
} else {
$checkDeleted = '';
}
// Add the general form
- $action = htmlspecialchars( $wgScript );
+ $action = htmlspecialchars( wfScript() );
$out->addHTML(
"<form action=\"$action\" method=\"get\" id=\"mw-history-searchform\">" .
Xml::fieldset(
@@ -178,7 +190,10 @@ class HistoryAction extends FormlessAction {
) .
Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n" .
Html::hidden( 'action', 'history' ) . "\n" .
- Xml::dateMenu( ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ), $month ) . '&#160;' .
+ Xml::dateMenu(
+ ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ),
+ $month
+ ) . '&#160;' .
( $tagSelector ? ( implode( '&#160;', $tagSelector ) . '&#160;' ) : '' ) .
$checkDeleted .
Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" .
@@ -204,9 +219,9 @@ class HistoryAction extends FormlessAction {
* direction. This is now only used by the feeds. It was previously
* used by the main UI but that's now handled by the pager.
*
- * @param $limit Integer: the limit number of revisions to get
- * @param $offset Integer
- * @param $direction Integer: either HistoryPage::DIR_PREV or HistoryPage::DIR_NEXT
+ * @param int $limit The limit number of revisions to get
+ * @param int $offset
+ * @param int $direction Either self::DIR_PREV or self::DIR_NEXT
* @return ResultWrapper
*/
function fetchRevisions( $limit, $offset, $direction ) {
@@ -217,9 +232,9 @@ class HistoryAction extends FormlessAction {
$dbr = wfGetDB( DB_SLAVE );
- if ( $direction == HistoryPage::DIR_PREV ) {
+ if ( $direction === self::DIR_PREV ) {
list( $dirs, $oper ) = array( "ASC", ">=" );
- } else { /* $direction == HistoryPage::DIR_NEXT */
+ } else { /* $direction === self::DIR_NEXT */
list( $dirs, $oper ) = array( "DESC", "<=" );
}
@@ -243,16 +258,17 @@ class HistoryAction extends FormlessAction {
/**
* Output a subscription feed listing recent edits to this page.
*
- * @param string $type feed type
+ * @param string $type Feed type
*/
function feed( $type ) {
- global $wgFeedClasses, $wgFeedLimit;
if ( !FeedUtils::checkFeedOutput( $type ) ) {
return;
}
$request = $this->getRequest();
- $feed = new $wgFeedClasses[$type](
+ $feedClasses = $this->context->getConfig()->get( 'FeedClasses' );
+ /** @var RSSFeed|AtomFeed $feed */
+ $feed = new $feedClasses[$type](
$this->getTitle()->getPrefixedText() . ' - ' .
$this->msg( 'history-feed-title' )->inContentLanguage()->text(),
$this->msg( 'history-feed-description' )->inContentLanguage()->text(),
@@ -262,9 +278,12 @@ class HistoryAction extends FormlessAction {
// Get a limit on number of feed entries. Provide a sane default
// of 10 if none is defined (but limit to $wgFeedLimit max)
$limit = $request->getInt( 'limit', 10 );
- $limit = min( max( $limit, 1 ), $wgFeedLimit );
+ $limit = min(
+ max( $limit, 1 ),
+ $this->context->getConfig()->get( 'FeedLimit' )
+ );
- $items = $this->fetchRevisions( $limit, 0, HistoryPage::DIR_NEXT );
+ $items = $this->fetchRevisions( $limit, 0, self::DIR_NEXT );
// Generate feed elements enclosed between header and footer.
$feed->outHeader();
@@ -294,7 +313,7 @@ class HistoryAction extends FormlessAction {
* Borrows Recent Changes' feed generation functions for formatting;
* includes a diff to the previous revision (if any).
*
- * @param $row Object: database row
+ * @param stdClass|array $row Database row
* @return FeedItem
*/
function feedItem( $row ) {
@@ -316,9 +335,10 @@ class HistoryAction extends FormlessAction {
$wgContLang->time( $rev->getTimestamp() ) )->inContentLanguage()->text();
} else {
$title = $rev->getUserText() .
- $this->msg( 'colon-separator' )->inContentLanguage()->text() .
- FeedItem::stripComment( $rev->getComment() );
+ $this->msg( 'colon-separator' )->inContentLanguage()->text() .
+ FeedItem::stripComment( $rev->getComment() );
}
+
return new FeedItem(
$title,
$text,
@@ -335,14 +355,28 @@ class HistoryAction extends FormlessAction {
* @ingroup Actions
*/
class HistoryPager extends ReverseChronologicalPager {
- public $lastRow = false, $counter, $historyPage, $buttons, $conds;
+ /**
+ * @var bool|stdClass
+ */
+ public $lastRow = false;
+
+ public $counter, $historyPage, $buttons, $conds;
+
protected $oldIdChecked;
+
protected $preventClickjacking = false;
/**
* @var array
*/
protected $parentLens;
+ /**
+ * @param HistoryAction $historyPage
+ * @param string $year
+ * @param string $month
+ * @param string $tagFilter
+ * @param array $conds
+ */
function __construct( $historyPage, $year = '', $month = '', $tagFilter = '', $conds = array() ) {
parent::__construct( $historyPage->getContext() );
$this->historyPage = $historyPage;
@@ -383,6 +417,7 @@ class HistoryPager extends ReverseChronologicalPager {
$this->tagFilter
);
wfRunHooks( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
+
return $queryInfo;
}
@@ -390,6 +425,10 @@ class HistoryPager extends ReverseChronologicalPager {
return 'rev_timestamp';
}
+ /**
+ * @param stdClass $row
+ * @return string
+ */
function formatRow( $row ) {
if ( $this->lastRow ) {
$latest = ( $this->counter == 1 && $this->mIsFirst );
@@ -401,6 +440,7 @@ class HistoryPager extends ReverseChronologicalPager {
$s = '';
}
$this->lastRow = $row;
+
return $s;
}
@@ -432,21 +472,24 @@ class HistoryPager extends ReverseChronologicalPager {
* @return string HTML output
*/
function getStartBody() {
- global $wgScript;
$this->lastRow = false;
$this->counter = 1;
$this->oldIdChecked = 0;
$this->getOutput()->wrapWikiMsg( "<div class='mw-history-legend'>\n$1\n</div>", 'histlegend' );
- $s = Html::openElement( 'form', array( 'action' => $wgScript,
+ $s = Html::openElement( 'form', array( 'action' => wfScript(),
'id' => 'mw-history-compare' ) ) . "\n";
$s .= Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n";
$s .= Html::hidden( 'action', 'historysubmit' ) . "\n";
// Button container stored in $this->buttons for re-use in getEndBody()
$this->buttons = '<div>';
+ $className = 'historysubmit mw-history-compareselectedversions-button';
+ if ( $this->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+ $className .= ' mw-ui-button mw-ui-constructive';
+ }
$this->buttons .= $this->submitButton( $this->msg( 'compareselectedversions' )->text(),
- array( 'class' => 'historysubmit mw-history-compareselectedversions-button' )
+ array( 'class' => $className )
+ Linker::tooltipAndAccesskeyAttribs( 'compareselectedversions' )
) . "\n";
@@ -457,13 +500,15 @@ class HistoryPager extends ReverseChronologicalPager {
$s .= $this->buttons;
$s .= '<ul id="pagehistory">' . "\n";
+
return $s;
}
private function getRevisionButton( $name, $msg ) {
$this->preventClickjacking();
# Note bug #20966, <button> is non-standard in IE<8
- $element = Html::element( 'button',
+ $element = Html::element(
+ 'button',
array(
'type' => 'submit',
'name' => $name,
@@ -502,15 +547,16 @@ class HistoryPager extends ReverseChronologicalPager {
$s .= $this->buttons;
}
$s .= '</form>';
+
return $s;
}
/**
* Creates a submit button
*
- * @param string $message text of the submit button, will be escaped
- * @param array $attributes attributes
- * @return String: HTML output for the submit button
+ * @param string $message Text of the submit button, will be escaped
+ * @param array $attributes Attributes
+ * @return string HTML output for the submit button
*/
function submitButton( $message, $attributes = array() ) {
# Disable submit button if history has 1 revision only
@@ -526,16 +572,17 @@ class HistoryPager extends ReverseChronologicalPager {
*
* @todo document some more, and maybe clean up the code (some params redundant?)
*
- * @param $row Object: the database row corresponding to the previous line.
- * @param $next Mixed: the database row corresponding to the next line. (chronologically previous)
- * @param $notificationtimestamp
- * @param $latest Boolean: whether this row corresponds to the page's latest revision.
- * @param $firstInList Boolean: whether this row corresponds to the first displayed on this history page.
- * @return String: HTML output for the row
+ * @param stdClass $row The database row corresponding to the previous line.
+ * @param mixed $next The database row corresponding to the next line
+ * (chronologically previous)
+ * @param bool|string $notificationtimestamp
+ * @param bool $latest Whether this row corresponds to the page's latest revision.
+ * @param bool $firstInList Whether this row corresponds to the first
+ * displayed on this history page.
+ * @return string HTML output for the row
*/
function historyLine( $row, $next, $notificationtimestamp = false,
- $latest = false, $firstInList = false )
- {
+ $latest = false, $firstInList = false ) {
$rev = new Revision( $row );
$rev->setTitle( $this->getTitle() );
@@ -548,12 +595,14 @@ class HistoryPager extends ReverseChronologicalPager {
$curlink = $this->curLink( $rev, $latest );
$lastlink = $this->lastLink( $rev, $next );
- $diffButtons = $this->diffButtons( $rev, $firstInList );
+ $curLastlinks = $curlink . $this->historyPage->message['pipe-separator'] . $lastlink;
$histLinks = Html::rawElement(
- 'span',
- array( 'class' => 'mw-history-histlinks' ),
- $this->msg( 'parentheses' )->rawParams( $curlink . $this->historyPage->message['pipe-separator'] . $lastlink )->escaped()
+ 'span',
+ array( 'class' => 'mw-history-histlinks' ),
+ $this->msg( 'parentheses' )->rawParams( $curLastlinks )->escaped()
);
+
+ $diffButtons = $this->diffButtons( $rev, $firstInList );
$s = $histLinks . $diffButtons;
$link = $this->revLink( $rev );
@@ -627,7 +676,11 @@ class HistoryPager extends ReverseChronologicalPager {
if ( $prevRev && $this->getTitle()->quickUserCan( 'edit', $user ) ) {
if ( $latest && $this->getTitle()->quickUserCan( 'rollback', $user ) ) {
// Get a rollback link without the brackets
- $rollbackLink = Linker::generateRollback( $rev, $this->getContext(), array( 'verify', 'noBrackets' ) );
+ $rollbackLink = Linker::generateRollback(
+ $rev,
+ $this->getContext(),
+ array( 'verify', 'noBrackets' )
+ );
if ( $rollbackLink ) {
$this->preventClickjacking();
$tools[] = $rollbackLink;
@@ -635,8 +688,8 @@ class HistoryPager extends ReverseChronologicalPager {
}
if ( !$rev->isDeleted( Revision::DELETED_TEXT )
- && !$prevRev->isDeleted( Revision::DELETED_TEXT ) )
- {
+ && !$prevRev->isDeleted( Revision::DELETED_TEXT )
+ ) {
# Create undo tooltip for the first (=latest) line only
$undoTooltip = $latest
? array( 'title' => $this->msg( 'tooltip-undo' )->text() )
@@ -686,8 +739,8 @@ class HistoryPager extends ReverseChronologicalPager {
/**
* Create a link to view this revision of the page
*
- * @param $rev Revision
- * @return String
+ * @param Revision $rev
+ * @return string
*/
function revLink( $rev ) {
$date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $this->getUser() );
@@ -705,15 +758,16 @@ class HistoryPager extends ReverseChronologicalPager {
if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) {
$link = "<span class=\"history-deleted\">$link</span>";
}
+
return $link;
}
/**
* Create a diff-to-current link for this revision for this page
*
- * @param $rev Revision
- * @param $latest Boolean: this is the latest revision of the page?
- * @return String
+ * @param Revision $rev
+ * @param bool $latest This is the latest revision of the page?
+ * @return string
*/
function curLink( $rev, $latest ) {
$cur = $this->historyPage->message['cur'];
@@ -735,18 +789,21 @@ class HistoryPager extends ReverseChronologicalPager {
/**
* Create a diff-to-previous link for this revision for this page.
*
- * @param $prevRev Revision: the previous revision
- * @param $next Mixed: the newer revision
- * @return String
+ * @param Revision $prevRev The revision being displayed
+ * @param stdClass|string|null $next The next revision in list (that is
+ * the previous one in chronological order).
+ * May either be a row, "unknown" or null.
+ * @return string
*/
function lastLink( $prevRev, $next ) {
$last = $this->historyPage->message['last'];
- # $next may either be a Row, null, or "unkown"
- $nextRev = is_object( $next ) ? new Revision( $next ) : $next;
- if ( is_null( $next ) ) {
+
+ if ( $next === null ) {
# Probably no next row
return $last;
- } elseif ( $next === 'unknown' ) {
+ }
+
+ if ( $next === 'unknown' ) {
# Next row probably exists but is unknown, use an oldid=prev link
return Linker::linkKnown(
$this->getTitle(),
@@ -757,30 +814,34 @@ class HistoryPager extends ReverseChronologicalPager {
'oldid' => 'prev'
)
);
- } elseif ( !$prevRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
- || !$nextRev->userCan( Revision::DELETED_TEXT, $this->getUser() ) )
- {
+ }
+
+ $nextRev = new Revision( $next );
+
+ if ( !$prevRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+ || !$nextRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
+ ) {
return $last;
- } else {
- return Linker::linkKnown(
- $this->getTitle(),
- $last,
- array(),
- array(
- 'diff' => $prevRev->getId(),
- 'oldid' => $next->rev_id
- )
- );
}
+
+ return Linker::linkKnown(
+ $this->getTitle(),
+ $last,
+ array(),
+ array(
+ 'diff' => $prevRev->getId(),
+ 'oldid' => $next->rev_id
+ )
+ );
}
/**
* Create radio buttons for page history
*
- * @param $rev Revision object
- * @param $firstInList Boolean: is this version the first one?
+ * @param Revision $rev
+ * @param bool $firstInList Is this version the first one?
*
- * @return String: HTML output for the radio buttons
+ * @return string HTML output for the radio buttons
*/
function diffButtons( $rev, $firstInList ) {
if ( $this->getNumRows() > 1 ) {
@@ -816,6 +877,7 @@ class HistoryPager extends ReverseChronologicalPager {
array_merge( $radio, $checkmark, array(
'name' => 'diff',
'id' => "mw-diff-$id" ) ) );
+
return $first . $second;
} else {
return '';
@@ -824,6 +886,7 @@ class HistoryPager extends ReverseChronologicalPager {
/**
* This is called if a write operation is possible from the generated HTML
+ * @param bool $enable
*/
function preventClickjacking( $enable = true ) {
$this->preventClickjacking = $enable;
@@ -837,16 +900,3 @@ class HistoryPager extends ReverseChronologicalPager {
return $this->preventClickjacking;
}
}
-
-/**
- * Backwards-compatibility alias
- */
-class HistoryPage extends HistoryAction {
- public function __construct( Page $article ) { # Just to make it public
- parent::__construct( $article );
- }
-
- public function history() {
- $this->onView();
- }
-}
diff --git a/includes/actions/InfoAction.php b/includes/actions/InfoAction.php
index 0a16f4a8..f932a405 100644
--- a/includes/actions/InfoAction.php
+++ b/includes/actions/InfoAction.php
@@ -33,7 +33,7 @@ class InfoAction extends FormlessAction {
/**
* Returns the name of the action this object responds to.
*
- * @return string lowercase
+ * @return string Lowercase name
*/
public function getName() {
return 'info';
@@ -153,6 +153,7 @@ class InfoAction extends FormlessAction {
*/
protected function makeHeader( $header ) {
$spanAttribs = array( 'class' => 'mw-headline', 'id' => Sanitizer::escapeId( $header ) );
+
return Html::rawElement( 'h2', array(), Html::element( 'span', $spanAttribs, $header ) );
}
@@ -192,13 +193,13 @@ class InfoAction extends FormlessAction {
* @return array
*/
protected function pageInfo() {
- global $wgContLang, $wgRCMaxAge, $wgMemc,
- $wgUnwatchedPageThreshold, $wgPageInfoTransclusionLimit;
+ global $wgContLang, $wgMemc;
$user = $this->getUser();
$lang = $this->getLanguage();
$title = $this->getTitle();
$id = $title->getArticleID();
+ $config = $this->context->getConfig();
$memcKey = wfMemcKey( 'infoaction',
sha1( $title->getPrefixedText() ), $this->page->getLatest() );
@@ -206,7 +207,7 @@ class InfoAction extends FormlessAction {
$version = isset( $pageCounts['cacheversion'] ) ? $pageCounts['cacheversion'] : false;
if ( $pageCounts === false || $version !== self::CACHE_VERSION ) {
// Get page information that would be too "expensive" to retrieve by normal means
- $pageCounts = self::pageCounts( $title );
+ $pageCounts = $this->pageCounts( $title );
$pageCounts['cacheversion'] = self::CACHE_VERSION;
$wgMemc->set( $memcKey, $pageCounts );
@@ -274,15 +275,37 @@ class InfoAction extends FormlessAction {
// Language in which the page content is (supposed to be) written
$pageLang = $title->getPageLanguage()->getCode();
- $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-language' ),
+
+ if ( $config->get( 'PageLanguageUseDB' ) && $this->getTitle()->userCan( 'pagelang' ) ) {
+ // Link to Special:PageLanguage with pre-filled page title if user has permissions
+ $titleObj = SpecialPage::getTitleFor( 'PageLanguage', $title->getPrefixedText() );
+ $langDisp = Linker::link(
+ $titleObj,
+ $this->msg( 'pageinfo-language' )->escaped()
+ );
+ } else {
+ // Display just the message
+ $langDisp = $this->msg( 'pageinfo-language' )->escaped();
+ }
+
+ $pageInfo['header-basic'][] = array( $langDisp,
Language::fetchLanguageName( $pageLang, $lang->getCode() )
. ' ' . $this->msg( 'parentheses', $pageLang ) );
+ // Content model of the page
+ $pageInfo['header-basic'][] = array(
+ $this->msg( 'pageinfo-content-model' ),
+ ContentHandler::getLocalizedName( $title->getContentModel() )
+ );
+
// Search engine status
$pOutput = new ParserOutput();
if ( isset( $pageProperties['noindex'] ) ) {
$pOutput->setIndexPolicy( 'noindex' );
}
+ if ( isset( $pageProperties['index'] ) ) {
+ $pOutput->setIndexPolicy( 'index' );
+ }
// Use robot policy logic
$policy = $this->page->getRobotPolicy( 'view', $pOutput );
@@ -298,19 +321,20 @@ class InfoAction extends FormlessAction {
);
}
+ $unwatchedPageThreshold = $config->get( 'UnwatchedPageThreshold' );
if (
$user->isAllowed( 'unwatchedpages' ) ||
- ( $wgUnwatchedPageThreshold !== false &&
- $pageCounts['watchers'] >= $wgUnwatchedPageThreshold )
+ ( $unwatchedPageThreshold !== false &&
+ $pageCounts['watchers'] >= $unwatchedPageThreshold )
) {
// Number of page watchers
$pageInfo['header-basic'][] = array(
$this->msg( 'pageinfo-watchers' ), $lang->formatNum( $pageCounts['watchers'] )
);
- } elseif ( $wgUnwatchedPageThreshold !== false ) {
+ } elseif ( $unwatchedPageThreshold !== false ) {
$pageInfo['header-basic'][] = array(
$this->msg( 'pageinfo-watchers' ),
- $this->msg( 'pageinfo-few-watchers' )->numParams( $wgUnwatchedPageThreshold )
+ $this->msg( 'pageinfo-few-watchers' )->numParams( $unwatchedPageThreshold )
);
}
@@ -498,7 +522,7 @@ class InfoAction extends FormlessAction {
// Recent number of edits (within past 30 days)
$pageInfo['header-edits'][] = array(
- $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $wgRCMaxAge ) ),
+ $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $config->get( 'RCMaxAge' ) ) ),
$lang->formatNum( $pageCounts['recent_edits'] )
);
@@ -532,9 +556,13 @@ class InfoAction extends FormlessAction {
$pageCounts['transclusion']['from'] > 0 ||
$pageCounts['transclusion']['to'] > 0
) {
- $options = array( 'LIMIT' => $wgPageInfoTransclusionLimit );
+ $options = array( 'LIMIT' => $config->get( 'PageInfoTransclusionLimit' ) );
$transcludedTemplates = $title->getTemplateLinksFrom( $options );
- $transcludedTargets = $title->getTemplateLinksTo( $options );
+ if ( $config->get( 'MiserMode' ) ) {
+ $transcludedTargets = array();
+ } else {
+ $transcludedTargets = $title->getTemplateLinksTo( $options );
+ }
// Page properties
$pageInfo['header-properties'] = array();
@@ -575,7 +603,7 @@ class InfoAction extends FormlessAction {
);
}
- if ( $pageCounts['transclusion']['to'] > 0 ) {
+ if ( !$config->get( 'MiserMode' ) && $pageCounts['transclusion']['to'] > 0 ) {
if ( $pageCounts['transclusion']['to'] > count( $transcludedTargets ) ) {
$more = Linker::link(
$whatLinksHere,
@@ -608,16 +636,15 @@ class InfoAction extends FormlessAction {
* @param Title $title Title to get counts for
* @return array
*/
- protected static function pageCounts( Title $title ) {
- global $wgRCMaxAge, $wgDisableCounters;
-
+ protected function pageCounts( Title $title ) {
wfProfileIn( __METHOD__ );
$id = $title->getArticleID();
+ $config = $this->context->getConfig();
$dbr = wfGetDB( DB_SLAVE );
$result = array();
- if ( !$wgDisableCounters ) {
+ if ( !$config->get( 'DisableCounters' ) ) {
// Number of views
$views = (int)$dbr->selectField(
'page',
@@ -658,8 +685,8 @@ class InfoAction extends FormlessAction {
);
$result['authors'] = $authors;
- // "Recent" threshold defined by $wgRCMaxAge
- $threshold = $dbr->timestamp( time() - $wgRCMaxAge );
+ // "Recent" threshold defined by RCMaxAge setting
+ $threshold = $dbr->timestamp( time() - $config->get( 'RCMaxAge' ) );
// Recent number of edits
$edits = (int)$dbr->selectField(
@@ -713,15 +740,19 @@ class InfoAction extends FormlessAction {
}
// Counts for the number of transclusion links (to/from)
- $result['transclusion']['to'] = (int)$dbr->selectField(
- 'templatelinks',
- 'COUNT(tl_from)',
- array(
- 'tl_namespace' => $title->getNamespace(),
- 'tl_title' => $title->getDBkey()
- ),
- __METHOD__
- );
+ if ( $config->get( 'MiserMode' ) ) {
+ $result['transclusion']['to'] = 0;
+ } else {
+ $result['transclusion']['to'] = (int)$dbr->selectField(
+ 'templatelinks',
+ 'COUNT(tl_from)',
+ array(
+ 'tl_namespace' => $title->getNamespace(),
+ 'tl_title' => $title->getDBkey()
+ ),
+ __METHOD__
+ );
+ }
$result['transclusion']['from'] = (int)$dbr->selectField(
'templatelinks',
@@ -731,6 +762,7 @@ class InfoAction extends FormlessAction {
);
wfProfileOut( __METHOD__ );
+
return $result;
}
@@ -745,25 +777,25 @@ class InfoAction extends FormlessAction {
/**
* Get a list of contributors of $article
- * @return string: html
+ * @return string Html
*/
protected function getContributors() {
- global $wgHiddenPrefs;
-
$contributors = $this->page->getContributors();
$real_names = array();
$user_names = array();
$anon_ips = array();
# Sift for real versus user names
+ /** @var $user User */
foreach ( $contributors as $user ) {
$page = $user->isAnon()
? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
: $user->getUserPage();
+ $hiddenPrefs = $this->context->getConfig()->get( 'HiddenPrefs' );
if ( $user->getID() == 0 ) {
$anon_ips[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
- } elseif ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
+ } elseif ( !in_array( 'realname', $hiddenPrefs ) && $user->getRealName() ) {
$real_names[] = Linker::link( $page, htmlspecialchars( $user->getRealName() ) );
} else {
$user_names[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
@@ -798,6 +830,7 @@ class InfoAction extends FormlessAction {
}
$count = count( $fulllist );
+
# "Based on work by ..."
return $count
? $this->msg( 'othercontribs' )->rawParams(
diff --git a/includes/actions/MarkpatrolledAction.php b/includes/actions/MarkpatrolledAction.php
index ff6cf13a..4016f672 100644
--- a/includes/actions/MarkpatrolledAction.php
+++ b/includes/actions/MarkpatrolledAction.php
@@ -70,6 +70,7 @@ class MarkpatrolledAction extends FormlessAction {
$this->getOutput()->setPageTitle( $this->msg( 'markedaspatrollederror' ) );
$this->getOutput()->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
$this->getOutput()->returnToMain( null, $return );
+
return;
}
diff --git a/includes/actions/ProtectAction.php b/includes/actions/ProtectAction.php
index ec6648e2..a7f1ac34 100644
--- a/includes/actions/ProtectAction.php
+++ b/includes/actions/ProtectAction.php
@@ -41,30 +41,15 @@ class ProtectAction extends FormlessAction {
}
public function show() {
+ if ( $this->getContext()->getConfig()->get( 'UseMediaWikiUIEverywhere' ) ) {
+ $out = $this->getOutput();
+ $out->addModuleStyles( array(
+ 'mediawiki.ui.input',
+ 'mediawiki.ui.checkbox',
+ ) );
+ }
$this->page->protect();
-
}
-
}
-/**
- * Handle page unprotection
- *
- * This is a wrapper that will call Article::unprotect().
- *
- * @ingroup Actions
- */
-class UnprotectAction extends ProtectAction {
-
- public function getName() {
- return 'unprotect';
- }
-
- public function show() {
-
- $this->page->unprotect();
-
- }
-
-}
diff --git a/includes/actions/RawAction.php b/includes/actions/RawAction.php
index 1a2b3cb1..d0d956ec 100644
--- a/includes/actions/RawAction.php
+++ b/includes/actions/RawAction.php
@@ -5,7 +5,7 @@
* Copyright © 2004 Gabriel Wicke <wicke@wikidev.net>
* http://wikidev.net/
*
- * Based on HistoryPage and SpecialExport
+ * Based on HistoryAction and SpecialExport
*
* 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
@@ -33,7 +33,13 @@
* @ingroup Actions
*/
class RawAction extends FormlessAction {
- private $mGen;
+ /**
+ * @var bool Does the request include a gen=css|javascript parameter
+ * @deprecated This used to be a string for "css" or "javascript" but
+ * it is no longer used. Setting this parameter results in empty content
+ * being served
+ */
+ private $gen = false;
public function getName() {
return 'raw';
@@ -48,10 +54,9 @@ class RawAction extends FormlessAction {
}
function onView() {
- global $wgSquidMaxage, $wgForcedRawSMaxage;
-
$this->getOutput()->disable();
$request = $this->getRequest();
+ $config = $this->context->getConfig();
if ( !$request->checkUrlExtension() ) {
return;
@@ -67,26 +72,25 @@ class RawAction extends FormlessAction {
$smaxage = $request->getIntOrNull( 'smaxage' );
if ( $gen == 'css' || $gen == 'js' ) {
- $this->mGen = $gen;
+ $this->gen = true;
if ( $smaxage === null ) {
- $smaxage = $wgSquidMaxage;
+ $smaxage = $config->get( 'SquidMaxage' );
}
- } else {
- $this->mGen = false;
}
$contentType = $this->getContentType();
- # Force caching for CSS and JS raw content, default: 5 minutes
+ # Force caching for CSS and JS raw content, default: 5 minutes.
+ # Note: If using a canonical url for userpage css/js, we send an HTCP purge.
if ( $smaxage === null ) {
if ( $contentType == 'text/css' || $contentType == 'text/javascript' ) {
- $smaxage = intval( $wgForcedRawSMaxage );
+ $smaxage = intval( $config->get( 'ForcedRawSMaxage' ) );
} else {
$smaxage = 0;
}
}
- $maxage = $request->getInt( 'maxage', $wgSquidMaxage );
+ $maxage = $request->getInt( 'maxage', $config->get( 'SquidMaxage' ) );
$response = $request->response();
@@ -99,7 +103,9 @@ class RawAction extends FormlessAction {
$privateCache = $privateCache ?: $this->getUser()->isLoggedIn();
# allow the client to cache this for 24 hours
$mode = $privateCache ? 'private' : 'public';
- $response->header( 'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage );
+ $response->header(
+ 'Cache-Control: ' . $mode . ', s-maxage=' . $smaxage . ', max-age=' . $maxage
+ );
$text = $this->getRawText();
@@ -122,13 +128,13 @@ class RawAction extends FormlessAction {
* Get the text that should be returned, or false if the page or revision
* was not found.
*
- * @return String|Bool
+ * @return string|bool
*/
public function getRawText() {
global $wgParser;
# No longer used
- if ( $this->mGen ) {
+ if ( $this->gen ) {
return '';
}
@@ -138,8 +144,9 @@ class RawAction extends FormlessAction {
// If it's a MediaWiki message we can just hit the message cache
if ( $request->getBool( 'usemsgcache' ) && $title->getNamespace() == NS_MEDIAWIKI ) {
- // The first "true" is to use the database, the second is to use the content langue
- // and the last one is to specify the message key already contains the language in it ("/de", etc.)
+ // The first "true" is to use the database, the second is to use
+ // the content langue and the last one is to specify the message
+ // key already contains the language in it ("/de", etc.).
$text = MessageCache::singleton()->get( $title->getDBkey(), true, true, true );
// If the message doesn't exist, return a blank
if ( $text === false ) {
@@ -161,7 +168,7 @@ class RawAction extends FormlessAction {
} elseif ( !$content instanceof TextContent ) {
// non-text content
wfHttpError( 415, "Unsupported Media Type", "The requested page uses the content model `"
- . $content->getModel() . "` which is not supported via this interface." );
+ . $content->getModel() . "` which is not supported via this interface." );
die();
} else {
// want a section?
@@ -181,7 +188,11 @@ class RawAction extends FormlessAction {
}
if ( $text !== false && $text !== '' && $request->getVal( 'templates' ) === 'expand' ) {
- $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
+ $text = $wgParser->preprocess(
+ $text,
+ $title,
+ ParserOptions::newFromContext( $this->getContext() )
+ );
}
return $text;
@@ -190,17 +201,18 @@ class RawAction extends FormlessAction {
/**
* Get the ID of the revision that should used to get the text.
*
- * @return Integer
+ * @return int
*/
public function getOldId() {
$oldid = $this->getRequest()->getInt( 'oldid' );
switch ( $this->getRequest()->getText( 'direction' ) ) {
case 'next':
# output next revision, or nothing if there isn't one
+ $nextid = 0;
if ( $oldid ) {
- $oldid = $this->getTitle()->getNextRevisionID( $oldid );
+ $nextid = $this->getTitle()->getNextRevisionID( $oldid );
}
- $oldid = $oldid ? $oldid : -1;
+ $oldid = $nextid ?: -1;
break;
case 'prev':
# output previous revision, or nothing if there isn't one
@@ -208,20 +220,21 @@ class RawAction extends FormlessAction {
# get the current revision so we can get the penultimate one
$oldid = $this->page->getLatest();
}
- $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
- $oldid = $prev ? $prev : -1;
+ $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
+ $oldid = $previd ?: -1;
break;
case 'cur':
$oldid = 0;
break;
}
+
return $oldid;
}
/**
* Get the content type to use for the response
*
- * @return String
+ * @return string
*/
public function getContentType() {
$ctype = $this->getRequest()->getVal( 'ctype' );
@@ -243,39 +256,3 @@ class RawAction extends FormlessAction {
return $ctype;
}
}
-
-/**
- * Backward compatibility for extensions
- *
- * @deprecated in 1.19
- */
-class RawPage extends RawAction {
- public $mOldId;
-
- /**
- * @param Page $page
- * @param WebRequest|bool $request The WebRequest (default: false).
- */
- function __construct( Page $page, $request = false ) {
- wfDeprecated( __CLASS__, '1.19' );
- parent::__construct( $page );
-
- if ( $request !== false ) {
- $context = new DerivativeContext( $this->getContext() );
- $context->setRequest( $request );
- $this->context = $context;
- }
- }
-
- public function view() {
- $this->onView();
- }
-
- public function getOldId() {
- # Some extensions like to set $mOldId
- if ( $this->mOldId !== null ) {
- return $this->mOldId;
- }
- return parent::getOldId();
- }
-}
diff --git a/includes/actions/RenderAction.php b/includes/actions/RenderAction.php
index 3d244fb3..16e407f4 100644
--- a/includes/actions/RenderAction.php
+++ b/includes/actions/RenderAction.php
@@ -41,9 +41,6 @@ class RenderAction extends FormlessAction {
}
public function show() {
-
$this->page->render();
-
}
-
}
diff --git a/includes/actions/RevertAction.php b/includes/actions/RevertAction.php
index a5fc4e17..6481630e 100644
--- a/includes/actions/RevertAction.php
+++ b/includes/actions/RevertAction.php
@@ -24,29 +24,14 @@
*/
/**
- * Dummy class for pages not in NS_FILE
- *
- * @ingroup Actions
- */
-class RevertAction extends Action {
-
- public function getName() {
- return 'revert';
- }
-
- public function show() {
- $this->getOutput()->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
- }
-
- public function execute() {}
-}
-
-/**
- * Class for pages in NS_FILE
+ * File reversion user interface
*
* @ingroup Actions
*/
-class RevertFileAction extends FormAction {
+class RevertAction extends FormAction {
+ /**
+ * @var OldLocalFile
+ */
protected $oldFile;
public function getName() {
@@ -58,17 +43,24 @@ class RevertFileAction extends FormAction {
}
protected function checkCanExecute( User $user ) {
+ if ( $this->getTitle()->getNamespace() !== NS_FILE ) {
+ throw new ErrorPageError( $this->msg( 'nosuchaction' ), $this->msg( 'nosuchactiontext' ) );
+ }
parent::checkCanExecute( $user );
$oldimage = $this->getRequest()->getText( 'oldimage' );
if ( strlen( $oldimage ) < 16
|| strpos( $oldimage, '/' ) !== false
- || strpos( $oldimage, '\\' ) !== false )
- {
+ || strpos( $oldimage, '\\' ) !== false
+ ) {
throw new ErrorPageError( 'internalerror', 'unexpected', array( 'oldimage', $oldimage ) );
}
- $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->getTitle(), $oldimage );
+ $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName(
+ $this->getTitle(),
+ $oldimage
+ );
+
if ( !$this->oldFile->exists() ) {
throw new ErrorPageError( '', 'filerevert-badversion' );
}
@@ -78,6 +70,7 @@ class RevertFileAction extends FormAction {
$form->setWrapperLegendMsg( 'filerevert-legend' );
$form->setSubmitTextMsg( 'filerevert-submit' );
$form->addHiddenField( 'oldimage', $this->getRequest()->getText( 'oldimage' ) );
+ $form->setTokenSalt( array( 'revert', $this->getTitle()->getPrefixedDBkey() ) );
}
protected function getFormFields() {
@@ -99,8 +92,10 @@ class RevertFileAction extends FormAction {
'raw' => true,
'default' => $this->msg( 'filerevert-intro',
$this->getTitle()->getText(), $userDate, $userTime,
- wfExpandUrl( $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ),
- PROTO_CURRENT ) )->parseAsBlock()
+ wfExpandUrl(
+ $this->page->getFile()->getArchiveUrl( $this->getRequest()->getText( 'oldimage' ) ),
+ PROTO_CURRENT
+ ) )->parseAsBlock()
),
'comment' => array(
'type' => 'text',
@@ -112,10 +107,21 @@ class RevertFileAction extends FormAction {
}
public function onSubmit( $data ) {
- $source = $this->page->getFile()->getArchiveVirtualUrl( $this->getRequest()->getText( 'oldimage' ) );
+ $source = $this->page->getFile()->getArchiveVirtualUrl(
+ $this->getRequest()->getText( 'oldimage' )
+ );
$comment = $data['comment'];
+
// TODO: Preserve file properties from database instead of reloading from file
- return $this->page->getFile()->upload( $source, $comment, $comment, 0, false, false, $this->getUser() );
+ return $this->page->getFile()->upload(
+ $source,
+ $comment,
+ $comment,
+ 0,
+ false,
+ false,
+ $this->getUser()
+ );
}
public function onSuccess() {
@@ -139,6 +145,7 @@ class RevertFileAction extends FormAction {
protected function getDescription() {
$this->getOutput()->addBacklinkSubtitle( $this->getTitle() );
+
return '';
}
}
diff --git a/includes/actions/RevisiondeleteAction.php b/includes/actions/RevisiondeleteAction.php
index 2949fa95..b6eeb7b4 100644
--- a/includes/actions/RevisiondeleteAction.php
+++ b/includes/actions/RevisiondeleteAction.php
@@ -49,6 +49,7 @@ class RevisiondeleteAction extends FormlessAction {
public function show() {
$special = SpecialPageFactory::getPage( 'Revisiondelete' );
$special->setContext( $this->getContext() );
+ $special->getContext()->setTitle( $special->getPageTitle() );
$special->run( '' );
}
}
diff --git a/includes/actions/RollbackAction.php b/includes/actions/RollbackAction.php
index 81bad9da..76d70d70 100644
--- a/includes/actions/RollbackAction.php
+++ b/includes/actions/RollbackAction.php
@@ -39,6 +39,7 @@ class RollbackAction extends FormlessAction {
$details = null;
$request = $this->getRequest();
+ $user = $this->getUser();
$result = $this->page->doRollback(
$request->getVal( 'from' ),
@@ -53,13 +54,16 @@ class RollbackAction extends FormlessAction {
throw new ThrottledError;
}
- if ( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) {
+ if ( isset( $result[0][0] ) &&
+ ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' )
+ ) {
$this->getOutput()->setPageTitle( $this->msg( 'rollbackfailed' ) );
$errArray = $result[0];
$errMsg = array_shift( $errArray );
$this->getOutput()->addWikiMsgArray( $errMsg, $errArray );
if ( isset( $details['current'] ) ) {
+ /** @var Revision $current */
$current = $details['current'];
if ( $current->getComment() != '' ) {
@@ -83,6 +87,7 @@ class RollbackAction extends FormlessAction {
throw new ErrorPageError( 'rollbackfailed', $error[0], array_slice( $error, 1 ) );
}
+ /** @var Revision $current */
$current = $details['current'];
$target = $details['target'];
$newId = $details['newid'];
@@ -91,12 +96,26 @@ class RollbackAction extends FormlessAction {
$old = Linker::revUserTools( $current );
$new = Linker::revUserTools( $target );
- $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )->parseAsBlock() );
+ $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )
+ ->parseAsBlock() );
+
+ if ( $user->getBoolOption( 'watchrollback' ) ) {
+ $user->addWatch( $this->page->getTitle(), WatchedItem::IGNORE_USER_RIGHTS );
+ }
+
$this->getOutput()->returnToMain( false, $this->getTitle() );
- if ( !$request->getBool( 'hidediff', false ) && !$this->getUser()->getBoolOption( 'norollbackdiff', false ) ) {
+ if ( !$request->getBool( 'hidediff', false ) &&
+ !$this->getUser()->getBoolOption( 'norollbackdiff', false )
+ ) {
$contentHandler = $current->getContentHandler();
- $de = $contentHandler->createDifferenceEngine( $this->getContext(), $current->getId(), $newId, false, true );
+ $de = $contentHandler->createDifferenceEngine(
+ $this->getContext(),
+ $current->getId(),
+ $newId,
+ false,
+ true
+ );
$de->showDiff( '', '' );
}
}
diff --git a/includes/actions/SubmitAction.php b/includes/actions/SubmitAction.php
new file mode 100644
index 00000000..fae49f61
--- /dev/null
+++ b/includes/actions/SubmitAction.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Wrapper for EditAction; sets the session cookie.
+ *
+ * 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
+ */
+
+/**
+ * This is the same as EditAction; except that it sets the session cookie.
+ *
+ * @ingroup Actions
+ */
+class SubmitAction extends EditAction {
+
+ public function getName() {
+ return 'submit';
+ }
+
+ public function show() {
+ if ( session_id() === '' ) {
+ // Send a cookie so anons get talk message notifications
+ wfSetupSession();
+ }
+
+ parent::show();
+ }
+}
diff --git a/includes/actions/UnprotectAction.php b/includes/actions/UnprotectAction.php
new file mode 100644
index 00000000..bc28c8ed
--- /dev/null
+++ b/includes/actions/UnprotectAction.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * action=unprotect handler
+ *
+ * Copyright © 2012 Timo Tijhof
+ *
+ * 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 Timo Tijhof
+ */
+
+/**
+ * Handle page unprotection
+ *
+ * This is a wrapper that will call Article::unprotect().
+ *
+ * @ingroup Actions
+ */
+class UnprotectAction extends ProtectAction {
+
+ public function getName() {
+ return 'unprotect';
+ }
+
+ public function show() {
+
+ $this->page->unprotect();
+ }
+}
diff --git a/includes/actions/UnwatchAction.php b/includes/actions/UnwatchAction.php
new file mode 100644
index 00000000..e2e5a1d8
--- /dev/null
+++ b/includes/actions/UnwatchAction.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Performs the 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
+ */
+
+/**
+ * Page removal from a user's watchlist
+ *
+ * @ingroup Actions
+ */
+class UnwatchAction extends WatchAction {
+
+ public function getName() {
+ return 'unwatch';
+ }
+
+ protected function getDescription() {
+ return $this->msg( 'removewatch' )->escaped();
+ }
+
+ public function onSubmit( $data ) {
+ wfProfileIn( __METHOD__ );
+ self::doUnwatch( $this->getTitle(), $this->getUser() );
+ wfProfileOut( __METHOD__ );
+
+ return true;
+ }
+
+ protected function alterForm( HTMLForm $form ) {
+ $form->setSubmitTextMsg( 'confirm-unwatch-button' );
+ }
+
+ protected function preText() {
+ return $this->msg( 'confirm-unwatch-top' )->parse();
+ }
+
+ public function onSuccess() {
+ $this->getOutput()->addWikiMsg( 'removedwatchtext', $this->getTitle()->getPrefixedText() );
+ }
+}
diff --git a/includes/actions/ViewAction.php b/includes/actions/ViewAction.php
index e227197d..3a24565c 100644
--- a/includes/actions/ViewAction.php
+++ b/includes/actions/ViewAction.php
@@ -43,5 +43,4 @@ class ViewAction extends FormlessAction {
public function show() {
$this->page->view();
}
-
}
diff --git a/includes/actions/WatchAction.php b/includes/actions/WatchAction.php
index 929c1b5f..8c9a46a5 100644
--- a/includes/actions/WatchAction.php
+++ b/includes/actions/WatchAction.php
@@ -1,6 +1,6 @@
<?php
/**
- * Performs the watch and unwatch actions on a page
+ * Performs the watch 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
@@ -51,6 +51,7 @@ class WatchAction extends FormAction {
wfProfileIn( __METHOD__ );
self::doWatch( $this->getTitle(), $this->getUser() );
wfProfileOut( __METHOD__ );
+
return true;
}
@@ -81,10 +82,10 @@ class WatchAction extends FormAction {
protected function checkCanExecute( User $user ) {
// Must be logged in
if ( $user->isAnon() ) {
- throw new ErrorPageError( 'watchnologin', 'watchnologintext' );
+ throw new UserNotLoggedIn( 'watchlistanontext', 'watchnologin' );
}
- return parent::checkCanExecute( $user );
+ parent::checkCanExecute( $user );
}
/**
@@ -96,7 +97,9 @@ class WatchAction extends FormAction {
* @return Status
*/
public static function doWatchOrUnwatch( $watch, Title $title, User $user ) {
- if ( $user->isLoggedIn() && $user->isWatched( $title, WatchedItem::IGNORE_USER_RIGHTS ) != $watch ) {
+ if ( $user->isLoggedIn() &&
+ $user->isWatched( $title, WatchedItem::IGNORE_USER_RIGHTS ) != $watch
+ ) {
// If the user doesn't have 'editmywatchlist', we still want to
// allow them to add but not remove items via edits and such.
if ( $watch ) {
@@ -105,6 +108,7 @@ class WatchAction extends FormAction {
return self::doUnwatch( $title, $user );
}
}
+
return Status::newGood();
}
@@ -116,8 +120,12 @@ class WatchAction extends FormAction {
* @param int $checkRights Passed through to $user->addWatch()
* @return Status
*/
- public static function doWatch( Title $title, User $user, $checkRights = WatchedItem::CHECK_USER_RIGHTS ) {
- if ( $checkRights !== WatchedItem::IGNORE_USER_RIGHTS && !$user->isAllowed( 'editmywatchlist' ) ) {
+ public static function doWatch( Title $title, User $user,
+ $checkRights = WatchedItem::CHECK_USER_RIGHTS
+ ) {
+ if ( $checkRights !== WatchedItem::IGNORE_USER_RIGHTS &&
+ !$user->isAllowed( 'editmywatchlist' )
+ ) {
return User::newFatalPermissionDeniedStatus( 'editmywatchlist' );
}
@@ -129,6 +137,7 @@ class WatchAction extends FormAction {
$user->addWatch( $title, $checkRights );
wfRunHooks( 'WatchArticleComplete', array( &$user, &$page ) );
}
+
return $status;
}
@@ -152,6 +161,7 @@ class WatchAction extends FormAction {
$user->removeWatch( $title );
wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$page ) );
}
+
return $status;
}
@@ -168,7 +178,7 @@ class WatchAction extends FormAction {
if ( $action != 'unwatch' ) {
$action = 'watch';
}
- $salt = array( $action, $title->getDBkey() );
+ $salt = array( $action, $title->getPrefixedDBkey() );
// This token stronger salted and not compatible with ApiWatch
// It's title/action specific because index.php is GET and API is POST
@@ -200,38 +210,3 @@ class WatchAction extends FormAction {
$this->getOutput()->addWikiMsg( 'addedwatchtext', $this->getTitle()->getPrefixedText() );
}
}
-
-/**
- * Page removal from a user's watchlist
- *
- * @ingroup Actions
- */
-class UnwatchAction extends WatchAction {
-
- public function getName() {
- return 'unwatch';
- }
-
- protected function getDescription() {
- return $this->msg( 'removewatch' )->escaped();
- }
-
- public function onSubmit( $data ) {
- wfProfileIn( __METHOD__ );
- self::doUnwatch( $this->getTitle(), $this->getUser() );
- wfProfileOut( __METHOD__ );
- return true;
- }
-
- protected function alterForm( HTMLForm $form ) {
- $form->setSubmitTextMsg( 'confirm-unwatch-button' );
- }
-
- protected function preText() {
- return $this->msg( 'confirm-unwatch-top' )->parse();
- }
-
- public function onSuccess() {
- $this->getOutput()->addWikiMsg( 'removedwatchtext', $this->getTitle()->getPrefixedText() );
- }
-}