jenkins-bot has submitted this change and it was merged.

Change subject: Use ChangeOps for wbsetclaimvalue and wbcreateclaim
......................................................................


Use ChangeOps for wbsetclaimvalue and wbcreateclaim

- wbsetclaimvalue & wbcreateclaim are now using ChangeOpClaim
- autocomment functionality added to wbsetclaimvalue
- these modules now also allow custom edit summaries

Bug: 41490
Bug: 50307
Change-Id: I0521a20bf6f600a952831418ebd4ef02bcb3f52f
---
M repo/Wikibase.classes.php
M repo/Wikibase.i18n.php
A repo/includes/api/ClaimModificationHelper.php
M repo/includes/api/CreateClaim.php
A repo/includes/api/ModifyClaim.php
M repo/includes/api/SetClaimValue.php
6 files changed, 495 insertions(+), 447 deletions(-)

Approvals:
  Daniel Kinzler: Looks good to me, but someone else must approve
  Addshore: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/repo/Wikibase.classes.php b/repo/Wikibase.classes.php
index 795b7c0..3bc9689 100644
--- a/repo/Wikibase.classes.php
+++ b/repo/Wikibase.classes.php
@@ -97,6 +97,8 @@
                'Wikibase\Api\RemoveQualifiers' => 
'includes/api/RemoveQualifiers.php',
                'Wikibase\Api\SetQualifier' => 'includes/api/SetQualifier.php',
                'Wikibase\Api\SnakValidationHelper' => 
'includes/api/SnakValidationHelper.php',
+               'Wikibase\Api\ModifyClaim' => 'includes/api/ModifyClaim.php',
+               'Wikibase\Api\ClaimModificationHelper' => 
'includes/api/ClaimModificationHelper.php',
 
                // includes/content
                'Wikibase\EntityContent' => 
'includes/content/EntityContent.php',
diff --git a/repo/Wikibase.i18n.php b/repo/Wikibase.i18n.php
index a826a0f..475a2cc 100644
--- a/repo/Wikibase.i18n.php
+++ b/repo/Wikibase.i18n.php
@@ -249,6 +249,7 @@
        'wikibase-api-invalid-snak' => 'Invalid snak', # Do not translate
        'wikibase-api-invalid-list' => 'Invalid list', # Do not translate
        'wikibase-api-invalid-property-id' => 'Invalid propertyid', # Do not 
translate
+       'wikibase-api-invalid-entity-id' => 'Invalid entityid', # Do not 
translate
        'wikibase-api-invalid-snak' => 'Invalid snak', # Do not translate
        'wikibase-api-no-common-iten' => 'There is no common item', # Do not 
translate
        'wikibase-api-no-data' => 'No data to operate on', # Do not translate
@@ -920,6 +921,7 @@
        'wikibase-api-invalid-snak' => '!!DO NOT TRANSLATE!! Invalid snak has 
been provided, This is similar to invalid-json',
        'wikibase-api-invalid-list' => '!!DO NOT TRANSLATE!! Invalid list or 
data has been provided. This can occour when a list conflicts with itself (the 
list contains something to modify, but also to remove this item)',
        'wikibase-api-invalid-property-id' => '!!DO NOT TRANSLATE!! Invalid 
propertyid has been supplied',
+       'wikibase-api-invalid-entity-id' => '!!DO NOT TRANSLATE!! Invalid 
entityid has been supplied',
        'wikibase-api-no-common-iten' => '!!DO NOT TRANSLATE!! There is no 
common item between to passed parameters when there should be',
        'wikibase-api-no-data' => '!!DO NOT TRANSLATE!! This is an error 
message for a situation where the "data" argument to the API is lacking 
content. Usually this should never be shown to the user, unless there are some 
exceptional error condition. This message should probably not exist in the 
final version.',
        'wikibase-api-no-external-page' => '!!DO NOT TRANSLATE!! This is an 
error message where the external client did reply, but either because of a 
faulty reply or because the page title could not be unwound, it was not 
possible to identify an external page.',
diff --git a/repo/includes/api/ClaimModificationHelper.php 
b/repo/includes/api/ClaimModificationHelper.php
new file mode 100644
index 0000000..8f6d30a
--- /dev/null
+++ b/repo/includes/api/ClaimModificationHelper.php
@@ -0,0 +1,217 @@
+<?php
+
+namespace Wikibase\Api;
+
+use Wikibase\Lib\EntityIdParser;
+
+use Wikibase\Lib\SnakConstructionService;
+
+use ApiBase, MWException;
+use Wikibase\EntityContent;
+use Wikibase\Claim;
+use Wikibase\Summary;
+use Wikibase\Lib\Serializers\SerializerFactory;
+use Wikibase\Entity;
+use Wikibase\EntityId;
+use Wikibase\Property;
+use Wikibase\EntityContentFactory;
+
+/**
+ * Helper class for modifying claims
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @ingroup WikibaseRepo
+ * @ingroup API
+ *
+ * @licence GNU GPL v2+
+ * @author Tobias Gritschacher < [email protected] >
+ * @author Jeroen De Dauw < [email protected] >
+ */
+class ClaimModificationHelper {
+
+       /**
+        * @since 0.4
+        *
+        * @var \ApiMain
+        */
+       protected $apiMain;
+
+       /**
+        * @since 0.4
+        *
+        * @var EntityContentFactory
+        */
+       protected $entityContentFactory;
+
+       /**
+        * @since 0.4
+        *
+        * @var SnakConstructionService
+        */
+       protected $snakConstructionService;
+
+       /**
+        * @since 0.4
+        *
+        * @var EntityIdParser
+        */
+       protected $entityIdParser;
+
+       /**
+        * @since 0.4
+        *
+        * @param \ApiMain $apiMain
+        * @param EntityContentFactory $entityContentFactory
+        * @param SnakConstructionService $snakConstructionService
+        * @param EntityIdParser $entityIdParser
+        */
+       public function __construct(
+               \ApiMain $apiMain,
+               EntityContentFactory $entityContentFactory,
+               SnakConstructionService $snakConstructionService,
+               EntityIdParser $entityIdParser
+       ) {
+               $this->apiMain = $apiMain;
+               $this->entityContentFactory = $entityContentFactory;
+               $this->snakConstructionService = $snakConstructionService;
+               $this->entityIdParser = $entityIdParser;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param Claim $claim
+        */
+       public function addClaimToApiResult( Claim $claim ) {
+               $serializerFactory = new SerializerFactory();
+               $serializer = $serializerFactory->newSerializerForObject( 
$claim );
+               $serializer->getOptions()->setIndexTags( 
$this->apiMain->getResult()->getIsRawMode() );
+
+               $this->apiMain->getResult()->addValue(
+                       null,
+                       'claim',
+                       $serializer->getSerialized( $claim )
+               );
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        *
+        * @return \Title
+        * TODO: this could go into a ApiWikibaseHelper as it is useful for 
almost all API modules
+        */
+       public function getEntityTitle( EntityId $entityId ) {
+               $entityTitle = 
EntityContentFactory::singleton()->getTitleForId( $entityId );
+
+               if ( $entityTitle === null ) {
+                       $this->apiMain->dieUsage( 'No such entity' , 
'no-such-entity' );
+               }
+
+               return $entityTitle;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param array $params
+        * @param EntityId $propertyId
+        *
+        * @return \Wikibase\Snak
+        *
+        * @throws ParseException
+        * @throws IllegalValueException
+        */
+       public function getSnakInstance( $params, EntityId $propertyId ) {
+               $valueData = null;
+               if ( isset( $params['value'] ) ) {
+                       $valueData = \FormatJson::decode( $params['value'], 
true );
+                       if ( $valueData === null ) {
+                               $this->apiMain->dieUsage( 'Could not decode 
snak value', 'invalid-snak' );
+                       }
+               }
+
+               if ( $propertyId->getEntityType() !== Property::ENTITY_TYPE ) {
+                       $this->apiMain->dieUsage( 'Property expected, got ' . 
$propertyId->getEntityType(), 'invalid-snak' );
+               }
+
+               try {
+                       $snak = $this->snakConstructionService->newSnak( 
$propertyId, $params['snaktype'], $valueData );
+               }
+               catch ( IllegalValueException $ex ) {
+                       $this->apiMain->dieUsage( 'Invalid snak: 
IllegalValueException', 'invalid-snak' );
+               }
+               catch ( InvalidArgumentException $ex ) {
+                       // shouldn't happen, but might.
+                       $this->apiMain->dieUsage( 'Invalid snak: 
InvalidArgumentException', 'invalid-snak' );
+               }
+
+               return $snak;
+       }
+
+       /**
+        * Parses an entity id string coming from the user
+        *
+        * @since 0.4
+        *
+        * @param string $entityIdParam
+        *
+        * TODO: this could go into an EntityModificationHelper or even in a 
ApiWikibaseHelper
+        * as it is useful for almost all API modules
+        */
+       public function getEntityIdFromString( $entityIdParam ) {
+               try {
+                       $entityId = $this->entityIdParser->parse( 
$entityIdParam );
+               } catch ( ParseException $parseException ) {
+                       $this->dieUsage( 'Invalid entity ID: ParseException', 
'invalid-entity-id' );
+               }
+
+               return $entityId;
+       }
+
+       /**
+        * Creates a new Summary instance suitable for representing the action 
performed by this module.
+        *
+        * @since 0.4
+        *
+        * @param array $params
+        *
+        * @return Summary
+        */
+       public function createSummary( array $params, \ApiBase $module ) {
+               $summary = new Summary( $module->getModuleName() );
+               if ( isset( $params['summary'] ) ) {
+                       $summary->setUserSummary( $params['summary'] );
+               }
+               return $summary;
+       }
+
+       /**
+        * @see ApiBase::getPossibleErrors()
+        */
+       public function getPossibleErrors() {
+               return array(
+                       array( 'code' => 'invalid-guid', 'info' => 
$this->apiMain->msg( 'wikibase-api-invalid-guid' )->text() ),
+                       array( 'code' => 'no-such-entity', 'info' => 
$this->apiMain->msg( 'wikibase-api-no-such-entity' )->text() ),
+                       array( 'code' => 'invalid-snak', 'info' => 
$this->apiMain->msg( 'wikibase-api-invalid-snak' )->text() ),
+                       array( 'code' => 'invalid-entity-id', 'info' => 
$this->apiMain->msg( 'wikibase-api-invalid-entity-id' )->text() ),
+               );
+       }
+}
diff --git a/repo/includes/api/CreateClaim.php 
b/repo/includes/api/CreateClaim.php
index 884ddb9..faf926e 100644
--- a/repo/includes/api/CreateClaim.php
+++ b/repo/includes/api/CreateClaim.php
@@ -3,24 +3,13 @@
 namespace Wikibase\Api;
 
 use ApiBase, MWException;
-
 use ApiMain;
-use DataValues\IllegalValueException;
-use InvalidArgumentException;
-use ValueParsers\ParseException;
 use Wikibase\EntityId;
-use Wikibase\Entity;
-use Wikibase\EntityContent;
-use Wikibase\EntityContentFactory;
-use Wikibase\Lib\PropertyNotFoundException;
-use Wikibase\Property;
 use Wikibase\Repo\WikibaseRepo;
-use Wikibase\LibRegistry;
-use Wikibase\Claim;
-use Wikibase\Autocomment;
-use Wikibase\Summary;
-use Wikibase\Snak;
+use Wikibase\Claims;
+use Wikibase\ChangeOpClaim;
 use Wikibase\Validators\ValidatorErrorLocalizer;
+use ValueParsers\ParseException;
 
 /**
  * API module for creating claims.
@@ -48,14 +37,23 @@
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
  * @author Daniel Kinzler
+ * @author Tobias Gritschacher < [email protected] >
  */
-class CreateClaim extends ApiWikibase {
-
+class CreateClaim extends ModifyClaim {
 
        /**
+        * @since 0.4
+        *
         * @var SnakValidationHelper
         */
        protected $snakValidation;
+
+       /**
+        * @since 0.4
+        *
+        * @var ClaimModificationHelper
+        */
+       protected $claimModificationHelper;
 
        /**
         * see ApiBase::__construct()
@@ -73,6 +71,13 @@
                        
WikibaseRepo::getDefaultInstance()->getDataTypeFactory(),
                        new ValidatorErrorLocalizer()
                );
+
+               $this->claimModificationHelper = new ClaimModificationHelper(
+                       $mainModule,
+                       
WikibaseRepo::getDefaultInstance()->getEntityContentFactory(),
+                       
WikibaseRepo::getDefaultInstance()->getSnakConstructionService(),
+                       WikibaseRepo::getDefaultInstance()->getEntityIdParser()
+               );
        }
 
        /**
@@ -86,105 +91,29 @@
                $params = $this->extractRequestParams();
                $this->validateParameters( $params );
 
-               $entityContent = $this->getEntityContent();
+               $entityId = 
$this->claimModificationHelper->getEntityIdFromString( $params['entity'] );
+               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
+               $entityTitle = $this->claimModificationHelper->getEntityTitle( 
$entityId );
+               // TODO: put loadEntityContent into a separate helper class for 
great reuse!
+               $entityContent = $this->loadEntityContent( $entityTitle, 
$baseRevisionId );
+               $entity = $entityContent->getEntity();
 
-               // It is possible we get an exception from this method because 
of specifying
-               // a non existing-property, specifying an entity id for an 
entity with wrong
-               // entity type or providing an invalid DataValue.
-               try {
-                       $snak = $this->getSnakInstance();
+               $propertyId = 
$this->claimModificationHelper->getEntityIdFromString( $params['property'] );
 
-                       $this->snakValidation->validateSnak( $snak );
+               $snak = $this->claimModificationHelper->getSnakInstance( 
$params, $propertyId );
+               $this->snakValidation->validateSnak( $snak );
 
-                       $claim = $this->addClaim( $entityContent->getEntity(), 
$snak );
-                       $summary = $this->createSummary( $snak, 'create' );
+               $summary = $this->claimModificationHelper->createSummary( 
$params, $this );
+               $changeOp = new ChangeOpClaim( '', $snak, 
WikibaseRepo::getDefaultInstance()->getIdFormatter() );
+               $changeOp->apply( $entity, $summary );
+               $claims = new Claims( $entity->getClaims() );
+               $claim = $claims->getClaimWithGuid( $changeOp->getClaimGuid() );
 
-                       $this->saveChanges( $entityContent, $summary );
+               $this->saveChanges( $entityContent, $summary );
 
-                       $this->outputClaim( $claim );
-
-               }
-               catch ( IllegalValueException $ex ) {
-                       $this->dieUsage( 'Invalid snak: IllegalValueException', 
'invalid-snak' );
-               }
-               catch ( PropertyNotFoundException $ex ) {
-                       $this->dieUsage( 'Invalid snak: 
PropertyNotFoundException', 'invalid-snak' );
-               }
-               catch ( ParseException $parseException ) {
-                       $this->dieUsage( 'Invalid guid: ParseException', 
'invalid-guid' );
-               }
+               $this->claimModificationHelper->addClaimToApiResult( $claim );
 
                wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * Constructs a new Claim based on the arguments provided to the API,
-        * adds it to the Entity and saves it.
-        *
-        * On success, the added Claim is returned as part of the Status object.
-        *
-        * @since 0.2
-        *
-        * @param \Wikibase\Entity $entity
-        * @param \Wikibase\Snak $snak
-        *
-        * @return Claim
-        */
-       protected function addClaim( Entity $entity, Snak $snak ) {
-               wfProfileIn( __METHOD__ );
-               $claim = $entity->newClaim( $snak );
-
-               $entity->addClaim( $claim );
-
-               wfProfileOut( __METHOD__ );
-               return $claim;
-       }
-
-       /**
-        * @since 0.3
-        *
-        * @param \Wikibase\EntityContent $content
-        * @param \Wikibase\Summary $summary
-        */
-       protected function saveChanges( EntityContent $content, Summary 
$summary ) {
-               $status = $this->attemptSaveEntity(
-                       $content,
-                       $summary->toString(),
-                       EDIT_UPDATE
-               );
-
-               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
-       }
-
-       /**
-        * Create a summary
-        *
-        * @since 0.4
-        *
-        * @param Snak $snak
-        * @param string $action
-        *
-        * @return Summary
-        * @throws \MWException
-        */
-       protected function createSummary( Snak $snak, $action ) {
-               if ( !is_string( $action ) ) {
-                       throw new \MWException( 'action is invalid or unknown 
type.' );
-               }
-
-               $summary = new Summary( $this->getModuleName() );
-               $summary->setAction( $action );
-               $summary->addAutoSummaryArgs( $snak->getPropertyId(), 
$snak->getDataValue() );
-
-               return $summary;
-       }
-
-       /**
-        * @see ApiBase::isWriteMode
-        * @return bool true
-        */
-       public function isWriteMode() {
-               return true;
        }
 
        /**
@@ -192,6 +121,8 @@
         * snaktype value are not set.
         *
         * @since 0.2
+        *
+        * @params array $params
         */
        protected function validateParameters( array $params ) {
                if ( $params['snaktype'] == 'value' XOR isset( $params['value'] 
) ) {
@@ -206,152 +137,82 @@
                if ( !isset( $params['property'] ) ) {
                        $this->dieUsage( 'A property ID needs to be provided 
when creating a claim with a Snak', 'param-missing' );
                }
-       }
 
-       /**
-        * @since 0.2
-        *
-        * @return EntityContent
-        */
-       protected function getEntityContent() {
-               $params = $this->extractRequestParams();
-
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-
-               $entityId = EntityId::newFromPrefixedId( $params['entity'] );
-               $entityTitle = $entityId ? 
EntityContentFactory::singleton()->getTitleForId( $entityId ) : null;
-               $entityContent = $entityTitle === null ? null : 
$this->loadEntityContent( $entityTitle, $baseRevisionId );
-
-               if ( $entityContent === null ) {
-                       $this->dieUsage( 'Entity not found, snak not created', 
'no-such-entity' );
+               if ( isset( $params['value'] ) && \FormatJson::decode( 
$params['value'], true ) == null ) {
+                       $this->dieUsage( 'Could not decode snak value', 
'invalid-snak' );
                }
-
-               return $entityContent;
-       }
-
-       /**
-        * @since 0.2
-        *
-        * @return Snak
-        * @throws ParseException
-        * @throws IllegalValueException
-        */
-       protected function getSnakInstance() {
-               $params = $this->extractRequestParams();
-
-               $snakType = $params['snaktype'];
-               $valueData = isset( $params['value'] ) ? \FormatJson::decode( 
$params['value'], true ) : null;
-
-               //TODO: Inject all this, or at least initialize it in a central 
location.
-               $factory = 
WikibaseRepo::getDefaultInstance()->getSnakConstructionService();
-               $entityIdParser = 
WikibaseRepo::getDefaultInstance()->getEntityIdParser();
-
-               $entityId = $entityIdParser->parse( $params['property'] );
-
-               if ( $entityId->getEntityType() !== Property::ENTITY_TYPE ) {
-                       $this->dieUsage( 'Property expected, got ' . 
$entityId->getEntityType(), 'invalid-snak' );
-               }
-
-               return $factory->newSnak(
-                       $entityId,
-                       $snakType,
-                       $valueData
-               );
-       }
-
-       /**
-        * @since 0.3
-        *
-        * @param Claim $claim
-        */
-       protected function outputClaim( Claim $claim ) {
-               $serializerFactory = new 
\Wikibase\Lib\Serializers\SerializerFactory();
-
-               $serializer = $serializerFactory->newSerializerForObject( 
$claim );
-               $serializer->getOptions()->setIndexTags( 
$this->getResult()->getIsRawMode() );
-
-               $this->getResult()->addValue(
-                       null,
-                       'claim',
-                       $serializer->getSerialized( $claim )
-               );
        }
 
        /**
         * @see \ApiBase::getPossibleErrors()
         */
        public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'invalid-snak', 'info' => $this->msg( 
'wikibase-api-invalid-snak' )->text() ),
-                       array( 'code' => 'invalid-guid', 'info' => $this->msg( 
'wikibase-api-invalid-guid' )->text() ),
-                       array( 'code' => 'param-missing', 'info' => $this->msg( 
'wikibase-api-param-missing' )->text() ),
-                       array( 'code' => 'param-illegal', 'info' => $this->msg( 
'wikibase-api-param-illegal' )->text() ),
-                       array( 'code' => 'no-such-entity', 'info' => 
$this->msg( 'wikibase-api-no-such-entity' )->text() ),
-               ) );
+               return array_merge(
+                       parent::getPossibleErrors(),
+                       $this->claimModificationHelper->getPossibleErrors(),
+                       array(
+                               array( 'code' => 'param-missing', 'info' => 
$this->msg( 'wikibase-api-param-missing' )->text() ),
+                               array( 'code' => 'param-illegal', 'info' => 
$this->msg( 'wikibase-api-param-illegal' )->text() ),
+                       )
+               );
        }
 
        /**
         * @see \ApiBase::getAllowedParams
-        *
-        * @since 0.2
-        *
-        * @return array
         */
        public function getAllowedParams() {
-               return array(
-                       'entity' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true,
-                       ),
-                       'snaktype' => array(
-                               ApiBase::PARAM_TYPE => array( 'value', 
'novalue', 'somevalue' ),
-                               ApiBase::PARAM_REQUIRED => true,
-                       ),
-                       'property' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => false,
-                       ),
-                       'value' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => false,
-                       ),
-                       'token' => null,
-                       'baserevid' => array(
-                               ApiBase::PARAM_TYPE => 'integer',
-                       ),
-                       'bot' => false,
+               return array_merge(
+                       parent::getAllowedParams(),
+                       array(
+                               'entity' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => true,
+                               ),
+                               'snaktype' => array(
+                                       ApiBase::PARAM_TYPE => array( 'value', 
'novalue', 'somevalue' ),
+                                       ApiBase::PARAM_REQUIRED => true,
+                               ),
+                               'property' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => false,
+                               ),
+                               'value' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => false,
+                               ),
+                               'token' => null,
+                               'baserevid' => array(
+                                       ApiBase::PARAM_TYPE => 'integer',
+                               ),
+                               'bot' => false,
+                       )
                );
        }
 
        /**
         * @see \ApiBase::getParamDescription
-        *
-        * @since 0.2
-        *
-        * @return array
         */
        public function getParamDescription() {
-               return array(
-                       'entity' => 'Id of the entity you are adding the claim 
to',
-                       'property' => 'Id of the snaks property',
-                       'value' => 'Value of the snak when creating a claim 
with a snak that has a value',
-                       'snaktype' => 'The type of the snak',
-                       'token' => 'An "edittoken" token previously obtained 
through the token module (prop=info).',
-                       'baserevid' => array( 'The numeric identifier for the 
revision to base the modification on.',
-                               "This is used for detecting conflicts during 
save."
-                       ),
-                       'bot' => array( 'Mark this edit as bot',
-                               'This URL flag will only be respected if the 
user belongs to the group "bot".'
-                       ),
+               return array_merge(
+                       parent::getParamDescription(),
+                       array(
+                               'entity' => 'Id of the entity you are adding 
the claim to',
+                               'property' => 'Id of the snaks property',
+                               'value' => 'Value of the snak when creating a 
claim with a snak that has a value',
+                               'snaktype' => 'The type of the snak',
+                               'token' => 'An "edittoken" token previously 
obtained through the token module (prop=info).',
+                               'baserevid' => array( 'The numeric identifier 
for the revision to base the modification on.',
+                                       "This is used for detecting conflicts 
during save."
+                               ),
+                               'bot' => array( 'Mark this edit as bot',
+                                       'This URL flag will only be respected 
if the user belongs to the group "bot".'
+                               ),
+                       )
                );
        }
 
        /**
         * @see \ApiBase::getDescription
-        *
-        * @since 0.2
-        *
-        * @return string
         */
        public function getDescription() {
                return array(
@@ -361,15 +222,12 @@
 
        /**
         * @see \ApiBase::getExamples
-        *
-        * @since 0.2
-        *
-        * @return array
         */
        protected function getExamples() {
                return array(
-                       
'api.php?action=wbcreateclaim&entity=q42&property=p9001&snaktype=novalue&token=foobar&baserevid=7201010',
-                       
'api.php?action=wbcreateclaim&entity=q42&property=p9001&snaktype=value&value={"entity-type":"item","numeric-id":1}&token=foobar&baserevid=7201010'
 => 'Creates a claim for q42 of p101 with a value of q1',
+                       
'api.php?action=wbcreateclaim&entity=q42&property=p9001&snaktype=novalue' => 
'Creates a claim for item q42 of property p9001 with a novalue snak.',
+                       
'api.php?action=wbcreateclaim&entity=q42&property=p9002&snaktype=value&value="itsastring"'
 => ' Creates a claim for item q42 of property p9002 with string value 
"itsastring"',
+                       
'api.php?action=wbcreateclaim&entity=q42&property=p9003&snaktype=value&value={"entity-type":"item","numeric-id":1}'
 => 'Creates a claim for item q42 of property p9003 with a value of item q1',
                );
        }
 }
diff --git a/repo/includes/api/ModifyClaim.php 
b/repo/includes/api/ModifyClaim.php
new file mode 100644
index 0000000..9d2f71d
--- /dev/null
+++ b/repo/includes/api/ModifyClaim.php
@@ -0,0 +1,101 @@
+<?php
+namespace Wikibase\Api;
+
+use ApiBase, MWException;
+use Wikibase\EntityContent;
+use Wikibase\Claim;
+use Wikibase\Summary;
+use Wikibase\Lib\Serializers\SerializerFactory;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Entity;
+use Wikibase\EntityId;
+use Wikibase\Property;
+use Wikibase\EntityContentFactory;
+
+/**
+ * Base class for modifying claims.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @ingroup WikibaseRepo
+ * @ingroup API
+ *
+ * @licence GNU GPL v2+
+ * @author Tobias Gritschacher < [email protected] >
+ * @author Jeroen De Dauw < [email protected] >
+ */
+abstract class ModifyClaim extends ApiWikibase {
+
+       /**
+        * @since 0.4
+        *
+        * @param \Wikibase\EntityContent $content
+        * @param \Wikibase\Summary $summary
+        */
+       public function saveChanges( EntityContent $content, Summary $summary ) 
{
+               $status = $this->attemptSaveEntity(
+                       $content,
+                       $summary->toString(),
+                       EDIT_UPDATE
+               );
+
+               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
+       }
+
+       /**
+        * @see ApiBase::isWriteMode
+        * @return bool true
+        */
+       public function isWriteMode() {
+               return true;
+       }
+
+       /**
+        * @see  \Api::getRequiredPermissions()
+        */
+       protected function getRequiredPermissions( Entity $entity, array 
$params ) {
+               $permissions = parent::getRequiredPermissions( $entity, $params 
);
+
+               $permissions[] = 'edit';
+               return $permissions;
+       }
+
+       /**
+        * @see \ApiBase::getAllowedParams
+        */
+       public function getAllowedParams() {
+               return array_merge(
+                       parent::getAllowedParams(),
+                       array( 'summary' => array( ApiBase::PARAM_TYPE => 
'string' ) )
+               );
+       }
+
+       /**
+        * @see ApiBase::getParamDescription()
+        */
+       public function getParamDescription() {
+               return array_merge(
+                       parent::getParamDescription(),
+                       array( 'summary' => array( 'Summary for the edit.',
+                               "Will be prepended by an automatically 
generated comment. The length limit of the
+                               autocomment together with the summary is 260 
characters. Be aware that everything above that
+                               limit will be cut off." )
+                       )
+               );
+       }
+}
diff --git a/repo/includes/api/SetClaimValue.php 
b/repo/includes/api/SetClaimValue.php
index 495d8cd..57f7524 100644
--- a/repo/includes/api/SetClaimValue.php
+++ b/repo/includes/api/SetClaimValue.php
@@ -3,24 +3,13 @@
 namespace Wikibase\Api;
 
 use ApiBase, MWException;
-
-use DataValues\IllegalValueException;
 use ApiMain;
-use ValueParsers\ParseException;
-use Wikibase\Autocomment;
 use Wikibase\EntityId;
 use Wikibase\Entity;
-use Wikibase\EntityContent;
-use Wikibase\EntityContentFactory;
-use Wikibase\Lib\PropertyNotFoundException;
-use Wikibase\Lib\SnakConstructionService;
-use Wikibase\SnakObject;
-use Wikibase\Claim;
 use Wikibase\Claims;
+use Wikibase\ChangeOpClaim;
 use Wikibase\Lib\ClaimGuidValidator;
 use Wikibase\Repo\WikibaseRepo;
-use Wikibase\Validators\ValidatorErrorLocalizer;
-use Wikibase\validators\SnakValidator;
 
 /**
  * API module for setting the DataValue contained by the main snak of a claim.
@@ -47,18 +36,16 @@
  *
  * @licence GNU GPL v2+
  * @author Jeroen De Dauw < [email protected] >
+ * @author Tobias Gritschacher < [email protected] >
  */
-class SetClaimValue extends ApiWikibase implements IAutocomment{
+class SetClaimValue extends ModifyClaim {
 
        /**
-        * @var SnakValidationHelper
+        * @since 0.4
+        *
+        * @var ClaimModificationHelper
         */
-       protected $snakValidation;
-
-       /**
-        * @var SnakConstructionService
-        */
-       protected $snakConstruction;
+       protected $claimModificationHelper;
 
        /**
         * see ApiBase::__construct()
@@ -70,14 +57,12 @@
        public function __construct( ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
                parent::__construct( $mainModule, $moduleName, $modulePrefix );
 
-               $this->snakValidation = new SnakValidationHelper(
-                       $this,
-                       
WikibaseRepo::getDefaultInstance()->getPropertyDataTypeLookup(),
-                       
WikibaseRepo::getDefaultInstance()->getDataTypeFactory(),
-                       new ValidatorErrorLocalizer()
+               $this->claimModificationHelper = new ClaimModificationHelper(
+                       $mainModule,
+                       
WikibaseRepo::getDefaultInstance()->getEntityContentFactory(),
+                       
WikibaseRepo::getDefaultInstance()->getSnakConstructionService(),
+                       WikibaseRepo::getDefaultInstance()->getEntityIdParser()
                );
-
-               $this->snakConstruction = 
WikibaseRepo::getDefaultInstance()->getSnakConstructionService();
        }
 
        /**
@@ -88,45 +73,44 @@
        public function execute() {
                wfProfileIn( __METHOD__ );
 
-               $content = $this->getEntityContent();
-
                $params = $this->extractRequestParams();
+               $this->validateParameters( $params );
 
-               try {
-                       $claim = $this->updateClaim(
-                               $content->getEntity(),
-                               $params['claim'],
-                               $params['snaktype'],
-                               isset( $params['value'] ) ? 
\FormatJson::decode( $params['value'], true ) : null
-                       );
+               $entityId = 
$this->claimModificationHelper->getEntityIdFromString(
+                       Entity::getIdFromClaimGuid( $params['claim'] )
+               );
+               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
+               $entityTitle = $this->claimModificationHelper->getEntityTitle( 
$entityId );
+               // TODO: put loadEntityContent into a separate helper class for 
great reuse!
+               $entityContent = $this->loadEntityContent( $entityTitle, 
$baseRevisionId );
+               $entity = $entityContent->getEntity();
+               $claims = new Claims( $entity->getClaims() );
+               $claimGuid = $params['claim'];
+               $claim = $claims->getClaimWithGuid( $claimGuid );
 
-                       $this->saveChanges( $content );
-                       $this->outputClaim( $claim );
+               if ( $claim === null ) {
+                       $this->dieUsage( "No claim for GUID: $claimGuid" , 
'no-such-claim' );
                }
-               catch ( IllegalValueException $ex ) {
-                       wfProfileOut( __METHOD__ );
-                       $this->dieUsage( 'Invalid snak: IllegalValueException', 
'invalid-snak' );
-               }
-               catch ( PropertyNotFoundException $ex ) {
-                       wfProfileOut( __METHOD__ );
-                       $this->dieUsage( 'Invalid snak: 
PropertyNotFoundException', 'invalid-snak' );
-               }
-               catch ( ParseException $parseException ) {
-                       wfProfileOut( __METHOD__ );
-                       $this->dieUsage( 'Invalid guid: ParseException', 
'invalid-guid' );
-               }
+
+               $snak = $this->claimModificationHelper->getSnakInstance( 
$params, $claim->getMainSnak()->getPropertyId() );
+
+               $summary = $this->claimModificationHelper->createSummary( 
$params, $this );
+               $changeOp = new ChangeOpClaim( $claimGuid, $snak, 
WikibaseRepo::getDefaultInstance()->getIdFormatter() );
+               $changeOp->apply( $entity, $summary );
+
+               $this->saveChanges( $entityContent, $summary );
+
+               $this->claimModificationHelper->addClaimToApiResult( $claim );
 
                wfProfileOut( __METHOD__ );
        }
 
        /**
-        * @since 0.3
+        * @since 0.4
         *
-        * @return \Wikibase\EntityContent
+        * @param array $params
         */
-       protected function getEntityContent() {
-               $params = $this->extractRequestParams();
-
+       protected function validateParameters( array $params ) {
                // @todo generalize handling of settings in api modules
                $settings = WikibaseRepo::getDefaultInstance()->getSettings();
                $entityPrefixes = $settings->getSetting( 'entityPrefixes' );
@@ -135,86 +119,6 @@
                if ( !( $claimGuidValidator->validate( $params['claim'] ) ) ) {
                        $this->dieUsage( 'Invalid claim guid' , 'invalid-guid' 
);
                }
-
-               $entityId = EntityId::newFromPrefixedId( 
Entity::getIdFromClaimGuid( $params['claim'] ) );
-               $entityTitle = 
EntityContentFactory::singleton()->getTitleForId( $entityId );
-
-               if ( $entityTitle === null ) {
-                       $this->dieUsage( 'No such entity' , 'no-such-entity' );
-               }
-
-               $baseRevisionId = isset( $params['baserevid'] ) ? intval( 
$params['baserevid'] ) : null;
-
-               return $this->loadEntityContent( $entityTitle, $baseRevisionId 
);
-       }
-
-       /**
-        * Updates the claim with specified GUID to have a main snak with 
provided value.
-        * The claim is modified in the passed along entity and is returned as 
well.
-        *
-        * @since 0.3
-        *
-        * @param \Wikibase\Entity $entity
-        * @param string $guid
-        * @param string $snakType
-        * @param mixed $value
-        *
-        * @return \Wikibase\Claim
-        */
-       protected function updateClaim( Entity $entity, $guid, $snakType, 
$value = null ) {
-               $claims = new Claims( $entity->getClaims() );
-
-               if ( !$claims->hasClaimWithGuid( $guid ) ) {
-                       $this->dieUsage( 'No such claim' , 'no-such-claim' );
-               }
-
-               $claim = $claims->getClaimWithGuid( $guid );
-               $oldSnak = $claim->getMainSnak();
-
-               try {
-                       $snak = $this->snakConstruction->newSnak( 
$oldSnak->getPropertyId(), $snakType, $value );
-                       $this->snakValidation->validateSnak( $snak );
-
-                       $claim->setMainSnak( $snak );
-                       $entity->setClaims( $claims );
-
-                       return $claim;
-               } catch ( IllegalValueException $ex ) {
-                       $this->dieUsage( $ex->getMessage(), 'invalid-snak' );
-               }
-       }
-
-       /**
-        * @since 0.3
-        *
-        * @param \Wikibase\EntityContent $content
-        */
-       protected function saveChanges( EntityContent $content ) {
-               $status = $this->attemptSaveEntity(
-                       $content,
-                       '', // TODO: automcomment
-                       EDIT_UPDATE
-               );
-
-               $this->addRevisionIdFromStatusToResult( 'pageinfo', 
'lastrevid', $status );
-       }
-
-       /**
-        * @since 0.3
-        *
-        * @param \Wikibase\Claim $claim
-        */
-       protected function outputClaim( Claim $claim ) {
-               $serializerFactory = new 
\Wikibase\Lib\Serializers\SerializerFactory();
-               $serializer = $serializerFactory->newSerializerForObject( 
$claim );
-
-               $serializer->getOptions()->setIndexTags( 
$this->getResult()->getIsRawMode() );
-
-               $this->getResult()->addValue(
-                       null,
-                       'claim',
-                       $serializer->getSerialized( $claim )
-               );
        }
 
        /**
@@ -225,24 +129,27 @@
         * @return array
         */
        public function getAllowedParams() {
-               return array(
-                       'claim' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true,
-                       ),
-                       'value' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => false,
-                       ),
-                       'snaktype' => array(
-                               ApiBase::PARAM_TYPE => array( 'value', 
'novalue', 'somevalue' ),
-                               ApiBase::PARAM_REQUIRED => true,
-                       ),
-                       'token' => null,
-                       'baserevid' => array(
-                               ApiBase::PARAM_TYPE => 'integer',
-                       ),
-                       'bot' => false,
+               return array_merge(
+                       parent::getAllowedParams(),
+                       array(
+                               'claim' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => true,
+                               ),
+                               'value' => array(
+                                       ApiBase::PARAM_TYPE => 'string',
+                                       ApiBase::PARAM_REQUIRED => false,
+                               ),
+                               'snaktype' => array(
+                                       ApiBase::PARAM_TYPE => array( 'value', 
'novalue', 'somevalue' ),
+                                       ApiBase::PARAM_REQUIRED => true,
+                               ),
+                               'token' => null,
+                               'baserevid' => array(
+                                       ApiBase::PARAM_TYPE => 'integer',
+                               ),
+                               'bot' => false,
+                       )
                );
        }
 
@@ -250,43 +157,38 @@
         * @see ApiBase::getPossibleErrors()
         */
        public function getPossibleErrors() {
-               return array_merge( parent::getPossibleErrors(), array(
-                       array( 'code' => 'invalid-guid', 'info' => $this->msg( 
'wikibase-api-invalid-guid' )->text() ),
-                       array( 'code' => 'no-such-entity', 'info' => 
$this->msg( 'wikibase-api-no-such-entity' )->text() ),
-                       array( 'code' => 'no-such-claim', 'info' => $this->msg( 
'wikibase-api-no-such-claim' )->text() ),
-                       array( 'code' => 'invalid-snak', 'info' => $this->msg( 
'wikibase-api-invalid-snak' )->text() ),
-               ) );
+               return array_merge(
+                       parent::getPossibleErrors(),
+                       $this->claimModificationHelper->getPossibleErrors(),
+                       array(
+                               array( 'code' => 'no-such-claim', 'info' => 
$this->msg( 'wikibase-api-no-such-claim' )->text() ),
+                       )
+               );
        }
 
        /**
         * @see \ApiBase::getParamDescription
-        *
-        * @since 0.3
-        *
-        * @return array
         */
        public function getParamDescription() {
-               return array(
-                       'claim' => 'A GUID identifying the claim',
-                       'snaktype' => 'The type of the snak',
-                       'value' => 'The value to set the datavalue of the the 
main snak of the claim to',
-                       'token' => 'An "edittoken" token previously obtained 
through the token module (prop=info).',
-                       'baserevid' => array( 'The numeric identifier for the 
revision to base the modification on.',
-                               "This is used for detecting conflicts during 
save."
-                       ),
-                       'bot' => array( 'Mark this edit as bot',
-                               'This URL flag will only be respected if the 
user belongs to the group "bot".'
-                       ),
-
+               return array_merge(
+                       parent::getParamDescription(),
+                       array(
+                               'claim' => 'A GUID identifying the claim',
+                               'snaktype' => 'The type of the snak',
+                               'value' => 'The value to set the datavalue of 
the the main snak of the claim to',
+                               'token' => 'An "edittoken" token previously 
obtained through the token module (prop=info).',
+                               'baserevid' => array( 'The numeric identifier 
for the revision to base the modification on.',
+                                       "This is used for detecting conflicts 
during save."
+                               ),
+                               'bot' => array( 'Mark this edit as bot',
+                                       'This URL flag will only be respected 
if the user belongs to the group "bot".'
+                               ),
+                       )
                );
        }
 
        /**
         * @see \ApiBase::getDescription
-        *
-        * @since 0.3
-        *
-        * @return string
         */
        public function getDescription() {
                return array(
@@ -296,44 +198,10 @@
 
        /**
         * @see \ApiBase::getExamples
-        *
-        * @since 0.3
-        *
-        * @return array
         */
        protected function getExamples() {
                return array(
                        
'api.php?action=wbsetclaimvalue&claim=q42$D8404CDA-25E4-4334-AF13-A3290BCD9C0F&snaktype=value&value={"entity-type":"item","numeric-id":1}&token=foobar&baserevid=7201010'
 => 'Sets the claim with the GUID of q42$D8404CDA-25E4-4334-AF13-A3290BCD9C0F 
to a value of q1',
                );
        }
-
-       /**
-        * @see \Wikibase\Api\IAutocomment::getTextForComment()
-        */
-       public function getTextForComment( array $params, $plural = 1 ) {
-               return Autocomment::formatAutoComment(
-                       $this->getModuleName(),
-                       array(
-                               /*plural */ (int)isset( $params['claim'] )
-                       )
-               );
-       }
-
-       /**
-        * @see \Wikibase\Api\IAutocomment::getTextForSummary()
-        */
-       public function getTextForSummary( array $params ) {
-               return Autocomment::formatAutoSummary(
-                       Autocomment::pickValuesFromParams( $params, 'claim' )
-               );
-       }
-
-       /**
-        * @see ApiBase::isWriteMode
-        * @return bool true
-        */
-       public function isWriteMode() {
-               return true;
-       }
-
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I0521a20bf6f600a952831418ebd4ef02bcb3f52f
Gerrit-PatchSet: 10
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[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