function setRedirectedFrom( $from ) {
$this->mRedirectedFrom = $from;
}
-
+
/**
* @return mixed false, Title of in-wiki target, or string with URL
*/
function followRedirect() {
$text = $this->getContent();
$rt = Title::newFromRedirect( $text );
-
+
# process if title object is valid and not special:userlogout
if( $rt ) {
if( $rt->getInterwiki() != '' ) {
//
// This can be hard to reverse and may produce loops,
// so they may be disabled in the site configuration.
-
+
$source = $this->mTitle->getFullURL( 'redirect=no' );
return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
}
// the rest of the page we're on.
//
// This can be hard to reverse, so they may be disabled.
-
+
if( $rt->isSpecial( 'Userlogout' ) ) {
// rolleyes
} else {
return $rt;
}
}
-
+
// No or invalid redirect
return false;
}
'page_id',
'page_namespace',
'page_title',
+ 'page_restrictions',
'page_counter',
'page_is_redirect',
'page_is_new',
$dbr =& $this->getDB();
$data = $this->pageDataFromId( $dbr, $this->getId() );
}
-
+
$lc =& LinkCache::singleton();
if ( $data ) {
$lc->addGoodLinkObj( $data->page_id, $this->mTitle );
$this->mTitle->mArticleID = $data->page_id;
+ # Old-fashioned restrictions.
+ $this->mTitle->loadRestrictions( $data->page_restrictions );
+
$this->mCounter = $data->page_counter;
$this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
$this->mIsRedirect = $data->page_is_redirect;
* @return Database
*/
function &getDB() {
- $ret =& wfGetDB( DB_MASTER );
- return $ret;
+ return wfGetDB( DB_MASTER );
}
/**
$parserCache =& ParserCache::singleton();
$ns = $this->mTitle->getNamespace(); # shortcut
-
+
# Get variables from query string
$oldid = $this->getOldID();
$diff = $wgRequest->getVal( 'diff' );
$rcid = $wgRequest->getVal( 'rcid' );
$rdfrom = $wgRequest->getVal( 'rdfrom' );
+ $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
$wgOut->setArticleFlag( true );
- if ( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
+
+ # Discourage indexing of printable versions, but encourage following
+ if( $wgOut->isPrintable() ) {
+ $policy = 'noindex,follow';
+ } elseif( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
+ # Honour customised robot policies for this namespace
$policy = $wgNamespaceRobotPolicies[$ns];
} else {
- # The default policy. Dev note: make sure you change the documentation
- # in DefaultSettings.php before changing it.
+ # Default to encourage indexing and following links
$policy = 'index,follow';
}
- $wgOut->setRobotpolicy( $policy );
+ $wgOut->setRobotPolicy( $policy );
# If we got diff and oldid in the query, we want to see a
# diff page instead of the article.
$de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid );
// DifferenceEngine directly fetched the revision:
$this->mRevIdFetched = $de->mNewid;
- $de->showDiffPage();
-
+ $de->showDiffPage( $diffOnly );
+
// Needed to get the page's current revision
$this->loadPageData();
if( $diff == 0 || $diff == $this->mLatest ) {
wfProfileOut( __METHOD__ );
return;
}
-
+
if ( empty( $oldid ) && $this->checkTouched() ) {
$wgOut->setETag($parserCache->getETag($this, $wgUser));
$wasRedirected = true;
}
}
-
+
$outputDone = false;
if ( $pcache ) {
if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
$oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false );
}
# Display content and don't save to parser cache
+ # With timing hack -- TS 2006-07-26
+ $time = -wfTime();
$this->outputWikiText( $text, false );
+ $time += wfTime();
+
+ # Timing hack
+ if ( $time > 3 ) {
+ wfDebugLog( 'slow-parse', sprintf( "%-5.2f %s", $time,
+ $this->mTitle->getPrefixedDBkey()));
+ }
if( !$this->isCurrent() ) {
$wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
}
+
}
}
/* title may have been set from the cache */
if ( $wgUseRCPatrol && !is_null( $rcid ) && $rcid != 0 && $wgUser->isAllowed( 'patrol' ) ) {
$wgOut->addHTML(
"<div class='patrollink'>" .
- wfMsg ( 'markaspatrolledlink',
- $sk->makeKnownLinkObj( $this->mTitle, wfMsg('markaspatrolledtext'), "action=markpatrolled&rcid=$rcid" )
+ wfMsgHtml( 'markaspatrolledlink',
+ $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml('markaspatrolledtext'),
+ "action=markpatrolled&rcid=$rcid" )
) .
'</div>'
);
function purge() {
global $wgUser, $wgRequest, $wgOut;
- if ( $wgUser->isLoggedIn() || $wgRequest->wasPosted() ) {
+ if ( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) {
if( wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
$this->doPurge();
}
$wgOut->addHTML( $msg );
}
}
-
+
/**
* Perform the actions of a page purging
*/
* when different from the currently set value.
* Giving 0 indicates the new page flag should
* be set on.
- * @param bool $lastRevIsRedirect If given, will optimize adding and
+ * @param bool $lastRevIsRedirect If given, will optimize adding and
* removing rows in redirect table.
* @return bool true on success, false on failure
* @private
$text = $revision->getText();
$rt = Title::newFromRedirect( $text );
-
+
$conditions = array( 'page_id' => $this->getId() );
if( !is_null( $lastRevision ) ) {
# An extra check against threads stepping on each other
if ($result) {
// FIXME: Should the result from updateRedirectOn() be returned instead?
- $this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
+ $this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
}
-
+
wfProfileOut( __METHOD__ );
return $result;
}
/**
- * Add row to the redirect table if this is a redirect, remove otherwise.
+ * Add row to the redirect table if this is a redirect, remove otherwise.
*
* @param Database $dbw
* @param $redirectTitle a title object pointing to the redirect target,
- * or NULL if this is not a redirect
- * @param bool $lastRevIsRedirect If given, will optimize adding and
+ * or NULL if this is not a redirect
+ * @param bool $lastRevIsRedirect If given, will optimize adding and
* removing rows in redirect table.
* @return bool true on success, false on failure
* @private
$dbw->replace( 'redirect', array( 'rd_from' ), $set, __METHOD__ );
} else {
- // This is not a redirect, remove row from redirect table
+ // This is not a redirect, remove row from redirect table
$where = array( 'rd_from' => $this->getId() );
$dbw->delete( 'redirect', $where, __METHOD__);
}
wfProfileOut( __METHOD__ );
return ( $dbw->affectedRows() != 0 );
}
-
+
return true;
}
*/
function replaceSection($section, $text, $summary = '', $edittime = NULL) {
wfProfileIn( __METHOD__ );
-
+
if( $section == '' ) {
// Whole-page edit; let the text through unmolested.
} else {
if ( $comment && $summary != "" ) {
$text = "== {$summary} ==\n\n".$text;
}
-
+
$this->doEdit( $text, $summary, $flags );
$dbw =& wfGetDB( DB_MASTER );
/**
* Article::doEdit()
*
- * Change an existing article or create a new article. Updates RC and all necessary caches,
+ * Change an existing article or create a new article. Updates RC and all necessary caches,
* optionally via the deferred update array.
*
* $wgUser must be set before calling this function.
* Defer some of the updates until the end of index.php
* EDIT_AUTOSUMMARY
* Fill in blank summaries with generated text where possible
- *
- * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
- * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If
+ *
+ * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
+ * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If
* EDIT_NEW is specified and the article does exist, a duplicate key error will cause an exception
* to be thrown from the Database. These two conditions are also possible with auto-detection due
* to MediaWiki's performance-optimised locking strategy.
if( !wfRunHooks( 'ArticleSave', array( &$this, &$wgUser, &$text,
&$summary, $flags & EDIT_MINOR,
- null, null, &$flags ) ) )
+ null, null, &$flags ) ) )
{
wfDebug( __METHOD__ . ": ArticleSave hook aborted save!\n" );
wfProfileOut( __METHOD__ );
$dbw =& wfGetDB( DB_MASTER );
$now = wfTimestampNow();
-
+
if ( $flags & EDIT_UPDATE ) {
# Update article, but only if changed.
wfProfileOut( __METHOD__ );
return false;
}
-
+
$revision = new Revision( array(
'page' => $this->getId(),
'comment' => $summary,
$rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary,
$lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
$revisionId );
-
+
# Mark as patrolled if the user can do so
- if( $wgUser->isAllowed( 'autopatrol' ) ) {
+ if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
RecentChange::markPatrolled( $rcid );
+ PatrolLog::record( $rcid, true );
}
}
$wgUser->incEditCount();
}
if ( $good ) {
- # Invalidate cache of this article and all pages using this article
+ # Invalidate cache of this article and all pages using this article
# as a template. Partly deferred.
Article::onArticleEdit( $this->mTitle );
-
+
# Update links tables, site stats, etc.
$changed = ( strcmp( $oldtext, $text ) != 0 );
$this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
}
} else {
# Create new article
-
+
# Set statistics members
- # We work out if it's countable after PST to avoid counter drift
+ # We work out if it's countable after PST to avoid counter drift
# when articles are created with {{subst:}}
$this->mGoodAdjustment = (int)$this->isCountable( $text );
$this->mTotalAdjustment = 1;
$rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary, $bot,
'', strlen( $text ), $revisionId );
# Mark as patrolled if the user can
- if( $wgUser->isAllowed( 'autopatrol' ) ) {
+ if( $GLOBALS['wgUseRCPatrol'] && $wgUser->isAllowed( 'autopatrol' ) ) {
RecentChange::markPatrolled( $rcid );
+ PatrolLog::record( $rcid, true );
}
}
$wgUser->incEditCount();
array( &$this, &$wgUser, $text,
$summary, $flags & EDIT_MINOR,
null, null, &$flags ) );
-
+
wfProfileOut( __METHOD__ );
return $good;
}
}
$wgOut->redirect( $this->mTitle->getFullURL( $query ) . $sectionAnchor );
}
-
+
/**
* Mark this particular edit as patrolled
*/
$wgOut->errorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
return;
}
-
+
# Check permissions
if( !$wgUser->isAllowed( 'patrol' ) ) {
$wgOut->permissionRequired( 'patrol' );
return;
}
-
+
# If we haven't been given an rc_id value, we can't do anything
$rcid = $wgRequest->getVal( 'rcid' );
if( !$rcid ) {
$wgOut->errorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
return;
}
-
+
# Handle the 'MarkPatrolled' hook
if( !wfRunHooks( 'MarkPatrolled', array( $rcid, &$wgUser, false ) ) ) {
return;
}
-
+
$return = SpecialPage::getTitleFor( 'Recentchanges' );
# If it's left up to us, check that the user is allowed to patrol this edit
# If the user has the "autopatrol" right, then we'll assume there are no
return;
}
}
-
+
# Mark the edit as patrolled
RecentChange::markPatrolled( $rcid );
+ PatrolLog::record( $rcid );
wfRunHooks( 'MarkPatrolledComplete', array( &$rcid, &$wgUser, false ) );
-
+
# Inform the user
$wgOut->setPageTitle( wfMsg( 'markedaspatrolled' ) );
$wgOut->addWikiText( wfMsgNoTrans( 'markedaspatrolledtext' ) );
$wgOut->readOnlyPage();
return;
}
-
+
if( $this->doWatch() ) {
$wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
}
-
+
/**
* Add this page to $wgUser's watchlist
* @return bool true on successful watch operation
if( $wgUser->isAnon() ) {
return false;
}
-
+
if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
$wgUser->addWatch( $this->mTitle );
return wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
}
-
+
return false;
}
$wgOut->readOnlyPage();
return;
}
-
+
if( $this->doUnwatch() ) {
$wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
$wgOut->setRobotpolicy( 'noindex,nofollow' );
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
}
-
+
/**
* Stop watching a page
* @return bool true on successful unwatch
return wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
}
-
+
return false;
}
*/
function updateRestrictions( $limit = array(), $reason = '', $cascade = 0 ) {
global $wgUser, $wgRestrictionTypes, $wgContLang;
-
+
$id = $this->mTitle->getArticleID();
if( !$wgUser->isAllowed( 'protect' ) || wfReadOnly() || $id == 0 ) {
return false;
}
+ if (!$cascade) {
+ $cascade = false;
+ }
+
# FIXME: Same limitations as described in ProtectionForm.php (line 37);
# we expect a single selection, but the schema allows otherwise.
$current = array();
$current = Article::flattenRestrictions( $current );
$updated = Article::flattenRestrictions( $limit );
-
+
$changed = ( $current != $updated );
$changed = $changed || ($this->mTitle->areRestrictionsCascading() != $cascade);
$protect = ( $updated != '' );
-
+
# If nothing's changed, do nothing
if( $changed ) {
if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
$dbw =& wfGetDB( DB_MASTER );
-
+
# Prepare a null revision to be added to the history
$comment = $wgContLang->ucfirst( wfMsgForContent( $protect ? 'protectedarticle' : 'unprotectedarticle', $this->mTitle->getPrefixedText() ) );
if( $reason )
if ($restrictions != '' ) {
$dbw->replace( 'page_restrictions', array( 'pr_pagetype'),
array( 'pr_page' => $id, 'pr_type' => $action
- , 'pr_level' => $restrictions, 'pr_cascade' => $cascade ), __METHOD__ );
+ , 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0 ), __METHOD__ );
} else {
$dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
'pr_type' => $action ), __METHOD__ );
}
}
-
+
+ # Update page record
+ $dbw->update( 'page',
+ array( /* SET */
+ 'page_touched' => $dbw->timestamp(),
+ 'page_restrictions' => '',
+ 'page_latest' => $nullRevId
+ ), array( /* WHERE */
+ 'page_id' => $id
+ ), 'Article::protect'
+ );
wfRunHooks( 'ArticleProtectComplete', array( &$this, &$wgUser, $limit, $reason ) );
-
+
# Update the protection log
$log = new LogPage( 'protect' );
} else {
$log->addEntry( 'unprotect', $this->mTitle, $reason );
}
-
+
} # End hook
} # End "changed" check
-
+
return true;
}
}
$wgOut->setPagetitle( wfMsg( 'confirmdelete' ) );
-
+
# Better double-check that it hasn't been deleted yet!
$dbw =& wfGetDB( DB_MASTER );
$conds = $this->mTitle->pageCond();
# and insert a warning if it does
$maxRevisions = 20;
$authors = $this->getLastNAuthors( $maxRevisions, $latest );
-
+
if( count( $authors ) > 1 && !$confirm ) {
$skin=$wgUser->getSkin();
$wgOut->addHTML( '<strong>' . wfMsg( 'historywarning' ) . ' ' . $skin->historyLink() . '</strong>' );
wfProfileOut( __METHOD__ );
return $authors;
}
-
+
/**
* Output deletion confirmation dialog
*/
* Do standard deferred updates after page edit.
* Update links tables, site stats, search index and message cache.
* Every 1000th edit, prune the recent changes table.
- *
+ *
* @private
* @param $text New text of the article
* @param $summary Edit summary
wfProfileOut( __METHOD__ );
}
-
+
/**
* Perform article updates on a special page creation.
*
global $wgLang, $wgOut, $wgUser;
if ( !wfRunHooks( 'DisplayOldSubtitle', array(&$this, &$oldid) ) ) {
- return;
- }
+ return;
+ }
$revision = Revision::newFromId( $oldid );
$nextdiff = $current
? wfMsg( 'diff' )
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
-
+
$userlinks = $sk->userLink( $revision->getUser(), $revision->getUserText() )
. $sk->userToolLinks( $revision->getUser(), $revision->getUserText() );
-
+
$r = "\n\t\t\t\t<div id=\"mw-revision-info\">" . wfMsg( 'revision-info', $td, $userlinks ) . "</div>\n" .
"\n\t\t\t\t<div id=\"mw-revision-nav\">" . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
$wgOut->setSubtitle( $r );
$title->touchLinks();
$title->purgeSquid();
-
+
# File cache
if ( $wgUseFileCache ) {
$cm = new HTMLFileCache( $title );
$dbr->freeResult( $res );
return $result;
}
-
+
/**
* Return an auto-generated summary if the text provided is a redirect.
*
$parserCache->save( $parserOutput, $this, $wgUser );
}
- if ( !wfReadOnly() ) {
+ if ( !wfReadOnly() && $this->mTitle->areRestrictionsCascading() ) {
+ // 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
- $result = array();
$id = $this->mTitle->getArticleID();
- if( $id == 0 ) {
- $tlTemplates = array();
- }
+ $tlTemplates = array();
$dbr =& wfGetDB( DB_SLAVE );
$res = $dbr->select( array( 'templatelinks' ),
if ( count( $templates_diff ) > 0 ) {
# Whee, link updates time.
$u = new LinksUpdate( $this->mTitle, $parserOutput );
-
+
$dbw =& wfGetDb( DB_MASTER );
$dbw->begin();
-
+
$u->doUpdate();
$dbw->commit();