From: David Mudrak Date: Mon, 4 Jan 2010 17:49:01 +0000 (+0000) Subject: A lot of changes here and there X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=a39d7d87aa34a5fd1a72c51d42d78b5afe370a48;p=moodle.git A lot of changes here and there --- diff --git a/mod/workshop/TODO.txt b/mod/workshop/TODO.txt new file mode 100644 index 0000000000..6d8726481e --- /dev/null +++ b/mod/workshop/TODO.txt @@ -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 diff --git a/mod/workshop/allocation.php b/mod/workshop/allocation.php index b1954a56d9..fb8d421bb5 100644 --- a/mod/workshop/allocation.php +++ b/mod/workshop/allocation.php @@ -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; diff --git a/mod/workshop/allocation/lib.php b/mod/workshop/allocation/lib.php index 791a9e5b43..706f636214 100644 --- a/mod/workshop/allocation/lib.php +++ b/mod/workshop/allocation/lib.php @@ -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(); diff --git a/mod/workshop/allocation/manual/allocator.php b/mod/workshop/allocation/manual/allocator.php index 975851aad4..ff3f691f78 100644 --- a/mod/workshop/allocation/manual/allocator.php +++ b/mod/workshop/allocation/manual/allocator.php @@ -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); diff --git a/mod/workshop/allocation/manual/renderer.php b/mod/workshop/allocation/manual/renderer.php index 3ceddae5b5..5178a4c978 100644 --- a/mod/workshop/allocation/manual/renderer.php +++ b/mod/workshop/allocation/manual/renderer.php @@ -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'); diff --git a/mod/workshop/allocation/random/allocator.php b/mod/workshop/allocation/random/allocator.php index d1268b06c4..db8dada198 100644 --- a/mod/workshop/allocation/random/allocator.php +++ b/mod/workshop/allocation/random/allocator.php @@ -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) { diff --git a/mod/workshop/allocation/random/settings_form.php b/mod/workshop/allocation/random/settings_form.php index 7299343f88..787a6554df 100644 --- a/mod/workshop/allocation/random/settings_form.php +++ b/mod/workshop/allocation/random/settings_form.php @@ -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'); diff --git a/mod/workshop/allocation/random/simpletest/testallocator.php b/mod/workshop/allocation/random/simpletest/testallocator.php index c08f7b1f0b..d3acd13964 100644 --- a/mod/workshop/allocation/random/simpletest/testallocator.php +++ b/mod/workshop/allocation/random/simpletest/testallocator.php @@ -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); } diff --git a/mod/workshop/assessment.php b/mod/workshop/assessment.php index b995d7700c..77ac63a2d7 100644 --- a/mod/workshop/assessment.php +++ b/mod/workshop/assessment.php @@ -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(); diff --git a/mod/workshop/db/install.xml b/mod/workshop/db/install.xml index a35f9f64df..5e3fa5a440 100644 --- a/mod/workshop/db/install.xml +++ b/mod/workshop/db/install.xml @@ -1,5 +1,5 @@ - @@ -154,8 +154,9 @@ - - + + + @@ -190,4 +191,4 @@ - + \ No newline at end of file diff --git a/mod/workshop/develtools.php b/mod/workshop/develtools.php index 734590884e..1d2e74cd73 100644 --- a/mod/workshop/develtools.php +++ b/mod/workshop/develtools.php @@ -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 = "

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.

"; + + $submission->contentformat = FORMAT_HTML; + $submission->contenttrust = 0; $submission->id = $DB->insert_record('workshop_submissions', $submission); - // todo print some info + echo "
Added submission by " . fullname($author) . "
\n"; + $c++; + } + if ($c == 0) { + echo "
No submission added
\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 ''; + echo $OUTPUT->footer(); } -echo $OUTPUT->header($navigation, $menu); -echo $OUTPUT->heading('Workshop development tools', 1); -echo 'Fake submissions'; -echo $OUTPUT->footer(); + diff --git a/mod/workshop/editform.php b/mod/workshop/editform.php index 3499056ceb..989020f8a4 100644 --- a/mod/workshop/editform.php +++ b/mod/workshop/editform.php @@ -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')); diff --git a/mod/workshop/fileinfolib.php b/mod/workshop/fileinfolib.php index fe41d9656b..994fdb878b 100644 --- a/mod/workshop/fileinfolib.php +++ b/mod/workshop/fileinfolib.php @@ -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; diff --git a/mod/workshop/grading/accumulative/assessment_form.php b/mod/workshop/grading/accumulative/assessment_form.php index ea36b5bb44..99d9cbe8cc 100644 --- a/mod/workshop/grading/accumulative/assessment_form.php +++ b/mod/workshop/grading/accumulative/assessment_form.php @@ -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 = '
' . "\n"; - $desc .= format_text($this->fields["description[$i]"], $this->fields["descriptionformat[$i]"]); + $desc = '
'."\n"; + $desc .= format_text($fields['description__idx_'.$i], $fields['descriptionformat__idx_'.$i]); $desc .= "\n
"; $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)); } } diff --git a/mod/workshop/grading/accumulative/edit_form.php b/mod/workshop/grading/accumulative/edit_form.php index d530b66ac1..13781ee91e 100644 --- a/mod/workshop/grading/accumulative/edit_form.php +++ b/mod/workshop/grading/accumulative/edit_form.php @@ -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); - $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); } - } diff --git a/mod/workshop/grading/accumulative/simpletest/teststrategy.php b/mod/workshop/grading/accumulative/simpletest/teststrategy.php index ff0b353b06..8bbbef52ec 100644 --- a/mod/workshop/grading/accumulative/simpletest/teststrategy.php +++ b/mod/workshop/grading/accumulative/simpletest/teststrategy.php @@ -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[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, @@ -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, + )); + } } diff --git a/mod/workshop/grading/accumulative/strategy.php b/mod/workshop/grading/accumulative/strategy.php index 2aa4fbf274..b14d550e22 100644 --- a/mod/workshop/grading/accumulative/strategy.php +++ b/mod/workshop/grading/accumulative/strategy.php @@ -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() { + /** @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. @@ -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; + } + } diff --git a/mod/workshop/grading/assessment_form.php b/mod/workshop/grading/assessment_form.php index 0599923fb5..10569256e2 100644 --- a/mod/workshop/grading/assessment_form.php +++ b/mod/workshop/grading/assessment_form.php @@ -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(); diff --git a/mod/workshop/grading/edit_form.php b/mod/workshop/grading/edit_form.php index 57f6fae6f6..2fe1dcab6f 100644 --- a/mod/workshop/grading/edit_form.php +++ b/mod/workshop/grading/edit_form.php @@ -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); diff --git a/mod/workshop/grading/lib.php b/mod/workshop/grading/lib.php new file mode 100644 index 0000000000..b76cf02e76 --- /dev/null +++ b/mod/workshop/grading/lib.php @@ -0,0 +1,83 @@ +. + +/** + * This file defines interface of all grading strategy logic classes + * + * @package mod-workshop + * @copyright 2009 David Mudrak + * @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); +} diff --git a/mod/workshop/grading/noerrors/edit_form.php b/mod/workshop/grading/noerrors/edit_form.php index b3634ba598..42e58caadf 100644 --- a/mod/workshop/grading/noerrors/edit_form.php +++ b/mod/workshop/grading/noerrors/edit_form.php @@ -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) { diff --git a/mod/workshop/grading/noerrors/strategy.php b/mod/workshop/grading/noerrors/strategy.php index 149e2a2b5e..292ed4b027 100644 --- a/mod/workshop/grading/noerrors/strategy.php +++ b/mod/workshop/grading/noerrors/strategy.php @@ -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(); diff --git a/mod/workshop/grading/strategy.php b/mod/workshop/grading/strategy.php deleted file mode 100644 index 290363d2c3..0000000000 --- a/mod/workshop/grading/strategy.php +++ /dev/null @@ -1,183 +0,0 @@ -. - -/** - * This file defines a base class for all grading strategy logic - * - * @package mod-workshop - * @copyright 2009 David Mudrak - * @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); - - } - -} diff --git a/mod/workshop/lang/en_utf8/workshop.php b/mod/workshop/lang/en_utf8/workshop.php index 194ba51691..d3be7e0568 100644 --- a/mod/workshop/lang/en_utf8/workshop.php +++ b/mod/workshop/lang/en_utf8/workshop.php @@ -25,10 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$string['userdatecreated'] = 'submitted on $a'; -$string['userdatemodified'] = 'modified on $a'; -$string['byfullname'] = 'by url}\">{$a->name}'; -$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 url}\">{$a->name}'; $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 $a'; +$string['userdatemodified'] = 'modified on $a'; $string['useselfassessmentdesc'] = 'Users perform self assessment of their own work'; $string['useselfassessment'] = 'Use self assessment'; $string['withoutsubmission'] = 'Warning - reviewer without own submission'; diff --git a/mod/workshop/lib.php b/mod/workshop/lib.php index 0dc0c277d3..67654b704c 100644 --- a/mod/workshop/lib.php +++ b/mod/workshop/lib.php @@ -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() { diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index ca44945987..e40ba9519d 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -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 @@ -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 + * + * 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)); } /** @@ -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); - } -} diff --git a/mod/workshop/renderer.php b/mod/workshop/renderer.php index fed5272927..c615ab4416 100644 --- a/mod/workshop/renderer.php +++ b/mod/workshop/renderer.php @@ -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) { diff --git a/mod/workshop/simpletest/testworkshopapi.php b/mod/workshop/simpletest/testworkshopapi.php index 50d6931d55..a85100fc91 100644 --- a/mod/workshop/simpletest/testworkshopapi.php +++ b/mod/workshop/simpletest/testworkshopapi.php @@ -16,7 +16,7 @@ // along with Moodle. If not, see . /** - * 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 @@ -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() { diff --git a/mod/workshop/submission.php b/mod/workshop/submission.php index f2857108e5..a676db763e 100644 --- a/mod/workshop/submission.php +++ b/mod/workshop/submission.php @@ -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(); diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 3a08cce692..bb42f6c459 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -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; diff --git a/mod/workshop/view.php b/mod/workshop/view.php index c9b9bf79c5..e078cbb076 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -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 ''; -echo $OUTPUT->box_end(); - echo $OUTPUT->box_start(); -echo $OUTPUT->heading(get_string('submission', 'workshop'), 3); -echo "id}\">My submission"; -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 ""; -$rs->close(); +echo "" . "\n"; +echo "\n"; echo $OUTPUT->box_end(); echo $OUTPUT->footer();