*/
/**
- * @var RequestContext
+ * @var IContextSource
*/
protected $mContext;
* Create an Article object of the appropriate class for the given page.
*
* @param $title Title
- * @param $context RequestContext
+ * @param $context IContextSource
* @return Article object
*/
- public static function newFromTitle( $title, RequestContext $context ) {
+ public static function newFromTitle( $title, IContextSource $context ) {
if ( NS_MEDIA == $title->getNamespace() ) {
// FIXME: where should this go?
$title = Title::makeTitle( NS_FILE, $title->getDBkey() );
$this->mRedirectedFrom = $from;
}
- /**
- * Get the Title object this text redirects to
- *
- * @param $text string article content containing redirect info
- * @return mixed false, Title of in-wiki target, or string with URL
- * @deprecated since 1.17
- */
- public function followRedirectText( $text ) {
- // recurse through to only get the final target
- return $this->getRedirectURL( Title::newFromRedirectRecurse( $text ) );
- }
-
/**
* Get the title object of the article
* @return Title object of this page
if ( $oldid ) {
$revision = Revision::newFromId( $oldid );
- if ( $revision === null ) {
+ if ( !$revision ) {
wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
return false;
}
}
}
} else {
- if ( $this->mPage->getLatest() === false ) {
+ if ( !$this->mPage->getLatest() ) {
wfDebug( __METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n" );
return false;
}
$revision = $this->mPage->getRevision();
- if ( $revision === null ) {
+ if ( !$revision ) {
wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" );
return false;
}
return;
}
- $wgOut->setArticleFlag( true );
# Set page title (may be overridden by DISPLAYTITLE)
$wgOut->setPageTitle( $this->getTitle()->getPrefixedText() );
return;
}
+ $wgOut->setArticleFlag( true );
# Allow frames by default
$wgOut->allowClickjacking();
wfDebug( __METHOD__ . ": showing CSS/JS source\n" );
$this->showCssOrJsPage();
$outputDone = true;
+ } elseif( !wfRunHooks( 'ArticleViewCustom', array( $this->mContent, $this->getTitle(), $wgOut ) ) ) {
+ # Allow extensions do their own custom view for certain pages
+ $outputDone = true;
} else {
$rt = Title::newFromRedirectArray( $text );
if ( $rt ) {
# tents of 'pagetitle-view-mainpage' instead of the default (if
# that's not empty).
# This message always exists because it is in the i18n files
- if ( $this->getTitle()->equals( Title::newMainPage() ) ) {
+ if ( $this->getTitle()->isMainPage() ) {
$msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage();
if ( !$msg->isDisabled() ) {
$wgOut->setHTMLTitle( $msg->title( $this->getTitle() )->text() );
protected function showCssOrJsPage() {
global $wgOut;
- $wgOut->wrapWikiMsg( "<div id='mw-clearyourcache'>\n$1\n</div>", 'clearyourcache' );
+ $dir = $this->getContext()->getLang()->getDir();
+ $lang = $this->getContext()->getLang()->getCode();
+
+ $wgOut->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
+ 'clearyourcache' );
// Give hooks a chance to customise the output
if ( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->getTitle(), $wgOut ) ) ) {
$target = array( $target );
}
- $imageDir = wfUILang()->getDir();
+ $lang = $this->getTitle()->getPageLanguage();
+ $imageDir = $lang->getDir();
if ( $appendSubtitle ) {
$wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) );
}
$nextRedirect = $wgStylePath . '/common/images/nextredirect' . $imageDir . '.png';
- $alt = wfUILang()->isRTL() ? '←' : '→';
+ $alt = $lang->isRTL() ? '←' : '→';
// Automatically append redirect=no to each link, since most of them are redirect pages themselves.
foreach ( $target as $rt ) {
$link .= Html::element( 'img', array( 'src' => $nextRedirect, 'alt' => $alt ) );
/**
* Removes trackback record for current article from trackbacks table
- * @deprecated since 1.19
+ * @deprecated since 1.18
*/
public function deletetrackback() {
return Action::factory( 'deletetrackback', $this )->show();
/**
* Mark this particular edit/page as patrolled
- * @deprecated since 1.19
+ * @deprecated since 1.18
*/
public function markpatrolled() {
Action::factory( 'markpatrolled', $this )->show();
/**
* User-interface handler for the "watch" action.
- * Requires Request to pass a token as of 1.19.
+ * Requires Request to pass a token as of 1.18.
* @deprecated since 1.18
*/
public function watch() {
/**
* User interface handler for the "unwatch" action.
- * Requires Request to pass a token as of 1.19.
+ * Requires Request to pass a token as of 1.18.
* @deprecated since 1.18
*/
public function unwatch() {
Action::factory( 'info', $this )->show();
}
+ /**
+ * Overriden by ImagePage class, only present here to avoid a fatal error
+ * Called for ?action=revert
+ */
+ public function revert() {
+ Action::factory( 'revert', $this )->show();
+ }
+
+ /**
+ * User interface for rollback operations
+ */
+ public function rollback() {
+ Action::factory( 'rollback', $this )->show();
+ }
+
/**
* Output a redirect back to the article.
* This is typically used after an edit.
*
- * @deprecated in 1.19; call $wgOut->redirect() directly
+ * @deprecated in 1.18; call $wgOut->redirect() directly
* @param $noRedir Boolean: add redirect=no
* @param $sectionAnchor String: section to redirect to, including "#"
* @param $extraQuery String: extra query params
$wgOut->redirect( $this->getTitle()->getFullURL( $query ) . $sectionAnchor );
}
- /**
- * Auto-generates a deletion reason
- *
- * @param &$hasHistory Boolean: whether the page has a history
- * @return mixed String containing deletion reason or empty string, or boolean false
- * if no revision occurred
- */
- public function generateReason( &$hasHistory ) {
- global $wgContLang;
-
- $dbw = wfGetDB( DB_MASTER );
- // Get the last revision
- $rev = Revision::newFromTitle( $this->getTitle() );
-
- if ( is_null( $rev ) ) {
- return false;
- }
-
- // Get the article's contents
- $contents = $rev->getText();
- $blank = false;
-
- // If the page is blank, use the text from the previous revision,
- // which can only be blank if there's a move/import/protect dummy revision involved
- if ( $contents == '' ) {
- $prev = $rev->getPrevious();
-
- if ( $prev ) {
- $contents = $prev->getText();
- $blank = true;
- }
- }
-
- // Find out if there was only one contributor
- // Only scan the last 20 revisions
- $res = $dbw->select( 'revision', 'rev_user_text',
- array( 'rev_page' => $this->mPage->getID(), $dbw->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ),
- __METHOD__,
- array( 'LIMIT' => 20 )
- );
-
- if ( $res === false ) {
- // This page has no revisions, which is very weird
- return false;
- }
-
- $hasHistory = ( $res->numRows() > 1 );
- $row = $dbw->fetchObject( $res );
-
- if ( $row ) { // $row is false if the only contributor is hidden
- $onlyAuthor = $row->rev_user_text;
- // Try to find a second contributor
- foreach ( $res as $row ) {
- if ( $row->rev_user_text != $onlyAuthor ) { // Bug 22999
- $onlyAuthor = false;
- break;
- }
- }
- } else {
- $onlyAuthor = false;
- }
-
- // Generate the summary with a '$1' placeholder
- if ( $blank ) {
- // The current revision is blank and the one before is also
- // blank. It's just not our lucky day
- $reason = wfMsgForContent( 'exbeforeblank', '$1' );
- } else {
- if ( $onlyAuthor ) {
- $reason = wfMsgForContent( 'excontentauthor', '$1', $onlyAuthor );
- } else {
- $reason = wfMsgForContent( 'excontent', '$1' );
- }
- }
-
- if ( $reason == '-' ) {
- // Allow these UI messages to be blanked out cleanly
- return '';
- }
-
- // Replace newlines with spaces to prevent uglyness
- $contents = preg_replace( "/[\n\r]/", ' ', $contents );
- // Calculate the maximum amount of chars to get
- // Max content length = max comment length - length of the comment (excl. $1)
- $maxLength = 255 - ( strlen( $reason ) - 2 );
- $contents = $wgContLang->truncate( $contents, $maxLength );
- // Remove possible unfinished links
- $contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
- // Now replace the '$1' placeholder
- $reason = str_replace( '$1', $contents, $reason );
-
- return $reason;
- }
-
-
/**
* UI entry point for page deletion
*/
}
}
- /**
- * User interface for rollback operations
- */
- public function rollback() {
- global $wgUser, $wgOut, $wgRequest;
-
- $details = null;
-
- $result = $this->mPage->doRollback(
- $wgRequest->getVal( 'from' ),
- $wgRequest->getText( 'summary' ),
- $wgRequest->getVal( 'token' ),
- $wgRequest->getBool( 'bot' ),
- $details
- );
-
- if ( in_array( array( 'actionthrottledtext' ), $result ) ) {
- $wgOut->rateLimited();
- return;
- }
-
- if ( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ) {
- $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
- $errArray = $result[0];
- $errMsg = array_shift( $errArray );
- $wgOut->addWikiMsgArray( $errMsg, $errArray );
-
- if ( isset( $details['current'] ) ) {
- $current = $details['current'];
-
- if ( $current->getComment() != '' ) {
- $wgOut->addWikiMsgArray( 'editcomment', array(
- Linker::formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
- }
- }
-
- return;
- }
-
- # Display permissions errors before read-only message -- there's no
- # point in misleading the user into thinking the inability to rollback
- # is only temporary.
- if ( !empty( $result ) && $result !== array( array( 'readonlytext' ) ) ) {
- # array_diff is completely broken for arrays of arrays, sigh.
- # Remove any 'readonlytext' error manually.
- $out = array();
- foreach ( $result as $error ) {
- if ( $error != array( 'readonlytext' ) ) {
- $out [] = $error;
- }
- }
- $wgOut->showPermissionsErrorPage( $out );
-
- return;
- }
-
- if ( $result == array( array( 'readonlytext' ) ) ) {
- $wgOut->readOnlyPage();
-
- return;
- }
-
- $current = $details['current'];
- $target = $details['target'];
- $newId = $details['newid'];
- $wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
- $wgOut->setRobotPolicy( 'noindex,nofollow' );
-
- if ( $current->getUserText() === '' ) {
- $old = wfMsg( 'rev-deleted-user' );
- } else {
- $old = Linker::userLink( $current->getUser(), $current->getUserText() )
- . Linker::userToolLinks( $current->getUser(), $current->getUserText() );
- }
-
- $new = Linker::userLink( $target->getUser(), $target->getUserText() )
- . Linker::userToolLinks( $target->getUser(), $target->getUserText() );
- $wgOut->addHTML( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
- $wgOut->returnToMain( false, $this->getTitle() );
-
- if ( !$wgRequest->getBool( 'hidediff', false ) && !$wgUser->getBoolOption( 'norollbackdiff', false ) ) {
- $de = new DifferenceEngine( $this->getTitle(), $current->getId(), $newId, false, true );
- $de->showDiff( '', '' );
- }
- }
-
/**
* Generate the navigation links when browsing through an article revisions
* It shows the information as:
"\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsgExt( 'revision-nav', array( 'escapenoentities', 'parsemag', 'replaceafter' ),
$prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
- $wgOut->addHTML( $r );
+ $wgOut->setSubtitle( $r );
}
/* Caching functions */
/**#@-*/
- /**
- * Overriden by ImagePage class, only present here to avoid a fatal error
- * Called for ?action=revert
- */
- public function revert() {
- global $wgOut;
- $wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
- }
-
/**
* Add the primary page-view wikitext to the output buffer
* Saves the text into the parser cache if possible.
global $wgEnableParserCache, $wgUser;
$user = is_null( $user ) ? $wgUser : $user;
+ wfProfileIn( __METHOD__ );
// Should the parser cache be used?
$useParserCache = $wgEnableParserCache &&
$user->getStubThreshold() == 0 &&
if ( $useParserCache ) {
$parserOutput = ParserCache::singleton()->get( $this, $this->mPage->getParserOptions() );
if ( $parserOutput !== false ) {
+ wfProfileOut( __METHOD__ );
return $parserOutput;
}
}
} else {
$rev = Revision::newFromTitle( $this->getTitle(), $oldid );
if ( $rev === null ) {
+ wfProfileOut( __METHOD__ );
return false;
}
$text = $rev->getText();
}
- return $this->getOutputFromWikitext( $text, $useParserCache );
+ $output = $this->getOutputFromWikitext( $text, $useParserCache );
+ wfProfileOut( __METHOD__ );
+ return $output;
}
/**
* @param $text string
* @param $cache boolean
* @param $parserOptions parsing options, defaults to false
- * @return string containing parsed output
+ * @return ParserOutput
*/
public function getOutputFromWikitext( $text, $cache = true, $parserOptions = false ) {
global $wgParser, $wgEnableParserCache, $wgUseFileCache;
$wgUseFileCache = false;
}
- $this->doCascadeProtectionUpdates( $this->mParserOutput );
-
- return $this->mParserOutput;
- }
-
- /**
- * Updates cascading protections
- *
- * @param $parserOutput ParserOutput object, or boolean false
- **/
- protected function doCascadeProtectionUpdates( $parserOutput ) {
- if ( !$this->isCurrent() || wfReadOnly() || !$this->getTitle()->areRestrictionsCascading() ) {
- return;
+ if ( $this->isCurrent() ) {
+ $this->mPage->doCascadeProtectionUpdates( $this->mParserOutput );
}
- // templatelinks table may have become out of sync,
- // especially if using variable-based transclusions.
- // For paranoia, check if things have changed and if
- // so apply updates to the database. This will ensure
- // that cascaded protections apply as soon as the changes
- // are visible.
-
- # Get templates from templatelinks
- $id = $this->getTitle()->getArticleID();
-
- $tlTemplates = array();
-
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array( 'templatelinks' ),
- array( 'tl_namespace', 'tl_title' ),
- array( 'tl_from' => $id ),
- __METHOD__
- );
-
- foreach ( $res as $row ) {
- $tlTemplates["{$row->tl_namespace}:{$row->tl_title}"] = true;
- }
-
- # Get templates from parser output.
- $poTemplates = array();
- foreach ( $parserOutput->getTemplates() as $ns => $templates ) {
- foreach ( $templates as $dbk => $id ) {
- $poTemplates["$ns:$dbk"] = true;
- }
- }
-
- # Get the diff
- $templates_diff = array_diff_key( $poTemplates, $tlTemplates );
-
- if ( count( $templates_diff ) > 0 ) {
- # Whee, link updates time.
- $u = new LinksUpdate( $this->getTitle(), $parserOutput, false );
- $u->doUpdate();
- }
+ return $this->mParserOutput;
}
/**
* Sets the context this Article is executed in
*
- * @param $context RequestContext
+ * @param $context IContextSource
* @since 1.18
*/
public function setContext( $context ) {
/**
* Gets the context this Article is executed in
*
- * @return RequestContext
+ * @return IContextSource
* @since 1.18
*/
public function getContext() {
- if ( $this->mContext instanceof RequestContext ) {
+ if ( $this->mContext instanceof IContextSource ) {
return $this->mContext;
} else {
wfDebug( __METHOD__ . " called and \$mContext is null. Return RequestContext::getMain(); for sanity\n" );
#wfWarn( "Access to raw $fname field " . __CLASS__ );
return $this->mPage->$fname;
}
- trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
+ trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
}
/**
*
* @param $fname String Field name
* @param $fvalue mixed New value
- * @param $args Array Arguments to the method
*/
public function __set( $fname, $fvalue ) {
if ( property_exists( $this->mPage, $fname ) ) {
} elseif ( !in_array( $fname, array( 'mContext', 'mPage' ) ) ) {
$this->mPage->$fname = $fvalue;
} else {
- trigger_error( 'Inaccessible property via __get(): ' . $fname, E_USER_NOTICE );
+ trigger_error( 'Inaccessible property via __set(): ' . $fname, E_USER_NOTICE );
}
}
#wfWarn( "Call to " . __CLASS__ . "::$fname; please use WikiPage instead" );
return call_user_func_array( array( $this->mPage, $fname ), $args );
}
- trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
+ trigger_error( 'Inaccessible function via __call(): ' . $fname, E_USER_ERROR );
}
// ****** B/C functions to work-around PHP silliness with __call and references ****** //
return $this->mPage->doDeleteArticle( $reason, $suppress, $id, $commit, $error );
}
- public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
- return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails );
+ public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails, User $user = null ) {
+ global $wgUser;
+ $user = is_null( $user ) ? $wgUser : $user;
+ return $this->mPage->doRollback( $fromP, $summary, $token, $bot, $resultDetails, $user );
+ }
+
+ public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser = null ) {
+ global $wgUser;
+ $guser = is_null( $guser ) ? $wgUser : $guser;
+ return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails, $guser );
}
- public function commitRollback( $fromP, $summary, $bot, &$resultDetails ) {
- return $this->mPage->commitRollback( $fromP, $summary, $bot, $resultDetails );
+ public function generateReason( &$hasHistory ) {
+ return $this->mPage->getAutoDeleteReason( $hasHistory );
}
// ****** B/C functions for static methods ( __callStatic is PHP>=5.3 ) ****** //
}
/**
- * @param $status Status
+ * @param $status Status
*/
function error( $status ) {
global $wgOut;