function test_is_enabled() { global $CFG; // Config alone $CFG->enablecompletion = COMPLETION_DISABLED; $this->assertEquals(COMPLETION_DISABLED, completion_info::is_enabled_for_site()); $CFG->enablecompletion = COMPLETION_ENABLED; $this->assertEquals(COMPLETION_ENABLED, completion_info::is_enabled_for_site()); // Course $course = (object)array('id' =>13); $c = new completion_info($course); $course->enablecompletion = COMPLETION_DISABLED; $this->assertEquals(COMPLETION_DISABLED, $c->is_enabled()); $course->enablecompletion = COMPLETION_ENABLED; $this->assertEquals(COMPLETION_ENABLED, $c->is_enabled()); $CFG->enablecompletion = COMPLETION_DISABLED; $this->assertEquals(COMPLETION_DISABLED, $c->is_enabled()); // Course and CM $cm = new stdClass(); $cm->completion = COMPLETION_TRACKING_MANUAL; $this->assertEquals(COMPLETION_DISABLED, $c->is_enabled($cm)); $CFG->enablecompletion = COMPLETION_ENABLED; $course->enablecompletion = COMPLETION_DISABLED; $this->assertEquals(COMPLETION_DISABLED, $c->is_enabled($cm)); $course->enablecompletion = COMPLETION_ENABLED; $this->assertEquals(COMPLETION_TRACKING_MANUAL, $c->is_enabled($cm)); $cm->completion = COMPLETION_TRACKING_NONE; $this->assertEquals(COMPLETION_TRACKING_NONE, $c->is_enabled($cm)); $cm->completion = COMPLETION_TRACKING_AUTOMATIC; $this->assertEquals(COMPLETION_TRACKING_AUTOMATIC, $c->is_enabled($cm)); }
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); } } }
/** * 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); }
/** * 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 ''; } } } }
/** * 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; }
/** * 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; }
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; }
/** * 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', '')); } }
/** * * @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); } }
/** * 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; }
/** * @global object * @param array $userids * @param object $choicegroup Choice main table row * @param object $cm Course-module object * @param object $course Course object * @return bool */ function choicegroup_delete_responses($userids, $choicegroup, $cm, $course) { global $CFG, $DB, $context; require_once $CFG->libdir . '/completionlib.php'; if (!is_array($userids) || empty($userids)) { return false; } foreach ($userids as $num => $userid) { if (empty($userid)) { unset($userids[$num]); } } $completion = new completion_info($course); $eventparams = array('context' => $context, 'objectid' => $choicegroup->id); foreach ($userids as $userid) { if ($current = choicegroup_get_user_answer($choicegroup, $userid)) { $currentgroup = $DB->get_record('groups', array('id' => $current->id), 'id,name', MUST_EXIST); if (groups_is_member($current->id, $userid)) { groups_remove_member($current->id, $userid); $event = \mod_choicegroup\event\choice_removed::create($eventparams); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('choicegroup', $choicegroup); $event->trigger(); } // Update completion state if ($completion->is_enabled($cm) && $choicegroup->completionsubmit) { $completion->update_state($cm, COMPLETION_INCOMPLETE, $userid); } } } return true; }
/** * Add a record to the facetoface submissions table and sends out an * email confirmation * * @param class $session record from the facetoface_sessions table * @param class $facetoface record from the facetoface table * @param class $course record from the course table * @param string $discountcode code entered by the user * @param integer $notificationtype type of notifications to send to user * @see {{MDL_F2F_INVITE}} * @param integer $statuscode Status code to set * @param integer $userid user to signup * @param bool $notifyuser whether or not to send an email confirmation * @param bool $displayerrors whether or not to return an error page on errors */ function facetoface_user_signup($session, $facetoface, $course, $discountcode, $notificationtype, $statuscode, $userid = false, $notifyuser = true) { global $DB, $OUTPUT, $USER; // Get user id if (!$userid) { $userid = $USER->id; } $return = false; $timenow = time(); // Check to see if a signup already exists if ($existingsignup = $DB->get_record('facetoface_signups', array('sessionid' => $session->id, 'userid' => $userid))) { $usersignup = $existingsignup; } else { // Otherwise, prepare a signup object $usersignup = new stdClass(); $usersignup->sessionid = $session->id; $usersignup->userid = $userid; } $usersignup->mailedreminder = 0; $usersignup->notificationtype = $notificationtype; $usersignup->discountcode = trim(strtoupper($discountcode)); if (empty($usersignup->discountcode)) { $usersignup->discountcode = null; } // Update/insert the signup record if (!empty($usersignup->id)) { $success = $DB->update_record('facetoface_signups', $usersignup); } else { $usersignup->id = $DB->insert_record('facetoface_signups', $usersignup); $success = (bool)$usersignup->id; } if (!$success) { print_error('error:couldnotupdatef2frecord', 'facetoface'); } // Work out which status to use // If approval not required if (!$facetoface->approvalreqd) { $new_status = $statuscode; } else { // If approval required // Get current status (if any) $current_status = $DB->get_field('facetoface_signups_status', 'statuscode', array('signupid' => $usersignup->id, 'superceded' => 0)); // If approved, then no problem if ($current_status == MDL_F2F_STATUS_APPROVED) { $new_status = $statuscode; } else if ($session->datetimeknown) { // If currently on the waitlist they have already been approved, no need to approve them again. if ($current_status == MDL_F2F_STATUS_WAITLISTED) { $new_status = $statuscode; } else { // Otherwise, send manager request. $new_status = MDL_F2F_STATUS_REQUESTED; } } else { $new_status = MDL_F2F_STATUS_WAITLISTED; } } // Update status. if (!facetoface_update_signup_status($usersignup->id, $new_status, $USER->id)) { print_error('error:f2ffailedupdatestatus', 'facetoface'); } // Add to user calendar -- if facetoface usercalentry is set to true if ($facetoface->usercalentry && in_array($new_status, array(MDL_F2F_STATUS_BOOKED, MDL_F2F_STATUS_WAITLISTED))) { facetoface_add_session_to_calendar($session, $facetoface, 'user', $userid, 'booking'); } // If session has already started, do not send a notification if (facetoface_has_session_started($session, $timenow)) { $notifyuser = false; } // Send notification. $notifytype = ((int)$notificationtype == MDL_F2F_NONE ? false : true); $session->notifyuser = $notifyuser && $notifytype; switch ($new_status) { case MDL_F2F_STATUS_BOOKED: $error = facetoface_send_confirmation_notice($facetoface, $session, $userid, $notificationtype, false); break; case MDL_F2F_STATUS_WAITLISTED: $error = facetoface_send_confirmation_notice($facetoface, $session, $userid, $notificationtype, true); break; case MDL_F2F_STATUS_REQUESTED: $error = facetoface_send_request_notice($facetoface, $session, $userid); break; } if (!empty($error)) { if ($error == 'userdoesnotexist') { print_error($error, 'facetoface'); } else { // Don't fail if email isn't sent, just display a warning echo $OUTPUT->notification(get_string($error, 'facetoface'), 'notifyproblem'); } } if ($session->notifyuser) { if (!$DB->update_record('facetoface_signups', $usersignup)) { print_error('error:couldnotupdatef2frecord', 'facetoface'); } } // Update course completion. if (in_array($new_status, array(MDL_F2F_STATUS_BOOKED, MDL_F2F_STATUS_WAITLISTED))) { $completion = new completion_info($course); if ($completion->is_enabled()) { $ccdetails = array( 'course' => $course->id, 'userid' => $userid, ); $cc = new completion_completion($ccdetails); $cc->mark_inprogress($timenow); } } return true; }
/** * Revert to draft. * * @param int $userid * @return boolean */ public function revert_to_draft($userid) { global $DB, $USER; // Need grade permission. require_capability('mod/assign:grade', $this->context); if ($this->get_instance()->teamsubmission) { $submission = $this->get_group_submission($userid, 0, false); } else { $submission = $this->get_user_submission($userid, false); } if (!$submission) { return false; } $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT; $this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission); // Give each submission plugin a chance to process the reverting to draft. $plugins = $this->get_submission_plugins(); foreach ($plugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { $plugin->revert_to_draft($submission); } } // Update the modified time on the grade (grader modified). $grade = $this->get_user_grade($userid, true); $grade->grader = $USER->id; $this->update_grade($grade); $completion = new completion_info($this->get_course()); if ($completion->is_enabled($this->get_course_module()) && $this->get_instance()->completionsubmit) { $completion->update_state($this->get_course_module(), COMPLETION_INCOMPLETE, $userid); } \mod_assign\event\submission_status_updated::create_from_submission($this, $submission)->trigger(); return true; }
/** * Prints a section full of activity modules */ function print_section($course, $section, $mods, $modnamesused, $absolute = false, $width = "100%", $hidecompletion = false) { global $CFG, $USER, $DB, $PAGE, $OUTPUT; static $initialised; static $groupbuttons; static $groupbuttonslink; static $isediting; static $ismoving; static $strmovehere; static $strmovefull; static $strunreadpostsone; static $groupings; static $modulenames; if (!isset($initialised)) { $groupbuttons = ($course->groupmode or !$course->groupmodeforce); $groupbuttonslink = !$course->groupmodeforce; $isediting = $PAGE->user_is_editing(); $ismoving = $isediting && ismoving($course->id); if ($ismoving) { $strmovehere = get_string("movehere"); $strmovefull = strip_tags(get_string("movefull", "", "'{$USER->activitycopyname}'")); } $modulenames = array(); $initialised = true; } $modinfo = get_fast_modinfo($course); $completioninfo = new completion_info($course); //Accessibility: replace table with list <ul>, but don't output empty list. if (!empty($section->sequence)) { // Fix bug #5027, don't want style=\"width:$width\". echo "<ul class=\"section img-text\">\n"; $sectionmods = explode(",", $section->sequence); foreach ($sectionmods as $modnumber) { if (empty($mods[$modnumber])) { continue; } /** * @var cm_info */ $mod = $mods[$modnumber]; if ($ismoving and $mod->id == $USER->activitycopy) { // do not display moving mod continue; } if (isset($modinfo->cms[$modnumber])) { // We can continue (because it will not be displayed at all) // if: // 1) The activity is not visible to users // and // 2a) The 'showavailability' option is not set (if that is set, // we need to display the activity so we can show // availability info) // or // 2b) The 'availableinfo' is empty, i.e. the activity was // hidden in a way that leaves no info, such as using the // eye icon. if (!$modinfo->cms[$modnumber]->uservisible && (empty($modinfo->cms[$modnumber]->showavailability) || empty($modinfo->cms[$modnumber]->availableinfo))) { // visibility shortcut continue; } } else { if (!file_exists("{$CFG->dirroot}/mod/{$mod->modname}/lib.php")) { // module not installed continue; } if (!coursemodule_visible_for_user($mod) && empty($mod->showavailability)) { // full visibility check continue; } } if (!isset($modulenames[$mod->modname])) { $modulenames[$mod->modname] = get_string('modulename', $mod->modname); } $modulename = $modulenames[$mod->modname]; // In some cases the activity is visible to user, but it is // dimmed. This is done if viewhiddenactivities is true and if: // 1. the activity is not visible, or // 2. the activity has dates set which do not include current, or // 3. the activity has any other conditions set (regardless of whether // current user meets them) $canviewhidden = has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $mod->id)); $accessiblebutdim = false; if ($canviewhidden) { $accessiblebutdim = !$mod->visible; if (!empty($CFG->enableavailability)) { $accessiblebutdim = $accessiblebutdim || $mod->availablefrom > time() || $mod->availableuntil && $mod->availableuntil < time() || count($mod->conditionsgrade) > 0 || count($mod->conditionscompletion) > 0; } } $liclasses = array(); $liclasses[] = 'activity'; $liclasses[] = $mod->modname; $liclasses[] = 'modtype_' . $mod->modname; $extraclasses = $mod->get_extra_classes(); if ($extraclasses) { $liclasses = array_merge($liclasses, explode(' ', $extraclasses)); } echo html_writer::start_tag('li', array('class' => join(' ', $liclasses), 'id' => 'module-' . $modnumber)); if ($ismoving) { echo '<a title="' . $strmovefull . '"' . ' href="' . $CFG->wwwroot . '/course/mod.php?moveto=' . $mod->id . '&sesskey=' . sesskey() . '">' . '<img class="movetarget" src="' . $OUTPUT->pix_url('movehere') . '" ' . ' alt="' . $strmovehere . '" /></a><br /> '; } $classes = array('mod-indent'); if (!empty($mod->indent)) { $classes[] = 'mod-indent-' . $mod->indent; if ($mod->indent > 15) { $classes[] = 'mod-indent-huge'; } } echo html_writer::start_tag('div', array('class' => join(' ', $classes))); // Get data about this course-module list($content, $instancename) = get_print_section_cm_text($modinfo->cms[$modnumber], $course); //Accessibility: for files get description via icon, this is very ugly hack! $altname = ''; $altname = $mod->modfullname; if (!empty($customicon)) { $archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); if ($archetype == MOD_ARCHETYPE_RESOURCE) { $mimetype = mimeinfo_from_icon('type', $customicon); $altname = get_mimetype_description($mimetype); } } // Avoid unnecessary duplication: if e.g. a forum name already // includes the word forum (or Forum, etc) then it is unhelpful // to include that in the accessible description that is added. if (false !== strpos(textlib::strtolower($instancename), textlib::strtolower($altname))) { $altname = ''; } // File type after name, for alphabetic lists (screen reader). if ($altname) { $altname = get_accesshide(' ' . $altname); } // We may be displaying this just in order to show information // about visibility, without the actual link $contentpart = ''; if ($mod->uservisible) { // Nope - in this case the link is fully working for user $linkclasses = ''; $textclasses = ''; if ($accessiblebutdim) { $linkclasses .= ' dimmed'; $textclasses .= ' dimmed_text'; $accesstext = '<span class="accesshide">' . get_string('hiddenfromstudents') . ': </span>'; } else { $accesstext = ''; } if ($linkclasses) { $linkcss = 'class="' . trim($linkclasses) . '" '; } else { $linkcss = ''; } if ($textclasses) { $textcss = 'class="' . trim($textclasses) . '" '; } else { $textcss = ''; } // Get on-click attribute value if specified $onclick = $mod->get_on_click(); if ($onclick) { $onclick = ' onclick="' . $onclick . '"'; } if ($url = $mod->get_url()) { // Display link itself echo '<a ' . $linkcss . $mod->extra . $onclick . ' href="' . $url . '"><img src="' . $mod->get_icon_url() . '" class="activityicon" alt="' . $modulename . '" /> ' . $accesstext . '<span class="instancename">' . $instancename . $altname . '</span></a>'; // If specified, display extra content after link if ($content) { $contentpart = '<div class="' . trim('contentafterlink' . $textclasses) . '">' . $content . '</div>'; } } else { // No link, so display only content $contentpart = '<div ' . $textcss . $mod->extra . '>' . $accesstext . $content . '</div>'; } if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { if (!isset($groupings)) { $groupings = groups_get_all_groupings($course->id); } echo " <span class=\"groupinglabel\">(" . format_string($groupings[$mod->groupingid]->name) . ')</span>'; } } else { $textclasses = $extraclasses; $textclasses .= ' dimmed_text'; if ($textclasses) { $textcss = 'class="' . trim($textclasses) . '" '; } else { $textcss = ''; } $accesstext = '<span class="accesshide">' . get_string('notavailableyet', 'condition') . ': </span>'; if ($url = $mod->get_url()) { // Display greyed-out text of link echo '<div ' . $textcss . $mod->extra . ' >' . '<img src="' . $mod->get_icon_url() . '" class="activityicon" alt="' . $modulename . '" /> <span>' . $instancename . $altname . '</span></div>'; // Do not display content after link when it is greyed out like this. } else { // No link, so display only content (also greyed) $contentpart = '<div ' . $textcss . $mod->extra . '>' . $accesstext . $content . '</div>'; } } // Module can put text after the link (e.g. forum unread) echo $mod->get_after_link(); // If there is content but NO link (eg label), then display the // content here (BEFORE any icons). In this case cons must be // displayed after the content so that it makes more sense visually // and for accessibility reasons, e.g. if you have a one-line label // it should work similarly (at least in terms of ordering) to an // activity. if (empty($url)) { echo $contentpart; } if ($isediting) { if ($groupbuttons and plugin_supports('mod', $mod->modname, FEATURE_GROUPS, 0)) { if (!($mod->groupmodelink = $groupbuttonslink)) { $mod->groupmode = $course->groupmode; } } else { $mod->groupmode = false; } echo ' '; echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section); echo $mod->get_after_edit_icons(); } // Completion $completion = $hidecompletion ? COMPLETION_TRACKING_NONE : $completioninfo->is_enabled($mod); if ($completion != COMPLETION_TRACKING_NONE && isloggedin() && !isguestuser() && $mod->uservisible) { $completiondata = $completioninfo->get_data($mod, true); $completionicon = ''; if ($isediting) { switch ($completion) { case COMPLETION_TRACKING_MANUAL: $completionicon = 'manual-enabled'; break; case COMPLETION_TRACKING_AUTOMATIC: $completionicon = 'auto-enabled'; break; default: // wtf } } else { if ($completion == COMPLETION_TRACKING_MANUAL) { switch ($completiondata->completionstate) { case COMPLETION_INCOMPLETE: $completionicon = 'manual-n'; break; case COMPLETION_COMPLETE: $completionicon = 'manual-y'; break; } } else { // Automatic switch ($completiondata->completionstate) { case COMPLETION_INCOMPLETE: $completionicon = 'auto-n'; break; case COMPLETION_COMPLETE: $completionicon = 'auto-y'; break; case COMPLETION_COMPLETE_PASS: $completionicon = 'auto-pass'; break; case COMPLETION_COMPLETE_FAIL: $completionicon = 'auto-fail'; break; } } } if ($completionicon) { $imgsrc = $OUTPUT->pix_url('i/completion-' . $completionicon); $imgalt = s(get_string('completion-alt-' . $completionicon, 'completion', $mod->name)); if ($completion == COMPLETION_TRACKING_MANUAL && !$isediting) { $imgtitle = s(get_string('completion-title-' . $completionicon, 'completion', $mod->name)); $newstate = $completiondata->completionstate == COMPLETION_COMPLETE ? COMPLETION_INCOMPLETE : COMPLETION_COMPLETE; // In manual mode the icon is a toggle form... // If this completion state is used by the // conditional activities system, we need to turn // off the JS. if (!empty($CFG->enableavailability) && condition_info::completion_value_used_as_condition($course, $mod)) { $extraclass = ' preventjs'; } else { $extraclass = ''; } echo "\n<form class='togglecompletion{$extraclass}' method='post' action='" . $CFG->wwwroot . "/course/togglecompletion.php'><div>\n<input type='hidden' name='id' value='{$mod->id}' />\n<input type='hidden' name='modulename' value='" . s($mod->name) . "' />\n<input type='hidden' name='sesskey' value='" . sesskey() . "' />\n<input type='hidden' name='completionstate' value='{$newstate}' />\n<input type='image' src='{$imgsrc}' alt='{$imgalt}' title='{$imgtitle}' />\n</div></form>"; } else { // In auto mode, or when editing, the icon is just an image echo "<span class='autocompletion'>"; echo "<img src='{$imgsrc}' alt='{$imgalt}' title='{$imgalt}' /></span>"; } } } // If there is content AND a link, then display the content here // (AFTER any icons). Otherwise it was displayed before if (!empty($url)) { echo $contentpart; } // Show availability information (for someone who isn't allowed to // see the activity itself, or for staff) if (!$mod->uservisible) { echo '<div class="availabilityinfo">' . $mod->availableinfo . '</div>'; } else { if ($canviewhidden && !empty($CFG->enableavailability)) { $ci = new condition_info($mod); $fullinfo = $ci->get_full_information(); if ($fullinfo) { echo '<div class="availabilityinfo">' . get_string($mod->showavailability ? 'userrestriction_visible' : 'userrestriction_hidden', 'condition', $fullinfo) . '</div>'; } } } echo html_writer::end_tag('div'); echo html_writer::end_tag('li') . "\n"; } } elseif ($ismoving) { echo "<ul class=\"section\">\n"; } if ($ismoving) { echo '<li><a title="' . $strmovefull . '"' . ' href="' . $CFG->wwwroot . '/course/mod.php?movetosection=' . $section->id . '&sesskey=' . sesskey() . '">' . '<img class="movetarget" src="' . $OUTPUT->pix_url('movehere') . '" ' . ' alt="' . $strmovehere . '" /></a></li> '; } if (!empty($section->sequence) || $ismoving) { echo "</ul><!--class='section'-->\n\n"; } }
// if we're printing stuff about the file upload $timemessage = 4; } if ($fromform->mailnow) { $message .= get_string("postmailnow", "forum"); $timemessage = 4; } else { $message .= '<p>' . get_string("postaddedsuccess", "forum") . '</p>'; $message .= '<p>' . get_string("postaddedtimeleft", "forum", format_time($CFG->maxeditingtime)) . '</p>'; } if ($subscribemessage = forum_post_subscription($discussion, $forum)) { $timemessage = 4; } // Update completion status $completion = new completion_info($course); if ($completion->is_enabled($cm) && ($forum->completiondiscussions || $forum->completionposts)) { $completion->update_state($cm, COMPLETION_COMPLETE); } redirect(forum_go_back_to("view.php?f={$fromform->forum}"), $message . $subscribemessage, $timemessage); } else { print_error("couldnotadd", "forum", $errordestination); } exit; } } } // To get here they need to edit a post, and the $post // variable will be loaded with all the particulars, // so bring up the form. // $course, $forum are defined. $discussion is for edit and reply only. if ($post->discussion) {
* @date 2015/12/19 */ set_user_preference('docked_block_instance_4', 1); set_user_preference('docked_block_instance_5', 1); set_user_preference('docked_block_instance_19', 1); set_user_preference('docked_block_instance_20', 1); set_user_preference('docked_block_instance_21', 1); set_user_preference('docked_block_instance_22', 1); } $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()) { $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); } // If viewing a section, make the title more specific if ($section and $section > 0 and course_format_uses_sections($course->format)) {
/** * Revert to draft. * * @param int $userid * @return boolean */ public function revert_to_draft($userid) { global $DB, $USER; // Need grade permission. require_capability('mod/assign:grade', $this->context); if ($this->get_instance()->teamsubmission) { $submission = $this->get_group_submission($userid, 0, false); } else { $submission = $this->get_user_submission($userid, false); } if (!$submission) { return false; } $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT; $this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission); // Give each submission plugin a chance to process the reverting to draft. $plugins = $this->get_submission_plugins(); foreach ($plugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { $plugin->revert_to_draft($submission); } } // Update the modified time on the grade (grader modified). $grade = $this->get_user_grade($userid, true); $grade->grader = $USER->id; $this->update_grade($grade); $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); $completion = new completion_info($this->get_course()); if ($completion->is_enabled($this->get_course_module()) && $this->get_instance()->completionsubmit) { $completion->update_state($this->get_course_module(), COMPLETION_INCOMPLETE, $userid); } $logmessage = get_string('reverttodraftforstudent', 'assign', array('id' => $user->id, 'fullname' => fullname($user))); $addtolog = $this->add_to_log('revert submission to draft', $logmessage, '', true); $params = array('context' => $this->context, 'objectid' => $submission->id, 'relateduserid' => $this->get_instance()->teamsubmission ? null : $userid, 'other' => array('newstatus' => $submission->status)); $event = \mod_assign\event\submission_status_updated::create($params); $event->set_legacy_logdata($addtolog); $event->trigger(); return true; }
$context = context_module::instance($cm->id); require_capability('mod/glossary:approve', $context); if ($newstate != $entry->approved && confirm_sesskey()) { $newentry = new stdClass(); $newentry->id = $entry->id; $newentry->approved = $newstate; $newentry->timemodified = time(); // wee need this date here to speed up recent activity, TODO: use timestamp in approved field instead in 2.0 $DB->update_record("glossary_entries", $newentry); // Trigger event about entry approval/disapproval. $params = array('context' => $context, 'objectid' => $entry->id); if ($newstate) { $event = \mod_glossary\event\entry_approved::create($params); } else { $event = \mod_glossary\event\entry_disapproved::create($params); } $entry->approved = $newstate ? 1 : 0; $entry->timemodified = $newentry->timemodified; $event->add_record_snapshot('glossary_entries', $entry); $event->trigger(); // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC && $glossary->completionentries) { $completion->update_state($cm, COMPLETION_COMPLETE, $entry->userid); } // Reset caches. if ($entry->usedynalink) { \mod_glossary\local\concept_cache::reset_glossary($glossary); } } redirect("view.php?id={$cm->id}&mode={$mode}&hook={$hook}");
} require_course_login($course, false, $cm); if (!($choice = choice_get_choice($cm->instance))) { print_error('invalidcoursemodule'); } $strchoice = get_string('modulename', 'choice'); $strchoices = get_string('modulenameplural', 'choice'); $context = context_module::instance($cm->id); list($choiceavailable, $warnings) = choice_get_availability_status($choice); if ($action == 'delchoice' and confirm_sesskey() and is_enrolled($context, NULL, 'mod/choice:choose') and $choice->allowupdate and $choiceavailable) { $answercount = $DB->count_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id)); if ($answercount > 0) { $DB->delete_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id)); // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $choice->completionsubmit) { $completion->update_state($cm, COMPLETION_INCOMPLETE); } redirect("view.php?id={$cm->id}"); } } $PAGE->set_title($choice->name); $PAGE->set_heading($course->fullname); /// Submit any new data if there is any if (data_submitted() && is_enrolled($context, NULL, 'mod/choice:choose') && confirm_sesskey()) { $timenow = time(); if (has_capability('mod/choice:deleteresponses', $context) && $action == 'delete') { //some responses need to be deleted choice_delete_responses($attemptids, $choice, $cm, $course); //delete responses. redirect("view.php?id={$cm->id}");
/** * deletes a completed given by completedid. * all related data such values or tracking data also will be deleted * * @global object * @param int $completedid * @return boolean */ function feedback_delete_completed($completedid) { global $DB, $CFG; require_once($CFG->libdir.'/completionlib.php'); if (!$completed = $DB->get_record('feedback_completed', array('id'=>$completedid))) { return false; } if (!$feedback = $DB->get_record('feedback', array('id'=>$completed->feedback))) { return false; } if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) { return false; } if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) { return false; } //first we delete all related values $DB->delete_records('feedback_value', array('completed'=>$completed->id)); //now we delete all tracking data $params = array('completed'=>$completed->id, 'feedback'=>$completed->feedback); if ($tracking = $DB->get_record('feedback_tracking', $params)) { $DB->delete_records('feedback_tracking', array('completed'=>$completed->id)); } // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $feedback->completionsubmit) { $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid); } //last we delete the completed-record return $DB->delete_records('feedback_completed', array('id'=>$completed->id)); }
} 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); $PAGE->set_heading($course->fullname);
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); } } } } redirect($urlRedirect, get_string('importfinished', 'booking'), 5); } else { redirect($urlRedirect, get_string('wrongfile', 'booking'), 5); } //In this case you process validated data. $mform->get_data() returns data posted in form. } else { echo $OUTPUT->header();
/** * Adds all the standard elements to a form to edit the settings for an activity module. */ function standard_coursemodule_elements() { global $COURSE, $CFG, $DB; $mform =& $this->_form; $this->_outcomesused = false; if ($this->_features->outcomes) { if ($outcomes = grade_outcome::fetch_all_available($COURSE->id)) { $this->_outcomesused = true; $mform->addElement('header', 'modoutcomes', get_string('outcomes', 'grades')); foreach ($outcomes as $outcome) { $mform->addElement('advcheckbox', 'outcome_' . $outcome->id, $outcome->get_name()); } } } if ($this->_features->rating) { require_once $CFG->dirroot . '/rating/lib.php'; $rm = new rating_manager(); $mform->addElement('header', 'modstandardratings', get_string('ratings', 'rating')); $permission = CAP_ALLOW; $rolenamestring = null; if (!empty($this->_cm)) { $context = context_module::instance($this->_cm->id); $rolenames = get_role_names_with_caps_in_context($context, array('moodle/rating:rate', 'mod/' . $this->_cm->modname . ':rate')); $rolenamestring = implode(', ', $rolenames); } else { $rolenamestring = get_string('capabilitychecknotavailable', 'rating'); } $mform->addElement('static', 'rolewarning', get_string('rolewarning', 'rating'), $rolenamestring); $mform->addHelpButton('rolewarning', 'rolewarning', 'rating'); $mform->addElement('select', 'assessed', get_string('aggregatetype', 'rating'), $rm->get_aggregate_types()); $mform->setDefault('assessed', 0); $mform->addHelpButton('assessed', 'aggregatetype', 'rating'); $mform->addElement('modgrade', 'scale', get_string('scale'), false); $mform->disabledIf('scale', 'assessed', 'eq', 0); $mform->addHelpButton('scale', 'modgrade', 'grades'); $mform->setDefault('scale', $CFG->gradepointdefault); $mform->addElement('checkbox', 'ratingtime', get_string('ratingtime', 'rating')); $mform->disabledIf('ratingtime', 'assessed', 'eq', 0); $mform->addElement('date_time_selector', 'assesstimestart', get_string('from')); $mform->disabledIf('assesstimestart', 'assessed', 'eq', 0); $mform->disabledIf('assesstimestart', 'ratingtime'); $mform->addElement('date_time_selector', 'assesstimefinish', get_string('to')); $mform->disabledIf('assesstimefinish', 'assessed', 'eq', 0); $mform->disabledIf('assesstimefinish', 'ratingtime'); } //doing this here means splitting up the grade related settings on the lesson settings page //$this->standard_grading_coursemodule_elements(); $mform->addElement('header', 'modstandardelshdr', get_string('modstandardels', 'form')); $mform->addElement('modvisible', 'visible', get_string('visible')); if (!empty($this->_cm)) { $context = context_module::instance($this->_cm->id); if (!has_capability('moodle/course:activityvisibility', $context)) { $mform->hardFreeze('visible'); } } if ($this->_features->idnumber) { $mform->addElement('text', 'cmidnumber', get_string('idnumbermod')); $mform->setType('cmidnumber', PARAM_RAW); $mform->addHelpButton('cmidnumber', 'idnumbermod'); } if ($this->_features->groups) { $options = array(NOGROUPS => get_string('groupsnone'), SEPARATEGROUPS => get_string('groupsseparate'), VISIBLEGROUPS => get_string('groupsvisible')); $mform->addElement('select', 'groupmode', get_string('groupmode', 'group'), $options, NOGROUPS); $mform->addHelpButton('groupmode', 'groupmode', 'group'); } if ($this->_features->groupings) { // Groupings selector - used to select grouping for groups in activity. $options = array(); if ($groupings = $DB->get_records('groupings', array('courseid' => $COURSE->id))) { foreach ($groupings as $grouping) { $options[$grouping->id] = format_string($grouping->name); } } core_collator::asort($options); $options = array(0 => get_string('none')) + $options; $mform->addElement('select', 'groupingid', get_string('grouping', 'group'), $options); $mform->addHelpButton('groupingid', 'grouping', 'group'); } if (!empty($CFG->enableavailability)) { // Add special button to end of previous section if groups/groupings // are enabled. if ($this->_features->groups || $this->_features->groupings) { $mform->addElement('static', 'restrictgroupbutton', '', html_writer::tag('button', get_string('restrictbygroup', 'availability'), array('id' => 'restrictbygroup', 'disabled' => 'disabled'))); } // Availability field. This is just a textarea; the user interface // interaction is all implemented in JavaScript. $mform->addElement('header', 'availabilityconditionsheader', get_string('restrictaccess', 'availability')); // Note: This field cannot be named 'availability' because that // conflicts with fields in existing modules (such as assign). // So it uses a long name that will not conflict. $mform->addElement('textarea', 'availabilityconditionsjson', get_string('accessrestrictions', 'availability')); // The _cm variable may not be a proper cm_info, so get one from modinfo. if ($this->_cm) { $modinfo = get_fast_modinfo($COURSE); $cm = $modinfo->get_cm($this->_cm->id); } else { $cm = null; } \core_availability\frontend::include_all_javascript($COURSE, $cm); } // Conditional activities: completion tracking section if (!isset($completion)) { $completion = new completion_info($COURSE); } if ($completion->is_enabled()) { $mform->addElement('header', 'activitycompletionheader', get_string('activitycompletion', 'completion')); // Unlock button for if people have completed it (will // be removed in definition_after_data if they haven't) $mform->addElement('submit', 'unlockcompletion', get_string('unlockcompletion', 'completion')); $mform->registerNoSubmitButton('unlockcompletion'); $mform->addElement('hidden', 'completionunlocked', 0); $mform->setType('completionunlocked', PARAM_INT); $trackingdefault = COMPLETION_TRACKING_NONE; // If system and activity default is on, set it. if ($CFG->completiondefault && $this->_features->defaultcompletion) { $trackingdefault = COMPLETION_TRACKING_MANUAL; } $mform->addElement('select', 'completion', get_string('completion', 'completion'), array(COMPLETION_TRACKING_NONE => get_string('completion_none', 'completion'), COMPLETION_TRACKING_MANUAL => get_string('completion_manual', 'completion'))); $mform->setDefault('completion', $trackingdefault); $mform->addHelpButton('completion', 'completion', 'completion'); // Automatic completion once you view it $gotcompletionoptions = false; if (plugin_supports('mod', $this->_modname, FEATURE_COMPLETION_TRACKS_VIEWS, false)) { $mform->addElement('checkbox', 'completionview', get_string('completionview', 'completion'), get_string('completionview_desc', 'completion')); $mform->disabledIf('completionview', 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); $gotcompletionoptions = true; } // Automatic completion once it's graded if (plugin_supports('mod', $this->_modname, FEATURE_GRADE_HAS_GRADE, false)) { $mform->addElement('checkbox', 'completionusegrade', get_string('completionusegrade', 'completion'), get_string('completionusegrade_desc', 'completion')); $mform->disabledIf('completionusegrade', 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); $mform->addHelpButton('completionusegrade', 'completionusegrade', 'completion'); $gotcompletionoptions = true; // If using the rating system, there is no grade unless ratings are enabled. if ($this->_features->rating) { $mform->disabledIf('completionusegrade', 'assessed', 'eq', 0); } } // Automatic completion according to module-specific rules $this->_customcompletionelements = $this->add_completion_rules(); foreach ($this->_customcompletionelements as $element) { $mform->disabledIf($element, 'completion', 'ne', COMPLETION_TRACKING_AUTOMATIC); } $gotcompletionoptions = $gotcompletionoptions || count($this->_customcompletionelements) > 0; // Automatic option only appears if possible if ($gotcompletionoptions) { $mform->getElement('completion')->addOption(get_string('completion_automatic', 'completion'), COMPLETION_TRACKING_AUTOMATIC); } // Completion expected at particular date? (For progress tracking) $mform->addElement('date_selector', 'completionexpected', get_string('completionexpected', 'completion'), array('optional' => true)); $mform->addHelpButton('completionexpected', 'completionexpected', 'completion'); $mform->disabledIf('completionexpected', 'completion', 'eq', COMPLETION_TRACKING_NONE); } $this->standard_hidden_coursemodule_elements(); }
/** * 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; }
/** * Prints a section full of activity modules * @Overrides course/lib.php=>print_section */ function ss_print_section($course, $section, $mods, $modnamesused, $absolute=false, $width="100%", $hidecompletion=false) { #print_r($mods); global $CFG, $USER, $DB, $PAGE, $OUTPUT; static $initialised; static $groupbuttons; static $groupbuttonslink; static $isediting; static $ismoving; static $strmovehere; static $strmovefull; static $strunreadpostsone; static $usetracking; static $groupings; if (!isset($initialised)) { $groupbuttons = ($course->groupmode or (!$course->groupmodeforce)); $groupbuttonslink = (!$course->groupmodeforce); $isediting = $PAGE->user_is_editing(); $ismoving = $isediting && ismoving($course->id); if ($ismoving) { $strmovehere = get_string("movehere"); $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); } include_once($CFG->dirroot.'/mod/forum/lib.php'); if ($usetracking = forum_tp_can_track_forums()) { $strunreadpostsone = get_string('unreadpostsone', 'forum'); } $initialised = true; } $labelformatoptions = new stdClass(); $labelformatoptions->noclean = true; $labelformatoptions->overflowdiv = true; /// Casting $course->modinfo to string prevents one notice when the field is null $modinfo = get_fast_modinfo($course); $completioninfo = new completion_info($course); //Accessibility: replace table with list <ul>, but don't output empty list. if (!empty($section->sequence)) { // Fix bug #5027, don't want style=\"width:$width\". echo "<ul class=\"section img-text\">\n"; $sectionmods = explode(",", $section->sequence); foreach ($sectionmods as $modnumber) { if (empty($mods[$modnumber])) { continue; } $mod = $mods[$modnumber]; if ($ismoving and $mod->id == $USER->activitycopy) { // do not display moving mod continue; } if (isset($modinfo->cms[$modnumber])) { // We can continue (because it will not be displayed at all) // if: // 1) The activity is not visible to users // and // 2a) The 'showavailability' option is not set (if that is set, // we need to display the activity so we can show // availability info) // or // 2b) The 'availableinfo' is empty, i.e. the activity was // hidden in a way that leaves no info, such as using the // eye icon. if (!$modinfo->cms[$modnumber]->uservisible && (empty($modinfo->cms[$modnumber]->showavailability) || empty($modinfo->cms[$modnumber]->availableinfo))) { // visibility shortcut continue; } } else { if (!file_exists("$CFG->dirroot/mod/$mod->modname/lib.php")) { // module not installed continue; } if (!coursemodule_visible_for_user($mod) && empty($mod->showavailability)) { // full visibility check continue; } } // In some cases the activity is visible to user, but it is // dimmed. This is done if viewhiddenactivities is true and if: // 1. the activity is not visible, or // 2. the activity has dates set which do not include current, or // 3. the activity has any other conditions set (regardless of whether // current user meets them) $canviewhidden = has_capability( 'moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $mod->id)); $accessiblebutdim = false; if ($canviewhidden) { $accessiblebutdim = !$mod->visible; if (!empty($CFG->enableavailability)) { $accessiblebutdim = $accessiblebutdim || $mod->availablefrom > time() || ($mod->availableuntil && $mod->availableuntil < time()) || count($mod->conditionsgrade) > 0 || count($mod->conditionscompletion) > 0; } } $liclasses = array(); $liclasses[] = 'activity'; $liclasses[] = $mod->modname; $liclasses[] = 'modtype_'.$mod->modname; echo html_writer::start_tag('li', array('class'=>join(' ', $liclasses), 'id'=>'module-'.$modnumber)); if ($ismoving) { echo '<a title="'.$strmovefull.'"'. ' href="'.$CFG->wwwroot.'/course/mod.php?moveto='.$mod->id.'&sesskey='.sesskey().'">'. '<img class="movetarget" src="'.$OUTPUT->pix_url('movehere') . '" '. ' alt="'.$strmovehere.'" /></a><br /> '; } $classes = array('mod-indent'); if (!empty($mod->indent)) { $classes[] = 'mod-indent-'.$mod->indent; if ($mod->indent > 15) { $classes[] = 'mod-indent-huge'; } } echo html_writer::start_tag('div', array('class'=>join(' ', $classes))); $extra = ''; if (!empty($modinfo->cms[$modnumber]->extra)) { $extra = $modinfo->cms[$modnumber]->extra; } if ($mod->modname == "label") { if ($accessiblebutdim || !$mod->uservisible) { echo '<div class="dimmed_text"><span class="accesshide">'. get_string('hiddenfromstudents').'</span>'; } else { echo '<div>'; } echo format_text($extra, FORMAT_HTML, $labelformatoptions); echo "</div>"; if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { if (!isset($groupings)) { $groupings = groups_get_all_groupings($course->id); } echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; } } else { // Normal activity $instancename = format_string($modinfo->cms[$modnumber]->name, true, $course->id); # echo format_string($modinfo->cms[$modnumber]->intro, true, $course->id); # echo format_string($modinfo->cms[$modnumber]->name, true, $course->id); # print_r($modinfo->cms[$modnumber]); $customicon = $modinfo->cms[$modnumber]->icon; if (!empty($customicon)) { if (substr($customicon, 0, 4) === 'mod/') { list($modname, $iconname) = explode('/', substr($customicon, 4), 2); $icon = $OUTPUT->pix_url($iconname, $modname); } else { $icon = $OUTPUT->pix_url($customicon); } } else { $icon = $OUTPUT->pix_url('icon', $mod->modname); } //Accessibility: for files get description via icon, this is very ugly hack! $altname = ''; $altname = $mod->modfullname; if (!empty($customicon)) { $archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); if ($archetype == MOD_ARCHETYPE_RESOURCE) { $mimetype = mimeinfo_from_icon('type', $customicon); $altname = get_mimetype_description($mimetype); } } // Avoid unnecessary duplication. if (false !== stripos($instancename, $altname)) { $altname = ''; } // File type after name, for alphabetic lists (screen reader). if ($altname) { $altname = get_accesshide(' '.$altname); } // We may be displaying this just in order to show information // about visibility, without the actual link if ($mod->uservisible) { // Display normal module link if (!$accessiblebutdim) { $linkcss = ''; $accesstext =''; } else { $linkcss = ' class="dimmed" '; $accesstext = '<span class="accesshide">'. get_string('hiddenfromstudents').': </span>'; } echo '<a '.$linkcss.' '.$extra. ' href="'.$CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$mod->id.'">'. '<img src="'.$icon.'" class="activityicon" alt="'.get_string('modulename',$mod->modname).'" /> '. $accesstext.'<span class="instancename">'.$instancename.$altname.'</span></a>'; if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { if (!isset($groupings)) { $groupings = groups_get_all_groupings($course->id); } echo " <span class=\"groupinglabel\">(".format_string($groupings[$mod->groupingid]->name).')</span>'; } } else { // Display greyed-out text of link echo '<span class="dimmed_text" '.$extra.' ><span class="accesshide">'. get_string('notavailableyet','condition').': </span>'. '<img src="'.$icon.'" class="activityicon" alt="'.get_string('modulename', $mod->modname).'" /> <span>'. $instancename.$altname.'</span></span>'; } } if ($usetracking && $mod->modname == 'forum') { if ($unread = forum_tp_count_forum_unread_posts($mod, $course)) { echo '<span class="unread"> <a href="'.$CFG->wwwroot.'/mod/forum/view.php?id='.$mod->id.'">'; if ($unread == 1) { echo $strunreadpostsone; } else { print_string('unreadpostsnumber', 'forum', $unread); } echo '</a></span>'; } } if ($isediting) { if ($groupbuttons and plugin_supports('mod', $mod->modname, FEATURE_GROUPS, 0)) { if (! $mod->groupmodelink = $groupbuttonslink) { $mod->groupmode = $course->groupmode; } } else { $mod->groupmode = false; } echo ' '; echo make_editing_buttons($mod, $absolute, true, $mod->indent, $section->section); hook_make_edit_icon_button($mod, $OUTPUT); } // Completion $completion = $hidecompletion ? COMPLETION_TRACKING_NONE : $completioninfo->is_enabled($mod); if ($completion!=COMPLETION_TRACKING_NONE && isloggedin() && !isguestuser() && $mod->uservisible) { $completiondata = $completioninfo->get_data($mod,true); $completionicon = ''; if ($isediting) { switch ($completion) { case COMPLETION_TRACKING_MANUAL : $completionicon = 'manual-enabled'; break; case COMPLETION_TRACKING_AUTOMATIC : $completionicon = 'auto-enabled'; break; default: // wtf } } else if ($completion==COMPLETION_TRACKING_MANUAL) { switch($completiondata->completionstate) { case COMPLETION_INCOMPLETE: $completionicon = 'manual-n'; break; case COMPLETION_COMPLETE: $completionicon = 'manual-y'; break; } } else { // Automatic switch($completiondata->completionstate) { case COMPLETION_INCOMPLETE: $completionicon = 'auto-n'; break; case COMPLETION_COMPLETE: $completionicon = 'auto-y'; break; case COMPLETION_COMPLETE_PASS: $completionicon = 'auto-pass'; break; case COMPLETION_COMPLETE_FAIL: $completionicon = 'auto-fail'; break; } } if ($completionicon) { $imgsrc = $OUTPUT->pix_url('i/completion-'.$completionicon); $imgalt = s(get_string('completion-alt-'.$completionicon, 'completion')); if ($completion == COMPLETION_TRACKING_MANUAL && !$isediting) { $imgtitle = s(get_string('completion-title-'.$completionicon, 'completion')); $newstate = $completiondata->completionstate==COMPLETION_COMPLETE ? COMPLETION_INCOMPLETE : COMPLETION_COMPLETE; // In manual mode the icon is a toggle form... // If this completion state is used by the // conditional activities system, we need to turn // off the JS. if (!empty($CFG->enableavailability) && condition_info::completion_value_used_as_condition($course, $mod)) { $extraclass = ' preventjs'; } else { $extraclass = ''; } echo " <form class='togglecompletion$extraclass' method='post' action='togglecompletion.php'><div> <input type='hidden' name='id' value='{$mod->id}' /> <input type='hidden' name='sesskey' value='".sesskey()."' /> <input type='hidden' name='completionstate' value='$newstate' /> <input type='image' src='$imgsrc' alt='$imgalt' title='$imgtitle' /> </div></form>"; } else { // In auto mode, or when editing, the icon is just an image echo "<span class='autocompletion'>"; echo "<img src='$imgsrc' alt='$imgalt' title='$imgalt' /></span>"; } } } // Show availability information (for someone who isn't allowed to // see the activity itself, or for staff) if (!$mod->uservisible) { echo '<div class="availabilityinfo">'.$mod->availableinfo.'</div>'; } else if ($canviewhidden && !empty($CFG->enableavailability)) { $ci = new condition_info($mod); $fullinfo = $ci->get_full_information(); if($fullinfo) { echo '<div class="availabilityinfo">'.get_string($mod->showavailability ? 'userrestriction_visible' : 'userrestriction_hidden','condition', $fullinfo).'</div>'; } } echo hook_show_activity_intro($mod); echo html_writer::end_tag('div'); echo html_writer::end_tag('li')."\n"; } } elseif ($ismoving) { echo "<ul class=\"section\">\n"; } if ($ismoving) { echo '<li><a title="'.$strmovefull.'"'. ' href="'.$CFG->wwwroot.'/course/mod.php?movetosection='.$section->id.'&sesskey='.sesskey().'">'. '<img class="movetarget" src="'.$OUTPUT->pix_url('movehere') . '" '. ' alt="'.$strmovehere.'" /></a></li> '; } if (!empty($section->sequence) || $ismoving) { echo "</ul><!--class='section'-->\n\n"; } }