* @file
*/
+use \MediaWiki\Logger\LoggerFactory;
+
/**
* Class representing a MediaWiki article and history.
*
return false;
}
- $title = $this->mTitle;
- wfGetDB( DB_MASTER )->onTransactionIdle( function() use ( $title ) {
- // Invalidate the cache in auto-commit mode
- $title->invalidateCache();
- } );
-
+ $this->mTitle->invalidateCache();
// Send purge after above page_touched update was committed
DeferredUpdates::addUpdate(
- new CdnCacheUpdate( $title->getCdnUrls() ),
+ new CdnCacheUpdate( $this->mTitle->getCdnUrls() ),
DeferredUpdates::PRESEND
);
}
// Do secondary updates once the main changes have been committed...
- $that = $this;
- $dbw->onTransactionIdle(
- function () use (
- $dbw, &$that, $revision, &$user, $content, $summary, &$flags,
- $changed, $meta, &$status
- ) {
- // Do per-page updates in a transaction
- $dbw->setFlag( DBO_TRX );
- // Update links tables, site stats, etc.
- $that->doEditUpdates(
- $revision,
- $user,
- [
- 'changed' => $changed,
- 'oldcountable' => $meta['oldCountable'],
- 'oldrevision' => $meta['oldRevision']
- ]
- );
- // Trigger post-save hook
- $params = [ &$that, &$user, $content, $summary, $flags & EDIT_MINOR,
- null, null, &$flags, $revision, &$status, $meta['baseRevId'] ];
- ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
- Hooks::run( 'PageContentSaveComplete', $params );
- }
+ DeferredUpdates::addUpdate(
+ new AtomicSectionUpdate(
+ $dbw,
+ __METHOD__,
+ function () use (
+ $revision, &$user, $content, $summary, &$flags,
+ $changed, $meta, &$status
+ ) {
+ // Update links tables, site stats, etc.
+ $this->doEditUpdates(
+ $revision,
+ $user,
+ [
+ 'changed' => $changed,
+ 'oldcountable' => $meta['oldCountable'],
+ 'oldrevision' => $meta['oldRevision']
+ ]
+ );
+ // Trigger post-save hook
+ $params = [ &$this, &$user, $content, $summary, $flags & EDIT_MINOR,
+ null, null, &$flags, $revision, &$status, $meta['baseRevId'] ];
+ ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
+ Hooks::run( 'PageContentSaveComplete', $params );
+ }
+ ),
+ DeferredUpdates::PRESEND
);
return $status;
$status->value['revision'] = $revision;
// Do secondary updates once the main changes have been committed...
- $that = $this;
- $dbw->onTransactionIdle(
- function () use (
- &$that, $dbw, $revision, &$user, $content, $summary, &$flags, $meta, &$status
- ) {
- // Do per-page updates in a transaction
- $dbw->setFlag( DBO_TRX );
- // Update links, etc.
- $that->doEditUpdates( $revision, $user, [ 'created' => true ] );
- // Trigger post-create hook
- $params = [ &$that, &$user, $content, $summary,
- $flags & EDIT_MINOR, null, null, &$flags, $revision ];
- ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $params );
- Hooks::run( 'PageContentInsertComplete', $params );
- // Trigger post-save hook
- $params = array_merge( $params, [ &$status, $meta['baseRevId'] ] );
- ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
- Hooks::run( 'PageContentSaveComplete', $params );
+ DeferredUpdates::addUpdate(
+ new AtomicSectionUpdate(
+ $dbw,
+ __METHOD__,
+ function () use (
+ $revision, &$user, $content, $summary, &$flags, $meta, &$status
+ ) {
+ // Update links, etc.
+ $this->doEditUpdates( $revision, $user, [ 'created' => true ] );
+ // Trigger post-create hook
+ $params = [ &$this, &$user, $content, $summary,
+ $flags & EDIT_MINOR, null, null, &$flags, $revision ];
+ ContentHandler::runLegacyHooks( 'ArticleInsertComplete', $params );
+ Hooks::run( 'PageContentInsertComplete', $params );
+ // Trigger post-save hook
+ $params = array_merge( $params, [ &$status, $meta['baseRevId'] ] );
+ ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
+ Hooks::run( 'PageContentSaveComplete', $params );
- }
+ }
+ )
);
return $status;
}
if ( $this->mPreparedEdit
- && $this->mPreparedEdit->newContent
+ && isset( $this->mPreparedEdit->newContent )
&& $this->mPreparedEdit->newContent->equals( $content )
&& $this->mPreparedEdit->revid == $revid
&& $this->mPreparedEdit->format == $serialFormat
}
}
);
+ } else {
+ // Try to avoid a second parse if {{REVISIONID}} is used
+ $edit->popts->setSpeculativeRevIdCallback( function () {
+ return 1 + (int)wfGetDB( DB_MASTER )->selectField(
+ 'revision',
+ 'MAX(rev_id)',
+ [],
+ __METHOD__
+ );
+ } );
}
$edit->output = $edit->pstContent
? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts )
];
$content = $revision->getContent();
+ $logger = LoggerFactory::getInstance( 'SaveParse' );
+
// See if the parser output before $revision was inserted is still valid
$editInfo = false;
if ( !$this->mPreparedEdit ) {
- wfDebug( __METHOD__ . ": No prepared edit...\n" );
+ $logger->debug( __METHOD__ . ": No prepared edit...\n" );
} elseif ( $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
- wfDebug( __METHOD__ . ": Prepared edit has vary-revision...\n" );
+ $logger->info( __METHOD__ . ": Prepared edit has vary-revision...\n" );
+ } elseif ( $this->mPreparedEdit->output->getFlag( 'vary-revision-id' )
+ && $this->mPreparedEdit->output->getSpeculativeRevIdUsed() !== $revision->getId()
+ ) {
+ $logger->info( __METHOD__ . ": Prepared edit has vary-revision-id with wrong ID...\n" );
} elseif ( $this->mPreparedEdit->output->getFlag( 'vary-user' ) && !$options['changed'] ) {
- wfDebug( __METHOD__ . ": Prepared edit has vary-user and is null...\n" );
+ $logger->info( __METHOD__ . ": Prepared edit has vary-user and is null...\n" );
} else {
wfDebug( __METHOD__ . ": Using prepared edit...\n" );
$editInfo = $this->mPreparedEdit;
$title->touchLinks();
$title->purgeSquid();
$title->deleteTitleProtection();
+
+ if ( $title->getNamespace() == NS_CATEGORY ) {
+ // Load the Category object, which will schedule a job to create
+ // the category table row if necessary. Checking a slave is ok
+ // here, in the worst case it'll run an unnecessary recount job on
+ // a category that probably doesn't have many members.
+ Category::newFromTitle( $title )->getID();
+ }
}
/**
*
* @param array $added The names of categories that were added
* @param array $deleted The names of categories that were deleted
+ * @param integer $id Page ID (this should be the original deleted page ID)
*/
- public function updateCategoryCounts( array $added, array $deleted ) {
- $that = $this;
- $method = __METHOD__;
+ public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) {
+ $id = $id ?: $this->getId();
$dbw = wfGetDB( DB_MASTER );
-
+ $method = __METHOD__;
// 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();
+ function () use ( $dbw, $added, $deleted, $id, $method ) {
+ $ns = $this->getTitle()->getNamespace();
$addFields = [ 'cat_pages = cat_pages + 1' ];
$removeFields = [ 'cat_pages = cat_pages - 1' ];
'category',
'cat_title',
[ 'cat_title' => $added ],
- __METHOD__
+ $method
);
// For category rows that already exist, do a plain
'category',
$addFields,
[ 'cat_title' => $existingAdded ],
- __METHOD__
+ $method
);
}
foreach ( $added as $catName ) {
$cat = Category::newFromName( $catName );
- Hooks::run( 'CategoryAfterPageAdded', [ $cat, $that ] );
+ Hooks::run( 'CategoryAfterPageAdded', [ $cat, $this ] );
}
foreach ( $deleted as $catName ) {
$cat = Category::newFromName( $catName );
- Hooks::run( 'CategoryAfterPageRemoved', [ $cat, $that ] );
+ Hooks::run( 'CategoryAfterPageRemoved', [ $cat, $this, $id ] );
+ }
+
+ // Refresh counts on categories that should be empty now, to
+ // trigger possible deletion. Check master for the most
+ // up-to-date cat_pages.
+ if ( count( $deleted ) ) {
+ $rows = $dbw->select(
+ 'category',
+ [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
+ [ 'cat_title' => $deleted, 'cat_pages <= 0' ],
+ $method
+ );
+ foreach ( $rows as $row ) {
+ $cat = Category::newFromRow( $row );
+ $cat->refreshCounts();
+ }
}
}
);