jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/377742 )
Change subject: Add request object of AddForm API action and created it from
API params
......................................................................
Add request object of AddForm API action and created it from API params
Change-Id: Ic593fcd9922f732036d7c5bdda4088887aa64928
---
A src/Api/AddFormRequest.php
A src/Api/AddFormRequestParser.php
A src/Api/AddFormRequestParserResult.php
A tests/phpunit/mediawiki/Api/AddFormRequestParserTest.php
A tests/phpunit/mediawiki/Api/AddFormRequestTest.php
5 files changed, 493 insertions(+), 0 deletions(-)
Approvals:
Aleksey Bekh-Ivanov (WMDE): Looks good to me, approved
jenkins-bot: Verified
diff --git a/src/Api/AddFormRequest.php b/src/Api/AddFormRequest.php
new file mode 100644
index 0000000..5a04c11
--- /dev/null
+++ b/src/Api/AddFormRequest.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Wikibase\Lexeme\Api;
+
+use Wikibase\DataModel\Entity\EntityIdParser;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Term\Term;
+use Wikibase\DataModel\Term\TermList;
+use Wikibase\Lexeme\ChangeOp\ChangeOpAddForm;
+use Wikibase\Lexeme\DataModel\LexemeId;
+use Wikimedia\Assert\Assert;
+
+/**
+ * @license GPL-2.0+
+ */
+class AddFormRequest {
+
+ /**
+ * @var LexemeId
+ */
+ private $lexemeId;
+
+ /**
+ * @var TermList
+ */
+ private $representations;
+
+ /**
+ * @var ItemId[]
+ */
+ private $grammaticalFeatures;
+
+ /**
+ * @param LexemeId $lexemeId
+ * @param TermList $representations
+ * @param ItemId[] $grammaticalFeatures
+ */
+ public function __construct(
+ LexemeId $lexemeId,
+ TermList $representations,
+ array $grammaticalFeatures
+ ) {
+ Assert::parameterElementType( ItemId::class,
$grammaticalFeatures, '$grammaticalFeatures' );
+ Assert::parameter( !$representations->isEmpty(),
'$representations', 'should not be empty' );
+
+ $this->lexemeId = $lexemeId;
+ $this->representations = $representations;
+ $this->grammaticalFeatures = $grammaticalFeatures;
+ }
+
+ /**
+ * @return ChangeOpAddForm
+ */
+ public function getChangeOp() {
+ return new ChangeOpAddForm( $this->representations,
$this->grammaticalFeatures );
+ }
+
+ /**
+ * @return LexemeId
+ */
+ public function getLexemeId() {
+ return $this->lexemeId;
+ }
+
+}
diff --git a/src/Api/AddFormRequestParser.php b/src/Api/AddFormRequestParser.php
new file mode 100644
index 0000000..bb2a7aa
--- /dev/null
+++ b/src/Api/AddFormRequestParser.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace Wikibase\Lexeme\Api;
+
+use Wikibase\DataModel\Entity\EntityIdParser;
+use Wikibase\DataModel\Entity\EntityIdParsingException;
+use Wikibase\DataModel\Term\Term;
+use Wikibase\DataModel\Term\TermList;
+use Wikibase\Lexeme\DataModel\LexemeId;
+
+/**
+ * @license GPL-2.0+
+ */
+class AddFormRequestParser {
+
+ /**
+ * @var EntityIdParser
+ */
+ private $entityIdParser;
+
+ public function __construct( EntityIdParser $entityIdParser ) {
+ $this->entityIdParser = $entityIdParser;
+ }
+
+ /**
+ * @param array $params
+ * @return AddFormRequestParserResult
+ */
+ public function parse( array $params ) {
+ $errors = $this->validateRequiredFieldsPresent( $params );
+ if ( $errors ) {
+ return AddFormRequestParserResult::newWithErrors(
$errors );
+ }
+
+ $data = json_decode( $params['data'], true );
+ if ( $data === null ) {
+ return AddFormRequestParserResult::newWithErrors( [
'data-invalid-json' ] );
+ }
+
+ $errors = $this->validateDataStructure( $data );
+ if ( $errors ) {
+ return AddFormRequestParserResult::newWithErrors(
$errors );
+ }
+
+ $lexemeId = $this->parseLexemeId( $params['lexemeId'], $errors
);
+ $representations = $this->parseRepresentations(
$data['representations'], $errors );
+ $grammaticalFeatures = $this->parseGrammaticalFeatures(
$data['grammaticalFeatures'], $errors );
+
+ if ( $errors ) {
+ return AddFormRequestParserResult::newWithErrors(
$errors );
+ }
+
+ return AddFormRequestParserResult::newWithRequest(
+ new AddFormRequest( $lexemeId, $representations,
$grammaticalFeatures )
+ );
+ }
+
+ private function validateDataStructure( $data ) {
+ $errors = [];
+
+ if ( !is_array( $data ) ) {
+ return [ 'data-not-array' ];
+ }
+
+ if ( !array_key_exists( 'representations', $data ) ) {
+ $errors[] = 'data-representations-key-missing';
+ } elseif ( !is_array( $data['representations'] ) ) {
+ $errors[] = 'data-representations-not-array';
+ }
+
+ if ( !array_key_exists( 'grammaticalFeatures', $data ) ) {
+ $errors[] = 'data-grammatical-features-key-missing';
+ } elseif ( !is_array( $data['grammaticalFeatures'] ) ) {
+ $errors[] = 'data-grammatical-features-not-array';
+ }
+
+ return $errors;
+ }
+
+ /**
+ * @param string $id
+ * @return LexemeId|null
+ */
+ private function parseLexemeId( $id, array &$errors ) {
+ try {
+ $lexemeId = $this->entityIdParser->parse( $id );
+ } catch ( EntityIdParsingException $e ) {
+ $errors[] = [ 'lexemeid-invalid', $id ];
+ return null;
+ }
+
+ if ( $lexemeId->getEntityType() !== 'lexeme' ) {
+ $errors[] = [ 'lexemeid-not-lexeme-id', $id ];
+ return null;
+ }
+
+ return $lexemeId;
+ }
+
+ private function parseRepresentations( array $data, array &$errors ) {
+ $representations = [];
+
+ foreach ( $data as $index => $representationData ) {
+ $incomplete = false;
+
+ if ( !array_key_exists( 'representation',
$representationData ) ) {
+ $errors[] = [ 'representation-text-missing',
$index ];
+ $incomplete = true;
+ }
+ if ( !array_key_exists( 'language', $representationData
) ) {
+ $errors[] = [
'representation-language-missing', $index ];
+ $incomplete = true;
+ }
+
+ if ( $incomplete ) {
+ continue;
+ }
+
+ $representations[] = new Term(
+ $representationData['language'],
+ $representationData['representation']
+ );
+ }
+
+ if ( empty( $representations ) ) {
+ $errors[] = 'representations-empty';
+ }
+
+ return new TermList( $representations );
+ }
+
+ private function parseGrammaticalFeatures( $data, array &$errors ) {
+ $features = [];
+
+ foreach ( $data as $index => $featureId ) {
+ try {
+ $id = $this->entityIdParser->parse( $featureId
);
+ } catch ( EntityIdParsingException $e ) {
+ $errors[] = [
'grammatical-feature-itemid-invalid', $featureId ];
+ continue;
+ }
+
+ if ( $id->getEntityType() !== 'item' ) {
+ $errors[] = [
'grammatical-feature-not-item-id', $featureId ];
+ continue;
+ }
+
+ $features[] = $id;
+ }
+
+ return $features;
+ }
+
+ private function validateRequiredFieldsPresent( array $params ) {
+ $errors = [];
+
+ if ( !array_key_exists( 'lexemeId', $params ) ) {
+ $errors[] = 'lexemeId-param-missing';
+ }
+
+ if ( !array_key_exists( 'data', $params ) ) {
+ $errors[] = 'data-parame-missing';
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/Api/AddFormRequestParserResult.php
b/src/Api/AddFormRequestParserResult.php
new file mode 100644
index 0000000..ba18383
--- /dev/null
+++ b/src/Api/AddFormRequestParserResult.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Wikibase\Lexeme\Api;
+
+/**
+ * @license GPL-2.0+
+ */
+class AddFormRequestParserResult {
+
+ private $request;
+
+ private $errors;
+
+ /**
+ * @param AddFormRequest|null $request
+ * @param string[] $errors
+ */
+ public function __construct( AddFormRequest $request = null, array
$errors ) {
+ $this->request = $request;
+ $this->errors = $errors;
+ }
+
+ public static function newWithRequest( AddFormRequest $request ) {
+ return new self( $request, [] );
+ }
+
+ public static function newWithErrors( array $errors ) {
+ return new self( null, $errors );
+ }
+
+ public function getRequest() {
+ return $this->request;
+ }
+
+ public function hasErrors() {
+ return !empty( $this->errors );
+ }
+
+ public function getErrors() {
+ return $this->errors;
+ }
+
+}
diff --git a/tests/phpunit/mediawiki/Api/AddFormRequestParserTest.php
b/tests/phpunit/mediawiki/Api/AddFormRequestParserTest.php
new file mode 100644
index 0000000..9f44cb7
--- /dev/null
+++ b/tests/phpunit/mediawiki/Api/AddFormRequestParserTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace Wikibase\Lexeme\Tests\MediaWiki\Api;
+
+use Wikibase\DataModel\Entity\DispatchingEntityIdParser;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Term\Term;
+use Wikibase\DataModel\Term\TermList;
+use Wikibase\Lexeme\Api\AddFormRequest;
+use Wikibase\Lexeme\Api\AddFormRequestParser;
+use Wikibase\Lexeme\ChangeOp\ChangeOpAddForm;
+use Wikibase\Lexeme\DataModel\LexemeId;
+
+/**
+ * @covers Wikibase\Lexeme\Api\AddFormRequestParser
+ *
+ * @group WikibaseLexeme
+ *
+ * @license GPL-2.0+
+ */
+class AddFormRequestParserTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider provideInvalidParamsAndErrors
+ */
+ public function testGivenInvalidParams_parseReturnsError( array $params
) {
+ $parser = $this->newAddFormRequestParser();
+
+ $result = $parser->parse( $params );
+
+ $this->assertTrue( $result->hasErrors() );
+ }
+
+ public function provideInvalidParamsAndErrors() {
+ $noRepresentationsInDataParams = json_encode(
+ [ 'grammaticalFeatures' => [] ]
+ );
+ $noGrammaticalFeaturesInDataParams = json_encode(
+ [ 'representations' => [ 'language' => 'en',
'representation' => 'goat' ] ]
+ );
+
+ return [
+ 'no lexemeId param' => [ [ 'data' =>
$this->getDataParam() ] ],
+ 'no data param' => [ [ 'lexemeId' => 'L1' ] ],
+ 'invalid lexeme ID (random string not ID)' => [ [
+ 'lexemeId' => 'foo', 'data' =>
$this->getDataParam()
+ ] ],
+ 'invalid lexeme ID (not a lexeme ID)' => [ [
+ 'lexemeId' => 'Q11', 'data' =>
$this->getDataParam()
+ ] ],
+ 'data not a well-formed JSON' => [ [ 'lexemeId' =>
'L1', 'data' => '{foo' ] ],
+ 'data not an array' => [ [ 'lexemeId' => 'L1', 'data'
=> 'foo' ] ],
+ 'no representations in data' => [ [
+ 'lexemeId' => 'L1', 'data' =>
$noRepresentationsInDataParams
+ ] ],
+ 'no grammatical features in data' => [ [
+ 'lexemeId' => 'L1', 'data' =>
$noGrammaticalFeaturesInDataParams
+ ] ],
+ 'representations not an array' => [ [
+ 'lexemeId' => 'L1', 'data' =>
$this->getDataParam( [ 'representations' => 'foo' ] )
+ ] ],
+ 'grammatical features not an array' => [ [
+ 'lexemeId' => 'L1', 'data' =>
$this->getDataParam( [ 'grammaticalFeatures' => 'Q1' ] )
+ ] ],
+ 'empty representation list in data' => [ [
+ 'lexemeId' => 'L1',
+ 'data' => $this->getDataParam( [
'representations' => [] ] )
+ ] ],
+ 'no representation string in data' => [ [
+ 'lexemeId' => 'L1',
+ 'data' => $this->getDataParam( [
'representations' => [ [ 'language' => 'en' ] ] ] )
+ ] ],
+ 'no representation language in data' => [ [
+ 'lexemeId' => 'L1',
+ 'data' => $this->getDataParam( [
'representations' => [ [ 'representation' => 'foo' ] ] ] )
+ ] ],
+ 'invalid item ID as grammatical feature (random string
not ID)' => [ [
+ 'lexemeId' => 'L1',
+ 'data' => $this->getDataParam(
+ [ 'representations' => [ [
'grammaticalFeatures' => [ 'foo' ] ] ] ]
+ )
+ ] ],
+ 'invalid item ID as grammatical feature (not an item
ID)' => [ [
+ 'lexemeId' => 'L1',
+ 'data' => $this->getDataParam(
+ [ 'representations' => [ [
'grammaticalFeatures' => [ 'L2' ] ] ] ]
+ )
+ ] ],
+ ];
+ }
+
+ public function testGivenValidData_parseReturnsRequestAndNoErrors() {
+ $parser = $this->newAddFormRequestParser();
+
+ $result = $parser->parse( [ 'lexemeId' => 'L1', 'data' =>
$this->getDataParam() ] );
+
+ $this->assertInstanceOf(
+ AddFormRequest::class,
+ $result->getRequest()
+ );
+ $this->assertFalse( $result->hasErrors() );
+ }
+
+ public function testLexemeIdPassedToRequestObject() {
+ $parser = $this->newAddFormRequestParser();
+
+ $result = $parser->parse( [ 'lexemeId' => 'L1', 'data' =>
$this->getDataParam() ] );
+ $request = $result->getRequest();
+
+ $this->assertEquals( new LexemeId( 'L1' ),
$request->getLexemeId() );
+ }
+
+ public function testFormDataPassedToRequestObject() {
+ $parser = $this->newAddFormRequestParser();
+
+ $result = $parser->parse( [ 'lexemeId' => 'L1', 'data' =>
$this->getDataParam() ] );
+ $request = $result->getRequest();
+
+ $this->assertEquals(
+ new ChangeOpAddForm( new TermList( [ new Term( 'en',
'goat' ) ] ), [ new ItemId( 'Q17' ) ] ),
+ $request->getChangeOp()
+ );
+ }
+
+ private function getDataParam( array $dataToUse = [] ) {
+ $simpleData = [
+ 'representations' => [
+ [
+ 'language' => 'en',
+ 'representation' => 'goat'
+ ]
+ ],
+ 'grammaticalFeatures' => [ 'Q17' ],
+ ];
+
+ return json_encode( array_merge( $simpleData, $dataToUse ) );
+ }
+
+ private function newAddFormRequestParser() {
+ $idParser = new DispatchingEntityIdParser( [
+ ItemId::PATTERN => function ( $id ) {
+ return new ItemId( $id );
+ },
+ LexemeId::PATTERN => function ( $id ) {
+ return new LexemeId( $id );
+ }
+ ] );
+
+ return new AddFormRequestParser( $idParser );
+ }
+
+}
diff --git a/tests/phpunit/mediawiki/Api/AddFormRequestTest.php
b/tests/phpunit/mediawiki/Api/AddFormRequestTest.php
new file mode 100644
index 0000000..b3c852b
--- /dev/null
+++ b/tests/phpunit/mediawiki/Api/AddFormRequestTest.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Wikibase\Lexeme\Tests\MediaWiki\Api;
+
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Term\Term;
+use Wikibase\DataModel\Term\TermList;
+use Wikibase\Lexeme\Api\AddFormRequest;
+use Wikibase\Lexeme\DataModel\LexemeId;
+use Wikibase\Lexeme\Tests\DataModel\NewLexeme;
+
+/**
+ * @covers Wikibase\Lexeme\Api\AddFormRequest
+ *
+ * @group WikibaseLexeme
+ *
+ * @license GPL-2.0+
+ */
+class AddFormRequestTest extends \PHPUnit_Framework_TestCase {
+
+ public function testReturnsChangeOpThatAddsForm() {
+ $request = new AddFormRequest(
+ new LexemeId( 'L1' ),
+ new TermList( [ new Term( 'en', 'goat' ) ] ),
+ [ new ItemId( 'Q1' ) ]
+ );
+
+ $changeOp = $request->getChangeOp();
+
+ $lexeme = NewLexeme::create()->build();
+
+ $changeOp->apply( $lexeme );
+
+ $forms = $lexeme->getForms();
+
+ $this->assertCount( 1, $forms );
+ $this->assertEquals( [ 'en' => 'goat' ],
$forms[0]->getRepresentations()->toTextArray() );
+ $this->assertEquals( [ new ItemId( 'Q1' ) ],
$forms[0]->getGrammaticalFeatures() );
+ }
+
+ public function
testGivenNonItemsAsGrammaticalFeatures_constructorThrowsException() {
+ $this->setExpectedException( \InvalidArgumentException::class );
+
+ new AddFormRequest(
+ new LexemeId( 'L1' ),
+ new TermList( [ new Term( 'en', 'goat' ) ] ),
+ [ 'foo' ]
+ );
+ }
+
+ public function
testGivenEmptyRepresentationList_constructorThrowsException() {
+ $this->setExpectedException( \InvalidArgumentException::class );
+
+ new AddFormRequest( new LexemeId( 'L1' ), new TermList(), [] );
+ }
+
+ public function testGetLexemeId() {
+ $lexemeId = new LexemeId( 'L1' );
+
+ $request = new AddFormRequest( $lexemeId, new TermList( [ new
Term( 'en', 'goat' ) ] ), [] );
+
+ $this->assertSame( $lexemeId, $request->getLexemeId() );
+ }
+
+}
--
To view, visit https://gerrit.wikimedia.org/r/377742
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic593fcd9922f732036d7c5bdda4088887aa64928
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/WikibaseLexeme
Gerrit-Branch: master
Gerrit-Owner: WMDE-leszek <[email protected]>
Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits