Deprecate ContentHandler::makeParserOptions()
[lhc/web/wiklou.git] / includes / page / WikiPage.php
index 261c954..7cc25bd 100644 (file)
@@ -768,7 +768,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to $wgUser
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return Content|null The content of the current revision
         *
@@ -808,7 +808,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return int User ID for the user that made the last article revision
         */
@@ -827,7 +827,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return User|null
         */
@@ -846,7 +846,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return string Username of the user that made the last article revision
         */
@@ -864,7 +864,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   Revision::FOR_PUBLIC       to be displayed to all users
         *   Revision::FOR_THIS_USER    to be displayed to the given user
         *   Revision::RAW              get the text regardless of permissions
-        * @param User $user User object to check for, only if FOR_THIS_USER is passed
+        * @param User|null $user User object to check for, only if FOR_THIS_USER is passed
         *   to the $audience parameter
         * @return string Comment stored for the last article revision
         */
@@ -1306,10 +1306,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param IDatabase $dbw
         * @param Revision $revision For ID number, and text used to set
         *   length and redirect status fields
-        * @param int $lastRevision If given, will not overwrite the page field
+        * @param int|null $lastRevision If given, will not overwrite the page field
         *   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|null $lastRevIsRedirect If given, will optimize adding and
         *   removing rows in redirect table.
         * @return bool Success; false if the page row was missing or page_latest changed
         */
@@ -1664,13 +1664,17 @@ class WikiPage implements Page, IDBAccessObject {
         *        to perform updates, if the edit was already saved.
         * @param RevisionSlotsUpdate|null $forUpdate The new content to be saved by the edit (pre PST),
         *        if the edit was not yet saved.
+        * @param bool $forEdit Only re-use if the cached DerivedPageDataUpdater has the current
+        *       revision as the edit's parent revision. This ensures that the same
+        *       DerivedPageDataUpdater cannot be re-used for two consecutive edits.
         *
         * @return DerivedPageDataUpdater
         */
        private function getDerivedDataUpdater(
                User $forUser = null,
                RevisionRecord $forRevision = null,
-               RevisionSlotsUpdate $forUpdate = null
+               RevisionSlotsUpdate $forUpdate = null,
+               $forEdit = false
        ) {
                if ( !$forRevision && !$forUpdate ) {
                        // NOTE: can't re-use an existing derivedDataUpdater if we don't know what the caller is
@@ -1693,7 +1697,8 @@ class WikiPage implements Page, IDBAccessObject {
                        && !$this->derivedDataUpdater->isReusableFor(
                                $forUser,
                                $forRevision,
-                               $forUpdate
+                               $forUpdate,
+                               $forEdit ? $this->getLatest() : null
                        )
                ) {
                        $this->derivedDataUpdater = null;
@@ -1716,16 +1721,18 @@ class WikiPage implements Page, IDBAccessObject {
         * @since 1.32
         *
         * @param User $user
+        * @param RevisionSlotsUpdate|null $forUpdate If given, allows any cached ParserOutput
+        *        that may already have been returned via getDerivedDataUpdater to be re-used.
         *
         * @return PageUpdater
         */
-       public function newPageUpdater( User $user ) {
+       public function newPageUpdater( User $user, RevisionSlotsUpdate $forUpdate = null ) {
                global $wgAjaxEditStash, $wgUseAutomaticEditSummaries, $wgPageCreationLog;
 
                $pageUpdater = new PageUpdater(
                        $user,
                        $this, // NOTE: eventually, PageUpdater should not know about WikiPage
-                       $this->getDerivedDataUpdater( $user ),
+                       $this->getDerivedDataUpdater( $user, null, $forUpdate, true ),
                        $this->getDBLoadBalancer(),
                        $this->getRevisionStore()
                );
@@ -1774,8 +1781,8 @@ class WikiPage implements Page, IDBAccessObject {
         * restores or repeats. The new revision is expected to have the exact same content as
         * the given original revision. This is used with rollbacks and with dummy "null" revisions
         * which are created to record things like page moves.
-        * @param User $user The user doing the edit
-        * @param string $serialFormat IGNORED.
+        * @param User|null $user The user doing the edit
+        * @param string|null $serialFormat IGNORED.
         * @param array|null $tags Change tags to apply to this edit
         * Callers are responsible for permission checks
         * (with ChangeTags::canAddTagsAccompanyingChange)
@@ -1820,10 +1827,13 @@ class WikiPage implements Page, IDBAccessObject {
                        $flags = ( $flags & ~EDIT_MINOR );
                }
 
+               $slotsUpdate = new RevisionSlotsUpdate();
+               $slotsUpdate->modifyContent( 'main', $content );
+
                // NOTE: while doEditContent() executes, callbacks to getDerivedDataUpdater and
                // prepareContentForEdit will generally use the DerivedPageDataUpdater that is also
                // used by this PageUpdater. However, there is no guarantee for this.
-               $updater = $this->newPageUpdater( $user );
+               $updater = $this->newPageUpdater( $user, $slotsUpdate );
                $updater->setContent( 'main', $content );
                $updater->setOriginalRevisionId( $originalRevId );
                $updater->setUndidRevisionId( $undidRevId );
@@ -1860,7 +1870,7 @@ class WikiPage implements Page, IDBAccessObject {
        /**
         * Get parser options suitable for rendering the primary article wikitext
         *
-        * @see ContentHandler::makeParserOptions
+        * @see ParserOptions::newCanonical
         *
         * @param IContextSource|User|string $context One of the following:
         *        - IContextSource: Use the User and the Language of the provided
@@ -1872,7 +1882,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @return ParserOptions
         */
        public function makeParserOptions( $context ) {
-               $options = $this->getContentHandler()->makeParserOptions( $context );
+               $options = ParserOptions::newCanonical( $context );
 
                if ( $this->getTitle()->isConversionTable() ) {
                        // @todo ConversionTable should become a separate content model, so
@@ -1987,7 +1997,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param int &$cascade Set to false if cascading protection isn't allowed.
         * @param string $reason
         * @param User $user The user updating the restrictions
-        * @param string|string[] $tags Change tags to add to the pages and protection log entries
+        * @param string|string[]|null $tags Change tags to add to the pages and protection log entries
         *   ($user should be able to add the specified tags before this is called)
         * @return Status Status object; if action is taken, $status->value is the log_id of the
         *   protection log entry.
@@ -2403,10 +2413,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string $reason Delete reason for deletion log
         * @param bool $suppress Suppress all revisions and log the deletion in
         *        the suppression log instead of the deletion log
-        * @param int $u1 Unused
-        * @param bool $u2 Unused
+        * @param int|null $u1 Unused
+        * @param bool|null $u2 Unused
         * @param array|string &$error Array of errors to append to
-        * @param User $user The deleting user
+        * @param User|null $user The deleting user
         * @return bool True if successful
         */
        public function doDeleteArticle(
@@ -2425,10 +2435,10 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string $reason Delete reason for deletion log
         * @param bool $suppress Suppress all revisions and log the deletion in
         *   the suppression log instead of the deletion log
-        * @param int $u1 Unused
-        * @param bool $u2 Unused
+        * @param int|null $u1 Unused
+        * @param bool|null $u2 Unused
         * @param array|string &$error Array of errors to append to
-        * @param User $deleter The deleting user
+        * @param User|null $deleter The deleting user
         * @param array $tags Tags to apply to the deletion action
         * @param string $logsubtype
         * @return Status Status object; if successful, $status->value is the log_id of the
@@ -2527,22 +2537,30 @@ class WikiPage implements Page, IDBAccessObject {
                // Note array_intersect() preserves keys from the first arg, and we're
                // assuming $revQuery has `revision` primary and isn't using subtables
                // for anything we care about.
-               $res = $dbw->select(
+               $dbw->lockForUpdate(
                        array_intersect(
                                $revQuery['tables'],
                                [ 'revision', 'revision_comment_temp', 'revision_actor_temp' ]
                        ),
-                       '1',
                        [ 'rev_page' => $id ],
                        __METHOD__,
-                       'FOR UPDATE',
+                       [],
                        $revQuery['joins']
                );
-               foreach ( $res as $row ) {
-                       // Fetch all rows in case the DB needs that to properly lock them.
+
+               // If SCHEMA_COMPAT_WRITE_OLD is set, also select all extra fields we still write,
+               // so we can copy it to the archive table.
+               // We know the fields exist, otherwise SCHEMA_COMPAT_WRITE_OLD could not function.
+               if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
+                       $revQuery['fields'][] = 'rev_text_id';
+
+                       if ( $wgContentHandlerUseDB ) {
+                               $revQuery['fields'][] = 'rev_content_model';
+                               $revQuery['fields'][] = 'rev_content_format';
+                       }
                }
 
-               // Get all of the page revisions
+                       // Get all of the page revisions
                $res = $dbw->select(
                        $revQuery['tables'],
                        $revQuery['fields'],
@@ -2584,17 +2602,15 @@ class WikiPage implements Page, IDBAccessObject {
                        ] + $commentStore->insert( $dbw, 'ar_comment', $comment )
                                + $actorMigration->getInsertValues( $dbw, 'ar_user', $user );
 
-                       if ( $wgMultiContentRevisionSchemaMigrationStage < MIGRATION_NEW ) {
+                       if ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
                                $rowInsert['ar_text_id'] = $row->rev_text_id;
-                       }
 
-                       if (
-                               $wgContentHandlerUseDB &&
-                               $wgMultiContentRevisionSchemaMigrationStage <= MIGRATION_WRITE_BOTH
-                       ) {
-                               $rowInsert['ar_content_model'] = $row->rev_content_model;
-                               $rowInsert['ar_content_format'] = $row->rev_content_format;
+                               if ( $wgContentHandlerUseDB ) {
+                                       $rowInsert['ar_content_model'] = $row->rev_content_model;
+                                       $rowInsert['ar_content_format'] = $row->rev_content_format;
+                               }
                        }
+
                        $rowsInsert[] = $rowInsert;
                        $revids[] = $row->rev_id;