Merge "Make change tagging of edits in RecentChange::notifyNew/Edit"
[lhc/web/wiklou.git] / includes / page / WikiPage.php
index c02f975..cfd8d6b 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 /**
- * Abstract class for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
+ * Interface for type hinting (accepts WikiPage, Article, ImagePage, CategoryPage)
  */
 interface Page {
 }
@@ -1636,6 +1636,9 @@ class WikiPage implements Page, IDBAccessObject {
         * @param User $user The user doing the edit
         * @param string $serialFormat Format for storing the content in the
         *   database.
+        * @param array|null $tags Change tags to apply to this edit
+        * Callers are responsible for permission checks
+        * (with ChangeTags::canAddTagsAccompanyingChange)
         *
         * @throws MWException
         * @return Status Possible errors:
@@ -1657,7 +1660,7 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function doEditContent(
                Content $content, $summary, $flags = 0, $baseRevId = false,
-               User $user = null, $serialFormat = null
+               User $user = null, $serialFormat = null, $tags = null
        ) {
                global $wgUser, $wgUseAutomaticEditSummaries;
 
@@ -1719,7 +1722,8 @@ class WikiPage implements Page, IDBAccessObject {
                        'oldContent' => $old_content,
                        'oldId' => $this->getLatest(),
                        'oldIsRedirect' => $this->isRedirect(),
-                       'oldCountable' => $this->isCountable()
+                       'oldCountable' => $this->isCountable(),
+                       'tags' => ( $tags !== null ) ? (array)$tags : array()
                );
 
                // Actually create the revision and create/update the page
@@ -1793,6 +1797,8 @@ class WikiPage implements Page, IDBAccessObject {
 
                $changed = !$content->equals( $oldContent );
 
+               $dbw = wfGetDB( DB_MASTER );
+
                if ( $changed ) {
                        $prepStatus = $content->prepareSave( $this, $flags, $oldid, $user );
                        $status->merge( $prepStatus );
@@ -1800,14 +1806,13 @@ class WikiPage implements Page, IDBAccessObject {
                                return $status;
                        }
 
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->begin( __METHOD__ );
+                       $dbw->startAtomic( __METHOD__ );
                        // Get the latest page_latest value while locking it.
                        // Do a CAS style check to see if it's the same as when this method
                        // started. If it changed then bail out before touching the DB.
                        $latestNow = $this->lockAndGetLatest();
                        if ( $latestNow != $oldid ) {
-                               $dbw->commit( __METHOD__ );
+                               $dbw->endAtomic( __METHOD__ );
                                // Page updated or deleted in the mean time
                                $status->fatal( 'edit-conflict' );
 
@@ -1849,13 +1854,14 @@ class WikiPage implements Page, IDBAccessObject {
                                        $oldContent ? $oldContent->getSize() : 0,
                                        $newsize,
                                        $revisionId,
-                                       $patrolled
+                                       $patrolled,
+                                       $meta['tags']
                                );
                        }
 
                        $user->incEditCount();
 
-                       $dbw->commit( __METHOD__ );
+                       $dbw->endAtomic( __METHOD__ );
                        $this->mTimestamp = $now;
                } else {
                        // Bug 32948: revision ID must be set to page {{REVISIONID}} and
@@ -1863,17 +1869,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $revision->setId( $this->getLatest() );
                }
 
-               // Update links tables, site stats, etc.
-               $this->doEditUpdates(
-                       $revision,
-                       $user,
-                       array(
-                               'changed' => $changed,
-                               'oldcountable' => $meta['oldCountable'],
-                               'oldrevision' => $meta['oldRevision']
-                       )
-               );
-
                if ( $changed ) {
                        // Return the new revision to the caller
                        $status->value['revision'] = $revision;
@@ -1884,11 +1879,32 @@ class WikiPage implements Page, IDBAccessObject {
                        $this->mTitle->invalidateCache( $now );
                }
 
-               // Trigger post-save hook
-               $hook_args = array( &$this, &$user, $content, $summary,
-                       $flags & EDIT_MINOR, null, null, &$flags, $revision, &$status, $meta['baseRevId'] );
-               ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $hook_args );
-               Hooks::run( 'PageContentSaveComplete', $hook_args );
+               // 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,
+                                       array(
+                                               'changed' => $changed,
+                                               'oldcountable' => $meta['oldCountable'],
+                                               'oldrevision' => $meta['oldRevision']
+                                       )
+                               );
+                               // Trigger post-save hook
+                               $params = array( &$that, &$user, $content, $summary, $flags & EDIT_MINOR,
+                                       null, null, &$flags, $revision, &$status, $meta['baseRevId'] );
+                               ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
+                               Hooks::run( 'PageContentSaveComplete', $params );
+                       }
+               );
 
                return $status;
        }
@@ -1978,7 +1994,8 @@ class WikiPage implements Page, IDBAccessObject {
                                '',
                                $newsize,
                                $revisionId,
-                               $patrolled
+                               $patrolled,
+                               $meta['tags']
                        );
                }
 
@@ -2200,7 +2217,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   - 'no-change': don't update the article count, ever
         */
        public function doEditUpdates( Revision $revision, User $user, array $options = array() ) {
-               global $wgRCWatchCategoryMembership;
+               global $wgRCWatchCategoryMembership, $wgContLang;
 
                $options += array(
                        'changed' => true,
@@ -2329,6 +2346,10 @@ class WikiPage implements Page, IDBAccessObject {
                        }
 
                        MessageCache::singleton()->replace( $shortTitle, $msgtext );
+
+                       if ( $wgContLang->hasVariants() ) {
+                               $wgContLang->updateConversionTable( $this->mTitle );
+                       }
                }
 
                if ( $options['created'] ) {
@@ -3048,13 +3069,17 @@ class WikiPage implements Page, IDBAccessObject {
         *    success        : 'summary' (str), 'current' (rev), 'target' (rev)
         *
         * @param User $user The user performing the rollback
+        * @param array|null $tags Change tags to apply to the rollback
+        * Callers are responsible for permission checks
+        * (with ChangeTags::canAddTagsAccompanyingChange)
+        *
         * @return array Array of errors, each error formatted as
         *   array(messagekey, param1, param2, ...).
         * On success, the array is empty.  This array can also be passed to
         * OutputPage::showPermissionsErrorPage().
         */
        public function doRollback(
-               $fromP, $summary, $token, $bot, &$resultDetails, User $user
+               $fromP, $summary, $token, $bot, &$resultDetails, User $user, $tags = null
        ) {
                $resultDetails = null;
 
@@ -3076,7 +3101,7 @@ class WikiPage implements Page, IDBAccessObject {
                        return $errors;
                }
 
-               return $this->commitRollback( $fromP, $summary, $bot, $resultDetails, $user );
+               return $this->commitRollback( $fromP, $summary, $bot, $resultDetails, $user, $tags );
        }
 
        /**
@@ -3093,9 +3118,15 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param array $resultDetails Contains result-specific array of additional values
         * @param User $guser The user performing the rollback
+        * @param array|null $tags Change tags to apply to the rollback
+        * Callers are responsible for permission checks
+        * (with ChangeTags::canAddTagsAccompanyingChange)
+        *
         * @return array
         */
-       public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser ) {
+       public function commitRollback( $fromP, $summary, $bot,
+               &$resultDetails, User $guser, $tags = null
+       ) {
                global $wgUseRCPatrol, $wgContLang;
 
                $dbw = wfGetDB( DB_MASTER );
@@ -3190,7 +3221,9 @@ class WikiPage implements Page, IDBAccessObject {
                        $summary,
                        $flags,
                        $target->getId(),
-                       $guser
+                       $guser,
+                       null,
+                       $tags
                );
 
                // Set patrolling and bot flag on the edits, which gets rollbacked.
@@ -3276,6 +3309,8 @@ class WikiPage implements Page, IDBAccessObject {
         * @param Title $title
         */
        public static function onArticleDelete( Title $title ) {
+               global $wgContLang;
+
                // Update existence markers on article/talk tabs...
                $other = $title->getOtherPage();
 
@@ -3291,6 +3326,10 @@ class WikiPage implements Page, IDBAccessObject {
                // Messages
                if ( $title->getNamespace() == NS_MEDIAWIKI ) {
                        MessageCache::singleton()->replace( $title->getDBkey(), false );
+
+                       if ( $wgContLang->hasVariants() ) {
+                               $wgContLang->updateConversionTable( $title );
+                       }
                }
 
                // Images