Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * View a single (usually the own) submission, submit own work.
  19   *
  20   * @package    mod_workshop
  21   * @copyright  2009 David Mudrak <david.mudrak@gmail.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  require(__DIR__.'/../../config.php');
  26  require_once (__DIR__.'/locallib.php');
  27  
  28  $cmid = required_param('cmid', PARAM_INT); // Course module id.
  29  $id = optional_param('id', 0, PARAM_INT); // Submission id.
  30  $edit = optional_param('edit', false, PARAM_BOOL); // Open the page for editing?
  31  $assess = optional_param('assess', false, PARAM_BOOL); // Instant assessment required.
  32  $delete = optional_param('delete', false, PARAM_BOOL); // Submission removal requested.
  33  $confirm = optional_param('confirm', false, PARAM_BOOL); // Submission removal request confirmed.
  34  
  35  $cm = get_coursemodule_from_id('workshop', $cmid, 0, false, MUST_EXIST);
  36  $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
  37  
  38  require_login($course, false, $cm);
  39  if (isguestuser()) {
  40      throw new \moodle_exception('guestsarenotallowed');
  41  }
  42  
  43  $workshoprecord = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST);
  44  $workshop = new workshop($workshoprecord, $cm, $course);
  45  
  46  $PAGE->set_url($workshop->submission_url(), array('cmid' => $cmid, 'id' => $id));
  47  
  48  $PAGE->set_secondary_active_tab("modulepage");
  49  
  50  if ($edit) {
  51      $PAGE->url->param('edit', $edit);
  52  }
  53  
  54  if ($id) { // submission is specified
  55      $submission = $workshop->get_submission_by_id($id);
  56  
  57  } else { // no submission specified
  58      if (!$submission = $workshop->get_submission_by_author($USER->id)) {
  59          $submission = new stdclass();
  60          $submission->id = null;
  61          $submission->authorid = $USER->id;
  62          $submission->example = 0;
  63          $submission->grade = null;
  64          $submission->gradeover = null;
  65          $submission->published = null;
  66          $submission->feedbackauthor = null;
  67          $submission->feedbackauthorformat = editors_get_preferred_format();
  68      }
  69  }
  70  
  71  $ownsubmission  = $submission->authorid == $USER->id;
  72  $canviewall     = has_capability('mod/workshop:viewallsubmissions', $workshop->context);
  73  $cansubmit      = has_capability('mod/workshop:submit', $workshop->context);
  74  $canallocate    = has_capability('mod/workshop:allocate', $workshop->context);
  75  $canpublish     = has_capability('mod/workshop:publishsubmissions', $workshop->context);
  76  $canoverride    = (($workshop->phase == workshop::PHASE_EVALUATION) and has_capability('mod/workshop:overridegrades', $workshop->context));
  77  $candeleteall   = has_capability('mod/workshop:deletesubmissions', $workshop->context);
  78  $userassessment = $workshop->get_assessment_of_submission_by_user($submission->id, $USER->id);
  79  $isreviewer     = !empty($userassessment);
  80  $editable       = ($cansubmit and $ownsubmission);
  81  $deletable      = $candeleteall;
  82  $ispublished    = ($workshop->phase == workshop::PHASE_CLOSED
  83                      and $submission->published == 1
  84                      and has_capability('mod/workshop:viewpublishedsubmissions', $workshop->context));
  85  
  86  if (empty($submission->id) and !$workshop->creating_submission_allowed($USER->id)) {
  87      $editable = false;
  88  }
  89  if ($submission->id and !$workshop->modifying_submission_allowed($USER->id)) {
  90      $editable = false;
  91  }
  92  
  93  $canviewall = $canviewall && $workshop->check_group_membership($submission->authorid);
  94  
  95  $editable = ($editable && $workshop->check_examples_assessed_before_submission($USER->id));
  96  $edit = ($editable and $edit);
  97  
  98  if (!$candeleteall and $ownsubmission and $editable) {
  99      // Only allow the student to delete their own submission if it's still editable and hasn't been assessed.
 100      if (count($workshop->get_assessments_of_submission($submission->id)) > 0) {
 101          $deletable = false;
 102      } else {
 103          $deletable = true;
 104      }
 105  }
 106  
 107  if ($submission->id and $delete and $confirm and $deletable) {
 108      require_sesskey();
 109      $workshop->delete_submission($submission);
 110  
 111      redirect($workshop->view_url());
 112  }
 113  
 114  $seenaspublished = false; // is the submission seen as a published submission?
 115  
 116  if ($submission->id and ($ownsubmission or $canviewall or $isreviewer)) {
 117      // ok you can go
 118  } elseif ($submission->id and $ispublished) {
 119      // ok you can go
 120      $seenaspublished = true;
 121  } elseif (is_null($submission->id) and $cansubmit) {
 122      // ok you can go
 123  } else {
 124      throw new \moodle_exception('nopermissions', 'error', $workshop->view_url(), 'view or create submission');
 125  }
 126  
 127  if ($submission->id) {
 128      // Trigger submission viewed event.
 129      $workshop->set_submission_viewed($submission);
 130  }
 131  
 132  if ($assess and $submission->id and !$isreviewer and $canallocate and $workshop->assessing_allowed($USER->id)) {
 133      require_sesskey();
 134      $assessmentid = $workshop->add_allocation($submission, $USER->id);
 135      redirect($workshop->assess_url($assessmentid));
 136  }
 137  
 138  if ($edit) {
 139      require_once (__DIR__.'/submission_form.php');
 140  
 141      $submission = file_prepare_standard_editor($submission, 'content', $workshop->submission_content_options(),
 142          $workshop->context, 'mod_workshop', 'submission_content', $submission->id);
 143  
 144      $submission = file_prepare_standard_filemanager($submission, 'attachment', $workshop->submission_attachment_options(),
 145          $workshop->context, 'mod_workshop', 'submission_attachment', $submission->id);
 146  
 147      $mform = new workshop_submission_form($PAGE->url, array('current' => $submission, 'workshop' => $workshop,
 148          'contentopts' => $workshop->submission_content_options(), 'attachmentopts' => $workshop->submission_attachment_options()));
 149  
 150      if ($mform->is_cancelled()) {
 151          redirect($workshop->view_url());
 152  
 153      } elseif ($cansubmit and $formdata = $mform->get_data()) {
 154  
 155          $formdata->id = $submission->id;
 156          // Creates or updates submission.
 157          $submission->id = $workshop->edit_submission($formdata);
 158  
 159          redirect($workshop->submission_url($submission->id));
 160      }
 161  }
 162  
 163  // load the form to override grade and/or publish the submission and process the submitted data eventually
 164  if (!$edit and ($canoverride or $canpublish)) {
 165      $options = array(
 166          'editable' => true,
 167          'editablepublished' => $canpublish,
 168          'overridablegrade' => $canoverride);
 169      $feedbackform = $workshop->get_feedbackauthor_form($PAGE->url, $submission, $options);
 170      if ($data = $feedbackform->get_data()) {
 171          $workshop->evaluate_submission($submission, $data, $canpublish, $canoverride);
 172          redirect($workshop->view_url());
 173      }
 174  }
 175  
 176  $PAGE->set_title($workshop->name);
 177  $PAGE->set_heading($course->fullname);
 178  $PAGE->activityheader->set_attrs([
 179      'hidecompletion' => true,
 180      'description' => ''
 181  ]);
 182  if ($edit) {
 183      $PAGE->navbar->add(get_string('mysubmission', 'workshop'), $workshop->submission_url(), navigation_node::TYPE_CUSTOM);
 184      $PAGE->navbar->add(get_string('editingsubmission', 'workshop'));
 185  } elseif ($ownsubmission) {
 186      $PAGE->navbar->add(get_string('mysubmission', 'workshop'));
 187  } else {
 188      $PAGE->navbar->add(get_string('submission', 'workshop'));
 189  }
 190  
 191  // Output starts here
 192  $output = $PAGE->get_renderer('mod_workshop');
 193  echo $output->header();
 194  echo $output->heading(get_string('mysubmission', 'workshop'), 3);
 195  
 196  // show instructions for submitting as thay may contain some list of questions and we need to know them
 197  // while reading the submitted answer
 198  if (trim($workshop->instructauthors)) {
 199      $instructions = file_rewrite_pluginfile_urls($workshop->instructauthors, 'pluginfile.php', $PAGE->context->id,
 200          'mod_workshop', 'instructauthors', null, workshop::instruction_editors_options($PAGE->context));
 201      print_collapsible_region_start('', 'workshop-viewlet-instructauthors', get_string('instructauthors', 'workshop'),
 202              'workshop-viewlet-instructauthors-collapsed');
 203      echo $output->box(format_text($instructions, $workshop->instructauthorsformat, array('overflowdiv'=>true)), array('generalbox', 'instructions'));
 204      print_collapsible_region_end();
 205  }
 206  
 207  // if in edit mode, display the form to edit the submission
 208  
 209  if ($edit) {
 210      if (!empty($CFG->enableplagiarism)) {
 211          require_once($CFG->libdir.'/plagiarismlib.php');
 212          echo plagiarism_print_disclosure($cm->id);
 213      }
 214      $mform->display();
 215      echo $output->footer();
 216      die();
 217  }
 218  
 219  // Confirm deletion (if requested).
 220  if ($deletable and $delete) {
 221      $prompt = get_string('submissiondeleteconfirm', 'workshop');
 222      if ($candeleteall) {
 223          $count = count($workshop->get_assessments_of_submission($submission->id));
 224          if ($count > 0) {
 225              $prompt = get_string('submissiondeleteconfirmassess', 'workshop', ['count' => $count]);
 226          }
 227      }
 228      echo $output->confirm($prompt, new moodle_url($PAGE->url, ['delete' => 1, 'confirm' => 1]), $workshop->view_url());
 229  }
 230  
 231  // else display the submission
 232  
 233  if ($submission->id) {
 234      if ($seenaspublished) {
 235          $showauthor = has_capability('mod/workshop:viewauthorpublished', $workshop->context);
 236      } else {
 237          $showauthor = has_capability('mod/workshop:viewauthornames', $workshop->context);
 238      }
 239      echo $output->render($workshop->prepare_submission($submission, $showauthor));
 240  } else {
 241      echo $output->box(get_string('noyoursubmission', 'workshop'));
 242  }
 243  
 244  // If not at removal confirmation screen, some action buttons can be displayed.
 245  if (!$delete) {
 246      // Display create/edit button.
 247      if ($editable) {
 248          if ($submission->id) {
 249              $btnurl = new moodle_url($PAGE->url, array('edit' => 'on', 'id' => $submission->id));
 250              $btntxt = get_string('editsubmission', 'workshop');
 251          } else {
 252              $btnurl = new moodle_url($PAGE->url, array('edit' => 'on'));
 253              $btntxt = get_string('createsubmission', 'workshop');
 254          }
 255          echo $output->box($output->single_button($btnurl, $btntxt, 'get'), 'mr-1 inline');
 256      }
 257  
 258      // Display delete button.
 259      if ($submission->id and $deletable) {
 260          $url = new moodle_url($PAGE->url, array('delete' => 1));
 261          echo $output->box($output->single_button($url, get_string('deletesubmission', 'workshop'), 'get'), 'mr-1 inline');
 262      }
 263  
 264      // Display assess button.
 265      if ($submission->id and !$edit and !$isreviewer and $canallocate and $workshop->assessing_allowed($USER->id)) {
 266          $url = new moodle_url($PAGE->url, array('assess' => 1));
 267          echo $output->box($output->single_button($url, get_string('assess', 'workshop'), 'post'), 'mr-1 inline');
 268      }
 269  }
 270  
 271  if (($workshop->phase == workshop::PHASE_CLOSED) and ($ownsubmission or $canviewall)) {
 272      if (!empty($submission->gradeoverby) and strlen(trim($submission->feedbackauthor)) > 0) {
 273          echo $output->render(new workshop_feedback_author($submission));
 274      }
 275  }
 276  
 277  // and possibly display the submission's review(s)
 278  
 279  if ($isreviewer) {
 280      // user's own assessment
 281      $strategy   = $workshop->grading_strategy_instance();
 282      $mform      = $strategy->get_assessment_form($PAGE->url, 'assessment', $userassessment, false);
 283      $options    = array(
 284          'showreviewer'  => true,
 285          'showauthor'    => $showauthor,
 286          'showform'      => !is_null($userassessment->grade),
 287          'showweight'    => true,
 288      );
 289      $assessment = $workshop->prepare_assessment($userassessment, $mform, $options);
 290      $assessment->title = get_string('assessmentbyyourself', 'workshop');
 291  
 292      if ($workshop->assessing_allowed($USER->id)) {
 293          if (is_null($userassessment->grade)) {
 294              $assessment->add_action($workshop->assess_url($assessment->id), get_string('assess', 'workshop'));
 295          } else {
 296              $assessment->add_action($workshop->assess_url($assessment->id), get_string('reassess', 'workshop'));
 297          }
 298      }
 299      if ($canoverride) {
 300          $assessment->add_action($workshop->assess_url($assessment->id), get_string('assessmentsettings', 'workshop'));
 301      }
 302  
 303      echo $output->render($assessment);
 304  
 305      if ($workshop->phase == workshop::PHASE_CLOSED) {
 306          if (strlen(trim($userassessment->feedbackreviewer)) > 0) {
 307              echo $output->render(new workshop_feedback_reviewer($userassessment));
 308          }
 309      }
 310  }
 311  
 312  if (has_capability('mod/workshop:viewallassessments', $workshop->context) or ($ownsubmission and $workshop->assessments_available())) {
 313      // other assessments
 314      $strategy       = $workshop->grading_strategy_instance();
 315      $assessments    = $workshop->get_assessments_of_submission($submission->id);
 316      $showreviewer   = has_capability('mod/workshop:viewreviewernames', $workshop->context);
 317      foreach ($assessments as $assessment) {
 318          if ($assessment->reviewerid == $USER->id) {
 319              // own assessment has been displayed already
 320              continue;
 321          }
 322          if (is_null($assessment->grade) and !has_capability('mod/workshop:viewallassessments', $workshop->context)) {
 323              // students do not see peer-assessment that are not graded yet
 324              continue;
 325          }
 326          $mform      = $strategy->get_assessment_form($PAGE->url, 'assessment', $assessment, false);
 327          $options    = array(
 328              'showreviewer'  => $showreviewer,
 329              'showauthor'    => $showauthor,
 330              'showform'      => !is_null($assessment->grade),
 331              'showweight'    => true,
 332          );
 333          $displayassessment = $workshop->prepare_assessment($assessment, $mform, $options);
 334          if ($canoverride) {
 335              $displayassessment->add_action($workshop->assess_url($assessment->id), get_string('assessmentsettings', 'workshop'));
 336          }
 337          echo $output->render($displayassessment);
 338  
 339          if ($workshop->phase == workshop::PHASE_CLOSED and has_capability('mod/workshop:viewallassessments', $workshop->context)) {
 340              if (strlen(trim($assessment->feedbackreviewer)) > 0) {
 341                  echo $output->render(new workshop_feedback_reviewer($assessment));
 342              }
 343          }
 344      }
 345  }
 346  
 347  if (!$edit and $canoverride) {
 348      // display a form to override the submission grade
 349      $feedbackform->display();
 350  }
 351  
 352  // If portfolios are enabled and we are not on the edit/removal confirmation screen, display a button to export this page.
 353  // The export is not offered if the submission is seen as a published one (it has no relation to the current user.
 354  if (!empty($CFG->enableportfolios)) {
 355      if (!$delete and !$edit and !$seenaspublished and $submission->id and ($ownsubmission or $canviewall or $isreviewer)) {
 356          if (has_capability('mod/workshop:exportsubmissions', $workshop->context)) {
 357              require_once($CFG->libdir.'/portfoliolib.php');
 358  
 359              $button = new portfolio_add_button();
 360              $button->set_callback_options('mod_workshop_portfolio_caller', array(
 361                  'id' => $workshop->cm->id,
 362                  'submissionid' => $submission->id,
 363              ), 'mod_workshop');
 364              $button->set_formats(PORTFOLIO_FORMAT_RICHHTML);
 365              echo html_writer::start_tag('div', array('class' => 'singlebutton'));
 366              echo $button->to_html(PORTFOLIO_ADD_FULL_FORM, get_string('exportsubmission', 'workshop'));
 367              echo html_writer::end_tag('div');
 368          }
 369      }
 370  }
 371  
 372  echo $output->footer();