Skip to content

Commit

Permalink
Merge "REST: Add AddPropertyStatementRouteHandler"
Browse files Browse the repository at this point in the history
  • Loading branch information
jenkins-bot authored and Gerrit Code Review committed Aug 11, 2023
2 parents 4fc8090 + 5513590 commit b122e7c
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 1 deletion.
8 changes: 7 additions & 1 deletion repo/rest-api/routes.dev.json
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
[ ]
[
{
"path": "/wikibase/v0/entities/properties/{property_id}/statements",
"method": "POST",
"factory": "Wikibase\\Repo\\RestApi\\RouteHandlers\\AddPropertyStatementRouteHandler::factory"
}
]
106 changes: 106 additions & 0 deletions repo/rest-api/src/RouteHandlers/AddPropertyStatementRouteHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php declare( strict_types=1 );

namespace Wikibase\Repo\RestApi\RouteHandlers;

use MediaWiki\Rest\Response;
use MediaWiki\Rest\SimpleHandler;
use MediaWiki\Rest\StringStream;
use MediaWiki\Rest\Validator\BodyValidator;
use Wikibase\DataModel\Services\Statement\GuidGenerator;
use Wikibase\Repo\RestApi\Application\Serialization\StatementSerializer;
use Wikibase\Repo\RestApi\Application\UseCases\AddPropertyStatement\AddPropertyStatement;
use Wikibase\Repo\RestApi\Application\UseCases\AddPropertyStatement\AddPropertyStatementRequest;
use Wikibase\Repo\RestApi\Application\UseCases\AddPropertyStatement\AddPropertyStatementValidator;
use Wikibase\Repo\RestApi\Application\Validation\StatementValidator;
use Wikibase\Repo\RestApi\Domain\Services\StatementReadModelConverter;
use Wikibase\Repo\RestApi\Infrastructure\DataAccess\EntityRevisionLookupPropertyDataRetriever;
use Wikibase\Repo\RestApi\Infrastructure\DataAccess\EntityUpdaterPropertyUpdater;
use Wikibase\Repo\RestApi\WbRestApi;
use Wikibase\Repo\WikibaseRepo;
use Wikimedia\ParamValidator\ParamValidator;

/**
* @license GPL-2.0-or-later
*/
class AddPropertyStatementRouteHandler extends SimpleHandler {

public const PROPERTY_ID_PATH_PARAM = 'property_id';
public const STATEMENT_BODY_PARAM = 'statement';

private AddPropertyStatement $useCase;
private StatementSerializer $statementSerializer;

public function __construct(
AddPropertyStatement $useCase,
StatementSerializer $statementSerializer
) {
$this->useCase = $useCase;
$this->statementSerializer = $statementSerializer;
}

public static function factory(): self {
$statementReadModelConverter = new StatementReadModelConverter(
WikibaseRepo::getStatementGuidParser(),
WikibaseRepo::getPropertyDataTypeLookup()
);
return new self(
new AddPropertyStatement(
new AddPropertyStatementValidator( new StatementValidator( WbRestApi::getStatementDeserializer() ) ),
new EntityRevisionLookupPropertyDataRetriever(
WikibaseRepo::getEntityRevisionLookup(),
$statementReadModelConverter
),
new GuidGenerator(),
new EntityUpdaterPropertyUpdater(
WbRestApi::getEntityUpdater(),
$statementReadModelConverter
)
),
WbRestApi::getSerializerFactory()->newStatementSerializer()
);
}

public function run( string $propertyId ): Response {
$body = $this->getValidatedBody();
$useCaseResponse = $this->useCase->execute(
new AddPropertyStatementRequest(
$propertyId,
$body[self::STATEMENT_BODY_PARAM]
)
);

$httpResponse = $this->getResponseFactory()->create();
$httpResponse->setStatus( 201 );
$httpResponse->setHeader( 'Content-Type', 'application/json' );
$httpResponse->setBody( new StringStream( json_encode(
$this->statementSerializer->serialize( $useCaseResponse->getStatement() )
) ) );

return $httpResponse;
}

public function getParamSettings(): array {
return [
self::PROPERTY_ID_PATH_PARAM => [
self::PARAM_SOURCE => 'path',
ParamValidator::PARAM_TYPE => 'string',
ParamValidator::PARAM_REQUIRED => true,
],
];
}

/**
* @inheritDoc
*/
public function getBodyValidator( $contentType ): BodyValidator {
return $contentType === 'application/json' ?
new TypeValidatingJsonBodyValidator( [
self::STATEMENT_BODY_PARAM => [
self::PARAM_SOURCE => 'body',
ParamValidator::PARAM_TYPE => 'object',
ParamValidator::PARAM_REQUIRED => true,
],
] ) : parent::getBodyValidator( $contentType );
}

}
36 changes: 36 additions & 0 deletions repo/rest-api/tests/mocha/api-testing/AddPropertyStatementTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';

const { assert } = require( 'api-testing' );
const { expect } = require( '../helpers/chaiHelper' );
const entityHelper = require( '../helpers/entityHelper' );
const { newAddPropertyStatementRequestBuilder } = require( '../helpers/RequestBuilderFactory' );

describe( newAddPropertyStatementRequestBuilder().getRouteDescription(), () => {
let testPropertyId;
let testStatement;

function assertValid201Response( response, propertyId = null, valueContent = null ) {
expect( response ).to.have.status( 201 );
assert.strictEqual( response.header[ 'content-type' ], 'application/json' );
assert.strictEqual( response.body.property.id, propertyId || testStatement.property.id );
assert.deepStrictEqual( response.body.value.content, valueContent || testStatement.value.content );
}

before( async () => {
testPropertyId = ( await entityHelper.createUniqueStringProperty() ).entity.id;
testStatement = entityHelper.newStatementWithRandomStringValue( testPropertyId );
} );

describe( '201 success response ', () => {
it( 'can add a statement to a property', async () => {
const response = await newAddPropertyStatementRequestBuilder( testPropertyId, testStatement )
.assertValidRequest().makeRequest();
assertValid201Response(
response,
testPropertyId,
testStatement.value.content
);
} );
} );

} );
7 changes: 7 additions & 0 deletions repo/rest-api/tests/mocha/helpers/RequestBuilderFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ module.exports = {
.withJsonBodyParam( 'statement', statement );
},

newAddPropertyStatementRequestBuilder( propertyId, statement ) {
return new RequestBuilder()
.withRoute( 'POST', '/entities/properties/{property_id}/statements' )
.withPathParam( 'property_id', propertyId )
.withJsonBodyParam( 'statement', statement );
},

newGetItemStatementRequestBuilder( itemId, statementId ) {
return new RequestBuilder()
.withRoute( 'GET', '/entities/items/{item_id}/statements/{statement_id}' )
Expand Down

0 comments on commit b122e7c

Please sign in to comment.