diff --git a/lib/externallib.php b/lib/externallib.php index c5cd8e7e859..24002e0bc44 100644 --- a/lib/externallib.php +++ b/lib/externallib.php @@ -182,7 +182,7 @@ class external_api { require_once($CFG->libdir . "/pagelib.php"); - $externalfunctioninfo = self::external_function_info($function); + $externalfunctioninfo = static::external_function_info($function); $currentpage = $PAGE; $currentcourse = $COURSE; diff --git a/lib/tests/externallib_test.php b/lib/tests/externallib_test.php index 619ae286a6c..aa8101f3f4e 100644 --- a/lib/tests/externallib_test.php +++ b/lib/tests/externallib_test.php @@ -535,7 +535,7 @@ class core_externallib_testcase extends advanced_testcase { public function test_call_external_function() { - global $PAGE, $COURSE; + global $PAGE, $COURSE, $CFG; $this->resetAfterTest(true); @@ -570,6 +570,16 @@ class core_externallib_testcase extends advanced_testcase { $this->assertSame($beforepage, $PAGE); $this->assertSame($beforecourse, $COURSE); + + // Test a function that triggers a PHP exception. + require_once($CFG->dirroot . '/lib/tests/fixtures/test_external_function_throwable.php'); + + // Call our test function. + $result = test_external_function_throwable::call_external_function('core_throw_exception', array(), false); + + $this->assertTrue($result['error']); + $this->assertArrayHasKey('exception', $result); + $this->assertEquals($result['exception']->message, 'Exception - Modulo by zero'); } /** diff --git a/lib/tests/fixtures/test_external_function_throwable.php b/lib/tests/fixtures/test_external_function_throwable.php new file mode 100644 index 00000000000..b1e975d73ff --- /dev/null +++ b/lib/tests/fixtures/test_external_function_throwable.php @@ -0,0 +1,86 @@ +. + +/** + * An external function that throws an exception, for tests. + * + * @package core + * @category phpunit + * @copyright 2020 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once("$CFG->libdir/externallib.php"); + +/** + * Create an external function that throws an exception, for tests. + * + * @copyright 2020 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class test_external_function_throwable extends external_api { + + /** + * Returns description of throw_exception() parameters. + * + * @return external_function_parameters + */ + public static function throw_exception_parameters() { + return new external_function_parameters(array()); + } + + /** + * Throws a PHP error. + * + * @return array empty array. + */ + public static function throw_exception() { + $a = 1 % 0; + + return array(); + } + + /** + * Returns description of throw_exception() result value. + * + * @return external_description + */ + public static function throw_exception_returns() { + return new external_single_structure(array()); + } + + /** + * Override external_function_info to accept our fake WebService. + */ + public static function external_function_info($function, $strictness=MUST_EXIST) { + if ($function == 'core_throw_exception') { + // Convert it to an object. + $function = new stdClass(); + $function->name = $function; + $function->classname = 'test_external_function_throwable'; + $function->methodname = 'throw_exception'; + $function->classpath = ''; // No need to define class path because current file is already loaded. + $function->component = 'fake'; + $function->capabilities = ''; + $function->services = 'moodle_mobile_app'; + $function->loginrequired = false; + } + + return parent::external_function_info($function, $strictness); + } +}