Skip to content

Commit

Permalink
Merge "REST: Modify AddItemStatement to use exceptions"
Browse files Browse the repository at this point in the history
  • Loading branch information
jenkins-bot authored and Gerrit Code Review committed Feb 27, 2023
2 parents 2d1cc94 + 119aa3b commit 370af68
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 275 deletions.
36 changes: 16 additions & 20 deletions repo/rest-api/src/RouteHandlers/AddItemStatementRouteHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Wikibase\Repo\RestApi\RouteHandlers;

use Exception;
use LogicException;
use MediaWiki\MediaWikiServices;
use MediaWiki\Rest\Handler;
use MediaWiki\Rest\RequestInterface;
Expand All @@ -19,9 +18,9 @@
use Wikibase\Repo\RestApi\RouteHandlers\Middleware\UserAgentCheckMiddleware;
use Wikibase\Repo\RestApi\Serialization\StatementSerializer;
use Wikibase\Repo\RestApi\UseCases\AddItemStatement\AddItemStatement;
use Wikibase\Repo\RestApi\UseCases\AddItemStatement\AddItemStatementErrorResponse;
use Wikibase\Repo\RestApi\UseCases\AddItemStatement\AddItemStatementRequest;
use Wikibase\Repo\RestApi\UseCases\AddItemStatement\AddItemStatementSuccessResponse;
use Wikibase\Repo\RestApi\UseCases\AddItemStatement\AddItemStatementResponse;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;
use Wikibase\Repo\RestApi\WbRestApi;
use Wikimedia\ParamValidator\ParamValidator;

Expand Down Expand Up @@ -95,23 +94,20 @@ public function run( ...$args ): Response {
*/
public function runUseCase( string $itemId ): Response {
$jsonBody = $this->getValidatedBody();
$useCaseResponse = $this->addItemStatement->execute(
new AddItemStatementRequest(
$itemId,
$jsonBody[self::STATEMENT_BODY_PARAM],
$jsonBody[self::TAGS_BODY_PARAM],
$jsonBody[self::BOT_BODY_PARAM],
$jsonBody[self::COMMENT_BODY_PARAM],
$this->getUsername()
)
);

if ( $useCaseResponse instanceof AddItemStatementSuccessResponse ) {
try {
$useCaseResponse = $this->addItemStatement->execute(
new AddItemStatementRequest(
$itemId,
$jsonBody[self::STATEMENT_BODY_PARAM],
$jsonBody[self::TAGS_BODY_PARAM],
$jsonBody[self::BOT_BODY_PARAM],
$jsonBody[self::COMMENT_BODY_PARAM],
$this->getUsername()
)
);
return $this->newSuccessHttpResponse( $useCaseResponse, $itemId );
} elseif ( $useCaseResponse instanceof AddItemStatementErrorResponse ) {
return $this->responseFactory->newErrorResponse( $useCaseResponse );
} else {
throw new LogicException( 'Received an unexpected use case result in ' . __CLASS__ );
} catch ( UseCaseException $e ) {
return $this->responseFactory->newErrorResponseFromException( $e );
}
}

Expand Down Expand Up @@ -156,7 +152,7 @@ public function getBodyValidator( $contentType ): BodyValidator {
] ) : parent::getBodyValidator( $contentType );
}

private function newSuccessHttpResponse( AddItemStatementSuccessResponse $useCaseResponse, string $itemId ): Response {
private function newSuccessHttpResponse( AddItemStatementResponse $useCaseResponse, string $itemId ): Response {
$httpResponse = $this->getResponseFactory()->create();
$httpResponse->setStatus( 201 );
$httpResponse->setHeader( 'Content-Type', 'application/json' );
Expand Down
19 changes: 8 additions & 11 deletions repo/rest-api/src/UseCases/AddItemStatement/AddItemStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Wikibase\Repo\RestApi\Domain\Services\ItemUpdater;
use Wikibase\Repo\RestApi\Domain\Services\PermissionChecker;
use Wikibase\Repo\RestApi\UseCases\ErrorResponse;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;

/**
* @license GPL-2.0-or-later
Expand Down Expand Up @@ -42,33 +43,29 @@ public function __construct(
}

/**
* @return AddItemStatementSuccessResponse | AddItemStatementErrorResponse
* @throws UseCaseException
*/
public function execute( AddItemStatementRequest $request ) {
$validationError = $this->validator->validate( $request );

if ( $validationError ) {
return AddItemStatementErrorResponse::newFromValidationError( $validationError );
}
public function execute( AddItemStatementRequest $request ): AddItemStatementResponse {
$this->validator->assertValidRequest( $request );

$statement = $this->validator->getValidatedStatement();
$itemId = new ItemId( $request->getItemId() );

$latestRevision = $this->revisionMetadataRetriever->getLatestRevisionMetadata( $itemId );
if ( $latestRevision->isRedirect() ) {
return new AddItemStatementErrorResponse(
throw new UseCaseException(
ErrorResponse::ITEM_REDIRECTED,
"Item {$request->getItemId()} has been merged into {$latestRevision->getRedirectTarget()}."
);
} elseif ( !$latestRevision->itemExists() ) {
return new AddItemStatementErrorResponse(
throw new UseCaseException(
ErrorResponse::ITEM_NOT_FOUND,
"Could not find an item with the ID: {$request->getItemId()}"
);
}
$user = $request->hasUser() ? User::withUsername( $request->getUsername() ) : User::newAnonymous();
if ( !$this->permissionChecker->canEdit( $user, $itemId ) ) {
return new AddItemStatementErrorResponse(
throw new UseCaseException(
ErrorResponse::PERMISSION_DENIED,
'You have no permission to edit this item.'
);
Expand All @@ -86,7 +83,7 @@ public function execute( AddItemStatementRequest $request ) {
);
$newRevision = $this->itemUpdater->update( $item, $editMetadata );

return new AddItemStatementSuccessResponse(
return new AddItemStatementResponse(
$newRevision->getItem()->getStatements()->getStatementById( $newStatementGuid ),
$newRevision->getLastModified(),
$newRevision->getRevisionId()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* @license GPL-2.0-or-later
*/
class AddItemStatementSuccessResponse {
class AddItemStatementResponse {

private Statement $statement;
private string $lastModified;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
namespace Wikibase\Repo\RestApi\UseCases\AddItemStatement;

use Wikibase\DataModel\Statement\Statement;
use Wikibase\Repo\RestApi\UseCases\ErrorResponse;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;
use Wikibase\Repo\RestApi\Validation\EditMetadataValidator;
use Wikibase\Repo\RestApi\Validation\ItemIdValidator;
use Wikibase\Repo\RestApi\Validation\StatementValidator;
use Wikibase\Repo\RestApi\Validation\ValidationError;

/**
* @license GPL-2.0-or-later
Expand All @@ -27,15 +28,96 @@ public function __construct(
$this->editMetadataValidator = $editMetadataValidator;
}

public function validate( AddItemStatementRequest $request ): ?ValidationError {
return $this->itemIdValidator->validate( $request->getItemId() ) ?:
$this->statementValidator->validate( $request->getStatement() ) ?:
$this->editMetadataValidator->validateComment( $request->getComment() ) ?:
$this->editMetadataValidator->validateEditTags( $request->getEditTags() );
/**
* @throws UseCaseException
*/
public function assertValidRequest( AddItemStatementRequest $request ): void {
$this->validateItemId( $request->getItemId() );
$this->validateStatement( $request->getStatement() );
$this->validateEditTags( $request->getEditTags() );
$this->validateComment( $request->getComment() );
}

public function getValidatedStatement(): ?Statement {
return $this->statementValidator->getValidatedStatement();
}

/**
* @throws UseCaseException
*/
private function validateItemId( ?string $itemId ): void {
if ( !isset( $itemId ) ) {
return;
}

$validationError = $this->itemIdValidator->validate( $itemId );

if ( $validationError ) {
throw new UseCaseException(
ErrorResponse::INVALID_ITEM_ID,
'Not a valid item ID: ' . $validationError->getContext()[ItemIdValidator::CONTEXT_VALUE]
);
}
}

/**
* @throws UseCaseException
*/
private function validateStatement( array $statement ): void {
$validationError = $this->statementValidator->validate( $statement );

if ( $validationError ) {
switch ( $validationError->getCode() ) {
case StatementValidator::CODE_INVALID_FIELD:
throw new UseCaseException(
ErrorResponse::STATEMENT_DATA_INVALID_FIELD,
"Invalid input for '{$validationError->getContext()[StatementValidator::CONTEXT_FIELD_NAME]}'",
[
'path' => $validationError->getContext()[StatementValidator::CONTEXT_FIELD_NAME],
'value' => $validationError->getContext()[StatementValidator::CONTEXT_FIELD_VALUE],
]
);
case StatementValidator::CODE_MISSING_FIELD:
throw new UseCaseException(
ErrorResponse::STATEMENT_DATA_MISSING_FIELD,
'Mandatory field missing in the statement data: ' .
$validationError->getContext()[StatementValidator::CONTEXT_FIELD_NAME],
[ 'path' => $validationError->getContext()[StatementValidator::CONTEXT_FIELD_NAME] ]
);
}
}
}

/**
* @throws UseCaseException
*/
private function validateEditTags( array $editTags ): void {
$validationError = $this->editMetadataValidator->validateEditTags( $editTags );

if ( $validationError ) {
throw new UseCaseException(
ErrorResponse::INVALID_EDIT_TAG,
"Invalid MediaWiki tag: {$validationError->getContext()[EditMetadataValidator::CONTEXT_TAG_VALUE]}"
);
}
}

/**
* @throws UseCaseException
*/
private function validateComment( ?string $comment ): void {
if ( !isset( $comment ) ) {
return;
}

$validationError = $this->editMetadataValidator->validateComment( $comment );

if ( $validationError ) {
$commentMaxLength = $validationError->getContext()[EditMetadataValidator::CONTEXT_COMMENT_MAX_LENGTH];
throw new UseCaseException(
ErrorResponse::COMMENT_TOO_LONG,
"Comment must not be longer than $commentMaxLength characters.",
);
}
}
}
Loading

0 comments on commit 370af68

Please sign in to comment.