Skip to content

Commit

Permalink
Merge "REST: Create GetPropertyDescriptionWithFallback route"
Browse files Browse the repository at this point in the history
  • Loading branch information
jenkins-bot authored and Gerrit Code Review committed Oct 7, 2024
2 parents 300275a + 250a81f commit 542283e
Show file tree
Hide file tree
Showing 18 changed files with 617 additions and 1 deletion.
5 changes: 5 additions & 0 deletions repo/rest-api/routes.dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@
"path": "/wikibase/v0/entities/items/{item_id}/descriptions_with_language_fallback/{language_code}",
"method": "GET",
"factory": "Wikibase\\Repo\\RestApi\\RouteHandlers\\GetItemDescriptionWithFallbackRouteHandler::factory"
},
{
"path": "/wikibase/v0/entities/properties/{property_id}/descriptions_with_language_fallback/{language_code}",
"method": "GET",
"factory": "Wikibase\\Repo\\RestApi\\RouteHandlers\\GetPropertyDescriptionWithFallbackRouteHandler::factory"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"get": {
"operationId": "getPropertyDescriptionWithFallback",
"tags": [ "descriptions" ],
"summary": "[WIP] Retrieve a Property's description in a specific language, with language fallback",
"description": "This endpoint is currently in development and is not recommended for production use",
"parameters": [
{ "$ref": "../../global/parameters.json#/PropertyId" },
{ "$ref": "../../global/parameters.json#/LanguageCode" },
{ "$ref": "../../global/parameters.json#/IfNoneMatch" },
{ "$ref": "../../global/parameters.json#/IfModifiedSince" },
{ "$ref": "../../global/parameters.json#/IfMatch" },
{ "$ref": "../../global/parameters.json#/IfUnmodifiedSince" },
{ "$ref": "../../global/parameters.json#/Authorization" }
],
"responses": {
"200": { "$ref": "../../global/responses.json#/Description" },
"304": { "$ref": "../../global/responses.json#/NotModified" },
"400": { "$ref": "../../global/responses.json#/InvalidTermByLanguageInput" },
"404": { "$ref": "../../global/responses.json#/ResourceNotFound" },
"412": { "$ref": "../../global/responses.json#/PreconditionFailedError" },
"500": { "$ref": "../../global/responses.json#/UnexpectedError" }
}
}
}
3 changes: 3 additions & 0 deletions repo/rest-api/specs/resources/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@
"/entities/properties/{property_id}/descriptions/{language_code}": {
"$ref": "./descriptions/description-in-language-for-property.json"
},
"/entities/properties/{property_id}/descriptions_with_language_fallback/{language_code}": {
"$ref": "./descriptions/description-with-fallback-for-property.json"
},
"/entities/items/{item_id}/statements": {
"$ref": "./statements/list-for-item.json"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyAliasesInLanguage\DeserializedGetPropertyAliasesInLanguageRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescription\DeserializedGetPropertyDescriptionRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptions\DeserializedGetPropertyDescriptionsRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback\DeserializedGetPropertyDescriptionWithFallbackRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabel\DeserializedGetPropertyLabelRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabels\DeserializedGetPropertyLabelsRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabelWithFallback\DeserializedGetPropertyLabelWithFallbackRequest;
Expand Down Expand Up @@ -88,6 +89,7 @@ class DeserializedRequestAdapter implements
DeserializedGetPropertyRequest,
DeserializedGetPropertyLabelsRequest,
DeserializedGetPropertyDescriptionsRequest,
DeserializedGetPropertyDescriptionWithFallbackRequest,
DeserializedGetPropertyAliasesRequest,
DeserializedGetPropertyAliasesInLanguageRequest,
DeserializedGetPropertyStatementRequest,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback;

use Wikibase\Repo\RestApi\Application\UseCaseRequestValidation\DeserializedLanguageCodeRequest;
use Wikibase\Repo\RestApi\Application\UseCaseRequestValidation\DeserializedPropertyIdRequest;

/**
* @license GPL-2.0-or-later
*/
interface DeserializedGetPropertyDescriptionWithFallbackRequest extends DeserializedPropertyIdRequest, DeserializedLanguageCodeRequest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback;

use Wikibase\Repo\RestApi\Application\UseCases\GetLatestPropertyRevisionMetadata;
use Wikibase\Repo\RestApi\Application\UseCases\UseCaseError;
use Wikibase\Repo\RestApi\Domain\Services\PropertyDescriptionRetriever;

/**
* @license GPL-2.0-or-later
*/
class GetPropertyDescriptionWithFallback {

private GetPropertyDescriptionWithFallbackValidator $validator;
private GetLatestPropertyRevisionMetadata $getRevisionMetadata;
private PropertyDescriptionRetriever $descriptionRetriever;

public function __construct(
GetPropertyDescriptionWithFallbackValidator $validator,
GetLatestPropertyRevisionMetadata $getRevisionMetadata,
PropertyDescriptionRetriever $descriptionRetriever
) {
$this->validator = $validator;
$this->getRevisionMetadata = $getRevisionMetadata;
$this->descriptionRetriever = $descriptionRetriever;
}

/**
* @throws UseCaseError
*/
public function execute( GetPropertyDescriptionWithFallbackRequest $request ): GetPropertyDescriptionWithFallbackResponse {
$deserializedRequest = $this->validator->validateAndDeserialize( $request );
$propertyId = $deserializedRequest->getPropertyId();
$languageCode = $deserializedRequest->getLanguageCode();

[ $revisionId, $lastModified ] = $this->getRevisionMetadata->execute( $propertyId );

$description = $this->descriptionRetriever->getDescription( $propertyId, $languageCode );
if ( !$description ) {
throw UseCaseError::newResourceNotFound( 'description' );
}

return new GetPropertyDescriptionWithFallbackResponse( $description, $lastModified, $revisionId );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback;

use Wikibase\Repo\RestApi\Application\UseCaseRequestValidation\DescriptionLanguageCodeRequest;
use Wikibase\Repo\RestApi\Application\UseCaseRequestValidation\PropertyIdRequest;
use Wikibase\Repo\RestApi\Application\UseCaseRequestValidation\UseCaseRequest;

/**
* @license GPL-2.0-or-later
*/
class GetPropertyDescriptionWithFallbackRequest implements UseCaseRequest, PropertyIdRequest, DescriptionLanguageCodeRequest {

private string $propertyId;
private string $languageCode;

public function __construct( string $propertyId, string $languageCode ) {
$this->propertyId = $propertyId;
$this->languageCode = $languageCode;
}

public function getPropertyId(): string {
return $this->propertyId;
}

public function getLanguageCode(): string {
return $this->languageCode;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback;

use Wikibase\Repo\RestApi\Domain\ReadModel\Description;

/**
* @license GPL-2.0-or-later
*/
class GetPropertyDescriptionWithFallbackResponse {

private Description $description;
private string $lastModified;
private int $revisionId;

public function __construct( Description $description, string $lastModified, int $revisionId ) {
$this->description = $description;
$this->lastModified = $lastModified;
$this->revisionId = $revisionId;
}

public function getDescription(): Description {
return $this->description;
}

public function getLastModified(): string {
return $this->lastModified;
}

public function getRevisionId(): int {
return $this->revisionId;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback;

use Wikibase\Repo\RestApi\Application\UseCases\UseCaseError;

/**
* @license GPL-2.0-or-later
*/
interface GetPropertyDescriptionWithFallbackValidator {

/**
* @throws UseCaseError
*/
public function validateAndDeserialize(
GetPropertyDescriptionWithFallbackRequest $request
): DeserializedGetPropertyDescriptionWithFallbackRequest;
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyAliasesInLanguage\GetPropertyAliasesInLanguageValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescription\GetPropertyDescriptionValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptions\GetPropertyDescriptionsValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback\GetPropertyDescriptionWithFallbackValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabel\GetPropertyLabelValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabels\GetPropertyLabelsValidator;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyLabelWithFallback\GetPropertyLabelWithFallbackValidator;
Expand Down Expand Up @@ -109,6 +110,7 @@ class ValidatingRequestDeserializer implements
GetPropertyValidator,
GetPropertyLabelsValidator,
GetPropertyDescriptionsValidator,
GetPropertyDescriptionWithFallbackValidator,
GetPropertyAliasesValidator,
GetPropertyAliasesInLanguageValidator,
GetPropertyStatementValidator,
Expand All @@ -135,8 +137,8 @@ class ValidatingRequestDeserializer implements
SetItemLabelValidator,
SetItemDescriptionValidator,
GetPropertyLabelValidator,
GetPropertyLabelWithFallbackValidator,
GetPropertyDescriptionValidator,
GetPropertyLabelWithFallbackValidator,
SetPropertyDescriptionValidator,
PatchPropertyLabelsValidator,
PatchPropertyDescriptionsValidator,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php declare( strict_types = 1 );

namespace Wikibase\Repo\RestApi\RouteHandlers;

use MediaWiki\Rest\RequestInterface;
use MediaWiki\Rest\Response;
use MediaWiki\Rest\ResponseInterface;
use MediaWiki\Rest\SimpleHandler;
use MediaWiki\Rest\StringStream;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback\GetPropertyDescriptionWithFallback;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback\GetPropertyDescriptionWithFallbackRequest;
use Wikibase\Repo\RestApi\Application\UseCases\GetPropertyDescriptionWithFallback\GetPropertyDescriptionWithFallbackResponse;
use Wikibase\Repo\RestApi\Application\UseCases\UseCaseError;
use Wikibase\Repo\RestApi\RouteHandlers\Middleware\AuthenticationMiddleware;
use Wikibase\Repo\RestApi\RouteHandlers\Middleware\MiddlewareHandler;
use Wikibase\Repo\RestApi\RouteHandlers\Middleware\UserAgentCheckMiddleware;
use Wikibase\Repo\RestApi\WbRestApi;
use Wikimedia\ParamValidator\ParamValidator;

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

private const PROPERTY_ID_PATH_PARAM = 'property_id';
private const LANGUAGE_CODE_PATH_PARAM = 'language_code';

private GetPropertyDescriptionWithFallback $useCase;
private MiddlewareHandler $middlewareHandler;
private ResponseFactory $responseFactory;

public function __construct(
GetPropertyDescriptionWithFallback $useCase,
MiddlewareHandler $middlewareHandler,
ResponseFactory $responseFactory
) {
$this->useCase = $useCase;
$this->middlewareHandler = $middlewareHandler;
$this->responseFactory = $responseFactory;
}

public static function factory(): self {
return new self(
WbRestApi::getGetPropertyDescriptionWithFallback(),
new MiddlewareHandler( [
WbRestApi::getUnexpectedErrorHandlerMiddleware(),
new UserAgentCheckMiddleware(),
new AuthenticationMiddleware(),
WbRestApi::getPreconditionMiddlewareFactory()->newPreconditionMiddleware(
fn( RequestInterface $request ): string => $request->getPathParam( self::PROPERTY_ID_PATH_PARAM )
),
] ),
new ResponseFactory()
);
}

public function needsWriteAccess(): bool {
return false;
}

/**
* @param mixed ...$args
*/
public function run( ...$args ): Response {
return $this->middlewareHandler->run( $this, [ $this, 'runUseCase' ], $args );
}

public function runUseCase( string $propertyId, string $languageCode ): Response {
try {
return $this->newSuccessHttpResponse(
$this->useCase->execute( new GetPropertyDescriptionWithFallbackRequest( $propertyId, $languageCode ) )
);
} catch ( UseCaseError $e ) {
return $this->responseFactory->newErrorResponseFromException( $e );
}
}

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

private function newSuccessHttpResponse( GetPropertyDescriptionWithFallbackResponse $useCaseResponse ): Response {
$httpResponse = $this->getResponseFactory()->create();
$httpResponse->setHeader( 'Content-Type', 'application/json' );
$httpResponse->setHeader( 'Last-Modified', wfTimestamp( TS_RFC2822, $useCaseResponse->getLastModified() ) );
$this->setEtagFromRevId( $httpResponse, $useCaseResponse->getRevisionId() );
$httpResponse->setBody( new StringStream( json_encode( $useCaseResponse->getDescription()->getText() ) ) );

return $httpResponse;
}

private function setEtagFromRevId( Response $response, int $revId ): void {
$response->setHeader( 'ETag', "\"$revId\"" );
}

/**
* Preconditions are checked via {@link PreconditionMiddleware}
*/
public function checkPreconditions(): ?ResponseInterface {
return null;
}

}
Loading

0 comments on commit 542283e

Please sign in to comment.