What was previously a REST API-only feature (the thumbnails hook allowing for thumbnails for non-file pages via the PageImages extension) is now also being adopted in the main search page. That hook will now be called with NS_FILE result thumbnails pre-filled, which was not the case previously. PageImages essentially duplicated NS_FILE thumbnail logic that was already present in Special:Search, so that can (and will in a follow-up patch) then be removed there. Special:Search will then simply take whatever is produced from the provider (which will include both NS_FILE thumbs - which it handled already - as well as whatever else it receives from the hook), as will the REST API (which already received both) Since thumbnails can now come in for multiple namespaces & having some of those results with & others without a thumbnail can be quite jarring, it was decided that we'd display placeholder images (for certain namespaces). This is now controlled by $wgThumbnailNamespaces. I also split up a few things in FullSearchResultWidget:: generateFileHtml for more clarity. Meanwhile also updated mediawiki.special.search.styles.less to use variables for known colors. Also implemented a 'transform' (required for testing this change properly) and 'getDisplayWidthHeight' (it became needed after implementing transform) callback function for mock Files, and updated some existing tests in response to these changes. And some more Rest test files have been updated to allow passing around a HookContainer instead of only an array of hooks (from which a new HookContainer would then be created) to allow the same container to be used across all relevant objects, who may have it injected as dependency. Bug: T306883 Change-Id: I2a679b51758020d3e822da01a1bde1ae632b0b0a
153 lines
5.1 KiB
PHP
153 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Tests\Rest\Handler;
|
|
|
|
use LocalFile;
|
|
use LocalRepo;
|
|
use MediaWiki\Page\PageReference;
|
|
use MediaWiki\User\UserIdentityValue;
|
|
use MockTitleTrait;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use RepoGroup;
|
|
use ThumbnailImage;
|
|
|
|
/**
|
|
* A trait providing utility functions for mocking media-related objects.
|
|
*
|
|
* @package MediaWiki\Tests\Rest\Handler
|
|
*/
|
|
trait MediaTestTrait {
|
|
|
|
use HandlerTestTrait;
|
|
use MockTitleTrait;
|
|
|
|
/**
|
|
* @param PageReference|string $title
|
|
*
|
|
* @return LocalFile|MockObject
|
|
*/
|
|
private function makeMissingMockFile( $title ) {
|
|
$title = $title instanceof PageReference
|
|
? $this->makeMockTitle( $title->getDBkey(), [ 'namespace' => $title->getNamespace() ] )
|
|
: $this->makeMockTitle( 'File:' . $title, [ 'namespace' => NS_FILE ] );
|
|
|
|
/** @var MockObject|LocalFile $file */
|
|
$file = $this->createNoOpMock(
|
|
LocalFile::class,
|
|
[ 'getTitle', 'exists', 'getDescriptionUrl', 'load' ]
|
|
);
|
|
$file->method( 'getTitle' )->willReturn( $title );
|
|
$file->method( 'exists' )->willReturn( false );
|
|
$file->method( 'getDescriptionUrl' )->willReturn(
|
|
'https://example.com/wiki/' . $title->getPrefixedDBkey()
|
|
);
|
|
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* @param PageReference|string $title
|
|
*
|
|
* @return LocalFile|MockObject
|
|
*/
|
|
private function makeMockFile( $title ) {
|
|
$title = $title instanceof PageReference
|
|
? $this->makeMockTitle( $title->getDBkey(), [ 'namespace' => $title->getNamespace() ] )
|
|
: $this->makeMockTitle( 'File:' . $title, [ 'namespace' => NS_FILE ] );
|
|
|
|
/** @var MockObject|LocalFile $file */
|
|
$file = $this->createNoOpMock(
|
|
LocalFile::class,
|
|
[ 'getName', 'getTitle', 'getDescriptionUrl', 'exists', 'userCan', 'getUploader', 'getTimestamp',
|
|
'getMediaType', 'getSize', 'getHeight', 'getWidth', 'getDisplayWidthHeight',
|
|
'getLength', 'getUrl', 'allowInlineDisplay', 'transform', 'getSha1', 'load', 'getMimeType' ]
|
|
);
|
|
$file->method( 'getName' )->willReturn( ucfirst( $title->getDBkey() ) );
|
|
$file->method( 'getTitle' )->willReturn( $title );
|
|
$file->method( 'exists' )->willReturn( true );
|
|
$file->method( 'userCan' )->willReturn( true );
|
|
$file->method( 'getUploader' )
|
|
->willReturn( UserIdentityValue::newRegistered( 7, 'Alice' ) );
|
|
$file->method( 'getTimestamp' )->willReturn( '20200102030405' );
|
|
$file->method( 'getMediaType' )->willReturn( 'test' );
|
|
$file->method( 'getSize' )->willReturn( 12345 );
|
|
$file->method( 'getHeight' )->willReturn( 400 );
|
|
$file->method( 'getWidth' )->willReturn( 600 );
|
|
$file->method( 'getLength' )->willReturn( 678 );
|
|
$file->method( 'getSha1' )->willReturn( 'DEADBEEF' );
|
|
$file->method( 'allowInlineDisplay' )->willReturn( true );
|
|
$file->method( 'getUrl' )->willReturn(
|
|
'https://media.example.com/static/' . $title->getDBkey()
|
|
);
|
|
$file->method( 'getDescriptionUrl' )->willReturn(
|
|
'https://example.com/wiki/' . $title->getPrefixedDBkey()
|
|
);
|
|
$file->method( 'getMimeType' )->willReturn( 'image/jpeg' );
|
|
|
|
$getDisplayWidthHeight = static function ( $maxWidth, $maxHeight, $page = 1 ) use ( $file ) {
|
|
$width = $file->getWidth( $page );
|
|
$height = $file->getHeight( $page );
|
|
$ratio = $width / $height;
|
|
if ( $width / $maxWidth > $height / $maxHeight ) {
|
|
return [ $maxWidth, round( $maxWidth / $ratio ) ];
|
|
}
|
|
return [ round( $maxHeight * $ratio ), $maxHeight ];
|
|
};
|
|
$file->method( 'getDisplayWidthHeight' )->willReturnCallback( $getDisplayWidthHeight );
|
|
|
|
$transform = static function ( $params ) use ( $file, $title ) {
|
|
return new ThumbnailImage(
|
|
$file,
|
|
'https://media.example.com/static/thumb/' . $title->getDBkey(),
|
|
false,
|
|
[
|
|
'width' => $params['width'] ?? 64,
|
|
'height' => $params['height'] ?? 64,
|
|
'page' => $params['page'] ?? false
|
|
]
|
|
);
|
|
};
|
|
$file->method( 'transform' )->willReturnCallback( $transform );
|
|
|
|
return $file;
|
|
}
|
|
|
|
/**
|
|
* @param array $existingFileDBKeys
|
|
* @return MockObject|RepoGroup
|
|
*/
|
|
private function makeMockRepoGroup( array $existingFileDBKeys ) {
|
|
$findFile = function ( $title ) use ( $existingFileDBKeys ) {
|
|
$title = $title instanceof PageReference
|
|
? $this->makeMockTitle( $title->getDBkey(), [ 'namespace' => $title->getNamespace() ] )
|
|
: $this->makeMockTitle( 'File:' . $title, [ 'namespace' => NS_FILE ] );
|
|
|
|
if ( !in_array( $title->getDBkey(), $existingFileDBKeys ) || $title->getNamespace() !== NS_FILE ) {
|
|
return $this->makeMissingMockFile( $title );
|
|
} else {
|
|
return $this->makeMockFile( $title );
|
|
}
|
|
};
|
|
|
|
$findFiles = static function ( array $inputItems ) use ( $findFile ) {
|
|
$files = [];
|
|
foreach ( $inputItems as $item ) {
|
|
$files[] = ( $findFile )( $item['title'] );
|
|
}
|
|
|
|
return $files;
|
|
};
|
|
|
|
$mockLocalRepo = $this->createMock( LocalRepo::class );
|
|
$mockLocalRepo->method( 'newFile' )->willReturnCallback( $findFile );
|
|
|
|
/** @var RepoGroup|MockObject $repoGroup */
|
|
$repoGroup = $this->createNoOpMock( RepoGroup::class, [ 'findFiles', 'findFile', 'getLocalRepo' ] );
|
|
$repoGroup->method( 'findFile' )->willReturnCallback( $findFile );
|
|
$repoGroup->method( 'findFiles' )->willReturnCallback( $findFiles );
|
|
$repoGroup->method( 'getLocalRepo' )->willReturn( $mockLocalRepo );
|
|
|
|
return $repoGroup;
|
|
}
|
|
|
|
}
|