function moodleform_mod($current, $section, $cm, $course) { global $CFG; $this->current = $current; $this->_instance = $current->instance; $this->_section = $section; $this->_cm = $cm; if ($this->_cm) { $this->context = context_module::instance($this->_cm->id); } else { $this->context = context_course::instance($course->id); } // Set the course format. require_once $CFG->dirroot . '/course/format/lib.php'; $this->courseformat = course_get_format($course); // Guess module name $matches = array(); if (!preg_match('/^mod_([^_]+)_mod_form$/', get_class($this), $matches)) { debugging('Use $modname parameter or rename form to mod_xx_mod_form, where xx is name of your module'); print_error('unknownmodulename'); } $this->_modname = $matches[1]; $this->init_features(); parent::moodleform('modedit.php'); }
/** * Constructor method, calls the parent constructor - MDL-21097 * * @param moodle_page $page * @param string $target one of rendering target constants */ public function __construct(moodle_page $page, $target) { parent::__construct($page, $target); $this->courseformat = course_get_format($page->course); $this->settings = $this->courseformat->get_settings(); /* Since format_grid_renderer::section_edit_controls() only displays the 'Set current section' control when editing mode is on we need to be sure that the link 'Turn editing mode on' is available for a user who does not have any other managing capability. */ $page->set_other_editing_capability('moodle/course:setcurrentsection'); }
/** * Generate the content to displayed on the left part of a section * before course modules are included * * @param stdClass $section The course_section entry from DB * @param stdClass $course The course entry from DB * @param bool $onsectionpage true if being printed on a section page * @return string HTML to output. */ protected function section_left_content($section, $course, $onsectionpage) { $o = $this->output->spacer(); if ($section->section != 0) { // Only in the non-general sections. if (course_get_format($course)->is_section_current($section)) { $o .= get_accesshide(get_string('currentsection', 'format_' . $course->format)); } } return $o; }
/** * Contructor * @param $course object The pre-defined course object. * Passed by reference, so that extended info can be added. * */ function course_format(&$course) { if (empty($this->course) && is_object($course)) { $this->course = clone $course; } $courseformatoptions = course_get_format($course)->get_format_options(); $this->course->numsections = $courseformatoptions['numsections']; //$course->hiddensections = $courseformatoptions['hiddensections']; //$course->coursedisplay = $courseformatoptions['coursedisplay']; /// Method should load any other course data into the course property. $this->get_course(); }
/** * Constructor method, calls the parent constructor - MDL-21097 * * @param moodle_page $page * @param string $target one of rendering target constants */ public function __construct(moodle_page $page, $target) { parent::__construct($page, $target); $this->togglelib = new topcoll_togglelib(); $this->courseformat = course_get_format($page->course); // Needed for collapsed topics settings retrieval. /* Since format_topcoll_renderer::section_edit_controls() only displays the 'Set current section' control when editing mode is on we need to be sure that the link 'Turn editing mode on' is available for a user who does not have any other managing capability. */ $page->set_other_editing_capability('moodle/course:setcurrentsection'); global $PAGE; $this->userisediting = $PAGE->user_is_editing(); $this->tctoggleiconsize = clean_param(get_config('format_topcoll', 'defaulttoggleiconsize'), PARAM_TEXT); }
public function test_update_course_numsections() { global $DB; $this->resetAfterTest(true); $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 10, 'format' => 'topics'), array('createsections' => true)); $generator->create_module('assign', array('course' => $course, 'section' => 7)); $this->setAdminUser(); $this->assertEquals(11, $DB->count_records('course_sections', array('course' => $course->id))); // Change the numsections to 8, last two sections did not have any activities, they should be deleted. update_course((object) array('id' => $course->id, 'numsections' => 8)); $this->assertEquals(9, $DB->count_records('course_sections', array('course' => $course->id))); $this->assertEquals(9, count(get_fast_modinfo($course)->get_section_info_all())); // Change the numsections to 5, section 8 should be deleted but section 7 should remain as it has activities. update_course((object) array('id' => $course->id, 'numsections' => 6)); $this->assertEquals(8, $DB->count_records('course_sections', array('course' => $course->id))); $this->assertEquals(8, count(get_fast_modinfo($course)->get_section_info_all())); $this->assertEquals(6, course_get_format($course)->get_course()->numsections); }
/** * Returns a form element for this rule. * * @param string $basename The form element base name. * @return string */ public function get_form($basename) { global $COURSE; $options = array(); $modinfo = get_fast_modinfo($this->courseid); $courseformat = course_get_format($this->courseid); foreach ($modinfo->get_sections() as $sectionnum => $cmids) { $modules = array(); foreach ($cmids as $cmid) { $cm = $modinfo->get_cm($cmid); $modules[$cm->context->id] = $cm->name; } $options[] = array($courseformat->get_section_name($sectionnum) => $modules); } $o = block_xp_rule::get_form($basename); $modules = html_writer::select($options, $basename . '[value]', $this->value, '', array('id' => '', 'class' => '')); $o .= get_string('activityoresourceis', 'block_xp', $modules); return $o; }
/** * 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(); }
private function delete_displayed_images() { global $CFG, $DB; /* We only process this information if the course we are backing up is in the 'grid' format (target format can change depending of restore options). Note: This appears to be a bit silly as this code is executed even if the course is not in the 'grid' format. */ $courseid = $this->task->get_courseid(); $format = $DB->get_field('course', 'format', array('id' => $courseid)); if ($format != 'grid') { return; } require_once $CFG->dirroot . '/course/format/lib.php'; // For format_base. require_once $CFG->dirroot . '/course/format/grid/lib.php'; // For format_grid. $courseformat = course_get_format($courseid); $courseformat->delete_displayed_images(); }
/** * 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)); }
/** * Displays the activities list in cases when course view page is not * redirected to the activity page. * * @param stdClass $course record from table course * @param bool $orphaned if false displays the main activity (if present) * if true displays all other activities */ public function display($course, $orphaned) { $courserenderer = $this->page->get_renderer('core', 'course'); $output = ''; $modinfo = get_fast_modinfo($course); if ($orphaned) { if (!empty($modinfo->sections[1])) { $output .= $this->output->heading(get_string('orphaned', 'format_singleactivity'), 3, 'sectionname'); $output .= $this->output->box(get_string('orphanedwarning', 'format_singleactivity')); $output .= $courserenderer->course_section_cm_list($course, 1, 1); } } else { $output .= $courserenderer->course_section_cm_list($course, 0, 0); if (empty($modinfo->sections[0]) && course_get_format($course)->activity_has_subtypes()) { // Course format was unable to automatically redirect to add module page. $output .= $courserenderer->course_section_add_cm_control($course, 0, 0); } } return $output; }
/** * Process the 'plugin_format_topcoll_course' element within the 'course' element in the 'course.xml' file in the * '/course' folder of the zipped backup 'mbz' file. */ public function process_topcoll($data) { global $DB; $data = (object) $data; // We only process this information if the course we are restoring to // has 'topcoll' format (target format can change depending of restore options). $format = $DB->get_field('course', 'format', array('id' => $this->task->get_courseid())); if ($format != 'topcoll') { return; } $data->courseid = $this->task->get_courseid(); if (!($course = $DB->get_record('course', array('id' => $data->courseid)))) { print_error('invalidcourseid', 'error'); } // From /course/view.php. $courseformat = course_get_format($course); if (empty($data->layoutcolumns)) { // Cope with backups from Moodle 2.0, 2.1 and 2.2 versions. $data->layoutcolumns = get_config('format_topcoll', 'defaultlayoutcolumns'); } $courseformat->restore_topcoll_setting($data->courseid, $data->layoutelement, $data->layoutstructure, $data->layoutcolumns, $data->tgfgcolour, $data->tgbgcolour, $data->tgbghvrcolour); // No need to annotate anything here. }
// Must set layout before gettting section info. See MDL-47555. $PAGE->set_pagelayout('course'); if ($section and $section > 0) { // Get section details and check it exists. $modinfo = get_fast_modinfo($course); $coursesections = $modinfo->get_section_info($section, MUST_EXIST); // Check user is allowed to see it. if (!$coursesections->uservisible) { // Note: We actually already know they don't have this capability // or uservisible would have been true; this is just to get the // correct error message shown. require_capability('moodle/course:viewhiddensections', $context); } } // Fix course format if it is no longer installed $course->format = course_get_format($course)->get_format(); $PAGE->set_pagetype('course-view-' . $course->format); $PAGE->set_other_editing_capability('moodle/course:update'); $PAGE->set_other_editing_capability('moodle/course:manageactivities'); $PAGE->set_other_editing_capability('moodle/course:activityvisibility'); if (course_format_uses_sections($course->format)) { $PAGE->set_other_editing_capability('moodle/course:sectionvisibility'); $PAGE->set_other_editing_capability('moodle/course:movesections'); } // Preload course format renderer before output starts. // This is a little hacky but necessary since // format.php is not included until after output starts if (file_exists($CFG->dirroot . '/course/format/' . $course->format . '/renderer.php')) { require_once $CFG->dirroot . '/course/format/' . $course->format . '/renderer.php'; if (class_exists('format_' . $course->format . '_renderer')) { // call get_renderer only if renderer is defined in format plugin
/** * Generates an array of sections and an array of activities for the given course. * * This method uses the cache to improve performance and avoid the get_fast_modinfo call * * @param stdClass $course * @return array Array($sections, $activities) */ protected function generate_sections_and_activities(stdClass $course) { global $CFG; require_once $CFG->dirroot . '/course/lib.php'; $modinfo = get_fast_modinfo($course); $sections = $modinfo->get_section_info_all(); // For course formats using 'numsections' trim the sections list $courseformatoptions = course_get_format($course)->get_format_options(); if (isset($courseformatoptions['numsections'])) { $sections = array_slice($sections, 0, $courseformatoptions['numsections'] + 1, true); } $activities = array(); foreach ($sections as $key => $section) { // Clone and unset summary to prevent $SESSION bloat (MDL-31802). $sections[$key] = clone $section; unset($sections[$key]->summary); $sections[$key]->hasactivites = false; if (!array_key_exists($section->section, $modinfo->sections)) { continue; } foreach ($modinfo->sections[$section->section] as $cmid) { $cm = $modinfo->cms[$cmid]; $activity = new stdClass(); $activity->id = $cm->id; $activity->course = $course->id; $activity->section = $section->section; $activity->name = $cm->name; $activity->icon = $cm->icon; $activity->iconcomponent = $cm->iconcomponent; $activity->hidden = !$cm->visible; $activity->modname = $cm->modname; $activity->nodetype = navigation_node::NODETYPE_LEAF; $activity->onclick = $cm->onclick; $url = $cm->url; if (!$url) { $activity->url = null; $activity->display = false; } else { $activity->url = $url->out(); $activity->display = $cm->uservisible ? true : false; if (self::module_extends_navigation($cm->modname)) { $activity->nodetype = navigation_node::NODETYPE_BRANCH; } } $activities[$cmid] = $activity; if ($activity->display) { $sections[$key]->hasactivites = true; } } } return array($sections, $activities); }
/** * Update courses * * @param array $courses * @since Moodle 2.5 */ public static function update_courses($courses) { global $CFG, $DB; require_once($CFG->dirroot . "/course/lib.php"); $warnings = array(); $params = self::validate_parameters(self::update_courses_parameters(), array('courses' => $courses)); $availablethemes = core_component::get_plugin_list('theme'); $availablelangs = get_string_manager()->get_list_of_translations(); foreach ($params['courses'] as $course) { // Catch any exception while updating course and return as warning to user. try { // Ensure the current user is allowed to run this function. $context = context_course::instance($course['id'], MUST_EXIST); self::validate_context($context); $oldcourse = course_get_format($course['id'])->get_course(); require_capability('moodle/course:update', $context); // Check if user can change category. if (array_key_exists('categoryid', $course) && ($oldcourse->category != $course['categoryid'])) { require_capability('moodle/course:changecategory', $context); $course['category'] = $course['categoryid']; } // Check if the user can change fullname. if (array_key_exists('fullname', $course) && ($oldcourse->fullname != $course['fullname'])) { require_capability('moodle/course:changefullname', $context); } // Check if the user can change shortname. if (array_key_exists('shortname', $course) && ($oldcourse->shortname != $course['shortname'])) { require_capability('moodle/course:changeshortname', $context); } // Check if the user can change the idnumber. if (array_key_exists('idnumber', $course) && ($oldcourse->idnumber != $course['idnumber'])) { require_capability('moodle/course:changeidnumber', $context); } // Check if user can change summary. if (array_key_exists('summary', $course) && ($oldcourse->summary != $course['summary'])) { require_capability('moodle/course:changesummary', $context); } // Summary format. if (array_key_exists('summaryformat', $course) && ($oldcourse->summaryformat != $course['summaryformat'])) { require_capability('moodle/course:changesummary', $context); $course['summaryformat'] = external_validate_format($course['summaryformat']); } // Check if user can change visibility. if (array_key_exists('visible', $course) && ($oldcourse->visible != $course['visible'])) { require_capability('moodle/course:visibility', $context); } // Make sure lang is valid. if (array_key_exists('lang', $course) && empty($availablelangs[$course['lang']])) { throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang'); } // Make sure theme is valid. if (array_key_exists('forcetheme', $course)) { if (!empty($CFG->allowcoursethemes)) { if (empty($availablethemes[$course['forcetheme']])) { throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme'); } else { $course['theme'] = $course['forcetheme']; } } } // Make sure completion is enabled before setting it. if (array_key_exists('enabledcompletion', $course) && !completion_info::is_enabled_for_site()) { $course['enabledcompletion'] = 0; } // Make sure maxbytes are less then CFG->maxbytes. if (array_key_exists('maxbytes', $course)) { $course['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $course['maxbytes']); } if (!empty($course['courseformatoptions'])) { foreach ($course['courseformatoptions'] as $option) { if (isset($option['name']) && isset($option['value'])) { $course[$option['name']] = $option['value']; } } } // Update course if user has all required capabilities. update_course((object) $course); } catch (Exception $e) { $warning = array(); $warning['item'] = 'course'; $warning['itemid'] = $course['id']; if ($e instanceof moodle_exception) { $warning['warningcode'] = $e->errorcode; } else { $warning['warningcode'] = $e->getCode(); } $warning['message'] = $e->getMessage(); $warnings[] = $warning; } } $result = array(); $result['warnings'] = $warnings; return $result; }
/** * Save the new setting * * @param string $data The new value to save * @return string empty or error message */ public function write_setting($data) { global $DB, $SITE, $COURSE; $record = new stdClass(); $record->id = $SITE->id; $record->{$this->name} = $data; $record->timemodified = time(); course_get_format($SITE)->update_course_format_options($record); $DB->update_record('course', $record); // Reset caches. $SITE = $DB->get_record('course', array('id' => $SITE->id), '*', MUST_EXIST); if ($SITE->id == $COURSE->id) { $COURSE = $SITE; } format_base::reset_course_cache($SITE->id); return ''; }
} } } // If, so far, we think a button should be printed, so check if they will be // allowed to access it. if ($viewobj->buttontext) { if (!$viewobj->moreattempts) { $viewobj->buttontext = ''; } else { if ($canattempt && ($viewobj->preventmessages = $viewobj->accessmanager->prevent_access())) { $viewobj->buttontext = ''; } } } } $viewobj->showbacktocourse = $viewobj->buttontext === '' && course_get_format($course)->has_view_page(); echo $OUTPUT->header(); if (isguestuser()) { // Guests can't do a quiz, so offer them a choice of logging in or going back. echo $output->view_page_guest($course, $quiz, $cm, $context, $viewobj->infomessages); } else { if (!isguestuser() && !($canattempt || $canpreview || $viewobj->canreviewmine)) { // If they are not enrolled in this course in a good enough role, tell them to enrol. echo $output->view_page_notenrolled($course, $quiz, $cm, $context, $viewobj->infomessages); } else { echo $output->view_page($course, $quiz, $cm, $context, $viewobj); } } $nav = new Navigation(); $roleid = $nav->get_user_role(); if ($roleid == 4) {
/** * Will create the moodle course from the template * course_ext is an array as obtained from ldap -- flattened somewhat * * @param array $course_ext * @param progress_trace $trace * @return mixed false on error, id for the newly created course otherwise. */ function create_course($course_ext, progress_trace $trace) { global $CFG, $DB; require_once "{$CFG->dirroot}/course/lib.php"; // Override defaults with template course $template = false; if ($this->get_config('template')) { if ($template = $DB->get_record('course', array('shortname' => $this->get_config('template')))) { $template = fullclone(course_get_format($template)->get_course()); unset($template->id); // So we are clear to reinsert the record unset($template->fullname); unset($template->shortname); unset($template->idnumber); } } if (!$template) { $courseconfig = get_config('moodlecourse'); $template = new stdClass(); $template->summary = ''; $template->summaryformat = FORMAT_HTML; $template->format = $courseconfig->format; $template->newsitems = $courseconfig->newsitems; $template->showgrades = $courseconfig->showgrades; $template->showreports = $courseconfig->showreports; $template->maxbytes = $courseconfig->maxbytes; $template->groupmode = $courseconfig->groupmode; $template->groupmodeforce = $courseconfig->groupmodeforce; $template->visible = $courseconfig->visible; $template->lang = $courseconfig->lang; $template->enablecompletion = $courseconfig->enablecompletion; } $course = $template; $course->category = $this->get_config('category'); if (!$DB->record_exists('course_categories', array('id' => $this->get_config('category')))) { $categories = $DB->get_records('course_categories', array(), 'sortorder', 'id', 0, 1); $first = reset($categories); $course->category = $first->id; } // Override with required ext data $course->idnumber = $course_ext[$this->get_config('course_idnumber')][0]; $course->fullname = $course_ext[$this->get_config('course_fullname')][0]; $course->shortname = $course_ext[$this->get_config('course_shortname')][0]; if (empty($course->idnumber) || empty($course->fullname) || empty($course->shortname)) { // We are in trouble! $trace->output(get_string('cannotcreatecourse', 'enrol_ldap') . ' ' . var_export($course, true)); return false; } $summary = $this->get_config('course_summary'); if (!isset($summary) || empty($course_ext[$summary][0])) { $course->summary = ''; } else { $course->summary = $course_ext[$this->get_config('course_summary')][0]; } // Check if the shortname already exists if it does - skip course creation. if ($DB->record_exists('course', array('shortname' => $course->shortname))) { $trace->output(get_string('duplicateshortname', 'enrol_ldap', $course)); return false; } $newcourse = create_course($course); return $newcourse->id; }
} else { if ($data = $mform->get_data()) { // Data submitted and validated, update and return to course. $DB->update_record('course_sections', $data); rebuild_course_cache($course->id, true); if (isset($data->section)) { // Usually edit form does not change relative section number but just in case. $sectionnum = $data->section; } if (!empty($CFG->enableavailability)) { // Update grade and completion conditions. $sectioninfo = get_fast_modinfo($course)->get_section_info($sectionnum); condition_info_section::update_section_from_form($sectioninfo, $data); rebuild_course_cache($course->id, true); } course_get_format($course->id)->update_section_format_options($data); // Set section info, as this might not be present in form_data. if (!isset($data->section)) { $data->section = $sectionnum; } // Trigger an event for course section update. /*$event = \core\event\course_section_updated::create( array( 'objectid' => $data->id, 'courseid' => $course->id, 'context' => $context, 'other' => array('sectionnum' => $data->section) ) ); $event->trigger();*/ require_once $CFG->dirroot . '/calendar/lib.php';
/** * Add the default blocks to a course. * * @param object $course a course object. */ function blocks_add_default_course_blocks($course) { global $CFG; if (!empty($CFG->defaultblocks_override)) { $blocknames = blocks_parse_default_blocks_list($CFG->defaultblocks_override); } else { if ($course->id == SITEID) { $blocknames = blocks_get_default_site_course_blocks(); } else { if (!empty($CFG->{'defaultblocks_' . $course->format})) { $blocknames = blocks_parse_default_blocks_list($CFG->{'defaultblocks_' . $course->format}); } else { $blocknames = course_get_format($course)->get_default_blocks(); } } } if ($course->id == SITEID) { $pagetypepattern = 'site-index'; } else { $pagetypepattern = 'course-view-*'; } $page = new moodle_page(); $page->set_course($course); $page->blocks->add_blocks($blocknames, $pagetypepattern); }
/** * Returns course-specific information to be output on any course page in the footer area * (for the current course) * * @return string */ public function course_footer() { global $CFG; if ($this->page->course->id == SITEID) { // return immediately and do not include /course/lib.php if not necessary return ''; } require_once($CFG->dirroot.'/course/lib.php'); $courseformat = course_get_format($this->page->course); if (($obj = $courseformat->course_footer()) !== null) { return $courseformat->get_renderer($this->page)->render($obj); } return ''; }
/** * Generates the content of the block and returns it. * * If the content has already been generated then the previously generated content is returned. * * @return stdClass */ public function get_content() { // The config should be loaded by now. // If its empty then we will use the global config for the section links block. if (isset($this->config)) { $config = $this->config; } else { $config = get_config('block_section_links'); } if ($this->content !== null) { return $this->content; } $this->content = new stdClass(); $this->content->footer = ''; $this->content->text = ''; if (empty($this->instance)) { return $this->content; } $course = $this->page->course; $courseformat = course_get_format($course); $courseformatoptions = $courseformat->get_format_options(); $context = context_course::instance($course->id); // Prepare the highlight value. if ($course->format == 'weeks') { $highlight = ceil((time() - $course->startdate) / 604800); } else { if ($course->format == 'topics') { $highlight = $course->marker; } else { $highlight = 0; } } // Prepare the increment value. if (!empty($config->numsections1) and $courseformatoptions['numsections'] > $config->numsections1) { $inc = $config->incby1; } else { if ($courseformatoptions['numsections'] > 22) { $inc = 2; } else { $inc = 1; } } if (!empty($config->numsections2) and $courseformatoptions['numsections'] > $config->numsections2) { $inc = $config->incby2; } else { if ($courseformatoptions['numsections'] > 40) { $inc = 5; } } // Prepare an array of sections to create links for. $sections = array(); $canviewhidden = has_capability('moodle/course:update', $context); $coursesections = $courseformat->get_sections(); $coursesectionscount = count($coursesections); for ($i = $inc; $i <= $coursesectionscount; $i += $inc) { if ($i > $courseformatoptions['numsections'] || !isset($coursesections[$i])) { continue; } $section = $coursesections[$i]; if ($section->section && ($section->visible || $canviewhidden)) { $sections[$i] = (object) array('section' => $section->section, 'visible' => $section->visible, 'highlight' => $section->section == $highlight); } } if (!empty($sections)) { $sectiontojumpto = false; if ($highlight && isset($sections[$highlight]) && ($sections[$highlight]->visible || $canviewhidden)) { $sectiontojumpto = $highlight; } // Render the sections. $renderer = $this->page->get_renderer('block_section_links'); $this->content->text = $renderer->render_section_links($this->page->course, $sections, $sectiontojumpto); } return $this->content; }
require_once $CFG->libdir . '/completionlib.php'; // 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;
/** * The URL to use for the specified course (with section) * * @param int|stdClass $courseorid The course to get the section name for (either object or just course id) * @param int|stdClass $section Section object from database or just field course_sections.section * if omitted the course view page is returned * @param array $options options for view URL. At the moment core uses: * 'navigation' (bool) if true and section has no separate page, the function returns null * 'sr' (int) used by multipage formats to specify to which section to return * @return moodle_url The url of course */ function course_get_url($courseorid, $section = null, $options = array()) { return course_get_format($courseorid)->get_view_url($section, $options); }
/** * Processing functions go here * * @global moodledatabase $DB * @param stdClass $data */ public function process_course($data) { global $CFG, $DB; $data = (object) $data; $fullname = $this->get_setting_value('course_fullname'); $shortname = $this->get_setting_value('course_shortname'); $startdate = $this->get_setting_value('course_startdate'); // Calculate final course names, to avoid dupes list($fullname, $shortname) = restore_dbops::calculate_course_names($this->get_courseid(), $fullname, $shortname); // Need to change some fields before updating the course record $data->id = $this->get_courseid(); $data->fullname = $fullname; $data->shortname = $shortname; // Only allow the idnumber to be set if the user has permission and the idnumber is not already in use by // another course on this site. $context = context::instance_by_id($this->task->get_contextid()); if (!empty($data->idnumber) && has_capability('moodle/course:changeidnumber', $context, $this->task->get_userid()) && $this->task->is_samesite() && !$DB->record_exists('course', array('idnumber' => $data->idnumber))) { // Do not reset idnumber. } else { $data->idnumber = ''; } // Any empty value for course->hiddensections will lead to 0 (default, show collapsed). // It has been reported that some old 1.9 courses may have it null leading to DB error. MDL-31532 if (empty($data->hiddensections)) { $data->hiddensections = 0; } // Set legacyrestrictmodules to true if the course was resticting modules. If so // then we will need to process restricted modules after execution. $this->legacyrestrictmodules = !empty($data->restrictmodules); $data->startdate = $this->apply_date_offset($data->startdate); if ($data->defaultgroupingid) { $data->defaultgroupingid = $this->get_mappingid('grouping', $data->defaultgroupingid); } if (empty($CFG->enablecompletion)) { $data->enablecompletion = 0; $data->completionstartonenrol = 0; $data->completionnotify = 0; } $languages = get_string_manager()->get_list_of_translations(); // Get languages for quick search if (!array_key_exists($data->lang, $languages)) { $data->lang = ''; } $themes = get_list_of_themes(); // Get themes for quick search later if (!array_key_exists($data->theme, $themes) || empty($CFG->allowcoursethemes)) { $data->theme = ''; } // Check if this is an old SCORM course format. if ($data->format == 'scorm') { $data->format = 'singleactivity'; $data->activitytype = 'scorm'; } // Course record ready, update it $DB->update_record('course', $data); course_get_format($data)->update_course_format_options($data); // Role name aliases restore_dbops::set_course_role_names($this->get_restoreid(), $this->get_courseid()); }
/** * The course module that this page belongs to (if it does belong to one). * * @param stdClass|cm_info $cm a record from course_modules table or cm_info from get_fast_modinfo(). * @param stdClass $course * @param stdClass $module * @return void * @throws coding_exception */ public function set_cm($cm, $course = null, $module = null) { global $DB, $CFG, $SITE; if (!isset($cm->id) || !isset($cm->course)) { throw new coding_exception('Invalid $cm. It has to be instance of cm_info or record from the course_modules table.'); } if (!$this->_course || $this->_course->id != $cm->course) { if (!$course) { $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); } if ($course->id != $cm->course) { throw new coding_exception('The course you passed to $PAGE->set_cm does not correspond to the $cm.'); } $this->set_course($course); } // Make sure we have a $cm from get_fast_modinfo as this contains activity access details. if (!$cm instanceof cm_info) { $modinfo = get_fast_modinfo($this->_course); $cm = $modinfo->get_cm($cm->id); } $this->_cm = $cm; // Unfortunately the context setting is a mess. // Let's try to work around some common block problems and show some debug messages. if (empty($this->_context) or $this->_context->contextlevel != CONTEXT_BLOCK) { $context = context_module::instance($cm->id); $this->set_context($context); } if ($module) { $this->set_activity_record($module); } // Notify course format that this page is set for the course module. if ($this->_course->id != $SITE->id) { require_once $CFG->dirroot . '/course/lib.php'; course_get_format($this->_course)->page_set_cm($this); } }
switch ($class) { case 'section': if (!$DB->record_exists('course_sections', array('course' => $course->id, 'section' => $id))) { throw new moodle_exception('AJAX commands.php: Bad Section ID ' . $id); } switch ($field) { case 'visible': require_capability('moodle/course:sectionvisibility', $coursecontext); $resourcestotoggle = set_section_visible($course->id, $id, $value); echo json_encode(array('resourcestotoggle' => $resourcestotoggle)); break; case 'move': require_capability('moodle/course:movesections', $coursecontext); move_section_to($course, $id, $value); // See if format wants to do something about it $response = course_get_format($course)->ajax_section_move(); if ($response !== null) { echo json_encode($response); } break; } break; case 'resource': switch ($field) { case 'visible': require_capability('moodle/course:activityvisibility', $modcontext); set_coursemodule_visible($cm->id, $value); \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger(); break; case 'duplicate': require_capability('moodle/course:manageactivities', $modcontext);
/** * Performs a full sync with external database. * * First it creates new courses if necessary, then * enrols and unenrols users. * * @param bool $verbose * @return int 0 means success, 1 db connect failure, 4 db read failure */ public function sync_courses($verbose = false) { global $CFG, $DB; // Make sure we sync either enrolments or courses. if (!$this->get_config('dbtype') or !$this->get_config('dbhost') or !$this->get_config('newcoursetable') or !$this->get_config('newcoursefullname') or !$this->get_config('newcourseshortname')) { if ($verbose) { mtrace('Course synchronisation skipped.'); } return 0; } if ($verbose) { mtrace('Starting course synchronisation...'); } // We may need a lot of memory here. @set_time_limit(0); raise_memory_limit(MEMORY_HUGE); if (!($extdb = $this->db_init())) { mtrace('Error while communicating with external enrolment database'); return 1; } $table = $this->get_config('newcoursetable'); $fullname = trim($this->get_config('newcoursefullname')); $shortname = trim($this->get_config('newcourseshortname')); $idnumber = trim($this->get_config('newcourseidnumber')); $category = trim($this->get_config('newcoursecategory')); // Lowercased versions - necessary because we normalise the resultset with array_change_key_case(). $fullname_l = strtolower($fullname); $shortname_l = strtolower($shortname); $idnumber_l = strtolower($idnumber); $category_l = strtolower($category); $localcategoryfield = $this->get_config('localcategoryfield', 'id'); $defaultcategory = $this->get_config('defaultcategory'); if (!$DB->record_exists('course_categories', array('id' => $defaultcategory))) { if ($verbose) { mtrace(" default course category does not exist!"); } $categories = $DB->get_records('course_categories', array(), 'sortorder', 'id', 0, 1); $first = reset($categories); $defaultcategory = $first->id; } $sqlfields = array($fullname, $shortname); if ($category) { $sqlfields[] = $category; } if ($idnumber) { $sqlfields[] = $idnumber; } $sql = $this->db_get_sql($table, array(), $sqlfields, true); $createcourses = array(); if ($rs = $extdb->Execute($sql)) { if (!$rs->EOF) { while ($fields = $rs->FetchRow()) { $fields = array_change_key_case($fields, CASE_LOWER); $fields = $this->db_decode($fields); if (empty($fields[$shortname_l]) or empty($fields[$fullname_l])) { if ($verbose) { mtrace(' error: invalid external course record, shortname and fullname are mandatory: ' . json_encode($fields)); // Hopefully every geek can read JS, right? } continue; } if ($DB->record_exists('course', array('shortname' => $fields[$shortname_l]))) { // Already exists, skip. continue; } // Allow empty idnumber but not duplicates. if ($idnumber and $fields[$idnumber_l] !== '' and $fields[$idnumber_l] !== null and $DB->record_exists('course', array('idnumber' => $fields[$idnumber_l]))) { if ($verbose) { mtrace(' error: duplicate idnumber, can not create course: ' . $fields[$shortname_l] . ' [' . $fields[$idnumber_l] . ']'); } continue; } $course = new stdClass(); $course->fullname = $fields[$fullname_l]; $course->shortname = $fields[$shortname_l]; $course->idnumber = $idnumber ? $fields[$idnumber_l] : ''; if ($category) { if (empty($fields[$category_l])) { // Empty category means use default. $course->category = $defaultcategory; } else { if ($coursecategory = $DB->get_record('course_categories', array($localcategoryfield => $fields[$category_l]), 'id')) { // Yay, correctly specified category! $course->category = $coursecategory->id; unset($coursecategory); } else { // Bad luck, better not continue because unwanted ppl might get access to course in different category. if ($verbose) { mtrace(' error: invalid category ' . $localcategoryfield . ', can not create course: ' . $fields[$shortname_l]); } continue; } } } else { $course->category = $defaultcategory; } $createcourses[] = $course; } } $rs->Close(); } else { mtrace('Error reading data from the external course table'); $extdb->Close(); return 4; } if ($createcourses) { require_once "{$CFG->dirroot}/course/lib.php"; $templatecourse = $this->get_config('templatecourse'); $template = false; if ($templatecourse) { if ($template = $DB->get_record('course', array('shortname' => $templatecourse))) { $template = fullclone(course_get_format($template)->get_course()); unset($template->id); unset($template->fullname); unset($template->shortname); unset($template->idnumber); } else { if ($verbose) { mtrace(" can not find template for new course!"); } } } if (!$template) { $courseconfig = get_config('moodlecourse'); $template = new stdClass(); $template->summary = ''; $template->summaryformat = FORMAT_HTML; $template->format = $courseconfig->format; $template->newsitems = $courseconfig->newsitems; $template->showgrades = $courseconfig->showgrades; $template->showreports = $courseconfig->showreports; $template->maxbytes = $courseconfig->maxbytes; $template->groupmode = $courseconfig->groupmode; $template->groupmodeforce = $courseconfig->groupmodeforce; $template->visible = $courseconfig->visible; $template->lang = $courseconfig->lang; $template->groupmodeforce = $courseconfig->groupmodeforce; } foreach ($createcourses as $fields) { $newcourse = clone $template; $newcourse->fullname = $fields->fullname; $newcourse->shortname = $fields->shortname; $newcourse->idnumber = $fields->idnumber; $newcourse->category = $fields->category; // Detect duplicate data once again, above we can not find duplicates // in external data using DB collation rules... if ($DB->record_exists('course', array('shortname' => $newcourse->shortname))) { if ($verbose) { mtrace(" can not insert new course, duplicate shortname detected: " . $newcourse->shortname); } continue; } else { if (!empty($newcourse->idnumber) and $DB->record_exists('course', array('idnumber' => $newcourse->idnumber))) { if ($verbose) { mtrace(" can not insert new course, duplicate idnumber detected: " . $newcourse->idnumber); } continue; } } $c = create_course($newcourse); if ($verbose) { mtrace(" creating course: {$c->id}, {$c->fullname}, {$c->shortname}, {$c->idnumber}, {$c->category}"); } } unset($createcourses); unset($template); } // Close db connection. $extdb->Close(); if ($verbose) { mtrace('...course synchronisation finished.'); } return 0; }
/** * Implements callback inplace_editable() allowing to edit values in-place * * @param string $itemtype * @param int $itemid * @param mixed $newvalue * @return \core\output\inplace_editable */ function format_topics_inplace_editable($itemtype, $itemid, $newvalue) { global $DB, $CFG; require_once $CFG->dirroot . '/course/lib.php'; if ($itemtype === 'sectionname' || $itemtype === 'sectionnamenl') { $section = $DB->get_record_sql('SELECT s.* FROM {course_sections} s JOIN {course} c ON s.course = c.id WHERE s.id = ? AND c.format = ?', array($itemid, 'topics'), MUST_EXIST); return course_get_format($section->course)->inplace_editable_update_section_name($section, $itemtype, $newvalue); } }
public function test_course_delete_section() { global $DB; $this->resetAfterTest(true); $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 6, 'format' => 'topics'), array('createsections' => true)); $assign0 = $generator->create_module('assign', array('course' => $course, 'section' => 0)); $assign1 = $generator->create_module('assign', array('course' => $course, 'section' => 1)); $assign21 = $generator->create_module('assign', array('course' => $course, 'section' => 2)); $assign22 = $generator->create_module('assign', array('course' => $course, 'section' => 2)); $assign3 = $generator->create_module('assign', array('course' => $course, 'section' => 3)); $assign5 = $generator->create_module('assign', array('course' => $course, 'section' => 5)); $assign6 = $generator->create_module('assign', array('course' => $course, 'section' => 6)); $this->setAdminUser(); // Attempt to delete non-existing section. $this->assertFalse(course_delete_section($course, 10, false)); $this->assertFalse(course_delete_section($course, 9, true)); // Attempt to delete 0-section. $this->assertFalse(course_delete_section($course, 0, true)); $this->assertTrue($DB->record_exists('course_modules', array('id' => $assign0->cmid))); // Delete last section. $this->assertTrue(course_delete_section($course, 6, true)); $this->assertFalse($DB->record_exists('course_modules', array('id' => $assign6->cmid))); $this->assertEquals(5, course_get_format($course)->get_course()->numsections); // Delete empty section. $this->assertTrue(course_delete_section($course, 4, false)); $this->assertEquals(4, course_get_format($course)->get_course()->numsections); // Delete section in the middle (2). $this->assertFalse(course_delete_section($course, 2, false)); $this->assertTrue(course_delete_section($course, 2, true)); $this->assertFalse($DB->record_exists('course_modules', array('id' => $assign21->cmid))); $this->assertFalse($DB->record_exists('course_modules', array('id' => $assign22->cmid))); $this->assertEquals(3, course_get_format($course)->get_course()->numsections); $this->assertEquals(array(0 => array($assign0->cmid), 1 => array($assign1->cmid), 2 => array($assign3->cmid), 3 => array($assign5->cmid)), get_fast_modinfo($course)->sections); // Make last section orphaned. update_course((object) array('id' => $course->id, 'numsections' => 2)); $this->assertEquals(2, course_get_format($course)->get_course()->numsections); // Remove orphaned section. $this->assertTrue(course_delete_section($course, 3, true)); $this->assertEquals(2, course_get_format($course)->get_course()->numsections); // Remove marked section. course_set_marker($course->id, 1); $this->assertTrue(course_get_format($course)->is_section_current(1)); $this->assertTrue(course_delete_section($course, 1, true)); $this->assertFalse(course_get_format($course)->is_section_current(1)); }