]> git.mjollnir.org Git - moodle.git/commitdiff
Mostly working on the view.php UI plus some changes
authorDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:00:54 +0000 (18:00 +0000)
committerDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:00:54 +0000 (18:00 +0000)
18 files changed:
mod/workshop/allocation.php
mod/workshop/allocation/lib.php
mod/workshop/allocation/manual/allocator.php
mod/workshop/allocation/random/allocator.php
mod/workshop/allocation/random/settings_form.php
mod/workshop/assessment.php
mod/workshop/editform.php
mod/workshop/grading/accumulative/strategy.php
mod/workshop/grading/lib.php
mod/workshop/grading/noerrors/strategy.php
mod/workshop/lang/en_utf8/workshop.php
mod/workshop/lib.php
mod/workshop/locallib.php
mod/workshop/renderer.php
mod/workshop/styles.php
mod/workshop/submission.php
mod/workshop/tabs.php [new file with mode: 0644]
mod/workshop/view.php

index d3e35b65c45979d8d5d0b887f5b092045ece9407..cb03276a17cd8068e048dc894232b72a613eb25d 100644 (file)
@@ -70,7 +70,7 @@ if (!empty($initresult)) {
     echo $OUTPUT->container_end();
 } else {
     echo $OUTPUT->container_start('allocator-ui');
-    $allocator->ui($wsoutput);
+    echo $allocator->ui();
     echo $OUTPUT->container_end();
 }
 echo $OUTPUT->footer();
index 7b429c02cd2a398aac6428e80774c06d3b832c1a..ec9fb60300a1782944389d9a07f0e85b6be64c18 100644 (file)
@@ -42,10 +42,11 @@ interface workshop_allocator {
      *
      * This method is called soon after the allocator is constructed and before any output
      * is generated. Therefore is may process any data submitted and do other tasks.
-     * It should not generate any output
+     * It should not generate any output. However if it does so, the output is rendered
+     * using the method {@link moodle_mod_workshop_renderer::allocation_init_result()}
      *
      * @throws moodle_exception
-     * @return mixed void or optional HTML string
+     * @return void|string
      */
     public function init();
 
@@ -53,13 +54,9 @@ interface workshop_allocator {
      * Print HTML to be displayed as the user interface
      *
      * If a form is part of the UI, the caller should have called $PAGE->set_url(...)
-     * The methods must produce output instead of just returning it so mform->display() can
-     * be used there. This should be changed once we make quickforms deprecated and then,
-     * this method will just return the required HTML code.
      *
      * @param stdClass $wsoutput workshop module renderer can be used
-     * @return void
+     * @return string HTML code to be echoed
      */
-    public function ui(moodle_mod_workshop_renderer $wsoutput);
-
+    public function ui();
 }
index 40f04aa24642fbbff15fef78bebcc06eb1811c9e..3fc6156c4a6379263e01c59f0d5b993ea8b8f14c 100644 (file)
@@ -28,22 +28,20 @@ defined('MOODLE_INTERNAL') || die();
 require_once(dirname(dirname(__FILE__)) . '/lib.php');                  // interface definition
 require_once(dirname(dirname(dirname(__FILE__))) . '/locallib.php');    // workshop internal API
 
-/**
- * These constants are used to pass status messages between init() and ui()
- */
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_ADDED',          1);
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_NOSUBMISSION',   2);
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_EXISTS',         3);
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL',    4);
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_DELETED',        5);
-define('WORKSHOP_ALLOCATION_MANUAL_MSG_DELETE_ERROR',   6);
-
 /**
  * Allows users to allocate submissions for review manually
  */
 class workshop_manual_allocator implements workshop_allocator {
 
-    /** workshop instance */
+    /** constants that are used to pass status messages between init() and ui() */
+    const MSG_ADDED         = 1;
+    const MSG_NOSUBMISSION  = 2;
+    const MSG_EXISTS        = 3;
+    const MSG_CONFIRM_DEL   = 4;
+    const MSG_DELETED       = 5;
+    const MSG_DELETE_ERROR  = 6;
+
+    /** @var workshop instance */
     protected $workshop;
 
     /**
@@ -72,18 +70,18 @@ class workshop_manual_allocator implements workshop_allocator {
             $submission = $this->workshop->get_submission_by_author($authorid);
             if (!$submission) {
                 // nothing submitted by the given user
-                $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_NOSUBMISSION;
+                $m[] = self::MSG_NOSUBMISSION;
                 $m[] = $authorid;
 
             } else {
                 // ok, we have the submission
                 $res = $this->workshop->add_allocation($submission, $reviewerid);
-                if ($res == WORKSHOP_ALLOCATION_EXISTS) {
-                    $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_EXISTS;
+                if ($res == workshop::ALLOCATION_EXISTS) {
+                    $m[] = self::MSG_EXISTS;
                     $m[] = $submission->userid;
                     $m[] = $reviewerid;
                 } else {
-                    $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_ADDED;
+                    $m[] = self::MSG_ADDED;
                     $m[] = $submission->userid;
                     $m[] = $reviewerid;
                 }
@@ -100,7 +98,7 @@ class workshop_manual_allocator implements workshop_allocator {
             $assessment     = $this->workshop->get_assessment_by_id($assessmentid);
             if ($assessment) {
                 if (!$confirmed) {
-                    $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL;
+                    $m[] = self::MSG_CONFIRM_DEL;
                     $m[] = $assessment->id;
                     $m[] = $assessment->authorid;
                     $m[] = $assessment->reviewerid;
@@ -111,11 +109,11 @@ class workshop_manual_allocator implements workshop_allocator {
                     }
                 } else {
                     if($this->workshop->delete_assessment($assessment->id)) {
-                        $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_DELETED;
+                        $m[] = self::MSG_DELETED;
                         $m[] = $assessment->authorid;
                         $m[] = $assessment->reviewerid;
                     } else {
-                        $m[] = WORKSHOP_ALLOCATION_MANUAL_MSG_DELETE_ERROR;
+                        $m[] = self::MSG_DELETE_ERROR;
                         $m[] = $assessment->authorid;
                         $m[] = $assessment->reviewerid;
                     }
@@ -130,9 +128,10 @@ class workshop_manual_allocator implements workshop_allocator {
     /**
      * Prints user interface - current allocation and a form to edit it
      */
-    public function ui(moodle_mod_workshop_renderer $wsoutput) {
+    public function ui() {
         global $PAGE;
         global $CFG;    // bacause we include other libs here
+        global $OUTPUT;
 
         $hlauthorid     = -1;           // highlight this author
         $hlreviewerid   = -1;           // highlight this reviewer
@@ -142,24 +141,24 @@ class workshop_manual_allocator implements workshop_allocator {
         if ($m) {
             $m = explode('-', $m);  // unserialize
             switch ($m[0]) {
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_ADDED:
+            case self::MSG_ADDED:
                 $hlauthorid     = $m[1];
                 $hlreviewerid   = $m[2];
                 $msg->text      = get_string('allocationadded', 'workshopallocation_manual');
                 $msg->sty       = 'ok';
                 break;
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_EXISTS:
+            case self::MSG_EXISTS:
                 $hlauthorid     = $m[1];
                 $hlreviewerid   = $m[2];
                 $msg->text      = get_string('allocationexists', 'workshopallocation_manual');
                 $msg->sty       = 'info';
                 break;
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_NOSUBMISSION:
+            case self::MSG_NOSUBMISSION:
                 $hlauthorid     = $m[1];
                 $msg->text      = get_string('nosubmissionfound', 'workshop');
                 $msg->sty       = 'error';
                 break;
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL:
+            case self::MSG_CONFIRM_DEL:
                 $hlauthorid     = $m[2];
                 $hlreviewerid   = $m[3];
                 if ($m[4] == 0) {
@@ -170,55 +169,58 @@ class workshop_manual_allocator implements workshop_allocator {
                     $msg->sty   = 'error';
                 }
                 break;
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_DELETED:
+            case self::MSG_DELETED:
                 $hlauthorid     = $m[1];
                 $hlreviewerid   = $m[2];
                 $msg->text      = get_string('assessmentdeleted', 'workshop');
                 $msg->sty       = 'ok';
                 break;
-            case WORKSHOP_ALLOCATION_MANUAL_MSG_DELETE_ERROR:
+            case self::MSG_DELETE_ERROR:
                 $hlauthorid     = $m[1];
                 $hlreviewerid   = $m[2];
                 $msg->text      = get_string('assessmentnotdeleted', 'workshop');
                 $msg->sty       = 'error';
                 break;
             }
-            if ($m[0] == WORKSHOP_ALLOCATION_MANUAL_MSG_CONFIRM_DEL) {
-                $handler = $PAGE->url->out_action();
-                $msg->extra = print_single_button($handler, array('mode' => 'del', 'what' => $m[1], 'confirm' => 1),
-                                get_string('iamsure', 'workshop'), 'post', '', true);
+            if ($m[0] == self::MSG_CONFIRM_DEL) {
+                $form = new html_form();
+                $form->url = new moodle_url($PAGE->url, array('mode' => 'del', 'what' => $m[1], 'confirm' => 1));
+                $form->button = new html_button();
+                $form->button->text = get_string('iamsure', 'workshop');
+                $form->method = 'post';
+                $msg->extra = $OUTPUT->button($form);
             }
         }
 
-        $peer = array(); // singular chosen due to readibility
+        $peers = array();
         $rs = $this->workshop->get_allocations_recordset();
         foreach ($rs as $allocation) {
             $currentuserid = $allocation->authorid;
-            if (!isset($peer[$currentuserid])) {
-                $peer[$currentuserid]                   = new stdClass();
-                $peer[$currentuserid]->id               = $allocation->authorid;
-                $peer[$currentuserid]->firstname        = $allocation->authorfirstname;
-                $peer[$currentuserid]->lastname         = $allocation->authorlastname;
-                $peer[$currentuserid]->picture          = $allocation->authorpicture;
-                $peer[$currentuserid]->imagealt         = $allocation->authorimagealt;
-                $peer[$currentuserid]->submissionid     = $allocation->submissionid;
-                $peer[$currentuserid]->submissiontitle  = $allocation->submissiontitle;
-                $peer[$currentuserid]->submissiongrade  = $allocation->submissiongrade;
-                $peer[$currentuserid]->reviewedby       = array(); // users who are reviewing this user's submission
-                $peer[$currentuserid]->reviewerof       = array(); // users whom submission is being reviewed by this user
+            if (!isset($peers[$currentuserid])) {
+                $peers[$currentuserid]                   = new stdClass();
+                $peers[$currentuserid]->id               = $allocation->authorid;
+                $peers[$currentuserid]->firstname        = $allocation->authorfirstname;
+                $peers[$currentuserid]->lastname         = $allocation->authorlastname;
+                $peers[$currentuserid]->picture          = $allocation->authorpicture;
+                $peers[$currentuserid]->imagealt         = $allocation->authorimagealt;
+                $peers[$currentuserid]->submissionid     = $allocation->submissionid;
+                $peers[$currentuserid]->submissiontitle  = $allocation->submissiontitle;
+                $peers[$currentuserid]->submissiongrade  = $allocation->submissiongrade;
+                $peers[$currentuserid]->reviewedby       = array(); // users who are reviewing this user's submission
+                $peers[$currentuserid]->reviewerof       = array(); // users whom submission is being reviewed by this user
             }
             if (!empty($allocation->reviewerid)) {
                 // example: "submission of user with id 45 is reviewed by user with id 87 in the assessment record 12"
-                $peer[$currentuserid]->reviewedby[$allocation->reviewerid] = $allocation->assessmentid;
+                $peers[$currentuserid]->reviewedby[$allocation->reviewerid] = $allocation->assessmentid;
             }
         }
         $rs->close();
 
-        foreach ($peer as $author) {
+        foreach ($peers as $author) {
             foreach ($author->reviewedby as $reviewerid => $assessmentid) {
-                if (isset($peer[$reviewerid])) {
+                if (isset($peers[$reviewerid])) {
                     // example: "user with id 87 is reviewer of the work submitted by user id 45 in the assessment record 12"
-                    $peer[$reviewerid]->reviewerof[$author->id] = $assessmentid;
+                    $peers[$reviewerid]->reviewerof[$author->id] = $assessmentid;
                 }
             }
         }
@@ -227,8 +229,7 @@ class workshop_manual_allocator implements workshop_allocator {
         // Here, we do not use neither the core renderer nor the workshop one but use an own one
         require_once(dirname(__FILE__) . '/renderer.php');
         $uioutput = $PAGE->theme->get_renderer('workshopallocation_manual', $PAGE);
-        echo $uioutput->display_allocations($this->workshop, $peer, $hlauthorid, $hlreviewerid, $msg);
+        return $uioutput->display_allocations($this->workshop, $peers, $hlauthorid, $hlreviewerid, $msg);
     }
 
 }
-
index fe11840259b03126be8e41cee03c6a395785b6fb..a4e10108e5716d3aaf59d8bdf74e7799b5610450 100644 (file)
@@ -31,22 +31,18 @@ require_once(dirname(dirname(__FILE__)) . '/lib.php');                  // inter
 require_once(dirname(dirname(dirname(__FILE__))) . '/locallib.php');    // workshop internal API
 require_once(dirname(__FILE__) . '/settings_form.php');                 // settings form
 
-/**
- * Constants used to pass status messages between init() and ui()
- */
-define('WORKSHOP_ALLOCATION_RANDOM_MSG_SUCCESS',    1);
-
-/**
- * Constants used in allocation settings form
- */
-define('WORKSHOP_USERTYPE_AUTHOR',                  1);
-define('WORKSHOP_USERTYPE_REVIEWER',                2);
-
 /**
  * Allocates the submissions randomly
  */
 class workshop_random_allocator implements workshop_allocator {
 
+    /** constants used to pass status messages between init() and ui() */
+    const MSG_SUCCESS       = 1;
+
+    /** constants used in allocation settings form */
+    const USERTYPE_AUTHOR   = 1;
+    const USERTYPE_REVIEWER = 2;
+
     /** workshop instance */
     protected $workshop;
 
@@ -157,21 +153,30 @@ class workshop_random_allocator implements workshop_allocator {
     }
 
     /**
-     * Prints user interface
+     * Returns the HTML code to print the user interface
      */
-    public function ui(moodle_mod_workshop_renderer $wsoutput) {
-        global $OUTPUT;
+    public function ui() {
+        global $OUTPUT, $PAGE;
 
         $m = optional_param('m', null, PARAM_INT);  // status message code
         $msg = new stdClass();
-        if ($m == WORKSHOP_ALLOCATION_RANDOM_MSG_SUCCESS) {
+        if ($m == self::MSG_SUCCESS) {
             $msg = (object)array('text' => get_string('randomallocationdone', 'workshopallocation_random'), 'sty' => 'ok');
         }
 
-        echo $OUTPUT->container_start('random-allocator');
-        echo $wsoutput->status_message($msg);
+        $out = '';
+        $out .= $OUTPUT->container_start('random-allocator');
+        $wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE);
+        $out .= $wsoutput->status_message($msg);
+        // the nasty hack follows to bypass the sad fact that moodle quickforms do not allow to actually
+        // return the HTML content, just to display it
+        ob_start();
         $this->mform->display();
-        echo $OUTPUT->container_end();
+        $out .= ob_get_contents();
+        ob_end_clean();
+        $out .= $OUTPUT->container_end();
+
+        return $out;
     }
 
     /**
@@ -232,7 +237,7 @@ class workshop_random_allocator implements workshop_allocator {
             }
             $submission = $submissions[$authorid];
             $status = $this->workshop->add_allocation($submission, $reviewerid, true);
-            if (WORKSHOP_ALLOCATION_EXISTS == $status) {
+            if (workshop::ALLOCATION_EXISTS == $status) {
                 debugging('newallocations array contains existing allocation, this should not happen');
             }
         }
@@ -342,14 +347,14 @@ class workshop_random_allocator implements workshop_allocator {
             // nothing to be done
             return array();
         }
-        if (WORKSHOP_USERTYPE_AUTHOR == $numper) {
+        if (self::USERTYPE_AUTHOR == $numper) {
             // circles are authors, squares are reviewers
             $o[] = 'info::Trying to allocate ' . $numofreviews . ' review(s) per author'; // todo translate
             $allcircles = $authors;
             $allsquares = $reviewers;
             // get current workload
             list($circlelinks, $squarelinks) = $this->convert_assessments_to_links($assessments);
-        } elseif (WORKSHOP_USERTYPE_REVIEWER == $numper) {
+        } elseif (self::USERTYPE_REVIEWER == $numper) {
             // circles are reviewers, squares are authors
             $o[] = 'info::trying to allocate ' . $numofreviews . ' review(s) per reviewer'; // todo translate
             $allcircles = $reviewers;
@@ -458,7 +463,7 @@ class workshop_random_allocator implements workshop_allocator {
             } // end of processing circles in the group
         } // end of processing circle groups
         $returned = array();
-        if (WORKSHOP_USERTYPE_AUTHOR == $numper) {
+        if (self::USERTYPE_AUTHOR == $numper) {
             // circles are authors, squares are reviewers
             foreach ($circlelinks as $circleid => $squares) {
                 foreach ($squares as $squareid) {
@@ -466,7 +471,7 @@ class workshop_random_allocator implements workshop_allocator {
                 }
             }
         }
-        if (WORKSHOP_USERTYPE_REVIEWER == $numper) {
+        if (self::USERTYPE_REVIEWER == $numper) {
             // circles are reviewers, squares are authors
             foreach ($circlelinks as $circleid => $squares) {
                 foreach ($squares as $squareid) {
index 178a009314fb6211c3d2891ce2a59da6a46d3751..c2585f16a2e7472931e11b9e1e80776a6c2af7a7 100644 (file)
@@ -60,14 +60,16 @@ class workshop_random_allocator_form extends moodleform {
         }
         $mform->addElement('static', 'groupmode', get_string('groupmode', 'group'), $grouplabel);
 
-        $options_numofreviewes = array(0=>0,1=>1, 2=>2, 3=>3, 4=>4);
-        $options_numper = array(WORKSHOP_USERTYPE_AUTHOR    => get_string('numperauthor', 'workshopallocation_random'),
-                                WORKSHOP_USERTYPE_REVIEWER  => get_string('numperreviewer', 'workshopallocation_random'));
+        $options_numofreviewes = array(0=>0,1=>1, 2=>2, 3=>3, 4=>4); // todo
+        $options_numper = array(
+            workshop_random_allocator::USERTYPE_AUTHOR      => get_string('numperauthor', 'workshopallocation_random'),
+            workshop_random_allocator::USERTYPE_REVIEWER    => get_string('numperreviewer', 'workshopallocation_random')
+        );
         $grpnumofreviews = array();
         $grpnumofreviews[] = $mform->createElement('select', 'numofreviews', '', $options_numofreviewes);
         $mform->setDefault('numofreviews', 4);
         $grpnumofreviews[] = $mform->createElement('select', 'numper', '', $options_numper);
-        $mform->setDefault('numper', WORKSHOP_USERTYPE_AUTHOR);
+        $mform->setDefault('numper', workshop_random_allocator::USERTYPE_AUTHOR);
         $mform->addGroup($grpnumofreviews, 'grpnumofreviews', get_string('numofreviews', 'workshop'), array(' '), false);
 
         $mform->addElement('advcheckbox', 'removecurrent', get_string('removecurrentallocations', 'workshopallocation_random'));
index d2da52f6e16ce009e5cdf93202f07b4a71f43ec2..246f20547e81ef8c6c68ca650d5e56b94b39798f 100644 (file)
@@ -58,19 +58,22 @@ if ('preview' == $mode) {
     $PAGE->set_url($workshop->previewform_url());
     $PAGE->set_title($workshop->name);
     $PAGE->set_heading($course->fullname);
-    $PAGE->navbar->add(get_string('editingassessmentform', 'workshop'), null, null, navigation_node::TYPE_CUSTOM,
-                        $workshop->editform_url());
+    $PAGE->navbar->add(get_string('editingassessmentform', 'workshop'), $workshop->editform_url(), navigation_node::TYPE_CUSTOM);
     $PAGE->navbar->add(get_string('previewassessmentform', 'workshop'));
+    $currenttab = 'editform';
 
 } elseif ('assessment' == $mode) {
-    if (!has_any_capability(array('mod/workshop:peerassess', 'mod/workshop:assessallsubmissions'), $PAGE->context)) {
+    // we do not require 'mod/workshop:peerassess' here, we just check that the assessment record
+    // has been prepared for the current user. So even a user without the peerassess capability
+    // (like a 'teacher', for example) can become a reviewer
+    if ($USER->id !== $assessment->userid) {
         print_error('nopermissions', '', $workshop->view_url());
     }
-    // todo do a check that the user is allowed to assess this submission
     $PAGE->set_url($workshop->assess_url($assessment->id));
     $PAGE->set_title($workshop->name);
     $PAGE->set_heading($course->fullname);
     $PAGE->navbar->add(get_string('assessingsubmission', 'workshop'));
+    $currenttab = 'assessment';
 }
 
 // load the grading strategy logic
@@ -90,6 +93,7 @@ if ($mform->is_cancelled()) {
     $rawgrade = $strategy->save_assessment($assessment, $data);
     if (!is_null($rawgrade) and isset($data->saveandclose)) {
         echo $OUTPUT->header();
+        include(dirname(__FILE__) . '/tabs.php');
         echo $OUTPUT->heading(get_string('assessmentresult', 'workshop'), 2);
         echo $OUTPUT->box('Given grade: ' . sprintf("%01.2f", $rawgrade * 100) . ' %'); // todo more detailed info using own renderer
         echo $OUTPUT->continue_button($workshop->view_url());
@@ -105,6 +109,7 @@ if ($mform->is_cancelled()) {
 // Output starts here
 
 echo $OUTPUT->header();
+include(dirname(__FILE__) . '/tabs.php');
 echo $OUTPUT->heading(get_string('assessmentform', 'workshop'), 2);
 
 if ('assessment' === $mode) {
index 6e613cd2f8c393945b3b96a4280aabbec4006360..63db56c06664c485484878386b494df5ac3b188e 100644 (file)
@@ -68,6 +68,8 @@ if ($mform->is_cancelled()) {
 // Output starts here
 
 echo $OUTPUT->header();
+$currenttab = 'editform';
+include(dirname(__FILE__) . '/tabs.php');
 echo $OUTPUT->heading(get_string('pluginname', 'workshopgrading_' . $workshop->strategy));
 
 $mform->display();
index 027db51ba751341bb1855901b943ac0a8d1f3158..6b750e6df25928ba36b412264e6fd711cc9a4095 100644 (file)
@@ -226,6 +226,18 @@ class workshop_accumulative_strategy implements workshop_strategy {
         return $this->update_peer_grade($assessment);
     }
 
+    /**
+     * Has the assessment form been defined and is ready to be used by the reviewers?
+     *
+     * @return boolean
+     */
+    public function form_ready() {
+        if (count($this->dimensions) > 0) {
+            return true;
+        }
+        return false;
+    }
+
 /// Internal methods
 
     /**
index 0beafa65d0d0d4f5d67a1b8824140473e22b3696..1efde373350120fff367b563a09da8f4ccbf8c72 100644 (file)
@@ -71,4 +71,11 @@ interface workshop_strategy {
      * @return float|null          Raw grade (0 to 1) for submission as suggested by the peer or null if impossible to count
      */
     public function save_assessment(stdClass $assessment, stdClass $data);
+
+    /**
+     * Has the assessment form been defined and is ready to be used by the reviewers?
+     *
+     * @return boolean
+     */
+    public function form_ready();
 }
index e92b2c48f84feb531d4991f7a57d2dd7bffb6a16..77e9021610ec32bb62826363645ac2f8c24b4a8b 100644 (file)
@@ -263,6 +263,18 @@ class workshop_noerrors_strategy implements workshop_strategy {
         return $this->update_peer_grade($assessment);
     }
 
+    /**
+     * Has the assessment form been defined and is ready to be used by the reviewers?
+     *
+     * @return boolean
+     */
+    public function form_ready() {
+        if (count($this->dimensions) > 0) {
+            return true;
+        }
+        return false;
+    }
+
 /// Internal methods
 
     /**
index 45f93c29da4d3bac5317ae625e3a80a00ed4ae4e..c439afec08ccb0c1a4cfe7c1a3d26095dc4b81c6 100644 (file)
 defined('MOODLE_INTERNAL') || die();
 
 $string[''] = '';
+$string['phaseclosed'] = 'Closed';
+$string['phaseevaluation'] = 'Grading evaluation phase';
+$string['phaseassessment'] = 'Assessment phase';
+$string['phasesubmission'] = 'Submission phase';
+$string['phasesetup'] = 'Setup';
+$string['taskassessself'] = 'Assess yourself';
+$string['taskassesspeers'] = 'Assess peers';
+$string['taskassesspeersinfo'] = 'total: $a->total<br />pending: $a->todo';
+$string['tasksubmit'] = 'Submit your work';
+$string['taskeditform'] = 'Define the assessment form';
 $string['accesscontrol'] = 'Access control';
 $string['agreeassessments'] = 'Assessments must be agreed';
 $string['agreeassessmentsdesc'] = 'Authors may comment assessments of their work and agree/disagree with it';
@@ -62,6 +72,7 @@ $string['confignexassessments'] = 'Default number of examples to be reviewed by
 $string['confignsassessments'] = 'Default number of allocated submissions to be reviewed by a user in the assessment phase';
 $string['configstrategy'] = 'Default grading strategy for workshops';
 $string['editassessmentform'] = 'Edit assessment form';
+$string['editassessmentformstrategy'] = 'Edit assessment form ($a)';
 $string['editingassessmentform'] = 'Editing assessment form';
 $string['editingsubmission'] = 'Editing submission';
 $string['editsubmission'] = 'Edit submission';
index 57443bc46b675fde566741f01dcab6e03e8a97df..016f254a090a317c074e40f923e95cce7d8c375c 100644 (file)
@@ -47,6 +47,29 @@ define('WORKSHOP_COMPARISON_NORMAL',    2);     /* f = 2.50 */
 define('WORKSHOP_COMPARISON_HIGH',      3);     /* f = 3.00 */
 define('WORKSHOP_COMPARISON_VERYHIGH',  4);     /* f = 5.00 */
 
+/**
+ * Returns the information if the module supports a feature
+ *
+ * @see plugin_supports() in lib/moodlelib.php
+ * @param string $feature FEATURE_xx constant for requested feature
+ * @return mixed true if the feature is supported, null if unknown
+ */
+function workshop_supports($feature) {
+    switch($feature) {
+        case FEATURE_GRADE_HAS_GRADE:   return true;
+        case FEATURE_GROUPS:            return true;
+        case FEATURE_GROUPINGS:         return true;
+        case FEATURE_GROUPMEMBERSONLY:  return true;
+        case FEATURE_MOD_INTRO:         return true;
+        case FEATURE_MOD_SUBPLUGINS:    return array(
+                                                'workshopgrading'    => 'mod/workshop/grading',
+                                                'workshopallocation' => 'mod/workshop/allocation'
+                                                );
+        default:                        return null;
+    }
+}
+
+
 /**
  * Saves a new instance of the workshop into the database
  *
@@ -223,29 +246,6 @@ function workshop_install() {
     return true;
 }
 
-/**
- * Returns the information if the module supports a feature
- *
- * @see plugin_supports() in lib/moodlelib.php
- * @todo review and add features
- * @param string $feature FEATURE_xx constant for requested feature
- * @return mixed true if the feature is supported, null if unknown
- */
-function workshop_supports($feature) {
-    switch($feature) {
-        case FEATURE_GRADE_HAS_GRADE:   return true;
-        case FEATURE_GROUPS:            return true;
-        case FEATURE_GROUPINGS:         return true;
-        case FEATURE_GROUPMEMBERSONLY:  return true;
-        case FEATURE_MOD_INTRO:         return true;
-        case FEATURE_MOD_SUBPLUGINS:    return array(
-                                                'workshopgrading'    => 'mod/workshop/grading',
-                                                'workshopallocation' => 'mod/workshop/allocation'
-                                                );
-        default:                        return null;
-    }
-}
-
 /**
  * Returns all other caps used in the module
  *
@@ -436,6 +436,8 @@ function workshop_get_file_info($browser, $areas, $course, $cm, $context, $filea
 /**
  * Extends the global navigation tree by adding workshop nodes if there is a relevant content
  *
+ * This can be called by an AJAX request so do not rely on $PAGE as it might not be set up properly.
+ *
  * @param navigation_node $navref An object representing the navigation tree node of the workshop module instance
  * @param stdClass $course
  * @param stdClass $module
@@ -446,14 +448,16 @@ function workshop_extend_navigation(navigation_node $navref, stdClass $course, s
 
     if (has_capability('mod/workshop:submit', $cm->context)) {
         $url = new moodle_url($CFG->wwwroot.'/mod/workshop/submission.php', array('cmid' => $cm->id));
-        $mysubmissionkey = $navref->add(get_string('mysubmission', 'workshop'), null, null, navigation_node::TYPE_CUSTOM, $url);
+        $mysubmissionkey = $navref->add(get_string('mysubmission', 'workshop'), $url);
+        $navref->get($mysubmissionkey)->mainnavonly = true;
     }
 }
 
 /**
  * Extends the settings navigation with the Workshop settings
 
- * This function is called when the context for the page is a workshop module.
+ * This function is called when the context for the page is a workshop module. This is not called by AJAX
+ * so it is safe to rely on the $PAGE.
  *
  * @param settings_navigation $settingsnav {@link settings_navigation}
  * @param stdClass $module
@@ -467,13 +471,13 @@ function workshop_extend_settings_navigation(settings_navigation $settingsnav, s
     $workshopnode->forceopen = true;
     //$workshopobject = $DB->get_record("workshop", array("id" => $PAGE->cm->instance));
 
-    if (has_capability('mod/workshop:editdimensions', $PAGE->context)) {
+    if (has_capability('mod/workshop:editdimensions', $PAGE->cm->context)) {
         $url = new moodle_url($CFG->wwwroot . '/mod/workshop/editform.php', array('cmid' => $PAGE->cm->id));
-        $workshopnode->add(get_string('editassessmentform', 'workshop'), null, null, settings_navigation::TYPE_SETTING, $url);
+        $workshopnode->add(get_string('editassessmentform', 'workshop'), $url, settings_navigation::TYPE_SETTING);
     }
     if (has_capability('mod/workshop:allocate', $PAGE->context)) {
         $url = new moodle_url($CFG->wwwroot . '/mod/workshop/allocation.php', array('cmid' => $PAGE->cm->id));
-        $workshopnode->add(get_string('allocate', 'workshop'), null, null, settings_navigation::TYPE_SETTING, $url);
+        $workshopnode->add(get_string('allocate', 'workshop'), $url, settings_navigation::TYPE_SETTING);
     }
 }
 
index 6b861dcec455940763c1d126e9381b8ecc2988c2..d95295dea99261d4889ca9a0bbbfaa43757a640c 100644 (file)
@@ -32,16 +32,6 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once(dirname(__FILE__).'/lib.php');      // we extend this library here
 
-define('WORKSHOP_ALLOCATION_EXISTS',    -1);    // return status of {@link add_allocation}
-define('WORKSHOP_ALLOCATION_ERROR',     -2);    // can be passed to a workshop renderer method
-
-/** workshop phases */
-define('WORKSHOP_PHASE_SETUP',          10);    // The moderator is setting up the workshop
-define('WORKSHOP_PHASE_SUBMISSION',     20);    // Participants work on their submissions
-define('WORKSHOP_PHASE_ASSESSMENT',     30);    // 
-define('WORKSHOP_PHASE_EVALUATION',     40);
-define('WORKSHOP_PHASE_CLOSED',         50);
-
 /**
  * Full-featured workshop API
  *
@@ -51,13 +41,30 @@ define('WORKSHOP_PHASE_CLOSED',         50);
  */
 class workshop {
 
+    /** return statuses of {@link add_allocation} to be passed to a workshop renderer method */
+    const ALLOCATION_EXISTS = -1;
+    const ALLOCATION_ERROR  = -2;
+
+    /** the internal code of the workshop phases as are stored in the database */
+    const PHASE_SETUP       = 10;
+    const PHASE_SUBMISSION  = 20;
+    const PHASE_ASSESSMENT  = 30;
+    const PHASE_EVALUATION  = 40;
+    const PHASE_CLOSED      = 50;
+
     /** @var stdClass course module record */
     public $cm = null;
 
     /** @var stdClass course record */
     public $course = null;
 
-    /** @var workshop_strategy grading strategy instance */
+    /** @var stdClass the workshop instance context */
+    public $context = null;
+
+    /**
+     * @var workshop_strategy grading strategy instance
+     * Do not use directly, get the instance using {@link workshop::grading_strategy_instance()}
+     */
     protected $strategyinstance = null;
 
     /** @var stdClass underlying database record */
@@ -77,6 +84,7 @@ class workshop {
         $this->dbrecord = $dbrecord;
         $this->cm       = $cm;
         $this->course   = $course;
+        $this->context  = get_context_instance(CONTEXT_MODULE, $this->cm->id);
     }
 
     /**
@@ -104,8 +112,7 @@ class workshop {
     public function get_peer_authors($musthavesubmission=true) {
         global $DB;
 
-        $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
-        $users = get_users_by_capability($context, 'mod/workshop:submit',
+        $users = get_users_by_capability($this->context, 'mod/workshop:submit',
                     'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
 
         if ($musthavesubmission) {
@@ -135,8 +142,7 @@ class workshop {
     public function get_peer_reviewers($musthavesubmission=false) {
         global $DB;
 
-        $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
-        $users = get_users_by_capability($context, 'mod/workshop:peerassess',
+        $users = get_users_by_capability($this->context, 'mod/workshop:peerassess',
                     'u.id, u.lastname, u.firstname', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
 
         if ($musthavesubmission) {
@@ -417,8 +423,7 @@ class workshop {
     public function get_allocations_recordset() {
         global $DB;
 
-        $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
-        $users = get_users_by_capability($context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
+        $users = get_users_by_capability($this->context, array('mod/workshop:submit', 'mod/workshop:peerassess'),
                     'u.id', 'u.lastname,u.firstname', '', '', '', '', false, false, true);
 
         list($usql, $params) = $DB->get_in_or_equal(array_keys($users), SQL_PARAMS_NAMED);
@@ -452,7 +457,7 @@ class workshop {
         global $DB;
 
         if ($DB->record_exists('workshop_assessments', array('submissionid' => $submission->id, 'userid' => $reviewerid))) {
-            return WORKSHOP_ALLOCATION_EXISTS;
+            return self::ALLOCATION_EXISTS;
         }
 
         $now = time();
@@ -496,12 +501,12 @@ class workshop {
             if (is_readable($strategylib)) {
                 require_once($strategylib);
             } else {
-                throw new moodle_exception('missingstrategy', 'workshop');
+                throw new coding_exception('the grading subplugin must contain library ' . $strategylib);
             }
             $classname = 'workshop_' . $this->strategy . '_strategy';
             $this->strategyinstance = new $classname($this);
             if (!in_array('workshop_strategy', class_implements($this->strategyinstance))) {
-                throw new moodle_exception('strategynotimplemented', 'workshop');
+                throw new coding_exception($classname . ' does not implement workshop_strategy interface');
             }
         }
         return $this->strategyinstance;
@@ -624,4 +629,124 @@ class workshop {
     public function strategy_name() {
         return get_string('pluginname', 'workshopgrading_' . $this->strategy);
     }
+
+    /**
+     * Prepare an individual workshop plan for the given user.
+     *
+     * @param mixed $userid 
+     * @return TODO
+     */
+    public function prepare_user_plan($userid) {
+        global $DB;
+
+        $phases = array();
+
+        // Prepare tasks for the setup phase
+        $phase = new stdClass();
+        $phase->title = get_string('phasesetup', 'workshop');
+        $phase->tasks = array();
+        if (has_capability('mod/workshop:editdimensions', $this->context, $userid)) {
+            $task = new stdClass();
+            $task->title = get_string('taskeditform', 'workshop');
+            $task->completed = $this->assessment_form_ready();
+            $phase->tasks['editform'] = $task;
+        }
+        $phases[self::PHASE_SETUP] = $phase;
+
+        // Prepare tasks for the submission phase
+        $phase = new stdClass();
+        $phase->title = get_string('phasesubmission', 'workshop');
+        $phase->tasks = array();
+        if (has_capability('mod/workshop:submit', $this->context, $userid)) {
+            $task = new stdClass();
+            $task->title = get_string('tasksubmit', 'workshop');
+            $task->completed = $DB->record_exists('workshop_submissions',
+                                        array('workshopid' => $this->id, 'example' => 0, 'userid' => $userid));
+            $phase->tasks['submit'] = $task;
+        }
+        $phases[self::PHASE_SUBMISSION] = $phase;
+
+        // Prepare tasks for the peer-assessment phase (includes eventual self-assessments)
+        $phase = new stdClass();
+        $phase->title = get_string('phaseassessment', 'workshop');
+        $phase->tasks = array();
+        $phase->isreviewer = has_capability('mod/workshop:peerassess', $this->context, $userid);
+        $phase->assessments = $this->get_assessments($userid); // todo make sure this does not contain assessment of examples
+        $numofpeers     = 0;    // number of allocated peer-assessments
+        $numofpeerstodo = 0;    // number of peer-assessments to do
+        $numofself      = 0;    // number of allocated self-assessments - should be 0 or 1
+        $numofselftodo  = 0;    // number of self-assessments to do - should be 0 or 1
+        foreach ($phase->assessments as $a) {
+            if ($a->authorid == $userid) {
+                $numofself++;
+                if (is_null($a->grade)) {
+                    $numofselftodo++;
+                }
+            } else {
+                $numofpeers++;
+                if (is_null($a->grade)) {
+                    $numofpeerstodo++;
+                }
+            }
+        }
+        unset($a);
+        if ($numofpeers) {
+            $task = new stdClass();
+            $task->completed = ($numofpeerstodo == 0);
+            $a = new stdClass();
+            $a->total = $numofpeers;
+            $a->todo  = $numofpeerstodo;
+            $task->title = get_string('taskassesspeers', 'workshop');
+            $task->info = get_string('taskassesspeersinfo', 'workshop', $a);
+            unset($a);
+            $phase->tasks['assesspeers'] = $task;
+        }
+        if ($numofself) {
+            $task = new stdClass();
+            $task->completed = ($numofselftodo == 0);
+            $task->title = get_string('taskassessself', 'workshop');
+            $phase->tasks['assessself'] = $task;
+        }
+        $phases[self::PHASE_ASSESSMENT] = $phase;
+
+        // Prepare tasks for the grading evaluation phase - todo
+        $phase = new stdClass();
+        $phase->title = get_string('phaseevaluation', 'workshop');
+        $phase->tasks = array();
+        $phases[self::PHASE_EVALUATION] = $phase;
+
+        // Prepare tasks for the "workshop closed" phase - todo
+        $phase = new stdClass();
+        $phase->title = get_string('phaseclosed', 'workshop');
+        $phase->tasks = array();
+        $phases[self::PHASE_CLOSED] = $phase;
+
+        // Polish data, set default values if not done explicitly
+        foreach ($phases as $phasecode => $phase) {
+            $phase->title       = isset($phase->title)      ? $phase->title     : '';
+            $phase->tasks       = isset($phase->tasks)      ? $phase->tasks     : array();
+            if ($phasecode == $this->phase) {
+                $phase->active = true;
+            } else {
+                $phase->active = false;
+            }
+
+            foreach ($phase->tasks as $taskcode => $task) {
+                $task->title        = isset($task->title)       ? $task->title      : '';
+                $task->info         = isset($task->info)        ? $task->info       : '';
+                $task->completed    = isset($task->completed)   ? $task->completed  : null;
+            }
+        }
+        return $phases;
+    }
+
+    /**
+     * Has the assessment form been defined?
+     *
+     * @return bool
+     */
+    public function assessment_form_ready() {
+        return $this->grading_strategy_instance()->form_ready();
+    }
+
 }
index 33616593c80cf530493599a84b9dfaa83c344430..16cbdb31e197cedf2603206105b064b701d9b62f 100644 (file)
@@ -87,7 +87,7 @@ class moodle_mod_workshop_renderer extends moodle_renderer_base {
      */
     public function allocation_init_result($result='') {
         $msg = new stdClass();
-        if ($result === WORKSHOP_ALLOCATION_ERROR) {
+        if ($result === workshop::ALLOCATION_ERROR) {
             $msg = (object)array('text' => get_string('allocationerror', 'workshop'), 'sty' => 'error');
         } else {
             $msg = (object)array('text' => get_string('allocationdone', 'workshop'), 'sty' => 'ok');
@@ -241,4 +241,68 @@ class moodle_mod_workshop_renderer extends moodle_renderer_base {
         return $this->output->output_tag('div', array('class' => 'attachments'), $outputimgs . $outputfiles);
     }
 
+    /**
+     * TODO: short description.
+     *
+     * @param array $plan
+     * @return TODO
+     */
+    public function user_plan(array $plan) {
+        if (empty($plan)) {
+            throw new coding_exception('you must provide the prepared user plan to be rendered');
+        }
+        $table = new html_table();
+        $table->set_classes('userplan');
+        $table->head = array();
+        $table->colclasses = array();
+        $row = new html_table_row();
+        $row->set_classes('phasetasks');
+        foreach ($plan as $phasecode => $phase) {
+            $table->head[] = $this->output->container($this->output->output_tag('span', array(), $phase->title));
+            $classes = 'phase' . $phasecode;
+            if ($phase->active) {
+                $classes .= ' active';
+            } else {
+                $classes .= ' nonactive';
+            }
+            $table->colclasses[] = $classes;
+            $cell = new html_table_cell();
+            $cell->text = $this->user_plan_tasks($phase->tasks);
+            $row->cells[] = $cell;
+        }
+        $table->data = array($row);
+
+        return $this->output->table($table);
+    }
+
+    /**
+     * TODO: short description.
+     *
+     * @param stdClass $tasks 
+     * @return TODO
+     */
+    protected function user_plan_tasks(array $tasks) {
+        $out = '';
+        foreach ($tasks as $taskcode => $task) {
+            $classes = '';
+            $icon = null;
+            if ($task->completed === true) {
+                $icon = new html_image();
+                $icon->src = $this->old_icon_url('i/tick_green_big.gif');
+                $icon->alt = '+';
+                $classes .= ' completed';
+            } elseif ($task->completed === false) {
+                $classes .= ' pending';
+            } else {
+                $classes .= ' statusunknown';
+            }
+            $title = $this->output->container($task->title, 'title');
+            $info = $this->output->container($task->info, 'info');
+            $out .= $this->output->output_tag('li', array('class' => $classes), $title . $info);
+        }
+        if ($out) {
+            $out = $this->output->output_tag('ul', array('class' => 'tasks'), $out);
+        }
+        return $out;
+    }
 }
index 3b0d543223631c6d4e2ab0762cb205ec4a446259..d5e63606dbe6cfab853f0fd8e2a1defbc68d2a72 100644 (file)
 .assessmentform .description {
     margin: 0px 1em;
 }
+
+/**
+ * User plan
+ */
+.userplan {
+    width: 70%;
+    margin: 1em auto 1em auto;
+}
+
+.userplan th {
+    vertical-align: bottom;
+    white-space: normal;
+    color: #999;
+    border-bottom: 1px solid #ddd;
+    padding: 3px;
+}
+
+.userplan th.active {
+    vertical-align: top;
+    color: black;
+    font-size: 110%;
+    border: 1px solid #ddd;
+    border-bottom: none;
+    background-color: #e7f1c3;
+}
+
+.userplan td {
+    width: 20%;
+    vertical-align: top;
+    border-right: 1px solid #ddd;
+    background-color: #f5f5f5;
+    color: #999;
+}
+
+.userplan td.lastcol {
+    border-right: none;
+}
+
+.userplan td.active {
+    color: black;
+    border-left: 1px solid #ddd;
+    border-right: 1px solid #ddd;
+    background-color: #e7f1c3;
+}
+
+.userplan tr.phasetasks li {
+    background-image: url(../../pix/i/completion-auto-n.gif);
+    background-position: top left;
+    background-repeat: no-repeat;
+}
+
+.userplan tr.phasetasks .completed {
+    background-image: url(../../pix/i/completion-auto-y.gif);
+}
+
+.userplan tr.phasetasks .tasks {
+    list-style:none;
+    margin: 3px;
+    padding: 0px;
+}
+
+.userplan tr.phasetasks .title {
+    padding: 0px 10px 0px 20px;
+}
+
+.userplan tr.phasetasks .info {
+    padding: 0px 10px 0px 25px;
+    font-size: 80%;
+}
index ed84de8a6eebbe52472b496d2362388a7dfa4164..60f5e11931b59252878ecd149d1f3fe3016eda9d 100644 (file)
@@ -102,11 +102,11 @@ if ($mform->is_cancelled()) {
 $PAGE->set_url('mod/workshop/submission.php', array('cmid' => $cm->id));
 $PAGE->set_title($workshop->name);
 $PAGE->set_heading($course->fullname);
-// the default navbar node for non-editing mode is set in {@link workshop_extend_navigation()}
 if ($edit) {
-    $PAGE->navbar->add(get_string('mysubmission', 'workshop'), null, null, navigation_node::TYPE_CUSTOM,
-                        $workshop->submission_url());
+    $PAGE->navbar->add(get_string('mysubmission', 'workshop'), $workshop->submission_url(), navigation_node::TYPE_CUSTOM);
     $PAGE->navbar->add(get_string('editingsubmission', 'workshop'));
+} else {
+    $PAGE->navbar->add(get_string('mysubmission', 'workshop'));
 }
 
 // Output starts here
diff --git a/mod/workshop/tabs.php b/mod/workshop/tabs.php
new file mode 100644 (file)
index 0000000..4d633b0
--- /dev/null
@@ -0,0 +1,51 @@
+<?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/>.
+
+/**
+ * Defines and prints the workshop navigation tabs
+ *
+ * Can be included from within a workshop script only
+ *
+ * @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();
+
+if (empty($workshop) or !is_a($workshop, 'workshop')) {
+    print_error('cannotcallscript');
+}
+if (!isset($currenttab)) {
+    $currenttab = 'info';
+}
+
+$tabs       = array();
+$row        = array();
+$inactive   = array();
+$activated  = array();
+
+// top level tabs
+if (has_capability('mod/workshop:view', $PAGE->context)) {
+    $row[] = new tabobject('info', $workshop->view_url()->out(), get_string('info', 'workshop'));
+}
+if (has_capability('mod/workshop:editdimensions', $PAGE->context)) {
+    $row[] = new tabobject('editform', $workshop->editform_url()->out(), get_string('editassessmentform', 'workshop'));
+}
+$tabs[] = $row;
+
+print_tabs($tabs, $currenttab, $inactive, $activated);
index 090b1d67d2bbc3eacea84900edd9c13dff6dc2a3..4f0954f81b0a26dc95034065480931517bb717c2 100644 (file)
@@ -44,14 +44,10 @@ if ($id) {
 }
 
 require_login($course, true, $cm);
-$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(...))) {
-//      unable to view this page
-//
+require_capability('mod/workshop:view', $PAGE->context);
+add_to_log($course->id, 'workshop', 'view', 'view.php?id='.$cm->id, $workshop->id);
 
-// todo logging add_to_log($course->id, "workshop", "view", "view.php?id=$cm->id", "$workshop->id");
+$workshop = new workshop($workshop, $cm, $course);
 
 if (!is_null($edit) && $PAGE->user_allowed_editing()) {
     $USER->editing = $edit;
@@ -60,6 +56,8 @@ if (!is_null($edit) && $PAGE->user_allowed_editing()) {
 $PAGE->set_url($workshop->view_url());
 $PAGE->set_title($workshop->name);
 $PAGE->set_heading($course->fullname);
+
+// todo 
 $buttons = array();
 if ($PAGE->user_allowed_editing()) {
     $editblocks                 = new html_form();
@@ -71,9 +69,32 @@ if ($PAGE->user_allowed_editing()) {
 $buttons[] = $OUTPUT->update_module_button($cm->id, 'workshop');
 $PAGE->set_button(implode('', $buttons));
 
+$wsoutput = $PAGE->theme->get_renderer('mod_workshop', $PAGE);
+
 /// Output starts here
 
 echo $OUTPUT->header();
+include(dirname(__FILE__) . '/tabs.php');
+
+$workshop->phase = 10;    // todo xxx devel hack
+echo $wsoutput->user_plan($workshop->prepare_user_plan($USER->id));
+
+
+switch ($workshop->phase) {
+case workshop::PHASE_SETUP:
+    // print workshop name and description
+    echo $OUTPUT->heading(format_string($workshop->name));
+    if (trim(strip_tags($workshop->intro))) {
+        echo $OUTPUT->box(format_module_intro('workshop', $workshop, $workshop->cm->id), 'generalbox', 'intro');
+    }
+    break;
+case workshop::PHASE_SUBMISSION:
+case workshop::PHASE_ASSESSMENT:
+case workshop::PHASE_EVALUATION:
+case workshop::PHASE_CLOSED:
+default:
+}
+
 
 /// Print the main part of the page - todo these are just links to help during development
 echo $OUTPUT->box_start();