jenkins-bot has submitted this change and it was merged. Change subject: Allow id and type params in wbeditentity data! ......................................................................
Allow id and type params in wbeditentity data! Bug: 54146 Change-Id: I379b280bdf398c4cf35284469bbbfa9ee7877084 --- M repo/includes/api/EditEntity.php M repo/tests/phpunit/includes/api/EditEntityTest.php 2 files changed, 88 insertions(+), 29 deletions(-) Approvals: Daniel Kinzler: Looks good to me, approved jenkins-bot: Verified diff --git a/repo/includes/api/EditEntity.php b/repo/includes/api/EditEntity.php index 73e7da7..72ba60d 100644 --- a/repo/includes/api/EditEntity.php +++ b/repo/includes/api/EditEntity.php @@ -7,8 +7,8 @@ use InvalidArgumentException; use MWException; use Revision; +use Site; use SiteList; -use SiteSQLStore; use Title; use Wikibase\ChangeOp\ChangeOp; use Wikibase\ChangeOp\ChangeOpAliases; @@ -20,6 +20,7 @@ use Wikibase\ChangeOp\ChangeOpSiteLink; use Wikibase\ChangeOp\ChangeOps; use Wikibase\Claim; +use Wikibase\DataModel\Entity\EntityId; use Wikibase\Entity; use Wikibase\EntityContent; use Wikibase\Item; @@ -124,7 +125,7 @@ $entity = $entityContent->getEntity(); $this->validateDataParameter( $params ); $data = json_decode( $params['data'], true ); - $this->validateDataProperties( $data, $entityContent->getWikiPage() ); + $this->validateDataProperties( $data, $entityContent ); if ( $params['clear'] ) { $entity->clear(); @@ -171,6 +172,12 @@ return $summary; } + /** + * @param array $data + * @param Entity $entity + * + * @return ChangeOps + */ protected function getChangeOps( array $data, Entity $entity ) { $changeOps = new ChangeOps(); @@ -306,6 +313,7 @@ $aliasesChangeOps = array(); foreach ( $indexedAliases as $langCode => $args ) { $aliasesToSet = array(); + $language = ''; foreach ( $args as $arg ) { $this->validateMultilangArgs( $arg, $langCode ); @@ -334,7 +342,7 @@ * @since 0.4 * * @param array $siteLinks - * @param Entity $entity + * @param Entity|Item $entity * * @return ChangeOpSiteLink[] */ @@ -360,6 +368,7 @@ } else { $this->dieUsage( "There is no site for global site id '$globalSiteId'", 'no-such-site' ); } + /** @var Site $linkSite */ if ( $shouldRemove ) { $siteLinksChangeOps[] = new ChangeOpSiteLink( $globalSiteId ); @@ -373,7 +382,7 @@ if ( $linkPage === false ) { $this->dieUsage( - "The external client site did not provide page information for site '{$globalSiteId}' and title '{$pageTitle}'", + "The external client site did not provide page information for site '{$globalSiteId}'", 'no-external-page' ); } } else { @@ -508,26 +517,33 @@ /** * @since 0.4 + * * @param array $data - * @param WikiPage|bool $page + * @param EntityContent $entityContent */ - protected function validateDataProperties( $data, $page ) { + protected function validateDataProperties( $data, $entityContent ) { $title = null; $revision = null; - if ( $page ) { - $title = $page->getTitle(); - $revision = $page->getRevision(); + if ( $entityContent ) { + $wikiPage = $entityContent->getWikiPage(); + $title = $wikiPage->getTitle(); + $revision = $wikiPage->getTitle(); } $allowedProps = array( + // ignored props 'length', 'count', 'touched', + // checked props + 'id', + 'type', 'pageid', 'ns', 'title', 'lastrevid', + // useful props 'labels', 'descriptions', 'aliases', @@ -537,7 +553,9 @@ ); $this->checkValidJson( $data, $allowedProps ); - $this->checkPageIdProp( $data, $page ); + $this->checkEntityId( $data, $entityContent->getEntity()->getId() ); + $this->checkEntityType( $data, $entityContent ); + $this->checkPageIdProp( $data, $entityContent ); $this->checkNamespaceProp( $data, $title ); $this->checkTitleProp( $data, $title ); $this->checkRevisionProp( $data, $revision ); @@ -576,7 +594,10 @@ protected function checkPageIdProp( $data, $page ) { if ( isset( $data['pageid'] ) && ( is_object( $page ) ? $page->getId() !== $data['pageid'] : true ) ) { - $this->dieUsage( 'Illegal field used in call, "pageid", must either be correct or not given', 'param-illegal' ); + $this->dieUsage( + 'Illegal field used in call, "pageid", must either be correct or not given', + 'param-illegal' + ); } } @@ -588,7 +609,10 @@ // not completely convinced that we can use title to get the namespace in this case if ( isset( $data['ns'] ) && ( is_object( $title ) ? $title->getNamespace() !== $data['ns'] : true ) ) { - $this->dieUsage( 'Illegal field used in call: "namespace", must either be correct or not given', 'param-illegal' ); + $this->dieUsage( + 'Illegal field used in call: "namespace", must either be correct or not given', + 'param-illegal' + ); } } @@ -599,7 +623,10 @@ protected function checkTitleProp( $data, $title ) { if ( isset( $data['title'] ) && ( is_object( $title ) ? $title->getPrefixedText() !== $data['title'] : true ) ) { - $this->dieUsage( 'Illegal field used in call: "title", must either be correct or not given', 'param-illegal' ); + $this->dieUsage( + 'Illegal field used in call: "title", must either be correct or not given', + 'param-illegal' + ); } } @@ -610,7 +637,33 @@ protected function checkRevisionProp( $data, $revision ) { if ( isset( $data['lastrevid'] ) && ( is_object( $revision ) ? $revision->getId() !== $data['lastrevid'] : true ) ) { - $this->dieUsage( 'Illegal field used in call: "lastrevid", must either be correct or not given', 'param-illegal' ); + $this->dieUsage( + 'Illegal field used in call: "lastrevid", must either be correct or not given', + 'param-illegal' + ); + } + } + + private function checkEntityId( $data, EntityId $entityId ) { + if ( isset( $data['id'] ) ) { + $entityIdParser = WikibaseRepo::getDefaultInstance()->getEntityIdParser(); + $dataId = $entityIdParser->parse( $data['id'] ); + if( !$entityId->equals( $dataId ) ) { + $this->dieUsage( + 'Invalid field used in call: "id", must match id parameter', + 'param-invalid' + ); + } + } + } + + private function checkEntityType( $data, EntityContent $entityContent ) { + if ( isset( $data['type'] ) + && $entityContent->getEntity()->getType() !== $data['type'] ) { + $this->dieUsage( + 'Invalid field used in call: "type", must match type associated with id', + 'param-invalid' + ); } } @@ -632,6 +685,7 @@ array( 'code' => 'not-recognized-string', 'info' => $this->msg( 'wikibase-api-not-recognized-string' )->text() ), array( 'code' => 'param-illegal', 'info' => $this->msg( 'wikibase-api-param-illegal' )->text() ), array( 'code' => 'param-missing', 'info' => $this->msg( 'wikibase-api-param-missing' )->text() ), + array( 'code' => 'param-invalid', 'info' => $this->msg( 'wikibase-api-param-invalid' )->text() ), array( 'code' => 'inconsistent-language', 'info' => $this->msg( 'wikibase-api-inconsistent-language' )->text() ), array( 'code' => 'not-recognised-language', 'info' => $this->msg( 'wikibase-not-recognised-language' )->text() ), array( 'code' => 'inconsistent-site', 'info' => $this->msg( 'wikibase-api-inconsistent-site' )->text() ), diff --git a/repo/tests/phpunit/includes/api/EditEntityTest.php b/repo/tests/phpunit/includes/api/EditEntityTest.php index 7a34c43..855add1 100644 --- a/repo/tests/phpunit/includes/api/EditEntityTest.php +++ b/repo/tests/phpunit/includes/api/EditEntityTest.php @@ -2,9 +2,6 @@ namespace Wikibase\Test\Api; -use ApiTestCase; -use Wikibase\DataModel\Entity\ItemId; -use Wikibase\DataModel\Entity\PropertyId; use Wikibase\ItemContent; use Wikibase\PropertyContent; @@ -15,22 +12,15 @@ * * @licence GNU GPL v2+ * @author Adam Shorland - * @author Michał Łazowik + * @author Michal Lazowik * * @group API * @group Wikibase * @group WikibaseAPI * @group EditEntityTest * @group BreakingTheSlownessBarrier - * - * The database group has as a side effect that temporal database tables are created. This makes - * it possible to test without poisoning a production database. * @group Database - * - * Some of the tests takes more time, and needs therefor longer time before they can be aborted - * as non-functional. The reason why tests are aborted is assumed to be set up of temporal databases - * that hold the first tests in a pending state awaiting access to the database. - * @group large + * @group medium */ class EditEntityTest extends WikibaseApiTestCase { @@ -42,6 +32,7 @@ if( !isset( self::$hasSetup ) ){ $this->initTestEntities( array( 'Berlin' ) ); + self::$idMap['%Berlin%'] = EntityTestHelper::getId( 'Berlin' ); $prop = PropertyContent::newEmpty(); $prop->getEntity()->setDataTypeId( 'string' ); @@ -64,19 +55,23 @@ self::$hasSetup = true; } + /** + * Provide data for a sequence of requests that will work when run in order + * @return array + */ public static function provideData() { return array( 'new item' => array( // new item 'p' => array( 'new' => 'item', 'data' => '{}' ), 'e' => array( 'type' => 'item' ) ), - 'new property' => array( // new property + 'new property' => array( // new property (also make sure if we pass in a valid type it is accepted) 'p' => array( 'new' => 'property', 'data' => '{"datatype":"string"}' ), 'e' => array( 'type' => 'property' ) ), 'new property (this is our current example in the api doc)' => array( // new property (this is our current example in the api doc) 'p' => array( 'new' => 'property', 'data' => '{"labels":{"en-gb":{"language":"en-gb","value":"Propertylabel"}},'. '"descriptions":{"en-gb":{"language":"en-gb","value":"Propertydescription"}},"datatype":"string"}' ), 'e' => array( 'type' => 'property' ) ), - 'add a sitelink..' => array( // add a sitelink.. + 'add a sitelink..' => array( // add a sitelink.. (also makes sure if we pass in a valid id it is accepted) 'p' => array( 'data' => '{"sitelinks":{"dewiki":{"site":"dewiki","title":"TestPage!","badges":["%Q42%","%Q149%"]}}}' ), 'e' => array( 'sitelinks' => array( @@ -358,7 +353,7 @@ /** * @dataProvider provideData */ - function testEditEntity( $params, $expected ) { + public function testEditEntity( $params, $expected ) { $this->injectIds( $params ); $this->injectIds( $expected ); @@ -413,6 +408,10 @@ } } + /** + * Provide data for requests that will fail with a set exception, code and message + * @return array + */ public static function provideExceptionData() { return array( 'no entity id given' => array( // no entity id given @@ -494,6 +493,12 @@ 'no sitelink - cannot change badges' => array( // no sitelink - cannot change badges 'p' => array( 'site' => 'enwiki', 'title' => 'Berlin', 'data' => '{"sitelinks":{"svwiki":{"site":"svwiki","badges":["%Q42%","%Q149%"]}}}' ), 'e' => array( 'exception' => array( 'type' => 'UsageException', 'code' => 'no-such-sitelink' ) ) ), + 'bad id in serialization' => array( // no entity id given + 'p' => array( 'id' => '%Berlin%', 'data' => '{"id":"Q13244"}'), + 'e' => array( 'exception' => array( 'type' => 'UsageException', 'code' => 'param-invalid', 'message' => 'Invalid field used in call: "id", must match id parameter' ) ) ), + 'bad type in serialization' => array( // no entity id given + 'p' => array( 'id' => '%Berlin%', 'data' => '{"id":"%Berlin%","type":"foobar"}'), + 'e' => array( 'exception' => array( 'type' => 'UsageException', 'code' => 'param-invalid', 'message' => 'Invalid field used in call: "type", must match type associated with id' ) ) ), ); } -- To view, visit https://gerrit.wikimedia.org/r/94775 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I379b280bdf398c4cf35284469bbbfa9ee7877084 Gerrit-PatchSet: 16 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Addshore <addshorew...@gmail.com> Gerrit-Reviewer: Addshore <addshorew...@gmail.com> Gerrit-Reviewer: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits