/** * Setup test data. */ public function setUp() { $this->resetAfterTest(); $this->setAdminUser(); // Create course and wiki. $this->course = $this->getDataGenerator()->create_course(); course_create_sections_if_missing($this->course, array(1, 2, 3, 4, 5, 6, 7, 8)); }
public function test_create_course_sections() { global $DB; $this->resetAfterTest(true); $course = $this->getDataGenerator()->create_course(array('shortname' => 'GrowingCourse', 'fullname' => 'Growing Course', 'numsections' => 5), array('createsections' => true)); // Ensure all 6 (0-5) sections were created and modinfo/sectioninfo cache works properly $sectionscreated = array_keys(get_fast_modinfo($course)->get_section_info_all()); $this->assertEquals(range(0, $course->numsections), $sectionscreated); // this will do nothing, section already exists $this->assertFalse(course_create_sections_if_missing($course, $course->numsections)); // this will create new section $this->assertTrue(course_create_sections_if_missing($course, $course->numsections + 1)); // Ensure all 7 (0-6) sections were created and modinfo/sectioninfo cache works properly $sectionscreated = array_keys(get_fast_modinfo($course)->get_section_info_all()); $this->assertEquals(range(0, $course->numsections + 1), $sectionscreated); }
/** * course_toc constructor. * @param null $course */ function __construct($course = null) { global $COURSE; if (empty($course)) { $course = $COURSE; } $supportedformats = ['weeks', 'topics']; if (!in_array($course->format, $supportedformats)) { return; } else { $this->formatsupportstoc = true; } $this->format = course_get_format($course); $this->course = $this->format->get_course(); // Has additional fields. course_create_sections_if_missing($course, range(0, $this->course->numsections)); $this->set_modules(); $this->set_chapters(); $this->set_footer(); }
/** * Add a new section with the provided title and (optional) summary * * @return string */ public function addsection_action() { global $CFG, $PAGE, $DB; require_once $CFG->dirroot . '/course/lib.php'; $sectioname = required_param('newsection', PARAM_TEXT); $summary = optional_param('summary', '', PARAM_RAW); require_sesskey(); $courseid = $PAGE->context->get_course_context()->instanceid; $course = course_get_format($courseid)->get_course(); $course->numsections++; course_get_format($course)->update_course_format_options(array('numsections' => $course->numsections)); course_create_sections_if_missing($course, range(0, $course->numsections)); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info($course->numsections, MUST_EXIST); $DB->set_field('course_sections', 'name', $sectioname, array('id' => $section->id)); $DB->set_field('course_sections', 'summary', $summary, array('id' => $section->id)); $DB->set_field('course_sections', 'summaryformat', FORMAT_HTML, array('id' => $section->id)); rebuild_course_cache($course->id); redirect(course_get_url($course, $section->section)); }
/** * Setup the section that is meant to contain the activities added via a given sidebar instance. * * @param object $course The course DB record object * @return object|null An object representing the created section or null on error */ function block_side_bar_create_section($course) { global $CFG, $DB; if (!is_object($course)) { throw new coding_exception('$course must be an object'); } // What is the configured number of sections in this course? $formatoptions = course_get_format($course)->get_format_options(); // Make sure the value we need was actually returned if (!isset($formatoptions['numsections'])) { return null; } // This is what the maximum section number for this course should be. $sectioncount = $formatoptions['numsections']; // This is what the new section number should be if we are simply appending a new section to the course. $sectionnum = $sectioncount + 1; // Check if there are already any "orphaned" sections in this course $sql = "SELECT MAX(section)\n FROM {course_sections}\n WHERE course = :courseid"; $maxsection = $DB->get_field_sql($sql, array('courseid' => $course->id)); // We have orphaned sections in the course so let's just add our new section after the last one if ($maxsection >= $sectionnum) { $sectionnum = $maxsection + 1; } // Just make sure that our section actually exists course_create_sections_if_missing($course->id, $sectionnum); rebuild_course_cache($course->id); // Update the Side Bar section with the required values to make it work $reseturl = new moodle_url('/blocks/side_bar/reset.php?cid=' . $course->id); $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => $sectionnum), 'id, section, name, visible'); $section->name = get_string('sidebar', 'block_side_bar'); $section->summary = get_string('sectionsummary', 'block_side_bar', (string) html_writer::link($reseturl, $reseturl)); $section->summaryformat = FORMAT_HTML; $section->visible = true; $DB->update_record('course_sections', $section); rebuild_course_cache($course->id, true); $sectioninfo = new stdClass(); $sectioninfo->id = $section->id; $sectioninfo->section = $section->section; return $sectioninfo; }
function get_content() { global $USER, $CFG, $DB, $OUTPUT; if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass(); $this->content->items = array(); $this->content->icons = array(); $this->content->footer = ''; if (empty($this->instance)) { return $this->content; } $course = $this->page->course; require_once $CFG->dirroot . '/course/lib.php'; $context = context_course::instance($course->id); $isediting = $this->page->user_is_editing() && has_capability('moodle/course:manageactivities', $context); /// extra fast view mode if (!$isediting) { $modinfo = get_fast_modinfo($course); if (!empty($modinfo->sections[0])) { foreach ($modinfo->sections[0] as $cmid) { $cm = $modinfo->cms[$cmid]; if (!$cm->uservisible) { continue; } if ($cm->indent > 0) { $indent = '<div class="mod-indent mod-indent-' . $cm->indent . '"></div>'; } else { $indent = ''; } if (!empty($cm->url)) { $attrs = array(); $attrs['title'] = $cm->modfullname; $attrs['class'] = $cm->extraclasses . ' activity-action'; if ($cm->onclick) { $attrs['id'] = html_writer::random_id('onclick'); $OUTPUT->add_action_handler(new component_action('click', $cm->onclick), $attrs['id']); } if (!$cm->visible) { $attrs['class'] .= ' dimmed'; } $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />'; $content = html_writer::link($cm->url, $icon . $cm->get_formatted_name(), $attrs); } else { $content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true)); } $this->content->items[] = $indent . html_writer::div($content, 'main-menu-content'); } } return $this->content; } // Slow & hacky editing mode. /** @var core_course_renderer $courserenderer */ $courserenderer = $this->page->get_renderer('core', 'course'); $ismoving = ismoving($course->id); course_create_sections_if_missing($course, 0); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(0); if ($ismoving) { $strmovehere = get_string('movehere'); $strmovefull = strip_tags(get_string('movefull', '', "'{$USER->activitycopyname}'")); $strcancel = get_string('cancel'); $stractivityclipboard = $USER->activitycopyname; } else { $strmove = get_string('move'); } $editbuttons = ''; if ($ismoving) { $this->content->icons[] = '<img src="' . $OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />'; $this->content->items[] = $USER->activitycopyname . ' (<a href="' . $CFG->wwwroot . '/course/mod.php?cancelcopy=true&sesskey=' . sesskey() . '">' . $strcancel . '</a>)'; } if (!empty($modinfo->sections[0])) { $options = array('overflowdiv' => true); foreach ($modinfo->sections[0] as $modnumber) { $mod = $modinfo->cms[$modnumber]; if (!$mod->uservisible) { continue; } if (!$ismoving) { $actions = course_get_cm_edit_actions($mod, $mod->indent); // Prepend list of actions with the 'move' action. $actions = array('move' => new action_menu_link_primary(new moodle_url('/course/mod.php', array('sesskey' => sesskey(), 'copy' => $mod->id)), new pix_icon('t/move', $strmove, 'moodle', array('class' => 'iconsmall', 'title' => '')), $strmove)) + $actions; $editbuttons = html_writer::tag('div', $courserenderer->course_section_cm_edit_actions($actions, $mod, array('donotenhance' => true)), array('class' => 'buttons')); } else { $editbuttons = ''; } if ($mod->visible || has_capability('moodle/course:viewhiddenactivities', $mod->context)) { if ($ismoving) { if ($mod->id == $USER->activitycopy) { continue; } $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?moveto=' . $mod->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } if ($mod->indent > 0) { $indent = '<div class="mod-indent mod-indent-' . $mod->indent . '"></div>'; } else { $indent = ''; } $url = $mod->url; if (!$url) { $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true)); } else { //Accessibility: incidental image - should be empty Alt text $attrs = array(); $attrs['title'] = $mod->modfullname; $attrs['class'] = $mod->extraclasses . ' activity-action'; if ($mod->onclick) { $attrs['id'] = html_writer::random_id('onclick'); $OUTPUT->add_action_handler(new component_action('click', $mod->onclick), $attrs['id']); } if (!$mod->visible) { $attrs['class'] .= ' dimmed'; } $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />'; $content = html_writer::link($url, $icon . $mod->get_formatted_name(), $attrs); } $this->content->items[] = $indent . html_writer::div($content . $editbuttons, 'main-menu-content'); } } } if ($ismoving) { $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?movetosection=' . $section->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } $this->content->footer = $courserenderer->course_section_add_cm_control($course, 0, null, array('inblock' => true)); return $this->content; }
/** * Check that the user can add a module. Also returns some information like the module, context and course section info. * The fucntion create the course section if it doesn't exist. * * @param object $course the course of the module * @param object $modulename the module name * @param object $section the section of the module * @return array list containing module, context, course section. * @throws moodle_exception if user is not allowed to perform the action or module is not allowed in this course */ function can_add_moduleinfo($course, $modulename, $section) { global $DB; $module = $DB->get_record('modules', array('name' => $modulename), '*', MUST_EXIST); $context = context_course::instance($course->id); require_capability('moodle/course:manageactivities', $context); course_create_sections_if_missing($course, $section); $cw = get_fast_modinfo($course)->get_section_info($section); if (!course_allowed_module($course, $module->name)) { print_error('moduledisable'); } return array($module, $context, $cw); }
public function test_available_hook() { global $DB; $this->resetAfterTest(); // Generate a course with two sections (0 and 1) and two modules. Course format is set to 'theunittest'. $generator = $this->getDataGenerator(); $course1 = $generator->create_course(array('format' => 'theunittest')); $this->assertEquals('theunittest', $course1->format); course_create_sections_if_missing($course1, array(0, 1)); $assign0 = $generator->create_module('assign', array('course' => $course1, 'section' => 0)); $assign1 = $generator->create_module('assign', array('course' => $course1, 'section' => 1)); // Enrol student and teacher. $roleids = $DB->get_records_menu('role', null, '', 'shortname, id'); $student = $generator->create_user(); $generator->enrol_user($student->id, $course1->id, $roleids['student']); $teacher = $generator->create_user(); $generator->enrol_user($teacher->id, $course1->id, $roleids['editingteacher']); // Make sure that initially both sections and both modules are available and visible for a student. $modinfostudent = get_fast_modinfo($course1, $student->id); $this->assertTrue($modinfostudent->get_section_info(1)->available); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->available); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->uservisible); $this->assertTrue($modinfostudent->get_cm($assign1->cmid)->available); $this->assertTrue($modinfostudent->get_cm($assign1->cmid)->uservisible); // Set 'hideoddsections' for the course to 1. // Section1 and assign1 will be unavailable, uservisible will be false for student and true for teacher. $data = (object) array('id' => $course1->id, 'hideoddsections' => 1); course_get_format($course1)->update_course_format_options($data); $modinfostudent = get_fast_modinfo($course1, $student->id); $this->assertFalse($modinfostudent->get_section_info(1)->available); $this->assertEmpty($modinfostudent->get_section_info(1)->availableinfo); $this->assertFalse($modinfostudent->get_section_info(1)->uservisible); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->available); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->uservisible); $this->assertFalse($modinfostudent->get_cm($assign1->cmid)->available); $this->assertFalse($modinfostudent->get_cm($assign1->cmid)->uservisible); $modinfoteacher = get_fast_modinfo($course1, $teacher->id); $this->assertFalse($modinfoteacher->get_section_info(1)->available); $this->assertEmpty($modinfoteacher->get_section_info(1)->availableinfo); $this->assertTrue($modinfoteacher->get_section_info(1)->uservisible); $this->assertTrue($modinfoteacher->get_cm($assign0->cmid)->available); $this->assertTrue($modinfoteacher->get_cm($assign0->cmid)->uservisible); $this->assertFalse($modinfoteacher->get_cm($assign1->cmid)->available); $this->assertTrue($modinfoteacher->get_cm($assign1->cmid)->uservisible); // Set 'hideoddsections' for the course to 2. // Section1 and assign1 will be unavailable, uservisible will be false for student and true for teacher. // Property availableinfo will be not empty. $data = (object) array('id' => $course1->id, 'hideoddsections' => 2); course_get_format($course1)->update_course_format_options($data); $modinfostudent = get_fast_modinfo($course1, $student->id); $this->assertFalse($modinfostudent->get_section_info(1)->available); $this->assertNotEmpty($modinfostudent->get_section_info(1)->availableinfo); $this->assertFalse($modinfostudent->get_section_info(1)->uservisible); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->available); $this->assertTrue($modinfostudent->get_cm($assign0->cmid)->uservisible); $this->assertFalse($modinfostudent->get_cm($assign1->cmid)->available); $this->assertFalse($modinfostudent->get_cm($assign1->cmid)->uservisible); $modinfoteacher = get_fast_modinfo($course1, $teacher->id); $this->assertFalse($modinfoteacher->get_section_info(1)->available); $this->assertNotEmpty($modinfoteacher->get_section_info(1)->availableinfo); $this->assertTrue($modinfoteacher->get_section_info(1)->uservisible); $this->assertTrue($modinfoteacher->get_cm($assign0->cmid)->available); $this->assertTrue($modinfoteacher->get_cm($assign0->cmid)->uservisible); $this->assertFalse($modinfoteacher->get_cm($assign1->cmid)->available); $this->assertTrue($modinfoteacher->get_cm($assign1->cmid)->uservisible); }
if ($completion->is_enabled()) { // This value tracks whether there has been a dynamic change to the page. // It is used so that if a user does this - (a) set some tickmarks, (b) // go to another page, (c) clicks Back button - the page will // automatically reload. Otherwise it would start with the wrong tick // values. echo html_writer::start_tag('form', array('action' => '.', 'method' => 'get')); echo html_writer::start_tag('div'); echo html_writer::empty_tag('input', array('type' => 'hidden', 'id' => 'completion_dynamic_change', 'name' => 'completion_dynamic_change', 'value' => '0')); echo html_writer::end_tag('div'); echo html_writer::end_tag('form'); } // Course wrapper start. echo html_writer::start_tag('div', array('class' => 'course-content')); // make sure that section 0 exists (this function will create one if it is missing) course_create_sections_if_missing($course, 0); // get information about course modules and existing module types // format.php in course formats may rely on presence of these variables $modinfo = get_fast_modinfo($course); $modnames = get_module_types_names(); $modnamesplural = get_module_types_names(true); $modnamesused = $modinfo->get_used_module_names(); $mods = $modinfo->get_cms(); $sections = $modinfo->get_section_info_all(); // CAUTION, hacky fundamental variable defintion to follow! // Note that because of the way course fromats are constructed though // inclusion we pass parameters around this way.. $displaysection = $section; // Include the actual course format. require $CFG->dirroot . '/course/format/' . $course->format . '/format.php'; /**
/** * Make sure that current active activity is in section 0 * * All other activities are moved to section 1 that will be displayed as 'Orphaned'. * It may be needed after the course format was changed or activitytype in * course settings has been changed. * * @return null|cm_info current activity */ public function reorder_activities() { course_create_sections_if_missing($this->courseid, array(0, 1)); foreach ($this->get_sections() as $sectionnum => $section) { if ($sectionnum && $section->visible || !$sectionnum && !$section->visible) { // Make sure that 0 section is visible and all others are hidden. set_section_visible($this->courseid, $sectionnum, $sectionnum == 0); } } $modinfo = get_fast_modinfo($this->courseid); // Find the current activity (first activity with the specified type in all course activities). $activitytype = $this->get_activitytype(); $activity = null; if (!empty($activitytype)) { foreach ($modinfo->sections as $sectionnum => $cmlist) { foreach ($cmlist as $cmid) { if ($modinfo->cms[$cmid]->modname === $activitytype) { $activity = $modinfo->cms[$cmid]; break 2; } } } } // Make sure the current activity is in the 0-section. if ($activity && $activity->sectionnum != 0) { moveto_module($activity, $modinfo->get_section_info(0)); // Cache was reset so get modinfo again. $modinfo = get_fast_modinfo($this->courseid); } // Move all other activities into section 1 (the order must be kept). $hasvisibleactivities = false; $firstorphanedcm = null; foreach ($modinfo->sections as $sectionnum => $cmlist) { if ($sectionnum && !empty($cmlist) && $firstorphanedcm === null) { $firstorphanedcm = reset($cmlist); } foreach ($cmlist as $cmid) { if ($sectionnum > 1) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1)); } else { if (!$hasvisibleactivities && $sectionnum == 1 && $modinfo->get_cm($cmid)->visible) { $hasvisibleactivities = true; } } } } if (!empty($modinfo->sections[0])) { foreach ($modinfo->sections[0] as $cmid) { if (!$activity || $cmid != $activity->id) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1), $firstorphanedcm); } } } if ($hasvisibleactivities) { set_section_visible($this->courseid, 1, false); } return $activity; }
// Horrible backwards compatible parameter aliasing.. if ($topic = optional_param('topic', 0, PARAM_INT)) { $url = $PAGE->url; $url->param('section', $topic); debugging('Outdated topic param passed to course/view.php', DEBUG_DEVELOPER); redirect($url); } // End backwards-compatible aliasing.. $context = context_course::instance($course->id); if ($marker >= 0 && has_capability('moodle/course:setcurrentsection', $context) && confirm_sesskey()) { $course->marker = $marker; course_set_marker($course->id, $marker); } // make sure all sections are created $course = course_get_format($course)->get_course(); course_create_sections_if_missing($course, range(0, $course->numsections)); //onetopic format is always multipage $course->realcoursedisplay = $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE; $course->coursedisplay = COURSE_DISPLAY_MULTIPAGE; $renderer = $PAGE->get_renderer('format_onetopic'); $section = optional_param('section', -1, PARAM_INT); if (isset($section) && $section >= 0 && $course->numsections >= $section) { $USER->display[$course->id] = $section; $displaysection = $section; } else { if (isset($USER->display[$course->id]) && $course->numsections >= $USER->display[$course->id]) { $displaysection = $USER->display[$course->id]; } else { $USER->display[$course->id] = 0; $displaysection = 0; }
function get_content() { global $USER, $CFG, $DB, $OUTPUT; if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass(); $this->content->items = array(); $this->content->icons = array(); $this->content->footer = ''; if (empty($this->instance)) { return $this->content; } $course = $this->page->course; require_once $CFG->dirroot . '/course/lib.php'; $context = context_course::instance($course->id); $isediting = $this->page->user_is_editing() && has_capability('moodle/course:manageactivities', $context); /// extra fast view mode if (!$isediting) { $modinfo = get_fast_modinfo($course); if (!empty($modinfo->sections[0])) { $options = array('overflowdiv' => true); foreach ($modinfo->sections[0] as $cmid) { $cm = $modinfo->cms[$cmid]; if (!$cm->uservisible) { continue; } $content = $cm->get_formatted_content(array('overflowdiv' => true, 'noclean' => true)); $instancename = $cm->get_formatted_name(); if (!($url = $cm->get_url())) { $this->content->items[] = $content; $this->content->icons[] = ''; } else { $linkcss = $cm->visible ? '' : ' class="dimmed" '; //Accessibility: incidental image - should be empty Alt text $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />'; $this->content->items[] = '<a title="' . $cm->modplural . '" ' . $linkcss . ' ' . $cm->extra . ' href="' . $url . '">' . $icon . $instancename . '</a>'; } } } return $this->content; } // Slow & hacky editing mode. /** @var core_course_renderer $courserenderer */ $courserenderer = $this->page->get_renderer('core', 'course'); $ismoving = ismoving($course->id); course_create_sections_if_missing($course, 0); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(0); if ($ismoving) { $strmovehere = get_string('movehere'); $strmovefull = strip_tags(get_string('movefull', '', "'{$USER->activitycopyname}'")); $strcancel = get_string('cancel'); $stractivityclipboard = $USER->activitycopyname; } $editbuttons = ''; if ($ismoving) { $this->content->icons[] = '<img src="' . $OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />'; $this->content->items[] = $USER->activitycopyname . ' (<a href="' . $CFG->wwwroot . '/course/mod.php?cancelcopy=true&sesskey=' . sesskey() . '">' . $strcancel . '</a>)'; } if (!empty($modinfo->sections[0])) { $options = array('overflowdiv' => true); foreach ($modinfo->sections[0] as $modnumber) { $mod = $modinfo->cms[$modnumber]; if (!$mod->uservisible) { continue; } if (!$ismoving) { $actions = course_get_cm_edit_actions($mod, -1); $editbuttons = html_writer::tag('div', $courserenderer->course_section_cm_edit_actions($actions, $mod, array('donotenhance' => true)), array('class' => 'buttons')); } else { $editbuttons = ''; } if ($mod->visible || has_capability('moodle/course:viewhiddenactivities', $context)) { if ($ismoving) { if ($mod->id == $USER->activitycopy) { continue; } $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?moveto=' . $mod->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true)); $instancename = $mod->get_formatted_name(); $linkcss = $mod->visible ? '' : ' class="dimmed" '; if (!($url = $mod->get_url())) { $this->content->items[] = $content . $editbuttons; $this->content->icons[] = ''; } else { //Accessibility: incidental image - should be empty Alt text $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />'; $this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra . ' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons; } } } } if ($ismoving) { $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?movetosection=' . $section->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } $this->content->footer = $courserenderer->course_section_add_cm_control($course, 0, null, array('inblock' => true)); return $this->content; }
/** * Create a course and either return a $course object * * Please note this functions does not verify any access control, * the calling code is responsible for all validation (usually it is the form definition). * * @param array $editoroptions course description editor options * @param object $data - all the data needed for an entry in the 'course' table * @return object new course instance */ function create_course($data, $editoroptions = NULL) { global $CFG, $DB; //check the categoryid - must be given for all new courses $category = $DB->get_record('course_categories', array('id' => $data->category), '*', MUST_EXIST); //check if the shortname already exist if (!empty($data->shortname)) { if ($DB->record_exists('course', array('shortname' => $data->shortname))) { throw new moodle_exception('shortnametaken'); } } //check if the id number already exist if (!empty($data->idnumber)) { if ($DB->record_exists('course', array('idnumber' => $data->idnumber))) { throw new moodle_exception('idnumbertaken'); } } $data->timecreated = time(); $data->timemodified = $data->timecreated; // place at beginning of any category $data->sortorder = 0; if ($editoroptions) { // summary text is updated later, we need context to store the files first $data->summary = ''; $data->summary_format = FORMAT_HTML; $data->coursepreview = ''; $data->coursepreview_format = FORMAT_HTML; } if (!isset($data->visible)) { // data not from form, add missing visibility info $data->visible = $category->visible; } $data->visibleold = $data->visible; $newcourseid = $DB->insert_record('course', $data); $context = context_course::instance($newcourseid, MUST_EXIST); if ($editoroptions) { // Save the files used in the summary editor and store $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); $DB->set_field('course', 'summary', $data->summary, array('id' => $newcourseid)); $DB->set_field('course', 'summaryformat', $data->summary_format, array('id' => $newcourseid)); $data = file_postupdate_standard_editor($data, 'coursepreview', $editoroptions, $context, 'course', 'coursepreview', 0); $DB->set_field('course', 'coursepreview', $data->coursepreview, array('id' => $newcourseid)); $DB->set_field('course', 'previewformat', $data->coursepreview_format, array('id' => $newcourseid)); } // update course format options course_get_format($newcourseid)->update_course_format_options($data); $course = course_get_format($newcourseid)->get_course(); // Setup the blocks blocks_add_default_course_blocks($course); // Create a default section. course_create_sections_if_missing($course, 0); fix_course_sortorder(); // new context created - better mark it as dirty mark_context_dirty($context->path); // Save any custom role names. save_local_role_names($course->id, (array) $data); // set up enrolments enrol_course_updated(true, $course, $data); add_to_log(SITEID, 'course', 'new', 'view.php?id=' . $course->id, $data->fullname . ' (ID ' . $course->id . ')'); // Trigger events events_trigger('course_created', $course); return $course; }
function get_content() { global $USER, $CFG, $DB, $OUTPUT; if ($this->content !== NULL) { return $this->content; } $this->content = new stdClass(); $this->content->items = array(); $this->content->icons = array(); $this->content->footer = ''; if (empty($this->instance)) { return $this->content; } $course = $this->page->course; require_once $CFG->dirroot . '/course/lib.php'; $context = context_course::instance($course->id); $isediting = $this->page->user_is_editing() && has_capability('moodle/course:manageactivities', $context); /// extra fast view mode if (!$isediting) { $modinfo = get_fast_modinfo($course); if (!empty($modinfo->sections[0])) { $options = array('overflowdiv' => true); foreach ($modinfo->sections[0] as $cmid) { $cm = $modinfo->cms[$cmid]; if (!$cm->uservisible) { continue; } list($content, $instancename) = get_print_section_cm_text($cm, $course); if (!($url = $cm->get_url())) { $this->content->items[] = $content; $this->content->icons[] = ''; } else { $linkcss = $cm->visible ? '' : ' class="dimmed" '; //Accessibility: incidental image - should be empty Alt text $icon = '<img src="' . $cm->get_icon_url() . '" class="icon" alt="" />'; $this->content->items[] = '<a title="' . $cm->modplural . '" ' . $linkcss . ' ' . $cm->extra . ' href="' . $url . '">' . $icon . $instancename . '</a>'; } } } return $this->content; } /// slow & hacky editing mode $ismoving = ismoving($course->id); course_create_sections_if_missing($course, 0); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(0); $groupbuttons = $course->groupmode; $groupbuttonslink = !$course->groupmodeforce; if ($ismoving) { $strmovehere = get_string('movehere'); $strmovefull = strip_tags(get_string('movefull', '', "'{$USER->activitycopyname}'")); $strcancel = get_string('cancel'); $stractivityclipboard = $USER->activitycopyname; } /// Casting $course->modinfo to string prevents one notice when the field is null $editbuttons = ''; if ($ismoving) { $this->content->icons[] = '<img src="' . $OUTPUT->pix_url('t/move') . '" class="iconsmall" alt="" />'; $this->content->items[] = $USER->activitycopyname . ' (<a href="' . $CFG->wwwroot . '/course/mod.php?cancelcopy=true&sesskey=' . sesskey() . '">' . $strcancel . '</a>)'; } if (!empty($modinfo->sections[0])) { $options = array('overflowdiv' => true); foreach ($modinfo->sections[0] as $modnumber) { $mod = $modinfo->cms[$modnumber]; if (!$mod->uservisible) { continue; } if (!$ismoving) { if ($groupbuttons) { if (!($mod->groupmodelink = $groupbuttonslink)) { $mod->groupmode = $course->groupmode; } } else { $mod->groupmode = false; } $editbuttons = '<div class="buttons">' . make_editing_buttons($mod, true, true) . '</div>'; } else { $editbuttons = ''; } if ($mod->visible || has_capability('moodle/course:viewhiddenactivities', $context)) { if ($ismoving) { if ($mod->id == $USER->activitycopy) { continue; } $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?moveto=' . $mod->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } list($content, $instancename) = get_print_section_cm_text($modinfo->cms[$modnumber], $course); $linkcss = $mod->visible ? '' : ' class="dimmed" '; if (!($url = $mod->get_url())) { $this->content->items[] = $content . $editbuttons; $this->content->icons[] = ''; } else { //Accessibility: incidental image - should be empty Alt text $icon = '<img src="' . $mod->get_icon_url() . '" class="icon" alt="" />'; $this->content->items[] = '<a title="' . $mod->modfullname . '" ' . $linkcss . ' ' . $mod->extra . ' href="' . $url . '">' . $icon . $instancename . '</a>' . $editbuttons; } } } } if ($ismoving) { $this->content->items[] = '<a title="' . $strmovefull . '" href="' . $CFG->wwwroot . '/course/mod.php?movetosection=' . $section->id . '&sesskey=' . sesskey() . '">' . '<img style="height:16px; width:80px; border:0px" src="' . $OUTPUT->pix_url('movehere') . '" alt="' . $strmovehere . '" /></a>'; $this->content->icons[] = ''; } $this->content->footer = print_section_add_menus($course, 0, null, true, true); return $this->content; }
public function test_move_module_in_course() { $this->resetAfterTest(true); // Setup fixture $course = $this->getDataGenerator()->create_course(array('numsections' => 5)); $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); $cms = get_fast_modinfo($course)->get_cms(); $cm = reset($cms); course_create_sections_if_missing($course, 3); $section3 = get_fast_modinfo($course)->get_section_info(3); moveto_module($cm, $section3); $modinfo = get_fast_modinfo($course); $this->assertTrue(empty($modinfo->sections[0])); $this->assertFalse(empty($modinfo->sections[3])); }
$courserenderer = $PAGE->get_renderer('core', 'course'); echo $OUTPUT->header(); /// Print Section or custom info $siteformatoptions = course_get_format($SITE)->get_format_options(); $modinfo = get_fast_modinfo($SITE); $modnames = get_module_types_names(); $modnamesplural = get_module_types_names(true); $modnamesused = $modinfo->get_used_module_names(); $mods = $modinfo->get_cms(); if (!empty($CFG->customfrontpageinclude)) { include $CFG->customfrontpageinclude; } else { if ($siteformatoptions['numsections'] > 0) { if ($editing) { // make sure section with number 1 exists course_create_sections_if_missing($SITE, 1); // re-request modinfo in case section was created $modinfo = get_fast_modinfo($SITE); } $section = $modinfo->get_section_info(1); if ($section && (!empty($modinfo->sections[1]) or !empty($section->summary)) or $editing) { echo $OUTPUT->box_start('generalbox sitetopic'); /// If currently moving a file then show the current clipboard if (ismoving($SITE->id)) { $stractivityclipboard = strip_tags(get_string('activityclipboard', '', $USER->activitycopyname)); echo '<p><font size="2">'; echo "{$stractivityclipboard} (<a href=\"course/mod.php?cancelcopy=true&sesskey=" . sesskey() . "\">" . get_string('cancel') . '</a>)'; echo '</font></p>'; } $context = context_course::instance(SITEID); $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php', $context->id, 'course', 'section', $section->id);
/** * Create a course and either return a $course object * * Please note this functions does not verify any access control, * the calling code is responsible for all validation (usually it is the form definition). * * @param array $editoroptions course description editor options * @param object $data - all the data needed for an entry in the 'course' table * @return object new course instance */ function create_course($data, $editoroptions = NULL) { global $DB; //check the categoryid - must be given for all new courses $category = $DB->get_record('course_categories', array('id' => $data->category), '*', MUST_EXIST); // Check if the shortname already exists. if (!empty($data->shortname)) { if ($DB->record_exists('course', array('shortname' => $data->shortname))) { throw new moodle_exception('shortnametaken', '', '', $data->shortname); } } // Check if the idnumber already exists. if (!empty($data->idnumber)) { if ($DB->record_exists('course', array('idnumber' => $data->idnumber))) { throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber); } } $data->timecreated = time(); $data->timemodified = $data->timecreated; // place at beginning of any category $data->sortorder = 0; if ($editoroptions) { // summary text is updated later, we need context to store the files first $data->summary = ''; $data->summary_format = FORMAT_HTML; } if (!isset($data->visible)) { // data not from form, add missing visibility info $data->visible = $category->visible; } $data->visibleold = $data->visible; $newcourseid = $DB->insert_record('course', $data); $context = context_course::instance($newcourseid, MUST_EXIST); if ($editoroptions) { // Save the files used in the summary editor and store $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); $DB->set_field('course', 'summary', $data->summary, array('id' => $newcourseid)); $DB->set_field('course', 'summaryformat', $data->summary_format, array('id' => $newcourseid)); } if ($overviewfilesoptions = course_overviewfiles_options($newcourseid)) { // Save the course overviewfiles $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0); } // update course format options course_get_format($newcourseid)->update_course_format_options($data); $course = course_get_format($newcourseid)->get_course(); // Setup the blocks blocks_add_default_course_blocks($course); // Create a default section. course_create_sections_if_missing($course, 0); fix_course_sortorder(); // purge appropriate caches in case fix_course_sortorder() did not change anything cache_helper::purge_by_event('changesincourse'); // new context created - better mark it as dirty $context->mark_dirty(); // Save any custom role names. save_local_role_names($course->id, (array) $data); // set up enrolments enrol_course_updated(true, $course, $data); // Trigger a course created event. $event = \core\event\course_created::create(array('objectid' => $course->id, 'context' => context_course::instance($course->id), 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname))); $event->trigger(); return $course; }
/** * Print table of contents for a course * * @Author: Stuart Lamour */ public function print_course_toc() { global $COURSE; // No access to course, return nothing. if (!can_access_course($COURSE)) { return ''; } $format = course_get_format($this->page->course); $course = $format->get_course(); // We don't want to display the toc if the current course is the site. if ($COURSE->id == SITEID) { return; } // If course does not have any sections then exit - it can't be a course without sections!!! if (!isset($course->numsections)) { return; } $singlepage = true; if ($COURSE->format === 'folderview') { $singlepage = false; } $contents = get_string('contents', 'theme_snap'); $o = '<nav id="course-toc"> <div> <h2 id="toc-desktop-menu-heading"> <span class=sr-only>Page</span>' . $contents . '</h2> <form id="toc-search" onSubmit="return false;"> <input id="toc-search-input" type="search" title="' . get_string("search") . '" placeholder="' . get_string("search") . '" aria-autocomplete="list" aria-haspopup="true" aria-activedescendant="toc-search-results" autocomplete="off" /> ' . $this->modulesearch() . ' </form> <a id="toc-mobile-menu-toggle" title="' . $contents . '" href="#course-toc"><i class="icon icon-office-52"></i></a> </div>'; $listlarge = ''; if ($course->numsections > 9) { $listlarge = "list-large"; } $toc = '<ol id="chapters" class="chapters ' . $listlarge . '" start="0">'; course_create_sections_if_missing($course, range(0, $course->numsections)); $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id)); $modinfo = get_fast_modinfo($course); foreach ($modinfo->get_section_info_all() as $section => $thissection) { if ($section > $course->numsections) { continue; } // Students - If course hidden sections completely invisible & section is hidden, and you cannot // see hidden things, bale out. if ($course->hiddensections && !$thissection->visible && !$canviewhidden) { continue; } $linkinfo = ''; $outputlink = true; $conditional = $this->is_section_conditional($thissection); if ($canviewhidden) { // Teachers. if ($conditional) { $linkinfo .= $this->toc_linkinfo(get_string('conditional', 'theme_snap')); } if (!$thissection->visible) { $linkinfo .= $this->toc_linkinfo(get_string('notpublished', 'theme_snap')); } } else { // Students. if ($conditional && $thissection->availableinfo) { // Conditional section, with text explaining conditions. $linkinfo .= $this->toc_linkinfo(get_string('conditional', 'theme_snap')); } if ($conditional && !$thissection->uservisible && !$thissection->availableinfo) { // Conditional section, totally hidden from user so skip. continue; } if (!$conditional && !$thissection->visible) { // Hidden section collapsed, so show as text in TOC. $outputlink = false; // Top trump - if not clickable, replace linkinfo. $linkinfo = $this->toc_linkinfo(get_string('notavailable')); } } /* // fun understanding what all these vars mean // $linkinfo .= $course->hiddensections; // visible - shows on conditionals when not completely hidden if($thissection->visible){ $linkinfo .= " section->visible "; } // uservisible - shows while conditions are met? if($thissection->uservisible){ $linkinfo .= " section->uservisible "; } // available - shown on hidden when 'colapsed' if($thissection->available){ $linkinfo .= " section->available "; } // availability info - shown on conditional when not hidden or met if($thissection->availableinfo){ $linkinfo .= " section->availableinfo "; } */ $sectionstring = get_section_name($course, $section); if ($sectionstring == get_string('general')) { $sectionstring = get_string('introduction', 'theme_snap'); } $sectionclass = ''; $highlight = ''; if (course_get_format($course)->is_section_current($section)) { $sectionclass = 'current'; $highlight = ' <small class=highlight-tag>' . get_string('current', 'theme_snap') . '</small>'; } if ($outputlink) { if ($singlepage) { $url = '#section-' . $section; } else { if ($section > 0) { $url = course_get_url($course, $section, array('navigation' => true, 'sr' => $section)); } else { // We need to create the url for section 0, or a hash will get returned. $url = new moodle_url('/course/view.php', array('id' => $course->id, 'section' => $section)); } } $link = "<a class='{$sectionclass}' href='{$url}'>{$sectionstring}</a>"; } else { $link = "<span class='{$sectionclass}' >{$sectionstring}</a>"; } $progress = $this->toc_progress($thissection, $course); $li = '<li>' . $link . $highlight . $progress . ' ' . $linkinfo . '</li>'; $toc .= $li; } $coursetools = get_string('coursetools', 'theme_snap'); $url = "#coursetools"; if ($COURSE->format == 'folderview') { $url = new moodle_url('/course/view.php', ['id' => $course->id, 'section' => 0], 'coursetools'); } $link = html_writer::link($url, $coursetools); $toc .= "<li>{$link}</li>"; $toc .= "</ol>"; $toc .= "</nav>"; $o .= $toc; return $o; }
/** * Create course section if does not exist yet * @param array|stdClass $record must contain 'course' and 'section' attributes * @param array|null $options * @return stdClass * @throws coding_exception */ public function create_course_section($record = null, array $options = null) { global $DB; $record = (array)$record; if (empty($record['course'])) { throw new coding_exception('course must be present in testing_data_generator::create_course_section() $record'); } if (!isset($record['section'])) { throw new coding_exception('section must be present in testing_data_generator::create_course_section() $record'); } course_create_sections_if_missing($record['course'], $record['section']); return get_fast_modinfo($record['course'])->get_section_info($record['section']); }
/** * Add a new section for a subpage to a course * @param int $courseid Course id to add sections to * @param int $minsection Lowest section number (default, null, uses get_min_section_number()) * @return int new section number */ public static function add_course_section($courseid, $minsection = null) { global $DB, $CFG; require_once $CFG->dirroot . '/course/lib.php'; // For course_create_sections_if_missing(). // Extra condition if the oucontent module (which has similar but simpler, // behaviour) is installed, so they don't tread on each others' toes. $oucontentjoin = ''; $oucontentwhere = ''; if (file_exists($CFG->dirroot . '/mod/oucontent')) { $oucontentjoin = "LEFT JOIN {oucontent} o ON o.course = cs.course AND o.coursesectionid = cs2.id"; $oucontentwhere = "AND o.id IS NULL"; } // Pick a section number. This query finds the first section, // on the course that is at least the minimum number, and does not have, // a used section in the following number, and returns that following, // section number. (This means it can fill up gaps if sections are deleted.) $sql = "\n SELECT cs.section+1 AS num\n FROM {course_sections} cs\n LEFT JOIN {course_sections} cs2 ON cs2.course = cs.course AND cs2.section = cs.section+1\n LEFT JOIN {subpage_sections} ss2 ON ss2.sectionid = cs2.id\n {$oucontentjoin}\n WHERE cs.course = ?\n AND cs.section >= ?\n AND ss2.id IS NULL\n {$oucontentwhere}\n ORDER BY cs.section"; if (is_null($minsection)) { $minsection = self::get_min_section_number($courseid); } $result = $DB->get_records_sql($sql, array($courseid, $minsection), 0, 1); if (count($result) == 0) { // If no existing sections, use the min number. $sectionnum = $minsection; } else { $sectionnum = reset($result)->num; } // Create a section entry with this section number then get it. course_create_sections_if_missing($courseid, $sectionnum); return $sectionnum; }
/** * Create a new section under given parent * * @param int|section_info $parent parent section * @param null|int|section_info $before * @return int */ public function create_new_section($parent = 0, $before = null) { $sections = get_fast_modinfo($this->courseid)->get_section_info_all(); $sectionnums = array_keys($sections); $sectionnum = array_pop($sectionnums) + 1; course_create_sections_if_missing($this->courseid, $sectionnum); $sectionnum = $this->move_section($sectionnum, $parent, $before); return $sectionnum; }
/** * Process the group tag. This defines a Moodle course. * @param string $tagconents The raw contents of the XML element */ function process_group_tag($tagcontents) { global $DB; // Get configs $truncatecoursecodes = $this->get_config('truncatecoursecodes'); $createnewcourses = $this->get_config('createnewcourses'); $createnewcategories = $this->get_config('createnewcategories'); // Process tag contents $group = new stdClass(); if (preg_match('{<sourcedid>.*?<id>(.+?)</id>.*?</sourcedid>}is', $tagcontents, $matches)) { $group->coursecode = trim($matches[1]); } if (preg_match('{<description>.*?<long>(.*?)</long>.*?</description>}is', $tagcontents, $matches)) { $group->long = trim($matches[1]); } if (preg_match('{<description>.*?<short>(.*?)</short>.*?</description>}is', $tagcontents, $matches)) { $group->short = trim($matches[1]); } if (preg_match('{<description>.*?<full>(.*?)</full>.*?</description>}is', $tagcontents, $matches)) { $group->full = trim($matches[1]); } if (preg_match('{<org>.*?<orgunit>(.*?)</orgunit>.*?</org>}is', $tagcontents, $matches)) { $group->category = trim($matches[1]); } $recstatus = $this->get_recstatus($tagcontents, 'group'); //echo "<p>get_recstatus for this group returned $recstatus</p>"; if (!(strlen($group->coursecode) > 0)) { $this->log_line('Error at line ' . $line . ': Unable to find course code in \'group\' element.'); } else { // First, truncate the course code if desired if (intval($truncatecoursecodes) > 0) { $group->coursecode = $truncatecoursecodes > 0 ? substr($group->coursecode, 0, intval($truncatecoursecodes)) : $group->coursecode; } /* -----------Course aliasing is DEACTIVATED until a more general method is in place--------------- // Second, look in the course alias table to see if the code should be translated to something else if($aliases = $DB->get_field('enrol_coursealias', 'toids', array('fromid'=>$group->coursecode))){ $this->log_line("Found alias of course code: Translated $group->coursecode to $aliases"); // Alias is allowed to be a comma-separated list, so let's split it $group->coursecode = explode(',', $aliases); } */ // For compatibility with the (currently inactive) course aliasing, we need this to be an array $group->coursecode = array($group->coursecode); // Third, check if the course(s) exist foreach ($group->coursecode as $coursecode) { $coursecode = trim($coursecode); if (!$DB->get_field('course', 'id', array('idnumber' => $coursecode))) { if (!$createnewcourses) { $this->log_line("Course {$coursecode} not found in Moodle's course idnumbers."); } else { // Create the (hidden) course(s) if not found $courseconfig = get_config('moodlecourse'); // Load Moodle Course shell defaults // New course. $course = new stdClass(); foreach ($this->coursemappings as $courseattr => $imsname) { if ($imsname == 'ignore') { continue; } // Check if the IMS file contains the mapped tag, otherwise fallback on coursecode. if ($imsname == 'coursecode') { $course->{$courseattr} = $coursecode; } else { if (!empty($group->{$imsname})) { $course->{$courseattr} = $group->{$imsname}; } else { $this->log_line('No ' . $imsname . ' description tag found for ' . $coursecode . ' coursecode, using ' . $coursecode . ' instead'); $course->{$courseattr} = $coursecode; } } } $course->idnumber = $coursecode; $course->format = $courseconfig->format; $course->visible = $courseconfig->visible; $course->newsitems = $courseconfig->newsitems; $course->showgrades = $courseconfig->showgrades; $course->showreports = $courseconfig->showreports; $course->maxbytes = $courseconfig->maxbytes; $course->groupmode = $courseconfig->groupmode; $course->groupmodeforce = $courseconfig->groupmodeforce; $course->enablecompletion = $courseconfig->enablecompletion; // Insert default names for teachers/students, from the current language // Handle course categorisation (taken from the group.org.orgunit field if present) if (!empty($group->category)) { // If the category is defined and exists in Moodle, we want to store it in that one if ($catid = $DB->get_field('course_categories', 'id', array('name' => $group->category))) { $course->category = $catid; } else { if ($createnewcategories) { // Else if we're allowed to create new categories, let's create this one $newcat = new stdClass(); $newcat->name = $group->category; $newcat->visible = 0; $catid = $DB->insert_record('course_categories', $newcat); $course->category = $catid; $this->log_line("Created new (hidden) category, #{$catid}: {$newcat->name}"); } else { // If not found and not allowed to create, stick with default $this->log_line('Category ' . $group->category . ' not found in Moodle database, so using default category instead.'); $course->category = $this->get_default_category_id(); } } } else { $course->category = $this->get_default_category_id(); } $course->timecreated = time(); $course->startdate = time(); // Choose a sort order that puts us at the start of the list! $course->sortorder = 0; $courseid = $DB->insert_record('course', $course); // Setup default enrolment plugins $course->id = $courseid; enrol_course_updated(true, $course, null); // Setup the blocks $course = $DB->get_record('course', array('id' => $courseid)); blocks_add_default_course_blocks($course); // Create default 0-section course_create_sections_if_missing($course, 0); add_to_log(SITEID, "course", "new", "view.php?id={$course->id}", "{$course->fullname} (ID {$course->id})"); $this->log_line("Created course {$coursecode} in Moodle (Moodle ID is {$course->id})"); } } else { if ($recstatus == 3 && ($courseid = $DB->get_field('course', 'id', array('idnumber' => $coursecode)))) { // If course does exist, but recstatus==3 (delete), then set the course as hidden $DB->set_field('course', 'visible', '0', array('id' => $courseid)); } } } // End of foreach(coursecode) } }
/** * Tests the get_forum_list() function. This funcion is the meat of the web service but we cannot * check it as a web service so we just call the function. */ public function test_forumlistapi() { global $DB; $this->resetAfterTest(true); // Create course. $record = new stdClass(); $record->shortname = 'testcourse'; $course = self::getDataGenerator()->create_course($record); // Create a teacher user and enrol them onto the course. $record = array(); $record['username'] = '******'; $teacher = self::getDataGenerator()->create_user($record); $roleid = $DB->get_field('role', 'id', array('shortname' => 'teacher')); self::getDataGenerator()->enrol_user($teacher->id, $course->id, $roleid); // Create a student user and enrol them onto the course. $record['username'] = '******'; $student = self::getDataGenerator()->create_user($record); $roleid = $DB->get_field('role', 'id', array('shortname' => 'student')); self::getDataGenerator()->enrol_user($student->id, $course->id, $roleid); // Create forum A. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum A'; $foruma = self::getDataGenerator()->create_module('forumng', $record); // Needed later when moving forums to specific sections. course_create_sections_if_missing($course->id, array(1)); $modinfo = get_fast_modinfo($course); $mod = $modinfo->get_cm($foruma->cmid); $sectionzero = $modinfo->get_section_info(0, MUST_EXIST); $sectionone = $modinfo->get_section_info(1, MUST_EXIST); // Create forum B. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum B'; $forumb = self::getDataGenerator()->create_module('forumng', $record); // Create forum C. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum C'; $forumc = self::getDataGenerator()->create_module('forumng', $record); // Make forum C hidden. set_coursemodule_visible($forumc->cmid, 0); $modinfo = get_fast_modinfo($course); // Move forum A to section 1. $mod = $modinfo->get_cm($foruma->cmid); moveto_module($mod, $sectionone); // Move forum B to section 0. $mod = $modinfo->get_cm($forumb->cmid); moveto_module($mod, $sectionzero); // Move forum C to section 1. $mod = $modinfo->get_cm($forumc->cmid); moveto_module($mod, $sectionone); // Student starts discussion in forum A. $record = new stdClass(); $record->course = $course->id; $record->forum = $foruma->id; $record->userid = $student->id; $this->setUser($student); $discussionid = self::getDataGenerator()->get_plugin_generator('mod_forumng')->create_discussion($record); // Teacher starts discussion in forum B. $record = new stdClass(); $record->course = $course->id; $record->forum = $forumb->id; $record->userid = $teacher->id; $this->setUser($teacher); $discussionid = self::getDataGenerator()->get_plugin_generator('mod_forumng')->create_discussion($record); // Call the web service function to get a list of forums for the teacher. $response = mod_forumng_external::get_forum_list($course->shortname, $teacher->username); // There should be 3 forums in the array. $this->assertEquals(3, count($response)); // Check each forum's data. $this->assertEquals('Forum B', $response[0]->name); $this->assertEquals('n', $response[0]->unread); $this->assertEquals('Forum A', $response[1]->name); $this->assertEquals('y', $response[1]->unread); $this->assertEquals('Forum C', $response[2]->name); $this->assertEquals('n', $response[2]->unread); // Call the web service function to get a list of forums for the student. $response = mod_forumng_external::get_forum_list($course->shortname, $student->username); // There should be 2 forums in the array. $this->assertEquals(2, count($response)); // Check each forum's data. $this->assertEquals('Forum B', $response[0]->name); $this->assertEquals('y', $response[0]->unread); $this->assertEquals('Forum A', $response[1]->name); $this->assertEquals('n', $response[1]->unread); // Call the webservice function with invalid username. $wronguser = '******'; try { // If this does not throw an exception then the test fails. $response = mod_forumng_external::get_forum_list($course->shortname, $wronguser); $this->fail(); } catch (moodle_exception $e) { $this->assertEquals(get_string('cannotfinduser', 'error', $wronguser), $e->errorcode); } // Call the webservice function with invalid course. $wrongcourse = 'doesnotexist'; try { // If this does not throw an exception then the test fails. $response = mod_forumng_external::get_forum_list($wrongcourse, $student->username); $this->fail(); } catch (Exception $e) { $this->assertEquals(get_string('cannotfindcourse', 'error'), $e->errorcode); } }
/** * Validate that the course rollover via link / template sets up the right * data */ public function test_version1importrolloversetscorrectcoursedata() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; // Get initial counts. $initialnumcourses = $DB->count_records('course'); $categoryid = $DB->get_field('course_categories', 'id', array('name' => 'childcategory')); $initialnumcoursesincategory = $DB->get_field('course_categories', 'coursecount', array('id' => $categoryid)); $initialnumforums = $DB->count_records('forum'); // Setup. set_config('backup_general_activities', 1, 'backup'); // Create a test course. $record = new stdClass(); $record->category = $categoryid; $record->shortname = 'rollovertemplateshortname'; $record->fullname = 'rollovertemplatefullname'; $record->id = $DB->insert_record('course', $record); // Make sure we have a section to work with. course_create_sections_if_missing($record, 1); $section = get_fast_modinfo($record)->get_section_info(1); // Create a test forum instance. $forum = new stdClass(); $forum->course = $record->id; $forum->type = 'news'; $forum->name = 'rollovertemplateforum'; $forum->intro = 'rollovertemplateintro'; $forum->id = $DB->insert_record('forum', $forum); // Add it as a course module. $forum->module = $DB->get_field('modules', 'id', array('name' => 'forum')); $forum->instance = $forum->id; $forum->section = $section->id; $cmid = add_course_module($forum); // Run the import. $data = $this->get_core_course_data('childcategory'); $data['shortname'] = 'rollovershortname'; $data['link'] = 'rollovertemplateshortname'; $this->run_core_course_import($data, false); // Validate the number of courses. $this->assertEquals($DB->count_records('course'), $initialnumcourses + 2); // Validate the course course data, as well as category and sortorder. $sortorder = $DB->get_field('course', 'sortorder', array('shortname' => 'rollovertemplateshortname')); $this->assert_record_exists('course', array('shortname' => 'rollovershortname', 'fullname' => 'rlipfullname', 'category' => $categoryid, 'sortorder' => $sortorder - 1)); // Validate that the category is updated with the correct number of courses. $this->assert_record_exists('course_categories', array('id' => $categoryid, 'coursecount' => $initialnumcoursesincategory + 2)); // Validate that the correct number of forum instances exist. $this->assertEquals($DB->count_records('forum'), $initialnumforums + 2); // Validate the specific forum / course module setup within the new course. $sql = "SELECT *\n FROM {modules} m\n JOIN {course_modules} cm ON m.id = cm.module\n JOIN {forum} f ON cm.instance = f.id\n JOIN {course} c ON cm.course = c.id\n JOIN {course_sections} cs ON c.id = cs.course AND cm.section = cs.id\n WHERE f.type = ? AND f.name = ? AND f.intro = ? AND c.shortname = ?"; $exist = $DB->record_exists_sql($sql, array('news', 'rollovertemplateforum', 'rollovertemplateintro', 'rollovershortname')); $this->assertTrue($exist); ini_set('max_execution_time', '0'); }