Page MenuHomePhabricator

Admin is unable to undelete a Validated page in Page namespace
Open, Needs TriagePublic

Description

While attempting to undelete a page with validated status revision, the following message appears:

Some or all of the undeletion failed: You are not allowed to change the proofreading status of this page

It is possible to undelete all revisions but the one with validated status.

The same message appears if another admin is attempting to undelete the validated revision.

Tested on:

https://pl.wikisource.org/wiki/Strona:PL_Nowele_obce_(antologia).djvu/011

Event Timeline

DannyS712 subscribed.

SpecialUndelete::undelete calls PageArchive::undelete, which goes to PageArchive::undeleteRevisions, which, for each slot in the latest restored row, has:

undeleteRevisions
$content = $revision->getContent( $role, RevisionRecord::RAW );
$status = $content->prepareSave( $article, 0, -1, $user );
if ( !$status->isOK() ) {
	$dbw->endAtomic( __METHOD__ );
	return $status;
}

Proofread page, when prepareSave is called:

PageContent::prepareSave
public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user ) {
	if ( !$this->isValid() ) {
		return Status::newFatal( 'invalid-content-data' );
	}
	$oldContent = $this->getContentForRevId( $parentRevId );
	if ( $oldContent->getModel() !== CONTENT_MODEL_PROOFREAD_PAGE ) {
		// Let's convert it to Page: page content
		$oldContent = $oldContent->convert( CONTENT_MODEL_PROOFREAD_PAGE );
	}
	if ( !( $oldContent instanceof self ) ) {
		return Status::newFatal( 'invalid-content-data' );
	}
	if ( !$oldContent->getLevel()->isChangeAllowed( $this->getLevel() ) ) {
		return Status::newFatal( 'proofreadpage_notallowedtext' );
	}
	return Status::newGood();
}

it is because of the last check (isChangeAllowed) that the error is returned, causing the $status to not pass isOK() and leading the undeletion to fail.

The $flags used are noted to be the same as WikiPage::doEditContent (now PageUpdater::saveRevision):

flags
*      EDIT_NEW
*          Create a new page, or fail with "edit-already-exists" if the page exists.
*      EDIT_UPDATE
*          Create a new revision, or fail with "edit-gone-missing" if the page does not exist.
*      EDIT_MINOR
*          Mark this revision as minor
*      EDIT_SUPPRESS_RC
*          Do not log the change in recentchanges
*      EDIT_FORCE_BOT
*          Mark the revision as automated ("bot edit")
*      EDIT_AUTOSUMMARY
*          Fill in blank summaries with generated text where possible
*      EDIT_INTERNAL
*          Signal that the page retrieve/save cycle happened entirely in this request.

Perhaps a flag could be used (or a new one added) to signal that the prepareSave call is for undeletion?

Update:
The $oldContent created when getting content for revid -1 is:

PageContent::getContentForRevId
if ( $revId !== -1 ) {
	[...]
}
return $this->getContentHandler()->makeEmptyContent();

And that empty content's level is then checked for changes. The level is from:

PageContentHandler::makeEmptyContent
public function makeEmptyContent() {
	return new PageContent(
		$this->wikitextContentHandler->makeEmptyContent(),
		$this->wikitextContentHandler->makeEmptyContent(),
		$this->wikitextContentHandler->makeEmptyContent(),
		new PageLevel()
	);
}

and the default level is based on:

PageLevel::__construct
public function __construct( $level = self::NOT_PROOFREAD, User $user = null ) {
	$this->level = $level;
	$this->user = $user;
}

by defaulting to NOT_PROOFREAD, there will always be an error for setting it to VALIDATED, unless the user has pagequality-admin rights.

Potential solutions:

  • Add a flag for undeletion
  • Add a hook for before running saveContent, to allow extensions to modify the user's rights temporarily, so that pagequality-admin can be forced to true temporarily