From c1f9b1f7b1b77776192048005dcc66dcf3df2bfb Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Sat, 27 Dec 2014 15:41:37 +0100 Subject: Update to MediaWiki 1.24.1 --- includes/actions/Action.php | 386 ++++++++++++++++++++++++++++++ includes/actions/CachedAction.php | 23 +- includes/actions/CreditsAction.php | 51 ++-- includes/actions/DeleteAction.php | 10 +- includes/actions/EditAction.php | 38 +-- includes/actions/FormAction.php | 123 ++++++++++ includes/actions/FormlessAction.php | 45 ++++ includes/actions/HistoryAction.php | 218 ++++++++++------- includes/actions/InfoAction.php | 97 +++++--- includes/actions/MarkpatrolledAction.php | 1 + includes/actions/ProtectAction.php | 29 +-- includes/actions/RawAction.php | 97 +++----- includes/actions/RenderAction.php | 3 - includes/actions/RevertAction.php | 61 ++--- includes/actions/RevisiondeleteAction.php | 1 + includes/actions/RollbackAction.php | 27 ++- includes/actions/SubmitAction.php | 42 ++++ includes/actions/UnprotectAction.php | 43 ++++ includes/actions/UnwatchAction.php | 57 +++++ includes/actions/ViewAction.php | 1 - includes/actions/WatchAction.php | 59 ++--- 21 files changed, 1074 insertions(+), 338 deletions(-) create mode 100644 includes/actions/Action.php create mode 100644 includes/actions/FormAction.php create mode 100644 includes/actions/FormlessAction.php create mode 100644 includes/actions/SubmitAction.php create mode 100644 includes/actions/UnprotectAction.php create mode 100644 includes/actions/UnwatchAction.php (limited to 'includes/actions') 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 @@ +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 \ page title + * + * @return string + */ + protected function getPageTitle() { + return $this->getTitle()->getPrefixedText(); + } + + /** + * Returns the description that goes below the \ 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 @@ 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 @@ +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 @@ +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( "
" . 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 ) . ' ' . + Xml::dateMenu( + ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ), + $month + ) . ' ' . ( $tagSelector ? ( implode( ' ', $tagSelector ) . ' ' ) : '' ) . $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( "
\n$1\n
", '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 = '
'; + $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 .= '
    ' . "\n"; + return $s; } private function getRevisionButton( $name, $msg ) { $this->preventClickjacking(); # Note bug #20966,