jenkins-bot has submitted this change and it was merged. Change subject: Use ChangeOps for SetStatementRank ......................................................................
Use ChangeOps for SetStatementRank + support for custom edit summary + add autosummaries Bug: 52654 Change-Id: I9dd81d18f41f3c70f6a315dc873f0fbd6879e025 --- M repo/Wikibase.classes.php M repo/Wikibase.i18n.php M repo/includes/api/ClaimModificationHelper.php M repo/includes/api/SetStatementRank.php A repo/includes/changeop/ChangeOpStatementRank.php A repo/tests/phpunit/includes/changeop/ChangeOpStatementRankTest.php 6 files changed, 338 insertions(+), 146 deletions(-) Approvals: Addshore: Looks good to me, approved jenkins-bot: Verified diff --git a/repo/Wikibase.classes.php b/repo/Wikibase.classes.php index 01a8340..7b5e203 100644 --- a/repo/Wikibase.classes.php +++ b/repo/Wikibase.classes.php @@ -59,6 +59,7 @@ 'Wikibase\ChangeOpMainSnak' => 'includes/changeop/ChangeOpMainSnak.php', 'Wikibase\ChangeOpQualifier' => 'includes/changeop/ChangeOpQualifier.php', 'Wikibase\ChangeOpReference' => 'includes/changeop/ChangeOpReference.php', + 'Wikibase\ChangeOpStatementRank' => 'includes/changeop/ChangeOpStatementRank.php', 'Wikibase\ChangeOpException' => 'includes/changeop/ChangeOpException.php', // includes/actions diff --git a/repo/Wikibase.i18n.php b/repo/Wikibase.i18n.php index 25a329d..7db411e 100644 --- a/repo/Wikibase.i18n.php +++ b/repo/Wikibase.i18n.php @@ -329,6 +329,7 @@ 'wikibase-item-summary-wbsetqualifier-update' => 'Changed {{PLURAL:$1|qualifier|qualifiers}}', 'wikibase-item-summary-wbremovequalifiers-remove' => 'Removed {{PLURAL:$1|qualifier|qualifiers}}', 'wikibase-item-summary-wbremovereferences-remove' => 'Removed {{PLURAL:$3|reference|references}} from claim', + 'wikibase-item-summary-wbsetstatementrank' => 'Changed rank of statement from \'$3\' to \'$4\'', // property - summary and autocomment, see docs/summaries.txt 'wikibase-property-summary-wbcreate-new' => 'Created a new property', // legacy, backwards compatibility @@ -1060,6 +1061,9 @@ 'wikibase-property-summary-special-create-property' => 'Automatic edit summary when creating a property, and supplying one or more values. Parameters: * $1 is the number of values set (that is 0 - zero); * $2 is the language code of the entity page during creation.', + 'wikibase-item-summary-wbsetstatementrank' => 'Automatic edit summary when changing the rank of a statement. Parameters: +* $3 is the old rank +* $4 is the new rank', 'wikibase-listdatatypes-wikibase-item-head' => '{{Wikibase-datatype-head|Item|wikibase-item}} {{Identical|Item}}', 'wikibase-listdatatypes-wikibase-item-body' => '{{Wikibase-datatype-body|Item}} diff --git a/repo/includes/api/ClaimModificationHelper.php b/repo/includes/api/ClaimModificationHelper.php index b2791d1..7dbd697 100644 --- a/repo/includes/api/ClaimModificationHelper.php +++ b/repo/includes/api/ClaimModificationHelper.php @@ -116,15 +116,16 @@ * @since 0.4 * * @param Claim $claim + * @param string $key */ - public function addClaimToApiResult( Claim $claim ) { + public function addClaimToApiResult( Claim $claim, $key = 'claim' ) { $serializerFactory = new SerializerFactory(); $serializer = $serializerFactory->newSerializerForObject( $claim ); $serializer->getOptions()->setIndexTags( $this->apiMain->getResult()->getIsRawMode() ); $this->apiMain->getResult()->addValue( null, - 'claim', + $key, $serializer->getSerialized( $claim ) ); } diff --git a/repo/includes/api/SetStatementRank.php b/repo/includes/api/SetStatementRank.php index 0cb39ea..df10479 100644 --- a/repo/includes/api/SetStatementRank.php +++ b/repo/includes/api/SetStatementRank.php @@ -3,17 +3,14 @@ namespace Wikibase\Api; use ApiBase; -use MWException; - -use Wikibase\EntityId; use Wikibase\Entity; -use Wikibase\EntityContent; -use Wikibase\EntityContentFactory; -use Wikibase\Statement; -use Wikibase\Settings; -use Wikibase\Lib\ClaimGuidValidator; -use Wikibase\Lib\Serializers\ClaimSerializer; +use Wikibase\Claims; +use Wikibase\Claim; use Wikibase\Repo\WikibaseRepo; +use Wikibase\ChangeOpStatementRank; +use Wikibase\ChangeOpException; +use Wikibase\Statement; +use Wikibase\Lib\Serializers\ClaimSerializer; /** * API module for setting the rank of a statement @@ -40,19 +37,9 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < jeroended...@gmail.com > + * @author Tobias Gritschacher < tobias.gritschac...@wikimedia.de > */ -class SetStatementRank extends ApiWikibase { - - // TODO: automcomment - // TODO: example - // TODO: rights - // TODO: conflict detection - - public function __construct( $mainModule, $moduleName, $modulePrefix = '' ) { - //NOTE: need to declare this constructor, so old PHP versions don't use the - //setStatementRank() function as the constructor. - parent::__construct( $mainModule, $moduleName, $modulePrefix ); - } +class SetStatementRank extends ModifyClaim { /** * @see \ApiBase::execute @@ -62,111 +49,71 @@ public function execute() { wfProfileIn( __METHOD__ ); - $content = $this->getEntityContent(); $params = $this->extractRequestParams(); + $this->validateParameters( $params ); - $statement = $this->setStatementRank( - $content->getEntity(), - $params['statement'], - $params['rank'] + $entityId = $this->claimModificationHelper->getEntityIdFromString( + Entity::getIdFromClaimGuid( $params['statement'] ) ); + $entityTitle = $this->claimModificationHelper->getEntityTitle( $entityId ); + $entityContent = $this->getEntityContent( $entityTitle ); + $entity = $entityContent->getEntity(); + $summary = $this->claimModificationHelper->createSummary( $params, $this ); - $this->saveChanges( $content ); + $claimGuid = $params['statement']; + $claims = new Claims( $entity->getClaims() ); - $this->outputStatement( $statement ); + if ( !$claims->hasClaimWithGuid( $claimGuid ) ) { + $this->dieUsage( 'Could not find the statement' , 'no-such-statement' ); + } + + $claim = $claims->getClaimWithGuid( $claimGuid ); + + if ( ! ( $claim instanceof Statement ) ) { + $this->dieUsage( 'The referenced claim is not a statement and thus cannot have a rank', 'not-statement' ); + } + + $changeOp = $this->getChangeOp(); + + try { + $changeOp->apply( $entity, $summary ); + } catch ( ChangeOpException $e ) { + $this->dieUsage( $e->getMessage(), 'failed-save' ); + } + + $this->saveChanges( $entityContent, $summary ); + + $this->claimModificationHelper->addClaimToApiResult( $claim, 'statement' ); wfProfileOut( __METHOD__ ); } /** - * @since 0.3 + * Check the provided parameters * - * @return \Wikibase\EntityContent + * @since 0.4 */ - protected function getEntityContent() { - $params = $this->extractRequestParams(); - - // @todo generalize handling of settings in api modules - $settings = WikibaseRepo::getDefaultInstance()->getSettings(); - $entityPrefixes = $settings->getSetting( 'entityPrefixes' ); - $claimGuidValidator = new ClaimGuidValidator( $entityPrefixes ); - - if ( !( $claimGuidValidator->validate( $params['statement'] ) ) ) { + protected function validateParameters( array $params ) { + if ( !( $this->claimModificationHelper->validateClaimGuid( $params['statement'] ) ) ) { $this->dieUsage( 'Invalid claim guid' , 'invalid-guid' ); } - - $entityId = EntityId::newFromPrefixedId( Entity::getIdFromClaimGuid( $params['statement'] ) ); - $entityTitle = EntityContentFactory::singleton()->getTitleForId( $entityId ); - - if ( $entityTitle === null ) { - $this->dieUsage( 'Could not find an existing entity' , 'no-such-entity' ); - } - - $baseRevisionId = isset( $params['baserevid'] ) ? intval( $params['baserevid'] ) : null; - - return $this->loadEntityContent( $entityTitle, $baseRevisionId ); } /** - * @since 0.3 + * @since 0.4 * - * @param Entity $entity - * @param string $statementGuid - * @param string $rank - * - * @return \Wikibase\Statement + * @return ChangeOpStatementRank */ - protected function setStatementRank( Entity $entity, $statementGuid, $rank ) { - $claims = new \Wikibase\Claims( $entity->getClaims() ); + protected function getChangeOp() { + $params = $this->extractRequestParams(); - if ( !$claims->hasClaimWithGuid( $statementGuid ) ) { - $this->dieUsage( 'Could not find the statement' , 'no-such-statement' ); - } + $claimGuid = $params['statement']; + $idFormatter = WikibaseRepo::getDefaultInstance()->getIdFormatter(); - $statement = $claims->getClaimWithGuid( $statementGuid ); + $rank = ClaimSerializer::unserializeRank( $params['rank'] ); + $changeOp = new ChangeOpStatementRank( $claimGuid, $rank, $idFormatter ); - if ( ! ( $statement instanceof Statement ) ) { - $this->dieUsage( 'The referenced claim is not a statement and thus does not have a rank' , 'not-statement' ); - } - - $statement->setRank( ClaimSerializer::unserializeRank( $rank ) ); - - $entity->setClaims( $claims ); - - return $statement; - } - - /** - * @since 0.3 - * - * @param \Wikibase\EntityContent $content - */ - protected function saveChanges( EntityContent $content ) { - // collect information and create an EditEntity - $summary = '/* wbsetstatementrank */'; // TODO: automcomment - $status = $this->attemptSaveEntity( $content, - $summary, - EDIT_UPDATE ); - - $this->addRevisionIdFromStatusToResult( 'pageinfo', 'lastrevid', $status ); - } - - /** - * @since 0.3 - * - * @param \Wikibase\Statement $statement - */ - protected function outputStatement( Statement $statement ) { - $serializerFactory = new \Wikibase\Lib\Serializers\SerializerFactory(); - $serializer = $serializerFactory->newSerializerForObject( $statement ); - - $serializer->getOptions()->setIndexTags( $this->getResult()->getIsRawMode() ); - - $this->getResult()->addValue( - null, - 'statement', - $serializer->getSerialized( $statement ) - ); + return $changeOp; } /** @@ -177,20 +124,18 @@ * @return array */ public function getAllowedParams() { - return array( - 'statement' => array( - ApiBase::PARAM_TYPE => 'string', - ApiBase::PARAM_REQUIRED => true, - ), - 'rank' => array( - ApiBase::PARAM_TYPE => ClaimSerializer::getRanks(), - ApiBase::PARAM_REQUIRED => true, - ), - 'token' => null, - 'baserevid' => array( - ApiBase::PARAM_TYPE => 'integer', - ), - 'bot' => false, + return array_merge( + parent::getAllowedParams(), + array( + 'statement' => array( + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => true, + ), + 'rank' => array( + ApiBase::PARAM_TYPE => ClaimSerializer::getRanks(), + ApiBase::PARAM_REQUIRED => true, + ), + ) ); } @@ -198,12 +143,14 @@ * @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-statement', 'info' => $this->msg( 'wikibase-api-no-such-statement' )->text() ), - array( 'code' => 'not-statement', 'info' => $this->msg( 'wikibase-api-not-statement' )->text() ), - ) ); + return array_merge( + parent::getPossibleErrors(), + $this->claimModificationHelper->getPossibleErrors(), + array( + array( 'code' => 'no-such-statement', 'info' => $this->msg( 'wikibase-api-no-such-statement' )->text() ), + array( 'code' => 'not-statement', 'info' => $this->msg( 'wikibase-api-not-statement' )->text() ), + ) + ); } /** @@ -214,16 +161,12 @@ * @return array */ public function getParamDescription() { - return array( - 'statement' => 'A GUID identifying the statement for which to set the rank', - 'rank' => 'The new value to set for the rank', - '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( + 'statement' => 'A GUID identifying the statement for which to set the rank', + 'rank' => 'The new value to set for the rank', + ) ); } @@ -249,16 +192,7 @@ */ protected function getExamples() { return array( - // TODO - // 'ex' => 'desc' + 'api.php?action=wbsetstatementrank&format=json&statement=q2$4554c0f4-47b2-1cd9-2db9-aa270064c9f3&rank=normal&token=foobar' => 'Set the rank for the given statement to normal', ); } - - /** - * @see \ApiBase::isWriteMode() - */ - public function isWriteMode() { - return true; - } - } diff --git a/repo/includes/changeop/ChangeOpStatementRank.php b/repo/includes/changeop/ChangeOpStatementRank.php new file mode 100644 index 0000000..4346d0b --- /dev/null +++ b/repo/includes/changeop/ChangeOpStatementRank.php @@ -0,0 +1,146 @@ +<?php + +namespace Wikibase; + +use InvalidArgumentException; +use Wikibase\Snak; +use Wikibase\Statement; +use Wikibase\Lib\EntityIdFormatter; +use Wikibase\Lib\Serializers\ClaimSerializer; + +/** + * Class for statement rank change operation + * + * 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 + * + * @licence GNU GPL v2+ + * @author Tobias Gritschacher < tobias.gritschac...@wikimedia.de > + */ +class ChangeOpStatementRank extends ChangeOp { + + /** + * @since 0.4 + * + * @var string + */ + protected $claimGuid; + + /** + * @since 0.4 + * + * @var integer + */ + protected $rank; + + /** + * @since 0.4 + * + * @var EntityIdFormatter + */ + protected $idFormatter; + + /** + * Constructs a new statement rank change operation + * + * @since 0.4 + * + * @param string $claimGuid + * @param integer $rank + * @param EntityIdFormatter $entityIdFormatter + * + * @throws InvalidArgumentException + */ + public function __construct( $claimGuid, $rank, EntityIdFormatter $idFormatter ) { + if ( !is_string( $claimGuid ) ) { + throw new InvalidArgumentException( '$claimGuid needs to be a string' ); + } + + if ( !is_integer( $rank ) ) { + throw new InvalidArgumentException( '$rank needs to be an integer' ); + } + + $this->claimGuid = $claimGuid; + $this->rank = $rank; + $this->idFormatter = $idFormatter; + } + + /** + * Applies the change to the given entity + * + * @since 0.4 + * + * @param Entity $entity + * @param Summary|null $summary + * + * @return bool + * + * @throws ChangeOpException + */ + public function apply( Entity $entity, Summary $summary = null ) { + $claims = new Claims( $entity->getClaims() ); + + if( !$claims->hasClaimWithGuid( $this->claimGuid ) ) { + throw new ChangeOpException( "Entity does not have claim with GUID $this->claimGuid" ); + } + + $claim = $claims->getClaimWithGuid( $this->claimGuid ); + + if ( ! ( $claim instanceof Statement ) ) { + throw new ChangeOpException( 'The referenced claim is not a statement and thus cannot have a rank' ); + } + + $oldRank = $claim->getRank(); + $claim->setRank( $this->rank ); + $this->updateSummary( $summary, null, '', $this->getSnakSummaryArgs( $claim->getMainSnak() ) ); + + if ( $summary !== null ) { + $summary->addAutoCommentArgs( + array( ClaimSerializer::serializeRank( $oldRank ), ClaimSerializer::serializeRank( $this->rank ) ) + ); + } + + $entity->setClaims( $claims ); + + return true; + } + + /** + * @since 0.4 + * + * @param Snak $mainSnak + * + * @return array + * + * @todo: REUSE!! + */ + protected function getSnakSummaryArgs( Snak $snak ) { + $propertyId = $this->idFormatter->format( $snak->getPropertyId() ); + + //TODO: use formatters here! + if ( $snak instanceof PropertyValueSnak ) { + $value = $snak->getDataValue(); + } else { + $value = $snak->getType(); + } + + $args = array( $propertyId => array( $value ) ); + return array( $args ); + } +} diff --git a/repo/tests/phpunit/includes/changeop/ChangeOpStatementRankTest.php b/repo/tests/phpunit/includes/changeop/ChangeOpStatementRankTest.php new file mode 100644 index 0000000..38403af --- /dev/null +++ b/repo/tests/phpunit/includes/changeop/ChangeOpStatementRankTest.php @@ -0,0 +1,106 @@ +<?php + +namespace Wikibase\Test; + +use Wikibase\Claims; +use Wikibase\ChangeOpStatementRank; +use Wikibase\ItemContent; +use Wikibase\Repo\WikibaseRepo; +use Wikibase\Lib\ClaimGuidGenerator; +use InvalidArgumentException; + +/** + * @covers Wikibase\ChangeOpStatementRank + * + * 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 + * + * @file + * @since 0.4 + * + * @ingroup Wikibase + * @ingroup Test + * + * @group Wikibase + * @group WikibaseRepo + * @group ChangeOp + * + * @licence GNU GPL v2+ + * @author Tobias Gritschacher < tobias.gritschac...@wikimedia.de > + */ +class ChangeOpStatementRankTest extends \PHPUnit_Framework_TestCase { + + public function invalidArgumentProvider() { + $item = ItemContent::newFromArray( array( 'entity' => 'q42' ) )->getEntity(); + $validIdFormatter = WikibaseRepo::getDefaultInstance()->getIdFormatter(); + $guidGenerator = new \Wikibase\Lib\ClaimGuidGenerator( $item->getId() ); + $validClaimGuid = $guidGenerator->newGuid(); + $validRank = 1; + + $args = array(); + $args[] = array( 123, $validRank, $validIdFormatter ); + $args[] = array( $validClaimGuid, ':-)', $validIdFormatter ); + + return $args; + } + + /** + * @dataProvider invalidArgumentProvider + * + * @expectedException InvalidArgumentException + */ + public function testInvalidConstruct( $claimGuid, $rank, $idFormatter ) { + $ChangeOpStatementRank = new ChangeOpStatementRank( $claimGuid, $rank, $idFormatter ); + } + + public function changeOpProvider() { + $idFormatter = WikibaseRepo::getDefaultInstance()->getIdFormatter(); + $snak = new \Wikibase\PropertyValueSnak( 2754236, new \DataValues\StringValue( 'test' ) ); + $args = array(); + + $item = $this->provideNewItemWithClaim( 'q123', $snak ); + $claims = $item->getClaims(); + $claimGuid = $claims[0]->getGuid(); + $rank = 1; + + $changeOp = new ChangeOpStatementRank( $claimGuid, $rank, $idFormatter ); + + $args[] = array ( $item, $changeOp, $rank ); + + return $args; + } + + /** + * @dataProvider changeOpProvider + * + * @param Entity $item + * @param ChangeOpStatementRank $changeOp + */ + public function testApplyStatementRank( $item, $changeOp, $expectedRank ) { + $this->assertTrue( $changeOp->apply( $item ), "Applying the ChangeOp did not return true" ); + $claims = new Claims( $item->getClaims() ); + $rank = $claims[0]->getRank(); + $this->assertEquals( $rank, $expectedRank, "No reference with expected hash" ); + } + + protected function provideNewItemWithClaim( $itemId, $snak ) { + $entity = ItemContent::newFromArray( array( 'entity' => $itemId ) )->getEntity(); + $claim = $entity->newClaim( $snak ); + $claims = new Claims(); + $claims->addClaim( $claim ); + $entity->setClaims( $claims ); + + return $entity; + } +} -- To view, visit https://gerrit.wikimedia.org/r/78238 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I9dd81d18f41f3c70f6a315dc873f0fbd6879e025 Gerrit-PatchSet: 4 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: Addshore <addshorew...@gmail.com> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits