Merge branch 'MDL-49242-master' of git://github.com/jleyva/moodle

This commit is contained in:
Eloy Lafuente (stronk7) 2015-03-11 00:11:56 +01:00
commit 338de2ed78
2 changed files with 299 additions and 19 deletions

View file

@ -43,6 +43,7 @@ class core_course_external extends external_api {
* Returns description of method parameters
*
* @return external_function_parameters
* @since Moodle 2.9 Options available
* @since Moodle 2.2
*/
public static function get_course_contents_parameters() {
@ -50,10 +51,20 @@ class core_course_external extends external_api {
array('courseid' => new external_value(PARAM_INT, 'course id'),
'options' => new external_multiple_structure (
new external_single_structure(
array('name' => new external_value(PARAM_ALPHANUM, 'option name'),
'value' => new external_value(PARAM_RAW, 'the value of the option, this param is personaly validated in the external function.')
array(
'name' => new external_value(PARAM_ALPHANUM,
'The expected keys (value format) are:
excludemodules (bool) Do not return modules, return only the sections structure
excludecontents (bool) Do not return module contents (i.e: files inside a resource)
sectionid (int) Return only this section
sectionnumber (int) Return only this section with number (order)
cmid (int) Return only this module information (among the whole sections structure)
modname (string) Return only modules with this name "label, forum, etc..."
modid (int) Return only the module with this id (to be used with modname'),
'value' => new external_value(PARAM_RAW, 'the value of the option,
this param is personaly validated in the external function.')
)
), 'Options, not used yet, might be used in later version', VALUE_DEFAULT, array())
), 'Options, used since Moodle 2.9', VALUE_DEFAULT, array())
)
);
}
@ -62,8 +73,9 @@ class core_course_external extends external_api {
* Get course contents
*
* @param int $courseid course id
* @param array $options These options are not used yet, might be used in later version
* @param array $options Options for filtering the results, used since Moodle 2.9
* @return array
* @since Moodle 2.9 Options available
* @since Moodle 2.2
*/
public static function get_course_contents($courseid, $options = array()) {
@ -74,6 +86,45 @@ class core_course_external extends external_api {
$params = self::validate_parameters(self::get_course_contents_parameters(),
array('courseid' => $courseid, 'options' => $options));
$filters = array();
if (!empty($params['options'])) {
foreach ($params['options'] as $option) {
$name = trim($option['name']);
// Avoid duplicated options.
if (!isset($filters[$name])) {
switch ($name) {
case 'excludemodules':
case 'excludecontents':
$value = clean_param($option['value'], PARAM_BOOL);
$filters[$name] = $value;
break;
case 'sectionid':
case 'sectionnumber':
case 'cmid':
case 'modid':
$value = clean_param($option['value'], PARAM_INT);
if (is_numeric($value)) {
$filters[$name] = $value;
} else {
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
}
break;
case 'modname':
$value = clean_param($option['value'], PARAM_PLUGIN);
if ($value) {
$filters[$name] = $value;
} else {
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
}
break;
default:
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
}
}
}
}
//retrieve the course
$course = $DB->get_record('course', array('id' => $params['courseid']), '*', MUST_EXIST);
@ -118,6 +169,27 @@ class core_course_external extends external_api {
continue;
}
// This becomes true when we are filtering and we found the value to filter with.
$sectionfound = false;
// Filter by section id.
if (!empty($filters['sectionid'])) {
if ($section->id != $filters['sectionid']) {
continue;
} else {
$sectionfound = true;
}
}
// Filter by section number. Note that 0 is a valid section number.
if (isset($filters['sectionnumber'])) {
if ($key != $filters['sectionnumber']) {
continue;
} else {
$sectionfound = true;
}
}
// reset $sectioncontents
$sectionvalues = array();
$sectionvalues['id'] = $section->id;
@ -129,7 +201,7 @@ class core_course_external extends external_api {
$sectioncontents = array();
//for each module of the section
if (!empty($modinfosections[$section->section])) {
if (empty($filters['excludemodules']) and !empty($modinfosections[$section->section])) {
foreach ($modinfosections[$section->section] as $cmid) {
$cm = $modinfo->cms[$cmid];
@ -138,6 +210,32 @@ class core_course_external extends external_api {
continue;
}
// This becomes true when we are filtering and we found the value to filter with.
$modfound = false;
// Filter by cmid.
if (!empty($filters['cmid'])) {
if ($cmid != $filters['cmid']) {
continue;
} else {
$modfound = true;
}
}
// Filter by module name and id.
if (!empty($filters['modname'])) {
if ($cm->modname != $filters['modname']) {
continue;
} else if (!empty($filters['modid'])) {
if ($cm->instance != $filters['modid']) {
continue;
} else {
// Note that if we are only filtering by modname we don't break the loop.
$modfound = true;
}
}
}
$module = array();
//common info (for people being able to see the module or availability dates)
@ -177,23 +275,36 @@ class core_course_external extends external_api {
//call $modulename_export_contents
//(each module callback take care about checking the capabilities)
require_once($CFG->dirroot . '/mod/' . $cm->modname . '/lib.php');
$getcontentfunction = $cm->modname.'_export_contents';
if (function_exists($getcontentfunction)) {
if ($contents = $getcontentfunction($cm, $baseurl)) {
if (empty($filters['excludecontents']) and $contents = $getcontentfunction($cm, $baseurl)) {
$module['contents'] = $contents;
} else {
$module['contents'] = array();
}
}
//assign result to $sectioncontents
$sectioncontents[] = $module;
// If we just did a filtering, break the loop.
if ($modfound) {
break;
}
}
}
$sectionvalues['modules'] = $sectioncontents;
// assign result to $coursecontents
$coursecontents[] = $sectionvalues;
// Break the loop if we are filtering.
if ($sectionfound) {
break;
}
}
}
return $coursecontents;

View file

@ -597,11 +597,10 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
}
/**
* Test get_course_contents
* Create a course with contents
* @return array A list with the course object and course modules objects
*/
public function test_get_course_contents() {
$this->resetAfterTest(true);
private function prepare_get_course_contents_test() {
$course = self::getDataGenerator()->create_course();
$forumdescription = 'This is the forum description';
$forum = $this->getDataGenerator()->create_module('forum',
@ -618,20 +617,33 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
'intro' => $labeldescription));
$labelcm = get_coursemodule_from_instance('label', $label->id);
$url = $this->getDataGenerator()->create_module('url', array('course' => $course->id,
'name' => 'URL: % & $ ../'));
'name' => 'URL: % & $ ../', 'section' => 2));
$urlcm = get_coursemodule_from_instance('url', $url->id);
// Set the required capabilities by the external function.
$context = context_course::instance($course->id);
$roleid = $this->assignUserCapability('moodle/course:view', $context->id);
$this->assignUserCapability('moodle/course:update', $context->id, $roleid);
$sections = core_course_external::get_course_contents($course->id, array());
return array($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm);
}
/**
* Test get_course_contents
*/
public function test_get_course_contents() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
$sections = core_course_external::get_course_contents($course->id, array());
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
// Check that forum and label descriptions are correctly returned.
$firstsection = array_pop($sections);
$firstsection = array_shift($sections);
$lastsection = array_pop($sections);
$modinfo = get_fast_modinfo($course);
$testexecuted = 0;
foreach ($firstsection['modules'] as $module) {
@ -653,8 +665,165 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
}
$this->assertEquals(2, $testexecuted);
// Check that the only return section has the 5 created modules
$this->assertEquals(5, count($firstsection['modules']));
// Check that the only return section has the 5 created modules.
$this->assertCount(4, $firstsection['modules']);
$this->assertCount(1, $lastsection['modules']);
try {
$sections = core_course_external::get_course_contents($course->id,
array(array("name" => "invalid", "value" => 1)));
$this->fail('Exception expected due to invalid option.');
} catch (moodle_exception $e) {
$this->assertEquals('errorinvalidparam', $e->errorcode);
}
}
/**
* Test get_course_contents excluding modules
*/
public function test_get_course_contents_excluding_modules() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludemodules", "value" => 1)));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$firstsection = array_shift($sections);
$lastsection = array_pop($sections);
$this->assertEmpty($firstsection['modules']);
$this->assertEmpty($lastsection['modules']);
}
/**
* Test get_course_contents excluding contents
*/
public function test_get_course_contents_excluding_contents() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(array("name" => "excludecontents", "value" => 1)));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
foreach ($sections as $section) {
foreach ($section['modules'] as $module) {
// Only resources return contents.
if (isset($module['contents'])) {
$this->assertEmpty($module['contents']);
}
}
}
}
/**
* Test get_course_contents filtering by section number
*/
public function test_get_course_contents_section_number() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(array("name" => "sectionnumber", "value" => 0)));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$this->assertCount(1, $sections);
$this->assertCount(4, $sections[0]['modules']);
}
/**
* Test get_course_contents filtering by cmid
*/
public function test_get_course_contents_cmid() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(array("name" => "cmid", "value" => $forumcm->id)));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$this->assertCount(2, $sections);
$this->assertCount(1, $sections[0]['modules']);
$this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
}
/**
* Test get_course_contents filtering by cmid and section
*/
public function test_get_course_contents_section_cmid() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(
array("name" => "cmid", "value" => $forumcm->id),
array("name" => "sectionnumber", "value" => 0)
));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$this->assertCount(1, $sections);
$this->assertCount(1, $sections[0]['modules']);
$this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
}
/**
* Test get_course_contents filtering by modname
*/
public function test_get_course_contents_modname() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(array("name" => "modname", "value" => "forum")));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$this->assertCount(2, $sections);
$this->assertCount(1, $sections[0]['modules']);
$this->assertEquals($forumcm->id, $sections[0]['modules'][0]["id"]);
}
/**
* Test get_course_contents filtering by modname
*/
public function test_get_course_contents_modid() {
$this->resetAfterTest(true);
list($course, $forumcm, $datacm, $pagecm, $labelcm, $urlcm) = $this->prepare_get_course_contents_test();
// Test exclude modules.
$sections = core_course_external::get_course_contents($course->id, array(
array("name" => "modname", "value" => "page"),
array("name" => "modid", "value" => $pagecm->instance),
));
// We need to execute the return values cleaning process to simulate the web service server.
$sections = external_api::clean_returnvalue(core_course_external::get_course_contents_returns(), $sections);
$this->assertCount(2, $sections);
$this->assertCount(1, $sections[0]['modules']);
$this->assertEquals("page", $sections[0]['modules'][0]["modname"]);
$this->assertEquals($pagecm->instance, $sections[0]['modules'][0]["instance"]);
}
/**