X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fpage%2FWikiPage.php;h=f34e894d722460393881fc96c3948b431941344e;hb=216865344b108082f9500b5eb8cd5efeaa7df72f;hp=b97082084d8d5cde3abe22cc22965b5e1189dbec;hpb=c2f3a2c5a40f9138b531e378e47da169f151854b;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php index b97082084d..f34e894d72 100644 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@ -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 ); @@ -1935,7 +1945,7 @@ class WikiPage implements Page, IDBAccessObject { $updater = $this->getDerivedDataUpdater( $user, $revision, $slots ); if ( !$updater->isUpdatePrepared() ) { - $updater->prepareContent( $user, $slots, [], $useCache ); + $updater->prepareContent( $user, $slots, $useCache ); if ( $revision ) { $updater->prepareUpdate( $revision ); @@ -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,30 +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. - $tablesFlat = []; - array_walk_recursive( - $revQuery['tables'], - function ( $a ) use ( &$tablesFlat ) { - $tablesFlat[] = $a; - } - ); - - $res = $dbw->select( + $dbw->lockForUpdate( array_intersect( - $tablesFlat, + $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'], @@ -2592,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; @@ -2967,9 +2975,16 @@ class WikiPage implements Page, IDBAccessObject { } $updater->setOriginalRevisionId( $target->getId() ); - $updater->setUndidRevisionId( $current->getId() ); + // Do not call setUndidRevisionId(), that causes an extra "mw-undo" tag to be added (T190374) $updater->addTags( $tags ); + // TODO: this logic should not be in the storage layer, it's here for compatibility + // with 1.31 behavior. Applying the 'autopatrol' right should be done in the same + // place the 'bot' right is handled, which is currently in EditPage::attemptSave. + if ( $wgUseRCPatrol && $this->getTitle()->userCan( 'autopatrol', $guser ) ) { + $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED ); + } + // Actually store the rollback $rev = $updater->saveRevision( CommentStoreComment::newUnsavedComment( $summary ), @@ -3259,16 +3274,13 @@ class WikiPage implements Page, IDBAccessObject { */ public function updateCategoryCounts( array $added, array $deleted, $id = 0 ) { $id = $id ?: $this->getId(); - $ns = $this->getTitle()->getNamespace(); + $type = MWNamespace::getCategoryLinkType( $this->getTitle()->getNamespace() ); $addFields = [ 'cat_pages = cat_pages + 1' ]; $removeFields = [ '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 ( $type !== 'page' ) { + $addFields[] = "cat_{$type}s = cat_{$type}s + 1"; + $removeFields[] = "cat_{$type}s = cat_{$type}s - 1"; } $dbw = wfGetDB( DB_MASTER ); @@ -3300,8 +3312,8 @@ class WikiPage implements Page, IDBAccessObject { $insertRows[] = [ 'cat_title' => $cat, 'cat_pages' => 1, - 'cat_subcats' => ( $ns == NS_CATEGORY ) ? 1 : 0, - 'cat_files' => ( $ns == NS_FILE ) ? 1 : 0, + 'cat_subcats' => ( $type === 'subcat' ) ? 1 : 0, + 'cat_files' => ( $type === 'file' ) ? 1 : 0, ]; } $dbw->upsert(