API: Restore ability for dieStatus() to be passed a non-fatal Status
authorBrad Jorsch <bjorsch@wikimedia.org>
Mon, 12 Jun 2017 16:54:24 +0000 (12:54 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Tue, 13 Jun 2017 14:30:24 +0000 (10:30 -0400)
This ability was accidentally removed in Iae0e2ce3.

Bug: T167690
Change-Id: I79cc9f2f8e75c3cf4e0942d17faafa84955aa020

includes/api/ApiBase.php
tests/phpunit/includes/api/ApiBaseTest.php

index a6c4b2a..5332d7e 100644 (file)
@@ -1863,6 +1863,23 @@ abstract class ApiBase extends ContextSource {
                        throw new MWException( 'Successful status passed to ApiBase::dieStatus' );
                }
 
+               // ApiUsageException needs a fatal status, but this method has
+               // historically accepted any non-good status. Convert it if necessary.
+               $status->setOK( false );
+               if ( !$status->getErrorsByType( 'error' ) ) {
+                       $newStatus = Status::newGood();
+                       foreach ( $status->getErrorsByType( 'warning' ) as $err ) {
+                               call_user_func_array(
+                                       [ $newStatus, 'fatal' ],
+                                       array_merge( [ $err['message'] ], $err['params'] )
+                               );
+                       }
+                       if ( !$newStatus->getErrorsByType( 'error' ) ) {
+                               $newStatus->fatal( 'unknownerror-nocode' );
+                       }
+                       $status = $newStatus;
+               }
+
                throw new ApiUsageException( $this, $status );
        }
 
index 253ac95..ee0ad94 100644 (file)
@@ -174,4 +174,43 @@ class ApiBaseTest extends ApiTestCase {
                ], $user ) );
        }
 
+       /**
+        * @covers ApiBase::dieStatus
+        */
+       public function testDieStatus() {
+               $mock = new MockApi();
+
+               $status = StatusValue::newGood();
+               $status->error( 'foo' );
+               $status->warning( 'bar' );
+               try {
+                       $mock->dieStatus( $status );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'foo' ), 'Exception has "foo"' );
+                       $this->assertFalse( ApiTestCase::apiExceptionHasCode( $ex, 'bar' ), 'Exception has "bar"' );
+               }
+
+               $status = StatusValue::newGood();
+               $status->warning( 'foo' );
+               $status->warning( 'bar' );
+               try {
+                       $mock->dieStatus( $status );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'foo' ), 'Exception has "foo"' );
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'bar' ), 'Exception has "bar"' );
+               }
+
+               $status = StatusValue::newGood();
+               $status->setOk( false );
+               try {
+                       $mock->dieStatus( $status );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( ApiUsageException $ex ) {
+                       $this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'unknownerror-nocode' ),
+                               'Exception has "unknownerror-nocode"' );
+               }
+       }
+
 }