public function is_available($not, \core_availability\info $info, $grabthelot, $userid) { $modinfo = $info->get_modinfo(); $completion = new \completion_info($modinfo->get_course()); if (!array_key_exists($this->cmid, $modinfo->cms)) { // If the cmid cannot be found, always return false regardless // of the condition or $not state. (Will be displayed in the // information message.) $allow = false; } else { // The completion system caches its own data so no caching needed here. $completiondata = $completion->get_data((object) array('id' => $this->cmid), $grabthelot, $userid, $modinfo); $allow = true; if ($this->expectedcompletion == COMPLETION_COMPLETE) { // Complete also allows the pass, fail states. switch ($completiondata->completionstate) { case COMPLETION_COMPLETE: case COMPLETION_COMPLETE_FAIL: case COMPLETION_COMPLETE_PASS: break; default: $allow = false; } } else { // Other values require exact match. if ($completiondata->completionstate != $this->expectedcompletion) { $allow = false; } } if ($not) { $allow = !$allow; } } return $allow; }
/** * Taken from /format/renderer.php * Generate a summary of the activites in a section * * @param stdClass $section The course_section entry from DB * @param stdClass $course the course record from DB * @param array $mods (argument not used) * @return string HTML to output. */ public static function section_activity_summary($section, $course, $mods) { global $CFG; require_once $CFG->libdir . '/completionlib.php'; $modinfo = get_fast_modinfo($course); if (empty($modinfo->sections[$section->section])) { return ''; } // Generate array with count of activities in this section. $sectionmods = array(); $total = 0; $complete = 0; $cancomplete = isloggedin() && !isguestuser(); $completioninfo = new completion_info($course); foreach ($modinfo->sections[$section->section] as $cmid) { $thismod = $modinfo->cms[$cmid]; if ($thismod->uservisible) { if (isset($sectionmods[$thismod->modname])) { $sectionmods[$thismod->modname]['name'] = $thismod->modplural; $sectionmods[$thismod->modname]['count']++; } else { $sectionmods[$thismod->modname]['name'] = $thismod->modfullname; $sectionmods[$thismod->modname]['count'] = 1; } if ($cancomplete && $completioninfo->is_enabled($thismod) != COMPLETION_TRACKING_NONE) { $total++; $completiondata = $completioninfo->get_data($thismod, true); if ($completiondata->completionstate == COMPLETION_COMPLETE || $completiondata->completionstate == COMPLETION_COMPLETE_PASS) { $complete++; } } } } if (empty($sectionmods)) { // No sections. return ''; } // Output section activities summary. $o = ''; $o .= "<div class='section-summary-activities mdl-right'>"; foreach ($sectionmods as $mod) { $o .= "<span class='activity-count'>"; $o .= $mod['name'] . ': ' . $mod['count']; $o .= "</span>"; } $o .= "</div>"; $a = false; // Output section completion data. if ($total > 0) { $a = new stdClass(); $a->complete = $complete; $a->total = $total; $a->percentage = $complete / $total * 100; $o .= "<div class='section-summary-activities mdl-right'>"; $o .= "<span class='activity-count'>" . get_string('progresstotal', 'completion', $a) . "</span>"; $o .= "</div>"; } $retobj = (object) array('output' => $o, 'progress' => $a, 'complete' => $complete, 'total' => $total); return $retobj; }
/** * toc progress percentage * @param stdClass $section * @param stdClass $course * @param boolean $perc - display as a percentage if true * @return string * * @Author Guy Thomas * @Date 2014-05-23 */ protected function toc_progress($section, $course, $perc = false) { global $CFG, $OUTPUT; require_once $CFG->libdir . '/completionlib.php'; $completioninfo = new completion_info($course); if (!$completioninfo->is_enabled()) { return ''; // Completion tracking not enabled. } $sac = snap_shared::section_activity_summary($section, $course, null); if (!empty($sac->progress)) { if ($perc) { $percentage = $sac->progress->percentage != null ? round($sac->progress->percentage, 0) . '%' : ''; return '<span class="completionstatus percentage">' . $percentage . '</span>'; } else { if ($sac->progress->total > 0) { $progress = get_string('progresstotal', 'completion', $sac->progress); $completed = ''; if ($sac->progress->complete === $sac->progress->total) { $winbadge = $OUTPUT->pix_url('i/completion-manual-y'); $completedstr = s(get_string('completed', 'completion')); $completed = "<img class=snap-section-complete src='{$winbadge}' alt='{$completedstr}' />"; } $printprogress = "<span class='completionstatus outoftotal'>{$completed} {$progress}</span>"; return $printprogress; } else { return ''; } } } }
/** * Test update_activity_completion_status_manually */ public function test_update_activity_completion_status_manually() { global $DB, $CFG; $this->resetAfterTest(true); $CFG->enablecompletion = true; $user = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), array('completion' => 1)); $cm = get_coursemodule_from_id('data', $data->cmid); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); $this->setUser($user); $result = core_completion_external::update_activity_completion_status_manually($data->cmid, true); // We need to execute the return values cleaning process to simulate the web service server. $result = external_api::clean_returnvalue(core_completion_external::update_activity_completion_status_manually_returns(), $result); // Check in DB. $this->assertEquals(1, $DB->get_field('course_modules_completion', 'completionstate', array('coursemoduleid' => $data->cmid))); // Check using the API. $completion = new completion_info($course); $completiondata = $completion->get_data($cm); $this->assertEquals(1, $completiondata->completionstate); $this->assertTrue($result['status']); $result = core_completion_external::update_activity_completion_status_manually($data->cmid, false); // We need to execute the return values cleaning process to simulate the web service server. $result = external_api::clean_returnvalue(core_completion_external::update_activity_completion_status_manually_returns(), $result); $this->assertEquals(0, $DB->get_field('course_modules_completion', 'completionstate', array('coursemoduleid' => $data->cmid))); $completiondata = $completion->get_data($cm); $this->assertEquals(0, $completiondata->completionstate); $this->assertTrue($result['status']); }
/** * Check if an activity is configured to only show navbuttons when * complete and then check if the activity is complete * @param cm_info $cm the course module for the activity * @return boolean true if the navbuttons should be shown */ function navbuttons_activity_showbuttons($cm) { $modname = $cm->modname; $show = get_config('block_navbuttons', 'activity' . $modname); if ($show === false || $show == NAVBUTTONS_ACTIVITY_ALWAYS) { return true; // No config or 'always show' } if ($show == NAVBUTTONS_ACTIVITY_NEVER) { return false; } if ($show == NAVBUTTONS_ACTIVITY_COMPLETE) { $completion = new completion_info($cm->get_course()); if (!$completion->is_enabled($cm)) { return true; // No completion tracking - show the buttons } $cmcompletion = $completion->get_data($cm); if ($cmcompletion->completionstate == COMPLETION_INCOMPLETE) { return false; } return true; } if (!isloggedin() || isguestuser()) { return true; // Always show the buttons if not logged in } // NAVBUTTONS_ACTIVITY_CUSTOM $funcname = 'navbuttons_mod_' . $modname . '_showbuttons'; if (!function_exists($funcname)) { return true; // Shouldn't have got to here, but allow the buttons anyway } return $funcname($cm); }
/** * Test survey_view * @return void */ public function test_survey_view() { global $CFG; $CFG->enablecompletion = 1; $this->resetAfterTest(); $this->setAdminUser(); // Setup test data. $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id), array('completion' => 2, 'completionview' => 1)); $context = context_module::instance($survey->cmid); $cm = get_coursemodule_from_instance('survey', $survey->id); // Trigger and capture the event. $sink = $this->redirectEvents(); survey_view($survey, $course, $cm, $context, 'form'); $events = $sink->get_events(); // 2 additional events thanks to completion. $this->assertCount(3, $events); $event = array_shift($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\\mod_survey\\event\\course_module_viewed', $event); $this->assertEquals($context, $event->get_context()); $moodleurl = new \moodle_url('/mod/survey/view.php', array('id' => $cm->id)); $this->assertEquals($moodleurl, $event->get_url()); $this->assertEquals('form', $event->other['viewed']); $this->assertEventContextNotUsed($event); $this->assertNotEmpty($event->get_name()); // Check completion status. $completion = new completion_info($course); $completiondata = $completion->get_data($cm); $this->assertEquals(1, $completiondata->completionstate); }
/** * Update completion status for the current user in an activity, only for activities with manual tracking. * @param int $cmid Course module id * @param bool $completed Activity completed or not * @return array Result and possible warnings * @since Moodle 2.9 * @throws moodle_exception */ public static function update_activity_completion_status_manually($cmid, $completed) { // Validate and normalize parameters. $params = self::validate_parameters(self::update_activity_completion_status_manually_parameters(), array('cmid' => $cmid, 'completed' => $completed)); $cmid = $params['cmid']; $completed = $params['completed']; $warnings = array(); $context = context_module::instance($cmid); self::validate_context($context); list($course, $cm) = get_course_and_cm_from_cmid($cmid); // Set up completion object and check it is enabled. $completion = new completion_info($course); if (!$completion->is_enabled()) { throw new moodle_exception('completionnotenabled', 'completion'); } // Check completion state is manual. if ($cm->completion != COMPLETION_TRACKING_MANUAL) { throw new moodle_exception('cannotmanualctrack', 'error'); } $targetstate = $completed ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE; $completion->update_state($cm, $targetstate); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; }
function execute($data, $row, $user, $courseid, $starttime = 0, $endtime = 0) { global $DB, $CFG; require_once("{$CFG->libdir}/completionlib.php"); $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); $info = new completion_info($course); // Is course complete? $coursecomplete = $info->is_course_complete($row->id); // Load course completion. $params = array( 'userid' => $row->id, 'course' => $course->id ); $ccompletion = new completion_completion($params); // Has this user completed any criteria? $criteriacomplete = $info->count_course_user_data($row->id); $content = ""; if ($coursecomplete) { $content .= get_string('complete'); } else if (!$criteriacomplete && !$ccompletion->timestarted) { $content .= html_writer::tag('i', get_string('notyetstarted', 'completion')); } else { $content .= html_writer::tag('i', get_string('inprogress', 'completion')); } return $content; }
public function execute() { global $DB, $CFG; $result = $DB->get_records_sql('SELECT ba.id, ba.bookingid, ba.optionid, ba.userid, b.course FROM {booking_answers} AS ba LEFT JOIN {booking_options} AS bo ON bo.id = ba.optionid LEFT JOIN {booking} AS b ON b.id = bo.bookingid WHERE bo.removeafterminutes > 0 AND ba.completed = 1 AND IF(ba.timemodified < (UNIX_TIMESTAMP() - (bo.removeafterminutes*60)), 1, 0) = 1;'); require_once $CFG->libdir . '/completionlib.php'; foreach ($result as $value) { $course = $DB->get_record('course', array('id' => $value->course)); $completion = new \completion_info($course); $cm = get_coursemodule_from_instance('booking', $value->bookingid); $userData = $DB->get_record('booking_answers', array('id' => $value->id)); $booking = $DB->get_record('booking', array('id' => $value->bookingid)); $userData->completed = '0'; $userData->timemodified = time(); $DB->update_record('booking_answers', $userData); if ($completion->is_enabled($cm) && $booking->enablecompletion) { $completion->update_state($cm, COMPLETION_INCOMPLETE, $userData->userid); } } }
public function get_content() { global $CFG, $USER; // If content is cached if ($this->content !== NULL) { return $this->content; } // Create empty content $this->content = new stdClass(); // Can edit settings? $can_edit = has_capability('moodle/course:update', get_context_instance(CONTEXT_COURSE, $this->page->course->id)); // Get course completion data $info = new completion_info($this->page->course); // Don't display if completion isn't enabled! if (!completion_info::is_enabled_for_site()) { if ($can_edit) { $this->content->text = get_string('completionnotenabledforsite', 'completion'); } return $this->content; } else { if (!$info->is_enabled()) { if ($can_edit) { $this->content->text = get_string('completionnotenabledforcourse', 'completion'); } return $this->content; } } // Get this user's data $completion = $info->get_completion($USER->id, COMPLETION_CRITERIA_TYPE_SELF); // Check if self completion is one of this course's criteria if (empty($completion)) { if ($can_edit) { $this->content->text = get_string('selfcompletionnotenabled', 'block_selfcompletion'); } return $this->content; } // Check this user is enroled if (!$info->is_tracked_user($USER->id)) { $this->content->text = get_string('notenroled', 'completion'); return $this->content; } // Is course complete? if ($info->is_course_complete($USER->id)) { $this->content->text = get_string('coursealreadycompleted', 'completion'); return $this->content; // Check if the user has already marked themselves as complete } else { if ($completion->is_complete()) { $this->content->text = get_string('alreadyselfcompleted', 'block_selfcompletion'); return $this->content; // If user is not complete, or has not yet self completed } else { $this->content->text = ''; $this->content->footer = '<br /><a href="' . $CFG->wwwroot . '/course/togglecompletion.php?course=' . $this->page->course->id . '">'; $this->content->footer .= get_string('completecourse', 'block_selfcompletion') . '</a>...'; } } return $this->content; }
/** * This function extends the navigation with the report items * * @param navigation_node $navigation The navigation node to extend * @param stdClass $course The course to object for the report * @param stdClass $context The context of the course */ function completion_report_extend_navigation($navigation, $course, $context) { global $CFG, $OUTPUT; if (has_capability('coursereport/completion:view', $context)) { $completion = new completion_info($course); if ($completion->is_enabled() && $completion->has_criteria()) { $url = new moodle_url('/course/report/completion/index.php', array('course' => $course->id)); $navigation->add(get_string('pluginname', 'coursereport_completion'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '')); } } }
protected function allow_add($course, \cm_info $cm = null, \section_info $section = null) { global $CFG; // Check if completion is enabled for the course. require_once $CFG->libdir . '/completionlib.php'; $info = new \completion_info($course); if (!$info->is_enabled()) { return false; } // Check if there's at least one other module with completion info. $params = $this->get_javascript_init_params($course, $cm, $section); return (array) $params[0] != false; }
public function course_completion_gauge(&$course, $div, $width = 160, $height = 160, $type = 'progressbar') { global $USER, $PAGE; $str = ''; $completion = new completion_info($course); if ($completion->is_enabled(null)) { $alltracked = count($completion->get_activities()); $progressinfo = $completion->get_progress_all('u.id = :userid', array('userid' => $USER->id)); $completed = 0; if (!empty($progressinfo)) { if (!empty($progressinfo[$USER->id]->progress)) { foreach ($progressinfo[$USER->id]->progress as $progressrecord) { if ($progressrecord->completionstate) { $completed++; } } } } $ratio = $alltracked == 0 ? 0 : round($completed / $alltracked * 100); $jqwrenderer = $PAGE->get_renderer('local_vflibs'); if ($div == 'div') { $str .= '<div class="course-completion" title="' . get_string('completion', 'local_my', 0 + $ratio) . '">'; } else { $str .= '<td class="course-completion" title="' . get_string('completion', 'local_my', 0 + $ratio) . '">'; } if ($type == 'gauge') { $properties = array('width' => $width, 'height' => $height, 'max' => 100, 'crop' => 120); $str .= $jqwrenderer->jqw_bargauge_simple('completion-jqw-' . $course->id, array($ratio), $properties); } else { $properties = array('width' => $width, 'height' => $height, 'animation' => 300, 'template' => 'success'); $str .= $jqwrenderer->jqw_progress_bar('completion-jqw-' . $course->id, $ratio, $properties); } if ($div == 'div') { $str .= '</div>'; } else { $str .= '</td>'; } } else { if ($div == 'div') { $str .= '<div class="course-completion">'; } else { $str .= '<td class="course-completion">'; } if ($div == 'div') { $str .= '</div>'; } else { $str .= '</td>'; } } return $str; }
/** * Routes to a valid action. * * @param string $action * @access public * @return string Rendered output for display. */ public function display_action($action) { $this->renderer->setup_page($this); $method = "action_{$action}"; if (!method_exists(__CLASS__, $method)) { throw new \invalid_parameter_exception("Unknown action: {$action}"); } $output = $this->{$method}(); $completion = new \completion_info($this->course); $completion->set_module_viewed($this->cm); $header = $this->header(); $footer = $this->renderer->footer(); return $header . $output . $footer; }
/** * This function extends the navigation with the report items * * @param navigation_node $navigation The navigation node to extend * @param stdClass $course The course to object for the report * @param stdClass $context The context of the course */ function progress_report_extend_navigation($navigation, $course, $context) { global $CFG, $OUTPUT; $showonnavigation = has_capability('coursereport/progress:view', $context); $group = groups_get_course_group($course, true); // Supposed to verify group if ($group === 0 && $course->groupmode == SEPARATEGROUPS) { $showonnavigation = $showonnavigation && has_capability('moodle/site:accessallgroups', $context); } $completion = new completion_info($course); $showonnavigation = $showonnavigation && $completion->is_enabled() && count($completion->get_activities()) > 0; if ($showonnavigation) { $url = new moodle_url('/course/report/progress/index.php', array('course' => $course->id)); $navigation->add(get_string('pluginname', 'coursereport_progress'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('i/report', '')); } }
function test_has_activities() { global $DB; $this->resetAfterTest(true); // Create a course with mixed auto completion data. $course = $this->getDataGenerator()->create_course(); $course2 = $this->getDataGenerator()->create_course(); $completionauto = array('completion' => COMPLETION_TRACKING_AUTOMATIC); $completionnone = array('completion' => COMPLETION_TRACKING_NONE); $c1forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id), $completionauto); $c2forum = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id), $completionnone); $c1 = new completion_info($course); $c2 = new completion_info($course2); $this->assertTrue($c1->has_activities()); $this->assertFalse($c2->has_activities()); }
/** * * @param cm_info $cm * @param stdClass $stopwatch * @param int $duration */ function mod_stopwatch_update_timer(cm_info $cm, $stopwatch, $duration) { global $USER, $DB, $CFG; require_once $CFG->libdir . '/completionlib.php'; $record = $DB->get_record('stopwatch_user', array('stopwatchid' => $cm->instance, 'courseid' => $cm->course, 'userid' => $USER->id)); if ($record) { $data = array('id' => $record->id, 'timemodified' => time(), 'duration' => $duration); $DB->update_record('stopwatch_user', $data); } else { $data = array('courseid' => $cm->course, 'stopwatchid' => $cm->instance, 'userid' => $USER->id, 'timecreated' => time(), 'timemodified' => time(), 'duration' => $duration); $DB->insert_record('stopwatch_user', $data); } // Update completion state $completion = new completion_info($cm->get_course()); if ($completion->is_enabled($cm) && $stopwatch->completiontimed) { $completion->update_state($cm, COMPLETION_COMPLETE); } }
/** * Updates activity completion status. * * @return void */ public static function update_require_specific_grade(\core\event\base $event) { global $DB; $entryuserid = $event->relateduserid; $giid = $event->other['itemid']; if (!($gitem = \grade_item::fetch(array('id' => $giid, 'itemmodule' => 'dataform')))) { return; } $dataformid = $gitem->iteminstance; $df = \mod_dataform_dataform::instance($dataformid); // Currently only completion by require entries. if ($df->completionspecificgrade) { $completion = new \completion_info($df->course); if ($completion->is_enabled($df->cm) != COMPLETION_TRACKING_AUTOMATIC) { return; } $completion->update_state($df->cm, COMPLETION_UNKNOWN, $entryuserid); } }
/** * Read page * * @throws \coding_exception * @return stdClass */ private function read_page() { global $PAGE, $COURSE; $cm = $PAGE->cm; $page = \theme_snap\local::get_page_mod($cm); $context = $PAGE->context; // Trigger module instance viewed event. $event = \mod_page\event\course_module_viewed::create(array('objectid' => $page->id, 'context' => $context)); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $COURSE); $event->add_record_snapshot('page', $page); $event->trigger(); // Update 'viewed' state if required by completion system. $completion = new \completion_info($COURSE); $completion->set_module_viewed($cm); $renderer = $PAGE->get_renderer('core', 'course'); $page->completionhtml = $renderer->course_section_cm_completion($COURSE, $completion, $cm); return $page; }
public function get_content() { global $USER; // If content is cached if ($this->content !== NULL) { return $this->content; } global $CFG; // Create empty content $this->content = new stdClass(); // Don't display if completion isn't enabled! if (!$this->page->course->enablecompletion) { $this->content->text = get_string('completionnotenabled', 'block_selfcompletion'); return $this->content; } // Get course completion data $info = new completion_info($this->page->course); $completion = $info->get_completion($USER->id, COMPLETION_CRITERIA_TYPE_SELF); // Is course complete? if ($info->is_course_complete($USER->id)) { return $this->content; } // Check if self completion is one of this course's criteria if (empty($completion)) { $this->content->text = get_string('selfcompletionnotenabled', 'block_selfcompletion'); return $this->content; } // Check this user is enroled if (!$info->is_tracked_user($USER->id)) { $this->content->text = get_string('notenroled', 'completion'); return $this->content; } // Check if the user has already marked themselves as complete if ($completion->is_complete()) { return $this->content; } else { $this->content->text = ''; $this->content->footer = '<br /><a href="' . $CFG->wwwroot . '/course/togglecompletion.php?course=' . $this->page->course->id . '">' . get_string('completecourse', 'block_selfcompletion') . '</a>...'; } return $this->content; }
/** * get_activity_tree :: course_modinfo -> integer -> context -> array * @param \course_modinfo $modinfo * @param integer $section_number * @param \context $context * @return array */ function get_activity_tree(\course_modinfo $modinfo, $section_number, \context $context) { $completion_info = new \completion_info($modinfo->get_course()); return F\map(F\filter($modinfo->get_section_info_all(), function (\section_info $section_info) { return $section_info->visible; }), function (\section_info $section_info) use($completion_info, $section_number, $context) { $mods = F\map(F\filter($section_info->modinfo->cms, function (\cm_info $cm_info) use($section_info) { global $CFG; return ($cm_info->uservisible || $CFG->enableavailability && !empty($cm_info->availableinfo)) && (int) $cm_info->sectionnum === (int) $section_info->section; }), function (\cm_info $cm_info) use($completion_info, $context) { global $CFG; $canComplete = $CFG->enablecompletion && isloggedin() && !isguestuser() && (int) $completion_info->is_enabled($cm_info) === COMPLETION_TRACKING_MANUAL; $hasCompleted = false; if ($canComplete) { $completion_data = $completion_info->get_data($cm_info, true); $hasCompleted = F\contains([COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS], (int) $completion_data->completionstate); } return (object) ['id' => (int) $cm_info->id, 'name' => $cm_info->name, 'modname' => $cm_info->modname, 'current' => is_current_mod($cm_info, $context), 'available' => $cm_info->available, 'canComplete' => $canComplete, 'hasCompleted' => $hasCompleted]; }); return (object) ['id' => (int) $section_info->id, 'section' => (int) $section_info->section, 'name' => \get_section_name($section_info->modinfo->courseid, $section_info->section), 'current' => is_current_section($section_info, $section_number, $context), 'activities' => array_values($mods)]; }); }
/** * Set properties from course and section. * @param \stdClass $course * @param \stdClass $section */ public function __construct($course, $section) { global $OUTPUT; static $compinfos = []; if (isset($compinfos[$course->id])) { $completioninfo = $compinfos[$course->id]; } else { $completioninfo = new \completion_info($course); $compinfos[$course->id] = $completioninfo; } if (!$completioninfo->is_enabled()) { return ''; // Completion tracking not enabled. } $sac = shared::section_activity_summary($section, $course, null); if (empty($sac->progress)) { return; } $this->progress = (object) ['complete' => $sac->progress->complete, 'total' => $sac->progress->total]; $this->pixcompleted = $OUTPUT->pix_url('i/completion-manual-y'); $this->completed = $sac->progress->complete === $sac->progress->total; }
public function test_glossary_view() { global $CFG; $origcompletion = $CFG->enablecompletion; $CFG->enablecompletion = true; $this->resetAfterTest(true); // Generate all the things. $c1 = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1)); $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1)); $u1 = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($u1->id, $c1->id); $modinfo = course_modinfo::instance($c1->id); $cm1 = $modinfo->get_cm($g1->cmid); $cm2 = $modinfo->get_cm($g2->cmid); $ctx1 = $cm1->context; $completion = new completion_info($c1); $this->setUser($u1); // Confirm what we've set up. $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm1, false, $u1->id)->viewed); $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm1, false, $u1->id)->completionstate); $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm2, false, $u1->id)->viewed); $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm2, false, $u1->id)->completionstate); // Simulate the view call. $sink = $this->redirectEvents(); glossary_view($g1, $c1, $cm1, $ctx1, 'letter'); $events = $sink->get_events(); // Assertions. $this->assertCount(3, $events); $this->assertEquals('\\core\\event\\course_module_completion_updated', $events[0]->eventname); $this->assertEquals('\\core\\event\\course_module_completion_updated', $events[1]->eventname); $this->assertEquals('\\mod_glossary\\event\\course_module_viewed', $events[2]->eventname); $this->assertEquals($g1->id, $events[2]->objectid); $this->assertEquals('letter', $events[2]->other['mode']); $this->assertEquals(COMPLETION_VIEWED, $completion->get_data($cm1, false, $u1->id)->viewed); $this->assertEquals(COMPLETION_COMPLETE, $completion->get_data($cm1, false, $u1->id)->completionstate); $this->assertEquals(COMPLETION_NOT_VIEWED, $completion->get_data($cm2, false, $u1->id)->viewed); $this->assertEquals(COMPLETION_INCOMPLETE, $completion->get_data($cm2, false, $u1->id)->completionstate); // Tear down. $sink->close(); $CFG->enablecompletion = $origcompletion; }
$nonsubmitters->send_message($nonsubmitteduser->id, $subject, $message); } // Send a copy of message to the instructor if appropriate. if (!empty($sendtoself)) { $nonsubmitters->send_message($USER->id, $subject, $message); } $do = "emailsent"; } $params = array('id' => $id, 'do' => $do, 'view_context' => 'box_solid'); redirect(new moodle_url('/mod/turnitintooltwo/view.php', $params)); exit; break; } } // Enable activity completion on page view. $completion = new completion_info($course); $completion->set_module_viewed($cm); // Show header and navigation if ($viewcontext == "box" || $viewcontext == "box_solid") { $PAGE->set_pagelayout('embedded'); $turnitintooltwoview->output_header($cm, $course, $url, '', '', array(), "", "", true, '', ''); } else { $turnitintooltwoview->output_header($cm, $course, $url, $turnitintooltwoassignment->turnitintooltwo->name, $SITE->fullname, array(), "", "", true, $OUTPUT->update_module_button($cm->id, "turnitintooltwo"), ''); // Dropdown to filter by groups. $groupmode = groups_get_activity_groupmode($cm); if ($groupmode) { groups_get_activity_group($cm, true); groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/turnitintooltwo/view.php?id=' . $id . '&do=' . $do); } $turnitintooltwoview->draw_tool_tab_menu($cm, $do); }
/** * Output the html for a multiple section page * * @param stdClass $course The course entry from DB * @param array $sections (argument not used) * @param array $mods (argument not used) * @param array $modnames (argument not used) * @param array $modnamesused (argument not used) */ public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) { $modinfo = get_fast_modinfo($course); $course = $this->courseformat->get_course(); if (empty($this->tcsettings)) { $this->tcsettings = $this->courseformat->get_settings(); } $context = context_course::instance($course->id); // Title with completion help icon. $completioninfo = new completion_info($course); echo $completioninfo->display_help_icon(); echo $this->output->heading($this->page_title(), 2, 'accesshide'); // Copy activity clipboard.. echo $this->course_activity_clipboard($course, 0); // Now the list of sections.. $this->tccolumnwidth = 100; // Reset to default. echo $this->start_section_list(); $sections = $modinfo->get_section_info_all(); // General section if non-empty. $thissection = $sections[0]; unset($sections[0]); if ($thissection->summary or !empty($modinfo->sections[0]) or $this->userisediting) { echo $this->section_header($thissection, $course, false, 0); echo $this->courserenderer->course_section_cm_list($course, $thissection, 0); echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0, 0); echo $this->section_footer(); } if ($course->numsections > 0) { if ($course->numsections > 1) { if ($this->userisediting || $course->coursedisplay != COURSE_DISPLAY_MULTIPAGE) { // Collapsed Topics all toggles. echo $this->toggle_all(); if ($this->tcsettings['displayinstructions'] == 2) { // Collapsed Topics instructions. echo $this->display_instructions(); } } } $currentsectionfirst = false; if ($this->tcsettings['layoutstructure'] == 4) { $currentsectionfirst = true; } if ($this->tcsettings['layoutstructure'] != 3 || $this->userisediting) { $section = 1; } else { $timenow = time(); $weekofseconds = 604800; $course->enddate = $course->startdate + $weekofseconds * $course->numsections; $section = $course->numsections; $weekdate = $course->enddate; // This should be 0:00 Monday of that week. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems. } $numsections = $course->numsections; // Because we want to manipulate this for column breakpoints. if ($this->tcsettings['layoutstructure'] == 3 && $this->userisediting == false) { $loopsection = 1; $numsections = 0; while ($loopsection <= $course->numsections) { $nextweekdate = $weekdate - $weekofseconds; if ((($thissection->uservisible || $thissection->visible && !$thissection->available && !empty($thissection->availableinfo)) && $nextweekdate <= $timenow) == true) { $numsections++; // Section not shown so do not count in columns calculation. } $weekdate = $nextweekdate; $section--; $loopsection++; } // Reset. $section = $course->numsections; $weekdate = $course->enddate; // This should be 0:00 Monday of that week. $weekdate -= 7200; // Subtract two hours to avoid possible DST problems. } if ($numsections < $this->tcsettings['layoutcolumns']) { $this->tcsettings['layoutcolumns'] = $numsections; // Help to ensure a reasonable display. } if ($this->tcsettings['layoutcolumns'] > 1 && $this->mobiletheme === false) { if ($this->tcsettings['layoutcolumns'] > 4) { // Default in config.php (and reset in database) or database has been changed incorrectly. $this->tcsettings['layoutcolumns'] = 4; // Update.... $this->courseformat->update_topcoll_columns_setting($this->tcsettings['layoutcolumns']); } if ($this->tablettheme === true && $this->tcsettings['layoutcolumns'] > 2) { // Use a maximum of 2 for tablets. $this->tcsettings['layoutcolumns'] = 2; } $this->tccolumnwidth = 100 / $this->tcsettings['layoutcolumns']; if ($this->tcsettings['layoutcolumnorientation'] == 2) { // Horizontal column layout. $this->tccolumnwidth -= 1; } else { $this->tccolumnwidth -= 0.2; } $this->tccolumnpadding = 0; // In 'px'. } else { if ($this->tcsettings['layoutcolumns'] < 1) { // Distributed default in plugin settings (and reset in database) or database has been changed incorrectly. $this->tcsettings['layoutcolumns'] = 1; // Update.... $this->courseformat->update_topcoll_columns_setting($this->tcsettings['layoutcolumns']); } } echo $this->end_section_list(); echo $this->start_toggle_section_list(); $loopsection = 1; $canbreak = false; // Once the first section is shown we can decide if we break on another column. $columncount = 1; $columnbreakpoint = 0; $shownsectioncount = 0; if ($this->userpreference != null) { $this->isoldtogglepreference = $this->togglelib->is_old_preference($this->userpreference); if ($this->isoldtogglepreference == true) { $ts1 = base_convert(substr($this->userpreference, 0, 6), 36, 2); $ts2 = base_convert(substr($this->userpreference, 6, 12), 36, 2); $thesparezeros = "00000000000000000000000000"; if (strlen($ts1) < 26) { // Need to PAD. $ts1 = substr($thesparezeros, 0, 26 - strlen($ts1)) . $ts1; } if (strlen($ts2) < 27) { // Need to PAD. $ts2 = substr($thesparezeros, 0, 27 - strlen($ts2)) . $ts2; } $tb = $ts1 . $ts2; } else { // Check we have enough digits for the number of toggles in case this has increased. $numdigits = $this->togglelib->get_required_digits($course->numsections); if ($numdigits > strlen($this->userpreference)) { if ($this->defaultuserpreference == 0) { $dchar = $this->togglelib->get_min_digit(); } else { $dchar = $this->togglelib->get_max_digit(); } for ($i = strlen($this->userpreference); $i < $numdigits; $i++) { $this->userpreference .= $dchar; } } $this->togglelib->set_toggles($this->userpreference); } } else { $numdigits = $this->togglelib->get_required_digits($course->numsections); if ($this->defaultuserpreference == 0) { $dchar = $this->togglelib->get_min_digit(); } else { $dchar = $this->togglelib->get_max_digit(); } $this->userpreference = ''; for ($i = 0; $i < $numdigits; $i++) { $this->userpreference .= $dchar; } $this->togglelib->set_toggles($this->userpreference); } while ($loopsection <= $course->numsections) { if ($this->tcsettings['layoutstructure'] == 3 && $this->userisediting == false) { $nextweekdate = $weekdate - $weekofseconds; } $thissection = $modinfo->get_section_info($section); /* Show the section if the user is permitted to access it, OR if it's not available but there is some available info text which explains the reason & should display. */ if ($this->tcsettings['layoutstructure'] != 3 || $this->userisediting) { $showsection = $thissection->uservisible || $thissection->visible && !$thissection->available && !empty($thissection->availableinfo); } else { $showsection = ($thissection->uservisible || $thissection->visible && !$thissection->available && !empty($thissection->availableinfo)) && $nextweekdate <= $timenow; } if ($currentsectionfirst == true && $showsection == true) { // Show the section if we were meant to and it is the current section:.... $showsection = $course->marker == $section; } else { if ($this->tcsettings['layoutstructure'] == 4 && $course->marker == $section) { $showsection = false; // Do not reshow current section. } } if (!$showsection) { // Hidden section message is overridden by 'unavailable' control. if ($this->tcsettings['layoutstructure'] != 4) { if ($this->tcsettings['layoutstructure'] != 3 || $this->userisediting) { if (!$course->hiddensections && $thissection->available) { $shownsectioncount++; echo $this->section_hidden($thissection); } } } } else { $shownsectioncount++; if (!$this->userisediting && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) { // Display section summary only. echo $this->section_summary($thissection, $course, null); } else { if ($this->isoldtogglepreference == true) { $togglestate = substr($tb, $section, 1); if ($togglestate == '1') { $thissection->toggle = true; } else { $thissection->toggle = false; } } else { $thissection->toggle = $this->togglelib->get_toggle_state($thissection->section); } echo $this->section_header($thissection, $course, false, 0); if ($thissection->uservisible) { echo $this->courserenderer->course_section_cm_list($course, $thissection, 0); echo $this->courserenderer->course_section_add_cm_control($course, $thissection->section, 0); } echo html_writer::end_tag('div'); echo $this->section_footer(); } } if ($currentsectionfirst == false) { /* Only need to do this on the iteration when $currentsectionfirst is not true as this iteration will always happen. Otherwise you get duplicate entries in course_sections in the DB. */ unset($sections[$section]); } if ($this->tcsettings['layoutstructure'] != 3 || $this->userisediting) { $section++; } else { $section--; if ($this->tcsettings['layoutstructure'] == 3 && $this->userisediting == false) { $weekdate = $nextweekdate; } } if ($this->mobiletheme === false) { // Only break in non-mobile themes. if ($this->tcsettings['layoutcolumnorientation'] == 1) { // Only break columns in vertical mode. if ($canbreak == false && $currentsectionfirst == false && $showsection == true) { $canbreak = true; $columnbreakpoint = $shownsectioncount + $numsections / $this->tcsettings['layoutcolumns'] - 1; if ($this->tcsettings['layoutstructure'] == 4) { $columnbreakpoint -= 1; } } if ($currentsectionfirst == false && $canbreak == true && $shownsectioncount >= $columnbreakpoint && $columncount < $this->tcsettings['layoutcolumns']) { echo $this->end_section_list(); echo $this->start_toggle_section_list(); $columncount++; // Next breakpoint is... $columnbreakpoint += $numsections / $this->tcsettings['layoutcolumns']; } } } $loopsection++; if ($currentsectionfirst == true && $loopsection > $course->numsections) { // Now show the rest. $currentsectionfirst = false; $loopsection = 1; $section = 1; } if ($section > $course->numsections) { // Activities inside this section are 'orphaned', this section will be printed as 'stealth' below. break; } } } if ($this->userisediting and has_capability('moodle/course:update', $context)) { // Print stealth sections if present. foreach ($modinfo->get_section_info_all() as $section => $thissection) { if ($section <= $course->numsections or empty($modinfo->sections[$section])) { // This is not stealth section or it is empty. continue; } echo $this->stealth_section_header($section); echo $this->courserenderer->course_section_cm_list($course, $thissection->section, 0); echo $this->stealth_section_footer(); } echo $this->end_section_list(); echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right')); // Increase number of sections. $straddsection = get_string('increasesections', 'moodle'); $url = new moodle_url('/course/changenumsections.php', array('courseid' => $course->id, 'increase' => true, 'sesskey' => sesskey())); $icon = $this->output->pix_icon('t/switch_plus', $straddsection); echo html_writer::link($url, $icon . get_accesshide($straddsection), array('class' => 'increase-sections')); if ($course->numsections > 0) { // Reduce number of sections sections. $strremovesection = get_string('reducesections', 'moodle'); $url = new moodle_url('/course/changenumsections.php', array('courseid' => $course->id, 'increase' => false, 'sesskey' => sesskey())); $icon = $this->output->pix_icon('t/switch_minus', $strremovesection); echo html_writer::link($url, $icon . get_accesshide($strremovesection), array('class' => 'reduce-sections')); } echo html_writer::end_tag('div'); } else { echo $this->end_section_list(); } }
/** * Deletes a single forum post. * * @global object * @param object $post Forum post object * @param mixed $children Whether to delete children. If false, returns false * if there are any children (without deleting the post). If true, * recursively deletes all children. If set to special value 'ignore', deletes * post regardless of children (this is for use only when deleting all posts * in a disussion). * @param object $course Course * @param object $cm Course-module * @param object $forum Forum * @param bool $skipcompletion True to skip updating completion state if it * would otherwise be updated, i.e. when deleting entire forum anyway. * @return bool */ function forum_delete_post($post, $children, $course, $cm, $forum, $skipcompletion=false) { global $DB, $CFG; require_once($CFG->libdir.'/completionlib.php'); $context = context_module::instance($cm->id); if ($children !== 'ignore' && ($childposts = $DB->get_records('forum_posts', array('parent'=>$post->id)))) { if ($children) { foreach ($childposts as $childpost) { forum_delete_post($childpost, true, $course, $cm, $forum, $skipcompletion); } } else { return false; } } //delete ratings require_once($CFG->dirroot.'/rating/lib.php'); $delopt = new stdClass; $delopt->contextid = $context->id; $delopt->component = 'mod_forum'; $delopt->ratingarea = 'post'; $delopt->itemid = $post->id; $rm = new rating_manager(); $rm->delete_ratings($delopt); //delete attachments $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_forum', 'attachment', $post->id); $fs->delete_area_files($context->id, 'mod_forum', 'post', $post->id); if ($DB->delete_records("forum_posts", array("id" => $post->id))) { forum_tp_delete_read_records(-1, $post->id); // Just in case we are deleting the last post forum_discussion_update_last_post($post->discussion); // Update completion state if we are tracking completion based on number of posts // But don't bother when deleting whole thing if (!$skipcompletion) { $completion = new completion_info($course); if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC && ($forum->completiondiscussions || $forum->completionreplies || $forum->completionposts)) { $completion->update_state($cm, COMPLETION_INCOMPLETE, $post->userid); } } return true; } return false; }
function checklist_update_grades($checklist, $userid = 0) { global $CFG, $DB; $items = $DB->get_records('checklist_item', array('checklist' => $checklist->id, 'userid' => 0, 'itemoptional' => CHECKLIST_OPTIONAL_NO, 'hidden' => CHECKLIST_HIDDEN_NO), '', 'id, grouping'); if (!$items) { return; } if (!($course = $DB->get_record('course', array('id' => $checklist->course)))) { return; } if (!($cm = get_coursemodule_from_instance('checklist', $checklist->id, $course->id))) { return; } $checkgroupings = false; // Don't check items against groupings unless we really have to if (isset($CFG->enablegroupmembersonly) && $CFG->enablegroupmembersonly && $checklist->autopopulate) { foreach ($items as $item) { if ($item->grouping) { $checkgroupings = true; break; } } } if ($checklist->teacheredit == CHECKLIST_MARKING_STUDENT) { $date = ', MAX(c.usertimestamp) AS datesubmitted'; $where = 'c.usertimestamp > 0'; } else { $date = ', MAX(c.teachertimestamp) AS dategraded'; $where = 'c.teachermark = ' . CHECKLIST_TEACHERMARK_YES; } if ($checkgroupings) { if ($userid) { $users = $DB->get_records('user', array('id' => $userid), null, 'id, firstname, lastname'); } else { if ($CFG->version < 2011120100) { $context = get_context_instance(CONTEXT_MODULE, $cm->id); } else { $context = context_module::instance($cm->id); } if (!($users = get_users_by_capability($context, 'mod/checklist:updateown', 'u.id, u.firstname, u.lastname', '', '', '', '', '', false))) { return; } } $grades = array(); // With groupings, need to update each user individually (as each has different groupings) foreach ($users as $userid => $user) { $groupings = checklist_class::get_user_groupings($userid, $course->id); $total = 0; $itemlist = ''; foreach ($items as $item) { if ($item->grouping) { if (!in_array($item->grouping, $groupings)) { continue; } } $itemlist .= $item->id . ','; $total++; } if (!$total) { // No items - set score to 0 $ugrade = new stdClass(); $ugrade->userid = $userid; $ugrade->rawgrade = 0; $ugrade->date = time(); } else { $itemlist = substr($itemlist, 0, -1); // Remove trailing ',' $sql = 'SELECT ? AS userid, (SUM(CASE WHEN ' . $where . ' THEN 1 ELSE 0 END) * ? / ? ) AS rawgrade' . $date; $sql .= " FROM {checklist_check} c "; $sql .= " WHERE c.item IN ({$itemlist})"; $sql .= ' AND c.userid = ? '; $ugrade = $DB->get_record_sql($sql, array($userid, $checklist->maxgrade, $total, $userid)); if (!$ugrade) { $ugrade = new stdClass(); $ugrade->userid = $userid; $ugrade->rawgrade = 0; $ugrade->date = time(); } } $ugrade->firstname = $user->firstname; $ugrade->lastname = $user->lastname; $grades[$userid] = $ugrade; } } else { // No need to check groupings, so update all student grades at once if ($userid) { $users = $userid; } else { if ($CFG->version < 2011120100) { $context = get_context_instance(CONTEXT_MODULE, $cm->id); } else { $context = context_module::instance($cm->id); } if (!($users = get_users_by_capability($context, 'mod/checklist:updateown', 'u.id', '', '', '', '', '', false))) { return; } $users = array_keys($users); } $total = count($items); list($usql, $uparams) = $DB->get_in_or_equal($users); list($isql, $iparams) = $DB->get_in_or_equal(array_keys($items)); $sql = 'SELECT u.id AS userid, (SUM(CASE WHEN ' . $where . ' THEN 1 ELSE 0 END) * ? / ? ) AS rawgrade' . $date; $sql .= ' , u.firstname, u.lastname '; $sql .= ' FROM {user} u LEFT JOIN {checklist_check} c ON u.id = c.userid'; $sql .= " WHERE u.id {$usql}"; $sql .= " AND c.item {$isql}"; $sql .= ' GROUP BY u.id, u.firstname, u.lastname'; $params = array_merge($uparams, $iparams); $params = array_merge(array($checklist->maxgrade, $total), $params); $grades = $DB->get_records_sql($sql, $params); } foreach ($grades as $grade) { // Log completion of checklist if ($grade->rawgrade == $checklist->maxgrade) { if ($checklist->emailoncomplete) { $timelimit = time() - 1 * 60 * 60; // Do not send another email if this checklist was already 'completed' in the last hour $filter = "l.time > ? AND l.cmid = ? AND l.userid = ? AND l.action = 'complete'"; get_logs($filter, array($timelimit, $cm->id, $grade->userid), '', 1, 1, $logcount); if ($logcount == 0) { if (!isset($context)) { if ($CFG->version < 2011120100) { $context = get_context_instance(CONTEXT_MODULE, $cm->id); } else { $context = context_module::instance($cm->id); } } if ($recipients = get_users_by_capability($context, 'mod/checklist:emailoncomplete', 'u.*', '', '', '', '', '', false)) { foreach ($recipients as $recipient) { $details = new stdClass(); $details->user = fullname($grade); $details->checklist = s($checklist->name); $subj = get_string('emailoncompletesubject', 'checklist', $details); $content = get_string('emailoncompletebody', 'checklist', $details); $content .= $CFG->wwwroot . '/mod/checklist/view.php?id=' . $cm->id; email_to_user($recipient, $grade, $subj, $content, '', '', '', false); } } } } add_to_log($checklist->course, 'checklist', 'complete', "view.php?id={$cm->id}", $checklist->name, $cm->id, $grade->userid); } $ci = new completion_info($course); if ($cm->completion == COMPLETION_TRACKING_AUTOMATIC) { $ci->update_state($cm, COMPLETION_UNKNOWN, $grade->userid); } } checklist_grade_item_update($checklist, $grades); }
/** * Mark the activity completed (if required) and trigger the page_viewed event. * * @param stdClass $wiki Wiki object. * @param stdClass $page Page object. * @param stdClass $course Course object. * @param stdClass $cm Course module object. * @param stdClass $context Context object. * @param int $uid Optional User ID. * @param array $other Optional Other params: title, wiki ID, group ID, groupanduser, prettyview. * @param stdClass $subwiki Optional Subwiki. * @since Moodle 3.1 */ function wiki_page_view($wiki, $page, $course, $cm, $context, $uid = null, $other = null, $subwiki = null) { // Trigger course_module_viewed event. $params = array('context' => $context, 'objectid' => $page->id); if ($uid != null) { $params['relateduserid'] = $uid; } if ($other != null) { $params['other'] = $other; } $event = \mod_wiki\event\page_viewed::create($params); $event->add_record_snapshot('wiki_pages', $page); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('wiki', $wiki); if ($subwiki != null) { $event->add_record_snapshot('wiki_subwikis', $subwiki); } $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($cm); }
} } else { echo $OUTPUT->notification('An error occurred while moving a section'); } } } } } else { $USER->editing = 0; } $SESSION->fromdiscussion = $PAGE->url->out(false); if ($course->id == SITEID) { // This course is not a real course. redirect($CFG->wwwroot . '/'); } $completion = new completion_info($course); if ($completion->is_enabled() && ajaxenabled()) { $PAGE->requires->string_for_js('completion-title-manual-y', 'completion'); $PAGE->requires->string_for_js('completion-title-manual-n', 'completion'); $PAGE->requires->string_for_js('completion-alt-manual-y', 'completion'); $PAGE->requires->string_for_js('completion-alt-manual-n', 'completion'); $PAGE->requires->js_init_call('M.core_completion.init'); } // We are currently keeping the button here from 1.x to help new teachers figure out // what to do, even though the link also appears in the course admin block. It also // means you can back out of a situation where you removed the admin block. :) if ($PAGE->user_allowed_editing()) { $buttons = $OUTPUT->edit_button($PAGE->url); $PAGE->set_button($buttons); } $PAGE->set_title(get_string('course') . ': ' . $course->fullname);
case get_string("optionid", "booking"): $optionIDPos = $key; break; case get_string("user") . " " . get_string("idnumber"): $userIDPos = $key; break; case get_string("searchFinished", "booking"): $completedPos = $key; break; default: break; } } if ($optionIDPos > -1 && $userIDPos > -1 && $completedPos > -1) { array_shift($csvArr); $completion = new completion_info($course); foreach ($csvArr as $line) { if (count($line) >= 3) { $user = $DB->get_record('booking_answers', array('bookingid' => $booking->id, 'userid' => $line[$userIDPos], 'optionid' => $line[$optionIDPos])); if ($user !== FALSE) { $user->completed = $line[$completedPos]; $user->timemodified = time(); $DB->update_record('booking_answers', $user, false); if ($completion->is_enabled($cm) && $booking->enablecompletion && $user->completed == 0) { $completion->update_state($cm, COMPLETION_INCOMPLETE, $user->userid); } if ($completion->is_enabled($cm) && $booking->enablecompletion && $user->completed == 1) { $completion->update_state($cm, COMPLETION_COMPLETE, $user->userid); } } }