John Erling Blad has submitted this change and it was merged.

Change subject: (bug 45099) Return full error report from API.
......................................................................


(bug 45099) Return full error report from API.

This generalizes entity saving and error handling in the API.
By this, consistency is improved, redundant code is reduced,
and error reporting is greatly improved.

There are some design issues here pending discussion, especially
in regards to moving from inheritance based code re-use towards
a composition based model. This change does not solve these issues,
but should make any future refactoring easier, and is thus a step
into the right direction.

patchset 9: rebased and solved conflict in ClaimSaver.php

Change-Id: I4094feee1e6166171fd15ffdf7249b3c0d27ce1c
---
M repo/includes/ClaimSaver.php
M repo/includes/EditEntity.php
M repo/includes/api/ApiWikibase.php
M repo/includes/api/CreateClaim.php
M repo/includes/api/LinkTitles.php
M repo/includes/api/ModifyEntity.php
M repo/includes/api/RemoveClaims.php
M repo/includes/api/RemoveQualifiers.php
M repo/includes/api/RemoveReferences.php
M repo/includes/api/SetClaim.php
M repo/includes/api/SetClaimValue.php
M repo/includes/api/SetQualifier.php
M repo/includes/api/SetReference.php
M repo/includes/api/SetStatementRank.php
M repo/tests/phpunit/includes/api/SetAliasesTest.php
M repo/tests/phpunit/includes/api/SetQualifierTest.php
16 files changed, 433 insertions(+), 334 deletions(-)

Approvals:
  John Erling Blad: Verified; Looks good to me, approved
  jenkins-bot: Checked



diff --git a/repo/includes/ClaimSaver.php b/repo/includes/ClaimSaver.php
index d0752a4..a9b1968 100644
--- a/repo/includes/ClaimSaver.php
+++ b/repo/includes/ClaimSaver.php
@@ -4,6 +4,7 @@
 
 use User;
 use MWException;
+use Status;
 use Wikibase\ExceptionWithCode;
 
 /**
@@ -46,18 +47,33 @@
         * @param string $token
         * @param User $user
         *
-        * @return int
+        * @return Status The status. The status value is an array which may 
contain
+        *         the following fields:
+        *
+        *         -revision: the revision object created by the save
+        *         -errorFlags: error flags using the EditEntity::XXX_ERROR 
constants
+        *         -errorCode: error code to use in API output
+        *
+        *         This status object can be used with 
ApiWikibase::handleSaveStatus().
         */
        public function saveClaim( Claim $claim, $baseRevId, $token, User $user 
) {
-               $entityId = $this->getEntityIdForClaim( $claim );
+               try {
+                       $entityId = $this->getEntityIdForClaim( $claim );
 
-               $content = $this->getEntityContent( $entityId, $baseRevId );
+                       $content = $this->getEntityContent( $entityId, 
$baseRevId );
 
-               $this->updateClaim( $content->getEntity(), $claim );
+                       $this->updateClaim( $content->getEntity(), $claim );
 
-               $newRevisionId = $this->saveChanges( $content, $baseRevId, 
$token, $user );
+                       $status = $this->saveChanges( $content, $baseRevId, 
$token, $user );
+               } catch ( ExceptionWithCode $ex ) {
+                       // put the error code into the status
+                       $value = array( 'errorCode' => $ex->getErrorCode() );
+                       $status = Status::newGood();
+                       $status->setResult( false, $value );
+                       //TODO: add an error message localization key, perhaps 
derived from the error code.
+               }
 
-               return $newRevisionId;
+               return $status;
        }
 
        /**
@@ -151,8 +167,7 @@
         * @param string $token
         * @param User $user
         *
-        * @return int
-        * @throws ExceptionWithCode
+        * @return Status
         */
        protected function saveChanges( EntityContent $content, 
$baseRevisionId, $token, User $user ) {
                $baseRevisionId = is_int( $baseRevisionId ) && $baseRevisionId 
> 0 ? $baseRevisionId : false;
@@ -164,12 +179,7 @@
                        $token
                );
 
-               if ( !$status->isOK() ) {
-                       throw new ExceptionWithCode( $status->getMessage(), 
'setclaim-save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-               return (int)$statusValue['revision']->getId();
+               return $status;
        }
 
 }
\ No newline at end of file
diff --git a/repo/includes/EditEntity.php b/repo/includes/EditEntity.php
index e8965ff..251059e 100644
--- a/repo/includes/EditEntity.php
+++ b/repo/includes/EditEntity.php
@@ -363,6 +363,7 @@
         *
         *  - new: bool whether the edit created a new page
         *  - revision: Revision the new revision object
+        *  - errorFlags: bit field indicating errors, see the XXX_ERROR 
constants.
         *
         * @since 0.1
         *
@@ -416,6 +417,17 @@
         */
        public function hasError( $errorType = self::ANY_ERROR ) {
                return ( $this->errorType & $errorType ) > 0;
+       }
+
+       /**
+        * Returns a bitfield indicating errors encountered while saving.
+        *
+        * @since 0.4
+        *
+        * @return int $errorType bit field using the EditEntity::XXX_ERROR 
constants.
+        */
+       public function getErrors( ) {
+               return $this->errorType;
        }
 
        /**
@@ -563,14 +575,15 @@
        /**
         * Attempts to save the new entity content, chile first checking for 
permissions, edit conflicts, etc.
         *
-        * @param String $summary    The edit summary
-        * @param int    $flags      The edit flags (see 
WikiPage::toEditContent)
-        * @param String|bool $token Edit token to check, or false to disable 
the token check.
-        *                           Null will fail the token text, as will the 
empty string.
+        * @param String      $summary    The edit summary
+        * @param int         $flags      The edit flags (see 
WikiPage::toEditContent)
+        * @param String|bool $token      Edit token to check, or false to 
disable the token check.
+        *                                Null will fail the token text, as 
will the empty string.
         *
+        * @throws \ReadOnlyError
         * @return Status Indicates success and provides detailed warnings or 
error messages. See
         *         getStatus() for more details.
-        * @see      WikiPage::toEditContent
+        * @see    WikiPage::doEditContent
         */
        public function attemptSave( $summary, $flags, $token ) {
                wfProfileIn( __METHOD__ );
@@ -586,8 +599,9 @@
                        //@todo: This is redundant to the error code set in 
isTokenOK().
                        //       We should figure out which error codes the 
callers expect,
                        //       and only set the correct error code, in one 
place, probably here.
-                       $this->status->fatal( 'session-failure' );
                        $this->errorType |= self::TOKEN_ERROR;
+                       $this->status->fatal( 'session-failure' );
+                       $this->status->setResult( false, array( 'errorFlags' => 
$this->errorType ) );
 
                        wfProfileOut( __METHOD__ );
                        return $this->status;
@@ -608,6 +622,8 @@
                }
 
                if ( !$this->status->isOK() ) {
+                       $this->status->setResult( false, array( 'errorFlags' => 
$this->errorType ) );
+
                        wfProfileOut( __METHOD__ );
                        return $this->status;
                }
@@ -637,6 +653,8 @@
                $this->status->merge( $filterStatus );
 
                if ( !$this->status->isOK() ) {
+                       $this->status->setResult( false, array( 'errorFlags' => 
$this->errorType ) );
+
                        wfProfileOut( __METHOD__ );
                        return $this->status;
                }
@@ -655,6 +673,12 @@
 
                $this->status->setResult( $editStatus->isOK(), 
$editStatus->getValue() );
                $this->status->merge( $editStatus );
+
+               if ( !$this->status->isOK() ) {
+                       $value = $this->status->getValue();
+                       $value['errorFlags'] = $this->errorType;
+                       $this->status->setResult( false, $value );
+               }
 
                wfProfileOut( __METHOD__ );
                return $this->status;
@@ -866,42 +890,5 @@
 
                wfProfileOut( __METHOD__ );
                return true;
-       }
-
-       /**
-        * Die with an error corresponding to any errors that occurred during 
attemptSave(), if any.
-        * Intended for use in API modules.
-        *
-        * If there is no error but there are warnings, they are added to the 
API module's result.
-        *
-        * @param \ApiBase $api          the API module to report the error for.
-        * @param String   $errorCode    string Brief, arbitrary, stable string 
to allow easy
-        *                               automated identification of the error, 
e.g., 'unknown_action'
-        * @param int      $httpRespCode int HTTP response code
-        * @param array    $extradata    array Data to add to the "<error>" 
element; array in ApiResult format
-        */
-       public function reportApiErrors( \ApiBase $api, $errorCode, 
$httpRespCode = 0, $extradata = null ) {
-               wfProfileIn( __METHOD__ );
-               if ( $this->status === null ) {
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               // report all warnings
-               // XXX: also report all errors, in sequence, here, before 
failing on the error?
-               $errors = $this->status->getErrorsByType( 'warning' );
-               if ( is_array($errors) && $errors !== array() ) {
-                       $path = array( null, 'warnings' );
-                       $api->getResult()->addValue( null, 'warnings', $errors 
);
-                       $api->getResult()->setIndexedTagName( $path, 'warning' 
);
-               }
-
-               if ( !$this->status->isOK() ) {
-                       $description = $this->status->getWikiText( 
'wikibase-api-cant-edit', 'wikibase-api-cant-edit' );
-                       wfProfileOut( __METHOD__ );
-                       $api->dieUsage( $description, $errorCode, 
$httpRespCode, $extradata );
-               }
-
-               wfProfileOut( __METHOD__ );
        }
 }
diff --git a/repo/includes/api/ApiWikibase.php 
b/repo/includes/api/ApiWikibase.php
index a65a720..85f98aa 100644
--- a/repo/includes/api/ApiWikibase.php
+++ b/repo/includes/api/ApiWikibase.php
@@ -7,6 +7,7 @@
 use Wikibase\Entity;
 use Wikibase\EntityContent;
 use Wikibase\Settings;
+use Wikibase\EditEntity;
 
 /**
  * Base class for API modules modifying a single item identified based on id 
xor a combination of site and page title.
@@ -21,6 +22,20 @@
  * @author John Erling Blad < [email protected] >
  */
 abstract class ApiWikibase extends \ApiBase {
+
+       /**
+        * Wrapper message for single errors
+        *
+        * @var bool|string
+        */
+       protected static $shortErrorContextMessage = false;
+
+       /**
+        * Wrapper message for multiple errors
+        *
+        * @var bool|string
+        */
+       protected static $longErrorContextMessage = false;
 
        /**
         * Figure out the instance-specific usekeys-state
@@ -402,4 +417,308 @@
 
                return $content;
        }
+
+       /**
+        * Signal errors and warnings from a save operation to the API call's 
output.
+        * This is much like handleStatus(), but specialized for Status objects 
returned by
+        * EditEntity::attemptSave(). In particular, the 'errorFlags' and 
'errorCode' fields
+        * from the status value are used to determine the error code to return 
to the caller.
+        *
+        * @note: this function may or may not return normally, depending on 
whether
+        *        the status is fatal or not.
+        *
+        * @see handleStatus().
+        *
+        * @param \Status $status The status to report
+        */
+       protected function handleSaveStatus( Status $status ) {
+               $value = $status->getValue();
+               $errorCode = null;
+
+               if ( is_array( $value ) && isset( $value['errorCode'] ) ) {
+                       $errorCode = $value['errorCode'];
+               } else {
+                       $editError = 0;
+
+                       if ( is_array( $value ) && isset( $value['errorFlags'] 
) ) {
+                               $editError = $value['errorFlags'];
+                       }
+
+                       if ( ( $editError & EditEntity::TOKEN_ERROR ) > 0 ) {
+                               $errorCode = 'session-failure';
+                       } elseif ( ( $editError & 
EditEntity::EDIT_CONFLICT_ERROR ) > 0 ) {
+                               $errorCode = 'edit-conflict';
+                       } elseif ( ( $editError & EditEntity::ANY_ERROR ) > 0 ) 
{
+                               $errorCode = 'save-failed';
+                       }
+               }
+
+               //NOTE: will just add warnings or do nothing if there's no error
+               $this->handleStatus( $status, $errorCode );
+       }
+
+       /**
+        * Include messages from a Status object in the API call's output.
+        *
+        * If $status->isOK() returns false, this method will terminate via the 
a call
+        * to $this->dieUsage().
+        *
+        * If $status->isOK() returns false, any errors from the $status object 
will be included
+        * in the error-section of the API response. Otherwise, any warnings 
from $status will be
+        * included in the warnings-section of the API response. In both cases, 
a messages-section
+        * is used that includes an HTML representation of the messages as well 
as a list of message
+        * keys and parameters, for client side rendering and localization.
+        *
+        * @param \Status $status The status to report
+        * @param string  $errorCode The API error code to use in case 
$status->isOK() returns false
+        * @param array   $extradata Additional data to include the the error 
report,
+        *                if $status->isOK() returns false
+        * @param int     $httpRespCode the HTTP response code to use in case
+        *                $status->isOK() returns false.
+        *
+        * @warning This is a temporary solution, pending a similar feature in 
MediaWiki core,
+        *          see bug 45843.
+        *
+        * @see \ApiBase::dieUsage()
+        */
+       protected function handleStatus( Status $status, $errorCode, array 
$extradata = array(), $httpRespCode = 0 ) {
+               wfProfileIn( __METHOD__ );
+
+               $res = $this->getResult();
+               $isError = !$status->isOK();
+
+               // report all warnings and errors
+               if ( $status->isGood() ) {
+                       $description = null;
+               } else {
+                       $description = $status->getWikiText( 
self::$shortErrorContextMessage, self::$longErrorContextMessage );
+               }
+
+               $errors = $status->getErrorsByType( $isError ? 'error' : 
'warning' );
+               $messages = $this->compileStatusReport( $errors );
+
+               if ( $messages ) {
+                       //NOTE: Status::getHTML() doesn't work, see bug 45844
+                       //$html = $status->getHTML( 
self::$shortErrorContextMessage, self::$longErrorContextMessage );
+
+                       // nasty workaround:
+                       $html = $this->messageToHtml( $description );
+                       $res->setContent( $messages, $html, 'html' );
+               }
+
+               if ( $isError ) {
+                       $res->setElement( $extradata, 'messages', $messages );
+
+                       wfProfileOut( __METHOD__ );
+                       $this->dieUsage( $description, $errorCode, 
$httpRespCode, $extradata );
+               } elseif ( $messages ) {
+                       $res->disableSizeCheck();
+                       $res->addValue( array( 'warnings' ), 'messages', 
$messages, true );
+                       $res->enableSizeCheck();
+
+                       wfProfileOut( __METHOD__ );
+               }
+       }
+
+       /**
+        * Converts the given wiki text to HTML, using the parser mode for 
interface messages.
+        *
+        * @note: this is only needed as a temporary workaround for bug 45844
+        *
+        * @param string|null|bool $text The wikitext to parse.
+        *
+        * @return string|null|bool HTML of the wikitext if $text is a string; 
$text if it's false or null
+        *
+        * @see \MessageCache::parse()
+        */
+       protected function messageToHtml( $text ) {
+               if ( $text === null || $text === false || $text === '' ) {
+                       return $text;
+               }
+
+               $out = \MessageCache::singleton()->parse( $text, 
$this->getContext()->getTitle(), /*linestart*/true,
+                       /*interface*/true, $this->getContext()->getLanguage() );
+
+               return $out->getText();
+       }
+
+       /**
+        * Utility method for compiling a list of messages into a form suitable 
for use
+        * in an API result structure.
+        *
+        * The $errors parameters is a list of (error) messages. Each entry in 
that array
+        * represents on message; the message can be represented as:
+        *
+        * * a message key, as a string
+        * * an indexed array with the message key as the first element, and 
the remaining elements
+        *   acting as message parameters
+        * * an associative array with the following fields:
+        *   - message: the message key (as a string); may also be a Message 
object, see below for that.
+        *   - params: a list of parameters (optional)
+        *   - type: the type of message (warning or error) (optional)
+        * * an associative array like above, but containing a Message object 
in the 'message' field.
+        *   In that case, the 'params' field is ignored and the parameter list 
is taken from the
+        *   Message object.
+        *
+        * This provides support for message lists coming from 
Status::getErrorsByType() as well as
+        * Title::getUserPermissionsErrors() etc.
+        *
+        * @param $errors array a list of errors, as returned by 
Status::getErrorsByType()
+        * @param $messages array an result structure to add to (optional)
+        *
+        * @return array a result structure containing the messages from 
$errors as well as what
+        *         was already present in the $messages parameter.
+        */
+       protected function compileStatusReport( $errors, $messages = array() ) {
+               if ( !is_array($errors) || $errors === array() ) {
+                       return $messages;
+               }
+
+               $res = $this->getResult();
+
+               foreach ( $errors as $m ) {
+                       $type = null;
+                       $name = null;
+                       $params = null;
+
+                       if ( is_string( $m ) ) {
+                               // it's a plain string containing a message key
+                               $name = $m;
+                       } elseif ( is_array( $m ) ) {
+                               if ( isset( $m[0]) ) {
+                                       // it's an indexed array, the first 
entriy is the message key, the rest are paramters
+                                       $name = $m[0];
+                                       $params = array_slice( $m, 1 );
+                               } else{
+                                       // it's an assoc array, find message 
key and params in fields.
+                                       $type = isset( $m['type'] ) ? 
$m['type'] : null;
+                                       $params = isset( $m['params'] ) ? 
$m['params'] : null;
+
+                                       if( isset( $m['message'] ) ) {
+                                               if ( $m['message'] instanceof 
\Message ) {
+                                                       // message object, 
handle below
+                                                       $m = $m['message']; // 
NOTE: this triggers the "$m is an object" case below!
+                                               } else {
+                                                       // plain key and param 
list
+                                                       $name = strval( 
$m['message'] );
+                                               }
+                                       }
+                               }
+                       }
+
+                       if ( $m instanceof \Message ) { //NOTE: no elsif, since 
$m can be manipulated
+                               // a message object
+
+                               $name = $m->getKey();
+                               $params = $m->getParams();
+                       }
+
+                       if ( $name !== null ) {
+                               // got at least a name
+
+                               $row = array();
+
+                               $res->setElement( $row, 'name', $name );
+
+                               if ( $type !== null ) {
+                                       $res->setElement( $row, 'type', $type );
+                               }
+
+                               if ( $params !== null && !empty( $params ) ) {
+                                       $res->setElement( $row, 'parameters', 
$params );
+                                       $res->setIndexedTagName( 
$row['parameters'], 'parameter' );
+                               }
+
+                               $messages[] = $row;
+                       }
+               }
+
+               $res->setIndexedTagName( $messages, 'message' );
+               return $messages;
+       }
+
+       /**
+        * Attempts to save the new entity content, chile first checking for 
permissions,
+        * edit conflicts, etc. Saving is done via EditEntity::attemptSave().
+        *
+        * This method automatically takes into account several parameters:
+        * * 'bot' for setting the bot flag
+        * * 'baserevid' for determining the edit's base revision for conflict 
resolution
+        * * 'token' for the edit token
+        *
+        * If an error occurs, it is automatically reported and execution of 
the API module
+        * is terminated using a call to dieUsage() (via handleStatus()). If 
there were any
+        * warnings, they will automatically be included in the API call's 
output (again, via
+        * handleStatus()).
+        *
+        * @param EntityContent $content  The content to save
+        * @param String $summary    The edit summary
+        * @param int    $flags      The edit flags (see 
WikiPage::toEditContent)
+        *
+        * @return Status the status of the save operation, as returned by 
EditEntity::attemptSave()
+        * @see  EditEntity::attemptSave()
+        *
+        * @todo: this could be factored out into a controller-like class, but 
that controller
+        *        would still need knowledge of the API module to be useful. 
We'll put it here
+        *        for now pending further discussion.
+        */
+       protected function attemptSaveEntity( EntityContent $content, $summary, 
$flags = 0 ) {
+               $params = $this->extractRequestParams();
+               $user = $this->getUser();
+
+               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
+
+               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
+               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
+
+               $editEntity = new EditEntity( $content, $user, $baseRevisionId, 
$this->getContext() );
+
+               if ( !$this->needsToken() ) {
+                       // false disabled the token check
+                       $token = false;
+               } else {
+                       // null fails the token check
+                       $token = isset( $params['token'] ) ? $params['token'] : 
null;
+               }
+
+               $status = $editEntity->attemptSave(
+                       $summary,
+                       $flags,
+                       $token
+               );
+
+               $this->handleSaveStatus( $status );
+               return $status;
+       }
+
+       /**
+        * Adds the ID of the new revision from the Status object to the API 
result structure.
+        * The status value is expected to be structured in the way that 
EditEntity::attemptSave()
+        * resp WikiPage::doEditContent() do it: as an array, with the new 
revision object in the
+        * 'revision' field.
+        *
+        * If no revision is found the the Status object, this method does 
nothing.
+        *
+        * @see ApiResult::addValue()
+        *
+        * @param string|null|array  $path  Where in the result to put the 
revision idf
+        * @param string  $name   The name to use for the revision id in the 
result structure
+        * @param \Status $status The status to get the revision ID from.
+        */
+       protected function addRevisionIdFromStatusToResult( $path, $name, 
Status $status ) {
+               $statusValue = $status->getValue();
+
+               /* @var \Revision $revision */
+               $revision = isset( $statusValue['revision'] )
+                       ? $statusValue['revision'] : null;
+
+               if ( $revision ) {
+                       $this->getResult()->addValue(
+                               $path,
+                               $name,
+                               intval( $revision->getId() )
+                       );
+               }
+
+       }
 }
diff --git a/repo/includes/api/CreateClaim.php 
b/repo/includes/api/CreateClaim.php
index 780e6fa..bf0386f 100644
--- a/repo/includes/api/CreateClaim.php
+++ b/repo/includes/api/CreateClaim.php
@@ -103,38 +103,16 @@
        /**
         * @since 0.3
         *
-        * @return \Wikibase\EntityContent
+        * @param \Wikibase\EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
-
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
-                       '', // TODO: autocomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
+               $status = $this->attemptSaveEntity(
+                       $content,
+                       '', // TODO: automcomment
+                       EDIT_UPDATE
                );
 
-               if ( !$status->isOK() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'createclaim-save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/LinkTitles.php b/repo/includes/api/LinkTitles.php
index 5f028a3..be1a1ae 100644
--- a/repo/includes/api/LinkTitles.php
+++ b/repo/includes/api/LinkTitles.php
@@ -138,38 +138,17 @@
 
                $this->addSiteLinksToResult( $return, 'entity' );
 
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-
                if ( $itemContent === null ) {
                        // to not have an ItemContent isn't really bad at this 
point
                        $status = Status::newGood( true );
                }
                else {
                        // Do the actual save, or if it don't exist yet create 
it.
-                       $editEntity = new \Wikibase\EditEntity( $itemContent, 
$user, false, $this->getContext() );
-                       $status = $editEntity->attemptSave(
+                       $status = $this->attemptSaveEntity( $itemContent,
                                $summary->toString(),
-                               $flags,
-                               ( $this->needsToken() ? $params['token'] : '' )
-                       );
+                               $flags );
 
-                       if ( $editEntity->hasError( 
\Wikibase\EditEntity::TOKEN_ERROR ) ) {
-                               $editEntity->reportApiErrors( $this, 
'session-failure' );
-                       }
-                       elseif ( $editEntity->hasError( 
\Wikibase\EditEntity::EDIT_CONFLICT_ERROR ) ) {
-                               $editEntity->reportApiErrors( $this, 
'edit-conflict' );
-                       }
-                       elseif ( $editEntity->hasError() ) {
-                               $editEntity->reportApiErrors( $this, 
'save-failed' );
-                       }
-
-                       $revision = $editEntity->getNewRevision();
-                       if ( $revision ) {
-                               $this->getResult()->addValue(
-                                       'entity',
-                                       'lastrevid', intval( $revision->getId() 
)
-                               );
-                       }
+                       $this->addRevisionIdFromStatusToResult( 'entity', 
'lastrevid', $status );
                }
 
                if ( $itemContent !== null ) {
diff --git a/repo/includes/api/ModifyEntity.php 
b/repo/includes/api/ModifyEntity.php
index 0b6f5f6..4ce54d3 100644
--- a/repo/includes/api/ModifyEntity.php
+++ b/repo/includes/api/ModifyEntity.php
@@ -208,27 +208,10 @@
                //NOTE: EDIT_NEW will not be set automatically. If the entity 
doesn't exist, and EDIT_NEW was
                //      not added to $this->flags explicitly, the save will 
fail.
 
-               // Do the actual save, or if it don't exist yet create it.
-               // There will be exceptions but we just leak them out ;)
                // collect information and create an EditEntity
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : false;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $editEntity = new \Wikibase\EditEntity( $entityContent, $user, 
$baseRevisionId, $this->getContext() );
-               $editEntity->attemptSave(
+               $status = $this->attemptSaveEntity( $entityContent,
                        $summary->toString(),
-                       $this->flags,
-                       ( $this->needsToken() ? $params['token'] : '' )
-               );
-
-               if ( $editEntity->hasError( \Wikibase\EditEntity::TOKEN_ERROR ) 
) {
-                       $editEntity->reportApiErrors( $this, 'session-failure' 
);
-               }
-               elseif ( $editEntity->hasError( 
\Wikibase\EditEntity::EDIT_CONFLICT_ERROR ) ) {
-                       $editEntity->reportApiErrors( $this, 'edit-conflict' );
-               }
-               elseif ( $editEntity->hasError() ) {
-                       $editEntity->reportApiErrors( $this, 'save-failed' );
-               }
+                       $this->flags );
 
                $this->getResult()->addValue(
                        'entity',
@@ -240,13 +223,7 @@
                        'type', $entityContent->getEntity()->getType()
                );
 
-               $revision = $editEntity->getNewRevision();
-               if ( $revision ) {
-                       $this->getResult()->addValue(
-                               'entity',
-                               'lastrevid', intval( $revision->getId() )
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'entity', 'lastrevid', 
$status );
 
                if ( isset( $params['site'] ) && isset( $params['title'] ) ) {
                        $normalized = array();
diff --git a/repo/includes/api/RemoveClaims.php 
b/repo/includes/api/RemoveClaims.php
index cd96931..f4a02a4 100644
--- a/repo/includes/api/RemoveClaims.php
+++ b/repo/includes/api/RemoveClaims.php
@@ -206,35 +206,13 @@
         * @param EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
-
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
+               $status = $this->attemptSaveEntity(
+                       $content,
                        '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
+                       EDIT_UPDATE
                );
 
-               if ( !$status->isGood() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/RemoveQualifiers.php 
b/repo/includes/api/RemoveQualifiers.php
index 03205b4..f3a9941 100644
--- a/repo/includes/api/RemoveQualifiers.php
+++ b/repo/includes/api/RemoveQualifiers.php
@@ -134,35 +134,13 @@
         * @param EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
+               // collect information and create an EditEntity
+               $summary = '/* wbremovequalifiers */'; //TODO: autosummary!
+               $status = $this->attemptSaveEntity( $content,
+                       $summary,
+                       EDIT_UPDATE );
 
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
-                       '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : false
-               );
-
-               if ( !$status->isOk() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/RemoveReferences.php 
b/repo/includes/api/RemoveReferences.php
index f792ed7..c1c114f 100644
--- a/repo/includes/api/RemoveReferences.php
+++ b/repo/includes/api/RemoveReferences.php
@@ -145,35 +145,13 @@
         * @param EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
+               // collect information and create an EditEntity
+               $summary = '/* wbremovereferences */'; //TODO: autosummary
+               $status = $this->attemptSaveEntity( $content,
+                       $summary,
+                       EDIT_UPDATE );
 
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
-                       '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
-               );
-
-               if ( !$status->isGood() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/SetClaim.php b/repo/includes/api/SetClaim.php
index 7396cb4..e191703 100644
--- a/repo/includes/api/SetClaim.php
+++ b/repo/includes/api/SetClaim.php
@@ -57,12 +57,11 @@
 
                $newRevisionId = null;
 
-               try {
-                       $newRevisionId = $claimSetter->saveClaim( $claim, 
$baseRevisionId, $token, $this->getUser() );
-               }
-               catch ( ExceptionWithCode $exception ) {
-                       $this->dieUsage( $exception->getMessage(), 
$exception->getErrorCode() );
-               }
+               $status = $claimSetter->saveClaim( $claim, $baseRevisionId, 
$token, $this->getUser() );
+               $this->handleSaveStatus( $status ); // die on error, report 
warnings, etc
+
+               $statusValue = $status->getValue();
+               $newRevisionId = isset( $statusValue['revision'] ) ? 
$statusValue['revision']->getId() : null;
 
                if ( $newRevisionId !== null ) {
                        $this->getResult()->addValue(
diff --git a/repo/includes/api/SetClaimValue.php 
b/repo/includes/api/SetClaimValue.php
index eae4c04..3033b60 100644
--- a/repo/includes/api/SetClaimValue.php
+++ b/repo/includes/api/SetClaimValue.php
@@ -145,35 +145,13 @@
         * @param \Wikibase\EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
-
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
+               $status = $this->attemptSaveEntity(
+                       $content,
                        '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
+                       EDIT_UPDATE
                );
 
-               if ( !$status->isGood() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'setclaimvalue-save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/SetQualifier.php 
b/repo/includes/api/SetQualifier.php
index de6b241..d533a39 100644
--- a/repo/includes/api/SetQualifier.php
+++ b/repo/includes/api/SetQualifier.php
@@ -257,35 +257,13 @@
         * @param EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
+               // collect information and create an EditEntity
+               $summary = '/* wbsetqualifier */'; // TODO: automcomment
+               $status = $this->attemptSaveEntity( $content,
+                       $summary,
+                       EDIT_UPDATE );
 
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
-                       '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : false
-               );
-
-               if ( !$status->isOk() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/SetReference.php 
b/repo/includes/api/SetReference.php
index 7cd71d5..f13bb25 100644
--- a/repo/includes/api/SetReference.php
+++ b/repo/includes/api/SetReference.php
@@ -179,34 +179,12 @@
         * @param \Wikibase\EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
+               $summary = '/* wbsetreference */'; // TODO: automcomment
+               $status = $this->attemptSaveEntity( $content,
+                       $summary,
+                       EDIT_UPDATE );
 
-               $status = $editEntity->attemptSave(
-                       '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
-               );
-
-               if ( !$status->isGood() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'setreference-save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/includes/api/SetStatementRank.php 
b/repo/includes/api/SetStatementRank.php
index 89adada..b39089f 100644
--- a/repo/includes/api/SetStatementRank.php
+++ b/repo/includes/api/SetStatementRank.php
@@ -135,35 +135,13 @@
         * @param \Wikibase\EntityContent $content
         */
        protected function saveChanges( EntityContent $content ) {
-               $params = $this->extractRequestParams();
+               // collect information and create an EditEntity
+               $summary = '/* wbsetstatementrank */'; // TODO: automcomment
+               $status = $this->attemptSaveEntity( $content,
+                       $summary,
+                       EDIT_UPDATE );
 
-               $user = $this->getUser();
-               $flags = 0;
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-               $baseRevisionId = $baseRevisionId > 0 ? $baseRevisionId : false;
-               $flags |= ( $user->isAllowed( 'bot' ) && $params['bot'] ) ? 
EDIT_FORCE_BOT : 0;
-               $flags |= EDIT_UPDATE;
-               $editEntity = new \Wikibase\EditEntity( $content, $user, 
$baseRevisionId, $this->getContext() );
-
-               $status = $editEntity->attemptSave(
-                       '', // TODO: automcomment
-                       $flags,
-                       isset( $params['token'] ) ? $params['token'] : ''
-               );
-
-               if ( !$status->isGood() ) {
-                       $this->dieUsage( 'Failed to save the change', 
'save-failed' );
-               }
-
-               $statusValue = $status->getValue();
-
-               if ( isset( $statusValue['revision'] ) ) {
-                       $this->getResult()->addValue(
-                               'pageinfo',
-                               'lastrevid',
-                               (int)$statusValue['revision']->getId()
-                       );
-               }
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
        }
 
        /**
diff --git a/repo/tests/phpunit/includes/api/SetAliasesTest.php 
b/repo/tests/phpunit/includes/api/SetAliasesTest.php
index 7ac5e8a..423530c 100644
--- a/repo/tests/phpunit/includes/api/SetAliasesTest.php
+++ b/repo/tests/phpunit/includes/api/SetAliasesTest.php
@@ -2,7 +2,7 @@
 
 namespace Wikibase\Test\Api;
 use ApiTestCase;
-//use Wikibase\Test\ApiModifyItemBase;
+//use Wikibase\Test\ModifyItemBase;
 
 /**
  * Tests for the ApiSetAliases API module.
diff --git a/repo/tests/phpunit/includes/api/SetQualifierTest.php 
b/repo/tests/phpunit/includes/api/SetQualifierTest.php
index 744d60e..8e5cc55 100644
--- a/repo/tests/phpunit/includes/api/SetQualifierTest.php
+++ b/repo/tests/phpunit/includes/api/SetQualifierTest.php
@@ -6,6 +6,7 @@
 use Wikibase\Statement;
 use Wikibase\Claim;
 use Wikibase\EntityId;
+//use Wikibase\Test\ModifyItemBase;
 
 /**
  * Unit tests for the Wikibase\Repo\Api\SetQualifier class.
@@ -42,7 +43,7 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  */
-class SetQualifierTest extends \ApiTestCase {
+class SetQualifierTest extends ModifyItemBase {
 
        /**
         * @return Snak[]
@@ -132,11 +133,14 @@
        }
 
        protected function makeAddRequest( $statementGuid, Snak $qualifier, 
EntityId $entityId ) {
+               $token = $this->getItemToken();
+
                $params = array(
                        'action' => 'wbsetqualifier',
                        'claim' => $statementGuid,
                        'snaktype' => $qualifier->getType(),
                        'property' => 
$qualifier->getPropertyId()->getPrefixedId(),
+                       'token' => $token
                );
 
                if ( $qualifier instanceof \Wikibase\PropertyValueSnak ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/49853
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I4094feee1e6166171fd15ffdf7249b3c0d27ce1c
Gerrit-PatchSet: 9
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Daniel Werner <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: John Erling Blad <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to