/mod/workshop/lib.php
PHP | 2207 lines | 1470 code | 266 blank | 471 comment | 321 complexity | fcd96577e388b96d70c6cb3a7c397e50 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- <?php
- // This file is part of Moodle - http://moodle.org/
- //
- // 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.
- //
- // 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
- /**
- * Library of workshop module functions needed by Moodle core and other subsystems
- *
- * All the functions neeeded by Moodle core, gradebook, file subsystem etc
- * are placed here.
- *
- * @package mod_workshop
- * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
- defined('MOODLE_INTERNAL') || die();
- require_once($CFG->dirroot . '/calendar/lib.php');
- define('WORKSHOP_EVENT_TYPE_SUBMISSION_OPEN', 'opensubmission');
- define('WORKSHOP_EVENT_TYPE_SUBMISSION_CLOSE', 'closesubmission');
- define('WORKSHOP_EVENT_TYPE_ASSESSMENT_OPEN', 'openassessment');
- define('WORKSHOP_EVENT_TYPE_ASSESSMENT_CLOSE', 'closeassessment');
- define('WORKSHOP_SUBMISSION_TYPE_DISABLED', 0);
- define('WORKSHOP_SUBMISSION_TYPE_AVAILABLE', 1);
- define('WORKSHOP_SUBMISSION_TYPE_REQUIRED', 2);
- ////////////////////////////////////////////////////////////////////////////////
- // Moodle core API //
- ////////////////////////////////////////////////////////////////////////////////
- /**
- * Returns the information if the module supports a feature
- *
- * @see plugin_supports() in lib/moodlelib.php
- * @param string $feature FEATURE_xx constant for requested feature
- * @return mixed true if the feature is supported, null if unknown
- */
- function workshop_supports($feature) {
- switch($feature) {
- case FEATURE_GRADE_HAS_GRADE: return true;
- case FEATURE_GROUPS: return true;
- case FEATURE_GROUPINGS: return true;
- case FEATURE_MOD_INTRO: return true;
- case FEATURE_BACKUP_MOODLE2: return true;
- case FEATURE_COMPLETION_TRACKS_VIEWS:
- return true;
- case FEATURE_SHOW_DESCRIPTION: return true;
- case FEATURE_PLAGIARISM: return true;
- default: return null;
- }
- }
- /**
- * Saves a new instance of the workshop into the database
- *
- * Given an object containing all the necessary data,
- * (defined by the form in mod_form.php) this function
- * will save a new instance and return the id number
- * of the new instance.
- *
- * @param stdClass $workshop An object from the form in mod_form.php
- * @return int The id of the newly inserted workshop record
- */
- function workshop_add_instance(stdclass $workshop) {
- global $CFG, $DB;
- require_once(__DIR__ . '/locallib.php');
- $workshop->phase = workshop::PHASE_SETUP;
- $workshop->timecreated = time();
- $workshop->timemodified = $workshop->timecreated;
- $workshop->useexamples = (int)!empty($workshop->useexamples);
- $workshop->usepeerassessment = 1;
- $workshop->useselfassessment = (int)!empty($workshop->useselfassessment);
- $workshop->latesubmissions = (int)!empty($workshop->latesubmissions);
- $workshop->phaseswitchassessment = (int)!empty($workshop->phaseswitchassessment);
- $workshop->evaluation = 'best';
- if (isset($workshop->gradinggradepass)) {
- $workshop->gradinggradepass = (float)unformat_float($workshop->gradinggradepass);
- }
- if (isset($workshop->submissiongradepass)) {
- $workshop->submissiongradepass = (float)unformat_float($workshop->submissiongradepass);
- }
- if (isset($workshop->submissionfiletypes)) {
- $filetypesutil = new \core_form\filetypes_util();
- $submissionfiletypes = $filetypesutil->normalize_file_types($workshop->submissionfiletypes);
- $workshop->submissionfiletypes = implode(' ', $submissionfiletypes);
- }
- if (isset($workshop->overallfeedbackfiletypes)) {
- $filetypesutil = new \core_form\filetypes_util();
- $overallfeedbackfiletypes = $filetypesutil->normalize_file_types($workshop->overallfeedbackfiletypes);
- $workshop->overallfeedbackfiletypes = implode(' ', $overallfeedbackfiletypes);
- }
- // insert the new record so we get the id
- $workshop->id = $DB->insert_record('workshop', $workshop);
- // we need to use context now, so we need to make sure all needed info is already in db
- $cmid = $workshop->coursemodule;
- $DB->set_field('course_modules', 'instance', $workshop->id, array('id' => $cmid));
- $context = context_module::instance($cmid);
- // process the custom wysiwyg editors
- if ($draftitemid = $workshop->instructauthorseditor['itemid']) {
- $workshop->instructauthors = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructauthors',
- 0, workshop::instruction_editors_options($context), $workshop->instructauthorseditor['text']);
- $workshop->instructauthorsformat = $workshop->instructauthorseditor['format'];
- }
- if ($draftitemid = $workshop->instructreviewerseditor['itemid']) {
- $workshop->instructreviewers = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructreviewers',
- 0, workshop::instruction_editors_options($context), $workshop->instructreviewerseditor['text']);
- $workshop->instructreviewersformat = $workshop->instructreviewerseditor['format'];
- }
- if ($draftitemid = $workshop->conclusioneditor['itemid']) {
- $workshop->conclusion = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'conclusion',
- 0, workshop::instruction_editors_options($context), $workshop->conclusioneditor['text']);
- $workshop->conclusionformat = $workshop->conclusioneditor['format'];
- }
- // re-save the record with the replaced URLs in editor fields
- $DB->update_record('workshop', $workshop);
- // create gradebook items
- workshop_grade_item_update($workshop);
- workshop_grade_item_category_update($workshop);
- // create calendar events
- workshop_calendar_update($workshop, $workshop->coursemodule);
- if (!empty($workshop->completionexpected)) {
- \core_completion\api::update_completion_date_event($cmid, 'workshop', $workshop->id, $workshop->completionexpected);
- }
- return $workshop->id;
- }
- /**
- * Given an object containing all the necessary data,
- * (defined by the form in mod_form.php) this function
- * will update an existing instance with new data.
- *
- * @param stdClass $workshop An object from the form in mod_form.php
- * @return bool success
- */
- function workshop_update_instance(stdclass $workshop) {
- global $CFG, $DB;
- require_once(__DIR__ . '/locallib.php');
- $workshop->timemodified = time();
- $workshop->id = $workshop->instance;
- $workshop->useexamples = (int)!empty($workshop->useexamples);
- $workshop->usepeerassessment = 1;
- $workshop->useselfassessment = (int)!empty($workshop->useselfassessment);
- $workshop->latesubmissions = (int)!empty($workshop->latesubmissions);
- $workshop->phaseswitchassessment = (int)!empty($workshop->phaseswitchassessment);
- if (isset($workshop->gradinggradepass)) {
- $workshop->gradinggradepass = (float)unformat_float($workshop->gradinggradepass);
- }
- if (isset($workshop->submissiongradepass)) {
- $workshop->submissiongradepass = (float)unformat_float($workshop->submissiongradepass);
- }
- if (isset($workshop->submissionfiletypes)) {
- $filetypesutil = new \core_form\filetypes_util();
- $submissionfiletypes = $filetypesutil->normalize_file_types($workshop->submissionfiletypes);
- $workshop->submissionfiletypes = implode(' ', $submissionfiletypes);
- }
- if (isset($workshop->overallfeedbackfiletypes)) {
- $filetypesutil = new \core_form\filetypes_util();
- $overallfeedbackfiletypes = $filetypesutil->normalize_file_types($workshop->overallfeedbackfiletypes);
- $workshop->overallfeedbackfiletypes = implode(' ', $overallfeedbackfiletypes);
- }
- // todo - if the grading strategy is being changed, we may want to replace all aggregated peer grades with nulls
- $DB->update_record('workshop', $workshop);
- $context = context_module::instance($workshop->coursemodule);
- // process the custom wysiwyg editors
- if ($draftitemid = $workshop->instructauthorseditor['itemid']) {
- $workshop->instructauthors = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructauthors',
- 0, workshop::instruction_editors_options($context), $workshop->instructauthorseditor['text']);
- $workshop->instructauthorsformat = $workshop->instructauthorseditor['format'];
- }
- if ($draftitemid = $workshop->instructreviewerseditor['itemid']) {
- $workshop->instructreviewers = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructreviewers',
- 0, workshop::instruction_editors_options($context), $workshop->instructreviewerseditor['text']);
- $workshop->instructreviewersformat = $workshop->instructreviewerseditor['format'];
- }
- if ($draftitemid = $workshop->conclusioneditor['itemid']) {
- $workshop->conclusion = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'conclusion',
- 0, workshop::instruction_editors_options($context), $workshop->conclusioneditor['text']);
- $workshop->conclusionformat = $workshop->conclusioneditor['format'];
- }
- // re-save the record with the replaced URLs in editor fields
- $DB->update_record('workshop', $workshop);
- // update gradebook items
- workshop_grade_item_update($workshop);
- workshop_grade_item_category_update($workshop);
- // update calendar events
- workshop_calendar_update($workshop, $workshop->coursemodule);
- $completionexpected = (!empty($workshop->completionexpected)) ? $workshop->completionexpected : null;
- \core_completion\api::update_completion_date_event($workshop->coursemodule, 'workshop', $workshop->id, $completionexpected);
- return true;
- }
- /**
- * Given an ID of an instance of this module,
- * this function will permanently delete the instance
- * and any data that depends on it.
- *
- * @param int $id Id of the module instance
- * @return boolean Success/Failure
- */
- function workshop_delete_instance($id) {
- global $CFG, $DB;
- require_once($CFG->libdir.'/gradelib.php');
- if (! $workshop = $DB->get_record('workshop', array('id' => $id))) {
- return false;
- }
- // delete all associated aggregations
- $DB->delete_records('workshop_aggregations', array('workshopid' => $workshop->id));
- // get the list of ids of all submissions
- $submissions = $DB->get_records('workshop_submissions', array('workshopid' => $workshop->id), '', 'id');
- // get the list of all allocated assessments
- $assessments = $DB->get_records_list('workshop_assessments', 'submissionid', array_keys($submissions), '', 'id');
- // delete the associated records from the workshop core tables
- $DB->delete_records_list('workshop_grades', 'assessmentid', array_keys($assessments));
- $DB->delete_records_list('workshop_assessments', 'id', array_keys($assessments));
- $DB->delete_records_list('workshop_submissions', 'id', array_keys($submissions));
- // call the static clean-up methods of all available subplugins
- $strategies = core_component::get_plugin_list('workshopform');
- foreach ($strategies as $strategy => $path) {
- require_once($path.'/lib.php');
- $classname = 'workshop_'.$strategy.'_strategy';
- call_user_func($classname.'::delete_instance', $workshop->id);
- }
- $allocators = core_component::get_plugin_list('workshopallocation');
- foreach ($allocators as $allocator => $path) {
- require_once($path.'/lib.php');
- $classname = 'workshop_'.$allocator.'_allocator';
- call_user_func($classname.'::delete_instance', $workshop->id);
- }
- $evaluators = core_component::get_plugin_list('workshopeval');
- foreach ($evaluators as $evaluator => $path) {
- require_once($path.'/lib.php');
- $classname = 'workshop_'.$evaluator.'_evaluation';
- call_user_func($classname.'::delete_instance', $workshop->id);
- }
- // delete the calendar events
- $events = $DB->get_records('event', array('modulename' => 'workshop', 'instance' => $workshop->id));
- foreach ($events as $event) {
- $event = calendar_event::load($event);
- $event->delete();
- }
- // gradebook cleanup
- grade_update('mod/workshop', $workshop->course, 'mod', 'workshop', $workshop->id, 0, null, array('deleted' => true));
- grade_update('mod/workshop', $workshop->course, 'mod', 'workshop', $workshop->id, 1, null, array('deleted' => true));
- // finally remove the workshop record itself
- // We must delete the module record after we delete the grade item.
- $DB->delete_records('workshop', array('id' => $workshop->id));
- return true;
- }
- /**
- * This standard function will check all instances of this module
- * and make sure there are up-to-date events created for each of them.
- * If courseid = 0, then every workshop event in the site is checked, else
- * only workshop events belonging to the course specified are checked.
- *
- * @param integer $courseid The Course ID.
- * @param int|stdClass $instance workshop module instance or ID.
- * @param int|stdClass $cm Course module object or ID.
- * @return bool Returns true if the calendar events were successfully updated.
- */
- function workshop_refresh_events($courseid = 0, $instance = null, $cm = null) {
- global $DB;
- // If we have instance information then we can just update the one event instead of updating all events.
- if (isset($instance)) {
- if (!is_object($instance)) {
- $instance = $DB->get_record('workshop', array('id' => $instance), '*', MUST_EXIST);
- }
- if (isset($cm)) {
- if (!is_object($cm)) {
- $cm = (object)array('id' => $cm);
- }
- } else {
- $cm = get_coursemodule_from_instance('workshop', $instance->id);
- }
- workshop_calendar_update($instance, $cm->id);
- return true;
- }
- if ($courseid) {
- // Make sure that the course id is numeric.
- if (!is_numeric($courseid)) {
- return false;
- }
- if (!$workshops = $DB->get_records('workshop', array('course' => $courseid))) {
- return false;
- }
- } else {
- if (!$workshops = $DB->get_records('workshop')) {
- return false;
- }
- }
- foreach ($workshops as $workshop) {
- if (!$cm = get_coursemodule_from_instance('workshop', $workshop->id, $courseid, false)) {
- continue;
- }
- workshop_calendar_update($workshop, $cm->id);
- }
- return true;
- }
- /**
- * List the actions that correspond to a view of this module.
- * This is used by the participation report.
- *
- * Note: This is not used by new logging system. Event with
- * crud = 'r' and edulevel = LEVEL_PARTICIPATING will
- * be considered as view action.
- *
- * @return array
- */
- function workshop_get_view_actions() {
- return array('view', 'view all', 'view submission', 'view example');
- }
- /**
- * List the actions that correspond to a post of this module.
- * This is used by the participation report.
- *
- * Note: This is not used by new logging system. Event with
- * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
- * will be considered as post action.
- *
- * @return array
- */
- function workshop_get_post_actions() {
- return array('add', 'add assessment', 'add example', 'add submission',
- 'update', 'update assessment', 'update example', 'update submission');
- }
- /**
- * Return a small object with summary information about what a
- * user has done with a given particular instance of this module
- * Used for user activity reports.
- * $return->time = the time they did it
- * $return->info = a short text description
- *
- * @param stdClass $course The course record.
- * @param stdClass $user The user record.
- * @param cm_info|stdClass $mod The course module info object or record.
- * @param stdClass $workshop The workshop instance record.
- * @return stdclass|null
- */
- function workshop_user_outline($course, $user, $mod, $workshop) {
- global $CFG, $DB;
- require_once($CFG->libdir.'/gradelib.php');
- $grades = grade_get_grades($course->id, 'mod', 'workshop', $workshop->id, $user->id);
- $submissiongrade = null;
- $assessmentgrade = null;
- $info = '';
- $time = 0;
- if (!empty($grades->items[0]->grades)) {
- $submissiongrade = reset($grades->items[0]->grades);
- $time = max($time, $submissiongrade->dategraded);
- if (!$submissiongrade->hidden || has_capability('moodle/grade:viewhidden', context_course::instance($course->id))) {
- $info .= get_string('submissiongrade', 'workshop') . ': ' . $submissiongrade->str_long_grade
- . html_writer::empty_tag('br');
- } else {
- $info .= get_string('submissiongrade', 'workshop') . ': ' . get_string('hidden', 'grades')
- . html_writer::empty_tag('br');
- }
- }
- if (!empty($grades->items[1]->grades)) {
- $assessmentgrade = reset($grades->items[1]->grades);
- $time = max($time, $assessmentgrade->dategraded);
- if (!$assessmentgrade->hidden || has_capability('moodle/grade:viewhidden', context_course::instance($course->id))) {
- $info .= get_string('gradinggrade', 'workshop') . ': ' . $assessmentgrade->str_long_grade;
- } else {
- $info .= get_string('gradinggrade', 'workshop') . ': ' . get_string('hidden', 'grades');
- }
- }
- if (!empty($info) and !empty($time)) {
- $return = new stdclass();
- $return->time = $time;
- $return->info = $info;
- return $return;
- }
- return null;
- }
- /**
- * Print a detailed representation of what a user has done with
- * a given particular instance of this module, for user activity reports.
- *
- * @param stdClass $course The course record.
- * @param stdClass $user The user record.
- * @param cm_info|stdClass $mod The course module info object or record.
- * @param stdClass $workshop The workshop instance record.
- * @return string HTML
- */
- function workshop_user_complete($course, $user, $mod, $workshop) {
- global $CFG, $DB, $OUTPUT;
- require_once(__DIR__.'/locallib.php');
- require_once($CFG->libdir.'/gradelib.php');
- $workshop = new workshop($workshop, $mod, $course);
- $grades = grade_get_grades($course->id, 'mod', 'workshop', $workshop->id, $user->id);
- if (!empty($grades->items[0]->grades)) {
- $submissiongrade = reset($grades->items[0]->grades);
- if (!$submissiongrade->hidden || has_capability('moodle/grade:viewhidden', context_course::instance($course->id))) {
- $info = get_string('submissiongrade', 'workshop') . ': ' . $submissiongrade->str_long_grade;
- } else {
- $info = get_string('submissiongrade', 'workshop') . ': ' . get_string('hidden', 'grades');
- }
- echo html_writer::tag('li', $info, array('class'=>'submissiongrade'));
- }
- if (!empty($grades->items[1]->grades)) {
- $assessmentgrade = reset($grades->items[1]->grades);
- if (!$assessmentgrade->hidden || has_capability('moodle/grade:viewhidden', context_course::instance($course->id))) {
- $info = get_string('gradinggrade', 'workshop') . ': ' . $assessmentgrade->str_long_grade;
- } else {
- $info = get_string('gradinggrade', 'workshop') . ': ' . get_string('hidden', 'grades');
- }
- echo html_writer::tag('li', $info, array('class'=>'gradinggrade'));
- }
- if (has_capability('mod/workshop:viewallsubmissions', $workshop->context)) {
- $canviewsubmission = true;
- if (groups_get_activity_groupmode($workshop->cm) == SEPARATEGROUPS) {
- // user must have accessallgroups or share at least one group with the submission author
- if (!has_capability('moodle/site:accessallgroups', $workshop->context)) {
- $usersgroups = groups_get_activity_allowed_groups($workshop->cm);
- $authorsgroups = groups_get_all_groups($workshop->course->id, $user->id, $workshop->cm->groupingid, 'g.id');
- $sharedgroups = array_intersect_key($usersgroups, $authorsgroups);
- if (empty($sharedgroups)) {
- $canviewsubmission = false;
- }
- }
- }
- if ($canviewsubmission and $submission = $workshop->get_submission_by_author($user->id)) {
- $title = format_string($submission->title);
- $url = $workshop->submission_url($submission->id);
- $link = html_writer::link($url, $title);
- $info = get_string('submission', 'workshop').': '.$link;
- echo html_writer::tag('li', $info, array('class'=>'submission'));
- }
- }
- if (has_capability('mod/workshop:viewallassessments', $workshop->context)) {
- if ($assessments = $workshop->get_assessments_by_reviewer($user->id)) {
- foreach ($assessments as $assessment) {
- $a = new stdclass();
- $a->submissionurl = $workshop->submission_url($assessment->submissionid)->out();
- $a->assessmenturl = $workshop->assess_url($assessment->id)->out();
- $a->submissiontitle = s($assessment->submissiontitle);
- echo html_writer::tag('li', get_string('assessmentofsubmission', 'workshop', $a));
- }
- }
- }
- }
- /**
- * Given a course and a time, this module should find recent activity
- * that has occurred in workshop activities and print it out.
- * Return true if there was output, or false is there was none.
- *
- * @param stdClass $course
- * @param bool $viewfullnames
- * @param int $timestart
- * @return boolean
- */
- function workshop_print_recent_activity($course, $viewfullnames, $timestart) {
- global $CFG, $USER, $DB, $OUTPUT;
- $authoramefields = get_all_user_name_fields(true, 'author', null, 'author');
- $reviewerfields = get_all_user_name_fields(true, 'reviewer', null, 'reviewer');
- $sql = "SELECT s.id AS submissionid, s.title AS submissiontitle, s.timemodified AS submissionmodified,
- author.id AS authorid, $authoramefields, a.id AS assessmentid, a.timemodified AS assessmentmodified,
- reviewer.id AS reviewerid, $reviewerfields, cm.id AS cmid
- FROM {workshop} w
- INNER JOIN {course_modules} cm ON cm.instance = w.id
- INNER JOIN {modules} md ON md.id = cm.module
- INNER JOIN {workshop_submissions} s ON s.workshopid = w.id
- INNER JOIN {user} author ON s.authorid = author.id
- LEFT JOIN {workshop_assessments} a ON a.submissionid = s.id
- LEFT JOIN {user} reviewer ON a.reviewerid = reviewer.id
- WHERE cm.course = ?
- AND md.name = 'workshop'
- AND s.example = 0
- AND (s.timemodified > ? OR a.timemodified > ?)
- ORDER BY s.timemodified";
- $rs = $DB->get_recordset_sql($sql, array($course->id, $timestart, $timestart));
- $modinfo = get_fast_modinfo($course); // reference needed because we might load the groups
- $submissions = array(); // recent submissions indexed by submission id
- $assessments = array(); // recent assessments indexed by assessment id
- $users = array();
- foreach ($rs as $activity) {
- if (!array_key_exists($activity->cmid, $modinfo->cms)) {
- // this should not happen but just in case
- continue;
- }
- $cm = $modinfo->cms[$activity->cmid];
- if (!$cm->uservisible) {
- continue;
- }
- // remember all user names we can use later
- if (empty($users[$activity->authorid])) {
- $u = new stdclass();
- $users[$activity->authorid] = username_load_fields_from_object($u, $activity, 'author');
- }
- if ($activity->reviewerid and empty($users[$activity->reviewerid])) {
- $u = new stdclass();
- $users[$activity->reviewerid] = username_load_fields_from_object($u, $activity, 'reviewer');
- }
- $context = context_module::instance($cm->id);
- $groupmode = groups_get_activity_groupmode($cm, $course);
- if ($activity->submissionmodified > $timestart and empty($submissions[$activity->submissionid])) {
- $s = new stdclass();
- $s->title = $activity->submissiontitle;
- $s->authorid = $activity->authorid;
- $s->timemodified = $activity->submissionmodified;
- $s->cmid = $activity->cmid;
- if ($activity->authorid == $USER->id || has_capability('mod/workshop:viewauthornames', $context)) {
- $s->authornamevisible = true;
- } else {
- $s->authornamevisible = false;
- }
- // the following do-while wrapper allows to break from deeply nested if-statements
- do {
- if ($s->authorid === $USER->id) {
- // own submissions always visible
- $submissions[$activity->submissionid] = $s;
- break;
- }
- if (has_capability('mod/workshop:viewallsubmissions', $context)) {
- if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
- if (isguestuser()) {
- // shortcut - guest user does not belong into any group
- break;
- }
- // this might be slow - show only submissions by users who share group with me in this cm
- if (!$modinfo->get_groups($cm->groupingid)) {
- break;
- }
- $authorsgroups = groups_get_all_groups($course->id, $s->authorid, $cm->groupingid);
- if (is_array($authorsgroups)) {
- $authorsgroups = array_keys($authorsgroups);
- $intersect = array_intersect($authorsgroups, $modinfo->get_groups($cm->groupingid));
- if (empty($intersect)) {
- break;
- } else {
- // can see all submissions and shares a group with the author
- $submissions[$activity->submissionid] = $s;
- break;
- }
- }
- } else {
- // can see all submissions from all groups
- $submissions[$activity->submissionid] = $s;
- }
- }
- } while (0);
- }
- if ($activity->assessmentmodified > $timestart and empty($assessments[$activity->assessmentid])) {
- $a = new stdclass();
- $a->submissionid = $activity->submissionid;
- $a->submissiontitle = $activity->submissiontitle;
- $a->reviewerid = $activity->reviewerid;
- $a->timemodified = $activity->assessmentmodified;
- $a->cmid = $activity->cmid;
- if ($activity->reviewerid == $USER->id || has_capability('mod/workshop:viewreviewernames', $context)) {
- $a->reviewernamevisible = true;
- } else {
- $a->reviewernamevisible = false;
- }
- // the following do-while wrapper allows to break from deeply nested if-statements
- do {
- if ($a->reviewerid === $USER->id) {
- // own assessments always visible
- $assessments[$activity->assessmentid] = $a;
- break;
- }
- if (has_capability('mod/workshop:viewallassessments', $context)) {
- if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
- if (isguestuser()) {
- // shortcut - guest user does not belong into any group
- break;
- }
- // this might be slow - show only submissions by users who share group with me in this cm
- if (!$modinfo->get_groups($cm->groupingid)) {
- break;
- }
- $reviewersgroups = groups_get_all_groups($course->id, $a->reviewerid, $cm->groupingid);
- if (is_array($reviewersgroups)) {
- $reviewersgroups = array_keys($reviewersgroups);
- $intersect = array_intersect($reviewersgroups, $modinfo->get_groups($cm->groupingid));
- if (empty($intersect)) {
- break;
- } else {
- // can see all assessments and shares a group with the reviewer
- $assessments[$activity->assessmentid] = $a;
- break;
- }
- }
- } else {
- // can see all assessments from all groups
- $assessments[$activity->assessmentid] = $a;
- }
- }
- } while (0);
- }
- }
- $rs->close();
- $shown = false;
- if (!empty($submissions)) {
- $shown = true;
- echo $OUTPUT->heading(get_string('recentsubmissions', 'workshop') . ':', 6);
- foreach ($submissions as $id => $submission) {
- $link = new moodle_url('/mod/workshop/submission.php', array('id'=>$id, 'cmid'=>$submission->cmid));
- if ($submission->authornamevisible) {
- $author = $users[$submission->authorid];
- } else {
- $author = null;
- }
- print_recent_activity_note($submission->timemodified, $author, $submission->title, $link->out(), false, $viewfullnames);
- }
- }
- if (!empty($assessments)) {
- $shown = true;
- echo $OUTPUT->heading(get_string('recentassessments', 'workshop') . ':', 6);
- core_collator::asort_objects_by_property($assessments, 'timemodified');
- foreach ($assessments as $id => $assessment) {
- $link = new moodle_url('/mod/workshop/assessment.php', array('asid' => $id));
- if ($assessment->reviewernamevisible) {
- $reviewer = $users[$assessment->reviewerid];
- } else {
- $reviewer = null;
- }
- print_recent_activity_note($assessment->timemodified, $reviewer, $assessment->submissiontitle, $link->out(), false, $viewfullnames);
- }
- }
- if ($shown) {
- return true;
- }
- return false;
- }
- /**
- * Returns all activity in course workshops since a given time
- *
- * @param array $activities sequentially indexed array of objects
- * @param int $index
- * @param int $timestart
- * @param int $courseid
- * @param int $cmid
- * @param int $userid defaults to 0
- * @param int $groupid defaults to 0
- * @return void adds items into $activities and increases $index
- */
- function workshop_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) {
- global $CFG, $COURSE, $USER, $DB;
- if ($COURSE->id == $courseid) {
- $course = $COURSE;
- } else {
- $course = $DB->get_record('course', array('id'=>$courseid));
- }
- $modinfo = get_fast_modinfo($course);
- $cm = $modinfo->cms[$cmid];
- $params = array();
- if ($userid) {
- $userselect = "AND (author.id = :authorid OR reviewer.id = :reviewerid)";
- $params['authorid'] = $userid;
- $params['reviewerid'] = $userid;
- } else {
- $userselect = "";
- }
- if ($groupid) {
- $groupselect = "AND (authorgroupmembership.groupid = :authorgroupid OR reviewergroupmembership.groupid = :reviewergroupid)";
- $groupjoin = "LEFT JOIN {groups_members} authorgroupmembership ON authorgroupmembership.userid = author.id
- LEFT JOIN {groups_members} reviewergroupmembership ON reviewergroupmembership.userid = reviewer.id";
- $params['authorgroupid'] = $groupid;
- $params['reviewergroupid'] = $groupid;
- } else {
- $groupselect = "";
- $groupjoin = "";
- }
- $params['cminstance'] = $cm->instance;
- $params['submissionmodified'] = $timestart;
- $params['assessmentmodified'] = $timestart;
- $authornamefields = get_all_user_name_fields(true, 'author', null, 'author');
- $reviewerfields = get_all_user_name_fields(true, 'reviewer', null, 'reviewer');
- $sql = "SELECT s.id AS submissionid, s.title AS submissiontitle, s.timemodified AS submissionmodified,
- author.id AS authorid, $authornamefields, author.picture AS authorpicture, author.imagealt AS authorimagealt,
- author.email AS authoremail, a.id AS assessmentid, a.timemodified AS assessmentmodified,
- reviewer.id AS reviewerid, $reviewerfields, reviewer.picture AS reviewerpicture,
- reviewer.imagealt AS reviewerimagealt, reviewer.email AS revieweremail
- FROM {workshop_submissions} s
- INNER JOIN {workshop} w ON s.workshopid = w.id
- INNER JOIN {user} author ON s.authorid = author.id
- LEFT JOIN {workshop_assessments} a ON a.submissionid = s.id
- LEFT JOIN {user} reviewer ON a.reviewerid = reviewer.id
- $groupjoin
- WHERE w.id = :cminstance
- AND s.example = 0
- $userselect $groupselect
- AND (s.timemodified > :submissionmodified OR a.timemodified > :assessmentmodified)
- ORDER BY s.timemodified ASC, a.timemodified ASC";
- $rs = $DB->get_recordset_sql($sql, $params);
- $groupmode = groups_get_activity_groupmode($cm, $course);
- $context = context_module::instance($cm->id);
- $grader = has_capability('moodle/grade:viewall', $context);
- $accessallgroups = has_capability('moodle/site:accessallgroups', $context);
- $viewauthors = has_capability('mod/workshop:viewauthornames', $context);
- $viewreviewers = has_capability('mod/workshop:viewreviewernames', $context);
- $submissions = array(); // recent submissions indexed by submission id
- $assessments = array(); // recent assessments indexed by assessment id
- $users = array();
- foreach ($rs as $activity) {
- // remember all user names we can use later
- if (empty($users[$activity->authorid])) {
- $u = new stdclass();
- $additionalfields = explode(',', user_picture::fields());
- $u = username_load_fields_from_object($u, $activity, 'author', $additionalfields);
- $users[$activity->authorid] = $u;
- }
- if ($activity->reviewerid and empty($users[$activity->reviewerid])) {
- $u = new stdclass();
- $additionalfields = explode(',', user_picture::fields());
- $u = username_load_fields_from_object($u, $activity, 'reviewer', $additionalfields);
- $users[$activity->reviewerid] = $u;
- }
- if ($activity->submissionmodified > $timestart and empty($submissions[$activity->submissionid])) {
- $s = new stdclass();
- $s->id = $activity->submissionid;
- $s->title = $activity->submissiontitle;
- $s->authorid = $activity->authorid;
- $s->timemodified = $activity->submissionmodified;
- if ($activity->authorid == $USER->id || has_capability('mod/workshop:viewauthornames', $context)) {
- $s->authornamevisible = true;
- } else {
- $s->authornamevisible = false;
- }
- // the following do-while wrapper allows to break from deeply nested if-statements
- do {
- if ($s->authorid === $USER->id) {
- // own submissions always visible
- $submissions[$activity->submissionid] = $s;
- break;
- }
- if (has_capability('mod/workshop:viewallsubmissions', $context)) {
- if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
- if (isguestuser()) {
- // shortcut - guest user does not belong into any group
- break;
- }
- // this might be slow - show only submissions by users who share group with me in this cm
- if (!$modinfo->get_groups($cm->groupingid)) {
- break;
- }
- $authorsgroups = groups_get_all_groups($course->id, $s->authorid, $cm->groupingid);
- if (is_array($authorsgroups)) {
- $authorsgroups = array_keys($authorsgroups);
- $intersect = array_intersect($authorsgroups, $modinfo->get_groups($cm->groupingid));
- if (empty($intersect)) {
- break;
- } else {
- // can see all submissions and shares a group with the author
- $submissions[$activity->submissionid] = $s;
- break;
- }
- }
- } else {
- // can see all submissions from all groups
- $submissions[$activity->submissionid] = $s;
- }
- }
- } while (0);
- }
- if ($activity->assessmentmodified > $timestart and empty($assessments[$activity->assessmentid])) {
- $a = new stdclass();
- $a->id = $activity->assessmentid;
- $a->submissionid = $activity->submissionid;
- $a->submissiontitle = $activity->submissiontitle;
- $a->reviewerid = $activity->reviewerid;
- $a->timemodified = $activity->assessmentmodified;
- if ($activity->reviewerid == $USER->id || has_capability('mod/workshop:viewreviewernames', $context)) {
- $a->reviewernamevisible = true;
- } else {
- $a->reviewernamevisible = false;
- }
- // the following do-while wrapper allows to break from deeply nested if-statements
- do {
- if ($a->reviewerid === $USER->id) {
- // own assessments always visible
- $assessments[$activity->assessmentid] = $a;
- break;
- }
- if (has_capability('mod/workshop:viewallassessments', $context)) {
- if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
- if (isguestuser()) {
- // shortcut - guest user does not belong into any group
- break;
- }
- // this might be slow - show only submissions by users who share group with me in this cm
- if (!$modinfo->get_groups($cm->groupingid)) {
- break;
- }
- $reviewersgroups = groups_get_all_groups($course->id, $a->reviewerid, $cm->groupingid);
- if (is_array($reviewersgroups)) {
- $reviewersgroups = array_keys($reviewersgroups);
- $intersect = array_intersect($reviewersgroups, $modinfo->get_groups($cm->groupingid));
- if (empty($intersect)) {
- break;
- } else {
- // can see all assessments and shares a group with the reviewer
- $assessments[$activity->assessmentid] = $a;
- break;
- }
- }
- } else {
- // can see all assessments from all groups
- $assessments[$activity->assessmentid] = $a;
- }
- }
- } while (0);
- }
- }
- $rs->close();
- $workshopname = format_string($cm->name, true);
- if ($grader) {
- require_once($CFG->libdir.'/gradelib.php');
- $grades = grade_get_grades($courseid, 'mod', 'workshop', $cm->instance, array_keys($users));
- }
- foreach ($submissions as $submission) {
- $tmpactivity = new stdclass();
- $tmpactivity->type = 'workshop';
- $tmpactivity->cmid = $cm->id;
- $tmpactivity->name = $workshopname;
- $tmpactivity->sectionnum = $cm->sectionnum;
- $tmpactivity->timestamp = $submission->timemodified;
- $tmpactivity->subtype = 'submission';
- $tmpactivity->content = $submission;
- if ($grader) {
- $tmpactivity->grade = $grades->items[0]->grades[$submission->authorid]->str_long_grade;
- }
- if ($submission->authornamevisible and !empty($users[$submission->authorid])) {
- $tmpactivity->user = $users[$submission->authorid];
- }
- $activities[$index++] = $tmpactivity;
- }
- foreach ($assessments as $assessment) {
- $tmpactivity = new stdclass();
- $tmpactivity->type = 'workshop';
- $tmpactivity->cmid = $cm->id;
- $tmpactivity->name = $workshopname;
- $tmpactivity->sectionnum = $cm->sectionnum;
- $tmpactivity->timestamp = $assessment->timemodified;
- $tmpactivity->subtype = 'assessment';
- $tmpactivity->content = $assessment;
- if ($grader) {
- $tmpactivity->grade = $grades->items[1]->grades[$assessment->reviewerid]->str_long_grade;
- }
- if ($assessment->reviewernamevisible and !empty($users[$assessment->reviewerid])) {
- $tmpactivity->user = $users[$assessment->reviewerid];
- }
- $activities[$index++] = $tmpactivity;
- }
- }
- /**
- * Print single activity item prepared by {@see workshop_get_recent_mod_activity()}
- */
- function workshop_print_recent_mod_activity($activity, $courseid, $detail, $modnames, $viewfullnames) {
- global $CFG, $OUTPUT;
- if (!empty($activity->user)) {
- echo html_writer::tag('div', $OUTPUT->user_picture($activity->user, array('courseid'=>$courseid)),
- array('style' => 'float: left; padding: 7px;'));
- }
- if ($activity->subtype == 'submission') {
- echo html_writer::start_tag('div', array('class'=>'submission', 'style'=>'padding: 7px; float:left;'));
- if ($detail) {
- echo html_writer::start_tag('h4', array('class'=>'workshop'));
- $url = new moodle_url('/mod/workshop/view.php', array('id'=>$activity->cmid));
- $name = s($activity->name);
- echo $OUTPUT->image_icon('icon', $name, $activity->type);
- echo ' ' . $modnames[$activity->type];
- echo html_writer::link($url, $name, array('class'=>'name', 'style'=>'margin-left: 5px'));
- echo html_writer::end_tag('h4');
- }
- echo html_writer::start_tag('div', array('class'=>'title'));
- $url = new moodle_url('/mod/workshop/submission.php', array('cmid'=>$activity->cmid, 'id'=>$activity->content->id));
- $name = s($activity->content->title);
- echo html_writer::tag('strong', html_writer::link($url, $name));
- echo html_writer::end_tag('div');
- if (!empty($activity->user)) {
- echo html_writer::start_tag('div', array('class'=>'user'));
- $url = new moodle_url('/user/view.php', array('id'=>$activity->user->id, 'course'=>$courseid));
- $name = fullname($activity->user);
- $link = html_writer::link($url, $name);
- echo get_string('submissionby', 'workshop', $link);
- echo ' - '.userdate($activity->timestamp);
- echo html_writer::end_tag('div');
- } else {
- echo html_writer::start_tag('div', array('class'=>'anonymous'));
- echo get_string('submission', 'workshop');
- echo ' - '.userdate($activity->timestamp);
- echo html_writer::end_tag('div');
- }
- echo html_writer::end_tag('div');
- }
- if ($activity->subtype == 'assessment') {
- echo html_writer::start_tag('div', array('class'=>'assessment', 'style'=>'padding: 7px; float:left;'));
- if ($detail) {
- echo html_writer::start_tag('h4', array('class'=>'workshop'));
- $url = new moodle_url('/mod/workshop/view.php', array('id'=>$activity->cmid));
- $name = s($activity->name);
- echo $OUTPUT->image_icon('icon', $name, $activity->type);
- echo ' ' . $modnames[$activity->type];
- echo html_writer::link($url, $name, array('class'=>'name', 'style'=>'margin-left: 5px'));
- echo html_writer::end_tag('h4');
- }
- echo html_writer::start_tag('div', array('class'=>'title'));
- $url = new moodle_url('/mod/workshop/assessment.php', array('asid'=>$activity->content->id));
- $name = s($activity->content->submissiontitle);
- echo html_writer::tag('em', html_writer::link($url, $name));
- echo html_writer::end_tag('div');
- if (!empty($activity->user)) {
- echo html_writer::start_tag('div', array('class'=>'user'));
- $url = new moodle_url('/user/view.php', array('id'=>$activity->user->id, 'course'=>$courseid));
- $name = fullname($activity->user);
- $link = html_writer::link($url, $name);
- echo get_string('assessmentbyfullname', 'workshop', $link);
- echo ' - '.userdate($activity->timestamp);
- echo html_writer::end_tag('div');
- } else {
- echo html_writer::start_tag('div', array('class'=>'anonymous'));
- echo get_string('assessment', 'workshop');
- echo ' - '.userdate($activity->timestamp);
- echo html_writer::end_tag('div');
- }
- echo html_writer::end_tag('div');
- }
- echo html_writer::empty_tag('br', array('style'=>'clear:both'));
- }
- /**
- * @deprecated since Moodle 3.8
- */
- function workshop_scale_used() {
- throw new coding_exception('workshop_scale_used() can not be used anymore. Plugins can implement ' .
- '<modname>_scale_used_anywhere, all implementations of <modname>_scale_used are now ignored');
- }
- /**
- * Is a given scale used by any instance of workshop?
- *
- * The function asks all installed grading strategy subplugins. The workshop
- * core itself does not use scales. Both grade for submission and grade for
- * assessments do not use scales.
- *
- * @param int $scaleid id of the scale to check
- * @return bool
- */
- function workshop_scale_used_anywhere($scaleid) {
- global $CFG; // other files included from here
- $strategies = core_component::get_plugin_list('workshopform');
- foreach ($strategies as $strategy => $strategypath) {
- $strategylib = $strategypath . '/lib.php';
- if (is_readable($strategylib)) {
- require_once($strategylib);
- } else {
- throw new coding_exception('the grading forms subplugin must contain library ' . $strategylib);
- }
- $classname = 'workshop_' . $strategy . '_strategy';
- if (method_exists($classname, 'scale_used')) {
- if (call_user_func(array($classname, 'scale_used'), $scaleid)) {
- // no need to include any other files - scale is used
- return true;
- }
- }
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // Gradebook API //
- ////////////////////////////////////////////////////////////////////////////////
- /**
- * Creates or updates grade items for the give workshop instance
- *
- * Needed by grade_update_mod_grades() in lib/gradelib.php. Also used by
- * {@link workshop_update_grades()}.
- *
- * @param stdClass $workshop instance object with extra cmidnumber property
- * @param stdClass $submissiongrades data for the first grade item
- * @param stdClass $assessmentgrades data for the second grade item
- * @return void
- */
- function workshop_grade_item_update(stdclass $workshop, $submissiongrades=null, $assessmentgrades=null) {
- global $CFG;
- require_once($CFG->libdir.'/gradelib.php');
- $a = new stdclass();
- $a->workshopname = clean_param($workshop->name, PARAM_NOTAGS);
- $item = array();
- $item['itemname'] = get_string('gradeitemsubmission', 'workshop', $a);
- $item['gradetype'] = GRADE_TYPE_VALUE;
- $item['grademax'] = $workshop->grade;
- $item['grademin'] = 0;
- grade_update('mod/workshop', $workshop->course, 'mod', 'workshop', $workshop->id, 0, $submissiongrades , $item);
- $item = array();
- $item['itemname'] = get_string('gradeitemassessment', 'workshop', $a);
- $item['gradetype'] = GRADE_TYPE…
Large files files are truncated, but you can click here to view the full file