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 $result = new ApiResult( 10 );
462 $formatter = new ApiErrorFormatter( $result, Language
::factory( 'en' ), 'none', false );
463 $result->setErrorFormatter( $formatter );
464 $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
465 $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult
::NO_SIZE_CHECK
) );
466 $this->assertSame( 0, $result->getSize() );
468 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
469 $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
470 $result->removeValue( null, 'foo' );
471 $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
473 $result = new ApiResult( 10 );
474 $obj = new ApiResultTestSerializableObject( 'ok' );
475 $obj->foobar
= 'foobaz';
476 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
477 $this->assertSame( 2, $result->getSize() );
479 $result = new ApiResult( 8388608 );
480 $result2 = new ApiResult( 8388608 );
481 $result2->addValue( null, 'foo', 'bar' );
482 $result->addValue( null, 'baz', $result2 );
483 $this->assertSame( array(
486 ApiResult
::META_TYPE
=> 'assoc',
488 ApiResult
::META_TYPE
=> 'assoc',
489 ), $result->getResultData() );
491 $result = new ApiResult( 8388608 );
492 $result->addValue( null, 'foo', "foo\x80bar" );
493 $result->addValue( null, 'bar', "a\xcc\x81" );
494 $result->addValue( null, 'baz', 74 );
495 $result->addValue( null, null, "foo\x80bar" );
496 $result->addValue( null, null, "a\xcc\x81" );
497 $this->assertSame( array(
498 'foo' => "foo\xef\xbf\xbdbar",
501 0 => "foo\xef\xbf\xbdbar",
503 ApiResult
::META_TYPE
=> 'assoc',
504 ), $result->getResultData() );
510 public function testMetadata() {
511 $arr = array( 'foo' => array( 'bar' => array() ) );
512 $result = new ApiResult( 8388608 );
513 $result->addValue( null, 'foo', array( 'bar' => array() ) );
518 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
519 ApiResult
::META_TYPE
=> 'default',
521 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
522 ApiResult
::META_TYPE
=> 'default',
524 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
525 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
526 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar' ),
527 ApiResult
::META_TYPE
=> 'array',
530 ApiResult
::setSubelementsList( $arr, 'foo' );
531 ApiResult
::setSubelementsList( $arr, array( 'bar', 'baz' ) );
532 ApiResult
::unsetSubelementsList( $arr, 'baz' );
533 ApiResult
::setIndexedTagNameRecursive( $arr, 'ritn' );
534 ApiResult
::setIndexedTagName( $arr, 'itn' );
535 ApiResult
::setPreserveKeysList( $arr, 'foo' );
536 ApiResult
::setPreserveKeysList( $arr, array( 'bar', 'baz' ) );
537 ApiResult
::unsetPreserveKeysList( $arr, 'baz' );
538 ApiResult
::setArrayTypeRecursive( $arr, 'default' );
539 ApiResult
::setArrayType( $arr, 'array' );
540 $this->assertSame( $expect, $arr );
542 $result->addSubelementsList( null, 'foo' );
543 $result->addSubelementsList( null, array( 'bar', 'baz' ) );
544 $result->removeSubelementsList( null, 'baz' );
545 $result->addIndexedTagNameRecursive( null, 'ritn' );
546 $result->addIndexedTagName( null, 'itn' );
547 $result->addPreserveKeysList( null, 'foo' );
548 $result->addPreserveKeysList( null, array( 'bar', 'baz' ) );
549 $result->removePreserveKeysList( null, 'baz' );
550 $result->addArrayTypeRecursive( null, 'default' );
551 $result->addArrayType( null, 'array' );
552 $this->assertEquals( $expect, $result->getResultData() );
554 $arr = array( 'foo' => array( 'bar' => array() ) );
558 ApiResult
::META_TYPE
=> 'kvp',
559 ApiResult
::META_KVP_KEY_NAME
=> 'key',
561 ApiResult
::META_TYPE
=> 'kvp',
562 ApiResult
::META_KVP_KEY_NAME
=> 'key',
564 ApiResult
::META_TYPE
=> 'BCkvp',
565 ApiResult
::META_KVP_KEY_NAME
=> 'bc',
567 ApiResult
::setArrayTypeRecursive( $arr, 'kvp', 'key' );
568 ApiResult
::setArrayType( $arr, 'BCkvp', 'bc' );
569 $this->assertSame( $expect, $arr );
575 public function testUtilityFunctions() {
578 'bar' => array( '_dummy' => 'foobaz' ),
579 'bar2' => (object)array( '_dummy' => 'foobaz' ),
581 '_dummy' => 'foobaz',
583 'foo2' => (object)array(
584 'bar' => array( '_dummy' => 'foobaz' ),
585 'bar2' => (object)array( '_dummy' => 'foobaz' ),
587 '_dummy' => 'foobaz',
589 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
590 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
591 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
592 ApiResult
::META_TYPE
=> 'array',
593 '_dummy' => 'foobaz',
594 '_dummy2' => 'foobaz!',
596 $this->assertEquals( array(
599 'bar2' => (object)array(),
602 'foo2' => (object)array(
604 'bar2' => (object)array(),
607 '_dummy2' => 'foobaz!',
608 ), ApiResult
::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
611 $data = ApiResult
::stripMetadataNonRecursive( $arr, $metadata );
612 $this->assertEquals( array(
614 'bar' => array( '_dummy' => 'foobaz' ),
615 'bar2' => (object)array( '_dummy' => 'foobaz' ),
617 '_dummy' => 'foobaz',
619 'foo2' => (object)array(
620 'bar' => array( '_dummy' => 'foobaz' ),
621 'bar2' => (object)array( '_dummy' => 'foobaz' ),
623 '_dummy' => 'foobaz',
625 '_dummy2' => 'foobaz!',
626 ), $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
627 $this->assertEquals( array(
628 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
629 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
630 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
631 ApiResult
::META_TYPE
=> 'array',
632 '_dummy' => 'foobaz',
633 ), $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
636 $data = ApiResult
::stripMetadataNonRecursive( (object)$arr, $metadata );
637 $this->assertEquals( (object)array(
639 'bar' => array( '_dummy' => 'foobaz' ),
640 'bar2' => (object)array( '_dummy' => 'foobaz' ),
642 '_dummy' => 'foobaz',
644 'foo2' => (object)array(
645 'bar' => array( '_dummy' => 'foobaz' ),
646 'bar2' => (object)array( '_dummy' => 'foobaz' ),
648 '_dummy' => 'foobaz',
650 '_dummy2' => 'foobaz!',
651 ), $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
652 $this->assertEquals( array(
653 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
654 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
655 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
656 ApiResult
::META_TYPE
=> 'array',
657 '_dummy' => 'foobaz',
658 ), $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
663 * @dataProvider provideTransformations
664 * @param string $label
665 * @param array $input
666 * @param array $transforms
667 * @param array|Exception $expect
669 public function testTransformations( $label, $input, $transforms, $expect ) {
670 $result = new ApiResult( false );
671 $result->addValue( null, 'test', $input );
673 if ( $expect instanceof Exception
) {
675 $output = $result->getResultData( 'test', $transforms );
676 $this->fail( 'Expected exception not thrown', $label );
677 } catch ( Exception
$ex ) {
678 $this->assertEquals( $ex, $expect, $label );
681 $output = $result->getResultData( 'test', $transforms );
682 $this->assertEquals( $expect, $output, $label );
686 public function provideTransformations() {
687 $kvp = function ( $keyKey, $key, $valKey, $value ) {
691 ApiResult
::META_PRESERVE_KEYS
=> array( $keyKey ),
692 ApiResult
::META_CONTENT
=> $valKey,
693 ApiResult
::META_TYPE
=> 'assoc',
697 'defaultArray' => array( 2 => 'a', 0 => 'b', 1 => 'c' ),
698 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
699 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c' ),
700 'array' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'array' ),
701 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'BCarray' ),
702 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'BCassoc' ),
703 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
704 'kvp' => array( 'x' => 'a', 'y' => 'b', 'z' => array( 'c' ), ApiResult
::META_TYPE
=> 'kvp' ),
705 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
706 ApiResult
::META_TYPE
=> 'BCkvp',
707 ApiResult
::META_KVP_KEY_NAME
=> 'key',
709 'kvpmerge' => array( 'x' => 'a', 'y' => array( 'b' ), 'z' => array( 'c' => 'd' ),
710 ApiResult
::META_TYPE
=> 'kvp',
711 ApiResult
::META_KVP_MERGE
=> true,
713 'emptyDefault' => array( '_dummy' => 1 ),
714 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
716 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
720 'bar' => array( '_dummy' => 'foobaz' ),
722 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
723 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
724 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
725 ApiResult
::META_TYPE
=> 'array',
728 '_dummy' => 'foobaz',
730 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
731 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
732 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
733 ApiResult
::META_TYPE
=> 'array',
734 '_dummy' => 'foobaz',
735 '_dummy2' => 'foobaz!',
746 ApiResult
::META_BC_BOOLS
=> array( 0, 'true', 'false' ),
748 array( 'BC' => array() ),
753 ApiResult
::META_BC_BOOLS
=> array( 0, 'true', 'false' ),
757 'BC: META_BC_SUBELEMENTS',
761 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
763 array( 'BC' => array() ),
767 ApiResult
::META_CONTENT
=> '*',
768 ApiResult
::META_TYPE
=> 'assoc',
771 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
778 ApiResult
::META_CONTENT
=> 'content',
780 array( 'BC' => array() ),
783 ApiResult
::META_CONTENT
=> '*',
789 'foo' => 'foo value',
790 'bar' => 'bar value',
791 '_baz' => 'baz value',
792 ApiResult
::META_TYPE
=> 'BCkvp',
793 ApiResult
::META_KVP_KEY_NAME
=> 'key',
794 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
796 array( 'BC' => array() ),
798 $kvp( 'key', 'foo', '*', 'foo value' ),
799 $kvp( 'key', 'bar', '*', 'bar value' ),
800 $kvp( 'key', '_baz', '*', 'baz value' ),
801 ApiResult
::META_TYPE
=> 'array',
802 ApiResult
::META_KVP_KEY_NAME
=> 'key',
803 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
809 ApiResult
::META_TYPE
=> 'BCarray',
811 array( 'BC' => array() ),
813 ApiResult
::META_TYPE
=> 'default',
819 ApiResult
::META_TYPE
=> 'BCassoc',
821 array( 'BC' => array() ),
823 ApiResult
::META_TYPE
=> 'default',
827 'BC: BCkvp exception',
829 ApiResult
::META_TYPE
=> 'BCkvp',
831 array( 'BC' => array() ),
832 new UnexpectedValueException(
833 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
837 'BC: nobool, no*, nosub',
841 'content' => 'content',
842 ApiResult
::META_CONTENT
=> 'content',
844 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
845 'BCarray' => array( ApiResult
::META_TYPE
=> 'BCarray' ),
846 'BCassoc' => array( ApiResult
::META_TYPE
=> 'BCassoc' ),
848 'foo' => 'foo value',
849 'bar' => 'bar value',
850 '_baz' => 'baz value',
851 ApiResult
::META_TYPE
=> 'BCkvp',
852 ApiResult
::META_KVP_KEY_NAME
=> 'key',
853 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
856 array( 'BC' => array( 'nobool', 'no*', 'nosub' ) ),
860 'content' => 'content',
862 'BCarray' => array( ApiResult
::META_TYPE
=> 'default' ),
863 'BCassoc' => array( ApiResult
::META_TYPE
=> 'default' ),
865 $kvp( 'key', 'foo', '*', 'foo value' ),
866 $kvp( 'key', 'bar', '*', 'bar value' ),
867 $kvp( 'key', '_baz', '*', 'baz value' ),
868 ApiResult
::META_TYPE
=> 'array',
869 ApiResult
::META_KVP_KEY_NAME
=> 'key',
870 ApiResult
::META_PRESERVE_KEYS
=> array( '_baz' ),
872 ApiResult
::META_CONTENT
=> 'content',
873 ApiResult
::META_BC_SUBELEMENTS
=> array( 'bc' ),
878 'Types: Normal transform',
880 array( 'Types' => array() ),
882 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
883 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
884 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
885 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
886 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
887 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
888 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
889 'kvp' => array( 'x' => 'a', 'y' => 'b',
890 'z' => array( 'c', ApiResult
::META_TYPE
=> 'array' ),
891 ApiResult
::META_TYPE
=> 'assoc'
893 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
894 ApiResult
::META_TYPE
=> 'assoc',
895 ApiResult
::META_KVP_KEY_NAME
=> 'key',
899 'y' => array( 'b', ApiResult
::META_TYPE
=> 'array' ),
900 'z' => array( 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ),
901 ApiResult
::META_TYPE
=> 'assoc',
902 ApiResult
::META_KVP_MERGE
=> true,
904 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
905 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
907 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
908 ApiResult
::META_TYPE
=> 'assoc',
912 'Types: AssocAsObject',
914 array( 'Types' => array( 'AssocAsObject' => true ) ),
916 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
917 'defaultAssoc' => (object)array( 'x' => 'a',
918 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
920 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
921 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
923 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
924 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
925 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
926 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
927 'kvp' => (object)array( 'x' => 'a', 'y' => 'b',
928 'z' => array( 'c', ApiResult
::META_TYPE
=> 'array' ),
929 ApiResult
::META_TYPE
=> 'assoc'
931 'BCkvp' => (object)array( 'x' => 'a', 'y' => 'b',
932 ApiResult
::META_TYPE
=> 'assoc',
933 ApiResult
::META_KVP_KEY_NAME
=> 'key',
935 'kvpmerge' => (object)array(
937 'y' => array( 'b', ApiResult
::META_TYPE
=> 'array' ),
938 'z' => (object)array( 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ),
939 ApiResult
::META_TYPE
=> 'assoc',
940 ApiResult
::META_KVP_MERGE
=> true,
942 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
943 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
945 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
946 ApiResult
::META_TYPE
=> 'assoc',
952 array( 'Types' => array( 'ArmorKVP' => 'name' ) ),
954 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
955 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
956 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
957 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
958 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
959 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
960 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
962 $kvp( 'name', 'x', 'value', 'a' ),
963 $kvp( 'name', 'y', 'value', 'b' ),
964 $kvp( 'name', 'z', 'value', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
965 ApiResult
::META_TYPE
=> 'array'
968 $kvp( 'key', 'x', 'value', 'a' ),
969 $kvp( 'key', 'y', 'value', 'b' ),
970 ApiResult
::META_TYPE
=> 'array',
971 ApiResult
::META_KVP_KEY_NAME
=> 'key',
974 $kvp( 'name', 'x', 'value', 'a' ),
975 $kvp( 'name', 'y', 'value', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
976 array( 'name' => 'z', 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc', ApiResult
::META_PRESERVE_KEYS
=> array( 'name' ) ),
977 ApiResult
::META_TYPE
=> 'array',
978 ApiResult
::META_KVP_MERGE
=> true,
980 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
981 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
983 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
984 ApiResult
::META_TYPE
=> 'assoc',
988 'Types: ArmorKVP + BC',
990 array( 'BC' => array(), 'Types' => array( 'ArmorKVP' => 'name' ) ),
992 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
993 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
994 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
995 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
996 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
997 'BCassoc' => array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'array' ),
998 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1000 $kvp( 'name', 'x', '*', 'a' ),
1001 $kvp( 'name', 'y', '*', 'b' ),
1002 $kvp( 'name', 'z', '*', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
1003 ApiResult
::META_TYPE
=> 'array'
1006 $kvp( 'key', 'x', '*', 'a' ),
1007 $kvp( 'key', 'y', '*', 'b' ),
1008 ApiResult
::META_TYPE
=> 'array',
1009 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1011 'kvpmerge' => array(
1012 $kvp( 'name', 'x', '*', 'a' ),
1013 $kvp( 'name', 'y', '*', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
1014 array( 'name' => 'z', 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc', ApiResult
::META_PRESERVE_KEYS
=> array( 'name' ) ),
1015 ApiResult
::META_TYPE
=> 'array',
1016 ApiResult
::META_KVP_MERGE
=> true,
1018 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
1019 'emptyAssoc' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
1021 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
1022 ApiResult
::META_TYPE
=> 'assoc',
1026 'Types: ArmorKVP + AssocAsObject',
1028 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ) ),
1030 'defaultArray' => array( 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ),
1031 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b',
1032 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1034 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b',
1035 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1037 'array' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
1038 'BCarray' => array( 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ),
1039 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1040 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ),
1042 (object)$kvp( 'name', 'x', 'value', 'a' ),
1043 (object)$kvp( 'name', 'y', 'value', 'b' ),
1044 (object)$kvp( 'name', 'z', 'value', array( 'c', ApiResult
::META_TYPE
=> 'array' ) ),
1045 ApiResult
::META_TYPE
=> 'array'
1048 (object)$kvp( 'key', 'x', 'value', 'a' ),
1049 (object)$kvp( 'key', 'y', 'value', 'b' ),
1050 ApiResult
::META_TYPE
=> 'array',
1051 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1053 'kvpmerge' => array(
1054 (object)$kvp( 'name', 'x', 'value', 'a' ),
1055 (object)$kvp( 'name', 'y', 'value', array( 'b', ApiResult
::META_TYPE
=> 'array' ) ),
1056 (object)array( 'name' => 'z', 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc', ApiResult
::META_PRESERVE_KEYS
=> array( 'name' ) ),
1057 ApiResult
::META_TYPE
=> 'array',
1058 ApiResult
::META_KVP_MERGE
=> true,
1060 'emptyDefault' => array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ),
1061 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ),
1063 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy' ),
1064 ApiResult
::META_TYPE
=> 'assoc',
1068 'Types: BCkvp exception',
1070 ApiResult
::META_TYPE
=> 'BCkvp',
1072 array( 'Types' => array() ),
1073 new UnexpectedValueException(
1074 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
1079 'Strip: With ArmorKVP + AssocAsObject transforms',
1081 array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ), 'Strip' => 'all' ),
1083 'defaultArray' => array( 'b', 'c', 'a' ),
1084 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
1085 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c' ),
1086 'array' => array( 'a', 'c', 'b' ),
1087 'BCarray' => array( 'a', 'c', 'b' ),
1088 'BCassoc' => (object)array( 'a', 'b', 'c' ),
1089 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c' ),
1091 (object)array( 'name' => 'x', 'value' => 'a' ),
1092 (object)array( 'name' => 'y', 'value' => 'b' ),
1093 (object)array( 'name' => 'z', 'value' => array( 'c' ) ),
1096 (object)array( 'key' => 'x', 'value' => 'a' ),
1097 (object)array( 'key' => 'y', 'value' => 'b' ),
1099 'kvpmerge' => array(
1100 (object)array( 'name' => 'x', 'value' => 'a' ),
1101 (object)array( 'name' => 'y', 'value' => array( 'b' ) ),
1102 (object)array( 'name' => 'z', 'c' => 'd' ),
1104 'emptyDefault' => array(),
1105 'emptyAssoc' => (object)array(),
1113 array( 'Strip' => 'all' ),
1120 '_dummy2' => 'foobaz!',
1126 array( 'Strip' => 'base' ),
1129 'bar' => array( '_dummy' => 'foobaz' ),
1131 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1132 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1133 ApiResult
::META_PRESERVE_KEYS
=> array( 'foo', 'bar', '_dummy2', 0 ),
1134 ApiResult
::META_TYPE
=> 'array',
1137 '_dummy' => 'foobaz',
1139 '_dummy2' => 'foobaz!',
1145 array( 'Strip' => 'bc' ),
1150 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1151 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1155 '_dummy2' => 'foobaz!',
1156 ApiResult
::META_SUBELEMENTS
=> array( 'foo', 'bar' ),
1157 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1169 ApiResult
::META_CONTENT
=> 'foo',
1170 ApiResult
::META_PRESERVE_KEYS
=> array( '_dummy2', '_dummy3' ),
1173 'Custom' => array( $this, 'customTransform' ),
1181 'baz' => array( 'a', 'b' ),
1182 '_dummy2' => '_DUMMY2',
1183 '_dummy3' => '_DUMMY3',
1184 ApiResult
::META_CONTENT
=> 'bar',
1192 * Custom transformer for testTransformations
1193 * @param array &$data
1194 * @param array &$metadata
1196 public function customTransform( &$data, &$metadata ) {
1197 // Prevent recursion
1198 if ( isset( $metadata['_added'] ) ) {
1199 $metadata[ApiResult
::META_TYPE
] = 'array';
1203 foreach ( $data as $k => $v ) {
1204 $data[$k] = strtoupper( $k );
1206 $data['baz'] = array( '_added' => 1, 'z' => 'b', 'y' => 'a' );
1207 $metadata[ApiResult
::META_PRESERVE_KEYS
][0] = '_dummy';
1208 $data[ApiResult
::META_CONTENT
] = 'bar';
1214 public function testAddMetadataToResultVars() {
1219 'sequential_numeric_keys' => array( 'a', 'b', 'c' ),
1220 'non_sequential_numeric_keys' => array( 'a', 'b', 4 => 'c' ),
1221 'string_keys' => array(
1225 'object_sequential_keys' => (object)array( 'a', 'b', 'c' ),
1226 '_type' => "should be overwritten in result",
1228 $this->assertSame( array(
1229 ApiResult
::META_TYPE
=> 'kvp',
1230 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1231 ApiResult
::META_PRESERVE_KEYS
=> array(
1233 'sequential_numeric_keys', 'non_sequential_numeric_keys',
1234 'string_keys', 'object_sequential_keys'
1236 ApiResult
::META_BC_BOOLS
=> array( 'b' ),
1237 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1241 'sequential_numeric_keys' => array(
1242 ApiResult
::META_TYPE
=> 'array',
1243 ApiResult
::META_BC_BOOLS
=> array(),
1244 ApiResult
::META_INDEXED_TAG_NAME
=> 'value',
1249 'non_sequential_numeric_keys' => array(
1250 ApiResult
::META_TYPE
=> 'kvp',
1251 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1252 ApiResult
::META_PRESERVE_KEYS
=> array( 0, 1, 4 ),
1253 ApiResult
::META_BC_BOOLS
=> array(),
1254 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1259 'string_keys' => array(
1260 ApiResult
::META_TYPE
=> 'kvp',
1261 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1262 ApiResult
::META_PRESERVE_KEYS
=> array( 'one', 'two' ),
1263 ApiResult
::META_BC_BOOLS
=> array(),
1264 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1268 'object_sequential_keys' => array(
1269 ApiResult
::META_TYPE
=> 'kvp',
1270 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1271 ApiResult
::META_PRESERVE_KEYS
=> array( 0, 1, 2 ),
1272 ApiResult
::META_BC_BOOLS
=> array(),
1273 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1278 ), ApiResult
::addMetadataToResultVars( $arr ) );
1284 public function testDeprecatedFunctions() {
1285 // Ignore ApiResult deprecation warnings during this test
1286 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1287 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1290 if ( preg_match( '/Use of ApiMain to ApiResult::__construct ' .
1291 'was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1296 $reset = new ScopedCallback( 'restore_error_handler' );
1298 $context = new DerivativeContext( RequestContext
::getMain() );
1299 $context->setConfig( new HashConfig( array(
1300 'APIModules' => array(),
1301 'APIFormatModules' => array(),
1302 'APIMaxResultSize' => 42,
1304 $main = new ApiMain( $context );
1305 $result = TestingAccessWrapper
::newFromObject( new ApiResult( $main ) );
1306 $this->assertSame( 42, $result->maxSize
);
1307 $this->assertSame( $main->getErrorFormatter(), $result->errorFormatter
);
1308 $this->assertSame( $main, $result->mainForContinuation
);
1310 $result = new ApiResult( 8388608 );
1312 $result->addContentValue( null, 'test', 'content' );
1313 $result->addContentValue( array( 'foo', 'bar' ), 'test', 'content' );
1314 $result->addIndexedTagName( null, 'itn' );
1315 $result->addSubelementsList( null, array( 'sub' ) );
1316 $this->assertSame( array(
1323 ), $result->getData() );
1326 ApiResult
::setContent( $arr, 'value' );
1327 ApiResult
::setContent( $arr, 'value2', 'foobar' );
1328 $this->assertSame( array(
1329 ApiResult
::META_CONTENT
=> 'content',
1330 'content' => 'value',
1332 ApiResult
::META_CONTENT
=> 'content',
1333 'content' => 'value2',
1337 $result = new ApiResult( 3 );
1338 $formatter = new ApiErrorFormatter_BackCompat( $result );
1339 $result->setErrorFormatter( $formatter );
1340 $result->disableSizeCheck();
1341 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
1342 $result->enableSizeCheck();
1343 $this->assertSame( 0, $result->getSize() );
1344 $this->assertFalse( $result->addValue( null, 'foo', '1234567890' ) );
1346 $arr = array( 'foo' => array( 'bar' => 1 ) );
1347 $result->setIndexedTagName_recursive( $arr, 'itn' );
1348 $this->assertSame( array(
1351 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn'
1355 $status = Status
::newGood();
1356 $status->fatal( 'parentheses', '1' );
1357 $status->fatal( 'parentheses', '2' );
1358 $status->warning( 'parentheses', '3' );
1359 $status->warning( 'parentheses', '4' );
1360 $this->assertSame( array(
1363 'message' => 'parentheses',
1366 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1371 'message' => 'parentheses',
1374 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1377 ApiResult
::META_INDEXED_TAG_NAME
=> 'error',
1378 ), $result->convertStatusToArray( $status, 'error' ) );
1379 $this->assertSame( array(
1381 'type' => 'warning',
1382 'message' => 'parentheses',
1385 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1389 'type' => 'warning',
1390 'message' => 'parentheses',
1393 ApiResult
::META_INDEXED_TAG_NAME
=> 'param',
1396 ApiResult
::META_INDEXED_TAG_NAME
=> 'warning',
1397 ), $result->convertStatusToArray( $status, 'warning' ) );
1403 public function testDeprecatedContinuation() {
1404 // Ignore ApiResult deprecation warnings during this test
1405 set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
1406 if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
1412 $reset = new ScopedCallback( 'restore_error_handler' );
1413 $allModules = array(
1414 new MockApiQueryBase( 'mock1' ),
1415 new MockApiQueryBase( 'mock2' ),
1416 new MockApiQueryBase( 'mocklist' ),
1418 $generator = new MockApiQueryBase( 'generator' );
1420 $main = new ApiMain( RequestContext
::getMain() );
1421 $result = new ApiResult( 8388608 );
1422 $result->setMainForContinuation( $main );
1423 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1424 $this->assertSame( array( false, $allModules ), $ret );
1425 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1426 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1427 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1428 $result->endContinuation( 'raw' );
1429 $result->endContinuation( 'standard' );
1430 $this->assertSame( array(
1432 'm1continue' => '1|2',
1433 'continue' => '||mock2',
1434 ), $result->getResultData( 'continue' ) );
1435 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1436 $this->assertSame( array(
1437 'mock1' => array( 'm1continue' => '1|2' ),
1438 'mocklist' => array( 'mlcontinue' => 2 ),
1439 'generator' => array( 'gcontinue' => 3 ),
1440 ), $result->getResultData( 'query-continue' ) );
1441 $main->setContinuationManager( null );
1443 $result = new ApiResult( 8388608 );
1444 $result->setMainForContinuation( $main );
1445 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1446 $this->assertSame( array( false, $allModules ), $ret );
1447 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1448 $result->setGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
1449 $result->endContinuation( 'raw' );
1450 $result->endContinuation( 'standard' );
1451 $this->assertSame( array(
1452 'm1continue' => '1|2',
1453 'continue' => '||mock2|mocklist',
1454 ), $result->getResultData( 'continue' ) );
1455 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1456 $this->assertSame( array(
1457 'mock1' => array( 'm1continue' => '1|2' ),
1458 'generator' => array( 'gcontinue' => '3|4' ),
1459 ), $result->getResultData( 'query-continue' ) );
1460 $main->setContinuationManager( null );
1462 $result = new ApiResult( 8388608 );
1463 $result->setMainForContinuation( $main );
1464 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1465 $this->assertSame( array( false, $allModules ), $ret );
1466 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1467 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1468 $result->endContinuation( 'raw' );
1469 $result->endContinuation( 'standard' );
1470 $this->assertSame( array(
1473 'continue' => 'gcontinue||',
1474 ), $result->getResultData( 'continue' ) );
1475 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1476 $this->assertSame( array(
1477 'mocklist' => array( 'mlcontinue' => 2 ),
1478 'generator' => array( 'gcontinue' => 3 ),
1479 ), $result->getResultData( 'query-continue' ) );
1480 $main->setContinuationManager( null );
1482 $result = new ApiResult( 8388608 );
1483 $result->setMainForContinuation( $main );
1484 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1485 $this->assertSame( array( false, $allModules ), $ret );
1486 $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
1487 $result->endContinuation( 'raw' );
1488 $result->endContinuation( 'standard' );
1489 $this->assertSame( array(
1491 'continue' => 'gcontinue||mocklist',
1492 ), $result->getResultData( 'continue' ) );
1493 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1494 $this->assertSame( array(
1495 'generator' => array( 'gcontinue' => 3 ),
1496 ), $result->getResultData( 'query-continue' ) );
1497 $main->setContinuationManager( null );
1499 $result = new ApiResult( 8388608 );
1500 $result->setMainForContinuation( $main );
1501 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1502 $this->assertSame( array( false, $allModules ), $ret );
1503 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1504 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1505 $result->endContinuation( 'raw' );
1506 $result->endContinuation( 'standard' );
1507 $this->assertSame( array(
1509 'm1continue' => '1|2',
1510 'continue' => '||mock2',
1511 ), $result->getResultData( 'continue' ) );
1512 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1513 $this->assertSame( array(
1514 'mock1' => array( 'm1continue' => '1|2' ),
1515 'mocklist' => array( 'mlcontinue' => 2 ),
1516 ), $result->getResultData( 'query-continue' ) );
1517 $main->setContinuationManager( null );
1519 $result = new ApiResult( 8388608 );
1520 $result->setMainForContinuation( $main );
1521 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1522 $this->assertSame( array( false, $allModules ), $ret );
1523 $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
1524 $result->endContinuation( 'raw' );
1525 $result->endContinuation( 'standard' );
1526 $this->assertSame( array(
1527 'm1continue' => '1|2',
1528 'continue' => '||mock2|mocklist',
1529 ), $result->getResultData( 'continue' ) );
1530 $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
1531 $this->assertSame( array(
1532 'mock1' => array( 'm1continue' => '1|2' ),
1533 ), $result->getResultData( 'query-continue' ) );
1534 $main->setContinuationManager( null );
1536 $result = new ApiResult( 8388608 );
1537 $result->setMainForContinuation( $main );
1538 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1539 $this->assertSame( array( false, $allModules ), $ret );
1540 $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
1541 $result->endContinuation( 'raw' );
1542 $result->endContinuation( 'standard' );
1543 $this->assertSame( array(
1545 'continue' => '-||mock1|mock2',
1546 ), $result->getResultData( 'continue' ) );
1547 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1548 $this->assertSame( array(
1549 'mocklist' => array( 'mlcontinue' => 2 ),
1550 ), $result->getResultData( 'query-continue' ) );
1551 $main->setContinuationManager( null );
1553 $result = new ApiResult( 8388608 );
1554 $result->setMainForContinuation( $main );
1555 $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
1556 $this->assertSame( array( false, $allModules ), $ret );
1557 $result->endContinuation( 'raw' );
1558 $result->endContinuation( 'standard' );
1559 $this->assertSame( null, $result->getResultData( 'continue' ) );
1560 $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
1561 $this->assertSame( null, $result->getResultData( 'query-continue' ) );
1562 $main->setContinuationManager( null );
1564 $result = new ApiResult( 8388608 );
1565 $result->setMainForContinuation( $main );
1566 $ret = $result->beginContinuation( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
1568 array( false, array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ) ),
1571 $main->setContinuationManager( null );
1573 $result = new ApiResult( 8388608 );
1574 $result->setMainForContinuation( $main );
1575 $ret = $result->beginContinuation( '-||', $allModules, array( 'mock1', 'mock2' ) );
1577 array( true, array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ) ),
1580 $main->setContinuationManager( null );
1582 $result = new ApiResult( 8388608 );
1583 $result->setMainForContinuation( $main );
1585 $result->beginContinuation( 'foo', $allModules, array( 'mock1', 'mock2' ) );
1586 $this->fail( 'Expected exception not thrown' );
1587 } catch ( UsageException
$ex ) {
1589 'Invalid continue param. You should pass the original value returned by the previous query',
1591 'Expected exception'
1594 $main->setContinuationManager( null );
1596 $result = new ApiResult( 8388608 );
1597 $result->setMainForContinuation( $main );
1598 $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ),
1599 array( 'mock1', 'mock2' ) );
1601 $result->setContinueParam( $allModules[1], 'm2continue', 1 );
1602 $this->fail( 'Expected exception not thrown' );
1603 } catch ( UnexpectedValueException
$ex ) {
1605 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
1607 'Expected exception'
1611 $result->setContinueParam( $allModules[2], 'mlcontinue', 1 );
1612 $this->fail( 'Expected exception not thrown' );
1613 } catch ( UnexpectedValueException
$ex ) {
1615 'Module \'mocklist\' called ApiContinuationManager::addContinueParam ' .
1616 'but was not passed to ApiContinuationManager::__construct',
1618 'Expected exception'
1621 $main->setContinuationManager( null );
1625 public function testObjectSerialization() {
1627 ApiResult
::setValue( $arr, 'foo', (object)array( 'a' => 1, 'b' => 2 ) );
1628 $this->assertSame( array(
1631 ApiResult
::META_TYPE
=> 'assoc',
1635 ApiResult
::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
1636 $this->assertSame( 'Ok', $arr['foo'] );
1639 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
1640 $this->assertSame( 'Ok', $arr['foo'] );
1644 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1645 new ApiResultTestStringifiableObject()
1647 $this->fail( 'Expected exception not thrown' );
1648 } catch ( UnexpectedValueException
$ex ) {
1650 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1651 'returned an object of class ApiResultTestStringifiableObject',
1653 'Expected exception'
1659 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN
) );
1660 $this->fail( 'Expected exception not thrown' );
1661 } catch ( UnexpectedValueException
$ex ) {
1663 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1664 'returned an invalid value: Cannot add non-finite floats to ApiResult',
1666 'Expected exception'
1671 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1673 'one' => new ApiResultTestStringifiableObject( '1' ),
1674 'two' => new ApiResultTestSerializableObject( 2 ),
1677 $this->assertSame( array(
1685 class ApiResultTestStringifiableObject
{
1688 public function __construct( $ret = 'Ok' ) {
1692 public function __toString() {
1697 class ApiResultTestSerializableObject
{
1700 public function __construct( $ret ) {
1704 public function __toString() {
1708 public function serializeForApiResult() {