7 class ApiResultTest
extends MediaWikiTestCase
{
12 public function testStaticDataMethods() {
15 ApiResult
::setValue( $arr, 'setValue', '1' );
17 ApiResult
::setValue( $arr, null, 'unnamed 1' );
18 ApiResult
::setValue( $arr, null, 'unnamed 2' );
20 ApiResult
::setValue( $arr, 'deleteValue', '2' );
21 ApiResult
::unsetValue( $arr, 'deleteValue' );
23 ApiResult
::setContentValue( $arr, 'setContentValue', '3' );
25 $this->assertSame( array(
29 ApiResult
::META_CONTENT
=> 'setContentValue',
30 'setContentValue' => '3',
34 ApiResult
::setValue( $arr, 'setValue', '99' );
35 $this->fail( 'Expected exception not thrown' );
36 } catch ( RuntimeException
$ex ) {
38 'Attempting to add element setValue=99, existing value is 1',
45 ApiResult
::setContentValue( $arr, 'setContentValue2', '99' );
46 $this->fail( 'Expected exception not thrown' );
47 } catch ( RuntimeException
$ex ) {
49 'Attempting to set content element as setContentValue2 when setContentValue ' .
50 'is already set as the content element',
56 ApiResult
::setValue( $arr, 'setValue', '99', ApiResult
::OVERRIDE
);
57 $this->assertSame( '99', $arr['setValue'] );
59 ApiResult
::setContentValue( $arr, 'setContentValue2', '99', ApiResult
::OVERRIDE
);
60 $this->assertSame( 'setContentValue2', $arr[ApiResult
::META_CONTENT
] );
62 $arr = array( 'foo' => 1, 'bar' => 1 );
63 ApiResult
::setValue( $arr, 'top', '2', ApiResult
::ADD_ON_TOP
);
64 ApiResult
::setValue( $arr, null, '2', ApiResult
::ADD_ON_TOP
);
65 ApiResult
::setValue( $arr, 'bottom', '2' );
66 ApiResult
::setValue( $arr, 'foo', '2', ApiResult
::OVERRIDE
);
67 ApiResult
::setValue( $arr, 'bar', '2', ApiResult
::OVERRIDE | ApiResult
::ADD_ON_TOP
);
68 $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom' ), array_keys( $arr ) );
71 ApiResult
::setValue( $arr, 'sub', array( 'foo' => 1 ) );
72 ApiResult
::setValue( $arr, 'sub', array( 'bar' => 1 ) );
73 $this->assertSame( array( 'sub' => array( 'foo' => 1, 'bar' => 1 ) ), $arr );
76 ApiResult
::setValue( $arr, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
77 $this->fail( 'Expected exception not thrown' );
78 } catch ( RuntimeException
$ex ) {
80 'Conflicting keys (foo) when attempting to merge element sub',
87 $title = Title
::newFromText( "MediaWiki:Foobar" );
91 ApiResult
::setValue( $arr, 'title', $title );
92 ApiResult
::setValue( $arr, 'obj', $obj );
93 $this->assertSame( array(
94 'title' => (string)$title,
95 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult
::META_TYPE
=> 'assoc' ),
100 ApiResult
::setValue( $arr, 'file', $fh );
101 $this->fail( 'Expected exception not thrown' );
102 } catch ( InvalidArgumentException
$ex ) {
104 'Cannot add resource(stream) to ApiResult',
110 ApiResult
::setValue( $arr, null, $fh );
111 $this->fail( 'Expected exception not thrown' );
112 } catch ( InvalidArgumentException
$ex ) {
114 'Cannot add resource(stream) to ApiResult',
121 ApiResult
::setValue( $arr, 'sub', $obj );
122 $this->fail( 'Expected exception not thrown' );
123 } catch ( InvalidArgumentException
$ex ) {
125 'Cannot add resource(stream) to ApiResult',
132 ApiResult
::setValue( $arr, null, $obj );
133 $this->fail( 'Expected exception not thrown' );
134 } catch ( InvalidArgumentException
$ex ) {
136 'Cannot add resource(stream) to ApiResult',
144 ApiResult
::setValue( $arr, 'inf', INF
);
145 $this->fail( 'Expected exception not thrown' );
146 } catch ( InvalidArgumentException
$ex ) {
148 'Cannot add non-finite floats to ApiResult',
154 ApiResult
::setValue( $arr, null, INF
);
155 $this->fail( 'Expected exception not thrown' );
156 } catch ( InvalidArgumentException
$ex ) {
158 'Cannot add non-finite floats to ApiResult',
164 ApiResult
::setValue( $arr, 'nan', NAN
);
165 $this->fail( 'Expected exception not thrown' );
166 } catch ( InvalidArgumentException
$ex ) {
168 'Cannot add non-finite floats to ApiResult',
174 ApiResult
::setValue( $arr, null, NAN
);
175 $this->fail( 'Expected exception not thrown' );
176 } catch ( InvalidArgumentException
$ex ) {
178 'Cannot add non-finite floats to ApiResult',
184 ApiResult
::setValue( $arr, null, NAN
, ApiResult
::NO_VALIDATE
);
187 ApiResult
::setValue( $arr, null, NAN
, ApiResult
::NO_SIZE_CHECK
);
188 $this->fail( 'Expected exception not thrown' );
189 } catch ( InvalidArgumentException
$ex ) {
191 'Cannot add non-finite floats to ApiResult',
198 $result2 = new ApiResult( 8388608 );
199 $result2->addValue( null, 'foo', 'bar' );
200 ApiResult
::setValue( $arr, 'baz', $result2 );
201 $this->assertSame( array(
203 ApiResult
::META_TYPE
=> 'assoc',
209 ApiResult
::setValue( $arr, 'foo', "foo\x80bar" );
210 ApiResult
::setValue( $arr, 'bar', "a\xcc\x81" );
211 ApiResult
::setValue( $arr, 'baz', 74 );
212 ApiResult
::setValue( $arr, null, "foo\x80bar" );
213 ApiResult
::setValue( $arr, null, "a\xcc\x81" );
214 $this->assertSame( array(
215 'foo' => "foo\xef\xbf\xbdbar",
218 0 => "foo\xef\xbf\xbdbar",
226 public function testInstanceDataMethods() {
227 $result = new ApiResult( 8388608 );
229 $result->addValue( null, 'setValue', '1' );
231 $result->addValue( null, null, 'unnamed 1' );
232 $result->addValue( null, null, 'unnamed 2' );
234 $result->addValue( null, 'deleteValue', '2' );
235 $result->removeValue( null, 'deleteValue' );
237 $result->addValue( array( 'a', 'b' ), 'deleteValue', '3' );
238 $result->removeValue( array( 'a', 'b', 'deleteValue' ), null, '3' );
240 $result->addContentValue( null, 'setContentValue', '3' );
242 $this->assertSame( array(
246 'a' => array( 'b' => array() ),
247 'setContentValue' => '3',
248 ApiResult
::META_TYPE
=> 'assoc',
249 ApiResult
::META_CONTENT
=> 'setContentValue',
250 ), $result->getResultData() );
251 $this->assertSame( 20, $result->getSize() );
254 $result->addValue( null, 'setValue', '99' );
255 $this->fail( 'Expected exception not thrown' );
256 } catch ( RuntimeException
$ex ) {
258 'Attempting to add element setValue=99, existing value is 1',
265 $result->addContentValue( null, 'setContentValue2', '99' );
266 $this->fail( 'Expected exception not thrown' );
267 } catch ( RuntimeException
$ex ) {
269 'Attempting to set content element as setContentValue2 when setContentValue ' .
270 'is already set as the content element',
276 $result->addValue( null, 'setValue', '99', ApiResult
::OVERRIDE
);
277 $this->assertSame( '99', $result->getResultData( array( 'setValue' ) ) );
279 $result->addContentValue( null, 'setContentValue2', '99', ApiResult
::OVERRIDE
);
280 $this->assertSame( 'setContentValue2',
281 $result->getResultData( array( ApiResult
::META_CONTENT
) ) );
284 $this->assertSame( array(
285 ApiResult
::META_TYPE
=> 'assoc',
286 ), $result->getResultData() );
287 $this->assertSame( 0, $result->getSize() );
289 $result->addValue( null, 'foo', 1 );
290 $result->addValue( null, 'bar', 1 );
291 $result->addValue( null, 'top', '2', ApiResult
::ADD_ON_TOP
);
292 $result->addValue( null, null, '2', ApiResult
::ADD_ON_TOP
);
293 $result->addValue( null, 'bottom', '2' );
294 $result->addValue( null, 'foo', '2', ApiResult
::OVERRIDE
);
295 $result->addValue( null, 'bar', '2', ApiResult
::OVERRIDE | ApiResult
::ADD_ON_TOP
);
296 $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom', ApiResult
::META_TYPE
),
297 array_keys( $result->getResultData() ) );
300 $result->addValue( null, 'foo', array( 'bar' => 1 ) );
301 $result->addValue( array( 'foo', 'top' ), 'x', 2, ApiResult
::ADD_ON_TOP
);
302 $result->addValue( array( 'foo', 'bottom' ), 'x', 2 );
303 $this->assertSame( array( 'top', 'bar', 'bottom' ),
304 array_keys( $result->getResultData( array( 'foo' ) ) ) );
307 $result->addValue( null, 'sub', array( 'foo' => 1 ) );
308 $result->addValue( null, 'sub', array( 'bar' => 1 ) );
309 $this->assertSame( array(
310 'sub' => array( 'foo' => 1, 'bar' => 1 ),
311 ApiResult
::META_TYPE
=> 'assoc',
312 ), $result->getResultData() );
315 $result->addValue( null, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
316 $this->fail( 'Expected exception not thrown' );
317 } catch ( RuntimeException
$ex ) {
319 'Conflicting keys (foo) when attempting to merge element sub',
326 $title = Title
::newFromText( "MediaWiki:Foobar" );
330 $result->addValue( null, 'title', $title );
331 $result->addValue( null, 'obj', $obj );
332 $this->assertSame( array(
333 'title' => (string)$title,
334 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult
::META_TYPE
=> 'assoc' ),
335 ApiResult
::META_TYPE
=> 'assoc',
336 ), $result->getResultData() );
340 $result->addValue( null, 'file', $fh );
341 $this->fail( 'Expected exception not thrown' );
342 } catch ( InvalidArgumentException
$ex ) {
344 'Cannot add resource(stream) to ApiResult',
350 $result->addValue( null, null, $fh );
351 $this->fail( 'Expected exception not thrown' );
352 } catch ( InvalidArgumentException
$ex ) {
354 'Cannot add resource(stream) to ApiResult',
361 $result->addValue( null, 'sub', $obj );
362 $this->fail( 'Expected exception not thrown' );
363 } catch ( InvalidArgumentException
$ex ) {
365 'Cannot add resource(stream) to ApiResult',
372 $result->addValue( null, null, $obj );
373 $this->fail( 'Expected exception not thrown' );
374 } catch ( InvalidArgumentException
$ex ) {
376 'Cannot add resource(stream) to ApiResult',
384 $result->addValue( null, 'inf', INF
);
385 $this->fail( 'Expected exception not thrown' );
386 } catch ( InvalidArgumentException
$ex ) {
388 'Cannot add non-finite floats to ApiResult',
394 $result->addValue( null, null, INF
);
395 $this->fail( 'Expected exception not thrown' );
396 } catch ( InvalidArgumentException
$ex ) {
398 'Cannot add non-finite floats to ApiResult',
404 $result->addValue( null, 'nan', NAN
);
405 $this->fail( 'Expected exception not thrown' );
406 } catch ( InvalidArgumentException
$ex ) {
408 'Cannot add non-finite floats to ApiResult',
414 $result->addValue( null, null, NAN
);
415 $this->fail( 'Expected exception not thrown' );
416 } catch ( InvalidArgumentException
$ex ) {
418 'Cannot add non-finite floats to ApiResult',
424 $result->addValue( null, null, NAN
, ApiResult
::NO_VALIDATE
);
427 $result->addValue( null, null, NAN
, ApiResult
::NO_SIZE_CHECK
);
428 $this->fail( 'Expected exception not thrown' );
429 } catch ( InvalidArgumentException
$ex ) {
431 'Cannot add non-finite floats to ApiResult',
438 $result->addParsedLimit( 'foo', 12 );
439 $this->assertSame( array(
440 'limits' => array( 'foo' => 12 ),
441 ApiResult
::META_TYPE
=> 'assoc',
442 ), $result->getResultData() );
443 $result->addParsedLimit( 'foo', 13 );
444 $this->assertSame( array(
445 'limits' => array( 'foo' => 13 ),
446 ApiResult
::META_TYPE
=> 'assoc',
447 ), $result->getResultData() );
448 $this->assertSame( null, $result->getResultData( array( 'foo', 'bar', 'baz' ) ) );
449 $this->assertSame( 13, $result->getResultData( array( 'limits', 'foo' ) ) );
451 $result->getResultData( array( 'limits', 'foo', 'bar' ) );
452 $this->fail( 'Expected exception not thrown' );
453 } catch ( InvalidArgumentException
$ex ) {
455 'Path limits.foo is not an array',
461 // Add two values and some metadata, but ensure metadata is not counted
462 $result = new ApiResult( 100 );
463 $obj = array( 'attr' => '12345' );
464 ApiResult
::setContentValue( $obj, 'content', '1234567890' );
465 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
466 $this->assertSame( 15, $result->getSize() );
468 $result = new ApiResult( 10 );
469 $formatter = new ApiErrorFormatter( $result, Language
::factory( 'en' ), 'none', false );
470 $result->setErrorFormatter( $formatter );
471 $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
472 $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult
::NO_SIZE_CHECK
) );
473 $this->assertSame( 0, $result->getSize() );
475 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
476 $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
477 $result->removeValue( null, 'foo' );
478 $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
480 $result = new ApiResult( 10 );
481 $obj = new ApiResultTestSerializableObject( 'ok' );
482 $obj->foobar
= 'foobaz';
483 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
484 $this->assertSame( 2, $result->getSize() );
486 $result = new ApiResult( 8388608 );
487 $result2 = new ApiResult( 8388608 );
488 $result2->addValue( null, 'foo', 'bar' );
489 $result->addValue( null, 'baz', $result2 );
490 $this->assertSame( array(
493 ApiResult
::META_TYPE
=> 'assoc',
495 ApiResult
::META_TYPE
=> 'assoc',
496 ), $result->getResultData() );
498 $result = new ApiResult( 8388608 );
499 $result->addValue( null, 'foo', "foo\x80bar" );
500 $result->addValue( null, 'bar', "a\xcc\x81" );
501 $result->addValue( null, 'baz', 74 );
502 $result->addValue( null, null, "foo\x80bar" );
503 $result->addValue( null, null, "a\xcc\x81" );
504 $this->assertSame( array(
505 'foo' => "foo\xef\xbf\xbdbar",
508 0 => "foo\xef\xbf\xbdbar",
510 ApiResult
::META_TYPE
=> 'assoc',
511 ), $result->getResultData() );
517 public function testMetadata() {
518 $arr = array( 'foo' => array( 'bar' => array() ) );
519 $result = new ApiResult( 8388608 );
520 $result->addValue( null, 'foo', array( 'bar' => array() ) );
525 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
526 ApiResult
::META_TYPE
=> 'default',
528 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
529 ApiResult
::META_TYPE
=> 'default',
531 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
532 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
533 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar' ),
534 ApiResult
::META_TYPE
=> 'array',
537 ApiResult
::setSubelementsList( $arr, 'foo' );
538 ApiResult
::setSubelementsList( $arr, array( 'bar', 'baz' ) );
539 ApiResult
::unsetSubelementsList( $arr, 'baz' );
540 ApiResult
::setIndexedTagNameRecursive( $arr, 'ritn' );
541 ApiResult
::setIndexedTagName( $arr, 'itn' );
542 ApiResult
::setPreserveKeysList( $arr, 'foo' );
543 ApiResult
::setPreserveKeysList( $arr, array( 'bar', 'baz' ) );
544 ApiResult
::unsetPreserveKeysList( $arr, 'baz' );
545 ApiResult
::setArrayTypeRecursive( $arr, 'default' );
546 ApiResult
::setArrayType( $arr, 'array' );
547 $this->assertSame( $expect, $arr );
549 $result->addSubelementsList( null, 'foo' );
550 $result->addSubelementsList( null, array( 'bar', 'baz' ) );
551 $result->removeSubelementsList( null, 'baz' );
552 $result->addIndexedTagNameRecursive( null, 'ritn' );
553 $result->addIndexedTagName( null, 'itn' );
554 $result->addPreserveKeysList( null, 'foo' );
555 $result->addPreserveKeysList( null, array( 'bar', 'baz' ) );
556 $result->removePreserveKeysList( null, 'baz' );
557 $result->addArrayTypeRecursive( null, 'default' );
558 $result->addArrayType( null, 'array' );
559 $this->assertEquals( $expect, $result->getResultData() );
561 $arr = array( 'foo' => array( 'bar' => array() ) );
565 ApiResult
::META_TYPE
=> 'kvp',
566 ApiResult
::META_KVP_KEY_NAME
=> 'key',
568 ApiResult
::META_TYPE
=> 'kvp',
569 ApiResult
::META_KVP_KEY_NAME
=> 'key',
571 ApiResult
::META_TYPE
=> 'BCkvp',
572 ApiResult
::META_KVP_KEY_NAME
=> 'bc',
574 ApiResult
::setArrayTypeRecursive( $arr, 'kvp', 'key' );
575 ApiResult
::setArrayType( $arr, 'BCkvp', 'bc' );
576 $this->assertSame( $expect, $arr );
582 public function testUtilityFunctions() {
585 'bar' => array( '_dummy' => 'foobaz' ),
586 'bar2' => (object)array( '_dummy' => 'foobaz' ),
588 '_dummy' => 'foobaz',
590 'foo2' => (object)array(
591 'bar' => array( '_dummy' => 'foobaz' ),
592 'bar2' => (object)array( '_dummy' => 'foobaz' ),
594 '_dummy' => 'foobaz',
596 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
597 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
598 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
599 ApiResult
::META_TYPE
=> 'array',
600 '_dummy' => 'foobaz',
601 '_dummy2' => 'foobaz!',
603 $this->assertEquals( array(
606 'bar2' => (object)array(),
609 'foo2' => (object)array(
611 'bar2' => (object)array(),
614 '_dummy2' => 'foobaz!',
615 ), ApiResult
::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
618 $data = ApiResult
::stripMetadataNonRecursive( $arr, $metadata );
619 $this->assertEquals( array(
621 'bar' => array( '_dummy' => 'foobaz' ),
622 'bar2' => (object)array( '_dummy' => 'foobaz' ),
624 '_dummy' => 'foobaz',
626 'foo2' => (object)array(
627 'bar' => array( '_dummy' => 'foobaz' ),
628 'bar2' => (object)array( '_dummy' => 'foobaz' ),
630 '_dummy' => 'foobaz',
632 '_dummy2' => 'foobaz!',
633 ), $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
634 $this->assertEquals( array(
635 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
636 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
637 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
638 ApiResult
::META_TYPE
=> 'array',
639 '_dummy' => 'foobaz',
640 ), $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
643 $data = ApiResult
::stripMetadataNonRecursive( (object)$arr, $metadata );
644 $this->assertEquals( (object)array(
646 'bar' => array( '_dummy' => 'foobaz' ),
647 'bar2' => (object)array( '_dummy' => 'foobaz' ),
649 '_dummy' => 'foobaz',
651 'foo2' => (object)array(
652 'bar' => array( '_dummy' => 'foobaz' ),
653 'bar2' => (object)array( '_dummy' => 'foobaz' ),
655 '_dummy' => 'foobaz',
657 '_dummy2' => 'foobaz!',
658 ), $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
659 $this->assertEquals( array(
660 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
661 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
662 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
663 ApiResult
::META_TYPE
=> 'array',
664 '_dummy' => 'foobaz',
665 ), $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
670 * @dataProvider provideTransformations
671 * @param string $label
672 * @param array $input
673 * @param array $transforms
674 * @param array|Exception $expect
676 public function testTransformations( $label, $input, $transforms, $expect ) {
677 $result = new ApiResult( false );
678 $result->addValue( null, 'test', $input );
680 if ( $expect instanceof Exception
) {
682 $output = $result->getResultData( 'test', $transforms );
683 $this->fail( 'Expected exception not thrown', $label );
684 } catch ( Exception
$ex ) {
685 $this->assertEquals( $ex, $expect, $label );
688 $output = $result->getResultData( 'test', $transforms );
689 $this->assertEquals( $expect, $output, $label );
693 public function provideTransformations() {
694 $kvp = function ( $keyKey, $key, $valKey, $value ) {
698 ApiResult
::META_PRESERVE_KEYS
=> array( $keyKey ),
699 ApiResult
::META_CONTENT
=> $valKey,
700 ApiResult
::META_TYPE
=> 'assoc',
704 'defaultArray' => array( 2 => 'a', 0 => 'b', 1 => 'c' ),
705 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
706 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c' ),
707 'array' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'array' ),
708 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'BCarray' ),
709 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'BCassoc' ),
710 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
711 'kvp' => array( 'x' => 'a', 'y' => 'b', 'z' => array( 'c' ), ApiResult
::META_TYPE
=> 'kvp' ),
712 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
713 ApiResult
::META_TYPE
=> 'BCkvp',
714 ApiResult
::META_KVP_KEY_NAME
=> 'key',
716 'kvpmerge' => array( 'x' => 'a', 'y' => array( 'b' ), 'z' => array( 'c' => 'd' ),
717 ApiResult
::META_TYPE
=> 'kvp',
718 ApiResult
::META_KVP_MERGE
=> true,
720 'emptyDefault' => array( '_dummy' => 1 ),
721 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
723 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
727 'bar' => array( '_dummy' => 'foobaz' ),
729 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
730 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
731 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
732 ApiResult
::META_TYPE
=> 'array',
735 '_dummy' => 'foobaz',
737 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
738 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
739 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
740 ApiResult
::META_TYPE
=> 'array',
741 '_dummy' => 'foobaz',
742 '_dummy2' => 'foobaz!',
753 ApiResult
::META_BC_BOOLS
=> array( 0, 'true', 'false' ),
755 array( 'BC' => array() ),
760 ApiResult
::META_BC_BOOLS
=> array( 0, 'true', 'false' ),
764 'BC: META_BC_SUBELEMENTS',
768 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
770 array( 'BC' => array() ),
774 ApiResult
::META_CONTENT
=> '*',
775 ApiResult
::META_TYPE
=> 'assoc',
778 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
785 ApiResult
::META_CONTENT
=> 'content',
787 array( 'BC' => array() ),
790 ApiResult
::META_CONTENT
=> '*',
796 'foo' => 'foo value',
797 'bar' => 'bar value',
798 '_baz' => 'baz value',
799 ApiResult
::META_TYPE
=> 'BCkvp',
800 ApiResult
::META_KVP_KEY_NAME
=> 'key',
801 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
803 array( 'BC' => array() ),
805 $kvp( 'key', 'foo', '*', 'foo value' ),
806 $kvp( 'key', 'bar', '*', 'bar value' ),
807 $kvp( 'key', '_baz', '*', 'baz value' ),
808 ApiResult
::META_TYPE
=> 'array',
809 ApiResult
::META_KVP_KEY_NAME
=> 'key',
810 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
816 ApiResult
::META_TYPE
=> 'BCarray',
818 array( 'BC' => array() ),
820 ApiResult
::META_TYPE
=> 'default',
826 ApiResult
::META_TYPE
=> 'BCassoc',
828 array( 'BC' => array() ),
830 ApiResult
::META_TYPE
=> 'default',
834 'BC: BCkvp exception',
836 ApiResult
::META_TYPE
=> 'BCkvp',
838 array( 'BC' => array() ),
839 new UnexpectedValueException(
840 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
844 'BC: nobool, no*, nosub',
848 'content' => 'content',
849 ApiResult
::META_CONTENT
=> 'content',
851 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
852 'BCarray' => array( ApiResult
::META_TYPE
=> 'BCarray' ),
853 'BCassoc' => array( ApiResult
::META_TYPE
=> 'BCassoc' ),
855 'foo' => 'foo value',
856 'bar' => 'bar value',
857 '_baz' => 'baz value',
858 ApiResult
::META_TYPE
=> 'BCkvp',
859 ApiResult
::META_KVP_KEY_NAME
=> 'key',
860 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
863 array( 'BC' => array( 'nobool', 'no*', 'nosub' ) ),
867 'content' => 'content',
869 'BCarray' => array( ApiResult
::META_TYPE
=> 'default' ),
870 'BCassoc' => array( ApiResult
::META_TYPE
=> 'default' ),
872 $kvp( 'key', 'foo', '*', 'foo value' ),
873 $kvp( 'key', 'bar', '*', 'bar value' ),
874 $kvp( 'key', '_baz', '*', 'baz value' ),
875 ApiResult
::META_TYPE
=> 'array',
876 ApiResult
::META_KVP_KEY_NAME
=> 'key',
877 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
879 ApiResult
::META_CONTENT
=> 'content',
880 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
885 'Types: Normal transform',
887 array( 'Types' => array() ),
889 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
890 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
891 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
892 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
893 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
894 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
895 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
896 'kvp' => array( 'x' => 'a', 'y' => 'b',
897 'z' => array( 'c', ApiResult
::META_TYPE
=> 'array' ),
898 ApiResult
::META_TYPE
=> 'assoc'
900 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
901 ApiResult
::META_TYPE
=> 'assoc',
902 ApiResult
::META_KVP_KEY_NAME
=> 'key',
906 'y' => array( 'b', ApiResult
::META_TYPE
=> 'array' ),
907 'z' => array( 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ),
908 ApiResult
::META_TYPE
=> 'assoc',
909 ApiResult
::META_KVP_MERGE
=> true,
911 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
912 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
914 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
915 ApiResult
::META_TYPE
=> 'assoc',
919 'Types: AssocAsObject',
921 array( 'Types' => array( 'AssocAsObject' => true ) ),
923 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
924 'defaultAssoc' => (object)array( 'x' => 'a',
925 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
927 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
928 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
930 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
931 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
932 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
933 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
934 'kvp' => (object)array( 'x' => 'a', 'y' => 'b',
935 'z' => array( 'c', ApiResult
::META_TYPE
=> 'array' ),
936 ApiResult
::META_TYPE
=> 'assoc'
938 'BCkvp' => (object)array( 'x' => 'a', 'y' => 'b',
939 ApiResult
::META_TYPE
=> 'assoc',
940 ApiResult
::META_KVP_KEY_NAME
=> 'key',
942 'kvpmerge' => (object)array(
944 'y' => array( 'b', ApiResult
::META_TYPE
=> 'array' ),
945 'z' => (object)array( 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ),
946 ApiResult
::META_TYPE
=> 'assoc',
947 ApiResult
::META_KVP_MERGE
=> true,
949 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
950 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
952 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
953 ApiResult
::META_TYPE
=> 'assoc',
959 array( 'Types' => array( 'ArmorKVP' => 'name' ) ),
961 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
962 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
963 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
964 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
965 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
966 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
967 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
969 $kvp( 'name', 'x', 'value', 'a' ),
970 $kvp( 'name', 'y', 'value', 'b' ),
971 $kvp( 'name', 'z', 'value', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
972 ApiResult
::META_TYPE
=> 'array'
975 $kvp( 'key', 'x', 'value', 'a' ),
976 $kvp( 'key', 'y', 'value', 'b' ),
977 ApiResult
::META_TYPE
=> 'array',
978 ApiResult
::META_KVP_KEY_NAME
=> 'key',
981 $kvp( 'name', 'x', 'value', 'a' ),
982 $kvp( 'name', 'y', 'value', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
986 ApiResult
::META_TYPE
=> 'assoc',
987 ApiResult
::META_PRESERVE_KEYS
=> array( 'name' )
989 ApiResult
::META_TYPE
=> 'array',
990 ApiResult
::META_KVP_MERGE
=> true,
992 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
993 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
995 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
996 ApiResult
::META_TYPE
=> 'assoc',
1000 'Types: ArmorKVP + BC',
1002 array( 'BC' => array(), 'Types' => array( 'ArmorKVP' => 'name' ) ),
1004 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
1005 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1006 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1007 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
1008 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1009 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'array' ),
1010 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1012 $kvp( 'name', 'x', '*', 'a' ),
1013 $kvp( 'name', 'y', '*', 'b' ),
1014 $kvp( 'name', 'z', '*', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
1015 ApiResult
::META_TYPE
=> 'array'
1018 $kvp( 'key', 'x', '*', 'a' ),
1019 $kvp( 'key', 'y', '*', 'b' ),
1020 ApiResult
::META_TYPE
=> 'array',
1021 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1023 'kvpmerge' => array(
1024 $kvp( 'name', 'x', '*', 'a' ),
1025 $kvp( 'name', 'y', '*', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
1029 ApiResult
::META_TYPE
=> 'assoc',
1030 ApiResult
::META_PRESERVE_KEYS
=> array( 'name' ) ),
1031 ApiResult
::META_TYPE
=> 'array',
1032 ApiResult
::META_KVP_MERGE
=> true,
1034 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
1035 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
1037 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
1038 ApiResult
::META_TYPE
=> 'assoc',
1042 'Types: ArmorKVP + AssocAsObject',
1044 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ) ),
1046 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
1047 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b',
1048 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1050 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
1051 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1053 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
1054 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
1055 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1056 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1058 (object)$kvp( 'name', 'x', 'value', 'a' ),
1059 (object)$kvp( 'name', 'y', 'value', 'b' ),
1060 (object)$kvp( 'name', 'z', 'value', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
1061 ApiResult
::META_TYPE
=> 'array'
1064 (object)$kvp( 'key', 'x', 'value', 'a' ),
1065 (object)$kvp( 'key', 'y', 'value', 'b' ),
1066 ApiResult
::META_TYPE
=> 'array',
1067 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1069 'kvpmerge' => array(
1070 (object)$kvp( 'name', 'x', 'value', 'a' ),
1071 (object)$kvp( 'name', 'y', 'value', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
1075 ApiResult
::META_TYPE
=> 'assoc',
1076 ApiResult
::META_PRESERVE_KEYS
=> array( 'name' )
1078 ApiResult
::META_TYPE
=> 'array',
1079 ApiResult
::META_KVP_MERGE
=> true,
1081 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
1082 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
1084 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
1085 ApiResult
::META_TYPE
=> 'assoc',
1089 'Types: BCkvp exception',
1091 ApiResult
::META_TYPE
=> 'BCkvp',
1093 array( 'Types' => array() ),
1094 new UnexpectedValueException(
1095 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
1100 'Strip: With ArmorKVP + AssocAsObject transforms',
1102 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ), 'Strip' => 'all' ),
1104 'defaultArray' => array( 'b', 'c', 'a' ),
1105 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
1106 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c' ),
1107 'array' => array( 'a', 'c', 'b' ),
1108 'BCarray' => array( 'a', 'c', 'b' ),
1109 'BCassoc' => (object)array( 'a', 'b', 'c' ),
1110 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c' ),
1112 (object)array( 'name' => 'x', 'value' => 'a' ),
1113 (object)array( 'name' => 'y', 'value' => 'b' ),
1114 (object)array( 'name' => 'z', 'value' => array( 'c' ) ),
1117 (object)array( 'key' => 'x', 'value' => 'a' ),
1118 (object)array( 'key' => 'y', 'value' => 'b' ),
1120 'kvpmerge' => array(
1121 (object)array( 'name' => 'x', 'value' => 'a' ),
1122 (object)array( 'name' => 'y', 'value' => array( 'b' ) ),
1123 (object)array( 'name' => 'z', 'c' => 'd' ),
1125 'emptyDefault' => array(),
1126 'emptyAssoc' => (object)array(),
1134 array( 'Strip' => 'all' ),
1141 '_dummy2' => 'foobaz!',
1147 array( 'Strip' => 'base' ),
1150 'bar' => array( '_dummy' => 'foobaz' ),
1152 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1153 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1154 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
1155 ApiResult
::META_TYPE
=> 'array',
1158 '_dummy' => 'foobaz',
1160 '_dummy2' => 'foobaz!',
1166 array( 'Strip' => 'bc' ),
1171 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1172 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1176 '_dummy2' => 'foobaz!',
1177 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1178 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1190 ApiResult
::META_CONTENT
=> 'foo',
1191 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy2', '_dummy3' ),
1194 'Custom' => array( $this, 'customTransform' ),
1202 'baz' => array( 'a', 'b' ),
1203 '_dummy2' => '_DUMMY2',
1204 '_dummy3' => '_DUMMY3',
1205 ApiResult
::META_CONTENT
=> 'bar',
1213 * Custom transformer for testTransformations
1214 * @param array &$data
1215 * @param array &$metadata
1217 public function customTransform( &$data, &$metadata ) {
1218 // Prevent recursion
1219 if ( isset( $metadata['_added'] ) ) {
1220 $metadata[ApiResult
::META_TYPE
] = 'array';
1224 foreach ( $data as $k => $v ) {
1225 $data[$k] = strtoupper( $k );
1227 $data['baz'] = array( '_added' => 1, 'z' => 'b', 'y' => 'a' );
1228 $metadata[ApiResult
::META_PRESERVE_KEYS
][0] = '_dummy';
1229 $data[ApiResult
::META_CONTENT
] = 'bar';
1235 public function testAddMetadataToResultVars() {
1240 'sequential_numeric_keys' => array( 'a', 'b', 'c' ),
1241 'non_sequential_numeric_keys' => array( 'a', 'b', 4 => 'c' ),
1242 'string_keys' => array(
1246 'object_sequential_keys' => (object)array( 'a', 'b', 'c' ),
1247 '_type' => "should be overwritten in result",
1249 $this->assertSame( array(
1250 ApiResult
::META_TYPE
=> 'kvp',
1251 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1252 ApiResult
::META_PRESERVE_KEYS
=> array(
1254 'sequential_numeric_keys', 'non_sequential_numeric_keys',
1255 'string_keys', 'object_sequential_keys'
1257 ApiResult
::META_BC_BOOLS
=> array( 'b' ),
1258 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1262 'sequential_numeric_keys' => array(
1263 ApiResult
::META_TYPE
=> 'array',
1264 ApiResult
::META_BC_BOOLS
=> array(),
1265 ApiResult
::META_INDEXED_TAG_NAME
=> 'value',
1270 'non_sequential_numeric_keys' => array(
1271 ApiResult
::META_TYPE
=> 'kvp',
1272 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1273 ApiResult
::META_PRESERVE_KEYS
=> array( 0, 1, 4 ),
1274 ApiResult
::META_BC_BOOLS
=> array(),
1275 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1280 'string_keys' => array(
1281 ApiResult
::META_TYPE
=> 'kvp',
1282 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1283 ApiResult
::META_PRESERVE_KEYS
=> array( 'one', 'two' ),
1284 ApiResult
::META_BC_BOOLS
=> array(),
1285 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1289 'object_sequential_keys' => array(
1290 ApiResult
::META_TYPE
=> 'kvp',
1291 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1292 ApiResult
::META_PRESERVE_KEYS
=> array( 0, 1, 2 ),
1293 ApiResult
::META_BC_BOOLS
=> array(),
1294 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1299 ), ApiResult
::addMetadataToResultVars( $arr ) );
1305 public function testDeprecatedFunctions() {
1306 // Ignore ApiResult deprecation warnings during this test
1307 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1308 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1311 if ( preg_match( '/Use of ApiMain to ApiResult::__construct ' .
1312 'was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1317 $reset = new ScopedCallback( 'restore_error_handler' );
1319 $context = new DerivativeContext( RequestContext
::getMain() );
1320 $context->setConfig( new HashConfig( array(
1321 'APIModules' => array(),
1322 'APIFormatModules' => array(),
1323 'APIMaxResultSize' => 42,
1325 $main = new ApiMain( $context );
1326 $result = TestingAccessWrapper
::newFromObject( new ApiResult( $main ) );
1327 $this->assertSame( 42, $result->maxSize
);
1328 $this->assertSame( $main->getErrorFormatter(), $result->errorFormatter
);
1329 $this->assertSame( $main, $result->mainForContinuation
);
1331 $result = new ApiResult( 8388608 );
1333 $result->addContentValue( null, 'test', 'content' );
1334 $result->addContentValue( array( 'foo', 'bar' ), 'test', 'content' );
1335 $result->addIndexedTagName( null, 'itn' );
1336 $result->addSubelementsList( null, array( 'sub' ) );
1337 $this->assertSame( array(
1344 ), $result->getData() );
1347 ApiResult
::setContent( $arr, 'value' );
1348 ApiResult
::setContent( $arr, 'value2', 'foobar' );
1349 $this->assertSame( array(
1350 ApiResult
::META_CONTENT
=> 'content',
1351 'content' => 'value',
1353 ApiResult
::META_CONTENT
=> 'content',
1354 'content' => 'value2',
1358 $result = new ApiResult( 3 );
1359 $formatter = new ApiErrorFormatter_BackCompat( $result );
1360 $result->setErrorFormatter( $formatter );
1361 $result->disableSizeCheck();
1362 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
1363 $result->enableSizeCheck();
1364 $this->assertSame( 0, $result->getSize() );
1365 $this->assertFalse( $result->addValue( null, 'foo', '1234567890' ) );
1367 $arr = array( 'foo' => array( 'bar' => 1 ) );
1368 $result->setIndexedTagName_recursive( $arr, 'itn' );
1369 $this->assertSame( array(
1372 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn'
1376 $status = Status
::newGood();
1377 $status->fatal( 'parentheses', '1' );
1378 $status->fatal( 'parentheses', '2' );
1379 $status->warning( 'parentheses', '3' );
1380 $status->warning( 'parentheses', '4' );
1381 $this->assertSame( array(
1384 'message' => 'parentheses',
1387 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1392 'message' => 'parentheses',
1395 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1398 ApiResult
::META_INDEXED_TAG_NAME
=> 'error',
1399 ), $result->convertStatusToArray( $status, 'error' ) );
1400 $this->assertSame( array(
1402 'type' => 'warning',
1403 'message' => 'parentheses',
1406 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1410 'type' => 'warning',
1411 'message' => 'parentheses',
1414 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1417 ApiResult
::META_INDEXED_TAG_NAME
=> 'warning',
1418 ), $result->convertStatusToArray( $status, 'warning' ) );
1424 public function testDeprecatedContinuation() {
1425 // Ignore ApiResult deprecation warnings during this test
1426 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1427 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1433 $reset = new ScopedCallback( 'restore_error_handler' );
1434 $allModules = array(
1435 new MockApiQueryBase( 'mock1' ),
1436 new MockApiQueryBase( 'mock2' ),
1437 new MockApiQueryBase( 'mocklist' ),
1439 $generator = new MockApiQueryBase( 'generator' );
1441 $main = new ApiMain( RequestContext
::getMain() );
1442 $result = new ApiResult( 8388608 );
1443 $result->setMainForContinuation( $main );
1444 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1445 $this->assertSame( array( false, $allModules ), $ret );
1446 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1447 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1448 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1449 $result->endContinuation( 'raw' );
1450 $result->endContinuation( 'standard' );
1451 $this->assertSame( array(
1453 'm1continue' => '1|2',
1454 'continue' => '||mock2',
1455 ), $result->getResultData( 'continue' ) );
1456 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1457 $this->assertSame( array(
1458 'mock1' => array( 'm1continue' => '1|2' ),
1459 'mocklist' => array( 'mlcontinue' => 2 ),
1460 'generator' => array( 'gcontinue' => 3 ),
1461 ), $result->getResultData( 'query-continue' ) );
1462 $main->setContinuationManager( null );
1464 $result = new ApiResult( 8388608 );
1465 $result->setMainForContinuation( $main );
1466 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1467 $this->assertSame( array( false, $allModules ), $ret );
1468 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1469 $result->setGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
1470 $result->endContinuation( 'raw' );
1471 $result->endContinuation( 'standard' );
1472 $this->assertSame( array(
1473 'm1continue' => '1|2',
1474 'continue' => '||mock2|mocklist',
1475 ), $result->getResultData( 'continue' ) );
1476 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1477 $this->assertSame( array(
1478 'mock1' => array( 'm1continue' => '1|2' ),
1479 'generator' => array( 'gcontinue' => '3|4' ),
1480 ), $result->getResultData( 'query-continue' ) );
1481 $main->setContinuationManager( null );
1483 $result = new ApiResult( 8388608 );
1484 $result->setMainForContinuation( $main );
1485 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1486 $this->assertSame( array( false, $allModules ), $ret );
1487 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1488 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1489 $result->endContinuation( 'raw' );
1490 $result->endContinuation( 'standard' );
1491 $this->assertSame( array(
1494 'continue' => 'gcontinue||',
1495 ), $result->getResultData( 'continue' ) );
1496 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1497 $this->assertSame( array(
1498 'mocklist' => array( 'mlcontinue' => 2 ),
1499 'generator' => array( 'gcontinue' => 3 ),
1500 ), $result->getResultData( 'query-continue' ) );
1501 $main->setContinuationManager( null );
1503 $result = new ApiResult( 8388608 );
1504 $result->setMainForContinuation( $main );
1505 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1506 $this->assertSame( array( false, $allModules ), $ret );
1507 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1508 $result->endContinuation( 'raw' );
1509 $result->endContinuation( 'standard' );
1510 $this->assertSame( array(
1512 'continue' => 'gcontinue||mocklist',
1513 ), $result->getResultData( 'continue' ) );
1514 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1515 $this->assertSame( array(
1516 'generator' => array( 'gcontinue' => 3 ),
1517 ), $result->getResultData( 'query-continue' ) );
1518 $main->setContinuationManager( null );
1520 $result = new ApiResult( 8388608 );
1521 $result->setMainForContinuation( $main );
1522 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1523 $this->assertSame( array( false, $allModules ), $ret );
1524 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1525 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1526 $result->endContinuation( 'raw' );
1527 $result->endContinuation( 'standard' );
1528 $this->assertSame( array(
1530 'm1continue' => '1|2',
1531 'continue' => '||mock2',
1532 ), $result->getResultData( 'continue' ) );
1533 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1534 $this->assertSame( array(
1535 'mock1' => array( 'm1continue' => '1|2' ),
1536 'mocklist' => array( 'mlcontinue' => 2 ),
1537 ), $result->getResultData( 'query-continue' ) );
1538 $main->setContinuationManager( null );
1540 $result = new ApiResult( 8388608 );
1541 $result->setMainForContinuation( $main );
1542 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1543 $this->assertSame( array( false, $allModules ), $ret );
1544 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1545 $result->endContinuation( 'raw' );
1546 $result->endContinuation( 'standard' );
1547 $this->assertSame( array(
1548 'm1continue' => '1|2',
1549 'continue' => '||mock2|mocklist',
1550 ), $result->getResultData( 'continue' ) );
1551 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1552 $this->assertSame( array(
1553 'mock1' => array( 'm1continue' => '1|2' ),
1554 ), $result->getResultData( 'query-continue' ) );
1555 $main->setContinuationManager( null );
1557 $result = new ApiResult( 8388608 );
1558 $result->setMainForContinuation( $main );
1559 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1560 $this->assertSame( array( false, $allModules ), $ret );
1561 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1562 $result->endContinuation( 'raw' );
1563 $result->endContinuation( 'standard' );
1564 $this->assertSame( array(
1566 'continue' => '-||mock1|mock2',
1567 ), $result->getResultData( 'continue' ) );
1568 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1569 $this->assertSame( array(
1570 'mocklist' => array( 'mlcontinue' => 2 ),
1571 ), $result->getResultData( 'query-continue' ) );
1572 $main->setContinuationManager( null );
1574 $result = new ApiResult( 8388608 );
1575 $result->setMainForContinuation( $main );
1576 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1577 $this->assertSame( array( false, $allModules ), $ret );
1578 $result->endContinuation( 'raw' );
1579 $result->endContinuation( 'standard' );
1580 $this->assertSame( null, $result->getResultData( 'continue' ) );
1581 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1582 $this->assertSame( null, $result->getResultData( 'query-continue' ) );
1583 $main->setContinuationManager( null );
1585 $result = new ApiResult( 8388608 );
1586 $result->setMainForContinuation( $main );
1587 $ret = $result->beginContinuation( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
1589 array( false, array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ) ),
1592 $main->setContinuationManager( null );
1594 $result = new ApiResult( 8388608 );
1595 $result->setMainForContinuation( $main );
1596 $ret = $result->beginContinuation( '-||', $allModules, array( 'mock1', 'mock2' ) );
1598 array( true, array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ) ),
1601 $main->setContinuationManager( null );
1603 $result = new ApiResult( 8388608 );
1604 $result->setMainForContinuation( $main );
1606 $result->beginContinuation( 'foo', $allModules, array( 'mock1', 'mock2' ) );
1607 $this->fail( 'Expected exception not thrown' );
1608 } catch ( UsageException
$ex ) {
1610 'Invalid continue param. You should pass the original value returned by the previous query',
1612 'Expected exception'
1615 $main->setContinuationManager( null );
1617 $result = new ApiResult( 8388608 );
1618 $result->setMainForContinuation( $main );
1619 $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ),
1620 array( 'mock1', 'mock2' ) );
1622 $result->setContinueParam( $allModules[1], 'm2continue', 1 );
1623 $this->fail( 'Expected exception not thrown' );
1624 } catch ( UnexpectedValueException
$ex ) {
1626 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
1628 'Expected exception'
1632 $result->setContinueParam( $allModules[2], 'mlcontinue', 1 );
1633 $this->fail( 'Expected exception not thrown' );
1634 } catch ( UnexpectedValueException
$ex ) {
1636 'Module \'mocklist\' called ApiContinuationManager::addContinueParam ' .
1637 'but was not passed to ApiContinuationManager::__construct',
1639 'Expected exception'
1642 $main->setContinuationManager( null );
1646 public function testObjectSerialization() {
1648 ApiResult
::setValue( $arr, 'foo', (object)array( 'a' => 1, 'b' => 2 ) );
1649 $this->assertSame( array(
1652 ApiResult
::META_TYPE
=> 'assoc',
1656 ApiResult
::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
1657 $this->assertSame( 'Ok', $arr['foo'] );
1660 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
1661 $this->assertSame( 'Ok', $arr['foo'] );
1665 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1666 new ApiResultTestStringifiableObject()
1668 $this->fail( 'Expected exception not thrown' );
1669 } catch ( UnexpectedValueException
$ex ) {
1671 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1672 'returned an object of class ApiResultTestStringifiableObject',
1674 'Expected exception'
1680 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN
) );
1681 $this->fail( 'Expected exception not thrown' );
1682 } catch ( UnexpectedValueException
$ex ) {
1684 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1685 'returned an invalid value: Cannot add non-finite floats to ApiResult',
1687 'Expected exception'
1692 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1694 'one' => new ApiResultTestStringifiableObject( '1' ),
1695 'two' => new ApiResultTestSerializableObject( 2 ),
1698 $this->assertSame( array(
1706 class ApiResultTestStringifiableObject
{
1709 public function __construct( $ret = 'Ok' ) {
1713 public function __toString() {
1718 class ApiResultTestSerializableObject
{
1721 public function __construct( $ret ) {
1725 public function __toString() {
1729 public function serializeForApiResult() {