| Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/repo/includes/Actions/SubmitEntityAction.php |
<?php
namespace Wikibase;
use Content;
use MWException;
use Revision;
use Status;
use Title;
use WatchAction;
use WikiPage;
/**
* Handles the submit action for Wikibase entities.
* This performs the undo and restore operations when requested.
* Otherwise it will just show the normal entity view.
*
* @since 0.1
*
* @license GPL-2.0+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author Jens Ohlig
* @author Daniel Kinzler
*/
class SubmitEntityAction extends EditEntityAction {
public function getName() {
return 'submit';
}
public function doesWrites() {
return true;
}
/**
* Show the entity using parent::show(), unless an undo operation is requested.
* In that case $this->undo(); is called to perform the action after a permission check.
*/
public function show() {
$request = $this->getRequest();
if ( $request->getCheck( 'undo' ) || $request->getCheck( 'undoafter' ) || $request->getCheck( 'restore' ) ) {
if ( $this->showPermissionError( 'read' ) || $this->showPermissionError( 'edit' ) ) {
return;
}
$this->undo();
return;
}
parent::show();
}
/**
* Perform the undo operation specified by the web request.
*/
public function undo() {
$request = $this->getRequest();
$title = $this->getTitle();
if ( !$request->wasPosted() || !$request->getCheck( 'wpSave' ) ) {
$args = array( 'action' => 'edit' );
if ( $request->getCheck( 'undo' ) ) {
$args['undo'] = $request->getInt( 'undo' );
}
if ( $request->getCheck( 'undoafter' ) ) {
$args['undoafter'] = $request->getInt( 'undoafter' );
}
if ( $request->getCheck( 'restore' ) ) {
$args['restore'] = $request->getInt( 'restore' );
}
$undoUrl = $title->getLocalURL( $args );
$this->getOutput()->redirect( $undoUrl );
return;
}
$revisions = $this->loadRevisions();
if ( !$revisions->isOK() ) {
$this->showUndoErrorPage( $revisions );
return;
}
/**
* @var Revision $olderRevision
* @var Revision $newerRevision
* @var Revision $latestRevision
*/
list( $olderRevision, $newerRevision, $latestRevision ) = $revisions->getValue();
/**
* @var EntityContent $latestContent
* @var EntityContent $olderContent
* @var EntityContent $newerContent
*/
$olderContent = $olderRevision->getContent();
$newerContent = $newerRevision->getContent();
$latestContent = $latestRevision->getContent();
$diff = $newerContent->getDiff( $olderContent );
$summary = $request->getText( 'wpSummary' );
$editToken = $request->getText( 'wpEditToken' );
if ( $newerRevision->getId() === $latestRevision->getId() ) { // restore
if ( $summary === '' ) {
$summary = $this->makeRestoreSummary( $olderRevision );
}
if ( $diff->isEmpty() ) {
$status = Status::newGood();
$status->warning( 'wikibase-empty-undo' );
} else {
$status = $this->attemptSave( $title, $olderContent, $summary, $editToken );
}
} else { // undo
$patchedContent = $latestContent->getPatchedCopy( $diff );
if ( $patchedContent->equals( $latestContent ) ) {
$status = Status::newGood();
$status->warning( 'wikibase-empty-undo' );
} else {
if ( $summary === '' ) {
$summary = $this->makeUndoSummary( $newerRevision );
}
$status = $this->attemptSave( $title, $patchedContent, $summary, $editToken );
}
}
if ( $status->isOK() ) {
$this->getOutput()->redirect( $title->getFullUrl() );
} else {
$this->showUndoErrorPage( $status );
}
}
/**
* @throws MWException
*/
public function execute() {
throw new MWException( 'Not applicable.' );
}
/**
* @param Title $title
* @param Content $content
* @param string $summary
* @param string $editToken
*
* @return Status
*/
private function attemptSave( Title $title, Content $content, $summary, $editToken ) {
$status = $this->getEditTokenStatus( $editToken );
if ( !$status->isOK() ) {
return $status;
}
$status = $this->getPermissionStatus( 'edit', $title );
if ( !$status->isOK() ) {
return $status;
}
// save edit
$page = new WikiPage( $title );
// NOTE: Constraint checks are performed automatically via EntityContent::prepareSave.
$status = $page->doEditContent( $content, $summary );
if ( !$status->isOK() ) {
return $status;
}
$this->doWatch( $title );
return $status;
}
/**
* Checks the given permission.
*
* @param string $permission
* @param Title $title
* @param string $quick
*
* @return Status a status object representing the check's result.
*/
private function getPermissionStatus( $permission, Title $title, $quick = '' ) {
//XXX: would be nice to be able to pass the $short flag too,
// as used by getUserPermissionsErrorsInternal. But Title doesn't expose that.
$errors = $title->getUserPermissionsErrors( $permission, $this->getUser(), $quick !== 'quick' );
$status = Status::newGood();
foreach ( $errors as $error ) {
call_user_func_array( array( $status, 'fatal' ), $error );
$status->setResult( false );
}
return $status;
}
/**
* Checks that the given token is valid.
*
* @param string $editToken
*
* @return Status
*/
private function getEditTokenStatus( $editToken ) {
$status = Status::newGood();
$user = $this->getUser();
if ( !$user->matchEditToken( $editToken ) ) {
if ( $user->matchEditTokenNoSuffix( $editToken ) ) {
$status = Status::newFatal( 'token_suffix_mismatch' );
} else {
$status = Status::newFatal( 'session_fail_preview' );
}
}
return $status;
}
/**
* Update watchlist.
*
* @param Title $title
*/
private function doWatch( Title $title ) {
$user = $this->getUser();
if ( $user->isLoggedIn()
&& $user->getOption( 'watchdefault' )
&& !$user->isWatched( $title )
) {
WatchAction::doWatch( $title, $user );
}
}
}