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' );
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 = [ '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( [ 0, 'top', 'foo', 'bar', 'bottom' ], array_keys( $arr ) );
71 ApiResult
::setValue( $arr, 'sub', [ 'foo' => 1 ] );
72 ApiResult
::setValue( $arr, 'sub', [ 'bar' => 1 ] );
73 $this->assertSame( [ 'sub' => [ 'foo' => 1, 'bar' => 1 ] ], $arr );
76 ApiResult
::setValue( $arr, 'sub', [ '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 );
94 'title' => (string)$title,
95 'obj' => [ '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 );
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" );
215 'foo' => "foo\xef\xbf\xbdbar",
218 0 => "foo\xef\xbf\xbdbar",
225 ApiResult
::setValue( $arr, 'foo', $obj );
229 ApiResult
::META_TYPE
=> 'assoc',
237 public function testInstanceDataMethods() {
238 $result = new ApiResult( 8388608 );
240 $result->addValue( null, 'setValue', '1' );
242 $result->addValue( null, null, 'unnamed 1' );
243 $result->addValue( null, null, 'unnamed 2' );
245 $result->addValue( null, 'deleteValue', '2' );
246 $result->removeValue( null, 'deleteValue' );
248 $result->addValue( [ 'a', 'b' ], 'deleteValue', '3' );
249 $result->removeValue( [ 'a', 'b', 'deleteValue' ], null, '3' );
251 $result->addContentValue( null, 'setContentValue', '3' );
257 'a' => [ 'b' => [] ],
258 'setContentValue' => '3',
259 ApiResult
::META_TYPE
=> 'assoc',
260 ApiResult
::META_CONTENT
=> 'setContentValue',
261 ], $result->getResultData() );
262 $this->assertSame( 20, $result->getSize() );
265 $result->addValue( null, 'setValue', '99' );
266 $this->fail( 'Expected exception not thrown' );
267 } catch ( RuntimeException
$ex ) {
269 'Attempting to add element setValue=99, existing value is 1',
276 $result->addContentValue( null, 'setContentValue2', '99' );
277 $this->fail( 'Expected exception not thrown' );
278 } catch ( RuntimeException
$ex ) {
280 'Attempting to set content element as setContentValue2 when setContentValue ' .
281 'is already set as the content element',
287 $result->addValue( null, 'setValue', '99', ApiResult
::OVERRIDE
);
288 $this->assertSame( '99', $result->getResultData( [ 'setValue' ] ) );
290 $result->addContentValue( null, 'setContentValue2', '99', ApiResult
::OVERRIDE
);
291 $this->assertSame( 'setContentValue2',
292 $result->getResultData( [ ApiResult
::META_CONTENT
] ) );
296 ApiResult
::META_TYPE
=> 'assoc',
297 ], $result->getResultData() );
298 $this->assertSame( 0, $result->getSize() );
300 $result->addValue( null, 'foo', 1 );
301 $result->addValue( null, 'bar', 1 );
302 $result->addValue( null, 'top', '2', ApiResult
::ADD_ON_TOP
);
303 $result->addValue( null, null, '2', ApiResult
::ADD_ON_TOP
);
304 $result->addValue( null, 'bottom', '2' );
305 $result->addValue( null, 'foo', '2', ApiResult
::OVERRIDE
);
306 $result->addValue( null, 'bar', '2', ApiResult
::OVERRIDE | ApiResult
::ADD_ON_TOP
);
307 $this->assertSame( [ 0, 'top', 'foo', 'bar', 'bottom', ApiResult
::META_TYPE
],
308 array_keys( $result->getResultData() ) );
311 $result->addValue( null, 'foo', [ 'bar' => 1 ] );
312 $result->addValue( [ 'foo', 'top' ], 'x', 2, ApiResult
::ADD_ON_TOP
);
313 $result->addValue( [ 'foo', 'bottom' ], 'x', 2 );
314 $this->assertSame( [ 'top', 'bar', 'bottom' ],
315 array_keys( $result->getResultData( [ 'foo' ] ) ) );
318 $result->addValue( null, 'sub', [ 'foo' => 1 ] );
319 $result->addValue( null, 'sub', [ 'bar' => 1 ] );
321 'sub' => [ 'foo' => 1, 'bar' => 1 ],
322 ApiResult
::META_TYPE
=> 'assoc',
323 ], $result->getResultData() );
326 $result->addValue( null, 'sub', [ 'foo' => 2, 'baz' => 2 ] );
327 $this->fail( 'Expected exception not thrown' );
328 } catch ( RuntimeException
$ex ) {
330 'Conflicting keys (foo) when attempting to merge element sub',
337 $title = Title
::newFromText( "MediaWiki:Foobar" );
341 $result->addValue( null, 'title', $title );
342 $result->addValue( null, 'obj', $obj );
344 'title' => (string)$title,
345 'obj' => [ 'foo' => 1, 'bar' => 2, ApiResult
::META_TYPE
=> 'assoc' ],
346 ApiResult
::META_TYPE
=> 'assoc',
347 ], $result->getResultData() );
351 $result->addValue( null, 'file', $fh );
352 $this->fail( 'Expected exception not thrown' );
353 } catch ( InvalidArgumentException
$ex ) {
355 'Cannot add resource(stream) to ApiResult',
361 $result->addValue( null, null, $fh );
362 $this->fail( 'Expected exception not thrown' );
363 } catch ( InvalidArgumentException
$ex ) {
365 'Cannot add resource(stream) to ApiResult',
372 $result->addValue( null, 'sub', $obj );
373 $this->fail( 'Expected exception not thrown' );
374 } catch ( InvalidArgumentException
$ex ) {
376 'Cannot add resource(stream) to ApiResult',
383 $result->addValue( null, null, $obj );
384 $this->fail( 'Expected exception not thrown' );
385 } catch ( InvalidArgumentException
$ex ) {
387 'Cannot add resource(stream) to ApiResult',
395 $result->addValue( null, 'inf', INF
);
396 $this->fail( 'Expected exception not thrown' );
397 } catch ( InvalidArgumentException
$ex ) {
399 'Cannot add non-finite floats to ApiResult',
405 $result->addValue( null, null, INF
);
406 $this->fail( 'Expected exception not thrown' );
407 } catch ( InvalidArgumentException
$ex ) {
409 'Cannot add non-finite floats to ApiResult',
415 $result->addValue( null, 'nan', NAN
);
416 $this->fail( 'Expected exception not thrown' );
417 } catch ( InvalidArgumentException
$ex ) {
419 'Cannot add non-finite floats to ApiResult',
425 $result->addValue( null, null, NAN
);
426 $this->fail( 'Expected exception not thrown' );
427 } catch ( InvalidArgumentException
$ex ) {
429 'Cannot add non-finite floats to ApiResult',
435 $result->addValue( null, null, NAN
, ApiResult
::NO_VALIDATE
);
438 $result->addValue( null, null, NAN
, ApiResult
::NO_SIZE_CHECK
);
439 $this->fail( 'Expected exception not thrown' );
440 } catch ( InvalidArgumentException
$ex ) {
442 'Cannot add non-finite floats to ApiResult',
449 $result->addParsedLimit( 'foo', 12 );
451 'limits' => [ 'foo' => 12 ],
452 ApiResult
::META_TYPE
=> 'assoc',
453 ], $result->getResultData() );
454 $result->addParsedLimit( 'foo', 13 );
456 'limits' => [ 'foo' => 13 ],
457 ApiResult
::META_TYPE
=> 'assoc',
458 ], $result->getResultData() );
459 $this->assertSame( null, $result->getResultData( [ 'foo', 'bar', 'baz' ] ) );
460 $this->assertSame( 13, $result->getResultData( [ 'limits', 'foo' ] ) );
462 $result->getResultData( [ 'limits', 'foo', 'bar' ] );
463 $this->fail( 'Expected exception not thrown' );
464 } catch ( InvalidArgumentException
$ex ) {
466 'Path limits.foo is not an array',
472 // Add two values and some metadata, but ensure metadata is not counted
473 $result = new ApiResult( 100 );
474 $obj = [ 'attr' => '12345' ];
475 ApiResult
::setContentValue( $obj, 'content', '1234567890' );
476 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
477 $this->assertSame( 15, $result->getSize() );
479 $result = new ApiResult( 10 );
480 $formatter = new ApiErrorFormatter( $result, Language
::factory( 'en' ), 'none', false );
481 $result->setErrorFormatter( $formatter );
482 $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
483 $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult
::NO_SIZE_CHECK
) );
484 $this->assertSame( 0, $result->getSize() );
486 $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
487 $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
488 $result->removeValue( null, 'foo' );
489 $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
491 $result = new ApiResult( 10 );
492 $obj = new ApiResultTestSerializableObject( 'ok' );
493 $obj->foobar
= 'foobaz';
494 $this->assertTrue( $result->addValue( null, 'foo', $obj ) );
495 $this->assertSame( 2, $result->getSize() );
497 $result = new ApiResult( 8388608 );
498 $result2 = new ApiResult( 8388608 );
499 $result2->addValue( null, 'foo', 'bar' );
500 $result->addValue( null, 'baz', $result2 );
504 ApiResult
::META_TYPE
=> 'assoc',
506 ApiResult
::META_TYPE
=> 'assoc',
507 ], $result->getResultData() );
509 $result = new ApiResult( 8388608 );
510 $result->addValue( null, 'foo', "foo\x80bar" );
511 $result->addValue( null, 'bar', "a\xcc\x81" );
512 $result->addValue( null, 'baz', 74 );
513 $result->addValue( null, null, "foo\x80bar" );
514 $result->addValue( null, null, "a\xcc\x81" );
516 'foo' => "foo\xef\xbf\xbdbar",
519 0 => "foo\xef\xbf\xbdbar",
521 ApiResult
::META_TYPE
=> 'assoc',
522 ], $result->getResultData() );
524 $result = new ApiResult( 8388608 );
528 $result->addValue( $arr, 'foo', $obj );
532 ApiResult
::META_TYPE
=> 'assoc',
534 ApiResult
::META_TYPE
=> 'assoc',
535 ], $result->getResultData() );
541 public function testMetadata() {
542 $arr = [ 'foo' => [ 'bar' => [] ] ];
543 $result = new ApiResult( 8388608 );
544 $result->addValue( null, 'foo', [ 'bar' => [] ] );
549 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
550 ApiResult
::META_TYPE
=> 'default',
552 ApiResult
::META_INDEXED_TAG_NAME
=> 'ritn',
553 ApiResult
::META_TYPE
=> 'default',
555 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
556 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
557 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar' ],
558 ApiResult
::META_TYPE
=> 'array',
561 ApiResult
::setSubelementsList( $arr, 'foo' );
562 ApiResult
::setSubelementsList( $arr, [ 'bar', 'baz' ] );
563 ApiResult
::unsetSubelementsList( $arr, 'baz' );
564 ApiResult
::setIndexedTagNameRecursive( $arr, 'ritn' );
565 ApiResult
::setIndexedTagName( $arr, 'itn' );
566 ApiResult
::setPreserveKeysList( $arr, 'foo' );
567 ApiResult
::setPreserveKeysList( $arr, [ 'bar', 'baz' ] );
568 ApiResult
::unsetPreserveKeysList( $arr, 'baz' );
569 ApiResult
::setArrayTypeRecursive( $arr, 'default' );
570 ApiResult
::setArrayType( $arr, 'array' );
571 $this->assertSame( $expect, $arr );
573 $result->addSubelementsList( null, 'foo' );
574 $result->addSubelementsList( null, [ 'bar', 'baz' ] );
575 $result->removeSubelementsList( null, 'baz' );
576 $result->addIndexedTagNameRecursive( null, 'ritn' );
577 $result->addIndexedTagName( null, 'itn' );
578 $result->addPreserveKeysList( null, 'foo' );
579 $result->addPreserveKeysList( null, [ 'bar', 'baz' ] );
580 $result->removePreserveKeysList( null, 'baz' );
581 $result->addArrayTypeRecursive( null, 'default' );
582 $result->addArrayType( null, 'array' );
583 $this->assertEquals( $expect, $result->getResultData() );
585 $arr = [ 'foo' => [ 'bar' => [] ] ];
589 ApiResult
::META_TYPE
=> 'kvp',
590 ApiResult
::META_KVP_KEY_NAME
=> 'key',
592 ApiResult
::META_TYPE
=> 'kvp',
593 ApiResult
::META_KVP_KEY_NAME
=> 'key',
595 ApiResult
::META_TYPE
=> 'BCkvp',
596 ApiResult
::META_KVP_KEY_NAME
=> 'bc',
598 ApiResult
::setArrayTypeRecursive( $arr, 'kvp', 'key' );
599 ApiResult
::setArrayType( $arr, 'BCkvp', 'bc' );
600 $this->assertSame( $expect, $arr );
606 public function testUtilityFunctions() {
609 'bar' => [ '_dummy' => 'foobaz' ],
610 'bar2' => (object)[ '_dummy' => 'foobaz' ],
612 '_dummy' => 'foobaz',
615 'bar' => [ '_dummy' => 'foobaz' ],
616 'bar2' => (object)[ '_dummy' => 'foobaz' ],
618 '_dummy' => 'foobaz',
620 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
621 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
622 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
623 ApiResult
::META_TYPE
=> 'array',
624 '_dummy' => 'foobaz',
625 '_dummy2' => 'foobaz!',
627 $this->assertEquals( [
630 'bar2' => (object)[],
635 'bar2' => (object)[],
638 '_dummy2' => 'foobaz!',
639 ], ApiResult
::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
642 $data = ApiResult
::stripMetadataNonRecursive( $arr, $metadata );
643 $this->assertEquals( [
645 'bar' => [ '_dummy' => 'foobaz' ],
646 'bar2' => (object)[ '_dummy' => 'foobaz' ],
648 '_dummy' => 'foobaz',
651 'bar' => [ '_dummy' => 'foobaz' ],
652 'bar2' => (object)[ '_dummy' => 'foobaz' ],
654 '_dummy' => 'foobaz',
656 '_dummy2' => 'foobaz!',
657 ], $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
658 $this->assertEquals( [
659 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
660 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
661 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
662 ApiResult
::META_TYPE
=> 'array',
663 '_dummy' => 'foobaz',
664 ], $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
667 $data = ApiResult
::stripMetadataNonRecursive( (object)$arr, $metadata );
668 $this->assertEquals( (object)[
670 'bar' => [ '_dummy' => 'foobaz' ],
671 'bar2' => (object)[ '_dummy' => 'foobaz' ],
673 '_dummy' => 'foobaz',
676 'bar' => [ '_dummy' => 'foobaz' ],
677 'bar2' => (object)[ '_dummy' => 'foobaz' ],
679 '_dummy' => 'foobaz',
681 '_dummy2' => 'foobaz!',
682 ], $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
683 $this->assertEquals( [
684 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
685 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
686 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
687 ApiResult
::META_TYPE
=> 'array',
688 '_dummy' => 'foobaz',
689 ], $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
694 * @dataProvider provideTransformations
695 * @param string $label
696 * @param array $input
697 * @param array $transforms
698 * @param array|Exception $expect
700 public function testTransformations( $label, $input, $transforms, $expect ) {
701 $result = new ApiResult( false );
702 $result->addValue( null, 'test', $input );
704 if ( $expect instanceof Exception
) {
706 $output = $result->getResultData( 'test', $transforms );
707 $this->fail( 'Expected exception not thrown', $label );
708 } catch ( Exception
$ex ) {
709 $this->assertEquals( $ex, $expect, $label );
712 $output = $result->getResultData( 'test', $transforms );
713 $this->assertEquals( $expect, $output, $label );
717 public function provideTransformations() {
718 $kvp = function ( $keyKey, $key, $valKey, $value ) {
722 ApiResult
::META_PRESERVE_KEYS
=> [ $keyKey ],
723 ApiResult
::META_CONTENT
=> $valKey,
724 ApiResult
::META_TYPE
=> 'assoc',
728 'defaultArray' => [ 2 => 'a', 0 => 'b', 1 => 'c' ],
729 'defaultAssoc' => [ 'x' => 'a', 1 => 'b', 0 => 'c' ],
730 'defaultAssoc2' => [ 2 => 'a', 3 => 'b', 0 => 'c' ],
731 'array' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'array' ],
732 'BCarray' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'BCarray' ],
733 'BCassoc' => [ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'BCassoc' ],
734 'assoc' => [ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
735 'kvp' => [ 'x' => 'a', 'y' => 'b', 'z' => [ 'c' ], ApiResult
::META_TYPE
=> 'kvp' ],
736 'BCkvp' => [ 'x' => 'a', 'y' => 'b',
737 ApiResult
::META_TYPE
=> 'BCkvp',
738 ApiResult
::META_KVP_KEY_NAME
=> 'key',
740 'kvpmerge' => [ 'x' => 'a', 'y' => [ 'b' ], 'z' => [ 'c' => 'd' ],
741 ApiResult
::META_TYPE
=> 'kvp',
742 ApiResult
::META_KVP_MERGE
=> true,
744 'emptyDefault' => [ '_dummy' => 1 ],
745 'emptyAssoc' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
747 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
751 'bar' => [ '_dummy' => 'foobaz' ],
753 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
754 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
755 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
756 ApiResult
::META_TYPE
=> 'array',
759 '_dummy' => 'foobaz',
761 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
762 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
763 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
764 ApiResult
::META_TYPE
=> 'array',
765 '_dummy' => 'foobaz',
766 '_dummy2' => 'foobaz!',
777 ApiResult
::META_BC_BOOLS
=> [ 0, 'true', 'false' ],
784 ApiResult
::META_BC_BOOLS
=> [ 0, 'true', 'false' ],
788 'BC: META_BC_SUBELEMENTS',
792 ApiResult
::META_BC_SUBELEMENTS
=> [ 'bc' ],
798 ApiResult
::META_CONTENT
=> '*',
799 ApiResult
::META_TYPE
=> 'assoc',
802 ApiResult
::META_BC_SUBELEMENTS
=> [ 'bc' ],
809 ApiResult
::META_CONTENT
=> 'content',
814 ApiResult
::META_CONTENT
=> '*',
820 'foo' => 'foo value',
821 'bar' => 'bar value',
822 '_baz' => 'baz value',
823 ApiResult
::META_TYPE
=> 'BCkvp',
824 ApiResult
::META_KVP_KEY_NAME
=> 'key',
825 ApiResult
::META_PRESERVE_KEYS
=> [ '_baz' ],
829 $kvp( 'key', 'foo', '*', 'foo value' ),
830 $kvp( 'key', 'bar', '*', 'bar value' ),
831 $kvp( 'key', '_baz', '*', 'baz value' ),
832 ApiResult
::META_TYPE
=> 'array',
833 ApiResult
::META_KVP_KEY_NAME
=> 'key',
834 ApiResult
::META_PRESERVE_KEYS
=> [ '_baz' ],
840 ApiResult
::META_TYPE
=> 'BCarray',
844 ApiResult
::META_TYPE
=> 'default',
850 ApiResult
::META_TYPE
=> 'BCassoc',
854 ApiResult
::META_TYPE
=> 'default',
858 'BC: BCkvp exception',
860 ApiResult
::META_TYPE
=> 'BCkvp',
863 new UnexpectedValueException(
864 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
868 'BC: nobool, no*, nosub',
872 'content' => 'content',
873 ApiResult
::META_CONTENT
=> 'content',
875 ApiResult
::META_BC_SUBELEMENTS
=> [ 'bc' ],
876 'BCarray' => [ ApiResult
::META_TYPE
=> 'BCarray' ],
877 'BCassoc' => [ ApiResult
::META_TYPE
=> 'BCassoc' ],
879 'foo' => 'foo value',
880 'bar' => 'bar value',
881 '_baz' => 'baz value',
882 ApiResult
::META_TYPE
=> 'BCkvp',
883 ApiResult
::META_KVP_KEY_NAME
=> 'key',
884 ApiResult
::META_PRESERVE_KEYS
=> [ '_baz' ],
887 [ 'BC' => [ 'nobool', 'no*', 'nosub' ] ],
891 'content' => 'content',
893 'BCarray' => [ ApiResult
::META_TYPE
=> 'default' ],
894 'BCassoc' => [ ApiResult
::META_TYPE
=> 'default' ],
896 $kvp( 'key', 'foo', '*', 'foo value' ),
897 $kvp( 'key', 'bar', '*', 'bar value' ),
898 $kvp( 'key', '_baz', '*', 'baz value' ),
899 ApiResult
::META_TYPE
=> 'array',
900 ApiResult
::META_KVP_KEY_NAME
=> 'key',
901 ApiResult
::META_PRESERVE_KEYS
=> [ '_baz' ],
903 ApiResult
::META_CONTENT
=> 'content',
904 ApiResult
::META_BC_SUBELEMENTS
=> [ 'bc' ],
909 'Types: Normal transform',
913 'defaultArray' => [ 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ],
914 'defaultAssoc' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
915 'defaultAssoc2' => [ 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
916 'array' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
917 'BCarray' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
918 'BCassoc' => [ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ],
919 'assoc' => [ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
920 'kvp' => [ 'x' => 'a', 'y' => 'b',
921 'z' => [ 'c', ApiResult
::META_TYPE
=> 'array' ],
922 ApiResult
::META_TYPE
=> 'assoc'
924 'BCkvp' => [ 'x' => 'a', 'y' => 'b',
925 ApiResult
::META_TYPE
=> 'assoc',
926 ApiResult
::META_KVP_KEY_NAME
=> 'key',
930 'y' => [ 'b', ApiResult
::META_TYPE
=> 'array' ],
931 'z' => [ 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ],
932 ApiResult
::META_TYPE
=> 'assoc',
933 ApiResult
::META_KVP_MERGE
=> true,
935 'emptyDefault' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ],
936 'emptyAssoc' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
938 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
939 ApiResult
::META_TYPE
=> 'assoc',
943 'Types: AssocAsObject',
945 [ 'Types' => [ 'AssocAsObject' => true ] ],
947 'defaultArray' => [ 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ],
948 'defaultAssoc' => (object)[ 'x' => 'a',
949 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
951 'defaultAssoc2' => (object)[ 2 => 'a', 3 => 'b',
952 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
954 'array' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
955 'BCarray' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
956 'BCassoc' => (object)[ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ],
957 'assoc' => (object)[ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
958 'kvp' => (object)[ 'x' => 'a', 'y' => 'b',
959 'z' => [ 'c', ApiResult
::META_TYPE
=> 'array' ],
960 ApiResult
::META_TYPE
=> 'assoc'
962 'BCkvp' => (object)[ 'x' => 'a', 'y' => 'b',
963 ApiResult
::META_TYPE
=> 'assoc',
964 ApiResult
::META_KVP_KEY_NAME
=> 'key',
966 'kvpmerge' => (object)[
968 'y' => [ 'b', ApiResult
::META_TYPE
=> 'array' ],
969 'z' => (object)[ 'c' => 'd', ApiResult
::META_TYPE
=> 'assoc' ],
970 ApiResult
::META_TYPE
=> 'assoc',
971 ApiResult
::META_KVP_MERGE
=> true,
973 'emptyDefault' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ],
974 'emptyAssoc' => (object)[ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
976 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
977 ApiResult
::META_TYPE
=> 'assoc',
983 [ 'Types' => [ 'ArmorKVP' => 'name' ] ],
985 'defaultArray' => [ 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ],
986 'defaultAssoc' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
987 'defaultAssoc2' => [ 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
988 'array' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
989 'BCarray' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
990 'BCassoc' => [ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ],
991 'assoc' => [ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
993 $kvp( 'name', 'x', 'value', 'a' ),
994 $kvp( 'name', 'y', 'value', 'b' ),
995 $kvp( 'name', 'z', 'value', [ 'c', ApiResult
::META_TYPE
=> 'array' ] ),
996 ApiResult
::META_TYPE
=> 'array'
999 $kvp( 'key', 'x', 'value', 'a' ),
1000 $kvp( 'key', 'y', 'value', 'b' ),
1001 ApiResult
::META_TYPE
=> 'array',
1002 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1005 $kvp( 'name', 'x', 'value', 'a' ),
1006 $kvp( 'name', 'y', 'value', [ 'b', ApiResult
::META_TYPE
=> 'array' ] ),
1010 ApiResult
::META_TYPE
=> 'assoc',
1011 ApiResult
::META_PRESERVE_KEYS
=> [ 'name' ]
1013 ApiResult
::META_TYPE
=> 'array',
1014 ApiResult
::META_KVP_MERGE
=> true,
1016 'emptyDefault' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ],
1017 'emptyAssoc' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
1019 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
1020 ApiResult
::META_TYPE
=> 'assoc',
1024 'Types: ArmorKVP + BC',
1026 [ 'BC' => [], 'Types' => [ 'ArmorKVP' => 'name' ] ],
1028 'defaultArray' => [ 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ],
1029 'defaultAssoc' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1030 'defaultAssoc2' => [ 2 => 'a', 3 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1031 'array' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
1032 'BCarray' => [ 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1033 'BCassoc' => [ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'array' ],
1034 'assoc' => [ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1036 $kvp( 'name', 'x', '*', 'a' ),
1037 $kvp( 'name', 'y', '*', 'b' ),
1038 $kvp( 'name', 'z', '*', [ 'c', ApiResult
::META_TYPE
=> 'array' ] ),
1039 ApiResult
::META_TYPE
=> 'array'
1042 $kvp( 'key', 'x', '*', 'a' ),
1043 $kvp( 'key', 'y', '*', 'b' ),
1044 ApiResult
::META_TYPE
=> 'array',
1045 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1048 $kvp( 'name', 'x', '*', 'a' ),
1049 $kvp( 'name', 'y', '*', [ 'b', ApiResult
::META_TYPE
=> 'array' ] ),
1053 ApiResult
::META_TYPE
=> 'assoc',
1054 ApiResult
::META_PRESERVE_KEYS
=> [ 'name' ] ],
1055 ApiResult
::META_TYPE
=> 'array',
1056 ApiResult
::META_KVP_MERGE
=> true,
1058 'emptyDefault' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ],
1059 'emptyAssoc' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
1061 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
1062 ApiResult
::META_TYPE
=> 'assoc',
1066 'Types: ArmorKVP + AssocAsObject',
1068 [ 'Types' => [ 'ArmorKVP' => 'name', 'AssocAsObject' => true ] ],
1070 'defaultArray' => [ 'b', 'c', 'a', ApiResult
::META_TYPE
=> 'array' ],
1071 'defaultAssoc' => (object)[ 'x' => 'a', 1 => 'b',
1072 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1074 'defaultAssoc2' => (object)[ 2 => 'a', 3 => 'b',
1075 0 => 'c', ApiResult
::META_TYPE
=> 'assoc'
1077 'array' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
1078 'BCarray' => [ 'a', 'c', 'b', ApiResult
::META_TYPE
=> 'array' ],
1079 'BCassoc' => (object)[ 'a', 'b', 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1080 'assoc' => (object)[ 2 => 'a', 0 => 'b', 1 => 'c', ApiResult
::META_TYPE
=> 'assoc' ],
1082 (object)$kvp( 'name', 'x', 'value', 'a' ),
1083 (object)$kvp( 'name', 'y', 'value', 'b' ),
1084 (object)$kvp( 'name', 'z', 'value', [ 'c', ApiResult
::META_TYPE
=> 'array' ] ),
1085 ApiResult
::META_TYPE
=> 'array'
1088 (object)$kvp( 'key', 'x', 'value', 'a' ),
1089 (object)$kvp( 'key', 'y', 'value', 'b' ),
1090 ApiResult
::META_TYPE
=> 'array',
1091 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1094 (object)$kvp( 'name', 'x', 'value', 'a' ),
1095 (object)$kvp( 'name', 'y', 'value', [ 'b', ApiResult
::META_TYPE
=> 'array' ] ),
1099 ApiResult
::META_TYPE
=> 'assoc',
1100 ApiResult
::META_PRESERVE_KEYS
=> [ 'name' ]
1102 ApiResult
::META_TYPE
=> 'array',
1103 ApiResult
::META_KVP_MERGE
=> true,
1105 'emptyDefault' => [ '_dummy' => 1, ApiResult
::META_TYPE
=> 'array' ],
1106 'emptyAssoc' => (object)[ '_dummy' => 1, ApiResult
::META_TYPE
=> 'assoc' ],
1108 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy' ],
1109 ApiResult
::META_TYPE
=> 'assoc',
1113 'Types: BCkvp exception',
1115 ApiResult
::META_TYPE
=> 'BCkvp',
1118 new UnexpectedValueException(
1119 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
1124 'Strip: With ArmorKVP + AssocAsObject transforms',
1126 [ 'Types' => [ 'ArmorKVP' => 'name', 'AssocAsObject' => true ], 'Strip' => 'all' ],
1128 'defaultArray' => [ 'b', 'c', 'a' ],
1129 'defaultAssoc' => (object)[ 'x' => 'a', 1 => 'b', 0 => 'c' ],
1130 'defaultAssoc2' => (object)[ 2 => 'a', 3 => 'b', 0 => 'c' ],
1131 'array' => [ 'a', 'c', 'b' ],
1132 'BCarray' => [ 'a', 'c', 'b' ],
1133 'BCassoc' => (object)[ 'a', 'b', 'c' ],
1134 'assoc' => (object)[ 2 => 'a', 0 => 'b', 1 => 'c' ],
1136 (object)[ 'name' => 'x', 'value' => 'a' ],
1137 (object)[ 'name' => 'y', 'value' => 'b' ],
1138 (object)[ 'name' => 'z', 'value' => [ 'c' ] ],
1141 (object)[ 'key' => 'x', 'value' => 'a' ],
1142 (object)[ 'key' => 'y', 'value' => 'b' ],
1145 (object)[ 'name' => 'x', 'value' => 'a' ],
1146 (object)[ 'name' => 'y', 'value' => [ 'b' ] ],
1147 (object)[ 'name' => 'z', 'c' => 'd' ],
1149 'emptyDefault' => [],
1150 'emptyAssoc' => (object)[],
1158 [ 'Strip' => 'all' ],
1165 '_dummy2' => 'foobaz!',
1171 [ 'Strip' => 'base' ],
1174 'bar' => [ '_dummy' => 'foobaz' ],
1176 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
1177 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1178 ApiResult
::META_PRESERVE_KEYS
=> [ 'foo', 'bar', '_dummy2', 0 ],
1179 ApiResult
::META_TYPE
=> 'array',
1182 '_dummy' => 'foobaz',
1184 '_dummy2' => 'foobaz!',
1190 [ 'Strip' => 'bc' ],
1195 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
1196 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1200 '_dummy2' => 'foobaz!',
1201 ApiResult
::META_SUBELEMENTS
=> [ 'foo', 'bar' ],
1202 ApiResult
::META_INDEXED_TAG_NAME
=> 'itn',
1214 ApiResult
::META_CONTENT
=> 'foo',
1215 ApiResult
::META_PRESERVE_KEYS
=> [ '_dummy2', '_dummy3' ],
1218 'Custom' => [ $this, 'customTransform' ],
1226 'baz' => [ 'a', 'b' ],
1227 '_dummy2' => '_DUMMY2',
1228 '_dummy3' => '_DUMMY3',
1229 ApiResult
::META_CONTENT
=> 'bar',
1236 * Custom transformer for testTransformations
1237 * @param array &$data
1238 * @param array &$metadata
1240 public function customTransform( &$data, &$metadata ) {
1241 // Prevent recursion
1242 if ( isset( $metadata['_added'] ) ) {
1243 $metadata[ApiResult
::META_TYPE
] = 'array';
1247 foreach ( $data as $k => $v ) {
1248 $data[$k] = strtoupper( $k );
1250 $data['baz'] = [ '_added' => 1, 'z' => 'b', 'y' => 'a' ];
1251 $metadata[ApiResult
::META_PRESERVE_KEYS
][0] = '_dummy';
1252 $data[ApiResult
::META_CONTENT
] = 'bar';
1258 public function testAddMetadataToResultVars() {
1263 'sequential_numeric_keys' => [ 'a', 'b', 'c' ],
1264 'non_sequential_numeric_keys' => [ 'a', 'b', 4 => 'c' ],
1269 'object_sequential_keys' => (object)[ 'a', 'b', 'c' ],
1270 '_type' => "should be overwritten in result",
1272 $this->assertSame( [
1273 ApiResult
::META_TYPE
=> 'kvp',
1274 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1275 ApiResult
::META_PRESERVE_KEYS
=> [
1277 'sequential_numeric_keys', 'non_sequential_numeric_keys',
1278 'string_keys', 'object_sequential_keys'
1280 ApiResult
::META_BC_BOOLS
=> [ 'b' ],
1281 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1285 'sequential_numeric_keys' => [
1286 ApiResult
::META_TYPE
=> 'array',
1287 ApiResult
::META_BC_BOOLS
=> [],
1288 ApiResult
::META_INDEXED_TAG_NAME
=> 'value',
1293 'non_sequential_numeric_keys' => [
1294 ApiResult
::META_TYPE
=> 'kvp',
1295 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1296 ApiResult
::META_PRESERVE_KEYS
=> [ 0, 1, 4 ],
1297 ApiResult
::META_BC_BOOLS
=> [],
1298 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1304 ApiResult
::META_TYPE
=> 'kvp',
1305 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1306 ApiResult
::META_PRESERVE_KEYS
=> [ 'one', 'two' ],
1307 ApiResult
::META_BC_BOOLS
=> [],
1308 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1312 'object_sequential_keys' => [
1313 ApiResult
::META_TYPE
=> 'kvp',
1314 ApiResult
::META_KVP_KEY_NAME
=> 'key',
1315 ApiResult
::META_PRESERVE_KEYS
=> [ 0, 1, 2 ],
1316 ApiResult
::META_BC_BOOLS
=> [],
1317 ApiResult
::META_INDEXED_TAG_NAME
=> 'var',
1322 ], ApiResult
::addMetadataToResultVars( $arr ) );
1325 public function testObjectSerialization() {
1327 ApiResult
::setValue( $arr, 'foo', (object)[ 'a' => 1, 'b' => 2 ] );
1328 $this->assertSame( [
1331 ApiResult
::META_TYPE
=> 'assoc',
1335 ApiResult
::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
1336 $this->assertSame( 'Ok', $arr['foo'] );
1339 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
1340 $this->assertSame( 'Ok', $arr['foo'] );
1344 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1345 new ApiResultTestStringifiableObject()
1347 $this->fail( 'Expected exception not thrown' );
1348 } catch ( UnexpectedValueException
$ex ) {
1350 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1351 'returned an object of class ApiResultTestStringifiableObject',
1353 'Expected exception'
1359 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN
) );
1360 $this->fail( 'Expected exception not thrown' );
1361 } catch ( UnexpectedValueException
$ex ) {
1363 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1364 'returned an invalid value: Cannot add non-finite floats to ApiResult',
1366 'Expected exception'
1371 ApiResult
::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1373 'one' => new ApiResultTestStringifiableObject( '1' ),
1374 'two' => new ApiResultTestSerializableObject( 2 ),
1377 $this->assertSame( [
1384 class ApiResultTestStringifiableObject
{
1387 public function __construct( $ret = 'Ok' ) {
1391 public function __toString() {
1396 class ApiResultTestSerializableObject
{
1399 public function __construct( $ret ) {
1403 public function __toString() {
1407 public function serializeForApiResult() {