Skip to content

Commit

Permalink
Merge "REST: Modify GetItem 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 370af68 + 6e83ac3 commit 68c48fd
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 180 deletions.
32 changes: 15 additions & 17 deletions repo/rest-api/src/RouteHandlers/GetItemRouteHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Wikibase\Repo\RestApi\RouteHandlers;

use LogicException;
use MediaWiki\Rest\Handler;
use MediaWiki\Rest\RequestInterface;
use MediaWiki\Rest\Response;
Expand All @@ -16,10 +15,10 @@
use Wikibase\Repo\RestApi\RouteHandlers\Middleware\UserAgentCheckMiddleware;
use Wikibase\Repo\RestApi\Serialization\ItemDataSerializer;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItem;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItemErrorResponse;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItemRequest;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItemSuccessResponse;
use Wikibase\Repo\RestApi\UseCases\ItemRedirectResponse;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItemResponse;
use Wikibase\Repo\RestApi\UseCases\ItemRedirectException;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;
use Wikibase\Repo\RestApi\WbRestApi;
use Wikimedia\ParamValidator\ParamValidator;

Expand Down Expand Up @@ -78,20 +77,19 @@ public function run( ...$args ): Response {

public function runUseCase( string $id ): Response {
$fields = explode( ',', $this->getValidatedParams()[self::FIELDS_QUERY_PARAM] );
$useCaseResponse = $this->getItem->execute( new GetItemRequest( $id, $fields ) );

if ( $useCaseResponse instanceof GetItemSuccessResponse ) {
return $this->newSuccessHttpResponse( $useCaseResponse );
} elseif ( $useCaseResponse instanceof ItemRedirectResponse ) {
return $this->newRedirectHttpResponse( $useCaseResponse );
} elseif ( $useCaseResponse instanceof GetItemErrorResponse ) {
return $this->responseFactory->newErrorResponse( $useCaseResponse );
} else {
throw new LogicException( 'Received an unexpected use case result in ' . __CLASS__ );

try {
return $this->newSuccessHttpResponse(
$this->getItem->execute( new GetItemRequest( $id, $fields ) )
);
} catch ( ItemRedirectException $e ) {
return $this->newRedirectHttpResponse( $e );
} catch ( UseCaseException $e ) {
return $this->responseFactory->newErrorResponseFromException( $e );
}
}

private function newSuccessHttpResponse( GetItemSuccessResponse $useCaseResponse ): Response {
private function newSuccessHttpResponse( GetItemResponse $useCaseResponse ): Response {
$httpResponse = $this->getResponseFactory()->create();
$httpResponse->setHeader( 'Content-Type', 'application/json' );
$httpResponse->setHeader( 'Last-Modified', wfTimestamp( TS_RFC2822, $useCaseResponse->getLastModified() ) );
Expand All @@ -103,12 +101,12 @@ private function newSuccessHttpResponse( GetItemSuccessResponse $useCaseResponse
return $httpResponse;
}

private function newRedirectHttpResponse( ItemRedirectResponse $useCaseResponse ): Response {
private function newRedirectHttpResponse( ItemRedirectException $e ): Response {
$httpResponse = $this->getResponseFactory()->create();
$httpResponse->setHeader(
'Location',
$this->getRouteUrl(
[ self::ITEM_ID_PATH_PARAM => $useCaseResponse->getRedirectTargetId() ],
[ self::ITEM_ID_PATH_PARAM => $e->getRedirectTargetId() ],
$this->getRequest()->getQueryParams()
)
);
Expand Down
26 changes: 14 additions & 12 deletions repo/rest-api/src/UseCases/GetItem/GetItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
use Wikibase\Repo\RestApi\Domain\Services\ItemDataRetriever;
use Wikibase\Repo\RestApi\Domain\Services\ItemRevisionMetadataRetriever;
use Wikibase\Repo\RestApi\UseCases\ErrorResponse;
use Wikibase\Repo\RestApi\UseCases\ItemRedirectResponse;
use Wikibase\Repo\RestApi\UseCases\ItemRedirectException;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;

/**
* @license GPL-2.0-or-later
Expand All @@ -28,28 +29,29 @@ public function __construct(
}

/**
* @return GetItemSuccessResponse|GetItemErrorResponse|ItemRedirectResponse
* @throws UseCaseException
* @throws ItemRedirectException
*/
public function execute( GetItemRequest $itemRequest ) {
$validationError = $this->validator->validate( $itemRequest );

if ( $validationError ) {
return GetItemErrorResponse::newFromValidationError( $validationError );
}
public function execute( GetItemRequest $itemRequest ): GetItemResponse {
$this->validator->assertValidRequest( $itemRequest );

$itemId = new ItemId( $itemRequest->getItemId() );
$latestRevisionMetadata = $this->revisionMetadataRetriever->getLatestRevisionMetadata( $itemId );

if ( !$latestRevisionMetadata->itemExists() ) {
return new GetItemErrorResponse(
throw new UseCaseException(
ErrorResponse::ITEM_NOT_FOUND,
"Could not find an item with the ID: {$itemRequest->getItemId()}"
);
} elseif ( $latestRevisionMetadata->isRedirect() ) {
return new ItemRedirectResponse( $latestRevisionMetadata->getRedirectTarget()->getSerialization() );
}

return new GetItemSuccessResponse(
if ( $latestRevisionMetadata->isRedirect() ) {
throw new ItemRedirectException(
$latestRevisionMetadata->getRedirectTarget()->getSerialization()
);
}

return new GetItemResponse(
$this->itemDataRetriever->getItemData( $itemId, $itemRequest->getFields() ),
$latestRevisionMetadata->getRevisionTimestamp(),
$latestRevisionMetadata->getRevisionId()
Expand Down
34 changes: 0 additions & 34 deletions repo/rest-api/src/UseCases/GetItem/GetItemErrorResponse.php

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 GetItemSuccessResponse {
class GetItemResponse {

private ItemData $itemData;

Expand Down
34 changes: 25 additions & 9 deletions repo/rest-api/src/UseCases/GetItem/GetItemValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,50 @@
namespace Wikibase\Repo\RestApi\UseCases\GetItem;

use Wikibase\Repo\RestApi\Domain\ReadModel\ItemData;
use Wikibase\Repo\RestApi\UseCases\ErrorResponse;
use Wikibase\Repo\RestApi\UseCases\UseCaseException;
use Wikibase\Repo\RestApi\Validation\ItemIdValidator;
use Wikibase\Repo\RestApi\Validation\ValidationError;

/**
* @license GPL-2.0-or-later
*/
class GetItemValidator {
public const CODE_INVALID_FIELD = 'invalid-field';

public const CONTEXT_FIELD_VALUE = 'field-value';
public const CODE_INVALID_FIELD = 'invalid-field';

private ItemIdValidator $itemIdValidator;

public function __construct( ItemIdValidator $itemIdValidator ) {
$this->itemIdValidator = $itemIdValidator;
}

public function validate( GetItemRequest $request ): ?ValidationError {
return $this->itemIdValidator->validate( $request->getItemId() )
?: $this->validateFields( $request->getFields() );
/**
* @throws UseCaseException
*/
public function assertValidRequest( GetItemRequest $request ): void {
$validationError = $this->itemIdValidator->validate( $request->getItemId() );

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

$this->validateFields( $request->getFields() );
}

private function validateFields( array $fields ): ?ValidationError {
/**
* @throws UseCaseException
*/
private function validateFields( array $fields ): void {
foreach ( $fields as $field ) {
if ( !in_array( $field, ItemData::VALID_FIELDS ) ) {
return new ValidationError( self::CODE_INVALID_FIELD, [ self::CONTEXT_FIELD_VALUE => $field ] );
throw new UseCaseException(
ErrorResponse::INVALID_FIELD,
'Not a valid field: ' . $field
);
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use PHPUnit\Framework\TestCase;
use Wikibase\Repo\RestApi\Presentation\Presenters\ErrorJsonPresenter;
use Wikibase\Repo\RestApi\UseCases\ErrorResponse;
use Wikibase\Repo\RestApi\UseCases\GetItem\GetItemErrorResponse;

/**
* @covers \Wikibase\Repo\RestApi\Presentation\Presenters\ErrorJsonPresenter
Expand All @@ -17,7 +16,7 @@
class ErrorJsonPresenterTest extends TestCase {

public function testGetJson_withoutContext(): void {
$error = new GetItemErrorResponse( ErrorResponse::ITEM_NOT_FOUND, 'Could not find an item with the ID Q123' );
$error = new ErrorResponse( ErrorResponse::ITEM_NOT_FOUND, 'Could not find an item with the ID Q123' );

$presenter = new ErrorJsonPresenter();

Expand Down

This file was deleted.

Loading

0 comments on commit 68c48fd

Please sign in to comment.