Separate MediaWiki unit and integration tests
[lhc/web/wiklou.git] / tests / phpunit / unit / includes / api / ApiResultTest.php
1 <?php
2
3 /**
4 * @covers ApiResult
5 * @group API
6 */
7 class ApiResultTest extends \MediaWikiUnitTestCase {
8
9 /**
10 * @covers ApiResult
11 */
12 public function testStaticDataMethods() {
13 $arr = [];
14
15 ApiResult::setValue( $arr, 'setValue', '1' );
16
17 ApiResult::setValue( $arr, null, 'unnamed 1' );
18 ApiResult::setValue( $arr, null, 'unnamed 2' );
19
20 ApiResult::setValue( $arr, 'deleteValue', '2' );
21 ApiResult::unsetValue( $arr, 'deleteValue' );
22
23 ApiResult::setContentValue( $arr, 'setContentValue', '3' );
24
25 $this->assertSame( [
26 'setValue' => '1',
27 'unnamed 1',
28 'unnamed 2',
29 ApiResult::META_CONTENT => 'setContentValue',
30 'setContentValue' => '3',
31 ], $arr );
32
33 try {
34 ApiResult::setValue( $arr, 'setValue', '99' );
35 $this->fail( 'Expected exception not thrown' );
36 } catch ( RuntimeException $ex ) {
37 $this->assertSame(
38 'Attempting to add element setValue=99, existing value is 1',
39 $ex->getMessage(),
40 'Expected exception'
41 );
42 }
43
44 try {
45 ApiResult::setContentValue( $arr, 'setContentValue2', '99' );
46 $this->fail( 'Expected exception not thrown' );
47 } catch ( RuntimeException $ex ) {
48 $this->assertSame(
49 'Attempting to set content element as setContentValue2 when setContentValue ' .
50 'is already set as the content element',
51 $ex->getMessage(),
52 'Expected exception'
53 );
54 }
55
56 ApiResult::setValue( $arr, 'setValue', '99', ApiResult::OVERRIDE );
57 $this->assertSame( '99', $arr['setValue'] );
58
59 ApiResult::setContentValue( $arr, 'setContentValue2', '99', ApiResult::OVERRIDE );
60 $this->assertSame( 'setContentValue2', $arr[ApiResult::META_CONTENT] );
61
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 ) );
69
70 $arr = [];
71 ApiResult::setValue( $arr, 'sub', [ 'foo' => 1 ] );
72 ApiResult::setValue( $arr, 'sub', [ 'bar' => 1 ] );
73 $this->assertSame( [ 'sub' => [ 'foo' => 1, 'bar' => 1 ] ], $arr );
74
75 try {
76 ApiResult::setValue( $arr, 'sub', [ 'foo' => 2, 'baz' => 2 ] );
77 $this->fail( 'Expected exception not thrown' );
78 } catch ( RuntimeException $ex ) {
79 $this->assertSame(
80 'Conflicting keys (foo) when attempting to merge element sub',
81 $ex->getMessage(),
82 'Expected exception'
83 );
84 }
85
86 $arr = [];
87 $title = Title::newFromText( "MediaWiki:Foobar" );
88 $obj = new stdClass;
89 $obj->foo = 1;
90 $obj->bar = 2;
91 ApiResult::setValue( $arr, 'title', $title );
92 ApiResult::setValue( $arr, 'obj', $obj );
93 $this->assertSame( [
94 'title' => (string)$title,
95 'obj' => [ 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ],
96 ], $arr );
97
98 $fh = tmpfile();
99 try {
100 ApiResult::setValue( $arr, 'file', $fh );
101 $this->fail( 'Expected exception not thrown' );
102 } catch ( InvalidArgumentException $ex ) {
103 $this->assertSame(
104 'Cannot add resource(stream) to ApiResult',
105 $ex->getMessage(),
106 'Expected exception'
107 );
108 }
109 try {
110 ApiResult::setValue( $arr, null, $fh );
111 $this->fail( 'Expected exception not thrown' );
112 } catch ( InvalidArgumentException $ex ) {
113 $this->assertSame(
114 'Cannot add resource(stream) to ApiResult',
115 $ex->getMessage(),
116 'Expected exception'
117 );
118 }
119 try {
120 $obj->file = $fh;
121 ApiResult::setValue( $arr, 'sub', $obj );
122 $this->fail( 'Expected exception not thrown' );
123 } catch ( InvalidArgumentException $ex ) {
124 $this->assertSame(
125 'Cannot add resource(stream) to ApiResult',
126 $ex->getMessage(),
127 'Expected exception'
128 );
129 }
130 try {
131 $obj->file = $fh;
132 ApiResult::setValue( $arr, null, $obj );
133 $this->fail( 'Expected exception not thrown' );
134 } catch ( InvalidArgumentException $ex ) {
135 $this->assertSame(
136 'Cannot add resource(stream) to ApiResult',
137 $ex->getMessage(),
138 'Expected exception'
139 );
140 }
141 fclose( $fh );
142
143 try {
144 ApiResult::setValue( $arr, 'inf', INF );
145 $this->fail( 'Expected exception not thrown' );
146 } catch ( InvalidArgumentException $ex ) {
147 $this->assertSame(
148 'Cannot add non-finite floats to ApiResult',
149 $ex->getMessage(),
150 'Expected exception'
151 );
152 }
153 try {
154 ApiResult::setValue( $arr, null, INF );
155 $this->fail( 'Expected exception not thrown' );
156 } catch ( InvalidArgumentException $ex ) {
157 $this->assertSame(
158 'Cannot add non-finite floats to ApiResult',
159 $ex->getMessage(),
160 'Expected exception'
161 );
162 }
163 try {
164 ApiResult::setValue( $arr, 'nan', NAN );
165 $this->fail( 'Expected exception not thrown' );
166 } catch ( InvalidArgumentException $ex ) {
167 $this->assertSame(
168 'Cannot add non-finite floats to ApiResult',
169 $ex->getMessage(),
170 'Expected exception'
171 );
172 }
173 try {
174 ApiResult::setValue( $arr, null, NAN );
175 $this->fail( 'Expected exception not thrown' );
176 } catch ( InvalidArgumentException $ex ) {
177 $this->assertSame(
178 'Cannot add non-finite floats to ApiResult',
179 $ex->getMessage(),
180 'Expected exception'
181 );
182 }
183
184 ApiResult::setValue( $arr, null, NAN, ApiResult::NO_VALIDATE );
185
186 try {
187 ApiResult::setValue( $arr, null, NAN, ApiResult::NO_SIZE_CHECK );
188 $this->fail( 'Expected exception not thrown' );
189 } catch ( InvalidArgumentException $ex ) {
190 $this->assertSame(
191 'Cannot add non-finite floats to ApiResult',
192 $ex->getMessage(),
193 'Expected exception'
194 );
195 }
196
197 $arr = [];
198 $result2 = new ApiResult( 8388608 );
199 $result2->addValue( null, 'foo', 'bar' );
200 ApiResult::setValue( $arr, 'baz', $result2 );
201 $this->assertSame( [
202 'baz' => [
203 ApiResult::META_TYPE => 'assoc',
204 'foo' => 'bar',
205 ]
206 ], $arr );
207
208 $arr = [];
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( [
215 'foo' => "foo\xef\xbf\xbdbar",
216 'bar' => "\xc3\xa1",
217 'baz' => 74,
218 0 => "foo\xef\xbf\xbdbar",
219 1 => "\xc3\xa1",
220 ], $arr );
221
222 $obj = new stdClass;
223 $obj->{'1'} = 'one';
224 $arr = [];
225 ApiResult::setValue( $arr, 'foo', $obj );
226 $this->assertSame( [
227 'foo' => [
228 1 => 'one',
229 ApiResult::META_TYPE => 'assoc',
230 ]
231 ], $arr );
232 }
233
234 /**
235 * @covers ApiResult
236 */
237 public function testInstanceDataMethods() {
238 $result = new ApiResult( 8388608 );
239
240 $result->addValue( null, 'setValue', '1' );
241
242 $result->addValue( null, null, 'unnamed 1' );
243 $result->addValue( null, null, 'unnamed 2' );
244
245 $result->addValue( null, 'deleteValue', '2' );
246 $result->removeValue( null, 'deleteValue' );
247
248 $result->addValue( [ 'a', 'b' ], 'deleteValue', '3' );
249 $result->removeValue( [ 'a', 'b', 'deleteValue' ], null, '3' );
250
251 $result->addContentValue( null, 'setContentValue', '3' );
252
253 $this->assertSame( [
254 'setValue' => '1',
255 'unnamed 1',
256 'unnamed 2',
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() );
263
264 try {
265 $result->addValue( null, 'setValue', '99' );
266 $this->fail( 'Expected exception not thrown' );
267 } catch ( RuntimeException $ex ) {
268 $this->assertSame(
269 'Attempting to add element setValue=99, existing value is 1',
270 $ex->getMessage(),
271 'Expected exception'
272 );
273 }
274
275 try {
276 $result->addContentValue( null, 'setContentValue2', '99' );
277 $this->fail( 'Expected exception not thrown' );
278 } catch ( RuntimeException $ex ) {
279 $this->assertSame(
280 'Attempting to set content element as setContentValue2 when setContentValue ' .
281 'is already set as the content element',
282 $ex->getMessage(),
283 'Expected exception'
284 );
285 }
286
287 $result->addValue( null, 'setValue', '99', ApiResult::OVERRIDE );
288 $this->assertSame( '99', $result->getResultData( [ 'setValue' ] ) );
289
290 $result->addContentValue( null, 'setContentValue2', '99', ApiResult::OVERRIDE );
291 $this->assertSame( 'setContentValue2',
292 $result->getResultData( [ ApiResult::META_CONTENT ] ) );
293
294 $result->reset();
295 $this->assertSame( [
296 ApiResult::META_TYPE => 'assoc',
297 ], $result->getResultData() );
298 $this->assertSame( 0, $result->getSize() );
299
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() ) );
309
310 $result->reset();
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' ] ) ) );
316
317 $result->reset();
318 $result->addValue( null, 'sub', [ 'foo' => 1 ] );
319 $result->addValue( null, 'sub', [ 'bar' => 1 ] );
320 $this->assertSame( [
321 'sub' => [ 'foo' => 1, 'bar' => 1 ],
322 ApiResult::META_TYPE => 'assoc',
323 ], $result->getResultData() );
324
325 try {
326 $result->addValue( null, 'sub', [ 'foo' => 2, 'baz' => 2 ] );
327 $this->fail( 'Expected exception not thrown' );
328 } catch ( RuntimeException $ex ) {
329 $this->assertSame(
330 'Conflicting keys (foo) when attempting to merge element sub',
331 $ex->getMessage(),
332 'Expected exception'
333 );
334 }
335
336 $result->reset();
337 $title = Title::newFromText( "MediaWiki:Foobar" );
338 $obj = new stdClass;
339 $obj->foo = 1;
340 $obj->bar = 2;
341 $result->addValue( null, 'title', $title );
342 $result->addValue( null, 'obj', $obj );
343 $this->assertSame( [
344 'title' => (string)$title,
345 'obj' => [ 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ],
346 ApiResult::META_TYPE => 'assoc',
347 ], $result->getResultData() );
348
349 $fh = tmpfile();
350 try {
351 $result->addValue( null, 'file', $fh );
352 $this->fail( 'Expected exception not thrown' );
353 } catch ( InvalidArgumentException $ex ) {
354 $this->assertSame(
355 'Cannot add resource(stream) to ApiResult',
356 $ex->getMessage(),
357 'Expected exception'
358 );
359 }
360 try {
361 $result->addValue( null, null, $fh );
362 $this->fail( 'Expected exception not thrown' );
363 } catch ( InvalidArgumentException $ex ) {
364 $this->assertSame(
365 'Cannot add resource(stream) to ApiResult',
366 $ex->getMessage(),
367 'Expected exception'
368 );
369 }
370 try {
371 $obj->file = $fh;
372 $result->addValue( null, 'sub', $obj );
373 $this->fail( 'Expected exception not thrown' );
374 } catch ( InvalidArgumentException $ex ) {
375 $this->assertSame(
376 'Cannot add resource(stream) to ApiResult',
377 $ex->getMessage(),
378 'Expected exception'
379 );
380 }
381 try {
382 $obj->file = $fh;
383 $result->addValue( null, null, $obj );
384 $this->fail( 'Expected exception not thrown' );
385 } catch ( InvalidArgumentException $ex ) {
386 $this->assertSame(
387 'Cannot add resource(stream) to ApiResult',
388 $ex->getMessage(),
389 'Expected exception'
390 );
391 }
392 fclose( $fh );
393
394 try {
395 $result->addValue( null, 'inf', INF );
396 $this->fail( 'Expected exception not thrown' );
397 } catch ( InvalidArgumentException $ex ) {
398 $this->assertSame(
399 'Cannot add non-finite floats to ApiResult',
400 $ex->getMessage(),
401 'Expected exception'
402 );
403 }
404 try {
405 $result->addValue( null, null, INF );
406 $this->fail( 'Expected exception not thrown' );
407 } catch ( InvalidArgumentException $ex ) {
408 $this->assertSame(
409 'Cannot add non-finite floats to ApiResult',
410 $ex->getMessage(),
411 'Expected exception'
412 );
413 }
414 try {
415 $result->addValue( null, 'nan', NAN );
416 $this->fail( 'Expected exception not thrown' );
417 } catch ( InvalidArgumentException $ex ) {
418 $this->assertSame(
419 'Cannot add non-finite floats to ApiResult',
420 $ex->getMessage(),
421 'Expected exception'
422 );
423 }
424 try {
425 $result->addValue( null, null, NAN );
426 $this->fail( 'Expected exception not thrown' );
427 } catch ( InvalidArgumentException $ex ) {
428 $this->assertSame(
429 'Cannot add non-finite floats to ApiResult',
430 $ex->getMessage(),
431 'Expected exception'
432 );
433 }
434
435 $result->addValue( null, null, NAN, ApiResult::NO_VALIDATE );
436
437 try {
438 $result->addValue( null, null, NAN, ApiResult::NO_SIZE_CHECK );
439 $this->fail( 'Expected exception not thrown' );
440 } catch ( InvalidArgumentException $ex ) {
441 $this->assertSame(
442 'Cannot add non-finite floats to ApiResult',
443 $ex->getMessage(),
444 'Expected exception'
445 );
446 }
447
448 $result->reset();
449 $result->addParsedLimit( 'foo', 12 );
450 $this->assertSame( [
451 'limits' => [ 'foo' => 12 ],
452 ApiResult::META_TYPE => 'assoc',
453 ], $result->getResultData() );
454 $result->addParsedLimit( 'foo', 13 );
455 $this->assertSame( [
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' ] ) );
461 try {
462 $result->getResultData( [ 'limits', 'foo', 'bar' ] );
463 $this->fail( 'Expected exception not thrown' );
464 } catch ( InvalidArgumentException $ex ) {
465 $this->assertSame(
466 'Path limits.foo is not an array',
467 $ex->getMessage(),
468 'Expected exception'
469 );
470 }
471
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() );
478
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() );
485 $result->reset();
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' ) );
490
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() );
496
497 $result = new ApiResult( 8388608 );
498 $result2 = new ApiResult( 8388608 );
499 $result2->addValue( null, 'foo', 'bar' );
500 $result->addValue( null, 'baz', $result2 );
501 $this->assertSame( [
502 'baz' => [
503 'foo' => 'bar',
504 ApiResult::META_TYPE => 'assoc',
505 ],
506 ApiResult::META_TYPE => 'assoc',
507 ], $result->getResultData() );
508
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" );
515 $this->assertSame( [
516 'foo' => "foo\xef\xbf\xbdbar",
517 'bar' => "\xc3\xa1",
518 'baz' => 74,
519 0 => "foo\xef\xbf\xbdbar",
520 1 => "\xc3\xa1",
521 ApiResult::META_TYPE => 'assoc',
522 ], $result->getResultData() );
523
524 $result = new ApiResult( 8388608 );
525 $obj = new stdClass;
526 $obj->{'1'} = 'one';
527 $arr = [];
528 $result->addValue( $arr, 'foo', $obj );
529 $this->assertSame( [
530 'foo' => [
531 1 => 'one',
532 ApiResult::META_TYPE => 'assoc',
533 ],
534 ApiResult::META_TYPE => 'assoc',
535 ], $result->getResultData() );
536 }
537
538 /**
539 * @covers ApiResult
540 */
541 public function testMetadata() {
542 $arr = [ 'foo' => [ 'bar' => [] ] ];
543 $result = new ApiResult( 8388608 );
544 $result->addValue( null, 'foo', [ 'bar' => [] ] );
545
546 $expect = [
547 'foo' => [
548 'bar' => [
549 ApiResult::META_INDEXED_TAG_NAME => 'ritn',
550 ApiResult::META_TYPE => 'default',
551 ],
552 ApiResult::META_INDEXED_TAG_NAME => 'ritn',
553 ApiResult::META_TYPE => 'default',
554 ],
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',
559 ];
560
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 );
572
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() );
584
585 $arr = [ 'foo' => [ 'bar' => [] ] ];
586 $expect = [
587 'foo' => [
588 'bar' => [
589 ApiResult::META_TYPE => 'kvp',
590 ApiResult::META_KVP_KEY_NAME => 'key',
591 ],
592 ApiResult::META_TYPE => 'kvp',
593 ApiResult::META_KVP_KEY_NAME => 'key',
594 ],
595 ApiResult::META_TYPE => 'BCkvp',
596 ApiResult::META_KVP_KEY_NAME => 'bc',
597 ];
598 ApiResult::setArrayTypeRecursive( $arr, 'kvp', 'key' );
599 ApiResult::setArrayType( $arr, 'BCkvp', 'bc' );
600 $this->assertSame( $expect, $arr );
601 }
602
603 /**
604 * @covers ApiResult
605 */
606 public function testUtilityFunctions() {
607 $arr = [
608 'foo' => [
609 'bar' => [ '_dummy' => 'foobaz' ],
610 'bar2' => (object)[ '_dummy' => 'foobaz' ],
611 'x' => 'ok',
612 '_dummy' => 'foobaz',
613 ],
614 'foo2' => (object)[
615 'bar' => [ '_dummy' => 'foobaz' ],
616 'bar2' => (object)[ '_dummy' => 'foobaz' ],
617 'x' => 'ok',
618 '_dummy' => 'foobaz',
619 ],
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!',
626 ];
627 $this->assertEquals( [
628 'foo' => [
629 'bar' => [],
630 'bar2' => (object)[],
631 'x' => 'ok',
632 ],
633 'foo2' => (object)[
634 'bar' => [],
635 'bar2' => (object)[],
636 'x' => 'ok',
637 ],
638 '_dummy2' => 'foobaz!',
639 ], ApiResult::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
640
641 $metadata = [];
642 $data = ApiResult::stripMetadataNonRecursive( $arr, $metadata );
643 $this->assertEquals( [
644 'foo' => [
645 'bar' => [ '_dummy' => 'foobaz' ],
646 'bar2' => (object)[ '_dummy' => 'foobaz' ],
647 'x' => 'ok',
648 '_dummy' => 'foobaz',
649 ],
650 'foo2' => (object)[
651 'bar' => [ '_dummy' => 'foobaz' ],
652 'bar2' => (object)[ '_dummy' => 'foobaz' ],
653 'x' => 'ok',
654 '_dummy' => 'foobaz',
655 ],
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)' );
665
666 $metadata = null;
667 $data = ApiResult::stripMetadataNonRecursive( (object)$arr, $metadata );
668 $this->assertEquals( (object)[
669 'foo' => [
670 'bar' => [ '_dummy' => 'foobaz' ],
671 'bar2' => (object)[ '_dummy' => 'foobaz' ],
672 'x' => 'ok',
673 '_dummy' => 'foobaz',
674 ],
675 'foo2' => (object)[
676 'bar' => [ '_dummy' => 'foobaz' ],
677 'bar2' => (object)[ '_dummy' => 'foobaz' ],
678 'x' => 'ok',
679 '_dummy' => 'foobaz',
680 ],
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)' );
690 }
691
692 /**
693 * @covers ApiResult
694 * @dataProvider provideTransformations
695 * @param string $label
696 * @param array $input
697 * @param array $transforms
698 * @param array|Exception $expect
699 */
700 public function testTransformations( $label, $input, $transforms, $expect ) {
701 $result = new ApiResult( false );
702 $result->addValue( null, 'test', $input );
703
704 if ( $expect instanceof Exception ) {
705 try {
706 $output = $result->getResultData( 'test', $transforms );
707 $this->fail( 'Expected exception not thrown', $label );
708 } catch ( Exception $ex ) {
709 $this->assertEquals( $ex, $expect, $label );
710 }
711 } else {
712 $output = $result->getResultData( 'test', $transforms );
713 $this->assertEquals( $expect, $output, $label );
714 }
715 }
716
717 public function provideTransformations() {
718 $kvp = function ( $keyKey, $key, $valKey, $value ) {
719 return [
720 $keyKey => $key,
721 $valKey => $value,
722 ApiResult::META_PRESERVE_KEYS => [ $keyKey ],
723 ApiResult::META_CONTENT => $valKey,
724 ApiResult::META_TYPE => 'assoc',
725 ];
726 };
727 $typeArr = [
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',
739 ],
740 'kvpmerge' => [ 'x' => 'a', 'y' => [ 'b' ], 'z' => [ 'c' => 'd' ],
741 ApiResult::META_TYPE => 'kvp',
742 ApiResult::META_KVP_MERGE => true,
743 ],
744 'emptyDefault' => [ '_dummy' => 1 ],
745 'emptyAssoc' => [ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
746 '_dummy' => 1,
747 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
748 ];
749 $stripArr = [
750 'foo' => [
751 'bar' => [ '_dummy' => 'foobaz' ],
752 'baz' => [
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',
757 ],
758 'x' => 'ok',
759 '_dummy' => 'foobaz',
760 ],
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!',
767 ];
768
769 return [
770 [
771 'BC: META_BC_BOOLS',
772 [
773 'BCtrue' => true,
774 'BCfalse' => false,
775 'true' => true,
776 'false' => false,
777 ApiResult::META_BC_BOOLS => [ 0, 'true', 'false' ],
778 ],
779 [ 'BC' => [] ],
780 [
781 'BCtrue' => '',
782 'true' => true,
783 'false' => false,
784 ApiResult::META_BC_BOOLS => [ 0, 'true', 'false' ],
785 ]
786 ],
787 [
788 'BC: META_BC_SUBELEMENTS',
789 [
790 'bc' => 'foo',
791 'nobc' => 'bar',
792 ApiResult::META_BC_SUBELEMENTS => [ 'bc' ],
793 ],
794 [ 'BC' => [] ],
795 [
796 'bc' => [
797 '*' => 'foo',
798 ApiResult::META_CONTENT => '*',
799 ApiResult::META_TYPE => 'assoc',
800 ],
801 'nobc' => 'bar',
802 ApiResult::META_BC_SUBELEMENTS => [ 'bc' ],
803 ],
804 ],
805 [
806 'BC: META_CONTENT',
807 [
808 'content' => '!!!',
809 ApiResult::META_CONTENT => 'content',
810 ],
811 [ 'BC' => [] ],
812 [
813 '*' => '!!!',
814 ApiResult::META_CONTENT => '*',
815 ],
816 ],
817 [
818 'BC: BCkvp type',
819 [
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' ],
826 ],
827 [ 'BC' => [] ],
828 [
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' ],
835 ],
836 ],
837 [
838 'BC: BCarray type',
839 [
840 ApiResult::META_TYPE => 'BCarray',
841 ],
842 [ 'BC' => [] ],
843 [
844 ApiResult::META_TYPE => 'default',
845 ],
846 ],
847 [
848 'BC: BCassoc type',
849 [
850 ApiResult::META_TYPE => 'BCassoc',
851 ],
852 [ 'BC' => [] ],
853 [
854 ApiResult::META_TYPE => 'default',
855 ],
856 ],
857 [
858 'BC: BCkvp exception',
859 [
860 ApiResult::META_TYPE => 'BCkvp',
861 ],
862 [ 'BC' => [] ],
863 new UnexpectedValueException(
864 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
865 ),
866 ],
867 [
868 'BC: nobool, no*, nosub',
869 [
870 'true' => true,
871 'false' => false,
872 'content' => 'content',
873 ApiResult::META_CONTENT => 'content',
874 'bc' => 'foo',
875 ApiResult::META_BC_SUBELEMENTS => [ 'bc' ],
876 'BCarray' => [ ApiResult::META_TYPE => 'BCarray' ],
877 'BCassoc' => [ ApiResult::META_TYPE => 'BCassoc' ],
878 'BCkvp' => [
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' ],
885 ],
886 ],
887 [ 'BC' => [ 'nobool', 'no*', 'nosub' ] ],
888 [
889 'true' => true,
890 'false' => false,
891 'content' => 'content',
892 'bc' => 'foo',
893 'BCarray' => [ ApiResult::META_TYPE => 'default' ],
894 'BCassoc' => [ ApiResult::META_TYPE => 'default' ],
895 'BCkvp' => [
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' ],
902 ],
903 ApiResult::META_CONTENT => 'content',
904 ApiResult::META_BC_SUBELEMENTS => [ 'bc' ],
905 ],
906 ],
907
908 [
909 'Types: Normal transform',
910 $typeArr,
911 [ 'Types' => [] ],
912 [
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'
923 ],
924 'BCkvp' => [ 'x' => 'a', 'y' => 'b',
925 ApiResult::META_TYPE => 'assoc',
926 ApiResult::META_KVP_KEY_NAME => 'key',
927 ],
928 'kvpmerge' => [
929 'x' => 'a',
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,
934 ],
935 'emptyDefault' => [ '_dummy' => 1, ApiResult::META_TYPE => 'array' ],
936 'emptyAssoc' => [ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
937 '_dummy' => 1,
938 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
939 ApiResult::META_TYPE => 'assoc',
940 ],
941 ],
942 [
943 'Types: AssocAsObject',
944 $typeArr,
945 [ 'Types' => [ 'AssocAsObject' => true ] ],
946 (object)[
947 'defaultArray' => [ 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ],
948 'defaultAssoc' => (object)[ 'x' => 'a',
949 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc'
950 ],
951 'defaultAssoc2' => (object)[ 2 => 'a', 3 => 'b',
952 0 => 'c', ApiResult::META_TYPE => 'assoc'
953 ],
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'
961 ],
962 'BCkvp' => (object)[ 'x' => 'a', 'y' => 'b',
963 ApiResult::META_TYPE => 'assoc',
964 ApiResult::META_KVP_KEY_NAME => 'key',
965 ],
966 'kvpmerge' => (object)[
967 'x' => 'a',
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,
972 ],
973 'emptyDefault' => [ '_dummy' => 1, ApiResult::META_TYPE => 'array' ],
974 'emptyAssoc' => (object)[ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
975 '_dummy' => 1,
976 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
977 ApiResult::META_TYPE => 'assoc',
978 ],
979 ],
980 [
981 'Types: ArmorKVP',
982 $typeArr,
983 [ 'Types' => [ 'ArmorKVP' => 'name' ] ],
984 [
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' ],
992 'kvp' => [
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'
997 ],
998 'BCkvp' => [
999 $kvp( 'key', 'x', 'value', 'a' ),
1000 $kvp( 'key', 'y', 'value', 'b' ),
1001 ApiResult::META_TYPE => 'array',
1002 ApiResult::META_KVP_KEY_NAME => 'key',
1003 ],
1004 'kvpmerge' => [
1005 $kvp( 'name', 'x', 'value', 'a' ),
1006 $kvp( 'name', 'y', 'value', [ 'b', ApiResult::META_TYPE => 'array' ] ),
1007 [
1008 'name' => 'z',
1009 'c' => 'd',
1010 ApiResult::META_TYPE => 'assoc',
1011 ApiResult::META_PRESERVE_KEYS => [ 'name' ]
1012 ],
1013 ApiResult::META_TYPE => 'array',
1014 ApiResult::META_KVP_MERGE => true,
1015 ],
1016 'emptyDefault' => [ '_dummy' => 1, ApiResult::META_TYPE => 'array' ],
1017 'emptyAssoc' => [ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
1018 '_dummy' => 1,
1019 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
1020 ApiResult::META_TYPE => 'assoc',
1021 ],
1022 ],
1023 [
1024 'Types: ArmorKVP + BC',
1025 $typeArr,
1026 [ 'BC' => [], 'Types' => [ 'ArmorKVP' => 'name' ] ],
1027 [
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' ],
1035 'kvp' => [
1036 $kvp( 'name', 'x', '*', 'a' ),
1037 $kvp( 'name', 'y', '*', 'b' ),
1038 $kvp( 'name', 'z', '*', [ 'c', ApiResult::META_TYPE => 'array' ] ),
1039 ApiResult::META_TYPE => 'array'
1040 ],
1041 'BCkvp' => [
1042 $kvp( 'key', 'x', '*', 'a' ),
1043 $kvp( 'key', 'y', '*', 'b' ),
1044 ApiResult::META_TYPE => 'array',
1045 ApiResult::META_KVP_KEY_NAME => 'key',
1046 ],
1047 'kvpmerge' => [
1048 $kvp( 'name', 'x', '*', 'a' ),
1049 $kvp( 'name', 'y', '*', [ 'b', ApiResult::META_TYPE => 'array' ] ),
1050 [
1051 'name' => 'z',
1052 'c' => 'd',
1053 ApiResult::META_TYPE => 'assoc',
1054 ApiResult::META_PRESERVE_KEYS => [ 'name' ] ],
1055 ApiResult::META_TYPE => 'array',
1056 ApiResult::META_KVP_MERGE => true,
1057 ],
1058 'emptyDefault' => [ '_dummy' => 1, ApiResult::META_TYPE => 'array' ],
1059 'emptyAssoc' => [ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
1060 '_dummy' => 1,
1061 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
1062 ApiResult::META_TYPE => 'assoc',
1063 ],
1064 ],
1065 [
1066 'Types: ArmorKVP + AssocAsObject',
1067 $typeArr,
1068 [ 'Types' => [ 'ArmorKVP' => 'name', 'AssocAsObject' => true ] ],
1069 (object)[
1070 'defaultArray' => [ 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ],
1071 'defaultAssoc' => (object)[ 'x' => 'a', 1 => 'b',
1072 0 => 'c', ApiResult::META_TYPE => 'assoc'
1073 ],
1074 'defaultAssoc2' => (object)[ 2 => 'a', 3 => 'b',
1075 0 => 'c', ApiResult::META_TYPE => 'assoc'
1076 ],
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' ],
1081 'kvp' => [
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'
1086 ],
1087 'BCkvp' => [
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',
1092 ],
1093 'kvpmerge' => [
1094 (object)$kvp( 'name', 'x', 'value', 'a' ),
1095 (object)$kvp( 'name', 'y', 'value', [ 'b', ApiResult::META_TYPE => 'array' ] ),
1096 (object)[
1097 'name' => 'z',
1098 'c' => 'd',
1099 ApiResult::META_TYPE => 'assoc',
1100 ApiResult::META_PRESERVE_KEYS => [ 'name' ]
1101 ],
1102 ApiResult::META_TYPE => 'array',
1103 ApiResult::META_KVP_MERGE => true,
1104 ],
1105 'emptyDefault' => [ '_dummy' => 1, ApiResult::META_TYPE => 'array' ],
1106 'emptyAssoc' => (object)[ '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ],
1107 '_dummy' => 1,
1108 ApiResult::META_PRESERVE_KEYS => [ '_dummy' ],
1109 ApiResult::META_TYPE => 'assoc',
1110 ],
1111 ],
1112 [
1113 'Types: BCkvp exception',
1114 [
1115 ApiResult::META_TYPE => 'BCkvp',
1116 ],
1117 [ 'Types' => [] ],
1118 new UnexpectedValueException(
1119 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
1120 ),
1121 ],
1122
1123 [
1124 'Strip: With ArmorKVP + AssocAsObject transforms',
1125 $typeArr,
1126 [ 'Types' => [ 'ArmorKVP' => 'name', 'AssocAsObject' => true ], 'Strip' => 'all' ],
1127 (object)[
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' ],
1135 'kvp' => [
1136 (object)[ 'name' => 'x', 'value' => 'a' ],
1137 (object)[ 'name' => 'y', 'value' => 'b' ],
1138 (object)[ 'name' => 'z', 'value' => [ 'c' ] ],
1139 ],
1140 'BCkvp' => [
1141 (object)[ 'key' => 'x', 'value' => 'a' ],
1142 (object)[ 'key' => 'y', 'value' => 'b' ],
1143 ],
1144 'kvpmerge' => [
1145 (object)[ 'name' => 'x', 'value' => 'a' ],
1146 (object)[ 'name' => 'y', 'value' => [ 'b' ] ],
1147 (object)[ 'name' => 'z', 'c' => 'd' ],
1148 ],
1149 'emptyDefault' => [],
1150 'emptyAssoc' => (object)[],
1151 '_dummy' => 1,
1152 ],
1153 ],
1154
1155 [
1156 'Strip: all',
1157 $stripArr,
1158 [ 'Strip' => 'all' ],
1159 [
1160 'foo' => [
1161 'bar' => [],
1162 'baz' => [],
1163 'x' => 'ok',
1164 ],
1165 '_dummy2' => 'foobaz!',
1166 ],
1167 ],
1168 [
1169 'Strip: base',
1170 $stripArr,
1171 [ 'Strip' => 'base' ],
1172 [
1173 'foo' => [
1174 'bar' => [ '_dummy' => 'foobaz' ],
1175 'baz' => [
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',
1180 ],
1181 'x' => 'ok',
1182 '_dummy' => 'foobaz',
1183 ],
1184 '_dummy2' => 'foobaz!',
1185 ],
1186 ],
1187 [
1188 'Strip: bc',
1189 $stripArr,
1190 [ 'Strip' => 'bc' ],
1191 [
1192 'foo' => [
1193 'bar' => [],
1194 'baz' => [
1195 ApiResult::META_SUBELEMENTS => [ 'foo', 'bar' ],
1196 ApiResult::META_INDEXED_TAG_NAME => 'itn',
1197 ],
1198 'x' => 'ok',
1199 ],
1200 '_dummy2' => 'foobaz!',
1201 ApiResult::META_SUBELEMENTS => [ 'foo', 'bar' ],
1202 ApiResult::META_INDEXED_TAG_NAME => 'itn',
1203 ],
1204 ],
1205
1206 [
1207 'Custom transform',
1208 [
1209 'foo' => '?',
1210 'bar' => '?',
1211 '_dummy' => '?',
1212 '_dummy2' => '?',
1213 '_dummy3' => '?',
1214 ApiResult::META_CONTENT => 'foo',
1215 ApiResult::META_PRESERVE_KEYS => [ '_dummy2', '_dummy3' ],
1216 ],
1217 [
1218 'Custom' => [ $this, 'customTransform' ],
1219 'BC' => [],
1220 'Types' => [],
1221 'Strip' => 'all'
1222 ],
1223 [
1224 '*' => 'FOO',
1225 'bar' => 'BAR',
1226 'baz' => [ 'a', 'b' ],
1227 '_dummy2' => '_DUMMY2',
1228 '_dummy3' => '_DUMMY3',
1229 ApiResult::META_CONTENT => 'bar',
1230 ],
1231 ],
1232 ];
1233 }
1234
1235 /**
1236 * Custom transformer for testTransformations
1237 * @param array &$data
1238 * @param array &$metadata
1239 */
1240 public function customTransform( &$data, &$metadata ) {
1241 // Prevent recursion
1242 if ( isset( $metadata['_added'] ) ) {
1243 $metadata[ApiResult::META_TYPE] = 'array';
1244 return;
1245 }
1246
1247 foreach ( $data as $k => $v ) {
1248 $data[$k] = strtoupper( $k );
1249 }
1250 $data['baz'] = [ '_added' => 1, 'z' => 'b', 'y' => 'a' ];
1251 $metadata[ApiResult::META_PRESERVE_KEYS][0] = '_dummy';
1252 $data[ApiResult::META_CONTENT] = 'bar';
1253 }
1254
1255 /**
1256 * @covers ApiResult
1257 */
1258 public function testAddMetadataToResultVars() {
1259 $arr = [
1260 'a' => "foo",
1261 'b' => false,
1262 'c' => 10,
1263 'sequential_numeric_keys' => [ 'a', 'b', 'c' ],
1264 'non_sequential_numeric_keys' => [ 'a', 'b', 4 => 'c' ],
1265 'string_keys' => [
1266 'one' => 1,
1267 'two' => 2
1268 ],
1269 'object_sequential_keys' => (object)[ 'a', 'b', 'c' ],
1270 '_type' => "should be overwritten in result",
1271 ];
1272 $this->assertSame( [
1273 ApiResult::META_TYPE => 'kvp',
1274 ApiResult::META_KVP_KEY_NAME => 'key',
1275 ApiResult::META_PRESERVE_KEYS => [
1276 'a', 'b', 'c',
1277 'sequential_numeric_keys', 'non_sequential_numeric_keys',
1278 'string_keys', 'object_sequential_keys'
1279 ],
1280 ApiResult::META_BC_BOOLS => [ 'b' ],
1281 ApiResult::META_INDEXED_TAG_NAME => 'var',
1282 'a' => "foo",
1283 'b' => false,
1284 'c' => 10,
1285 'sequential_numeric_keys' => [
1286 ApiResult::META_TYPE => 'array',
1287 ApiResult::META_BC_BOOLS => [],
1288 ApiResult::META_INDEXED_TAG_NAME => 'value',
1289 0 => 'a',
1290 1 => 'b',
1291 2 => 'c',
1292 ],
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',
1299 0 => 'a',
1300 1 => 'b',
1301 4 => 'c',
1302 ],
1303 'string_keys' => [
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',
1309 'one' => 1,
1310 'two' => 2,
1311 ],
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',
1318 0 => 'a',
1319 1 => 'b',
1320 2 => 'c',
1321 ],
1322 ], ApiResult::addMetadataToResultVars( $arr ) );
1323 }
1324
1325 public function testObjectSerialization() {
1326 $arr = [];
1327 ApiResult::setValue( $arr, 'foo', (object)[ 'a' => 1, 'b' => 2 ] );
1328 $this->assertSame( [
1329 'a' => 1,
1330 'b' => 2,
1331 ApiResult::META_TYPE => 'assoc',
1332 ], $arr['foo'] );
1333
1334 $arr = [];
1335 ApiResult::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
1336 $this->assertSame( 'Ok', $arr['foo'] );
1337
1338 $arr = [];
1339 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
1340 $this->assertSame( 'Ok', $arr['foo'] );
1341
1342 try {
1343 $arr = [];
1344 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1345 new ApiResultTestStringifiableObject()
1346 ) );
1347 $this->fail( 'Expected exception not thrown' );
1348 } catch ( UnexpectedValueException $ex ) {
1349 $this->assertSame(
1350 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1351 'returned an object of class ApiResultTestStringifiableObject',
1352 $ex->getMessage(),
1353 'Expected exception'
1354 );
1355 }
1356
1357 try {
1358 $arr = [];
1359 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN ) );
1360 $this->fail( 'Expected exception not thrown' );
1361 } catch ( UnexpectedValueException $ex ) {
1362 $this->assertSame(
1363 'ApiResultTestSerializableObject::serializeForApiResult() ' .
1364 'returned an invalid value: Cannot add non-finite floats to ApiResult',
1365 $ex->getMessage(),
1366 'Expected exception'
1367 );
1368 }
1369
1370 $arr = [];
1371 ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
1372 [
1373 'one' => new ApiResultTestStringifiableObject( '1' ),
1374 'two' => new ApiResultTestSerializableObject( 2 ),
1375 ]
1376 ) );
1377 $this->assertSame( [
1378 'one' => '1',
1379 'two' => 2,
1380 ], $arr['foo'] );
1381 }
1382 }
1383
1384 class ApiResultTestStringifiableObject {
1385 private $ret;
1386
1387 public function __construct( $ret = 'Ok' ) {
1388 $this->ret = $ret;
1389 }
1390
1391 public function __toString() {
1392 return $this->ret;
1393 }
1394 }
1395
1396 class ApiResultTestSerializableObject {
1397 private $ret;
1398
1399 public function __construct( $ret ) {
1400 $this->ret = $ret;
1401 }
1402
1403 public function __toString() {
1404 return "Fail";
1405 }
1406
1407 public function serializeForApiResult() {
1408 return $this->ret;
1409 }
1410 }