A lot of changes here and there

This commit is contained in:
David Mudrak
2010-01-04 17:49:01 +00:00
parent b8ead2e6a4
commit a39d7d87aa
31 changed files with 722 additions and 580 deletions
+3
View File
@@ -0,0 +1,3 @@
- assessment form, dimension description - I want to have a single filearea
for all dimension descriptions within the given workshop. Does not work,
TBD with skodak
+1 -1
View File
@@ -38,7 +38,7 @@ $PAGE->set_url('mod/workshop/allocation.php', array('cmid' => $cmid, 'method' =>
$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, $course);
$workshop = new workshop($workshop, $cm, $course);
require_login($course, false, $cm);
$context = $PAGE->context;
+1 -1
View File
@@ -44,7 +44,7 @@ interface workshop_allocator {
* is generated. Therefore is may process any data submitted and do other tasks.
* It should not generate any output
*
* @throws moodle_workshop_exception
* @throws moodle_exception
* @return mixed void or optional HTML string
*/
public function init();
+2 -2
View File
@@ -64,7 +64,7 @@ class workshop_manual_allocator implements workshop_allocator {
switch ($mode) {
case 'new':
if (!confirm_sesskey()) {
throw new moodle_workshop_exception($this->workshop, 'confirmsesskeybad');
throw new moodle_exception('confirmsesskeybad');
}
$reviewerid = required_param('by', PARAM_INT);
$authorid = required_param('of', PARAM_INT);
@@ -93,7 +93,7 @@ class workshop_manual_allocator implements workshop_allocator {
break;
case 'del':
if (!confirm_sesskey()) {
throw new moodle_workshop_exception($this->workshop, 'confirmsesskeybad');
throw new moodle_exception('confirmsesskeybad');
}
$assessmentid = required_param('what', PARAM_INT);
$confirmed = optional_param('confirm', 0, PARAM_INT);
+5 -6
View File
@@ -41,7 +41,6 @@ class moodle_mod_workshop_allocation_manual_renderer extends moodle_renderer_bas
*
* @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) {
@@ -52,7 +51,7 @@ class moodle_mod_workshop_allocation_manual_renderer extends moodle_renderer_bas
/**
* Display the table of all current allocations and widgets to modify them
*
* @param workshop $workshop workshop instance object
* @param workshop $workshop workshop API instance
* @param array $peers prepared array of all allocations
* @param int $hlauthorid highlight this author
* @param int $hlreviewerid highlight this reviewer
@@ -122,11 +121,11 @@ class moodle_mod_workshop_allocation_manual_renderer extends moodle_renderer_bas
* Returns information about the current reviewers of the given participant and a selector do add new one
*
* @param stdClass $user participant data
* @param workshop_api $workshop workshop record
* @param workshop $workshop workshop record
* @param array $peers objects with properties to display picture and fullname
* @return string html code
*/
protected function reviewers_of_participant(stdClass $user, workshop_api $workshop, &$peers) {
protected function reviewers_of_participant(stdClass $user, workshop $workshop, &$peers) {
$o = '';
if (is_null($user->submissionid)) {
$o .= $this->output->output_tag('span', array('class' => 'info'), get_string('nothingtoreview', 'workshop'));
@@ -161,11 +160,11 @@ class moodle_mod_workshop_allocation_manual_renderer extends moodle_renderer_bas
* Returns information about the current reviewees of the given participant and a selector do add new one
*
* @param stdClass $user participant data
* @param workshop_api $workshop workshop record
* @param workshop $workshop workshop record
* @param array $peers objects with properties to display picture and fullname
* @return string html code
*/
protected function reviewees_of_participant(stdClass $user, workshop_api $workshop, &$peers) {
protected function reviewees_of_participant(stdClass $user, workshop $workshop, &$peers) {
$o = '';
if (is_null($user->submissionid)) {
$o .= $this->output->container(get_string('withoutsubmission', 'workshop'), 'info');
+9 -9
View File
@@ -74,7 +74,7 @@ class workshop_random_allocator implements workshop_allocator {
} else if ($settings = $this->mform->get_data()) {
// process validated data
if (!confirm_sesskey()) {
throw new moodle_workshop_exception($this->workshop, 'confirmsesskeybad');
throw new moodle_exception('confirmsesskeybad');
}
$o = array(); // list of output messages
$numofreviews = required_param('numofreviews', PARAM_INT);
@@ -177,9 +177,9 @@ class workshop_random_allocator implements workshop_allocator {
* If the submission has already been allocated, it is skipped. If the author is not found among
* reviewers, the submission is not assigned.
*
* @param array $authors as returned by {@see workshop_api::get_peer_authors_by_group()}
* @param array $reviewers as returned by {@see workshop_api::get_peer_reviewers_by_group()}
* @param array $assessments as returned by {@see workshop_api::get_assessments()}
* @param array $authors as returned by {@see workshop::get_peer_authors_by_group()}
* @param array $reviewers as returned by {@see workshop::get_peer_reviewers_by_group()}
* @param array $assessments as returned by {@see workshop::get_assessments()}
* @return array of new allocations to be created, array of array(reviewerid => authorid)
*/
protected function self_allocation($authors=array(), $reviewers=array(), $assessments=array()) {
@@ -225,7 +225,7 @@ class workshop_random_allocator implements workshop_allocator {
foreach ($newallocations as $newallocation) {
list($reviewerid, $authorid) = each($newallocation);
if (!isset($submissions[$authorid])) {
throw new moodle_workshop_exception($this->workshop, 'unabletoallocateauthorwithoutsubmission');
throw new moodle_exception('unabletoallocateauthorwithoutsubmission', 'workshop');
}
$submission = $submissions[$authorid];
$status = $this->workshop->add_allocation($submission, $reviewerid, true);
@@ -249,7 +249,7 @@ class workshop_random_allocator implements workshop_allocator {
if (is_array($submissions)) {
foreach ($submissions as $submissionid => $submission) {
if (isset($byauthor[$submission->userid])) {
throw new moodle_workshop_exception($this->workshop, 'moresubmissionsbyauthor');
throw new moodle_exception('moresubmissionsbyauthor', 'workshop');
}
$byauthor[$submission->userid] = $submission;
}
@@ -354,7 +354,7 @@ class workshop_random_allocator implements workshop_allocator {
// get current workload
list($squarelinks, $circlelinks) = $this->convert_assessments_to_links($assessments);
} else {
throw new moodle_workshop_exception($this->workshop, 'unknown user type passed');
throw new moodle_exception('unknownusertypepassed', 'workshop');
}
$o[] = 'debug::circle links = ' . json_encode($circlelinks);
$o[] = 'debug::square links = ' . json_encode($squarelinks);
@@ -374,7 +374,7 @@ class workshop_random_allocator implements workshop_allocator {
unset($squaregroupsworkload[0]); // [0] is not real group, it contains all users
$o[] = 'debug::square workload = ' . json_encode($squareworkload);
$o[] = 'debug::square group workload = ' . json_encode($squaregroupsworkload);
$gmode = groups_get_activity_groupmode($this->workshop->cm, $this->workshop->courserecord);
$gmode = groups_get_activity_groupmode($this->workshop->cm, $this->workshop->course);
if (SEPARATEGROUPS == $gmode) {
// shuffle all groups but [0] which means "all users"
$circlegroups = array_keys(array_diff_key($allcircles, array(0 => null)));
@@ -477,7 +477,7 @@ class workshop_random_allocator implements workshop_allocator {
/**
* Extracts the information about reviews from the authors' and reviewers' perspectives
*
* @param array $assessments array of assessments as returned by {@link workshop_api::get_assessments()}
* @param array $assessments array of assessments as returned by {@link workshop::get_assessments()}
* @return array of two arrays
*/
protected function convert_assessments_to_links($assessments) {
@@ -46,7 +46,7 @@ class workshop_random_allocator_form extends moodleform {
$mform->addElement('header', 'settings', get_string('allocationsettings', 'workshop'));
$gmode = groups_get_activity_groupmode($workshop->cm, $workshop->courserecord);
$gmode = groups_get_activity_groupmode($workshop->cm, $workshop->course);
switch ($gmode) {
case NOGROUPS:
$grouplabel = get_string('groupsnone', 'group');
@@ -67,7 +67,10 @@ class workshop_allocation_random_test extends UnitTestCase {
protected $allocator;
public function setUp() {
$this->workshop = new workshop((object)array('id' => 42), new stdClass(), new stdClass());
$cm = (object)array('id' => 3);
$course = (object)array('id' => 11);
$workshop = (object)array('id' => 42);
$this->workshop = new workshop($workshop, $cm, $course);
$this->allocator = new testable_workshop_random_allocator($this->workshop);
}
@@ -141,7 +144,7 @@ class workshop_allocation_random_test extends UnitTestCase {
87 => (object)array('id' => 121, 'userid' => 3),
);
// set expectation
$this->expectException('moodle_workshop_exception');
$this->expectException('moodle_exception');
// exercise SUT
$submissions = $this->allocator->index_submissions_by_authors($submissions);
}
+21 -18
View File
@@ -48,20 +48,21 @@ if ($preview = optional_param('preview', 0, PARAM_INT)) {
}
require_login($course, false, $cm);
$workshop = new workshop_api($workshop, $cm, $course);
if (isguestuser()) {
print_error('guestsarenotallowed');
}
$workshop = new workshop($workshop, $cm, $course);
if ('preview' == $mode) {
require_capability('mod/workshop:editdimensions', $PAGE->context);
// TODO logging add_to_log($course->id, "workshop", "view", "view.php?id=$cm->id", "$workshop->id");
$PAGE->set_url($workshop->previewform_url());
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
} elseif ('assessment' == $mode) {
if (!(has_capability('mod/workshop:peerassess', $PAGE->context) || has_capability('mod/workshop:peerassess', $PAGE->context))) {
if (!has_any_capability(array('mod/workshop:peerassess', 'mod/workshop:assessallsubmissions'), $PAGE->context)) {
print_error('nopermissions', '', $workshop->view_url());
}
// TODO logging add_to_log($course->id, "workshop", "view", "view.php?id=$cm->id", "$workshop->id");
$PAGE->set_url($workshop->assess_url($assessment->id));
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
@@ -79,22 +80,20 @@ $strategy = $workshop->grading_strategy_instance();
// load the form to edit the grading strategy dimensions
$mform = $strategy->get_assessment_form($PAGE->url, $mode);
// initialize form data
//todo $mform->set_data($formdata);
if ($mform->is_cancelled()) {
redirect($returnurl);
} elseif ($data = $mform->get_data()) {
if (isset($data->backtoeditform)) {
// user wants to return from preview to form editing
redirect($workshop->editform_url());
}
$strategy->save_assessment($data);
$strategy->save_assessment($assessment, $data);
if (isset($data->saveandclose)) {
redirect($workshop->view_url());
} else {
// save and continue - redirect to self to prevent data being re-posted by pressing "Reload"
redirect($PAGE->url->out());
redirect($PAGE->url);
}
}
@@ -108,7 +107,7 @@ $navlinks[] = array('name' => format_string($workshop->name),
'type' => 'activityinstance');
if ($mode == 'preview') {
$navlinks[] = array('name' => get_string('editingassessmentform', 'workshop'),
'link' => $workshop->editform_url(),
'link' => $workshop->editform_url()->out(),
'type' => 'title');
$navlinks[] = array('name' => get_string('previewassessmentform', 'workshop'),
'link' => '',
@@ -122,16 +121,20 @@ $navigation = build_navigation($navlinks);
// Output starts here
$wsoutput = $THEME->get_renderer('mod_workshop', $PAGE); // workshop renderer
echo $OUTPUT->header($navigation);
echo $OUTPUT->heading(get_string('assessmentform', 'workshop'), 2);
if (has_capability('mod/workshop:viewauthornames', $PAGE->context)) {
$showname = true;
$author = $workshop->user_info($submission->userid);
} else {
$showname = false;
$author = null;
if ('assessment' === $mode) {
if (has_capability('mod/workshop:viewauthornames', $PAGE->context)) {
$showname = true;
$author = $workshop->user_info($submission->userid);
} else {
$showname = false;
$author = null;
}
$wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE); // workshop renderer
echo $wsoutput->submission_full($submission, $showname, $author);
}
echo $wsoutput->submission_full($submission, $showname, $author);
$mform->display();
echo $OUTPUT->footer();
+5 -4
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/workshop/db" VERSION="20090727" COMMENT="XMLDB file for Moodle mod/workshop"
<XMLDB PATH="mod/workshop/db" VERSION="20090731" COMMENT="XMLDB file for Moodle mod/workshop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@@ -154,8 +154,9 @@
<FIELD NAME="workshopid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" COMMENT="The id of the Workshop instance where this dimension is used as a part of evaluation form." PREVIOUS="id" NEXT="sort"/>
<FIELD NAME="sort" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The order of the dimension in the form" PREVIOUS="workshopid" NEXT="description"/>
<FIELD NAME="description" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="The description of the dimension" PREVIOUS="sort" NEXT="descriptionformat"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description" NEXT="grade"/>
<FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" COMMENT="If greater than 0, then the value is maximum grade on a scale 0..grade. If lesser than 0, then its absolute value is the id of a record in scale table. If equals 0, then no grading is possible for this dimension, just commenting." PREVIOUS="descriptionformat" NEXT="weight"/>
<FIELD NAME="descriptionformat" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field" PREVIOUS="description" NEXT="descriptiontrust"/>
<FIELD NAME="descriptiontrust" TYPE="int" LENGTH="3" NOTNULL="false" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="Can the content be trusted" PREVIOUS="descriptionformat" NEXT="grade"/>
<FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="false" COMMENT="If greater than 0, then the value is maximum grade on a scale 0..grade. If lesser than 0, then its absolute value is the id of a record in scale table. If equals 0, then no grading is possible for this dimension, just commenting." PREVIOUS="descriptiontrust" NEXT="weight"/>
<FIELD NAME="weight" TYPE="int" LENGTH="5" NOTNULL="false" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" COMMENT="The weigh of the dimension" PREVIOUS="grade"/>
</FIELDS>
<KEYS>
@@ -190,4 +191,4 @@
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>
+43 -12
View File
@@ -39,7 +39,7 @@ has_capability('moodle/site:config', get_system_context()) || die('You are not a
$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, $course); // wrap the record with a full API
$workshop = new workshop($workshop, $cm, $course); // wrap the record with a full API
require_login($course, false, $cm);
@@ -48,15 +48,18 @@ $PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_button(update_module_button($cm->id, $course->id, get_string('modulename', 'workshop')));
$wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE);
$navigation = build_navigation('Development tools', $cm);
$menu = navmenu($course, $cm);
// todo $menu = navmenu($course, $cm);
switch ($tool) {
case 'mksubmissions':
$authors = $workshop->get_peer_authors(false);
$authorswithsubmission = $workshop->get_peer_authors(true);
$authors = array_diff_key($authors, $authorswithsubmission);
echo $OUTPUT->header($navigation, $menu);
echo $OUTPUT->header($navigation);
$c = 0; // counter
foreach ($authors as $authorid => $author) {
$timenow = time() - rand(0, 60 * 60 * 24 * 7); // submitted sometimes during last week
$submission = new stdClass();
@@ -66,18 +69,46 @@ case 'mksubmissions':
$submission->timecreated = $timenow;
$submission->timemodified = $timenow;
$submission->title = $author->firstname . '\'s submission';
$submission->data = '';
$submission->dataformat = FORMAT_HTML;
$submission->datatrust = 0;
$submission->content = "<p>Pellentesque habitant morbi tristique " .
"senectus et netus et malesuada fames ac " .
"turpis egestas. Sed posuere volutpat nunc " .
"semper ultricies! Aenean elementum metus in " .
"lorem volutpat eu volutpat neque vulputate? " .
"Pellentesque sit amet sem leo. In hac " .
"habitasse platea dictumst. Proin quis " .
"accumsan elit. Nulla quis libero ac nunc " .
"elementum commodo at et sem. Vestibulum " .
"eget euismod felis. Lorem ipsum dolor sit " .
"amet, consectetur adipiscing elit. Aliquam " .
"id tellus vel velit aliquet volutpat at " .
"quis arcu. Nulla laoreet tincidunt sodales. " .
"Suspendisse potenti. Curabitur sagittis " .
"arcu nec erat aliquet imperdiet. Aenean at " .
"mi ut est molestie posuere a vitae mauris.</p>";
$submission->contentformat = FORMAT_HTML;
$submission->contenttrust = 0;
$submission->id = $DB->insert_record('workshop_submissions', $submission);
// todo print some info
echo "<pre>Added submission by " . fullname($author) . "</pre>\n";
$c++;
}
if ($c == 0) {
echo "<pre>No submission added</pre>\n";
}
echo $OUTPUT->continue_button($PAGE->url->out());
echo $OUTPUT->footer();
exit;
exit();
case 'menu':
// no break, skip to default
default:
echo $OUTPUT->header($navigation);
echo $OUTPUT->heading('Workshop development tools', 1);
echo '<ul>';
echo '<li><a href="' . $PAGE->url->out(false, array('tool' => 'mksubmissions')) . '">Fake submissions</a></li>';
echo '<li><a href="' . $PAGE->url->out(false, array('tool' => 'rmsubmissions')) . '">Remove all submissions (TODO)</a></li>';
echo '</ul>';
echo $OUTPUT->footer();
}
echo $OUTPUT->header($navigation, $menu);
echo $OUTPUT->heading('Workshop development tools', 1);
echo '<a href="' . $PAGE->url->out(false, array('tool' => 'mksubmissions')) . '">Fake submissions</a>';
echo $OUTPUT->footer();
+4 -11
View File
@@ -35,7 +35,7 @@ require_login($course, false, $cm);
require_capability('mod/workshop:editdimensions', $PAGE->context);
$workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
$workshop = new workshop_api($workshop, $cm, $course);
$workshop = new workshop($workshop, $cm, $course);
$PAGE->set_url($workshop->editform_url());
$PAGE->set_title($workshop->name);
@@ -44,21 +44,13 @@ $PAGE->set_heading($course->fullname);
// load the grading strategy logic
$strategy = $workshop->grading_strategy_instance();
// load the assessment form definition from the database
// this must be called before get_edit_strategy_form() where we have to know
// the number of repeating fieldsets
$formdata = $strategy->load_form();
// load the form to edit the grading strategy dimensions
$mform = $strategy->get_edit_strategy_form($PAGE->url);
// initialize form data
$mform->set_data($formdata);
if ($mform->is_cancelled()) {
redirect($workshop->view_url());
} elseif ($data = $mform->get_data()) {
$strategy->save_form($data);
$strategy->save_edit_strategy_form($data);
if (isset($data->saveandclose)) {
redirect($workshop->view_url());
} elseif (isset($data->saveandpreview)) {
@@ -83,8 +75,9 @@ $navlinks[] = array('name' => get_string('editingassessmentform', 'workshop'),
$navigation = build_navigation($navlinks);
// OUTPUT STARTS HERE
// todo use outputlib
print_header_simple(format_string($workshop->name), '', $navigation, '', '', true, '', navmenu($course, $cm));
print_header_simple(format_string($workshop->name), '', $navigation, '', '', true, '');
print_heading(get_string('strategy' . $workshop->strategy, 'workshop'));
+7 -4
View File
@@ -26,11 +26,13 @@
defined('MOODLE_INTERNAL') || die();
/**
* Represents the nodes of the virtual directory tree that may be browsed in file manager
* Represents virtual root node for all submissions
*
* Here we create a virtual hierarchy of all submissions, sorted by their author.
* Workshop submission uses two fileareas: workshop_submission_content
* for editor's embeded media and workshop_submission_attachment for attachments.
* In both, the itemid represents the submission id.
*/
class workshop_file_info extends file_info {
class workshop_file_info_submissions_container extends file_info {
protected $course;
protected $cm;
protected $areas;
@@ -90,7 +92,8 @@ class workshop_file_info extends file_info {
global $DB;
$children = array();
$itemids = $DB->get_records('files', array('contextid' => $this->context->id, 'filearea' => $this->filearea), 'itemid', "DISTINCT itemid");
$itemids = $DB->get_records('files', array('contextid' => $this->context->id, 'filearea' => $this->filearea),
'itemid', "DISTINCT itemid");
foreach ($itemids as $itemid => $unused) {
if ($child = $this->browser->get_file_info($this->context, $this->filearea, $itemid)) {
$children[] = $child;
@@ -25,7 +25,6 @@
defined('MOODLE_INTERNAL') || die();
//require_once(dirname(dirname(dirname(__FILE__))).'/lib.php'); // module library
require_once(dirname(dirname(__FILE__)).'/assessment_form.php'); // parent class definition
/**
@@ -40,32 +39,38 @@ class workshop_accumulative_assessment_form extends workshop_assessment_form {
*
* Called by the parent::definition()
*
* @access protected
* @return void
*/
protected function definition_inner(&$mform) {
$fields = (array)$this->_customdata['fields'];
$nodims = $this->_customdata['nodims']; // number of assessment dimensions
for ($i = 0; $i < $this->strategy->get_number_of_dimensions(); $i++) {
$mform->addElement('hidden', 'nodims', $nodims);
for ($i = 0; $i < $nodims; $i++) {
// dimension header
$mform->addElement('header', "dimensionhdr[$i]",
str_replace('{no}', $i+1, get_string('dimensionnumberaccumulative', 'workshop', '{no}')));
$dimtitle = get_string('dimensionnumberaccumulative', 'workshop', $i+1);
$mform->addElement('header', "dimensionhdr__idx_$i", $dimtitle);
// dimension id
$mform->addElement('hidden', 'dimensionid__idx_'.$i, $fields['dimensionid__idx_'.$i]);
// dimension description
$desc = '<div id="id_dim_'.$this->fields["dimensionid[$i]"] . '_desc" class="fitem description accumulative">' . "\n";
$desc .= format_text($this->fields["description[$i]"], $this->fields["descriptionformat[$i]"]);
$desc = '<div id="id_dim_'.$fields['dimensionid__idx_'.$i].'_desc" class="fitem description accumulative">'."\n";
$desc .= format_text($fields['description__idx_'.$i], $fields['descriptionformat__idx_'.$i]);
$desc .= "\n</div>";
$mform->addElement('html', $desc);
// grade for this aspect
$label = 'Grade'; // todo
$label = 'Grade'; // todo i18n
$label .= ' / ' . $fields['grade__idx_' . $i];
$options = array(10,9,8,7,6,5,4,3,2,1,0); // todo
$mform->addElement('select', "grade[$i]", $label, $options);
$mform->addElement('select', 'grade__idx_' . $i, $label, $options);
// comment
$label = 'Comment'; //todo
$mform->addElement('htmleditor', "comment[$i]", $label, array());
$label = 'Comment'; //todo i18n
//$mform->addElement('editor', 'peercomment__idx_' . $i, $label, null, array('maxfiles' => 0));
$mform->addElement('textarea', 'peercomment__idx_' . $i, $label, array('cols' => 60, 'rows' => 5));
}
}
+22 -22
View File
@@ -40,34 +40,34 @@ class workshop_edit_accumulative_strategy_form extends workshop_edit_strategy_fo
*
* Called by the parent::definition()
*
* @access protected
* @return void
*/
protected function definition_inner(&$mform) {
$gradeoptions = array(20 => 20, 10 => 10, 5 => 5);
$norepeats = $this->_customdata['norepeats']; // number of dimensions to display
$descriptionopts = $this->_customdata['descriptionopts']; // wysiwyg fields options
$current = $this->_customdata['current']; // current data to be set
$mform->addElement('hidden', 'norepeats', $norepeats);
// value not to be overridden by submitted value
$mform->setConstants(array('norepeats' => $norepeats));
$gradeoptions = array(20 => 20, 10 => 10, 8=>8, 5 => 5);
$weights = workshop_get_dimension_weights();
$repeated = array();
$repeated[] =& $mform->createElement('hidden', 'dimensionid', 0);
$repeated[] =& $mform->createElement('header', 'dimension',
get_string('dimensionnumberaccumulative', 'workshop', '{no}'));
$repeated[] =& $mform->createElement('htmleditor', 'description',
get_string('dimensiondescription', 'workshop'), array());
$repeated[] =& $mform->createElement('select', 'grade', get_string('grade'), $gradeoptions);
$repeated[] =& $mform->createElement('select', 'weight', get_string('dimensionweight', 'workshop'), $weights);
for ($i = 0; $i < $norepeats; $i++) {
$mform->addElement('header', 'dimension'.$i, get_string('dimensionnumberaccumulative', 'workshop', $i+1));
$mform->addElement('hidden', 'dimensionid__idx_'.$i);
$mform->addElement('editor', 'description__idx_'.$i.'_editor', get_string('dimensiondescription', 'workshop'),
array('cols' => 20), $descriptionopts);
$mform->addElement('select', 'grade__idx_'.$i, get_string('grade'), $gradeoptions);
$mform->addElement('select', 'weight__idx_'.$i, get_string('dimensionweight', 'workshop'), $weights);
}
$repeatedoptions = array();
$repeatedoptions['description']['type'] = PARAM_CLEANHTML;
$repeatedoptions['description']['helpbutton'] = array('dimensiondescription',
get_string('dimensiondescription', 'workshop'), 'workshop');
$repeatedoptions['grade']['default'] = 10;
$repeatedoptions['weight']['default'] = 1;
$numofdimensionstoadd = 2;
$numofinitialdimensions = 3;
$numofdisplaydimensions = max($this->strategy->get_number_of_dimensions() + $numofdimensionstoadd, $numofinitialdimensions);
$this->repeat_elements($repeated, $numofdisplaydimensions, $repeatedoptions, 'numofdimensions', 'adddimensions', $numofdimensionstoadd, get_string('addmoredimensionsaccumulative', 'workshop', $numofdimensionstoadd));
$mform->registerNoSubmitButton('noadddims');
$mform->addElement('submit', 'noadddims', get_string('addmoredimensionsaccumulative', 'workshop',
WORKSHOP_STRATEGY_ADDDIMS));
$mform->closeHeaderBefore('noadddims');
$this->set_data($current);
}
}
@@ -32,15 +32,15 @@ require_once($CFG->dirroot . '/mod/workshop/grading/accumulative/strategy.php');
* Test subclass that makes all the protected methods we want to test public
*/
class testable_workshop_accumulative_strategy extends workshop_accumulative_strategy {
public function _cook_dimension_records(array $raw) {
return parent::_cook_dimension_records($raw);
}
public function _cook_form_data(stdClass $raw) {
return parent::_cook_form_data($raw);
public function _cook_edit_form_data(stdClass $raw) {
return parent::_cook_edit_form_data($raw);
}
public function _cook_assessment_form_data(stdClass $assessment, stdClass $raw) {
return parent::_cook_assessment_form_data($assessment, $raw);
}
}
class workshop_accumulative_strategy_test extends UnitTestCase {
@@ -59,11 +59,10 @@ class workshop_accumulative_strategy_test extends UnitTestCase {
/** setup testing environment */
public function setUp() {
$this->workshop = new stdClass;
$this->workshop->id = 42;
$this->workshop->strategy = 'accumulative';
$cm = (object)array('id' => 3);
$course = (object)array('id' => 11);
$workshop = (object)array('id' => 42, 'strategy' => 'accumulative');
$this->workshop = new workshop($workshop, $cm, $course);
$this->strategy = new testable_workshop_accumulative_strategy($this->workshop);
// emulate a form with 5 dimensions. The first three are already in DB, the forth is new and the
@@ -71,12 +70,27 @@ class workshop_accumulative_strategy_test extends UnitTestCase {
$this->rawform = new stdClass;
$this->rawform->workshopid = 42;
$this->rawform->strategy = 'accumulative';
$this->rawform->numofdimensions = 5;
$this->rawform->dimensionid = array(0 => 3, 1=> 2, 2 => 1, 3 => 0, 4 => 0);
$this->rawform->description = array(0 => 'First', 1 => 'Second', 2 => 'Third', 3 => 'Forth', 4 => '');
$this->rawform->descriptionformat = array(0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1);
$this->rawform->grade = array(0 => 10, 1 => 5, 2 => 5, 3 => 2, 4 => 10);
$this->rawform->weight = array(0 => 1, 1 => 1, 2 => 2, 3 => 2, 4 => 1);
$this->rawform->norepeats = 5;
$this->rawform->dimensionid__idx_0 = 3;
$this->rawform->dimensionid__idx_1 = 2;
$this->rawform->dimensionid__idx_2 = 1;
$this->rawform->dimensionid__idx_3 = 0;
$this->rawform->dimensionid__idx_4 = 0;
$this->rawform->description__idx_0_editor = array('text' => 'First', 'format' =>1, 'itemid' => 123456789);
$this->rawform->description__idx_1_editor = array('text' => 'Second', 'format' =>1, 'itemid' => 123456788);
$this->rawform->description__idx_2_editor = array('text' => 'Third', 'format' =>1, 'itemid' => 123456787);
$this->rawform->description__idx_3_editor = array('text' => 'Forth', 'format' =>1, 'itemid' => 123456786);
$this->rawform->description__idx_4_editor = array('text' => '', 'format' =>1, 'itemid' => 123456785);
$this->rawform->grade__idx_0 = 10;
$this->rawform->grade__idx_1 = 5;
$this->rawform->grade__idx_2 = 5;
$this->rawform->grade__idx_3 = 2;
$this->rawform->grade__idx_4 = 10;
$this->rawform->weight__idx_0 = 1;
$this->rawform->weight__idx_1 = 1;
$this->rawform->weight__idx_2 = 2;
$this->rawform->weight__idx_3 = 2;
$this->rawform->weight__idx_4 = 1;
// emulate two assessment dimensions being stored in database
$this->rawdb = array();
@@ -98,37 +112,57 @@ class workshop_accumulative_strategy_test extends UnitTestCase {
$this->rawdb[7]->grade = 10;
$this->rawdb[7]->weight = 1;
// emulate the filled assessment form
$this->rawass->nodims = 5;
$this->rawass->strategyname = 'accumulative';
$this->rawass->dimensionid__idx_0 = 3;
$this->rawass->grade__idx_0 = 10;
$this->rawass->peercomment__idx_0 = 'Great';
$this->rawass->dimensionid__idx_1 = 2;
$this->rawass->grade__idx_1 = 4;
$this->rawass->peercomment__idx_1 = 'Hmm';
$this->rawass->dimensionid__idx_2 = 1;
$this->rawass->grade__idx_2 = 1;
$this->rawass->peercomment__idx_2 = 'Uch';
$this->rawass->dimensionid__idx_3 = 4;
$this->rawass->grade__idx_3 = 0;
$this->rawass->peercomment__idx_3 = 'Grrr';
$this->rawass->dimensionid__idx_4 = 5;
$this->rawass->grade__idx_4 = 7;
$this->rawass->peercomment__idx_4 = 'Bye';
}
public function tearDown() {
$this->workshop = null;
$this->strategy = null;
$this->rawform = null;
$this->rawdb = null;
}
public function test_cook_dimension_records() {
// excersise SUT
$cooked = $this->strategy->_cook_dimension_records($this->rawdb);
// verify
$this->assertIsA($cooked, 'stdClass');
$cooked = (array)$cooked;
$this->assertEqual($cooked['dimensionid[0]'], 3);
$this->assertEqual($cooked['description[0]'], 'First');
$this->assertEqual($cooked['descriptionformat[0]'], 1);
$this->assertEqual($cooked['grade[0]'], 20);
$this->assertEqual($cooked['weight[0]'], 16);
$this->assertEqual($cooked->dimensionid__idx_0, 3);
$this->assertEqual($cooked->description__idx_0, 'First');
$this->assertEqual($cooked->descriptionformat__idx_0, 1);
$this->assertEqual($cooked->grade__idx_0, 20);
$this->assertEqual($cooked->weight__idx_0, 16);
$this->assertEqual($cooked['dimensionid[1]'], 7);
$this->assertEqual($cooked['description[1]'], 'Second');
$this->assertEqual($cooked['descriptionformat[1]'], 1);
$this->assertEqual($cooked['grade[1]'], 10);
$this->assertEqual($cooked['weight[1]'], 1);
$this->assertEqual($cooked->dimensionid__idx_1, 7);
$this->assertEqual($cooked->description__idx_1, 'Second');
$this->assertEqual($cooked->descriptionformat__idx_1, 1);
$this->assertEqual($cooked->grade__idx_1, 10);
$this->assertEqual($cooked->weight__idx_1, 1);
}
public function test_cook_form_data() {
public function test_cook_edit_form_data() {
$cooked = $this->strategy->_cook_form_data($this->rawform);
$cooked = $this->strategy->_cook_edit_form_data($this->rawform);
$this->assertIsA($cooked, 'Array');
$this->assertEqual(count($cooked), 5);
$this->assertEqual($cooked[2], (object)array(
'id' => 1,
'workshopid' => 42,
@@ -158,4 +192,40 @@ class workshop_accumulative_strategy_test extends UnitTestCase {
));
}
public function test__cook_assessment_form_data() {
// fixture set-up
$assessment = new stdClass();
$assessment->id = 90;
// exercise SUT
$cooked = $this->strategy->_cook_assessment_form_data($assessment, $this->rawass);
// verify
$this->assertIsA($cooked, 'Array');
$this->assertEqual(count($cooked), 5);
$this->assertEqual($cooked[0], (object)array(
'assessmentid' => 90,
'strategy' => 'accumulative',
'dimensionid' => 3,
'grade' => 10,
'peercomment' => 'Great',
'peercommentformat' => FORMAT_HTML,
));
$this->assertEqual($cooked[2], (object)array(
'assessmentid' => 90,
'strategy' => 'accumulative',
'dimensionid' => 1,
'grade' => 1,
'peercomment' => 'Uch',
'peercommentformat' => FORMAT_HTML,
));
$this->assertEqual($cooked[3], (object)array(
'assessmentid' => 90,
'strategy' => 'accumulative',
'dimensionid' => 4,
'grade' => 0,
'peercomment' => 'Grrr',
'peercommentformat' => FORMAT_HTML,
));
}
}
+197 -34
View File
@@ -25,23 +25,92 @@
defined('MOODLE_INTERNAL') || die();
require_once(dirname(dirname(__FILE__)) . '/strategy.php'); // parent class
require_once(dirname(dirname(__FILE__)) . '/lib.php'); // interface definition
/**
* Accumulative grading strategy logic.
*/
class workshop_accumulative_strategy extends workshop_base_strategy {
class workshop_accumulative_strategy implements workshop_strategy {
public function load_form() {
global $DB;
/** @var workshop the parent workshop instance */
protected $workshop;
$dims = $DB->get_records('workshop_forms_' . $this->name, array('workshopid' => $this->workshop->id), 'sort');
$this->nodimensions = count($dims);
return $this->_cook_dimension_records($dims);
/** @var int number of dimensions defined in database, must be set in {@link load_fields()} */
protected $nodimensions=null;
/** @var array options for dimension description fields */
protected $descriptionopts;
/**
* Constructor
*
* @param object $workshop The workshop instance record
* @return void
*/
public function __construct($workshop) {
$this->workshop = $workshop;
$this->descriptionopts = array('trusttext' => true, 'subdirs' => true, 'maxfiles' => -1);
}
/**
* Transpones the dimension data from DB so the assessment form editor can be populated by set_data
* @return string
*/
public function name() {
return 'accumulative';
}
/**
* Factory method returning an instance of an assessment form editor class
*
* @param $actionurl URL of form handler, defaults to auto detect the current url
*/
public function get_edit_strategy_form($actionurl=null) {
global $CFG; // needed because the included files use it
global $PAGE;
require_once(dirname(__FILE__) . '/edit_form.php');
$fields = $this->load_fields();
if (is_null($this->nodimensions)) {
throw new coding_exception('You forgot to set the number of dimensions in load_fields()');
}
$norepeatsdefault = max($this->nodimensions + WORKSHOP_STRATEGY_ADDDIMS, WORKSHOP_STRATEGY_MINDIMS);
$norepeats = optional_param('norepeats', $norepeatsdefault, PARAM_INT); // number of dimensions
$noadddims = optional_param('noadddims', '', PARAM_ALPHA); // shall we add more?
if ($noadddims) {
$norepeats += WORKSHOP_STRATEGY_ADDDIMS;
}
for ($i = 0; $i < $norepeats; $i++) {
// prepare all editor elements
$fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts,
$PAGE->context, 'workshop_dimension_description', 0);
}
$customdata = array();
$customdata['workshop'] = $this->workshop;
$customdata['strategy'] = $this;
$customdata['norepeats'] = $norepeats;
$customdata['descriptionopts'] = $this->descriptionopts;
$customdata['current'] = $fields;
$attributes = array('class' => 'editstrategyform');
return new workshop_edit_accumulative_strategy_form($actionurl, $customdata, 'post', '', $attributes);
}
/**
* Returns the fields of the assessment form and sets {@var nodimensions}
*/
protected function load_fields() {
global $DB;
$dims = $DB->get_records('workshop_forms_' . $this->name(), array('workshopid' => $this->workshop->id), 'sort');
$this->nodimensions = count($dims);
$fields = $this->_cook_dimension_records($dims);
return $fields;
}
/**
* Maps the data from DB to their form fields
*
* Called internally from load_form(). Could be private but keeping protected
* for unit testing purposes.
@@ -54,14 +123,15 @@ class workshop_accumulative_strategy extends workshop_base_strategy {
$formdata = array();
$key = 0;
foreach ($raw as $dimension) {
$formdata['dimensionid[' . $key . ']'] = $dimension->id;
$formdata['description[' . $key . ']'] = $dimension->description;
$formdata['descriptionformat[' . $key . ']'] = $dimension->descriptionformat;
$formdata['grade[' . $key . ']'] = $dimension->grade;
$formdata['weight[' . $key . ']'] = $dimension->weight;
$formdata['dimensionid__idx_' . $key] = $dimension->id;
$formdata['description__idx_' . $key] = $dimension->description;
$formdata['descriptionformat__idx_' . $key] = $dimension->descriptionformat;
$formdata['grade__idx_' . $key] = $dimension->grade;
$formdata['weight__idx_' . $key] = $dimension->weight;
$key++;
}
return (object)$formdata;
$cooked = (object)$formdata;
return $cooked;
}
/**
@@ -74,18 +144,17 @@ class workshop_accumulative_strategy extends workshop_base_strategy {
*
* @uses $DB
* @param object $data Raw data returned by the dimension editor form
* @access public
* @return void
*/
public function save_form(stdClass $data) {
public function save_edit_strategy_form(stdClass $data) {
global $DB;
if (!isset($data->strategyname) || ($data->strategyname != $this->name)) {
if (!isset($data->strategyname) || ($data->strategyname != $this->name())) {
// the workshop strategy has changed since the form was opened for editing
throw new moodle_exception('strategyhaschanged', 'workshop');
}
$data = $this->_cook_form_data($data);
$data = $this->_cook_edit_form_data($data);
$todelete = array();
foreach ($data as $record) {
if (empty($record->description)) {
@@ -97,41 +166,135 @@ class workshop_accumulative_strategy extends workshop_base_strategy {
}
if (empty($record->id)) {
// new field
$record->id = $DB->insert_record('workshop_forms_' . $this->name, $record);
$record->id = $DB->insert_record('workshop_forms_' . $this->name(), $record);
} else {
// exiting field
$DB->update_record('workshop_forms_' . $this->name, $record);
$DB->update_record('workshop_forms_' . $this->name(), $record);
}
}
$DB->delete_records_list('workshop_forms_' . $this->name, 'id', $todelete);
$DB->delete_records_list('workshop_forms_' . $this->name(), 'id', $todelete);
}
/**
* Prepares data returned by mform so they can be saved into database
* Prepares data returned by {@link workshop_edit_accumulative_strategy_form} so they can be saved into database
*
* It automatically adds some columns into every record. The sorting is
* done by the order of the returned array and starts with 1.
* Called internally from save_form() only. Could be private but
* Called internally from {@link save_edit_strategy_form()} only. Could be private but
* keeping protected for unit testing purposes.
*
* @param object $raw Raw data returned by mform
* @return array Array of objects to be inserted/updated in DB
*/
protected function _cook_form_data(stdClass $raw) {
protected function _cook_edit_form_data(stdClass $raw) {
global $PAGE;
$cook = array();
for ($k = 0; $k < $raw->numofdimensions; $k++) {
$cook[$k] = new stdClass();
$cook[$k]->id = isset($raw->dimensionid[$k]) ? $raw->dimensionid[$k] : null;
$cook[$k]->workshopid = $this->workshop->id;
$cook[$k]->sort = $k + 1;
$cook[$k]->description = isset($raw->description[$k]) ? $raw->description[$k] : null;
$cook[$k]->descriptionformat = FORMAT_HTML;
$cook[$k]->grade = isset($raw->grade[$k]) ? $raw->grade[$k] : null;
$cook[$k]->weight = isset($raw->weight[$k]) ? $raw->weight[$k] : null;
for ($i = 0; $i < $raw->norepeats; $i++) {
$raw = file_postupdate_standard_editor($raw, 'description__idx_'.$i, $this->descriptionopts,
$PAGE->context, 'workshop_dimension_description', 0);
$cook[$i] = new stdClass();
$fieldname = 'dimensionid__idx_'.$i;
$cook[$i]->id = isset($raw->$fieldname) ? $raw->$fieldname : null;
$cook[$i]->workshopid = $this->workshop->id;
$cook[$i]->sort = $i + 1;
$fieldname = 'description__idx_'.$i;
$cook[$i]->description = isset($raw->$fieldname) ? $raw->$fieldname : null;
$fieldname = 'description__idx_'.$i.'format';
$cook[$i]->descriptionformat = isset($raw->$fieldname) ? $raw->$fieldname : FORMAT_HTML;
$fieldname = 'grade__idx_'.$i;
$cook[$i]->grade = isset($raw->$fieldname) ? $raw->$fieldname : null;
$fieldname = 'weight__idx_'.$i;
$cook[$i]->weight = isset($raw->$fieldname) ? $raw->$fieldname : null;
}
return $cook;
}
/**
* Factory method returning an instance of an assessment form
*
* @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
* @param string $mode Mode to open the form in: preview/assessment
*/
public function get_assessment_form(moodle_url $actionurl=null, $mode='preview') {
global $CFG; // needed because the included files use it
require_once(dirname(__FILE__) . '/assessment_form.php');
$fields = $this->load_fields();
if (is_null($this->nodimensions)) {
throw new coding_exception('You forgot to set the number of dimensions in load_fields()');
}
// set up the required custom data common for all strategies
$customdata['strategy'] = $this;
$customdata['mode'] = $mode;
// set up strategy-specific custom data
$customdata['nodims'] = $this->nodimensions;
$customdata['fields'] = $fields;
$attributes = array('class' => 'assessmentform accumulative');
return new workshop_accumulative_assessment_form($actionurl, $customdata, 'post', '', $attributes);
}
/**
* Saves the filled assessment
*
* This method processes data submitted using the form returned by {@link get_assessment_form()}
*
* @param object $assessment Assessment being filled
* @param object $data Raw data as returned by the assessment form
* @return void
*/
public function save_assessment(stdClass $assessment, stdClass $data) {
global $DB;
if (!isset($data->strategyname) || ($data->strategyname != $this->name())) {
// the workshop strategy has changed since the form was opened for editing
throw new moodle_exception('strategyhaschanged', 'workshop');
}
if (!isset($data->nodims)) {
throw coding_expection('You did not send me the number of assessment dimensions to process');
}
foreach ($this->_cook_assessment_form_data($assessment, $data) as $cooked) {
$cooked->id = $DB->get_field('workshop_grades', 'id', array('assessmentid' => $cooked->assessmentid,
'strategy' => 'accumulative',
'dimensionid' => $cooked->dimensionid));
if (false === $cooked->id) {
// not found - new grade
$cooked->id = $DB->insert_record('workshop_grades', $cooked);
} else {
// update existing grade
$DB->update_record('workshop_grades', $cooked);
}
}
// todo recalculate grades
}
/**
* Prepares data returned by {@link workshop_accumulative_assessment_form} so they can be saved into database
*
* Called internally from {@link save_assessment()} only. Could be private but
* keeping protected for unit testing purposes.
*
* @param object $raw Raw data returned by mform
* @return array Array of objects to be inserted/updated in DB
*/
protected function _cook_assessment_form_data(stdClass $assessment, stdClass $raw) {
$raw = (array)$raw;
$cooked = array();
for ($i = 0; $i < $raw['nodims']; $i++) {
$grade = new stdClass();
$grade->assessmentid = $assessment->id;
$grade->strategy = $raw['strategyname'];
$grade->dimensionid = $raw['dimensionid__idx_' . $i];
$grade->grade = $raw['grade__idx_' . $i];
$grade->peercomment = $raw['peercomment__idx_' . $i];
$grade->peercommentformat = FORMAT_HTML;
$cooked[$i] = $grade;
}
return $cooked;
}
}
+5 -15
View File
@@ -38,15 +38,6 @@ require_once($CFG->libdir . '/formslib.php'); // parent class definition
*/
class workshop_assessment_form extends moodleform {
/** object Strategy logic instance */
protected $strategy;
/** array Assessment form fields defined by teacher */
protected $fields = array();
/** string The mode of the form: "preview" or "assessment" */
protected $mode = 'preview';
/**
* Add the fields that are common for all grading strategies.
*
@@ -55,19 +46,18 @@ class workshop_assessment_form extends moodleform {
* $mform->removeElement().
* Strategy subclassess should define their own fields in definition_inner()
*
* @access public
* @return void
*/
public function definition() {
global $CFG;
$mform = $this->_form;
$this->strategy = $this->_customdata['strategy'];
$this->fields = (array)$this->_customdata['fields'];
$this->mode = $this->_customdata['mode'];
$mform = $this->_form;
$this->mode = $this->_customdata['mode']; // influences the save buttons
$this->strategy = $this->_customdata['strategy']; // strategy name sends back for cross check
$mform->addElement('hidden', 'strategyname', $this->strategy->name);
$mform->addElement('hidden', 'strategyname', $this->strategy->name());
// add the strategy-specific fields
$this->definition_inner($mform);
$buttonarray = array();
+3 -2
View File
@@ -49,16 +49,17 @@ class workshop_edit_strategy_form extends moodleform {
* $mform->removeElement().
* Stretegy subclassess should define their own fields in definition_inner()
*
* @access public
* @return void
*/
public function definition() {
global $CFG;
$mform = $this->_form;
$this->workshop = $this->_customdata['workshop'];
$this->strategy = $this->_customdata['strategy'];
$mform->addElement('hidden', 'strategyname', $this->strategy->name);
$mform->addElement('hidden', 'workshopid', $this->workshop->id);
$mform->addElement('hidden', 'strategyname', $this->strategy->name());
$this->definition_inner($mform);
+83
View File
@@ -0,0 +1,83 @@
<?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/>.
/**
* This file defines interface of all grading strategy logic classes
*
* @package mod-workshop
* @copyright 2009 David Mudrak <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
define('WORKSHOP_STRATEGY_MINDIMS', 3); // default number of dimensions to show
define('WORKSHOP_STRATEGY_ADDDIMS', 2); // number of dimensions to add
/**
* Strategy interface defines all methods that strategy subplugins has to implement
*/
interface workshop_strategy {
/**
* Returns name of the strategy
*
* The name may be used to generate table names, class names, paths etc.
*
* @return string
*/
public function name();
/**
* Factory method returning a form that is used to define the assessment form
*
* @param string $actionurl URL of the action handler script, defaults to auto detect
* @return object The instance of the assessment form editor class
*/
public function get_edit_strategy_form($actionurl=null);
/**
* Saves the assessment dimensions and other grading form elements
*
* Assessment dimension (also know as assessment element) represents one aspect or criterion
* to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
* are saved in workshop_forms_{strategyname} tables.
*
* @param object $data Raw data as returned by the form editor
* @return void
*/
public function save_edit_strategy_form(stdClass $data);
/**
* Factory method returning an instance of an assessment form
*
* @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
* @param string $mode Mode to open the form in: preview or assessment
*/
public function get_assessment_form(moodle_url $actionurl=null, $mode='preview');
/**
* Saves the filled assessment
*
* This method processes data submitted using the form returned by {@link get_assessment_form()}
*
* @param object $assessment Assessment being filled
* @param object $data Raw data as returned by the assessment form
* @return void
*/
public function save_assessment(stdClass $assessment, stdClass $data);
}
@@ -40,7 +40,6 @@ class workshop_edit_noerrors_strategy_form extends workshop_edit_strategy_form {
*
* Called by the parent::definition()
*
* @access protected
* @return void
*/
protected function definition_inner(&$mform) {
+5 -5
View File
@@ -35,7 +35,7 @@ class workshop_noerrors_strategy extends workshop_base_strategy {
public function load_form() {
global $DB;
$dims = $DB->get_records('workshop_forms_' . $this->name, array('workshopid' => $this->workshop->id), 'sort');
$dims = $DB->get_records('workshop_forms_' . $this->name(), array('workshopid' => $this->workshop->id), 'sort');
$maps = $DB->get_records('workshop_forms_noerrors_map', array('workshopid' => $this->workshop->id), 'nonegative');
$this->nodimensions = count($dims);
return $this->_cook_database_records($dims, $maps);
@@ -88,7 +88,7 @@ class workshop_noerrors_strategy extends workshop_base_strategy {
public function save_form(stdClass $data) {
global $DB;
if (!isset($data->strategyname) || ($data->strategyname != $this->name)) {
if (!isset($data->strategyname) || ($data->strategyname != $this->name())) {
// the workshop strategy has changed since the form was opened for editing
throw new moodle_exception('strategyhaschanged', 'workshop');
}
@@ -106,14 +106,14 @@ class workshop_noerrors_strategy extends workshop_base_strategy {
}
if (empty($record->id)) {
// new field
$record->id = $DB->insert_record('workshop_forms_' . $this->name, $record);
$record->id = $DB->insert_record('workshop_forms_' . $this->name(), $record);
} else {
// exiting field
$DB->update_record('workshop_forms_' . $this->name, $record);
$DB->update_record('workshop_forms_' . $this->name(), $record);
}
}
// delete dimensions if the teacher removed the description
$DB->delete_records_list('workshop_forms_' . $this->name, 'id', $todelete);
$DB->delete_records_list('workshop_forms_' . $this->name(), 'id', $todelete);
// re-save the mappings
$current = array();
-183
View File
@@ -1,183 +0,0 @@
<?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/>.
/**
* This file defines a base class for all grading strategy logic
*
* @package mod-workshop
* @copyright 2009 David Mudrak <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Strategy interface defines all methods that strategy subplugins has to implemens
*/
interface workshop_strategy {
/**
* Factory method returning an instance of an assessment form editor class
*
* The returned class will probably expand the base workshop_edit_strategy_form. The number of
* dimensions that will be passed by set_data() must be already known here becase the
* definition() of the form has to know the number and it is called before set_data().
*
* @param string $actionurl URL of the action handler script, defaults to auto detect
* @access public
* @return object The instance of the assessment form editor class
*/
public function get_edit_strategy_form($actionurl=null);
/**
* Load the assessment dimensions and other grading form elements
*
* Assessment dimension (also know as assessment element) represents one aspect or criterion
* to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
* are saved in workshop_forms_{strategyname} tables.
* The returned object is passed to the mform set_data() method.
*
* @access public
* @return object Object representing the form fields values
*/
public function load_form();
/**
* Save the assessment dimensions and other grading form elements
*
* Assessment dimension (also know as assessment element) represents one aspect or criterion
* to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
* are saved in workshop_forms_{strategyname} tables.
*
* @access public
* @param object $data Raw data as returned by the form editor
* @return void
*/
public function save_form(stdClass $data);
/**
* Return the number of assessment dimensions defined in the instance of the strategy
*
* @return int Zero or positive integer
*/
public function get_number_of_dimensions();
}
/**
* Base class for grading strategy logic
*
* This base class implements the default behaviour that should be suitable for the most
* of simple grading strategies.
*/
abstract class workshop_base_strategy implements workshop_strategy {
/** the name of the strategy */
public $name;
/** the parent workshop instance */
protected $workshop;
/** number of dimensions defined in database */
protected $nodimensions;
/**
* Constructor
*
* @param object $workshop The workshop instance record
* @access public
* @return void
*/
public function __construct($workshop) {
$this->name = $workshop->strategy;
$this->workshop = $workshop;
$this->nodimensions = null;
}
/**
* Factory method returning an instance of an assessment form editor class
*
* By default, the class is defined in grading/{strategy}/edit_form.php and is named
* workshop_edit_{strategy}_strategy_form
*
* @param $actionurl URL of form handler, defaults to auto detect the current url
*/
public function get_edit_strategy_form($actionurl=null) {
global $CFG; // needed because the included files use it
$strategyform = dirname(__FILE__) . '/' . $this->name . '/edit_form.php';
if (file_exists($strategyform)) {
require_once($strategyform);
} else {
throw new moodle_exception('errloadingstrategyform', 'workshop');
}
$classname = 'workshop_edit_' . $this->name . '_strategy_form';
$customdata = new stdClass;
$customdata = array(
'strategy' => $this,
);
$attributes = array('class' => 'editstrategyform');
return new $classname($actionurl, $customdata, 'post', '', $attributes);
}
/**
* By default, the number of loaded dimensions is set by load_form()
*
* @access public
* @return Array of records
*/
public function get_number_of_dimensions() {
return $this->nodimensions;
}
/**
* Factory method returning an instance of an assessment form
*
* By default, the class is defined in grading/{strategy}/assessment_form.php and is named
* workshop_{strategy}_assessment_form
*
* @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
* @param string $mode Mode to open the form in: preview/assessment
*/
public function get_assessment_form(moodle_url $actionurl=null, $mode='preview') {
global $CFG; // needed because the included files use it
$assessmentform = dirname(__FILE__) . '/' . $this->name . '/assessment_form.php';
if (is_readable($assessmentform)) {
require_once($assessmentform);
} else {
throw new moodle_exception('errloadingassessmentform', 'workshop');
}
$classname = 'workshop_' . $this->name . '_assessment_form';
$customdata = new stdClass;
$customdata = array(
'strategy' => $this,
'fields' => $this->load_form(),
'mode' => $mode,
);
$attributes = array('class' => 'assessmentform');
return new $classname($actionurl, $customdata, 'post', '', $attributes);
}
}
+5 -4
View File
@@ -25,10 +25,7 @@
defined('MOODLE_INTERNAL') || die();
$string['userdatecreated'] = 'submitted on <span>$a</span>';
$string['userdatemodified'] = 'modified on <span>$a</span>';
$string['byfullname'] = 'by <a href=\"{$a->url}\">{$a->name}</a>';
$string[''] = '';
$string['strategyhaschanged'] = 'The workshop grading strategy has changed since the form was opened for editing.';
$string[''] = '';
$string[''] = '';
$string[''] = '';
@@ -59,6 +56,7 @@ $string['allocationrandom'] = 'Random allocation';
$string['allocationsettings'] = 'Allocation settings';
$string['allocation'] = 'Submission allocation';
$string['allocationview'] = 'View current allocations';
$string['areadimensiondescription'] = 'Assessment dimensions';
$string['areasubmissionattachment'] = 'Submission attachments';
$string['areasubmissioncontent'] = 'Submission texts';
$string['areyousuretodeallocate'] = 'Are you sure you want deallocate the selected assessment?';
@@ -74,6 +72,7 @@ $string['assessmentsettings'] = 'Assessment settings';
$string['assessmentstart'] = 'Start of assessment phase';
$string['assesswosubmission'] = 'Users can assess without their own submission';
$string['backtoeditform'] = 'Back to editing form';
$string['byfullname'] = 'by <a href=\"{$a->url}\">{$a->name}</a>';
$string['comparisonhigh'] = 'High';
$string['comparisonlow'] = 'Low';
$string['comparisonnormal'] = 'Normal';
@@ -164,6 +163,8 @@ $string['useexamplesdesc'] = 'Users practise evaluating on example submissions';
$string['useexamples'] = 'Use examples';
$string['usepeerassessmentdesc'] = 'Users perform peer assessment of others\' work';
$string['usepeerassessment'] = 'Use peer assessment';
$string['userdatecreated'] = 'submitted on <span>$a</span>';
$string['userdatemodified'] = 'modified on <span>$a</span>';
$string['useselfassessmentdesc'] = 'Users perform self assessment of their own work';
$string['useselfassessment'] = 'Use self assessment';
$string['withoutsubmission'] = 'Warning - reviewer without own submission';
+90 -107
View File
@@ -48,79 +48,24 @@ define('WORKSHOP_COMPARISON_HIGH', 3); /* f = 3.00 */
define('WORKSHOP_COMPARISON_VERYHIGH', 4); /* f = 5.00 */
/**
* The base class of workshop instances
* Saves a new instance of the workshop into the database
*
* It defines methods that are part of any activity module API and may be called by Moodle core.
* The class just wraps the database record from the {workshop} table and adds some
* methods that implement the compulsory activity module API.
* For full-featured workshop class see {@link workshop_api}.
*/
class workshop {
/** @var object course module record */
public $cm;
/** @var object course record */
public $courserecord;
/**
*
* Initializes the object using the data from DB. Makes deep copy of all $dbrecord properties.
* Please do not confuse $this->course (integer property from the database record) and
* $this->courserecord (object containing the whole course record).
*
* @param object $instance The instance data row from {workshop} table
* @param object $cm Course module record
* @param object $courserecord Course record
*/
public function __construct(stdClass $instance, stdClass $cm, stdClass $courserecord) {
foreach ($instance as $key => $val) {
if (is_object($val) || (is_array($val))) {
// this should not happen if the $dbrecord is really just the record returned by $DB
$this->{$key} = unserialize(serialize($val));
} else {
$this->{$key} = $val;
}
}
$this->cm = $cm;
$this->courserecord = $courserecord;
}
/**
* 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 object $data An object from the form in mod_form.php
* @return int The id of the newly inserted workshop record
*/
public static function add_instance($data) {
global $DB;
$data->timecreated = time();
$data->timemodified = $data->timecreated;
return $DB->insert_record('workshop', $data);
}
}
/**
* Given an object containing all the necessary data,
* (defined by the form in mod_form.php) this function
* will create a new instance and return the id number
* will save a new instance and return the id number
* of the new instance.
*
* @param object $data An object from the form in mod_form.php
* @return int The id of the newly inserted workshop record
*/
function workshop_add_instance($data) {
return workshop::add_instance($data);
}
global $DB;
// TODO convert following functions into workshop methods
$data->timecreated = time();
$data->timemodified = $data->timecreated;
return $DB->insert_record('workshop', $data);
}
/**
* Given an object containing all the necessary data,
@@ -320,6 +265,27 @@ function workshop_get_extra_capabilities() {
// File API //
////////////////////////////////////////////////////////////////////////////////
/**
* Returns the lists of all browsable file areas within the given module context
*
* The file area workshop_intro for the activity introduction field is added automatically
* by {@link file_browser::get_file_info_module()}
*
* @param object $course
* @param object $cm
* @param object $context
* @return array of [(string)filearea] => (string)description
*/
function workshop_get_file_areas($course, $cm, $context) {
$areas = array();
if (has_capability('moodle/course:managefiles', $context)) {
$areas['workshop_dimension_description'] = get_string('areadimensiondescription', 'workshop');
$areas['workshop_submission_content'] = get_string('areasubmissioncontent', 'workshop');
$areas['workshop_submission_attachment'] = get_string('areasubmissionattachment', 'workshop');
}
return $areas;
}
/**
* Serves the files from the workshop file areas
*
@@ -344,7 +310,7 @@ function workshop_pluginfile($course, $cminfo, $context, $filearea, $args, $forc
return false;
}
$fileareas = array('workshop_submission_content', 'workshop_submission_attachment');
$fileareas = array('workshop_submission_content', 'workshop_submission_attachment', 'workshop_dimension_description');
if (!in_array($filearea, $fileareas)) {
return false;
}
@@ -371,31 +337,17 @@ function workshop_pluginfile($course, $cminfo, $context, $filearea, $args, $forc
if ((!$file = $fs->get_file_by_hash(sha1($fullpath))) || ($file->is_directory())) {
return false;
}
// TODO MDL-19941 make sure the user is allowed to see the submission
// TODO make sure the user is allowed to see the file
// finally send the file
send_stored_file($file, 0, 0, true); // download MUST be forced - security!
}
if ('workshop_dimension_description' == $filearea) {
// media embedded by teacher into the dimension description
send_stored_file($file);
/**
* Returns the lists of all browsable file areas within the given module context
*
* The file area workshop_intro for the activity introduction field is added automatically
* by {@link file_browser::get_file_info_module()}
*
* @param object $course
* @param object $cm
* @param object $context
* @return array of [(string)filearea] => (string)description
*/
function workshop_get_file_areas($course, $cm, $context) {
$areas = array();
// todo re-think capability checking
if (has_capability('mod/workshop:submit', $context) || has_capability('mod/workshop:submitexamples', $context)) {
$areas['workshop_submission_content'] = get_string('areasubmissioncontent', 'workshop');
$areas['workshop_submission_attachment'] = get_string('areasubmissionattachment', 'workshop');
} else {
// files uploaded by students in their attachments - forcing download for security reasons
send_stored_file($file, 0, 0, true);
}
return $areas;
}
/**
@@ -416,33 +368,66 @@ function workshop_get_file_info($browser, $areas, $course, $cm, $context, $filea
global $CFG, $DB;
static $authors=null; // cache for submission authors
if (!($filearea == 'workshop_submission_content' || $filearea == 'workshop_submission_attachment')) {
if (!has_capability('moodle/course:managefiles', $context)) {
return null;
}
if (is_null($itemid)) {
require_once($CFG->dirroot . '/mod/workshop/fileinfolib.php');
return new workshop_file_info($browser, $course, $cm, $context, $areas, $filearea);
}
$fs = get_file_storage();
$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
if (!$storedfile = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
return null;
if ($filearea === 'workshop_submission_content' or $filearea === 'workshop_submission_attachment') {
if (is_null($itemid)) {
require_once($CFG->dirroot . '/mod/workshop/fileinfolib.php');
return new workshop_file_info_submissions_container($browser, $course, $cm, $context, $areas, $filearea);
}
// we are inside the submission container
$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
if (!$storedfile = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
if ($filepath === '/' and $filename === '.') {
$storedfile = new virtual_root_file($context->id, $filearea, $itemid);
} else {
// not found
return null;
}
}
// let us display the author's name instead of itemid (submission id)
if (is_null($authors)) {
$sql = 'SELECT s.id, u.lastname, u.firstname
FROM {workshop_submissions} s
JOIN {user} u ON (s.userid = u.id)
WHERE s.workshopid = ?';
$params[0] = $cm->instance;
$authors = $DB->get_records_sql($sql, $params);
}
$urlbase = $CFG->wwwroot . '/pluginfile.php';
$topvisiblename = fullname($authors[$itemid]);
// do not allow manual modification of any files!
return new file_info_stored($browser, $context, $storedfile, $urlbase, $topvisiblename, true, true, false, false);
}
if (is_null($authors)) {
$sql = 'SELECT s.id, u.lastname, u.firstname
FROM {workshop_submissions} s
JOIN {user} u ON (s.userid = u.id)
WHERE s.workshopid = ?';
$params[0] = $cm->instance;
$authors = $DB->get_records_sql($sql, $params);
if ($filearea === 'workshop_dimension_description') {
// always only itemid 0
$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
$urlbase = $CFG->wwwroot.'/pluginfile.php';
if (!$storedfile = $fs->get_file($context->id, $filearea, 0, $filepath, $filename)) {
if ($filepath === '/' and $filename === '.') {
$storedfile = new virtual_root_file($context->id, $filearea, 0);
} else {
// not found
return null;
}
}
return new file_info_stored($browser, $context, $storedfile, $urlbase, $areas[$filearea], false, true, true, false);
}
$urlbase = $CFG->wwwroot . '/pluginfile.php';
$topvisiblename = fullname($authors[$itemid]);
// do not allow manual modification of any files!
return new file_info_stored($browser, $context, $storedfile, $urlbase, $topvisiblename, true, true, false, false);
}
////////////////////////////////////////////////////////////////////////////////
@@ -458,7 +443,6 @@ function workshop_get_file_info($browser, $areas, $course, $cm, $context, $filea
* assessment are defined via a HTML select form element. By default it returns
* an array 0, 1, 2, ..., 98, 99, 100.
*
* @access public
* @return array Array of integers
*/
function workshop_get_maxgrades() {
@@ -516,7 +500,6 @@ function workshop_get_dimension_weights() {
/**
* Return an array of the localized grading strategy names
*
* @access public
* $return array Array ['string' => 'string']
*/
function workshop_get_strategies() {
+43 -51
View File
@@ -21,7 +21,7 @@
* All the workshop specific functions, needed to implement the module
* logic, should go to here. Instead of having bunch of function named
* workshop_something() taking the workshop instance as the first
* parameter, we use a class workshop_api that provides all methods.
* parameter, we use a class workshop that provides all methods.
*
* @package mod-workshop
* @copyright 2009 David Mudrak <[email protected]>
@@ -37,24 +37,42 @@ define('WORKSHOP_ALLOCATION_EXISTS', -1); // return status of {@link a
/**
* Full-featured workshop API
*
* This extends the module base API and adds the internal methods that are called
* This wraps the workshop database record with a set of methods that are called
* from the module itself. The class should be initialized right after you get
* $workshop and $cm records at the begining of the script.
* $workshop, $cm and $course records at the begining of the script.
*/
class workshop_api extends workshop {
class workshop {
/** @var object course module record */
public $cm = null;
/** @var object course record */
public $course = null;
/** grading strategy instance */
protected $strategy_api=null;
private $_strategyinstance = null;
/**
* Initialize the object using the data from DB
* Initializes the object using the data from DB
*
* @param object $instance The instance data row from {workshop} table
* @param object $cm Course module record
* @param object $courserecord Course record
* Makes deep copy of all passed records properties. Replaces integer $course attribute
* with a full database record (course should not be stored in instances table anyway).
*
* @param object $instance Workshop instance data from {workshop} table
* @param object $cm Course module record as returned by {@link get_coursemodule_from_id()}
* @param object $course Course record from {course} table
*/
public function __construct($instance, $cm, $courserecord) {
parent::__construct($instance, $cm, $courserecord);
public function __construct(stdClass $instance, stdClass $cm, stdClass $course) {
foreach ($instance as $key => $val) {
if (is_object($val) || (is_array($val))) {
// this should not happen if the $instance is really just the record returned by $DB
$this->{$key} = unserialize(serialize($val)); // makes deep copy of referenced variables
} else {
$this->{$key} = $val;
}
}
$this->cm = unserialize(serialize($cm));
$this->course = unserialize(serialize($course));
}
/**
@@ -78,6 +96,7 @@ class workshop_api extends workshop {
}
if ($musthavesubmission && is_null($userswithsubmission)) {
$userswithsubmission = array();
$submissions = $DB->get_records_list('workshop_submissions', 'userid', array_keys($users),'', 'id,userid');
foreach ($submissions as $submission) {
$userswithsubmission[$submission->userid] = null;
@@ -268,7 +287,7 @@ class workshop_api extends workshop {
}
return $submissions;
} else {
throw new moodle_workshop_exception($this, 'wrongparameter');
throw new moodle_exception('wrongparameter');
}
}
@@ -322,7 +341,7 @@ class workshop_api extends workshop {
* @param mixed $reviewerid 'all'|int|array User ID of the reviewer
* @param mixed $id 'all'|int Assessment ID
* @return array [assessmentid] => assessment object
* @see workshop_api::get_assessments_recordset() for the structure of returned objects
* @see workshop::get_assessments_recordset() for the structure of returned objects
*/
public function get_assessments($reviewerid='all', $id='all') {
$rs = $this->get_assessments_recordset($reviewerid, $id);
@@ -348,7 +367,7 @@ class workshop_api extends workshop {
* Get the information about the given assessment
*
* @param int $id Assessment ID
* @see workshop_api::get_assessments_recordset() for the structure of data returned
* @see workshop::get_assessments_recordset() for the structure of data returned
* @return mixed false if not found, object otherwise
*/
public function get_assessment_by_id($id) {
@@ -366,7 +385,7 @@ class workshop_api extends workshop {
* Get the information about all assessments assigned to the given reviewer
*
* @param int $id Reviewer ID
* @see workshop_api::get_assessments_recordset() for the structure of data returned
* @see workshop::get_assessments_recordset() for the structure of data returned
* @return array array of objects
*/
public function get_assessments_by_reviewer($id) {
@@ -479,20 +498,20 @@ class workshop_api extends workshop {
* @return object Instance of a grading strategy
*/
public function grading_strategy_instance() {
if (is_null($this->strategy_api)) {
if (is_null($this->_strategyinstance)) {
$strategylib = dirname(__FILE__) . '/grading/' . $this->strategy . '/strategy.php';
if (is_readable($strategylib)) {
require_once($strategylib);
} else {
throw new moodle_workshop_exception($this, 'missingstrategy');
throw new moodle_exception('missingstrategy', 'workshop');
}
$classname = 'workshop_' . $this->strategy . '_strategy';
$this->strategy_api = new $classname($this);
if (!in_array('workshop_strategy', class_implements($this->strategy_api))) {
throw new moodle_workshop_exception($this, 'strategynotimplemented');
$this->_strategyinstance = new $classname($this);
if (!in_array('workshop_strategy', class_implements($this->_strategyinstance))) {
throw new moodle_exception('strategynotimplemented', 'workshop');
}
}
return $this->strategy_api;
return $this->_strategyinstance;
}
/**
@@ -526,7 +545,7 @@ class workshop_api extends workshop {
if (is_readable($allocationlib)) {
require_once($allocationlib);
} else {
throw new moodle_workshop_exception($this, 'missingallocator');
throw new coding_exception('Unable to find allocator.php');
}
$classname = 'workshop_' . $method . '_allocator';
return new $classname($this);
@@ -560,9 +579,9 @@ class workshop_api extends workshop {
* @param int $assessmentid The ID of assessment record
* @return object {@link moodle_url} the URL of the assessment page
*/
public function assess_url() {
public function assess_url($assessmentid) {
global $CFG;
return new moodle_url($CFG->wwwroot . '/mod/workshop/assessment.php', array('asid' => $this->cm->id));
return new moodle_url($CFG->wwwroot . '/mod/workshop/assessment.php', array('asid' => $assessmentid));
}
/**
@@ -582,30 +601,3 @@ class workshop_api extends workshop {
}
}
/**
* Class for workshop exceptions. Just saves a couple of arguments of the
* constructor for a moodle_exception.
*
* @param object $workshop Should be workshop or its subclass
* @param string $errorcode
* @param mixed $a Object/variable to pass to get_string
* @param string $link URL to continue after the error notice
* @param $debuginfo
*/
class moodle_workshop_exception extends moodle_exception {
function __construct($workshop, $errorcode, $a = NULL, $link = '', $debuginfo = null) {
global $CFG;
if (!$link) {
$link = $CFG->wwwroot . '/mod/workshop/view.php?a=' . $workshop->id;
}
if ('confirmsesskeybad' == $errorcode) {
$module = '';
} else {
$module = 'workshop';
}
parent::__construct($errorcode, $module, $link, $a, $debuginfo);
}
}
-1
View File
@@ -44,7 +44,6 @@ class moodle_mod_workshop_renderer extends moodle_renderer_base {
*
* @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) {
+7 -8
View File
@@ -16,7 +16,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for workshop_api class defined in mod/workshop/locallib.php
* Unit tests for workshop class defined in mod/workshop/locallib.php
*
* @package mod-workshop
* @copyright 2009 David Mudrak <[email protected]>
@@ -32,25 +32,24 @@ require_once($CFG->dirroot . '/mod/workshop/locallib.php'); // Include the code
* Test subclass that makes all the protected methods we want to test public.
* Also re-implements bridging methods so we can test more easily.
*/
class testable_workshop_api extends workshop_api {
class testable_workshop extends workshop {
}
/**
* Test cases for the internal workshop api
*/
class workshop_api_test extends UnitTestCase {
class workshop_internal_api_test extends UnitTestCase {
/** workshop instance emulation */
protected $workshop;
/** setup testing environment */
public function setUp() {
$workshoprecord = new stdClass;
$workshoprecord->id = 42;
$cm = new stdClass;
$this->workshop = new testable_workshop_api($workshoprecord, $cm);
$cm = (object)array('id' => 3);
$course = (object)array('id' => 11);
$workshop = (object)array('id' => 42);
$this->workshop = new testable_workshop($workshop, $cm, $course);
}
public function tearDown() {
+3 -3
View File
@@ -41,7 +41,7 @@ if (isguestuser()) {
}
$workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
$workshop = new workshop_api($workshop, $cm, $course);
$workshop = new workshop($workshop, $cm, $course);
if ($id) { // submission is specified
$submission = $DB->get_record('workshop_submissions', array('id' => $id, 'workshopid' => $workshop->id), '*', MUST_EXIST);
@@ -101,9 +101,9 @@ $PAGE->set_heading($course->fullname);
$stredit = empty($submission->id) ? get_string('editingsubmission', 'workshop') : get_string('edit');
$navigation = build_navigation($stredit, $cm);
$menu = navmenu($course, $cm);
// todo $menu = navmenu($course, $cm);
echo $OUTPUT->header($navigation, $menu);
echo $OUTPUT->header($navigation);
echo $OUTPUT->heading(format_string($workshop->name), 2);
$mform->display();
echo $OUTPUT->footer();
+2 -2
View File
@@ -28,6 +28,6 @@
defined('MOODLE_INTERNAL') || die();
$module->version = 2009070500;
$module->requires = 2009050619; // Requires this Moodle version
$module->version = 2009073100;
$module->requires = 2009073000; // Requires this Moodle version
$module->cron = 60;
+33 -29
View File
@@ -29,8 +29,9 @@
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
$w = optional_param('w', 0, PARAM_INT); // workshop instance ID
$id = optional_param('id', 0, PARAM_INT); // course_module ID, or
$w = optional_param('w', 0, PARAM_INT); // workshop instance ID
$edit = optional_param('edit', null, PARAM_BOOL);
if ($id) {
$cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST);
@@ -43,7 +44,7 @@ if ($id) {
}
require_login($course, true, $cm);
$workshop = new workshop_api($workshop, $cm, $course);
$workshop = new workshop($workshop, $cm, $course);
// todo has_capability() check using something like
// if (!(($workshop->is_open() && has_capability('mod/workshop:view')) || has_capability(...) || has_capability(...))) {
@@ -52,10 +53,23 @@ $workshop = new workshop_api($workshop, $cm, $course);
// todo logging add_to_log($course->id, "workshop", "view", "view.php?id=$cm->id", "$workshop->id");
if (!is_null($edit) && $PAGE->user_allowed_editing()) {
$USER->editing = $edit;
}
$PAGE->set_url($workshop->view_url());
$PAGE->set_title($workshop->name);
$PAGE->set_heading($course->fullname);
$PAGE->set_button(update_module_button($cm->id, $course->id, get_string('modulename', 'workshop')));
$buttons = array();
if ($PAGE->user_allowed_editing()) {
$editblocks = new html_form();
$editblocks->method = 'get';
$editblocks->button->text = get_string($PAGE->user_is_editing() ? 'blockseditoff' : 'blocksediton');
$editblocks->url = new moodle_url($PAGE->url, array('edit' => $PAGE->user_is_editing() ? 'off' : 'on'));
$buttons[] = $OUTPUT->button($editblocks);
}
$buttons[] = update_module_button($cm->id, $course->id, get_string('modulename', 'workshop'));
$PAGE->set_button(implode('', $buttons));
// todo navigation will be changed yet for Moodle 2.0
$navlinks = array();
@@ -66,39 +80,29 @@ $navlinks[] = array('name' => format_string($workshop->name),
'link' => '',
'type' => 'activityinstance');
$navigation = build_navigation($navlinks);
$menu = navmenu($course, $cm);
//$menu = navmenu($course, $cm); todo
/// Output starts here
echo $OUTPUT->header($navigation, $menu);
echo $OUTPUT->header($navigation);
/// Print the main part of the page - todo these are just links to help during development
echo $OUTPUT->heading('Workshop administration tools', 3);
echo $OUTPUT->box_start();
echo $OUTPUT->heading('Workshop administration tools', 3);
echo '<ul>';
echo '<li><a href="' . $workshop->editform_url()->out() . '">Edit grading form (' . get_string('strategy' . $workshop->strategy, 'workshop') . ')</a></li>';
echo "<li><a href=\"allocation.php?cmid={$cm->id}\">Allocate submissions</a></li>";
echo "<li><a href=\"develtools.php?cmid={$cm->id}\">Development tools</a></li>";
echo '</ul>';
echo $OUTPUT->box_end();
echo $OUTPUT->heading('Workshop testing', 1);
echo "<ol>\n";
echo '<li><a href="' . $workshop->editform_url()->out() . '">Edit grading form (' . get_string('strategy' . $workshop->strategy, 'workshop') . ')</a></li>' . "\n";
echo "<li><a href=\"submission.php?cmid={$cm->id}\">View/edit your own submission</a></li>\n";
echo "<li><a href=\"develtools.php?tool=mksubmissions&amp;cmid={$cm->id}\">Fake others' submissions</a></li>\n";
echo "<li><a href=\"allocation.php?cmid={$cm->id}\">Allocate submissions</a></li>\n";
echo $OUTPUT->box_start();
echo $OUTPUT->heading(get_string('submission', 'workshop'), 3);
echo "<a href=\"submission.php?cmid={$cm->id}\">My submission</a>";
echo $OUTPUT->box_end();
echo $OUTPUT->box_start();
echo $OUTPUT->heading(get_string('assessment', 'workshop'), 3);
$rs = $workshop->get_assessments_recordset($USER->id);
echo "You are expected to assess following submissions:";
echo "<ul>";
foreach ($rs as $assessment) {
echo "<li><a href=\"assessment.php?asid={$assessment->id}\">Assessment of '{$assessment->title}' by {$assessment->authorid}</a></li>";
$assessments = $workshop->get_assessments($USER->id);
echo "<li>Assess submissions\n";
echo "<ol>\n";
foreach ($assessments as $assessment) {
echo "<li><a href=\"assessment.php?asid={$assessment->id}\">Assessment of '{$assessment->title}' by {$assessment->authorid}</a></li>" . "\n";
}
echo "</ul>";
$rs->close();
echo "</ol></li>" . "\n";
echo "</ol>\n";
echo $OUTPUT->box_end();
echo $OUTPUT->footer();