Manual allocator uses the new subrendering feature

This commit is contained in:
David Mudrak 2010-01-04 17:46:33 +00:00
parent 6e3099730e
commit 66c9894dbc
9 changed files with 501 additions and 456 deletions

View File

@ -34,54 +34,38 @@ require_once(dirname(__FILE__).'/allocation/lib.php');
$cmid = required_param('cmid', PARAM_INT); // course module
$method = optional_param('method', 'manual', PARAM_ALPHA); // method to use
$PAGE->set_url('mod/workshop/allocation.php', array('cmid' => $cmid));
$PAGE->set_url('mod/workshop/allocation.php', array('cmid' => $cmid, 'method' => $method));
if (!$cm = get_coursemodule_from_id('workshop', $cmid)) {
print_error('invalidcoursemodule');
}
if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
print_error('coursemisconf');
}
if (!$workshop = $DB->get_record('workshop', array('id' => $cm->instance))) {
print_error('err_invalidworkshopid', 'workshop');
}
$workshop = new workshop_api($workshop, $cm);
$cm = get_coursemodule_from_id('workshop', $cmid, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
$workshop = new workshop_api($workshop, $cm);
require_login($course, false, $cm);
$context = $PAGE->context;
require_capability('mod/workshop:allocate', $context);
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
//
// todo navigation will be changed yet for Moodle 2.0
$navigation = build_navigation(get_string('allocation', 'workshop'), $cm);
$allocator = workshop_allocator_instance($workshop, $method);
try {
$allocator->init();
}
catch (moodle_workshop_exception $e) {
echo $OUTPUT->header($navigation);
throw $e;
}
$allocator = $workshop->allocator_instance($method);
$allocator->init();
//
// Output starts here
//
$wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE);
echo $OUTPUT->header($navigation);
$allocators = workshop_installed_allocators();
$allocators = $workshop->installed_allocators();
$tabrow = array();
foreach ($allocators as $methodid => $methodname) {
$tabrow[] = new tabobject($methodid, "allocation.php?cmid={$cmid}&method={$methodid}", $methodname);
}
print_tabs(array($tabrow), $method);
echo $OUTPUT->container_start('allocator allocator-' . $method);
echo $allocator->ui();
echo $OUTPUT->container_end();
print_tabs(array($tabrow), $method); // todo use $output call
echo $OUTPUT->container($allocator->ui(), 'allocator-ui');
echo $OUTPUT->footer();

View File

@ -57,114 +57,8 @@ interface workshop_allocator {
*
* If a form is part of the UI, the caller should have call $PAGE->set_url(...)
*
* @access public
* @return string HTML to be displayed
*/
public function ui();
}
/**
* Return list of available allocation methods
*
* @access public
* @return array Array ['string' => 'string'] of localized allocation method names
*/
function workshop_installed_allocators() {
$installed = get_list_of_plugins('mod/workshop/allocation');
$forms = array();
foreach ($installed as $allocation) {
$forms[$allocation] = get_string('allocation' . $allocation, 'workshop');
}
// usability - make sure that manual allocation appears the first
if (isset($forms['manual'])) {
$m = array('manual' => $forms['manual']);
unset($forms['manual']);
$forms = array_merge($m, $forms);
}
return $forms;
}
/**
* Returns instance of submissions allocator
*
* @param object $workshop Workshop record
* @param object $method The name of the allocation method, must be PARAM_ALPHA
* @return object Instance of submissions allocator
*/
function workshop_allocator_instance(workshop $workshop, $method) {
$allocationlib = dirname(__FILE__) . '/' . $method . '/allocator.php';
if (is_readable($allocationlib)) {
require_once($allocationlib);
} else {
throw new moodle_exception('missingallocator', 'workshop');
}
$classname = 'workshop_' . $method . '_allocator';
return new $classname($workshop);
}
/**
* Returns the list of submissions and assessments allocated to them in the given workshop
*
* Submissions without allocated assessment are returned too, having assessment attributes null.
* This also fetches all other associated information (like details about the author and reviewer)
* needed to produce allocation reports.
* The returned structure is recordset of objects with following properties:
* [submissionid] [submissiontitle] [authorid] [authorfirstname]
* [authorlastname] [authorpicture] [authorimagealt] [assessmentid]
* [timeallocated] [reviewerid] [reviewerfirstname] [reviewerlastname]
* [reviewerpicture] [reviewerimagealt]
*
* @param object $workshop The workshop object
* @return object Recordset of allocations
*/
function workshop_get_allocations(workshop $workshop) {
global $DB;
$sql = 'SELECT s.id AS submissionid, s.title AS submissiontitle, s.userid AS authorid,
author.firstname AS authorfirstname, author.lastname AS authorlastname,
author.picture AS authorpicture, author.imagealt AS authorimagealt,
a.id AS assessmentid, a.timecreated AS timeallocated, a.userid AS reviewerid,
reviewer.firstname AS reviewerfirstname, reviewer.lastname AS reviewerlastname,
reviewer.picture as reviewerpicture, reviewer.imagealt AS reviewerimagealt
FROM {workshop_submissions} s
LEFT JOIN {workshop_assessments} a ON (s.id = a.submissionid)
LEFT JOIN {user} author ON (s.userid = author.id)
LEFT JOIN {user} reviewer ON (a.userid = reviewer.id)
WHERE s.workshopid = ?
ORDER BY author.lastname,author.firstname,reviewer.lastname,reviewer.firstname';
return $DB->get_recordset_sql($sql, array($workshop->id));
}
/**
* Allocate a submission to a user for review
*
* @param object $workshop Workshop record
* @param object $submission Submission record
* @param int $reviewerid User ID
* @access public
* @return int ID of the new assessment or an error code
*/
function workshop_add_allocation(workshop $workshop, stdClass $submission, $reviewerid) {
global $DB;
if ($DB->record_exists('workshop_assessments', array('submissionid' => $submission->id, 'userid' => $reviewerid))) {
return WORKSHOP_ALLOCATION_EXISTS;
}
$now = time();
$assessment = new stdClass();
$assessment->submissionid = $submission->id;
$assessment->userid = $reviewerid;
$assessment->timecreated = $now;
$assessment->timemodified = $now;
return $DB->insert_record('workshop_assessments', $assessment);
}

View File

@ -75,10 +75,10 @@ class workshop_manual_allocator implements workshop_allocator {
$reviewerid = required_param('by', PARAM_INT);
$authorid = required_param('of', PARAM_INT);
$m = array(); // message object to be passed to the next page
$rs = $this->workshop->get_submissions($authorid);
$rs = $this->workshop->get_submissions_recordset($authorid);
$submission = $rs->current();
$rs->close();
if (!$submission) {
if (empty($submission->id)) {
// nothing submitted by the given user
$m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_NOSUBMISSION;
$m[] = $authorid;
@ -109,10 +109,10 @@ class workshop_manual_allocator implements workshop_allocator {
}
$assessmentid = required_param('what', PARAM_INT);
$confirmed = optional_param('confirm', 0, PARAM_INT);
$rs = $this->workshop->get_assessments('all', $assessmentid);
$rs = $this->workshop->get_assessments_recordset('all', $assessmentid);
$assessment = $rs->current();
$rs->close();
if ($assessment) {
if (!empty($assessment)) {
if (!$confirmed) {
$m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL;
$m[] = $assessment->id;
@ -134,9 +134,6 @@ class workshop_manual_allocator implements workshop_allocator {
}
break;
}
// if we stay on this page, set the environment
$PAGE->requires->css('mod/workshop/allocation/manual/ui.css');
}
@ -146,71 +143,64 @@ class workshop_manual_allocator implements workshop_allocator {
public function ui() {
global $PAGE;
$o = ''; // output buffer
$hlauthorid = -1; // highlight this author
$hlreviewerid = -1; // highlight this reviewer
$msg = ''; // msg text
$sty = ''; // msg style
$m = optional_param('m', '', PARAM_ALPHANUMEXT); // message object
$hlauthorid = -1; // highlight this author
$hlreviewerid = -1; // highlight this reviewer
$msg = new stdClass; // message to render
$m = optional_param('m', '', PARAM_ALPHANUMEXT); // message object
if ($m) {
$m = explode('-', $m); // unserialize
switch ($m[0]) {
case WORKSHOP_ALLOCATION_MANUAL_MSG_ADDED:
$hlauthorid = $m[1];
$hlreviewerid = $m[2];
$msg = get_string('allocationadded', 'workshop');
$sty = 'ok';
$msg->text = get_string('allocationadded', 'workshop');
$msg->sty = 'ok';
break;
case WORKSHOP_ALLOCATION_MANUAL_MSG_EXISTS:
$hlauthorid = $m[1];
$hlreviewerid = $m[2];
$msg = get_string('allocationexists', 'workshop');
$sty = 'info';
$msg->text = get_string('allocationexists', 'workshop');
$msg->sty = 'info';
break;
case WORKSHOP_ALLOCATION_MANUAL_MSG_NOSUBMISSION:
$hlauthorid = $m[1];
$msg = get_string('nosubmissionfound', 'workshop');
$sty = 'error';
$msg->text = get_string('nosubmissionfound', 'workshop');
$msg->sty = 'error';
break;
case WORKSHOP_ALLOCATION_MANUAL_MSG_WOSUBMISSION:
$hlauthorid = $m[1];
$hlreviewerid = $m[2];
$msg = get_string('cantassesswosubmission', 'workshop');
$sty = 'error';
$msg->text = get_string('cantassesswosubmission', 'workshop');
$sty->sty = 'error';
break;
case WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL:
$hlauthorid = $m[2];
$hlreviewerid = $m[3];
if ($m[4] == 0) {
$msg = get_string('areyousuretodeallocate', 'workshop');
$sty = 'info';
$msg->text = get_string('areyousuretodeallocate', 'workshop');
$msg->sty = 'info';
} else {
$msg = get_string('areyousuretodeallocategraded', 'workshop');
$sty = 'error';
$msg->text = get_string('areyousuretodeallocategraded', 'workshop');
$msg->sty = 'error';
}
break;
case WORKSHOP_ALLOCATION_MANUAL_MSG_DELETED:
$hlauthorid = $m[1];
$hlreviewerid = $m[2];
$msg = get_string('assessmentdeleted', 'workshop');
$sty = 'ok';
$msg->text = get_string('assessmentdeleted', 'workshop');
$msg->sty = 'ok';
break;
}
$o .= '<div id="message" class="' . $sty . '">';
$o .= ' <span>' . $msg . '</span>';
$o .= ' <div id="message-close"><a href="' . $PAGE->url->out() . '">' .
get_string('messageclose', 'workshop') . '</a></div>';
if ($m[0] == WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL) {
$handler = $PAGE->url->out_action();
$o .= print_single_button($handler, array('mode' => 'del', 'what' => $m[1], 'confirm' => 1),
$msg->extra = print_single_button($handler, array('mode' => 'del', 'what' => $m[1], 'confirm' => 1),
get_string('iamsure', 'workshop'), 'post', '', true);
}
$o .= '</div>';
}
$peer = array(); // singular chosen due to readibility
$rs = $this->workshop->get_allocations();
$rs = $this->workshop->get_allocations_recordset();
foreach ($rs as $allocation) {
$currentuserid = $allocation->authorid;
if (!isset($peer[$currentuserid])) {
@ -237,159 +227,19 @@ class workshop_manual_allocator implements workshop_allocator {
foreach ($peer as $author) {
foreach ($author->reviewedby as $reviewerid => $assessmentid) {
// example: "user with id 87 is reviewer of the work submitted by user id 45 in the assessment record 12"
if (isset($peer[$reviewerid])) {
// example: "user with id 87 is reviewer of the work submitted by user id 45 in the assessment record 12"
$peer[$reviewerid]->reviewerof[$author->id] = $assessmentid;
}
}
}
if (empty($peer)) {
$o .= '<div id="message" class="info">' . get_string('nosubmissions', 'workshop') . '</div>';
} else {
$o .= '<table class="allocations">' . "\n";
$o .= '<thead><tr>';
$o .= '<th>' . get_string('participantreviewedby', 'workshop') . '</th>';
$o .= '<th>' . get_string('participant', 'workshop') . '</th>';
$o .= '<th>' . get_string('participantrevierof', 'workshop') . '</th>';
$o .= '</thead><tbody>';
$counter = 0;
foreach ($peer as $user) {
$o .= '<tr class="r' . $counter % 2 . '">' . "\n";
if ($user->id == $hlauthorid) {
$highlight=' highlight';
} else {
$highlight='';
}
$o .= '<td class="reviewedby' . $highlight . '">' . "\n";
if (is_null($user->submissionid)) {
$o .= '<span class="info">' . "\n";
$o .= get_string('nothingtoreview', 'workshop');
$o .= '</span>' . "\n";
} else {
$handler = $PAGE->url->out_action() . '&amp;mode=new&amp;of=' . $user->id . '&amp;by=';
$o .= popup_form($handler, $this->available_reviewers($user->id), 'addreviewof' . $user->id, '',
get_string('chooseuser', 'workshop'), '', '', true, 'self', get_string('addreviewer', 'workshop'));
}
$o .= '<ul>' . "\n";
foreach ($user->reviewedby as $reviewerid => $assessmentid) {
$o .= '<li>';
$o .= print_user_picture($peer[$reviewerid], $this->workshop->course, null, 16, true);
$o .= fullname($peer[$reviewerid]);
// delete
$handler = $PAGE->url->out_action(array('mode' => 'del', 'what' => $assessmentid));
$o .= '<a class="action" href="' . $handler . '"> X </a>'; // todo icon and link title
$o .= '</li>';
}
$o .= '</ul>' . "\n";
$o .= '</td>' . "\n";
$o .= '<td class="peer">' . "\n";
$o .= print_user_picture($user, $this->workshop->course, null, 35, true);
$o .= fullname($user);
$o .= '<div class="submission">' . "\n";
if (is_null($user->submissionid)) {
$o .= '<span class="info">' . get_string('nosubmissionfound', 'workshop');
} else {
$o .= '<div class="title"><a href="#">' . s($user->submissiontitle) . '</a></div>';
if (is_null($user->submissiongrade)) {
$o .= '<div class="grade missing">' . get_string('nogradeyet', 'workshop') . '</div>';
} else {
$o .= '<div class="grade">' . s($user->submissiongrade) . '</div>'; // todo calculate
}
}
$o .= '</div>' . "\n";
$o .= '</td>' . "\n";
if ($user->id == $hlreviewerid) {
$highlight=' highlight';
} else {
$highlight='';
}
$o .= '<td class="reviewerof' . $highlight . '">' . "\n";
if (!($this->workshop->assesswosubmission) && is_null($user->submissionid)) {
$o .= '<span class="info">' . "\n";
$o .= get_string('cantassesswosubmission', 'workshop');
$o .= '</span>' . "\n";
} else {
$handler = $PAGE->url->out_action() . '&mode=new&amp;by=' . $user->id . '&amp;of=';
$o .= popup_form($handler, $this->available_reviewees($user->id), 'addreviewby' . $user->id, '',
get_string('chooseuser', 'workshop'), '', '', true, 'self', get_string('addreviewee', 'workshop'));
$o .= '<ul>' . "\n";
foreach ($user->reviewerof as $authorid => $assessmentid) {
$o .= '<li>';
$o .= print_user_picture($peer[$authorid], $this->workshop->course, null, 16, true);
$o .= fullname($peer[$authorid]);
// delete
$handler = $PAGE->url->out_action(array('mode' => 'del', 'what' => $assessmentid));
$o .= '<a class="action" href="' . $handler . '"> X </a>'; // todo icon and link title
$o .= '</li>';
}
$o .= '</ul>' . "\n";
}
$o .= '</td>' . "\n";
$o .= '</tr>' . "\n";
$counter++;
}
$o .= '</tbody></table>' . "\n";
}
return $o;
// ok, we have all data. Let it pass to the renderer and return the output
require_once(dirname(__FILE__) . '/renderer.php');
$uioutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE, 'allocation_manual');
return $uioutput->display_allocations($this->workshop, $peer, $hlauthorid, $hlreviewerid, $msg);
}
/**
* Return a list of reviewers that can review a submission
*
* @param int $authorid User ID of the submission author
* @return array Select options
*/
protected function available_reviewers($authorid) {
$users = $this->workshop->get_peer_reviewers();
$options = array();
foreach ($users as $user) {
$options[$user->id] = fullname($user);
}
if (0 == $this->workshop->useselfassessment) {
// students can not review their own submissions in this workshop
if (isset($options[$authorid])) {
unset($options[$authorid]);
}
}
return $options;
}
/**
* Return a list of reviewees whom work can be reviewed by a given user
*
* @param int $reviewerid User ID of the reviewer
* @return array Select options
*/
protected function available_reviewees($reviewerid) {
$rs = $this->workshop->get_submissions();
$options = array();
foreach ($rs as $submission) {
$options[$submission->userid] = fullname((object)array('firstname' => $submission->authorfirstname,
'lastname' => $submission->authorlastname));
}
$rs->close();
if (0 == $this->workshop->useselfassessment) {
// students can not be reviewed by themselves in this workshop
if (isset($options[$reviewerid])) {
unset($options[$reviewerid]);
}
}
return $options;
}
}

View File

@ -0,0 +1,228 @@
<?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/>.
/**
* Renderer class for the manual allocation UI is defined 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();
/**
* Manual allocation renderer class
*/
class moodle_mod_workshop_allocation_manual_renderer {
/** the underlying renderer to use */
protected $output;
/** the page we are doing output for */
protected $page;
/**
* Workshop renderer constructor
*
* @param mixed $page the page we are doing output for
* @param mixed $output lower-level renderer, typically moodle_core_renderer
* @access public
* @return void
*/
public function __construct($page, $output) {
$this->page = $page;
$this->output = $output;
}
/**
* Display the table of all current allocations and widgets to modify them
*
* @param workshop $workshop workshop instance object
* @param array $peers prepared array of all allocations
* @param int $hlauthorid highlight this author
* @param int $hlreviewerid highlight this reviewer
* @param object message to display
* @return string html code
*/
public function display_allocations(workshop $workshop, &$peers, $hlauthorid=null, $hlreviewerid=null, $msg=null) {
if (empty($peers)) {
return $this->status_message((object)array('text' => get_string('nosubmissions', 'workshop')));
}
$table = new stdClass();
$table->class = 'allocations';
$table->head = array(get_string('participantreviewedby', 'workshop'),
get_string('participant', 'workshop'),
get_string('participantrevierof', 'workshop'));
$table->rowclass = array();
$table->colclasses = array('reviewedby', 'peer', 'reviewerof');
$table->data = array();
foreach ($peers as $user) {
$row = array();
$row[] = $this->reviewers_of_participant($user, $workshop, $peers);
$row[] = $this->participant($user);
$row[] = $this->reviewees_of_participant($user, $workshop, $peers);
$thisrowclasses = array();
if ($user->id == $hlauthorid) {
$thisrowclasses[] = 'highlightreviewedby';
}
if ($user->id == $hlreviewerid) {
$thisrowclasses[] = 'highlightreviewerof';
}
$table->rowclass[] = implode(' ', $thisrowclasses);
$table->data[] = $row;
}
return $this->output->container($this->status_message($msg) . print_table($table, true), 'manual-allocator');
}
/**
* Returns html code for a status message
*
* @param string $message to display
* @return string html
*/
protected function status_message(stdClass $message) {
if (empty($message->text)) {
return '';
}
$sty = $message->sty ? $message->sty : 'info';
$o = '<span>' . $message->text . '</span>';
$closer = '<a href="' . $this->page->url->out() . '">' . get_string('messageclose', 'workshop') . '</a>';
$o .= $this->output->container($closer, 'status-message-closer');
if (isset($message->extra)) {
$o .= $message->extra;
}
return $this->output->container($o, array('status-message', $sty));
}
protected function participant(stdClass $user) {
$o = print_user_picture($user, $this->page->course->id, null, 35, true);
$o .= fullname($user);
$o .= '<div class="submission">' . "\n";
if (is_null($user->submissionid)) {
$o .= '<span class="info">' . get_string('nosubmissionfound', 'workshop');
} else {
$o .= '<div class="title"><a href="#">' . s($user->submissiontitle) . '</a></div>';
if (is_null($user->submissiongrade)) {
$o .= '<div class="grade missing">' . get_string('nogradeyet', 'workshop') . '</div>';
} else {
$o .= '<div class="grade">' . s($user->submissiongrade) . '</div>'; // todo calculate
}
}
$o .= '</div>' . "\n";
return $o;
}
protected function reviewers_of_participant(stdClass $user, workshop $workshop, &$peers) {
$o = '';
if (is_null($user->submissionid)) {
$o .= '<span class="info">' . "\n";
$o .= get_string('nothingtoreview', 'workshop');
$o .= '</span>' . "\n";
} else {
$options = array();
foreach ($workshop->get_peer_reviewers() as $reviewer) {
$options[$reviewer->id] = fullname($reviewer);
}
if (!$workshop->useselfassessment) {
// students can not review their own submissions in this workshop
if (isset($options[$user->id])) {
unset($options[$user->id]);
}
}
$handler = $this->page->url->out_action() . '&amp;mode=new&amp;of=' . $user->id . '&amp;by=';
$o .= popup_form($handler, $options, 'addreviewof' . $user->id, '',
get_string('chooseuser', 'workshop'), '', '', true, 'self', get_string('addreviewer', 'workshop'));
}
$o .= '<ul>' . "\n";
foreach ($user->reviewedby as $reviewerid => $assessmentid) {
$o .= '<li>';
$o .= print_user_picture($peers[$reviewerid], $this->page->course->id, null, 16, true);
$o .= fullname($peers[$reviewerid]);
$handler = $this->page->url->out_action(array('mode' => 'del', 'what' => $assessmentid));
$o .= '<a class="action" href="' . $handler . '"> X </a>';
$o .= '</li>';
}
$o .= '</ul>' . "\n";
return $o;
}
protected function reviewees_of_participant(stdClass $user, workshop $workshop, &$peers) {
$o = '';
if (!$workshop->assesswosubmission && is_null($user->submissionid)) {
$o .= '<span class="info">' . "\n";
$o .= get_string('cantassesswosubmission', 'workshop');
$o .= '</span>' . "\n";
} else {
$options = array();
foreach ($workshop->get_peer_authors(true) as $author) {
$options[$author->id] = fullname($author);
}
if (!$workshop->useselfassessment) {
// students can not be reviewed by themselves in this workshop
if (isset($options[$user->id])) {
unset($options[$user->id]);
}
}
$handler = $this->page->url->out_action() . '&mode=new&amp;by=' . $user->id . '&amp;of=';
$o .= popup_form($handler, $options, 'addreviewby' . $user->id, '',
get_string('chooseuser', 'workshop'), '', '', true, 'self', get_string('addreviewee', 'workshop'));
$o .= '<ul>' . "\n";
foreach ($user->reviewerof as $authorid => $assessmentid) {
$o .= '<li>';
$o .= print_user_picture($peers[$authorid], $this->page->course->id, null, 16, true);
$o .= fullname($peers[$authorid]);
// delete
$handler = $this->page->url->out_action(array('mode' => 'del', 'what' => $assessmentid));
$o .= '<a class="action" href="' . $handler . '"> X </a>'; // todo icon and link title
$o .= '</li>';
}
$o .= '</ul>' . "\n";
}
return $o;
}
}

View File

@ -1,81 +0,0 @@
.allocations {
margin: 0px auto;
}
.allocations .r0 {
background-color: #eee;
}
.allocations .highlight {
background-color: #fff3d2;
}
.allocations tr td {
vertical-align: top;
padding: 5px;
}
.allocations tr td.peer {
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}
.allocations .reviewedby .info,
.allocations .peer .info,
.allocations .reviewerof .info {
font-size: 80%;
color: #888;
font-style: italic;
}
.allocations .reviewedby img.userpicture,
.allocations .reviewerof img.userpicture {
height: 16px;
width: 16px;
margin-right: 3px;
vertical-align: middle;
}
.allocations .peer img.userpicture {
height: 35px;
width: 35px;
vertical-align: middle;
margin-right: 5px;
}
.allocations .peer .submission {
font-size: 90%;
margin-top: 1em;
}
#message {
padding: 5px 5em 5px 15px;
margin: 0px auto 20px auto;
width: 60%;
font-size: 80%;
position: relative;
}
#message-close {
font-weight: bold;
position: absolute;
top: 5px;
right: 15px;
}
#message.ok {
color: #547c22;
background-color: #e7f1c3;
}
#message.error {
color: #dd0221;
background-color: #ffd3d9;
}
#message.info {
color: #1666a9;
background-color: #d2ebff;
}

View File

@ -56,6 +56,7 @@ class workshop_api extends workshop {
* @param object $md Course module record
*/
public function __construct($instance, $cm) {
parent::__construct($instance, $cm);
}
@ -63,21 +64,33 @@ class workshop_api extends workshop {
/**
* Fetches all users with the capability mod/workshop:submit in the current context
*
* Static variable used to cache the results. The returned objects contain id, lastname
* Static variables used to cache the results. The returned objects contain id, lastname
* and firstname properties and are ordered by lastname,firstname
*
* @param object $context The context instance where the capability should be checked
* @param bool $musthavesubmission If true, returns only users with existing submission. All possible authors otherwise.
* @return array Array of '(int)userid => (stdClass)userinfo'
*/
public function get_peer_authors() {
static $users=null;
public function get_peer_authors($musthavesubmission=false) {
global $DB;
static $users = null;
static $userswithsubmission = null;
if (is_null($users)) {
$context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
$users = get_users_by_capability($context, 'mod/workshop:submit',
'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
}
return $users;
if ($musthavesubmission && is_null($userswithsubmission)) {
$userswithsubmission = $DB->get_records_list('workshop_submissions', 'userid', array_keys($users),'', 'userid');
$userswithsubmission = array_intersect_key($users, $userswithsubmission);
}
if ($musthavesubmission) {
return $userswithsubmission;
} else {
return $users;
}
}
@ -98,24 +111,13 @@ class workshop_api extends workshop {
$context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
$users = get_users_by_capability($context, 'mod/workshop:peerassess',
'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
}
if (!$this->assesswosubmission) {
$userswithsubmission = array();
// users without their own submission can not be reviewers
$rs = $DB->get_recordset_list('workshop_submissions', 'userid', array_keys($users),'', 'id,userid');
foreach ($rs as $submission) {
if (isset($users[$submission->userid])) {
$userswithsubmission[$submission->userid] = 'submission_exists';
} else {
// this is a submission by a user who does not have mod/workshop:peerassess
// this is either bug or workshop capabilities have been overridden after the submission
}
if (!$this->assesswosubmission) {
// users without their own submission can not be reviewers
$withsubmission = $DB->get_records_list('workshop_submissions', 'userid', array_keys($users),'', 'userid');
$users = array_intersect_key($users, $withsubmission);
}
$rs->close();
return array_intersect_key($users, $userswithsubmission);
} else {
return $users;
}
return $users;
}
@ -130,7 +132,7 @@ class workshop_api extends workshop {
* @todo unittest
* @return object moodle_recordset
*/
public function get_submissions($userid='all', $examples=false) {
public function get_submissions_recordset($userid='all', $examples=false) {
global $DB;
$sql = 'SELECT s.*, u.lastname AS authorlastname, u.firstname AS authorfirstname
@ -169,7 +171,7 @@ class workshop_api extends workshop {
* @param mixed $id 'all'|int Assessment ID
* @return object moodle_recordset
*/
public function get_assessments($reviewerid='all', $id='all') {
public function get_assessments_recordset($reviewerid='all', $id='all') {
global $DB;
$sql = 'SELECT a.*,
@ -220,7 +222,7 @@ class workshop_api extends workshop {
*
* @return object moodle_recordset
*/
public function get_allocations() {
public function get_allocations_recordset() {
global $DB;
static $users=null;
@ -325,12 +327,50 @@ class workshop_api extends workshop {
}
/**
* Return list of available allocation methods
*
* @return array Array ['string' => 'string'] of localized allocation method names
*/
public function installed_allocators() {
$installed = get_list_of_plugins('mod/workshop/allocation');
$forms = array();
foreach ($installed as $allocation) {
$forms[$allocation] = get_string('allocation' . $allocation, 'workshop');
}
// usability - make sure that manual allocation appears the first
if (isset($forms['manual'])) {
$m = array('manual' => $forms['manual']);
unset($forms['manual']);
$forms = array_merge($m, $forms);
}
return $forms;
}
/**
* Returns instance of submissions allocator
*
* @param object $method The name of the allocation method, must be PARAM_ALPHA
* @return object Instance of submissions allocator
*/
public function allocator_instance($method) {
$allocationlib = dirname(__FILE__) . '/allocation/' . $method . '/allocator.php';
if (is_readable($allocationlib)) {
require_once($allocationlib);
} else {
throw new moodle_exception('missingallocator', 'workshop');
}
$classname = 'workshop_' . $method . '_allocator';
return new $classname($this);
}
}
/**
* Class for workshop exceptions. Just saves a couple of arguments of the
* constructor for a moodle_exception.

62
mod/workshop/renderer.php Normal file
View File

@ -0,0 +1,62 @@
<?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/>.
/**
* All workshop module renderers are defined 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();
/**
* Workshop module renderer class
*
* @package
* @version $Id$
* @copyright
* @author David Mudrak <david.mudrak@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class moodle_mod_workshop_renderer {
/** the underlying renderer to use */
protected $output;
/** the page we are doing output for */
protected $page;
/**
* Workshop renderer constructor
*
* @param mixed $page the page we are doing output for
* @param mixed $output lower-level renderer, typically moodle_core_renderer
* @access public
* @return void
*/
public function __construct($page, $output) {
$this->page = $page;
$this->output = $output;
}
}

86
mod/workshop/styles.php Normal file
View File

@ -0,0 +1,86 @@
/**
* Manual allocator
*/
.manual-allocator .allocations {
margin: 0px auto;
}
.manual-allocator .allocations .r0 {
background-color: #eee;
}
.manual-allocator .allocations .highlightreviewedby .reviewedby,
.manual-allocator .allocations .highlightreviewerof .reviewerof {
background-color: #fff3d2;
}
.manual-allocator .allocations tr td {
vertical-align: top;
padding: 5px;
}
.manual-allocator .allocations tr td.peer {
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}
.manual-allocator .allocations .reviewedby .info,
.manual-allocator .allocations .peer .info,
.manual-allocator .allocations .reviewerof .info {
font-size: 80%;
color: #888;
font-style: italic;
}
.manual-allocator .allocations .reviewedby img.userpicture,
.manual-allocator .allocations .reviewerof img.userpicture {
height: 16px;
width: 16px;
margin-right: 3px;
vertical-align: middle;
}
.manual-allocator .allocations .peer img.userpicture {
height: 35px;
width: 35px;
vertical-align: middle;
margin-right: 5px;
}
.manual-allocator .allocations .peer .submission {
font-size: 90%;
margin-top: 1em;
}
.manual-allocator .status-message {
padding: 5px 5em 5px 15px;
margin: 0px auto 20px auto;
width: 60%;
font-size: 80%;
position: relative;
}
.manual-allocator .status-message-closer {
font-weight: bold;
position: absolute;
top: 5px;
right: 15px;
}
.manual-allocator .status-message.ok {
color: #547c22;
background-color: #e7f1c3;
}
.manual-allocator .status-message.error {
color: #dd0221;
background-color: #ffd3d9;
}
.manual-allocator .status-message.info {
color: #1666a9;
background-color: #d2ebff;
}

View File

@ -31,56 +31,34 @@ require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once(dirname(__FILE__).'/locallib.php');
$id = optional_param('id', 0, PARAM_INT); // course_module ID, or
$a = optional_param('a', 0, PARAM_INT); // workshop instance ID
$w = optional_param('w', 0, PARAM_INT); // workshop instance ID
if ($id) {
if (! $cm = get_coursemodule_from_id('workshop', $id)) {
error('Course Module ID was incorrect');
}
if (! $course = $DB->get_record('course', array('id' => $cm->course))) {
error('Course is misconfigured');
}
if (! $workshop = $DB->get_record('workshop', array('id' => $cm->instance))) {
error('Course module is incorrect');
}
} else if ($a) {
if (! $workshop = $DB->get_record('workshop', array('id' => $a))) {
error('Course module is incorrect');
}
if (! $course = $DB->get_record('course', array('id' => $workshop->course))) {
error('Course is misconfigured');
}
if (! $cm = get_coursemodule_from_instance('workshop', $workshop->id, $course->id)) {
error('Course Module ID was incorrect');
}
$cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST);
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
} else {
error('You must specify a course_module ID or an instance ID');
$workshop = $DB->get_record('workshop', array('id' => $w), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $workshop->course), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('workshop', $workshop->id, $course->id, false, MUST_EXIST);
}
require_login($course, true, $cm);
$context = $PAGE->context;
$workshop = new workshop_api($workshop, $cm);
require_login($course, true, $cm);
$context = $PAGE->context;
// todo has_capability() check
// todo has_capability() check using something like
// if (!(($workshop->is_open() && has_capability('mod/workshop:view')) || has_capability(...) || has_capability(...))) {
// unable to view this page
//
add_to_log($course->id, "workshop", "view", "view.php?id=$cm->id", "$workshop->id");
/// Print the page header
$PAGE->set_url('mod/workshop/view.php', array('id' => $cm->id));
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_button(update_module_button($cm->id, $course->id, get_string('modulename', 'workshop')));
// other things you may want to set - remove if not needed
//$PAGE->set_cacheable(false);
//$PAGE->set_focuscontrol('some-html-id');
// todo navigation will be changed yet for Moodle 2.0
$navlinks = array();
$navlinks[] = array('name' => get_string('modulenameplural', 'workshop'),
@ -92,8 +70,12 @@ $navlinks[] = array('name' => format_string($workshop->name),
$navigation = build_navigation($navlinks);
$menu = navmenu($course, $cm);
$output = $THEME->get_renderer('mod_workshop', $PAGE);
echo $OUTPUT->header($navigation, $menu);
echo $OUTPUT->heading('Workshop administration tools', 3);
/// Print the main part of the page - todo these are just links to help during development
echo $OUTPUT->box_start();
@ -112,7 +94,7 @@ echo $OUTPUT->box_end();
echo $OUTPUT->box_start();
echo $OUTPUT->heading(get_string('assessment', 'workshop'), 3);
$rs = $workshop->get_assessments($USER->id);
$rs = $workshop->get_assessments_recordset($USER->id);
echo "You are expected to assess following submissions:";
echo "<ul>";
foreach ($rs as $assessment) {