If a client submits data that is not NFC-normalized Unicode or that contains C0 controls other than HT, LF, and CR, it gets normalized before the API ever sees it. Which can lead to difficult-to-handle bugs when, for example, a title is subject to normalization so the client can't find the specific title it submitted anywhere in the response (T139130). This patch does two things: * Detects when normalization was applied to an input value (at the MediaWiki level, anyway; if PHP or earlier does it we're just out of luck) and add a warning to that effect. * For ApiPageSet's 'titles' parameter, split into the individual titles and add them to the 'normalized' list in the response. This requires encoding the pre-normalized strings to avoid ApiResult's own normalization. Bug: T29849 Bug: T144071 Change-Id: I215fd3edd7a5e1b45292e60768bf6dd5ad7f34de
99 lines
2.9 KiB
PHP
99 lines
2.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @group API
|
|
* @group medium
|
|
* @group Database
|
|
*/
|
|
class ApiPageSetTest extends ApiTestCase {
|
|
public static function provideRedirectMergePolicy() {
|
|
return [
|
|
'By default nothing is merged' => [
|
|
null,
|
|
[]
|
|
],
|
|
|
|
'A simple merge policy adds the redirect data in' => [
|
|
function( $current, $new ) {
|
|
if ( !isset( $current['index'] ) || $new['index'] < $current['index'] ) {
|
|
$current['index'] = $new['index'];
|
|
}
|
|
return $current;
|
|
},
|
|
[ 'index' => 1 ],
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideRedirectMergePolicy
|
|
*/
|
|
public function testRedirectMergePolicyWithArrayResult( $mergePolicy, $expect ) {
|
|
list( $target, $pageSet ) = $this->createPageSetWithRedirect();
|
|
$pageSet->setRedirectMergePolicy( $mergePolicy );
|
|
$result = [
|
|
$target->getArticleID() => []
|
|
];
|
|
$pageSet->populateGeneratorData( $result );
|
|
$this->assertEquals( $expect, $result[$target->getArticleID()] );
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideRedirectMergePolicy
|
|
*/
|
|
public function testRedirectMergePolicyWithApiResult( $mergePolicy, $expect ) {
|
|
list( $target, $pageSet ) = $this->createPageSetWithRedirect();
|
|
$pageSet->setRedirectMergePolicy( $mergePolicy );
|
|
$result = new ApiResult( false );
|
|
$result->addValue( null, 'pages', [
|
|
$target->getArticleID() => []
|
|
] );
|
|
$pageSet->populateGeneratorData( $result, [ 'pages' ] );
|
|
$this->assertEquals(
|
|
$expect,
|
|
$result->getResultData( [ 'pages', $target->getArticleID() ] )
|
|
);
|
|
}
|
|
|
|
protected function createPageSetWithRedirect() {
|
|
$target = Title::makeTitle( NS_MAIN, 'UTRedirectTarget' );
|
|
$sourceA = Title::makeTitle( NS_MAIN, 'UTRedirectSourceA' );
|
|
$sourceB = Title::makeTitle( NS_MAIN, 'UTRedirectSourceB' );
|
|
self::editPage( 'UTRedirectTarget', 'api page set test' );
|
|
self::editPage( 'UTRedirectSourceA', '#REDIRECT [[UTRedirectTarget]]' );
|
|
self::editPage( 'UTRedirectSourceB', '#REDIRECT [[UTRedirectTarget]]' );
|
|
|
|
$request = new FauxRequest( [ 'redirects' => 1 ] );
|
|
$context = new RequestContext();
|
|
$context->setRequest( $request );
|
|
$main = new ApiMain( $context );
|
|
$pageSet = new ApiPageSet( $main );
|
|
|
|
$pageSet->setGeneratorData( $sourceA, [ 'index' => 1 ] );
|
|
$pageSet->setGeneratorData( $sourceB, [ 'index' => 3 ] );
|
|
$pageSet->populateFromTitles( [ $sourceA, $sourceB ] );
|
|
|
|
return [ $target, $pageSet ];
|
|
}
|
|
|
|
public function testHandleNormalization() {
|
|
$context = new RequestContext();
|
|
$context->setRequest( new FauxRequest( [ 'titles' => "a|B|a\xcc\x8a" ] ) );
|
|
$main = new ApiMain( $context );
|
|
$pageSet = new ApiPageSet( $main );
|
|
$pageSet->execute();
|
|
|
|
$this->assertSame(
|
|
[ 0 => [ 'A' => -1, 'B' => -2, 'Å' => -3 ] ],
|
|
$pageSet->getAllTitlesByNamespace()
|
|
);
|
|
$this->assertSame(
|
|
[
|
|
[ 'fromencoded' => true, 'from' => 'a%CC%8A', 'to' => 'å' ],
|
|
[ 'fromencoded' => false, 'from' => 'a', 'to' => 'A' ],
|
|
[ 'fromencoded' => false, 'from' => 'å', 'to' => 'Å' ],
|
|
],
|
|
$pageSet->getNormalizedTitlesAsResult()
|
|
);
|
|
}
|
|
}
|