diff --git a/course/externallib.php b/course/externallib.php index 550cc920e24..8344993c085 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -142,16 +142,6 @@ class core_course_external extends external_api { //retrieve the course $course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST); - if ($course->id != SITEID) { - // Check course format exist. - if (!file_exists($CFG->dirroot . '/course/format/' . $course->format . '/lib.php')) { - throw new moodle_exception('cannotgetcoursecontents', 'webservice', '', null, - get_string('courseformatnotfound', 'error', $course->format)); - } else { - require_once($CFG->dirroot . '/course/format/' . $course->format . '/lib.php'); - } - } - // now security checks $context = context_course::instance($course->id, IGNORE_MISSING); try { diff --git a/course/tests/externallib_test.php b/course/tests/externallib_test.php index 79a7c5104be..3c5f18fa616 100644 --- a/course/tests/externallib_test.php +++ b/course/tests/externallib_test.php @@ -1715,6 +1715,23 @@ class externallib_test extends externallib_advanced_testcase { } } + /** + * Test get_course_contents for courses with invalid course format. + */ + public function test_get_course_contents_invalid_format() { + global $DB; + $this->resetAfterTest(); + + list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test(); + + $DB->set_field('course', 'format', 'fakeformat', ['id' => $course->id]); + + // WS should falback to default course format (topics) and avoid exceptions (but debugging will happen). + $result = core_course_external::get_course_contents($course->id); + $this->assertDebuggingCalled(); + $result = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $result); + } + /** * Test duplicate_course */ diff --git a/course/upgrade.txt b/course/upgrade.txt index e1dd6d8ab4d..d6d60e0ddb9 100644 --- a/course/upgrade.txt +++ b/course/upgrade.txt @@ -10,6 +10,7 @@ information provided here is intended especially for developers. * The method `make_categories_options`, deprecated since 3.10, has been removed * External function core_course_external::get_courses_by_field and core_course_external::search_courses now return a field called "courseimage" containing a URL pointing to the course image. +* External function core_course_external::get_course_contents() does not throw exceptions for invalid course formats anymore. === 4.1 === * The function course_modchooser() has been finally deprecated and can not be used anymore. Please use diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt index 7c8d426160e..32eb96d0d18 100644 --- a/lang/en/deprecated.txt +++ b/lang/en/deprecated.txt @@ -90,3 +90,5 @@ studentsperpage,core_grades studentsperpage_help,core_grades type_contentbank,core_plugin type_contentbank_plural,core_plugin +missingversionfile,core_webservice +cannotgetcoursecontents,core_webservice diff --git a/lang/en/webservice.php b/lang/en/webservice.php index 8636e501e5c..a7d88049f16 100644 --- a/lang/en/webservice.php +++ b/lang/en/webservice.php @@ -42,7 +42,6 @@ $string['arguments'] = 'Arguments'; $string['authmethod'] = 'Authentication method'; $string['callablefromajax'] = 'Callable from AJAX'; $string['cannotcreatetoken'] = 'No permission to create web service token for the service {$a}.'; -$string['cannotgetcoursecontents'] = 'Cannot get course contents'; $string['configwebserviceplugins'] = 'For security reasons, only protocols that are in use should be enabled.'; $string['context'] = 'Context'; $string['createservicedescription'] = 'A service is a set of web service functions. You will allow the user to access to a new service. On the Add service page check \'Enable\' and \'Authorised users\' options. Select \'No required capability\'.'; @@ -126,7 +125,6 @@ $string['missingcaps_help'] = 'List of capabilities declared by the service whic $string['missingpassword'] = 'Missing password'; $string['missingrequiredcapability'] = 'The capability {$a} is required.'; $string['missingusername'] = 'Missing username'; -$string['missingversionfile'] = 'Coding error: version.php file is missing for the component {$a}'; $string['nameexists'] = 'This name is already in use by another service'; $string['nocapabilitytouseparameter'] = 'The user does not have the required capability to use the parameter {$a}'; $string['nofunctions'] = 'This service has no functions.'; @@ -235,3 +233,6 @@ $string['wsusername'] = 'Web service username'; // Deprecated since Moodle 3.11. $string['usernameoridnousererror'] = 'No users were found with this username/user id.'; $string['usernameoridoccurenceerror'] = 'More than one user was found with this username. Please enter the user id.'; +// Deprecated since Moodle 4.2. +$string['missingversionfile'] = 'Coding error: version.php file is missing for the component {$a}'; +$string['cannotgetcoursecontents'] = 'Cannot get course contents'; diff --git a/webservice/externallib.php b/webservice/externallib.php index 591debdf9b7..95ec4cbb8d0 100644 --- a/webservice/externallib.php +++ b/webservice/externallib.php @@ -142,9 +142,8 @@ class core_webservice_external extends \core_external\external_api { $version = $componentversions[$function->component]; } } else { - // Function component should always have a version.php, - // otherwise the function should have been described with component => 'moodle'. - throw new moodle_exception('missingversionfile', 'webservice', '', $function->component); + // Ignore this component or plugin, it was probably incorrectly uninstalled. + continue; } } $functioninfo['version'] = $version; diff --git a/webservice/tests/externallib_test.php b/webservice/tests/externallib_test.php index a46a32ec78a..d4f9e425c86 100644 --- a/webservice/tests/externallib_test.php +++ b/webservice/tests/externallib_test.php @@ -208,4 +208,66 @@ class externallib_test extends externallib_advanced_testcase { $this->assertEquals(PHP_INT_MAX, $result['userquota']); } + /** + * Test get_site_info with missing components. + */ + public function test_get_site_missing_components() { + global $USER, $DB; + + $this->resetAfterTest(true); + $this->setAdminUser(); + + // Add a web service and token. + $webservice = new \stdClass(); + $webservice->name = 'Test web service'; + $webservice->enabled = true; + $webservice->restrictedusers = false; + $webservice->component = 'moodle'; + $webservice->timecreated = time(); + $webservice->downloadfiles = true; + $webservice->uploadfiles = true; + $externalserviceid = $DB->insert_record('external_services', $webservice); + + // Add a function to the service (missing plugin). + $DB->insert_record('external_functions', + [ + 'component' => 'mod_random', + 'name' => 'mod_random_get_info' + ] + ); + + // Insert one from missing component. + $DB->insert_record('external_services_functions', + [ + 'externalserviceid' => $externalserviceid, + 'functionname' => 'mod_random_get_info' + ] + ); + // Insert a core one. + $DB->insert_record('external_services_functions', + [ + 'externalserviceid' => $externalserviceid, + 'functionname' => 'core_user_get_users' + ] + ); + + $_POST['wstoken'] = 'testtoken'; + $externaltoken = new \stdClass(); + $externaltoken->token = 'testtoken'; + $externaltoken->tokentype = 0; + $externaltoken->userid = $USER->id; + $externaltoken->externalserviceid = $externalserviceid; + $externaltoken->contextid = 1; + $externaltoken->creatorid = $USER->id; + $externaltoken->timecreated = time(); + $DB->insert_record('external_tokens', $externaltoken); + + // Execution should complete. + $result = \core_webservice_external::get_site_info(); + $result = external_api::clean_returnvalue(\core_webservice_external::get_site_info_returns(), $result); + // Check we ignore the missing component function. + $this->assertCount(1, $result['functions']); + $this->assertEquals('core_user_get_users', $result['functions'][0]['name']); + } + } diff --git a/webservice/upgrade.txt b/webservice/upgrade.txt index 8662cd753ed..5d0bc2bc2d8 100644 --- a/webservice/upgrade.txt +++ b/webservice/upgrade.txt @@ -3,6 +3,10 @@ information provided here is intended especially for developers. This information is intended for authors of webservices, not people writing webservice clients. +=== 4.2 === + +* External function core_webservice_external::get_site_info() does not throw exceptions for missing components anymore. + === 4.1 === * The XMLRPC webservice (protocol) has been completely removed. It's now available in the plugins directory.