use Psr\Log\NullLogger;
use RecentChange;
use Revision;
+use RuntimeException;
use stdClass;
use Title;
use User;
$slotRoles = $rev->getSlotRoles();
// Make sure the main slot is always provided throughout migration
- if ( !in_array( 'main', $slotRoles ) ) {
+ if ( !in_array( SlotRecord::MAIN, $slotRoles ) ) {
throw new InvalidArgumentException(
'main slot must be provided'
);
}
// If we are not writing into the new schema, we can't support extra slots.
- if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW ) && $slotRoles !== [ 'main' ] ) {
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_NEW )
+ && $slotRoles !== [ SlotRecord::MAIN ]
+ ) {
throw new InvalidArgumentException(
'Only the main slot is supported when not writing to the MCR enabled schema!'
);
}
// As long as we are not reading from the new schema, we don't want to write extra slots.
- if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) && $slotRoles !== [ 'main' ] ) {
+ if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW )
+ && $slotRoles !== [ SlotRecord::MAIN ]
+ ) {
throw new InvalidArgumentException(
'Only the main slot is supported when not reading from the MCR enabled schema!'
);
// Technically, this could go away after MCR migration: while
// calling code may require a main slot to exist, RevisionStore
// really should not know or care about that requirement.
- $rev->getSlot( 'main', RevisionRecord::RAW );
+ $rev->getSlot( SlotRecord::MAIN, RevisionRecord::RAW );
foreach ( $slotRoles as $role ) {
$slot = $rev->getSlot( $role, RevisionRecord::RAW );
Assert::postcondition(
$slot->getContent() !== null,
- $role . ' slot must have content'
+ $role . ' slot must have content'
);
Assert::postcondition(
$slot->hasRevision(),
- $role . ' slot must have a revision associated'
+ $role . ' slot must have a revision associated'
);
}
$newSlots[$role] = $slot;
// Write the main slot's text ID to the revision table for backwards compatibility
- if ( $slot->getRole() === 'main'
+ if ( $slot->getRole() === SlotRecord::MAIN
&& $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
) {
$blobAddress = $slot->getAddress();
$contentId = null;
// Write the main slot's text ID to the revision table for backwards compatibility
- if ( $protoSlot->getRole() === 'main'
+ if ( $protoSlot->getRole() === SlotRecord::MAIN
&& $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD )
) {
// If SCHEMA_COMPAT_WRITE_NEW is also set, the fake content ID is overwritten
if ( $this->hasMcrSchemaFlags( SCHEMA_COMPAT_WRITE_OLD ) ) {
// In non MCR mode this IF section will relate to the main slot
- $mainSlot = $rev->getSlot( 'main' );
+ $mainSlot = $rev->getSlot( SlotRecord::MAIN );
$model = $mainSlot->getModel();
$format = $mainSlot->getFormat();
) {
$this->checkDatabaseWikiId( $dbw );
+ $pageId = $title->getArticleID();
+
// T51581: Lock the page table row to ensure no other process
// is adding a revision to the page at the same time.
// Avoid locking extra tables, compare T191892.
$pageLatest = $dbw->selectField(
'page',
'page_latest',
- [ 'page_id' => $title->getArticleID() ],
+ [ 'page_id' => $pageId ],
__METHOD__,
[ 'FOR UPDATE' ]
);
$title
);
+ if ( !$oldRevision ) {
+ $msg = "Failed to load latest revision ID $pageLatest of page ID $pageId.";
+ $this->logger->error(
+ $msg,
+ [ 'exception' => new RuntimeException( $msg ) ]
+ );
+ return null;
+ }
+
// Construct the new revision
$timestamp = wfTimestampNow(); // TODO: use a callback, so we can override it for testing.
$newRevision = MutableRevisionRecord::newFromParentRevision( $oldRevision );
*/
private function emulateMainSlot_1_29( $row, $queryFlags, Title $title ) {
$mainSlotRow = new stdClass();
- $mainSlotRow->role_name = 'main';
+ $mainSlotRow->role_name = SlotRecord::MAIN;
$mainSlotRow->model_name = null;
$mainSlotRow->slot_revision_id = null;
$mainSlotRow->slot_content_id = null;
$mainSlotRow->slot_content_id =
function ( SlotRecord $slot ) use ( $queryFlags, $mainSlotRow ) {
$db = $this->getDBConnectionRefForQueryFlags( $queryFlags );
- return $this->findSlotContentId( $db, $mainSlotRow->slot_revision_id, 'main' );
+ return $this->findSlotContentId( $db, $mainSlotRow->slot_revision_id, SlotRecord::MAIN );
};
}
$slots[$row->role_name] = new SlotRecord( $row, $contentCallback );
}
- if ( !isset( $slots['main'] ) ) {
+ if ( !isset( $slots[SlotRecord::MAIN] ) ) {
throw new RevisionAccessException(
'Main slot of revision ' . $revId . ' not found in database!'
);
) {
if ( !$this->hasMcrSchemaFlags( SCHEMA_COMPAT_READ_NEW ) ) {
$mainSlot = $this->emulateMainSlot_1_29( $revisionRow, $queryFlags, $title );
- $slots = new RevisionSlots( [ 'main' => $mainSlot ] );
+ $slots = new RevisionSlots( [ SlotRecord::MAIN => $mainSlot ] );
} else {
// XXX: do we need the same kind of caching here
// that getKnownCurrentRevision uses (if $revId == page_latest?)
$row->ar_actor ?? null
);
} catch ( InvalidArgumentException $ex ) {
- wfWarn( __METHOD__ . ': ' . $ex->getMessage() );
- $user = new UserIdentityValue( 0, '', 0 );
+ wfWarn( __METHOD__ . ': ' . $title->getPrefixedDBkey() . ': ' . $ex->getMessage() );
+ $user = new UserIdentityValue( 0, 'Unknown user', 0 );
}
$db = $this->getDBConnectionRefForQueryFlags( $queryFlags );
$row->rev_actor ?? null
);
} catch ( InvalidArgumentException $ex ) {
- wfWarn( __METHOD__ . ': ' . $ex->getMessage() );
- $user = new UserIdentityValue( 0, '', 0 );
+ wfWarn( __METHOD__ . ': ' . $title->getPrefixedDBkey() . ': ' . $ex->getMessage() );
+ $user = new UserIdentityValue( 0, 'Unknown user', 0 );
}
$db = $this->getDBConnectionRefForQueryFlags( $queryFlags );
$ret['fields']['slot_revision_id'] = 'slots.rev_id';
$ret['fields']['slot_content_id'] = 'NULL';
$ret['fields']['slot_origin'] = 'slots.rev_id';
- $ret['fields']['role_name'] = $db->addQuotes( 'main' );
+ $ret['fields']['role_name'] = $db->addQuotes( SlotRecord::MAIN );
if ( in_array( 'content', $options, true ) ) {
$ret['fields']['content_size'] = 'slots.rev_len';