50use Wikimedia\Assert\Assert;
198 $this->rcPatrolStatus =
$status;
209 $this->usePageCreationLog = $use;
230 return $this->loadBalancer->getConnectionRef( $mode, [], $this->
getWikiId() );
238 return $this->wikiPage->getTitle();
246 return $this->wikiPage->getTitle();
292 $parentId = $parent ? $parent->getId() : 0;
294 return $parentId !== $expectedParentRevision;
325 return $this->derivedDataUpdater->grabCurrentRevision();
351 $this->slotsUpdate->modifyContent( $role,
$content );
362 $this->slotsUpdate->modifySlot( $slot );
384 $inheritedSlot = SlotRecord::newInherited( $originalSlot );
385 $this->slotsUpdate->modifySlot( $inheritedSlot );
400 $this->slotsUpdate->removeSlot( $role );
425 Assert::parameterType(
'integer|boolean',
$originalRevId,
'$originalRevId' );
447 Assert::parameterType(
'integer',
$undidRevId,
'$undidRevId' );
458 Assert::parameterType(
'string', $tag,
'$tag' );
459 $this->tags[] = trim( $tag );
469 Assert::parameterElementType(
'string',
$tags,
'$tags' );
470 foreach (
$tags as $tag ) {
491 foreach ( $this->slotsUpdate->getModifiedRoles() as $role ) {
495 $content = $this->slotsUpdate->getModifiedSlot( $role )->getContent();
498 $tag = $handler->getChangeTag( $old_content,
$content, $flags );
510 return array_unique(
$tags );
523 if ( $parent && $parent->hasSlot( $role ) ) {
524 return $parent->getContent( $role, RevisionRecord::RAW );
536 if ( $this->slotsUpdate->isModifiedSlot( $role ) ) {
537 $slot = $this->slotsUpdate->getModifiedSlot( $role );
542 $slot = $parent->getSlot( $role, RevisionRecord::RAW );
548 return ContentHandler::getForModelID( $slot->getModel() );
557 if ( !$this->useAutomaticEditSummaries || ( $flags &
EDIT_AUTOSUMMARY ) === 0 ) {
558 return CommentStoreComment::newUnsavedComment(
'' );
564 $roles = $this->slotsUpdate->getModifiedRoles();
565 $role = reset( $roles );
567 if ( $role ===
false ) {
568 return CommentStoreComment::newUnsavedComment(
'' );
572 $content = $this->slotsUpdate->getModifiedSlot( $role )->getContent();
574 $summary = $handler->getAutosummary( $old_content,
$content, $flags );
576 return CommentStoreComment::newUnsavedComment( $summary );
627 Assert::parameterType(
'integer', $flags,
'$flags' );
630 throw new RuntimeException(
'saveRevision() has already been called on this PageUpdater!' );
635 throw new RuntimeException(
'Something is trying to edit an article with an empty title' );
641 $this->slotsUpdate->getModifiedRoles(),
645 $this->slotsUpdate->getRemovedRoles(),
654 foreach ( $this->slotsUpdate->getModifiedRoles() as $role ) {
655 $slot = $this->slotsUpdate->getModifiedSlot( $role );
656 $roleHandler = $this->slotRoleRegistry->getRoleHandler( $role );
658 if ( !$roleHandler->isAllowedModel( $slot->getModel(), $this->getTitle() ) ) {
659 $contentHandler = ContentHandler::getForModelID( $slot->getModel() );
660 $this->status = Status::newFatal(
'content-not-allowed-here',
661 ContentHandler::getLocalizedName( $contentHandler->getModelID() ),
662 $this->getTitle()->getPrefixedText(),
663 wfMessage( $roleHandler->getNameMessageKey() )
691 $this->derivedDataUpdater->prepareContent(
725 $this->derivedDataUpdater->getCanonicalParserOutput();
727 $mainContent = $this->derivedDataUpdater->getSlots()->getContent( SlotRecord::MAIN );
730 $hookStatus = Status::newGood( [] );
734 $flags &
EDIT_MINOR,
null,
null, &$flags, &$hookStatus ];
736 if ( !Hooks::run(
'PageContentSave', $hook_args ) ) {
737 if ( $hookStatus->isOK() ) {
739 $hookStatus->fatal(
'edit-hook-aborted' );
742 $this->status = $hookStatus;
749 if ( $summary->text ===
'' && $summary->data ===
null ) {
762 DeferredUpdates::addCallableUpdate(
function () use (
$user ) {
772 return ( $this->status && $this->status->isOK() )
773 ? $this->status->value[
'revision-record']
783 return $this->status !==
null;
819 return $this->status && $this->status->isOK();
828 return $this->status && $this->status->isOK() && $this->status->value[
'new'];
840 && $this->status->isOK()
841 && $this->status->value[
'revision-record'] ===
null;
851 return ( $this->status && $this->status->isOK() )
852 ? $this->status->value[
'revision-record']
884 $rev = $this->derivedDataUpdater->getRevision();
885 '@phan-var MutableRevisionRecord $rev';
887 $rev->setPageId(
$title->getArticleID() );
890 $oldid = $parent->getId();
891 $rev->setParentId( $oldid );
896 $rev->setComment( $comment );
897 $rev->setUser(
$user );
898 $rev->setMinorEdit( ( $flags &
EDIT_MINOR ) > 0 );
900 foreach ( $rev->getSlots()->getSlots() as $slot ) {
913 $rev->getSlotRoles(),
932 $status = Status::newGood( [
'new' =>
false,
'revision' =>
null,
'revision-record' =>
null ] );
935 $oldid = $oldRev ? $oldRev->getId() : 0;
955 $now = $newRevisionRecord->getTimestamp();
958 $changed = $this->derivedDataUpdater->isChange();
963 $dbw->startAtomic( __METHOD__ );
969 if ( $latestNow != $oldid ) {
973 $dbw->endAtomic( __METHOD__ );
986 $newRevisionRecord = $this->revisionStore->insertRevisionOn( $newRevisionRecord, $dbw );
987 $newLegacyRevision =
new Revision( $newRevisionRecord );
991 $wasRedirect = $this->derivedDataUpdater->wasRedirect();
999 'NewRevisionFromEditComplete',
1006 RecentChange::notifyEdit(
1009 $newRevisionRecord->isMinor(),
1013 $newRevisionRecord->getTimestamp(),
1017 $newRevisionRecord->getSize(),
1018 $newRevisionRecord->getId(),
1019 $this->rcPatrolStatus,
1026 $dbw->endAtomic( __METHOD__ );
1029 $status->value[
'revision-record'] = $newRevisionRecord;
1032 $status->value[
'revision'] = $newLegacyRevision;
1038 $newRevisionRecord = $oldRev;
1044 $this->
getTitle()->invalidateCache( $now );
1053 DeferredUpdates::addUpdate(
1062 [
'changed' => $changed, ]
1064 DeferredUpdates::PRESEND
1082 if ( !$this->derivedDataUpdater->getSlots()->hasSlot( SlotRecord::MAIN ) ) {
1086 $status = Status::newGood( [
'new' =>
true,
'revision' =>
null,
'revision-record' =>
null ] );
1099 $now = $newRevisionRecord->getTimestamp();
1102 $dbw->startAtomic( __METHOD__ );
1107 if ( $newid ===
false ) {
1108 $dbw->endAtomic( __METHOD__ );
1118 $newRevisionRecord->setPageId( $newid );
1121 $newRevisionRecord = $this->revisionStore->insertRevisionOn( $newRevisionRecord, $dbw );
1122 $newLegacyRevision =
new Revision( $newRevisionRecord );
1133 'NewRevisionFromEditComplete',
1140 RecentChange::notifyNew(
1143 $newRevisionRecord->isMinor(),
1148 $newRevisionRecord->getSize(),
1149 $newRevisionRecord->getId(),
1150 $this->rcPatrolStatus,
1157 if ( $this->usePageCreationLog ) {
1161 $logEntry->setPerformer(
$user );
1162 $logEntry->setTarget( $this->
getTitle() );
1163 $logEntry->setComment( $summary->text );
1164 $logEntry->setTimestamp( $now );
1165 $logEntry->setAssociatedRevId( $newRevisionRecord->getId() );
1166 $logEntry->insert();
1172 $dbw->endAtomic( __METHOD__ );
1176 $status->value[
'revision'] = $newLegacyRevision;
1177 $status->value[
'revision-record'] = $newRevisionRecord;
1180 DeferredUpdates::addUpdate(
1189 [
'created' =>
true ]
1191 DeferredUpdates::PRESEND
1212 $summary, $flags,
$status, $hints
1215 $hints[
'causeAction'] =
'edit-page';
1218 $newLegacyRevision =
new Revision( $newRevisionRecord );
1219 $mainContent = $newRevisionRecord->
getContent( SlotRecord::MAIN, RevisionRecord::RAW );
1222 $this->derivedDataUpdater->prepareUpdate( $newRevisionRecord, $hints );
1223 $this->derivedDataUpdater->doUpdates();
1228 if ( $hints[
'created'] ??
false ) {
1231 $flags &
EDIT_MINOR,
null,
null, &$flags, $newLegacyRevision ];
1232 Hooks::run(
'PageContentInsertComplete', $params );
1237 $flags &
EDIT_MINOR,
null,
null, &$flags, $newLegacyRevision,
1239 Hooks::run(
'PageContentSaveComplete', $params );
1248 return $this->slotRoleRegistry->getRequiredRoles( $this->
getTitle() );
1255 return $this->slotRoleRegistry->getAllowedRoles( $this->
getTitle() );
1260 if ( !in_array( $role, $allowedRoles ) ) {
1267 if ( in_array( $role, $requiredRoles ) ) {
1275 $forbidden = array_diff( $roles, $allowedRoles );
1276 if ( !empty( $forbidden ) ) {
1278 'edit-slots-cannot-add',
1279 count( $forbidden ),
1280 implode(
', ', $forbidden )
1288 $needed = array_diff( $roles, $requiredRoles );
1289 if ( !empty( $needed ) ) {
1291 'edit-slots-cannot-remove',
1293 implode(
', ', $needed )
1301 $missing = array_diff( $requiredRoles, $roles );
1302 if ( !empty( $missing ) ) {
1304 'edit-slots-missing',
1306 implode(
', ', $missing )
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Deferrable Update for closure/callback updates via IDatabase::doAtomicSection()
A content handler knows how do deal with a specific type of content on a wiki page.
Class for managing the deferred updates.
Class for creating new log entries and inserting them into the database.
A handle for managing updates for derived page data on edit, import, purge, etc.
Exception representing a failure to update a page entry.
Controller-like object for creating and updating pages by creating new revisions.
getStatus()
The Status object indicating whether saveRevision() was successful, or null if saveRevision() was not...
getUndidRevisionId()
Returns the revision ID set by setUndidRevisionId(), indicating what revision is being undone by this...
computeEffectiveTags( $flags)
inheritSlot(SlotRecord $originalSlot)
Explicitly inherit a slot from some earlier revision.
wasSuccessful()
Whether saveRevision() completed successfully.
boolean $ajaxEditStash
see $wgAjaxEditStash
ILoadBalancer $loadBalancer
RevisionSlotsUpdate $slotsUpdate
saveRevision(CommentStoreComment $summary, $flags=0)
Change an existing article or create a new article.
isNew()
Whether saveRevision() was called and created a new page.
checkFlags( $flags)
Check flags and add EDIT_NEW or EDIT_UPDATE to them as needed.
addTag( $tag)
Sets a tag to apply to this update.
checkAllRolesAllowed(array $roles, Status $status)
isUnchanged()
Whether saveRevision() did not create a revision because the content didn't change (null-edit).
int $rcPatrolStatus
the RC patrol status the new revision should be marked with.
checkNoRolesRequired(array $roles, Status $status)
getParentContent( $role)
Returns the content of the given slot of the parent revision, with no audience checks applied.
getAtomicSectionUpdate(IDatabase $dbw, WikiPage $wikiPage, RevisionRecord $newRevisionRecord, User $user, CommentStoreComment $summary, $flags, Status $status, $hints=[])
getContentHandler( $role)
makeNewRevision(CommentStoreComment $comment, User $user, $flags, Status $status)
Constructs a MutableRevisionRecord based on the Content prepared by the DerivedPageDataUpdater.
getNewRevision()
The new revision created by saveRevision(), or null if saveRevision() has not yet been called,...
SlotRoleRegistry $slotRoleRegistry
setUsePageCreationLog( $use)
Whether to create a log entry for new page creations.
removeSlot( $role)
Removes the slot with the given role.
checkAllRequiredRoles(array $roles, Status $status)
setOriginalRevisionId( $originalRevId)
Sets the ID of an earlier revision that is being repeated or restored by this update.
addTags(array $tags)
Sets tags to apply to this update.
setUseAutomaticEditSummaries( $useAutomaticEditSummaries)
Can be used to enable or disable automatic summaries that are applied to certain kinds of changes,...
grabParentRevision()
Returns the revision that was the page's current revision when grabParentRevision() was first called.
hasEditConflict( $expectedParentRevision)
Checks whether this update conflicts with another update performed between the client loading data to...
getDBConnectionRef( $mode)
doCreate(CommentStoreComment $summary, User $user, $flags)
setRcPatrolStatus( $status)
Sets the "patrolled" status of the edit.
ensureRoleNotRequired( $role)
setUndidRevisionId( $undidRevId)
Sets the ID of revision that was undone by the present update.
wasCommitted()
Whether saveRevision() has been called on this instance.
setAjaxEditStash( $ajaxEditStash)
doModify(CommentStoreComment $summary, User $user, $flags)
DerivedPageDataUpdater $derivedDataUpdater
getExplicitTags()
Returns the list of tags set using the addTag() method.
boolean $useAutomaticEditSummaries
see $wgUseAutomaticEditSummaries
ensureRoleAllowed( $role)
__construct(User $user, WikiPage $wikiPage, DerivedPageDataUpdater $derivedDataUpdater, ILoadBalancer $loadBalancer, RevisionStore $revisionStore, SlotRoleRegistry $slotRoleRegistry)
setSlot(SlotRecord $slot)
Set the new slot for the given slot role.
bool $usePageCreationLog
whether to create a log entry for new page creations.
setContent( $role, Content $content)
Set the new content for the given slot role.
getOriginalRevisionId()
Returns the ID of an earlier revision that is being repeated or restored by this update.
RevisionStore $revisionStore
Utility class for creating new RC entries.
isOK()
Returns whether the operation completed.
fatal( $message,... $parameters)
Add an error and set OK to false, indicating that the operation as a whole was fatal.
merge( $other, $overwriteValue=false)
Merge another status object into this one.
error( $message,... $parameters)
Add an error, do not set fatal flag This can be used for non-fatal errors.
warning( $message,... $parameters)
Add a new warning.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
getName()
Get the user name, or the IP of an anonymous user.
addAutopromoteOnceGroups( $event)
Add the user to the group if he/she meets given criteria.
incEditCount()
Schedule a deferred update to update the user's edit count.
Class representing a MediaWiki article and history.
insertOn( $dbw, $pageId=null)
Insert a new empty page record for this article.
updateRevisionOn( $dbw, $revision, $lastRevision=null, $lastRevIsRedirect=null)
Update the page record to point to a newly saved revision.
lockAndGetLatest()
Lock the page row for this title+id and return page_latest (or 0)
Base interface for content objects.