--- /dev/null
+- 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
$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;
* 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();
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);
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);
*
* @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) {
/**
* 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
* 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'));
* 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');
} 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);
* 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()) {
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);
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;
}
// 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);
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)));
/**
* 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) {
$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');
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);
}
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);
}
}
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);
// 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);
}
}
'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' => '',
// 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();
<?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"
>
<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>
</KEYS>
</TABLE>
</TABLES>
-</XMLDB>
+</XMLDB>
\ No newline at end of file
$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);
$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();
$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();
+
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);
// 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)) {
$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'));
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;
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;
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
/**
*
* 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));
}
}
*
* Called by the parent::definition()
*
- * @access protected
* @return void
*/
protected function definition_inner(&$mform) {
- $gradeoptions = array(20 => 20, 10 => 10, 5 => 5);
- $weights = workshop_get_dimension_weights();
+ $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));
- $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);
+ $gradeoptions = array(20 => 20, 10 => 10, 8=>8, 5 => 5);
+ $weights = workshop_get_dimension_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;
+ 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);
+ }
- $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);
}
-
}
* 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 {
/** 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
$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();
$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[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_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__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,
));
}
+ 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,
+ ));
+ }
}
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() {
+ /** @var workshop the parent workshop instance */
+ protected $workshop;
+
+ /** @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);
+ }
+
+ /**
+ * @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');
+ $dims = $DB->get_records('workshop_forms_' . $this->name(), array('workshopid' => $this->workshop->id), 'sort');
$this->nodimensions = count($dims);
- return $this->_cook_dimension_records($dims);
+ $fields = $this->_cook_dimension_records($dims);
+ return $fields;
}
/**
- * Transpones the dimension data from DB so the assessment form editor can be populated by set_data
+ * Maps the data from DB to their form fields
*
* Called internally from load_form(). Could be private but keeping protected
* for unit testing purposes.
$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;
}
/**
*
* @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)) {
}
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;
+ }
+
}
*/
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.
*
* $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();
* $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);
--- /dev/null
+<?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 <david.mudrak@gmail.com>
+ * @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);
+}
*
* Called by the parent::definition()
*
- * @access protected
* @return void
*/
protected function definition_inner(&$mform) {
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);
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');
}
}
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();
+++ /dev/null
-<?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 <david.mudrak@gmail.com>
- * @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);
-
- }
-
-}
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[''] = '';
$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?';
$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';
$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';
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,
// 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
*
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;
}
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;
}
/**
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);
}
////////////////////////////////////////////////////////////////////////////////
* 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() {
/**
* Return an array of the localized grading strategy names
*
- * @access public
* $return array Array ['string' => 'string']
*/
function workshop_get_strategies() {
* 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 <david.mudrak@gmail.com>
/**
* 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
+ *
+ * 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 The instance data row from {workshop} table
- * @param object $cm Course module record
- * @param object $courserecord Course record
+ * @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));
}
/**
}
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;
}
return $submissions;
} else {
- throw new moodle_workshop_exception($this, 'wrongparameter');
+ throw new moodle_exception('wrongparameter');
}
}
* @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);
* 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) {
* 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) {
* @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;
}
/**
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);
* @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));
}
/**
}
}
-
-/**
- * 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);
- }
-}
*
* @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) {
// 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 <david.mudrak@gmail.com>
* 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() {
}
$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);
$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();
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;
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);
}
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(...))) {
// 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();
'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->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>";
+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&cmid={$cm->id}\">Fake others' submissions</a></li>\n";
+echo "<li><a href=\"allocation.php?cmid={$cm->id}\">Allocate submissions</a></li>\n";
+
+$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();