Merge branch 'MDL-27508-workshop-groups' of git://github.com/mudrd8mz/moodle

This commit is contained in:
Dan Poltawski
2012-05-01 11:16:20 +08:00
11 changed files with 507 additions and 113 deletions
+40 -15
View File
@@ -61,6 +61,13 @@ class workshop_manual_allocator implements workshop_allocator {
global $PAGE;
$mode = optional_param('mode', 'display', PARAM_ALPHA);
$perpage = optional_param('perpage', null, PARAM_INT);
if ($perpage and $perpage > 0 and $perpage <= 1000) {
require_sesskey();
set_user_preference('workshopallocation_manual_perpage', $perpage);
redirect($PAGE->url);
}
$result = new workshop_allocation_result($this);
@@ -141,9 +148,9 @@ class workshop_manual_allocator implements workshop_allocator {
$output = $PAGE->get_renderer('workshopallocation_manual');
$pagingvar = 'page';
$page = optional_param($pagingvar, 0, PARAM_INT);
$perpage = 10; // todo let the user modify this
$page = optional_param('page', 0, PARAM_INT);
$perpage = get_user_preferences('workshopallocation_manual_perpage', 10);
$groupid = groups_get_activity_group($this->workshop->cm, true);
$hlauthorid = -1; // highlight this author
$hlreviewerid = -1; // highlight this reviewer
@@ -200,24 +207,20 @@ class workshop_manual_allocator implements workshop_allocator {
}
}
// fetch the list of ids of all workshop participants - this may get really long so fetch just id
$participants = get_users_by_capability($PAGE->context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
'u.id', 'u.lastname,u.firstname,u.id', '', '', '', '', false, false, true);
$numofparticipants = count($participants); // we will need later for the pagination
// fetch the list of ids of all workshop participants
$numofparticipants = $this->workshop->count_participants(false, $groupid);
$participants = $this->workshop->get_participants(false, $groupid, $perpage * $page, $perpage);
if ($hlauthorid > 0 and $hlreviewerid > 0) {
// display just those two users
$participants = array_intersect_key($participants, array($hlauthorid => null, $hlreviewerid => null));
$button = $output->single_button($PAGE->url, get_string('showallparticipants', 'workshopallocation_manual'), 'get');
} else {
// slice the list of participants according to the current page
$participants = array_slice($participants, $page * $perpage, $perpage, true);
$button = '';
}
// this will hold the information needed to display user names and pictures
$userinfo = $DB->get_records_list('user', 'id', array_keys($participants), '', user_picture::fields());
$userinfo = $participants;
// load the participants' submissions
$submissions = $this->workshop->get_submissions(array_keys($participants));
@@ -315,6 +318,7 @@ class workshop_manual_allocator implements workshop_allocator {
// prepare data to be rendered
$data = new workshopallocation_manual_allocations();
$data->workshop = $this->workshop;
$data->allocations = $allocations;
$data->userinfo = $userinfo;
$data->authors = $this->workshop->get_potential_authors();
@@ -323,11 +327,15 @@ class workshop_manual_allocator implements workshop_allocator {
$data->hlreviewerid = $hlreviewerid;
$data->selfassessment = $this->workshop->useselfassessment;
// prepare paging bar
$pagingbar = new paging_bar($numofparticipants, $page, $perpage, $PAGE->url, $pagingvar);
$pagingbarout = $output->render($pagingbar);
// prepare the group selector
$groupselector = $output->container(groups_print_activity_menu($this->workshop->cm, $PAGE->url, true), 'groupwidget');
return $pagingbarout . $output->render($message) . $output->render($data) . $button . $pagingbarout;
// prepare paging bar
$pagingbar = new paging_bar($numofparticipants, $page, $perpage, $PAGE->url, 'page');
$pagingbarout = $output->render($pagingbar);
$perpageselector = $output->perpage_selector($perpage);
return $groupselector . $pagingbarout . $output->render($message) . $output->render($data) . $button . $pagingbarout . $perpageselector;
}
/**
@@ -350,11 +358,28 @@ class workshop_manual_allocator implements workshop_allocator {
* @see workshop_manual_allocator::ui()
*/
class workshopallocation_manual_allocations implements renderable {
/** @var workshop module instance */
public $workshop;
/** @var array of stdClass, indexed by userid, properties userid, submissionid, (array)reviewedby, (array)reviewerof */
public $allocations;
/** @var array of stdClass contains the data needed to display the user name and picture */
public $userinfo;
/* var array of stdClass potential authors */
public $authors;
/* var array of stdClass potential reviewers */
public $reviewers;
/* var int the id of the user to highlight as the author */
public $hlauthorid;
/* var int the id of the user to highlight as the reviewer */
public $hlreviewerid;
/* var bool should the selfassessment be allowed */
public $selfassessment;
}
+8 -1
View File
@@ -31,6 +31,9 @@ defined('MOODLE_INTERNAL') || die();
*/
class workshopallocation_manual_renderer extends mod_workshop_renderer {
/** @var workshop module instance */
protected $workshop;
////////////////////////////////////////////////////////////////////////////
// External rendering API
////////////////////////////////////////////////////////////////////////////
@@ -42,6 +45,9 @@ class workshopallocation_manual_renderer extends mod_workshop_renderer {
* @return string html code
*/
protected function render_workshopallocation_manual_allocations(workshopallocation_manual_allocations $data) {
$this->workshop = $data->workshop;
$allocations = $data->allocations; // array prepared array of all allocations data
$userinfo = $data->userinfo; // names and pictures of all required users
$authors = $data->authors; // array potential reviewees
@@ -101,7 +107,8 @@ class workshopallocation_manual_renderer extends mod_workshop_renderer {
if (is_null($allocation->submissionid)) {
$o .= $this->output->container(get_string('nosubmissionfound', 'workshop'), 'info');
} else {
$o .= $this->output->container(format_string($allocation->submissiontitle), 'title');
$link = $this->workshop->submission_url($allocation->submissionid);
$o .= $this->output->container(html_writer::link($link, format_string($allocation->submissiontitle)), 'title');
if (is_null($allocation->submissiongrade)) {
$o .= $this->output->container(get_string('nogradeyet', 'workshop'), array('grade', 'missing'));
} else {
+15
View File
@@ -63,6 +63,21 @@ $canoverridegrades = has_capability('mod/workshop:overridegrades', $worksho
$isreviewer = ($USER->id == $assessment->reviewerid);
$isauthor = ($USER->id == $submission->authorid);
if ($canviewallsubmissions) {
// check this flag against the group membership yet
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, $submission->authorid, $workshop->cm->groupingid, 'g.id');
$sharedgroups = array_intersect_key($usersgroups, $authorsgroups);
if (empty($sharedgroups)) {
$canviewallsubmissions = false;
}
}
}
}
if ($isreviewer or $isauthor or ($canviewallassessments and $canviewallsubmissions)) {
// such a user can continue
} else {
+11 -6
View File
@@ -156,8 +156,9 @@ $capabilities = array(
)
),
// Ability to view a work submitted by an other user. Applies to the user's group only
// or - if the user is allowed to access all groups - applies to any submission
// Ability to view the work submitted by an other user. In separate groups mode,
// the user has to be allowed to access all groups or be the member of the
// submission author's group.
'mod/workshop:viewallsubmissions' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
@@ -168,8 +169,9 @@ $capabilities = array(
)
),
// Ability to view published submission when the workshop is closed. Applies to the user's group only
// or - if the user is allowed to access all groups - applies to any submission
// Ability to view published submission when the workshop is closed. Group mode
// restrictions do not apply here, published submissions are available in all
// groups even in the separate groups mode.
'mod/workshop:viewpublishedsubmissions' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
@@ -193,8 +195,11 @@ $capabilities = array(
)
),
// Ability to always view the assessments of other users' work and the calculated grades, regardless the phase.
// Applies to the user's group only or - if the user is allowed to access all groups - applies to any assessment
// Ability to always view the assessments of other users' work and the calculated grades,
// regardless the phase. The separate groups membership is checked against the submission
// author only, not against the reviewer. In other words, if the user has this capability
// and is allowed to see some submission, then they are implicitly allowed to see all
// assessments of that submissions even if they do not share a group with the reviewer.
'mod/workshop:viewallassessments' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
+4 -1
View File
@@ -33,7 +33,7 @@ $string['allocation'] = 'Submission allocation';
$string['allocationdone'] = 'Allocation done';
$string['allocationerror'] = 'Allocation error';
$string['allocationconfigured'] = 'Allocation configured';
$string['allsubmissions'] = 'All submissions';
$string['allsubmissions'] = 'All submissions ({$a})';
$string['alreadygraded'] = 'Already graded';
$string['areainstructauthors'] = 'Instructions for submission';
$string['areainstructreviewers'] = 'Instructions for assessment';
@@ -144,6 +144,7 @@ $string['gradinggradecalculated'] = 'Calculated grade for assessment';
$string['gradinggradeof'] = 'Grade for assessment (of {$a})';
$string['gradinggradeover'] = 'Override grade for assessment';
$string['gradingsettings'] = 'Grading settings';
$string['groupnoallowed'] = 'You are not allowed to access any group in this workshop';
$string['chooseuser'] = 'Choose user...';
$string['iamsure'] = 'Yes, I am sure';
$string['info'] = 'Info';
@@ -195,6 +196,8 @@ $string['saveandclose'] = 'Save and close';
$string['saveandcontinue'] = 'Save and continue editing';
$string['saveandpreview'] = 'Save and preview';
$string['selfassessmentdisabled'] = 'Self-assessment disabled';
$string['showingperpage'] = 'Showing {$a} items per page';
$string['showingperpagechange'] = 'Change ...';
$string['someuserswosubmission'] = 'There is at least one author who has not yet submitted their work';
$string['sortasc'] = 'Ascending sort';
$string['sortdesc'] = 'Descending sort';
+13 -1
View File
@@ -306,7 +306,19 @@ function workshop_user_complete($course, $user, $mod, $workshop) {
}
if (has_capability('mod/workshop:viewallsubmissions', $workshop->context)) {
if ($submission = $workshop->get_submission_by_author($user->id)) {
$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);
+292 -59
View File
@@ -380,40 +380,181 @@ class workshop {
////////////////////////////////////////////////////////////////////////////////
/**
* Fetches all users with the capability mod/workshop:submit in the current context
* Fetches all enrolled users with the capability mod/workshop:submit in the current workshop
*
* The returned objects contain id, lastname and firstname properties and are ordered by lastname,firstname
* The returned objects contain properties required by user_picture and are ordered by lastname, firstname.
* Only users with the active enrolment are returned.
*
* @todo handle with limits and groups
* @param bool $musthavesubmission If true, return only users who have already submitted. All possible authors otherwise.
* @return array array[userid] => stdclass{->id ->lastname ->firstname}
* @param bool $musthavesubmission if true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set)
* @param int $limitnum return a subset containing this number of records (optional, required if $limitfrom is set)
* @return array array[userid] => stdClass
*/
public function get_potential_authors($musthavesubmission=true) {
$users = get_users_by_capability($this->context, 'mod/workshop:submit',
'u.id,u.lastname,u.firstname', 'u.lastname,u.firstname,u.id', '', '', '', '', false, false, true);
if ($musthavesubmission) {
$users = array_intersect_key($users, $this->users_with_submission(array_keys($users)));
public function get_potential_authors($musthavesubmission=true, $groupid=0, $limitfrom=0, $limitnum=0) {
global $DB;
list($sql, $params) = $this->get_users_with_capability_sql('mod/workshop:submit', $musthavesubmission, $groupid);
if (empty($sql)) {
return array();
}
return $users;
$sql .= " ORDER BY lastname ASC, firstname ASC, id ASC";
return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
}
/**
* Fetches all users with the capability mod/workshop:peerassess in the current context
* Returns the total number of users that would be fetched by {@link self::get_potential_authors()}
*
* The returned objects contain id, lastname and firstname properties and are ordered by lastname,firstname
*
* @todo handle with limits and groups
* @param bool $musthavesubmission If true, return only users who have already submitted. All possible users otherwise.
* @return array array[userid] => stdclass{->id ->lastname ->firstname}
* @param bool $musthavesubmission if true, count only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @return int
*/
public function get_potential_reviewers($musthavesubmission=false) {
$users = get_users_by_capability($this->context, 'mod/workshop:peerassess',
'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname,u.id', '', '', '', '', false, false, true);
if ($musthavesubmission) {
// users without their own submission can not be reviewers
$users = array_intersect_key($users, $this->users_with_submission(array_keys($users)));
public function count_potential_authors($musthavesubmission=true, $groupid=0) {
global $DB;
list($sql, $params) = $this->get_users_with_capability_sql('mod/workshop:submit', $musthavesubmission, $groupid);
if (empty($sql)) {
return 0;
}
return $users;
$sql = "SELECT COUNT(*)
FROM ($sql) tmp";
return $DB->count_records_sql($sql, $params);
}
/**
* Fetches all enrolled users with the capability mod/workshop:peerassess in the current workshop
*
* The returned objects contain properties required by user_picture and are ordered by lastname, firstname.
* Only users with the active enrolment are returned.
*
* @param bool $musthavesubmission if true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set)
* @param int $limitnum return a subset containing this number of records (optional, required if $limitfrom is set)
* @return array array[userid] => stdClass
*/
public function get_potential_reviewers($musthavesubmission=false, $groupid=0, $limitfrom=0, $limitnum=0) {
global $DB;
list($sql, $params) = $this->get_users_with_capability_sql('mod/workshop:peerassess', $musthavesubmission, $groupid);
if (empty($sql)) {
return array();
}
$sql .= " ORDER BY lastname ASC, firstname ASC, id ASC";
return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
}
/**
* Returns the total number of users that would be fetched by {@link self::get_potential_reviewers()}
*
* @param bool $musthavesubmission if true, count only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @return int
*/
public function count_potential_reviewers($musthavesubmission=false, $groupid=0) {
global $DB;
list($sql, $params) = $this->get_users_with_capability_sql('mod/workshop:peerassess', $musthavesubmission, $groupid);
if (empty($sql)) {
return 0;
}
$sql = "SELECT COUNT(*)
FROM ($sql) tmp";
return $DB->count_records_sql($sql, $params);
}
/**
* Fetches all enrolled users that are authors or reviewers (or both) in the current workshop
*
* The returned objects contain properties required by user_picture and are ordered by lastname, firstname.
* Only users with the active enrolment are returned.
*
* @see self::get_potential_authors()
* @see self::get_potential_reviewers()
* @param bool $musthavesubmission if true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set)
* @param int $limitnum return a subset containing this number of records (optional, required if $limitfrom is set)
* @return array array[userid] => stdClass
*/
public function get_participants($musthavesubmission=false, $groupid=0, $limitfrom=0, $limitnum=0) {
global $DB;
list($sql, $params) = $this->get_participants_sql($musthavesubmission, $groupid);
if (empty($sql)) {
return array();
}
$sql .= " ORDER BY lastname ASC, firstname ASC, id ASC";
return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
}
/**
* Returns the total number of records that would be returned by {@link self::get_participants()}
*
* @param bool $musthavesubmission if true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @return int
*/
public function count_participants($musthavesubmission=false, $groupid=0) {
global $DB;
list($sql, $params) = $this->get_participants_sql($musthavesubmission, $groupid);
if (empty($sql)) {
return 0;
}
$sql = "SELECT COUNT(*)
FROM ($sql) tmp";
return $DB->count_records_sql($sql, $params);
}
/**
* Checks if the given user is an actively enrolled participant in the workshop
*
* @param int $userid, defaults to the current $USER
* @return boolean
*/
public function is_participant($userid=null) {
global $USER, $DB;
if (is_null($userid)) {
$userid = $USER->id;
}
list($sql, $params) = $this->get_participants_sql();
if (empty($sql)) {
return false;
}
$sql = "SELECT COUNT(*)
FROM {user} uxx
JOIN ({$sql}) pxx ON uxx.id = pxx.id
WHERE uxx.id = :uxxid";
$params['uxxid'] = $userid;
if ($DB->count_records_sql($sql, $params)) {
return true;
}
return false;
}
/**
@@ -479,28 +620,71 @@ class workshop {
return $DB->get_records_sql($sql, $params);
}
/**
* Returns the total number of records that would be returned by {@link self::get_submissions()}
*
* @param mixed $authorid int|array|'all' If set to [array of] integer, return submission[s] of the given user[s] only
* @param int $groupid If non-zero, return only submissions by authors in the specified group
* @return int number of records
*/
public function count_submissions($authorid='all', $groupid=0) {
global $DB;
$params = array('workshopid' => $this->id);
$sql = "SELECT COUNT(s.id)
FROM {workshop_submissions} s
JOIN {user} u ON (s.authorid = u.id)";
if ($groupid) {
$sql .= " JOIN {groups_members} gm ON (gm.userid = u.id AND gm.groupid = :groupid)";
$params['groupid'] = $groupid;
}
$sql .= " WHERE s.example = 0 AND s.workshopid = :workshopid";
if ('all' === $authorid) {
// no additional conditions
} elseif (!empty($authorid)) {
list($usql, $uparams) = $DB->get_in_or_equal($authorid, SQL_PARAMS_NAMED);
$sql .= " AND authorid $usql";
$params = array_merge($params, $uparams);
} else {
// $authorid is empty
return 0;
}
return $DB->count_records_sql($sql, $params);
}
/**
* Returns submissions from this workshop
*
* Fetches data from {workshop_submissions} and adds some useful information from other
* tables. Does not return textual fields to prevent possible memory lack issues.
*
* @see self::count_submissions()
* @param mixed $authorid int|array|'all' If set to [array of] integer, return submission[s] of the given user[s] only
* @param int $groupid If non-zero, return only submissions by authors in the specified group
* @param int $limitfrom Return a subset of records, starting at this point (optional)
* @param int $limitnum Return a subset containing this many records in total (optional, required if $limitfrom is set)
* @return array of records or an empty array
*/
public function get_submissions($authorid='all') {
public function get_submissions($authorid='all', $groupid=0, $limitfrom=0, $limitnum=0) {
global $DB;
$authorfields = user_picture::fields('u', null, 'authoridx', 'author');
$gradeoverbyfields = user_picture::fields('t', null, 'gradeoverbyx', 'over');
$params = array('workshopid' => $this->id);
$sql = "SELECT s.id, s.workshopid, s.example, s.authorid, s.timecreated, s.timemodified,
s.title, s.grade, s.gradeover, s.gradeoverby, s.published,
$authorfields, $gradeoverbyfields
FROM {workshop_submissions} s
INNER JOIN {user} u ON (s.authorid = u.id)
LEFT JOIN {user} t ON (s.gradeoverby = t.id)
JOIN {user} u ON (s.authorid = u.id)";
if ($groupid) {
$sql .= " JOIN {groups_members} gm ON (gm.userid = u.id AND gm.groupid = :groupid)";
$params['groupid'] = $groupid;
}
$sql .= " LEFT JOIN {user} t ON (s.gradeoverby = t.id)
WHERE s.example = 0 AND s.workshopid = :workshopid";
$params = array('workshopid' => $this->id);
if ('all' === $authorid) {
// no additional conditions
@@ -514,7 +698,7 @@ class workshop {
}
$sql .= " ORDER BY u.lastname, u.firstname";
return $DB->get_records_sql($sql, $params);
return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
}
/**
@@ -1422,18 +1606,18 @@ class workshop {
* Prepares data object with all workshop grades to be rendered
*
* @param int $userid the user we are preparing the report for
* @param mixed $groups single group or array of groups - only show users who are in one of these group(s). Defaults to all
* @param int $groupid if non-zero, prepare the report for the given group only
* @param int $page the current page (for the pagination)
* @param int $perpage participants per page (for the pagination)
* @param string $sortby lastname|firstname|submissiontitle|submissiongrade|gradinggrade
* @param string $sorthow ASC|DESC
* @return stdclass data for the renderer
*/
public function prepare_grading_report_data($userid, $groups, $page, $perpage, $sortby, $sorthow) {
public function prepare_grading_report_data($userid, $groupid, $page, $perpage, $sortby, $sorthow) {
global $DB;
$canviewall = has_capability('mod/workshop:viewallassessments', $this->context, $userid);
$isparticipant = has_any_capability(array('mod/workshop:submit', 'mod/workshop:peerassess'), $this->context, $userid);
$isparticipant = $this->is_participant($userid);
if (!$canviewall and !$isparticipant) {
// who the hell is this?
@@ -1450,9 +1634,7 @@ class workshop {
// get the list of user ids to be displayed
if ($canviewall) {
// fetch the list of ids of all workshop participants - this may get really long so fetch just id
$participants = get_users_by_capability($this->context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
'u.id', '', '', '', $groups, '', false, false, true);
$participants = $this->get_participants(false, $groupid);
} else {
// this is an ordinary workshop participant (aka student) - display the report just for him/her
$participants = array($userid => (object)array('id' => $userid));
@@ -2087,32 +2269,84 @@ class workshop {
}
/**
* Given a list of user ids, returns the filtered one containing just ids of users with own submission
* Returns SQL to fetch all enrolled users with the given capability in the current workshop
*
* Example submissions are ignored.
* The returned array consists of string $sql and the $params array. Note that the $sql can be
* empty if groupmembersonly is enabled and the associated grouping is empty.
*
* @param array $userids
* @return array
* @param string $capability the name of the capability
* @param bool $musthavesubmission ff true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @return array of (string)sql, (array)params
*/
protected function users_with_submission(array $userids) {
global $DB;
protected function get_users_with_capability_sql($capability, $musthavesubmission, $groupid) {
global $CFG;
/** @var int static counter used to generate unique parameter holders */
static $inc = 0;
$inc++;
if (empty($userids)) {
return array();
}
$userswithsubmission = array();
list($usql, $uparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$sql = "SELECT id,authorid
FROM {workshop_submissions}
WHERE example = 0 AND workshopid = :workshopid AND authorid $usql";
$params = array('workshopid' => $this->id);
$params = array_merge($params, $uparams);
$submissions = $DB->get_records_sql($sql, $params);
foreach ($submissions as $submission) {
$userswithsubmission[$submission->authorid] = true;
// if the caller requests all groups and we are in groupmembersonly mode, use the
// recursive call of itself to get users from all groups in the grouping
if (empty($groupid) and !empty($CFG->enablegroupmembersonly) and $this->cm->groupmembersonly) {
$groupingid = $this->cm->groupingid;
$groupinggroupids = array_keys(groups_get_all_groups($this->cm->course, 0, $this->cm->groupingid, 'g.id'));
$sql = array();
$params = array();
foreach ($groupinggroupids as $groupinggroupid) {
if ($groupinggroupid > 0) { // just in case in order not to fall into the endless loop
list($gsql, $gparams) = $this->get_users_with_capability_sql($capability, $musthavesubmission, $groupinggroupid);
$sql[] = $gsql;
$params = array_merge($params, $gparams);
}
}
$sql = implode(PHP_EOL." UNION ".PHP_EOL, $sql);
return array($sql, $params);
}
return $userswithsubmission;
list($esql, $params) = get_enrolled_sql($this->context, $capability, $groupid, true);
$userfields = user_picture::fields('u');
$sql = "SELECT $userfields
FROM {user} u
JOIN ($esql) je ON (je.id = u.id AND u.deleted = 0) ";
if ($musthavesubmission) {
$sql .= " JOIN {workshop_submissions} ws ON (ws.authorid = u.id AND ws.example = 0 AND ws.workshopid = :workshopid{$inc}) ";
$params['workshopid'.$inc] = $this->id;
}
return array($sql, $params);
}
/**
* Returns SQL statement that can be used to fetch all actively enrolled participants in the workshop
*
* @param bool $musthavesubmission if true, return only users who have already submitted
* @param int $groupid 0 means ignore groups, any other value limits the result by group id
* @return array of (string)sql, (array)params
*/
protected function get_participants_sql($musthavesubmission=false, $groupid=0) {
list($sql1, $params1) = $this->get_users_with_capability_sql('mod/workshop:submit', $musthavesubmission, $groupid);
list($sql2, $params2) = $this->get_users_with_capability_sql('mod/workshop:peerassess', $musthavesubmission, $groupid);
if (empty($sql1) or empty($sql2)) {
if (empty($sql1) and empty($sql2)) {
return array('', array());
} else if (empty($sql1)) {
$sql = $sql2;
$params = $params2;
} else {
$sql = $sql1;
$params = $params1;
}
} else {
$sql = $sql1.PHP_EOL." UNION ".PHP_EOL.$sql2;
$params = array_merge($params1, $params2);
}
return array($sql, $params);
}
/**
@@ -2303,8 +2537,7 @@ class workshop_user_plan implements renderable {
$task = new stdclass();
$task->title = get_string('allocate', 'workshop');
$task->link = $workshop->allocation_url();
$numofauthors = count(get_users_by_capability($workshop->context, 'mod/workshop:submit', 'u.id', '', '', '',
'', '', false, true));
$numofauthors = $workshop->count_potential_authors(false);
$numofsubmissions = $DB->count_records('workshop_submissions', array('workshopid'=>$workshop->id, 'example'=>0));
$sql = 'SELECT COUNT(s.id) AS nonallocated
FROM {workshop_submissions} s
@@ -2475,7 +2708,7 @@ class workshop_user_plan implements renderable {
$phase->title = get_string('phaseevaluation', 'workshop');
$phase->tasks = array();
if (has_capability('mod/workshop:overridegrades', $workshop->context)) {
$expected = count($workshop->get_potential_authors(false));
$expected = $workshop->count_potential_authors(false);
$calculated = $DB->count_records_select('workshop_submissions',
'workshopid = ? AND (grade IS NOT NULL OR gradeover IS NOT NULL)', array($workshop->id));
$task = new stdclass();
@@ -2491,7 +2724,7 @@ class workshop_user_plan implements renderable {
}
$phase->tasks['calculatesubmissiongrade'] = $task;
$expected = count($workshop->get_potential_reviewers(false));
$expected = $workshop->count_potential_reviewers(false);
$calculated = $DB->count_records_select('workshop_aggregations',
'workshopid = ? AND gradinggrade IS NOT NULL', array($workshop->id));
$task = new stdclass();
+24
View File
@@ -690,6 +690,30 @@ class mod_workshop_renderer extends plugin_renderer_base {
return $this->render_workshop_assessment($assessment);
}
/**
* Renders a perpage selector for workshop listings
*
* The scripts using this have to define the $PAGE->url prior to calling this
* and deal with eventually submitted value themselves.
*
* @param int $current current value of the perpage parameter
* @return string HTML
*/
public function perpage_selector($current=10) {
$options = array();
foreach (array(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 1000) as $option) {
if ($option != $current) {
$options[$option] = $option;
}
}
$select = new single_select($this->page->url, 'perpage', $options, '', array('' => get_string('showingperpagechange', 'mod_workshop')));
$select->label = get_string('showingperpage', 'mod_workshop', $current);
$select->method = 'post';
return $this->output->container($this->output->render($select), 'perpagewidget');
}
////////////////////////////////////////////////////////////////////////////
// Internal rendering helper methods
////////////////////////////////////////////////////////////////////////////
+10
View File
@@ -18,6 +18,16 @@
text-align: left;
}
.path-mod-workshop .groupwidget {
text-align:center;
margin: 0.75 auto;
}
.path-mod-workshop .perpagewidget {
text-align:center;
margin: 0.75 auto;
}
/**
* Submission - one line summary display
*/
+15
View File
@@ -87,6 +87,21 @@ if ($submission->id and !$workshop->modifying_submission_allowed($USER->id)) {
$editable = false;
}
if ($canviewall) {
// check this flag against the group membership yet
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, $submission->authorid, $workshop->cm->groupingid, 'g.id');
$sharedgroups = array_intersect_key($usersgroups, $authorsgroups);
if (empty($sharedgroups)) {
$canviewall = false;
}
}
}
}
if ($editable and $workshop->useexamples and $workshop->examplesmode == workshop::EXAMPLES_BEFORE_SUBMISSION
and !has_capability('mod/workshop:manageexamples', $workshop->context)) {
// check that all required examples have been assessed by the user
+75 -30
View File
@@ -34,6 +34,10 @@ require_once($CFG->libdir.'/completionlib.php');
$id = optional_param('id', 0, PARAM_INT); // course_module ID, or
$w = optional_param('w', 0, PARAM_INT); // workshop instance ID
$editmode = optional_param('editmode', null, PARAM_BOOL);
$page = optional_param('page', 0, PARAM_INT);
$perpage = optional_param('perpage', null, PARAM_INT);
$sortby = optional_param('sortby', 'lastname', PARAM_ALPHA);
$sorthow = optional_param('sorthow', 'ASC', PARAM_ALPHA);
if ($id) {
$cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST);
@@ -63,6 +67,12 @@ $PAGE->set_url($workshop->view_url());
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
if ($perpage and $perpage > 0 and $perpage <= 1000) {
require_sesskey();
set_user_preference('workshop_perpage', $perpage);
redirect($PAGE->url);
}
$output = $PAGE->get_renderer('mod_workshop');
$userplan = new workshop_user_plan($workshop, $USER->id);
@@ -172,15 +182,43 @@ case workshop::PHASE_SUBMISSION:
}
if (has_capability('mod/workshop:viewallsubmissions', $PAGE->context)) {
$shownames = has_capability('mod/workshop:viewauthornames', $PAGE->context);
print_collapsible_region_start('', 'workshop-viewlet-allsubmissions', get_string('allsubmissions', 'workshop'));
$groupmode = groups_get_activity_groupmode($workshop->cm);
$groupid = groups_get_activity_group($workshop->cm, true);
if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $workshop->context)) {
$allowedgroups = groups_get_activity_allowed_groups($workshop->cm);
if (empty($allowedgroups)) {
echo $output->container(get_string('groupnoallowed', 'mod_workshop'), 'groupwidget error');
break;
}
if (! in_array($groupid, array_keys($allowedgroups))) {
echo $output->container(get_string('groupnotamember', 'core_group'), 'groupwidget error');
break;
}
}
$countsubmissions = $workshop->count_submissions('all', $groupid);
$perpage = get_user_preferences('workshop_perpage', 10);
$pagingbar = new paging_bar($countsubmissions, $page, $perpage, $PAGE->url, 'page');
print_collapsible_region_start('', 'workshop-viewlet-allsubmissions', get_string('allsubmissions', 'workshop', $countsubmissions));
echo $output->box_start('generalbox allsubmissions');
if (! $submissions = $workshop->get_submissions('all')) {
echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget');
if ($countsubmissions == 0) {
echo $output->container(get_string('nosubmissions', 'workshop'), 'nosubmissions');
} else {
$submissions = $workshop->get_submissions('all', $groupid, $page * $perpage, $perpage);
$shownames = has_capability('mod/workshop:viewauthornames', $workshop->context);
echo $output->render($pagingbar);
foreach ($submissions as $submission) {
echo $output->render($workshop->prepare_submission_summary($submission, $shownames));
}
echo $output->render($pagingbar);
echo $output->perpage_selector($perpage);
}
foreach ($submissions as $submission) {
echo $output->render($workshop->prepare_submission_summary($submission, $shownames));
}
echo $output->box_end();
print_collapsible_region_end();
}
@@ -214,19 +252,16 @@ case workshop::PHASE_ASSESSMENT:
}
if (has_capability('mod/workshop:viewallassessments', $PAGE->context)) {
$page = optional_param('page', 0, PARAM_INT);
$sortby = optional_param('sortby', 'lastname', PARAM_ALPHA);
$sorthow = optional_param('sorthow', 'ASC', PARAM_ALPHA);
$perpage = 10; // todo let the user modify this
$groups = ''; // todo let the user choose the group
$PAGE->set_url($PAGE->url, compact('sortby', 'sorthow', 'page')); // TODO: this is suspicious
$data = $workshop->prepare_grading_report_data($USER->id, $groups, $page, $perpage, $sortby, $sorthow);
$perpage = get_user_preferences('workshop_perpage', 10);
$groupid = groups_get_activity_group($workshop->cm, true);
$data = $workshop->prepare_grading_report_data($USER->id, $groupid, $page, $perpage, $sortby, $sorthow);
if ($data) {
$showauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context);
$showreviewernames = has_capability('mod/workshop:viewreviewernames', $workshop->context);
// prepare paging bar
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $PAGE->url, 'page');
$baseurl = new moodle_url($PAGE->url, array('sortby' => $sortby, 'sorthow' => $sorthow));
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $baseurl, 'page');
// grading report display options
$reportopts = new stdclass();
@@ -237,9 +272,15 @@ case workshop::PHASE_ASSESSMENT:
$reportopts->showsubmissiongrade = false;
$reportopts->showgradinggrade = false;
print_collapsible_region_start('', 'workshop-viewlet-gradereport', get_string('gradesreport', 'workshop'));
echo $output->box_start('generalbox gradesreport');
echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget');
echo $output->render($pagingbar);
echo $output->render(new workshop_grading_report($data, $reportopts));
echo $output->render($pagingbar);
echo $output->perpage_selector($perpage);
echo $output->box_end();
print_collapsible_region_end();
}
}
if (trim($workshop->instructreviewers)) {
@@ -346,13 +387,9 @@ case workshop::PHASE_ASSESSMENT:
break;
case workshop::PHASE_EVALUATION:
if (has_capability('mod/workshop:viewallassessments', $PAGE->context)) {
$page = optional_param('page', 0, PARAM_INT);
$sortby = optional_param('sortby', 'lastname', PARAM_ALPHA);
$sorthow = optional_param('sorthow', 'ASC', PARAM_ALPHA);
$perpage = 10; // todo let the user modify this
$groups = ''; // todo let the user choose the group
$PAGE->set_url($PAGE->url, compact('sortby', 'sorthow', 'page')); // TODO: this is suspicious
$data = $workshop->prepare_grading_report_data($USER->id, $groups, $page, $perpage, $sortby, $sorthow);
$perpage = get_user_preferences('workshop_perpage', 10);
$groupid = groups_get_activity_group($workshop->cm, true);
$data = $workshop->prepare_grading_report_data($USER->id, $groupid, $page, $perpage, $sortby, $sorthow);
if ($data) {
$showauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context);
$showreviewernames = has_capability('mod/workshop:viewreviewernames', $workshop->context);
@@ -366,7 +403,8 @@ case workshop::PHASE_EVALUATION:
}
// prepare paging bar
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $PAGE->url, 'page');
$baseurl = new moodle_url($PAGE->url, array('sortby' => $sortby, 'sorthow' => $sorthow));
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $baseurl, 'page');
// grading report display options
$reportopts = new stdclass();
@@ -377,9 +415,15 @@ case workshop::PHASE_EVALUATION:
$reportopts->showsubmissiongrade = true;
$reportopts->showgradinggrade = true;
print_collapsible_region_start('', 'workshop-viewlet-gradereport', get_string('gradesreport', 'workshop'));
echo $output->box_start('generalbox gradesreport');
echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget');
echo $output->render($pagingbar);
echo $output->render(new workshop_grading_report($data, $reportopts));
echo $output->render($pagingbar);
echo $output->perpage_selector($perpage);
echo $output->box_end();
print_collapsible_region_end();
}
}
if (has_capability('mod/workshop:overridegrades', $workshop->context)) {
@@ -454,19 +498,16 @@ case workshop::PHASE_EVALUATION:
break;
case workshop::PHASE_CLOSED:
if (has_capability('mod/workshop:viewallassessments', $PAGE->context)) {
$page = optional_param('page', 0, PARAM_INT);
$sortby = optional_param('sortby', 'lastname', PARAM_ALPHA);
$sorthow = optional_param('sorthow', 'ASC', PARAM_ALPHA);
$perpage = 10; // todo let the user modify this
$groups = ''; // todo let the user choose the group
$PAGE->set_url($PAGE->url, compact('sortby', 'sorthow', 'page')); // TODO: this is suspicious
$data = $workshop->prepare_grading_report_data($USER->id, $groups, $page, $perpage, $sortby, $sorthow);
$perpage = get_user_preferences('workshop_perpage', 10);
$groupid = groups_get_activity_group($workshop->cm, true);
$data = $workshop->prepare_grading_report_data($USER->id, $groupid, $page, $perpage, $sortby, $sorthow);
if ($data) {
$showauthornames = has_capability('mod/workshop:viewauthornames', $workshop->context);
$showreviewernames = has_capability('mod/workshop:viewreviewernames', $workshop->context);
// prepare paging bar
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $PAGE->url, 'page');
$baseurl = new moodle_url($PAGE->url, array('sortby' => $sortby, 'sorthow' => $sorthow));
$pagingbar = new paging_bar($data->totalcount, $page, $perpage, $baseurl, 'page');
// grading report display options
$reportopts = new stdclass();
@@ -478,9 +519,13 @@ case workshop::PHASE_CLOSED:
$reportopts->showgradinggrade = true;
print_collapsible_region_start('', 'workshop-viewlet-gradereport', get_string('gradesreport', 'workshop'));
echo $output->box_start('generalbox gradesreport');
echo $output->container(groups_print_activity_menu($workshop->cm, $PAGE->url, true), 'groupwidget');
echo $output->render($pagingbar);
echo $output->render(new workshop_grading_report($data, $reportopts));
echo $output->render($pagingbar);
echo $output->perpage_selector($perpage);
echo $output->box_end();
print_collapsible_region_end();
}
}