ApiBlockInfoTrait: Add formatted and relative times

Providing just standard timestamps means that formatting
has to happen in the client, however that means loading a
large deprecated library (moment.js). We already have
localised formatting functions in PHP so just provide
the output of those in the API.

Also fix test mocks to correctly provide a language object
rather than a string.

Bug: T224635
Change-Id: I73dcfcdbbc6e90bc692bf5a456075fe1eaed2df9
This commit is contained in:
Ed Sanders 2021-12-02 16:27:31 +00:00
parent 133d249b94
commit c0ecb08bdb
3 changed files with 32 additions and 4 deletions

View file

@ -36,7 +36,10 @@ trait ApiBlockInfoTrait {
* - blockedbyid - user ID of the blocker * - blockedbyid - user ID of the blocker
* - blockreason - reason provided for the block * - blockreason - reason provided for the block
* - blockedtimestamp - timestamp for when the block was placed/modified * - blockedtimestamp - timestamp for when the block was placed/modified
* - blockedtimestampformatted - blockedtimestamp, formatted for the current locale
* - blockexpiry - expiry time of the block * - blockexpiry - expiry time of the block
* - blockexpiryformatted - blockexpiry formatted for the current locale, omitted if infinite
* - blockexpiryrelative - relative time to blockexpiry (e.g. 'in 5 days'), omitted if infinite
* - blockpartial - block only applies to certain pages, namespaces and/or actions * - blockpartial - block only applies to certain pages, namespaces and/or actions
* - systemblocktype - system block type, if any * - systemblocktype - system block type, if any
*/ */
@ -57,11 +60,26 @@ trait ApiBlockInfoTrait {
$vals['blockreason'] = $block->getReasonComment() $vals['blockreason'] = $block->getReasonComment()
->message->inLanguage( $language )->plain(); ->message->inLanguage( $language )->plain();
$vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->getTimestamp() ); $vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->getTimestamp() );
$vals['blockexpiry'] = ApiResult::formatExpiry( $block->getExpiry(), 'infinite' ); $expiry = ApiResult::formatExpiry( $block->getExpiry(), 'infinite' );
$vals['blockexpiry'] = $expiry;
$vals['blockpartial'] = !$block->isSitewide(); $vals['blockpartial'] = !$block->isSitewide();
$vals['blocknocreate'] = $block->isCreateAccountBlocked(); $vals['blocknocreate'] = $block->isCreateAccountBlocked();
$vals['blockanononly'] = !$block->isHardblock(); $vals['blockanononly'] = !$block->isHardblock();
$user = $this->getUser();
// Formatted timestamps
$vals['blockedtimestampformatted'] = $language->formatExpiry(
$block->getTimestamp(), true, 'infinity', $user
);
if ( $expiry !== 'infinite' ) {
$vals['blockexpiryformatted'] = $language->formatExpiry(
$expiry, true, 'infinity', $user
);
$vals['blockexpiryrelative'] = $language->getHumanTimestamp(
new MWTimestamp( $expiry ), new MWTimestamp(), $user
);
}
if ( $block instanceof SystemBlock ) { if ( $block instanceof SystemBlock ) {
$vals['systemblocktype'] = $block->getSystemBlockType(); $vals['systemblocktype'] = $block->getSystemBlockType();
} }
@ -80,6 +98,12 @@ trait ApiBlockInfoTrait {
*/ */
abstract public function getLanguage(); abstract public function getLanguage();
/**
* @see IContextSource::getUser
* @return User
*/
abstract public function getUser();
/** @} */ /** @} */
// endregion -- end of methods required from ApiBase // endregion -- end of methods required from ApiBase

View file

@ -1347,7 +1347,8 @@ class ApiBaseTest extends ApiTestCase {
MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock( $block ); MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock( $block );
$mockTrait = $this->getMockForTrait( ApiBlockInfoTrait::class ); $mockTrait = $this->getMockForTrait( ApiBlockInfoTrait::class );
$mockTrait->method( 'getLanguage' )->willReturn( 'en' ); $language = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' );
$mockTrait->method( 'getLanguage' )->willReturn( $language );
$userInfoTrait = TestingAccessWrapper::newFromObject( $mockTrait ); $userInfoTrait = TestingAccessWrapper::newFromObject( $mockTrait );
$blockinfo = [ 'blockinfo' => $userInfoTrait->getBlockDetails( $block ) ]; $blockinfo = [ 'blockinfo' => $userInfoTrait->getBlockDetails( $block ) ];
@ -1406,7 +1407,8 @@ class ApiBaseTest extends ApiTestCase {
MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock( $block ); MediaWikiServices::getInstance()->getDatabaseBlockStore()->insertBlock( $block );
$mockTrait = $this->getMockForTrait( ApiBlockInfoTrait::class ); $mockTrait = $this->getMockForTrait( ApiBlockInfoTrait::class );
$mockTrait->method( 'getLanguage' )->willReturn( 'en' ); $language = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' );
$mockTrait->method( 'getLanguage' )->willReturn( $language );
$userInfoTrait = TestingAccessWrapper::newFromObject( $mockTrait ); $userInfoTrait = TestingAccessWrapper::newFromObject( $mockTrait );
$blockinfo = [ 'blockinfo' => $userInfoTrait->getBlockDetails( $block ) ]; $blockinfo = [ 'blockinfo' => $userInfoTrait->getBlockDetails( $block ) ];

View file

@ -2,6 +2,7 @@
use MediaWiki\Block\DatabaseBlock; use MediaWiki\Block\DatabaseBlock;
use MediaWiki\Block\SystemBlock; use MediaWiki\Block\SystemBlock;
use MediaWiki\MediaWikiServices;
use Wikimedia\TestingAccessWrapper; use Wikimedia\TestingAccessWrapper;
/** /**
@ -12,8 +13,9 @@ class ApiBlockInfoTraitTest extends MediaWikiIntegrationTestCase {
* @dataProvider provideGetBlockDetails * @dataProvider provideGetBlockDetails
*/ */
public function testGetBlockDetails( $block, $expectedInfo ) { public function testGetBlockDetails( $block, $expectedInfo ) {
$language = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' );
$mock = $this->getMockForTrait( ApiBlockInfoTrait::class ); $mock = $this->getMockForTrait( ApiBlockInfoTrait::class );
$mock->method( 'getLanguage' )->willReturn( 'en' ); $mock->method( 'getLanguage' )->willReturn( $language );
$info = TestingAccessWrapper::newFromObject( $mock )->getBlockDetails( $block ); $info = TestingAccessWrapper::newFromObject( $mock )->getBlockDetails( $block );
$subset = array_merge( [ $subset = array_merge( [
'blockid' => null, 'blockid' => null,