* (and only when) $wgActions[$action] === true. This allows subclasses
* to override the default behavior.
*
- * @todo: move this UI stuff somewhere else
+ * @todo Move this UI stuff somewhere else
*
* @return Array
*/
public function pageDataFromTitle( $dbr, $title, $options = array() ) {
return $this->pageData( $dbr, array(
'page_namespace' => $title->getNamespace(),
- 'page_title' => $title->getDBkey() ), $options );
+ 'page_title' => $title->getDBkey() ), $options );
}
/**
*/
public function isRedirect() {
$content = $this->getContent();
- if ( !$content ) return false;
+ if ( !$content ) {
+ return false;
+ }
return $content->isRedirect();
}
* @return String|false The text of the current revision
* @deprecated as of 1.21, getContent() should be used instead.
*/
- public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { // @todo: deprecated, replace usage!
+ public function getText( $audience = Revision::FOR_PUBLIC, User $user = null ) { // @todo deprecated, replace usage!
ContentHandler::deprecated( __METHOD__, '1.21' );
$this->loadLastEdit();
public function setCachedLastEditTime( $timestamp ) {
global $wgMemc;
$key = wfMemcKey( 'page-lastedit', md5( $this->mTitle->getPrefixedDBkey() ) );
- $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60*15 );
+ $wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60 * 15 );
}
/**
$dbw = wfGetDB( DB_MASTER );
$dbw->replace( 'redirect', array( 'rd_from' ),
array(
- 'rd_from' => $this->getId(),
+ 'rd_from' => $this->getId(),
'rd_namespace' => $rt->getNamespace(),
- 'rd_title' => $rt->getDBkey(),
- 'rd_fragment' => $rt->getFragment(),
+ 'rd_title' => $rt->getDBkey(),
+ 'rd_fragment' => $rt->getFragment(),
'rd_interwiki' => $rt->getInterwiki(),
),
__METHOD__
// 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 ) );
+ return $rt->getFullURL( array( 'rdfrom' => $source ) );
} else {
// External pages pages without "local" bit set are not valid
// redirect targets
public function doPurge() {
global $wgUseSquid;
- if( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
+ if ( !wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
return false;
}
}
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
- // @todo: move this logic to MessageCache
+ // @todo move this logic to MessageCache
if ( $this->exists() ) {
// NOTE: use transclusion text for messages.
$content = $this->getContent();
$text = $content === null ? null : $content->getWikitextForTransclusion();
- if ( $text === null ) $text = false;
+ if ( $text === null ) {
+ $text = false;
+ }
} else {
$text = false;
}
*
* @return boolean whether sections are supported.
*
- * @todo: the skin should check this and not offer section functionality if sections are not supported.
- * @todo: the EditPage should check this and not offer section functionality if sections are not supported.
+ * @todo The skin should check this and not offer section functionality if sections are not supported.
+ * @todo The EditPage should check this and not offer section functionality if sections are not supported.
*/
public function supportsSections() {
return $this->getContentHandler()->supportsSections();
// Provide autosummaries if one is not provided and autosummaries are enabled.
if ( $wgUseAutomaticEditSummaries && $flags & EDIT_AUTOSUMMARY && $summary == '' ) {
- if ( !$old_content ) $old_content = null;
+ if ( !$old_content ) {
+ $old_content = null;
+ }
$summary = $handler->getAutosummary( $old_content, $content, $flags );
}
$options = $this->getContentHandler()->makeParserOptions( $context );
if ( $this->getTitle()->isConversionTable() ) {
- //@todo: ConversionTable should become a separate content model, so we don't need special cases like this one.
+ // @todo ConversionTable should become a separate content model, so we don't need special cases like this one.
$options->disableContentConversion();
}
$content = $revision->getContent();
// Parse the text
- // Be careful not to double-PST: $text is usually already PST-ed once
+ // Be careful not to do pre-save transform twice: $text is usually
+ // already pre-save transformed once.
if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
$editInfo = $this->prepareContentForEdit( $content, $revision->getId(), $user );
if ( 0 == mt_rand( 0, 99 ) ) {
// Flush old entries from the `recentchanges` table; we do this on
// random requests so as to avoid an increase in writes for no good reason
- global $wgRCMaxAge;
-
- $dbw = wfGetDB( DB_MASTER );
- $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
- $dbw->delete(
- 'recentchanges',
- array( 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ),
- __METHOD__
- );
+ RecentChange::purgeExpiredChanges();
}
}
DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, $good, $total ) );
DeferredUpdates::addUpdate( new SearchUpdate( $id, $title, $content->getTextForSearchIndex() ) );
- // @TODO: let the search engine decide what to do with the content object
+ // @todo let the search engine decide what to do with the content object
// If this is another user's talk page, update newtalk.
// Don't do this if $options['changed'] = false (null-edits) nor if
&& $shortTitle != $user->getTitleKey()
&& !( $revision->isMinor() && $user->isAllowed( 'nominornewtalk' ) )
) {
- if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this ) ) ) {
- $other = User::newFromName( $shortTitle, false );
- if ( !$other ) {
- wfDebug( __METHOD__ . ": invalid username\n" );
- } elseif ( User::isIP( $shortTitle ) ) {
- // An anonymous user
- $other->setNewtalk( true, $revision );
- } elseif ( $other->isLoggedIn() ) {
- $other->setNewtalk( true, $revision );
- } else {
- wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" );
+ $recipient = User::newFromName( $shortTitle, false );
+ if ( !$recipient ) {
+ wfDebug( __METHOD__ . ": invalid username\n" );
+ } else {
+ // Allow extensions to prevent user notification when a new message is added to their talk page
+ if ( wfRunHooks( 'ArticleEditUpdateNewTalk', array( &$this, $recipient ) ) ) {
+ if ( User::isIP( $shortTitle ) ) {
+ // An anonymous user
+ $recipient->setNewtalk( true, $revision );
+ } elseif ( $recipient->isLoggedIn() ) {
+ $recipient->setNewtalk( true, $revision );
+ } else {
+ wfDebug( __METHOD__ . ": don't need to notify a nonexistent user\n" );
+ }
}
}
}
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
// XXX: could skip pseudo-messages like js/css here, based on content model.
$msgtext = $content ? $content->getWikitextForTransclusion() : null;
- if ( $msgtext === false || $msgtext === null ) $msgtext = '';
+ if ( $msgtext === false || $msgtext === null ) {
+ $msgtext = '';
+ }
MessageCache::singleton()->replace( $shortTitle, $msgtext );
}
- if( $options['created'] ) {
+ if ( $options['created'] ) {
self::onArticleCreate( $this->mTitle );
} else {
self::onArticleEdit( $this->mTitle );
* @return Status
*/
public function doUpdateRestrictions( array $limit, array $expiry, &$cascade, $reason, User $user ) {
- global $wgContLang;
+ global $wgContLang, $wgCascadingRestrictionLevels;
if ( wfReadOnly() ) {
return Status::newFatal( 'readonlytext', wfReadOnlyReason() );
return Status::newGood();
}
- // Only restrictions with the 'protect' right can cascade...
- // Otherwise, people who cannot normally protect can "protect" pages via transclusion
+ // Only certain restrictions can cascade... Otherwise, users who cannot normally protect pages
+ // could "protect" them by transcluding them on protected pages they are allowed to edit.
$editrestriction = isset( $limit['edit'] ) ? array( $limit['edit'] ) : $this->mTitle->getRestrictions( 'edit' );
+ $cascadingRestrictionLevels = $wgCascadingRestrictionLevels;
+ if ( in_array( 'sysop', $cascadingRestrictionLevels ) ) {
+ $cascadingRestrictionLevels[] = 'protect'; // backwards compatibility
+ }
+
// The schema allows multiple restrictions
- if ( !in_array( 'protect', $editrestriction ) && !in_array( 'sysop', $editrestriction ) ) {
+ if ( !array_intersect( $editrestriction, $cascadingRestrictionLevels ) ) {
$cascade = false;
}
* performs permissions checks on $user, then calls commitRollback()
* to do the dirty work
*
- * @todo: separate the business/permission stuff out from backend code
+ * @todo Separate the business/permission stuff out from backend code
*
* @param string $fromP Name of the user whose edits to rollback.
* @param string $summary Custom summary. Set to default summary if empty.
$wgContLang->timeanddate( wfTimestamp( TS_MW, $s->rev_timestamp ) ),
$current->getId(), $wgContLang->timeanddate( $current->getTimestamp() )
);
- if( $summary instanceof Message ) {
+ if ( $summary instanceof Message ) {
$summary = $summary->params( $args )->inContentLanguage()->text();
} else {
$summary = wfMsgReplaceArgs( $summary, $args );
$resultDetails = array(
'summary' => $summary,
'current' => $current,
- 'target' => $target,
- 'newid' => $revId
+ 'target' => $target,
+ 'newid' => $revId
);
return array();
* Purge caches on page update etc
*
* @param $title Title object
- * @todo: verify that $title is always a Title object (and never false or null), add Title hint to parameter $title
+ * @todo Verify that $title is always a Title object (and never false or null), add Title hint to parameter $title
*/
public static function onArticleEdit( $title ) {
// Invalidate caches of articles which include this page
* @param array $added The names of categories that were added
* @param array $deleted The names of categories that were deleted
*/
- public function updateCategoryCounts( $added, $deleted ) {
- $ns = $this->mTitle->getNamespace();
+ public function updateCategoryCounts( array $added, array $deleted ) {
+ $that = $this;
+ $method = __METHOD__;
$dbw = wfGetDB( DB_MASTER );
- // First make sure the rows exist. If one of the "deleted" ones didn't
- // exist, we might legitimately not create it, but it's simpler to just
- // create it and then give it a negative value, since the value is bogus
- // anyway.
- //
- // Sometimes I wish we had INSERT ... ON DUPLICATE KEY UPDATE.
- $insertCats = array_merge( $added, $deleted );
- if ( !$insertCats ) {
- // Okay, nothing to do
- return;
- }
+ // Do this at the end of the commit to reduce lock wait timeouts
+ $dbw->onTransactionPreCommitOrIdle(
+ function() use ( $dbw, $that, $method, $added, $deleted ) {
+ $ns = $that->getTitle()->getNamespace();
- $insertRows = array();
+ // First make sure the rows exist. If one of the "deleted" ones didn't
+ // exist, we might legitimately not create it, but it's simpler to just
+ // create it and then give it a negative value, since the value is bogus
+ // anyway.
+ //
+ // Sometimes I wish we had INSERT ... ON DUPLICATE KEY UPDATE.
+ $insertCats = array_merge( $added, $deleted );
+ if ( !$insertCats ) {
+ // Okay, nothing to do
+ return;
+ }
- foreach ( $insertCats as $cat ) {
- $insertRows[] = array(
- 'cat_id' => $dbw->nextSequenceValue( 'category_cat_id_seq' ),
- 'cat_title' => $cat
- );
- }
- $dbw->insert( 'category', $insertRows, __METHOD__, 'IGNORE' );
+ $insertRows = array();
+ foreach ( $insertCats as $cat ) {
+ $insertRows[] = array(
+ 'cat_id' => $dbw->nextSequenceValue( 'category_cat_id_seq' ),
+ 'cat_title' => $cat
+ );
+ }
+ $dbw->insert( 'category', $insertRows, $method, 'IGNORE' );
- $addFields = array( 'cat_pages = cat_pages + 1' );
- $removeFields = array( 'cat_pages = cat_pages - 1' );
+ $addFields = array( 'cat_pages = cat_pages + 1' );
+ $removeFields = array( 'cat_pages = cat_pages - 1' );
- if ( $ns == NS_CATEGORY ) {
- $addFields[] = 'cat_subcats = cat_subcats + 1';
- $removeFields[] = 'cat_subcats = cat_subcats - 1';
- } elseif ( $ns == NS_FILE ) {
- $addFields[] = 'cat_files = cat_files + 1';
- $removeFields[] = 'cat_files = cat_files - 1';
- }
+ if ( $ns == NS_CATEGORY ) {
+ $addFields[] = 'cat_subcats = cat_subcats + 1';
+ $removeFields[] = 'cat_subcats = cat_subcats - 1';
+ } elseif ( $ns == NS_FILE ) {
+ $addFields[] = 'cat_files = cat_files + 1';
+ $removeFields[] = 'cat_files = cat_files - 1';
+ }
- if ( $added ) {
- $dbw->update(
- 'category',
- $addFields,
- array( 'cat_title' => $added ),
- __METHOD__
- );
- }
+ if ( $added ) {
+ $dbw->update(
+ 'category',
+ $addFields,
+ array( 'cat_title' => $added ),
+ $method
+ );
+ }
- if ( $deleted ) {
- $dbw->update(
- 'category',
- $removeFields,
- array( 'cat_title' => $deleted ),
- __METHOD__
- );
- }
+ if ( $deleted ) {
+ $dbw->update(
+ 'category',
+ $removeFields,
+ array( 'cat_title' => $deleted ),
+ $method
+ );
+ }
- foreach( $added as $catName ) {
- $cat = Category::newFromName( $catName );
- wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $this ) );
- }
- foreach( $deleted as $catName ) {
- $cat = Category::newFromName( $catName );
- wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $this ) );
- }
+ foreach ( $added as $catName ) {
+ $cat = Category::newFromName( $catName );
+ wfRunHooks( 'CategoryAfterPageAdded', array( $cat, $that ) );
+ }
+ foreach ( $deleted as $catName ) {
+ $cat = Category::newFromName( $catName );
+ wfRunHooks( 'CategoryAfterPageRemoved', array( $cat, $that ) );
+ }
+ }
+ );
}
/**
function doWork() {
global $wgUseFileCache;
- // @todo: several of the methods called on $this->page are not declared in Page, but present
+ // @todo several of the methods called on $this->page are not declared in Page, but present
// in WikiPage and delegated by Article.
$isCurrent = $this->revid === $this->page->getLatest();