<?php // This file is part of VPL for Moodle - http://vpl.dis.ulpgc.es/ // // VPL for Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // VPL for Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with VPL for Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Functions to coordinate with moodle * * @package mod_vpl * @copyright 2012 Juan Carlos RodrÃguez-del-Pino * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Juan Carlos RodrÃguez-del-Pino <jcrodriguez@dis.ulpgc.es> */ defined('MOODLE_INTERNAL') || die(); require_once(dirname(__FILE__).'/locallib.php'); require_once($CFG->dirroot.'/course/lib.php'); /** * Create/update grade item for given VPL activity. * * @param stdClass VPL record with extra cmidnumber * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook * @return int 0 if ok, error code otherwise * (Code and comments adaptes from Moodle assign) */ function vpl_grade_item_update($instance, $grades=null) { global $CFG; require_once($CFG->libdir.'/gradelib.php'); $itemdetails = array('itemname' => $instance->name); $itemdetails ['hidden'] = ($instance->visiblegrade > 0) ? 0 : 1; if ( isset($instance->cmidnumber) ) { $itemdetails['idnumber'] = $instance->cmidnumber; } if ($instance->grade > 0) { $itemdetails['gradetype'] = GRADE_TYPE_VALUE; $itemdetails['grademax'] = $instance->grade; $itemdetails['grademin'] = 0; } else if ($instance->grade < 0) { $itemdetails['gradetype'] = GRADE_TYPE_SCALE; $itemdetails['scaleid'] = -$instance->grade; } if ($instance->grade == 0 || $instance->example != 0) { $itemdetails['gradetype'] = GRADE_TYPE_NONE; $itemdetails['deleted'] = 1; } if ($grades === 'reset') { $itemdetails['reset'] = true; $grades = null; } return grade_update('mod/vpl', $instance->course, 'mod', 'vpl', $instance->id, 0, $grades, $itemdetails); } /** * Update activity grades. * * @param stdClass VPL database record * @param int $userid specific user only, 0 means all * @param bool $nullifnone - not used * (API and comment taken from Moodle assign) */ function vpl_update_grades($instance, $userid=0, $nullifnone=true) { global $CFG, $USER; require_once($CFG->libdir.'/gradelib.php'); require_once(dirname( __FILE__ ) . '/vpl_submission_CE.class.php'); if ($instance->grade == 0) { return vpl_grade_item_update($instance); } else if ($userid == 0) { $vpl = new mod_vpl( false, $instance->id); $subs = $vpl->all_last_user_submission(); } else { $vpl = new mod_vpl( false, $instance->id); $sub = $vpl->last_user_submission($userid); if ($sub === false) { $subs = array(); } else { $subs = array($sub); } } $grades = array(); foreach ($subs as $sub) { if ($sub->dategraded > 0) { $subc = new mod_vpl_submission_CE($vpl, $sub); $feedback = $subc->result_to_html($subc->get_grade_comments(), false); $grade = new stdClass(); $grade->userid = $sub->userid; $grade->rawgrade = $subc->reduce_grade($sub->grade); $grade->feedback = $feedback; $grade->feedbackformat = FORMAT_HTML; if ( $sub->grader > 0 ) { $grade->usermodified = $sub->grader; } else { $grade->usermodified = $USER->id; } $grade->dategraded = $sub->dategraded; $grade->datesubmitted = $sub->datesubmitted; $grades[$grade->userid] = $grade; } } return vpl_grade_item_update($instance, $grades); } /** * Delete grade_item from a vpl instance+id * * @param Object $instance of vpl DB with id */ function vpl_delete_grade_item($instance) { global $CFG; require_once($CFG->libdir . '/gradelib.php'); $itemdetails = array ( 'deleted' => 1 ); grade_update( 'mod/vpl', $instance->course, 'mod', VPL, $instance->id, 0, null, $itemdetails ); } /** * Create an event object from a vpl instance+id * * @param stdClass $instance of vpl DB record * @param int $id vpl DB record id * @return Object with event information */ function vpl_create_event($instance, $id) { $event = new stdClass(); $event->name = $instance->name; $event->description = $instance->shortdescription; $event->format = FORMAT_PLAIN; $event->courseid = $instance->course; $event->modulename = VPL; $event->instance = $id; $event->eventtype = 'duedate'; $event->timestart = $instance->duedate; return $event; } /** * Add a new vpl instance and return the id * * @param Object $instance from the form in mod_form * @return int id of the new vpl */ function vpl_add_instance($instance) { global $CFG, $DB; require_once($CFG->dirroot . '/calendar/lib.php'); vpl_truncate_vpl( $instance ); $id = $DB->insert_record( VPL, $instance ); // Add event. if ($instance->duedate) { calendar_event::create( vpl_create_event( $instance, $id ) ); } // Add grade to grade book. $instance->id = $id; vpl_grade_item_update( $instance ); return $id; } /** * Update a vpl instance * * @param object from the form in mod.html * @return boolean OK */ function vpl_update_instance($instance) { global $CFG, $DB; require_once($CFG->dirroot . '/calendar/lib.php'); vpl_truncate_vpl( $instance ); $instance->id = $instance->instance; // Update event. $event = vpl_create_event( $instance, $instance->id ); if ($eventid = $DB->get_field( 'event', 'id', array ( 'modulename' => VPL, 'instance' => $instance->id ) )) { $event->id = $eventid; $calendarevent = calendar_event::load( $eventid ); if ($instance->duedate) { $calendarevent->update( $event ); } else { $calendarevent->delete(); } } else { if ($instance->duedate) { calendar_event::create( $event ); } } $cm = get_coursemodule_from_instance( VPL, $instance->id, $instance->course ); $instance->cmidnumber = $cm->id; vpl_grade_item_update( $instance ); return $DB->update_record( VPL, $instance ); } /** * Delete an instance by id * * @param int $id instance Id * @return boolean OK */ function vpl_delete_instance( $id ) { global $DB, $CFG; // Delete all data files. $instance = $DB->get_record( VPL, array ( "id" => $id ) ); if ( $instance === false ) { return false; } vpl_delete_dir( $CFG->dataroot . '/vpl_data/' . $id ); // Delete grade_item. vpl_delete_grade_item( $instance ); // Delete event. $DB->delete_records( 'event', array ( 'modulename' => VPL, 'instance' => $id ) ); // Delete all submissions records. $DB->delete_records( 'vpl_submissions', array ( 'vpl' => $id ) ); // Delete vpl record. $DB->delete_records( VPL, array ( 'id' => $id ) ); // Locate related VPLs and reset its basedon $id to 0. $related = $DB->get_records_select( VPL, 'basedon = ?', array ( $id ) ); foreach ($related as $other) { $other->basedon = 0; $DB->update_record( VPL, $other ); } return true; } /** * * @param string $feature * FEATURE_xx constant for requested feature * @return mixed True if module supports feature, null if doesn't know */ function vpl_supports($feature) { switch ($feature) { case FEATURE_GROUPS : return true; case FEATURE_GROUPINGS : return true; case FEATURE_GROUPMEMBERSONLY : return true; case FEATURE_MOD_INTRO : return true; case FEATURE_COMPLETION_TRACKS_VIEWS : // TODO FEATURE_COMPLETION_TRACKS_VIEWS. return false; case FEATURE_COMPLETION_HAS_RULES : // TODO FEATURE_COMPLETION_HAS_RULES. return false; case FEATURE_GRADE_HAS_GRADE : return true; case FEATURE_GRADE_OUTCOMES : return true; case FEATURE_BACKUP_MOODLE2 : return true; case FEATURE_SHOW_DESCRIPTION : return true; case FEATURE_ADVANCED_GRADING : return true; default : return null; } } /** * Lists all gradable areas for the advanced grading methods gramework * * @return array('string'=>'string') An array with area names as keys and descriptions as values */ function vpl_grading_areas_list() { return array('submissions' => get_string('submissions', 'vpl')); } /** * Return an object with short information about what a user has done with a given particular * instance of this module $return->time = the time they did it $return->info = a short text * description * */ function vpl_user_outline($course, $user, $mod, $instance) { // Search submisions for $user $instance. $vpl = new mod_vpl( null, $instance->id ); $subinstance = $vpl->last_user_submission( $user->id ); if (! $subinstance) { $return = null; } else { require_once('vpl_submission.class.php'); $return = new stdClass(); $submission = new mod_vpl_submission( $vpl, $subinstance ); $return->time = $subinstance->datesubmitted; $subs = $vpl->user_submissions( $user->id ); if (count( $subs ) > 1) { $info = get_string( 'nsubmissions', VPL, count( $subs ) ); } else { $info = get_string( 'submission', VPL, count( $subs ) ); } if ($subinstance->dategraded) { $info .= '<br />' . get_string( 'grade' ) . ': ' . $submission->get_grade_core(); } $url = vpl_mod_href( 'forms/submissionview.php', 'id', $vpl->get_course_module()->id, 'userid', $user->id ); $return->info = '<a href="' . $url . '">' . $info . '</a>'; } return $return; } /** * Print a detailed report of what a user has done with a given particular instance of this * module * */ function vpl_user_complete($course, $user, $mod, $vpl) { require_once('vpl_submission.class.php'); // TODO Print a detailed report of what a user has done with a given particular instance. // Search submisions for $user $instance. $vpl = new mod_vpl( null, $vpl->id ); $sub = $vpl->last_user_submission( $user->id ); if (! $sub) { $return = null; } else { $submission = new mod_vpl_submission( $vpl, $sub ); $submission->print_info( true ); $submission->print_grade( true ); } return true; } /** * Returns all VPL assignments since a given time */ function vpl_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid = 0, $groupid = 0) { global $CFG, $USER, $DB; $grader = false; $vpl = new mod_vpl( $cmid ); $modinfo = get_fast_modinfo( $vpl->get_course() ); $cm = $modinfo->get_cm($cmid); $vplid = $vpl->get_instance()->id; $grader = $vpl->has_capability( VPL_GRADE_CAPABILITY ); if (! $vpl->is_visible() && ! $grader) { return; } $select = 'select * from {vpl_submissions} subs'; $where = ' where (subs.vpl = :vplid) and ((subs.datesubmitted >= :timestartsub) or (subs.dategraded >= :timestartgrade))'; $parms = array ( 'vplid' => $vplid, 'timestartsub' => $timestart, 'timestartgrade' => $timestart); if (! $grader || ($userid != 0)) { // User activity. if ( ! $grader ) { $userid = $USER->id; } $parms['userid'] = $userid; $where .= ' and (subs.userid = :userid)'; } if ($groupid != 0) { // Group activity. $parms['groupid'] = $groupid; $select .= ' join {groups_members} gm on gm.userid=subs.userid '; $where .= ' and gm.groupid = :groupid'; } $where .= ' order by subs.datesubmitted DESC'; $subs = $DB->get_records_sql( $select . $where , $parms); if ($grader) { require_once($CFG->libdir.'/gradelib.php'); $userids = array(); foreach ($subs as $sub) { $userids[] = $sub->userid; } $grades = grade_get_grades($courseid, 'mod', 'vpl', $cm->instance, $userids); } $aname = format_string( $vpl->get_printable_name(), true ); foreach ($subs as $sub) { // Show recent activity. $activity = new stdClass(); $activity->type = 'vpl'; $activity->cmid = $cm->id; $activity->name = $aname; $activity->sectionnum = $cm->sectionnum; $activity->timestamp = $sub->datesubmitted; if ($grader && isset($grades->items[0]) && isset($grades->items[0]->grades[$sub->userid])) { $activity->grade = $grades->items[0]->grades[$sub->userid]->str_long_grade; } $activity->user = $DB->get_record( 'user', array ( 'id' => $sub->userid ) ); $activities [$index ++] = $activity; } return true; } function vpl_print_recent_mod_activity($activity, $courseid, $detail, $modnames, $viewfullnames) { // TODO improve. global $CFG, $OUTPUT; echo '<table border="0" cellpadding="3" cellspacing="0" class="vpl-recent">'; echo '<tr><td class="userpicture" valign="top">'; echo $OUTPUT->user_picture( $activity->user ); echo '</td><td>'; if ($detail) { $modname = $modnames[$activity->type]; echo '<div class="title">'; echo '<img src="' . $OUTPUT->pix_url('icon', 'vpl') . '" ' . 'class="icon" alt="' . $modname . '">'; echo '<a href="' . $CFG->wwwroot . '/mod/vpl/view.php?id=' . $activity->cmid . '">'; echo $activity->name; echo '</a>'; echo '</div>'; } if (isset($activity->grade)) { echo '<div class="grade">'; echo get_string('grade').': '; echo $activity->grade; echo '</div>'; } echo '<div class="user">'; $fullname = fullname( $activity->user, $viewfullnames ); echo "<a href=\"{$CFG->wwwroot}/user/view.php?id={$activity->user->id}&course=$courseid\">" . "{$fullname}</a> - "; $link = vpl_mod_href( 'forms/submissionview.php', 'id', $activity->cmid, 'userid', $activity->user->id, 'inpopup', 1 ); echo '<a href="' . $link . '">' . userdate( $activity->timestamp ) . '</a>'; echo '</div>'; echo "</td></tr></table>"; return; } /** * Given a course_module object, this function returns any "extra" information * that may be needed whenprinting this activity in a course listing. * See get_array_of_activities() in course/lib.php. * * @param $coursemodule object * The coursemodule object (record). * @return object An object on information that the coures will know about * (most noticeably, an icon). fields all optional extra, icon, name. */ function vpl_get_coursemodule_info_not_valid($coursemodule) { global $CFG; $ret = new stdClass(); $ret->icon = $CFG->wwwroot.'/mod/vpl/icon.gif'; $vpl = new mod_vpl($coursemodule->id); $instance = $vpl->get_instance(); if ($instance->example) { // Is example. $ret->icon = $CFG->wwwroot.'/mod/vpl/icon_yellow.gif'; $ret->name = $vpl->get_instance()->name.' '.get_string('example', VPL); return; } if ($instance->grade == 0) { // Not grade_able . $ret->icon = $CFG->wwwroot.'/mod/vpl/icon_green.gif'; return; } if ($instance->automaticgrading) { // Automatic grading. $ret->icon = $CFG->wwwroot.'/mod/vpl/icon_red.gif'; } if ($instance->duedate > 0 && $instance->duedate < time()) { // Closed. $ret->icon = $CFG->wwwroot.'/mod/vpl/icon_black.gif'; return; } return $ret; } /** * Get icon mapping for font-awesome. * * @return array */ function mod_vpl_get_fontawesome_icon_map() { return [ 'mod_vpl:testcases' => 'fa-check-square-o', 'mod_vpl:basic' => 'fa-cog', 'mod_vpl:test' => 'fa-user-secret', 'mod_vpl:executionoptions' => 'fa-sliders', 'mod_vpl:correctedfiles' => 'fa-graduation-cap', 'mod_vpl:requiredfiles' => 'fa-shield', 'mod_vpl:requestedfiles' => 'fa-shield', 'mod_vpl:maxresourcelimits' => 'fa-tachometer', 'mod_vpl:resourcelimits' => 'fa-tachometer', 'mod_vpl:executionfiles' => 'fa-file-code-o', 'mod_vpl:local_jail_servers' => 'fa-server', 'mod_vpl:check_jail_servers' => 'fa-rocket', 'mod_vpl:variations' => 'fa-random', 'mod_vpl:keepfiles' => 'fa-link', 'mod_vpl:advancedsettings' => 'fa-cogs', 'mod_vpl:submission' => 'fa-cloud-upload', 'mod_vpl:submissionview' => 'fa-archive', 'mod_vpl:edit' => 'fa-code', 'mod_vpl:grade' => 'fa-check-circle', 'mod_vpl:previoussubmissionslist' => 'fa-history', 'mod_vpl:modulenameplural' => 'fa-list-ul', 'mod_vpl:checkgroups' => 'fa-group', 'mod_vpl:description' => 'fa-tasks', 'mod_vpl:similarity' => 'fa-clone', 'mod_vpl:submissionslist' => 'fa-list-ul', 'mod_vpl:loading' => 'fa-spinner fa-pulse', 'mod_vpl:copy' => 'fa-copy', 'mod_vpl:submissionscharts' => 'fa-bar-chart', 'mod_vpl:gradercomments' => 'fa-check-square', 'mod_vpl:downloadsubmissions' => 'fa-cloud-download', 'mod_vpl:downloadallsubmissions' => 'fa-history', 'mod_vpl:user' => 'fa-user', 'mod_vpl:group' => 'fa-group', 'mod_vpl:exitrole' => 'fa-close', ]; } /** * Create e new navigation node with icon * @param navigation_node $vplnode * @param string $str string to be i18n * @param moodle_url $url * @param navigation_node::TYPE $type * @param string $comp component by default VPL * @return navigation_node */ function vpl_navi_node_create($vplnode, $str, $url, $beforekey = null, $type = navigation_node::TYPE_SETTING, $comp = 'mod_vpl') { $stri18n = get_string($str, $comp); $node = $vplnode->create( $stri18n, $url, $type, null, null, new pix_icon( $str, '', 'mod_vpl') ); return $vplnode->add_node($node, $beforekey); } function vpl_extend_navigation(navigation_node $vplnode, $course, $module, $cm) { global $USER; $vpl = new mod_vpl( $cm->id ); $parm = array( 'id' => $cm->id ); $url = new moodle_url( '/mod/vpl/view.php', $parm ); vpl_navi_node_create($vplnode, 'description', $url, null, navigation_node::TYPE_ACTIVITY); $url = new moodle_url( '/mod/vpl/views/submissionslist.php', $parm ); vpl_navi_node_create($vplnode, 'submissionslist', $url, null, navigation_node::TYPE_ACTIVITY); $url = new moodle_url( '/mod/vpl/similarity/similarity_form.php', $parm ); vpl_navi_node_create($vplnode, 'similarity', $url, null, navigation_node::TYPE_ACTIVITY); if (!$vpl->has_capability( VPL_SIMILARITY_CAPABILITY ) && !$vpl->has_capability( VPL_GRADE_CAPABILITY ) && !$vpl->has_capability( VPL_MANAGE_CAPABILITY )) { $parmsuser = array( 'id' => $cm->id, 'userid' => $USER->id); $url = new moodle_url( '/mod/vpl/forms/submission.php', $parmsuser ); vpl_navi_node_create($vplnode, 'submission', $url, null, navigation_node::TYPE_ACTIVITY); $url = new moodle_url( '/mod/vpl/forms/edit.php', $parmsuser ); vpl_navi_node_create($vplnode, 'edit', $url, null, navigation_node::TYPE_ACTIVITY); $url = new moodle_url( '/mod/vpl/forms/submissionview.php', $parmsuser ); vpl_navi_node_create($vplnode, 'submissionview', $url, null, navigation_node::TYPE_ACTIVITY); $url = new moodle_url( '/mod/vpl/views/previoussubmissionslist.php', $parmsuser ); vpl_navi_node_create($vplnode, 'previoussubmissionslist', $url, null, navigation_node::TYPE_ACTIVITY); } } function vpl_extend_settings_navigation(settings_navigation $settings, navigation_node $vplnode) { global $PAGE, $USER; if (! isset( $PAGE->cm->id )) { return; } $cmid = $PAGE->cm->id; $context = context_module::instance( $cmid ); if (has_capability( VPL_MANAGE_CAPABILITY, $context )) { $klist = $vplnode->get_children_key_list(); if (count( $klist ) > 1) { $fkn = $klist [1]; } else { $fkn = null; } $parms = array ( 'id' => $cmid ); // Basic settings. vpl_navi_node_create($vplnode, 'testcases', new moodle_url( '/mod/vpl/forms/files.php', array ( 'id' => $cmid, 'type' => 'testcases' )), $fkn); vpl_navi_node_create($vplnode, 'executionoptions', new moodle_url( '/mod/vpl/forms/executionoptions.php', $parms ), $fkn); vpl_navi_node_create($vplnode, 'requestedfiles', new moodle_url( '/mod/vpl/forms/files.php', array ( 'id' => $cmid, 'type' => 'required' )), $fkn); vpl_navi_node_create($vplnode, 'correctedfiles', new moodle_url( '/mod/vpl/forms/files.php', array ( 'id' => $cmid, 'type' => 'corrected' )), $fkn); // Advanced settings. $urlexecutionfiles = new moodle_url( '/mod/vpl/forms/files.php', array ( 'id' => $cmid, 'type' => 'execution' )); $advanced = vpl_navi_node_create($vplnode, 'advancedsettings', $urlexecutionfiles, $fkn, navigation_node::TYPE_CONTAINER, 'moodle'); vpl_navi_node_create($advanced, 'executionfiles', $urlexecutionfiles); vpl_navi_node_create($advanced, 'maxresourcelimits', new moodle_url( '/mod/vpl/forms/executionlimits.php', $parms )); vpl_navi_node_create($advanced, 'keepfiles', new moodle_url( '/mod/vpl/forms/executionkeepfiles.php', $parms )); vpl_navi_node_create($advanced, 'variations', new moodle_url( '/mod/vpl/forms/variations.php', $parms )); vpl_navi_node_create($advanced, 'check_jail_servers', new moodle_url( '/mod/vpl/views/checkjailservers.php', $parms )); if (has_capability( VPL_SETJAILS_CAPABILITY, $context )) { vpl_navi_node_create($advanced, 'local_jail_servers', new moodle_url( '/mod/vpl/forms/local_jail_servers.php', $parms )); } // Test activity navigation. $parmsuser = array ( 'id' => $cmid, 'userid' => optional_param( 'userid', $USER->id, PARAM_INT ) ); $urlsubmissionview = new moodle_url( '/mod/vpl/forms/submissionview.php', $parmsuser ); $testact = vpl_navi_node_create($vplnode, 'test', $urlsubmissionview, $fkn, navigation_node::TYPE_CONTAINER); vpl_navi_node_create($testact, 'submission', new moodle_url( '/mod/vpl/forms/submission.php', $parmsuser ), null, navigation_node::TYPE_ACTIVITY); vpl_navi_node_create($testact, 'edit', new moodle_url( '/mod/vpl/forms/edit.php', $parmsuser ), null, navigation_node::TYPE_ACTIVITY); vpl_navi_node_create($testact, 'submissionview', $urlsubmissionview, null, navigation_node::TYPE_ACTIVITY); vpl_navi_node_create($testact, 'grade', new moodle_url( '/mod/vpl/forms/gradesubmission.php', $parmsuser ), null, navigation_node::TYPE_ACTIVITY, 'moodle'); vpl_navi_node_create($testact, 'previoussubmissionslist', new moodle_url( '/mod/vpl/views/previoussubmissionslist.php', $parmsuser ), null, navigation_node::TYPE_ACTIVITY); vpl_navi_node_create($vplnode, 'modulenameplural', new moodle_url( '/mod/vpl/index.php', array ('id' => $PAGE->cm->course)), $fkn); vpl_navi_node_create($vplnode, 'checkgroups', new moodle_url( '/mod/vpl/views/checkvpls.php', array ('id' => $PAGE->cm->course)), $fkn); } } /** * Run periodically to check for vpl visibility update * * @uses $CFG * @return boolean * */ function vpl_cron() { global $DB; $rebuilds = array (); $now = time(); $sql = 'SELECT id, startdate, duedate, course, name FROM {vpl} WHERE startdate > ? and startdate <= ? and (duedate > ? or duedate = 0)'; $parms = array ( $now - (2 * 3600), $now, $now ); $vpls = $DB->get_records_sql( $sql, $parms ); foreach ($vpls as $instance) { if (! instance_is_visible( VPL, $instance )) { $vpl = new mod_vpl( null, $instance->id ); echo 'Setting visible "' . s( $vpl->get_printable_name() ) . '"'; $cm = $vpl->get_course_module(); $rebuilds [$cm->id] = $cm; } } foreach ($rebuilds as $cmid => $cm) { set_coursemodule_visible( $cm->id, true ); rebuild_course_cache( $cm->course ); } return true; } /** * Must return an array of user records (all data) who are participants for a given instance * of vpl. Must include every user involved in the instance, independient of his role * (student, teacher, admin...) See other modules as example. * * @param int $vplid ID of an instance of this module * @return mixed boolean/array of users */ function vpl_get_participants($vplid) { global $CFG, $DB; // Locate students. $submiters = $DB->get_records_sql( 'SELECT DISTINCT userid FROM {vpl_submissions} WHERE vpl = ?', array ( $vplid ) ); // Locate graders. $graders = $DB->get_records_sql( 'SELECT DISTINCT grader FROM {vpl_submissions} WHERE vpl = ? AND grader > 0', array ( $vplid ) ); // TODO Refactor to only one query. // Read users records. $participants = array (); foreach ($submiters as $submiter) { $user = $DB->get_record( 'user', array ( 'id' => $submiter->userid ) ); if ($user) { $participants [$user->id] = $user; } } foreach ($graders as $grader) { if ($grader->grader > 0) { // Exist and Not automatic grader. $user = $DB->get_record( 'user', array ( 'id' => $grader->grader ) ); if ($user) { $participants [$user->id] = $user; } } } if (count( $participants ) > 0) { return $participants; } else { return false; } } function vpl_scale_used($vplid, $scaleid) { global $DB; return $scaleid and $DB->record_exists( VPL, array ( 'id' => "$vplid", 'grade' => "-$scaleid" ) ); } /** * Checks if scale is being used by any instance of vpl. This is used to find out if scale * used anywhere * * @param $scaleid int * @return boolean True if the scale is used by any vpl */ function vpl_scale_used_anywhere($scaleid) { global $DB; return $scaleid and $DB->record_exists( VPL, array ( 'grade' => "-$scaleid" ) ); } function vpl_get_view_actions() { return array ( 'view', 'view all', 'view all submissions', 'run', 'debug', 'edit submission', 'execution keep file form', 'execution limits form', 'edit full description', 'view grade', 'Diff', 'view similarity', 'view watermarks', 'similarity form', 'view previous' ); } function vpl_get_post_actions() { return array ( 'save submision', 'evaluate', 'execution save keeplist', 'execution save limits', 'execution save options', 'execution options form', 'save full description', 'remove grade', 'upload submission', 'variations form' ); } /** * Removes all grades from gradebook * * @param int $courseid * @param * string optional type */ function vpl_reset_gradebook($courseid, $type = '') { global $CFG; require_once($CFG->libdir . '/gradelib.php'); if ($cms = get_coursemodules_in_course( VPL, $course->id )) { foreach ($cms as $cmid => $cm) { $vpl = new mod_vpl( $cmid ); $instance = $vpl->get_instance(); $itemdetails = array ( 'reset' => 1 ); grade_update( 'mod/vpl', $instance->course, 'mod', VPL, $instance->id , 0, null, $itemdetails ); } } } /** * This function is used by the reset_course_userdata function in moodlelib. This function * will remove all posts from the specified vpl instance and clean up any related data. * * @param $data stdClass the data submitted from the reset course. * @return array status array */ function vpl_reset_userdata($data) { global $CFG, $DB; $status = array (); if ($data->reset_vpl_submissions) { $componentstr = get_string( 'modulenameplural', VPL ); if ($cms = get_coursemodules_in_course( VPL, $data->courseid )) { foreach ($cms as $cmid => $cm) { // For each vpl instance in course. $vpl = new mod_vpl( $cmid ); $instance = $vpl->get_instance(); // Delete submissions records. $DB->delete_records( VPL_SUBMISSIONS, array ( 'vpl' => $instance->id ) ); // Delete variations assigned. $DB->delete_records( VPL_ASSIGNED_VARIATIONS, array ( 'vpl' => $instance->id ) ); // Delete submission files. fulldelete( $CFG->dataroot . '/vpl_data/' . $data->courseid . '/' . $instance->id . '/usersdata' ); $status [] = array ( 'component' => $componentstr, 'item' => get_string( 'resetvpl', VPL, $instance->name ), 'error' => false ); } } } return $status; } /** * Implementation of the function for printing the form elements that control whether * the course reset functionality affects the assignment. * * @param $mform moodleform passed by reference */ function vpl_reset_course_form_definition(&$mform) { $mform->addElement( 'header', 'vplheader', get_string( 'modulenameplural', VPL ) ); $mform->addElement( 'advcheckbox', 'reset_vpl_submissions', get_string( 'deleteallsubmissions', VPL ) ); } /** * Course reset form defaults. */ function vpl_reset_course_form_defaults($course) { return array ( 'reset_vpl_submissions' => 1 ); } /* * any/all functions defined by the module should be in here. If the modulename is called * widget, then the required functions include: Other functions available but not required * are: o widget_delete_course() - code to clean up anything that would be leftover after * all instances are deleted o widget_process_options() - code to pre-process the form data * from module settings o widget_reset_course_form() and widget_delete_userdata() - used to * implement Reset course feature. To avoid possible conflict, any module functions should * be named starting with widget_ and any constants you define should start with WIDGET_ */