fixed recent regression + simplified code a bit
[moodle.git] / mod / assignment / type / online / assignment.class.php
CommitLineData
e7521559 1<?php
6cb1b93e 2require_once($CFG->libdir.'/formslib.php');
8ceabede 3require_once($CFG->libdir . '/portfoliolib.php');
67a87e7d 4require_once($CFG->dirroot . '/mod/assignment/lib.php');
f77cfb73 5/**
6 * Extend the base assignment class for assignments where you upload a single file
7 *
8 */
9class assignment_online extends assignment_base {
10
7bddd4b7 11 function assignment_online($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
12 parent::assignment_base($cmid, $assignment, $cm, $course);
0b5a80a1 13 $this->type = 'online';
f77cfb73 14 }
15
f77cfb73 16 function view() {
f8ffb97e 17 global $OUTPUT, $CFG, $USER, $PAGE;
6cb1b93e 18
19 $edit = optional_param('edit', 0, PARAM_BOOL);
20 $saved = optional_param('saved', 0, PARAM_BOOL);
21
22 $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
0468976c 23 require_capability('mod/assignment:view', $context);
6cb1b93e 24
f8ffb97e 25 $submission = $this->get_submission($USER->id, false);
1648afb2 26
2eac7ec1 27 //Guest can not submit nor edit an assignment (bug: 4604)
be07f21b 28 if (!has_capability('mod/assignment:submit', $context)) {
f8ffb97e 29 $editable = false;
6cb1b93e 30 } else {
2eac7ec1 31 $editable = $this->isopen() && (!$submission || $this->assignment->resubmit || !$submission->timemarked);
32 }
6cb1b93e 33 $editmode = ($editable and $edit);
f77cfb73 34
35 if ($editmode) {
f8ffb97e
PS
36 // prepare form and process submitted data
37 $editoroptions = array('noclean'=>false, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$this->course->maxbytes);
38
39 $data = new object();
40 $data->id = $this->cm->id;
41 $data->edit = 1;
42 if ($submission) {
43 $data->sid = $submission->id;
44 $data->text = $submission->data1;
45 $data->textformat = $submission->data2;
46 } else {
47 $data->sid = NULL;
48 $data->text = '';
49 $data->textformat = NULL;
f7de5478 50 }
f77cfb73 51
f8ffb97e 52 $data = file_prepare_standard_editor($data, 'text', $editoroptions, $this->context, 'assignment_online_submission', $data->sid);
cb59ca28 53
f8ffb97e 54 $mform = new mod_assignment_online_edit_form(null, array($data, $editoroptions));
f77cfb73 55
f8ffb97e
PS
56 if ($mform->is_cancelled()) {
57 redirect($PAGE->url);
6cb1b93e 58 }
6cb1b93e 59
f8ffb97e
PS
60 if ($data = $mform->get_data()) {
61 $submission = $this->get_submission($USER->id, true); //create the submission if needed & its id
62
63 $data = file_postupdate_standard_editor($data, 'text', $editoroptions, $this->context, 'assignment_online_submission', $submission->id);
64
65 $submission = $this->update_submission($data);
5571b5f4 66
ca4fb814 67 //TODO fix log actions - needs db upgrade
f8ffb97e 68 add_to_log($this->course->id, 'assignment', 'upload', 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
9bf660b3 69 $this->email_teachers($submission);
f8ffb97e 70
3e7bf58a 71 //redirect to get updated submission date and word count
f8ffb97e 72 redirect(new moodle_url($PAGE->url, array('saved'=>1)));
f77cfb73 73 }
6cb1b93e 74 }
75
f8ffb97e
PS
76 add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id);
77
6cb1b93e 78/// print header, etc. and display form if needed
79 if ($editmode) {
80 $this->view_header(get_string('editmysubmission', 'assignment'));
81 } else {
82 $this->view_header();
83 }
84
85 $this->view_intro();
86
87 $this->view_dates();
88
89 if ($saved) {
3a003ead 90 echo $OUTPUT->notification(get_string('submissionsaved', 'assignment'), 'notifysuccess');
3e7bf58a 91 }
f77cfb73 92
61240489 93 if (has_capability('mod/assignment:submit', $context)) {
61240489 94 if ($editmode) {
a6e1750a 95 echo $OUTPUT->box_start('generalbox', 'onlineenter');
6cb1b93e 96 $mform->display();
61240489 97 } else {
01e0da58 98 echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter', 'online');
728e1931 99 if ($submission && has_capability('mod/assignment:exportownsubmission', $this->context)) {
007772d6 100 $text = file_rewrite_pluginfile_urls($submission->data1, 'pluginfile.php', $this->context->id, 'assignment_online_submission', $submission->id);
c561f44c 101 echo format_text($text, $submission->data2);
6afa5981
PL
102 if ($CFG->enableportfolios) {
103 require_once($CFG->libdir . '/portfoliolib.php');
104 $button = new portfolio_add_button();
105 $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id), '/mod/assignment/locallib.php');
106 $fs = get_file_storage();
107 if ($files = $fs->get_area_files($this->context->id, 'assignment_online_submission', $submission->id, "timemodified", false)) {
108 $button->set_formats(PORTFOLIO_FORMAT_RICHHTML);
109 } else {
110 $button->set_formats(PORTFOLIO_FORMAT_PLAINHTML);
111 }
112 $button->render();
df346604 113 }
61240489 114 } else if (!has_capability('mod/assignment:submit', $context)) { //fix for #4604
d9cb14b8 115 echo '<div style="text-align:center">'. get_string('guestnosubmit', 'assignment').'</div>';
61240489 116 } else if ($this->isopen()){ //fix for #4206
d9cb14b8 117 echo '<div style="text-align:center">'.get_string('emptysubmission', 'assignment').'</div>';
61240489 118 }
61240489 119 }
01e0da58 120 echo $OUTPUT->box_end();
12dce253 121 if (!$editmode && $editable) {
8ceabede
RW
122 if (!empty($submission)) {
123 $submitbutton = "editmysubmission";
124 } else {
125 $submitbutton = "addsubmission";
126 }
12dce253 127 echo "<div style='text-align:center'>";
8ceabede 128 echo $OUTPUT->single_button(new moodle_url('view.php', array('id'=>$this->cm->id, 'edit'=>'1')), get_string($submitbutton, 'assignment'));
12dce253 129 echo "</div>";
130 }
6cb1b93e 131
61240489 132 }
f77cfb73 133
134 $this->view_feedback();
135
136 $this->view_footer();
137 }
138
3e7bf58a 139 /*
140 * Display the assignment dates
141 */
142 function view_dates() {
3a003ead 143 global $USER, $CFG, $OUTPUT;
3e7bf58a 144
145 if (!$this->assignment->timeavailable && !$this->assignment->timedue) {
146 return;
147 }
148
3a003ead 149 echo $OUTPUT->box_start('generalbox boxaligncenter', 'dates');
3e7bf58a 150 echo '<table>';
151 if ($this->assignment->timeavailable) {
152 echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
153 echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
154 }
155 if ($this->assignment->timedue) {
156 echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
157 echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
158 }
159 $submission = $this->get_submission($USER->id);
160 if ($submission) {
161 echo '<tr><td class="c0">'.get_string('lastedited').':</td>';
162 echo ' <td class="c1">'.userdate($submission->timemodified);
1884f2a6 163 /// Decide what to count
164 if ($CFG->assignment_itemstocount == ASSIGNMENT_COUNT_WORDS) {
165 echo ' ('.get_string('numwords', '', count_words(format_text($submission->data1, $submission->data2))).')</td></tr>';
166 } else if ($CFG->assignment_itemstocount == ASSIGNMENT_COUNT_LETTERS) {
167 echo ' ('.get_string('numletters', '', count_letters(format_text($submission->data1, $submission->data2))).')</td></tr>';
168 }
3e7bf58a 169 }
170 echo '</table>';
3a003ead 171 echo $OUTPUT->box_end();
3e7bf58a 172 }
173
f77cfb73 174 function update_submission($data) {
74d7d735 175 global $CFG, $USER, $DB;
f77cfb73 176
177 $submission = $this->get_submission($USER->id, true);
178
6cb1b93e 179 $update = new object();
180 $update->id = $submission->id;
181 $update->data1 = $data->text;
f8ffb97e 182 $update->data2 = $data->textformat;
0cbc1f11 183 $update->timemodified = time();
f77cfb73 184
9d749339 185 $DB->update_record('assignment_submissions', $update);
12dce253 186
187 $submission = $this->get_submission($USER->id);
188 $this->update_grade($submission);
d2b6ee29 189 return $submission;
f77cfb73 190 }
191
192
9bf660b3 193 function print_student_answer($userid, $return=false){
f2a1963c 194 global $OUTPUT;
9bf660b3 195 if (!$submission = $this->get_submission($userid)) {
196 return '';
197 }
e7521559 198
9bf16314
PS
199 $link = new moodle_url("/mod/assignment/type/online/file.php?id={$this->cm->id}&userid={$submission->userid}");
200 $action = new popup_action('click', $link, 'file'.$userid, array('height' => 450, 'width' => 580));
201 $popup = $OUTPUT->action_link($link, shorten_text(trim(strip_tags(format_text($submission->data1,$submission->data2))), 15), $action, array('title'=>get_string('submission', 'assignment')));
e7521559 202
9bf660b3 203 $output = '<div class="files">'.
b5d0cafc 204 '<img src="'.$OUTPUT->pix_url('f/html') . '" class="icon" alt="html" />'.
a9573c08 205 $popup .
9bf660b3 206 '</div>';
207 return $output;
208 }
6cb1b93e 209
f77cfb73 210 function print_user_files($userid, $return=false) {
47c96a77 211 global $OUTPUT, $CFG;
6cb1b93e 212
f77cfb73 213 if (!$submission = $this->get_submission($userid)) {
214 return '';
215 }
e7521559 216
9bf16314
PS
217 $link = new moodle_url("/mod/assignment/type/online/file.php?id={$this->cm->id}&userid={$submission->userid}");
218 $action = new popup_action('click', $link, 'file'.$userid, array('height' => 450, 'width' => 580));
219 $popup = $OUTPUT->action_link($link, shorten_text(trim(strip_tags(format_text($submission->data1,$submission->data2))), 15), $action, array('title'=>get_string('submission', 'assignment')));
6cb1b93e 220
f77cfb73 221 $output = '<div class="files">'.
b5d0cafc 222 '<img align="middle" src="'.$OUTPUT->pix_url('f/html') . '" height="16" width="16" alt="html" />'.
a9573c08 223 $popup .
f77cfb73 224 '</div>';
225
d2b6ee29 226 $wordcount = '<p id="wordcount">';
63d69d54 227 /// Decide what to count
228 if ($CFG->assignment_itemstocount == ASSIGNMENT_COUNT_WORDS) {
d2b6ee29 229 $wordcount .= ' ('.get_string('numwords', '', count_words(format_text($submission->data1, $submission->data2))).')';
63d69d54 230 } else if ($CFG->assignment_itemstocount == ASSIGNMENT_COUNT_LETTERS) {
d2b6ee29 231 $wordcount .= ' ('.get_string('numletters', '', count_letters(format_text($submission->data1, $submission->data2))).')';
63d69d54 232 }
d2b6ee29 233 $wordcount .= '</p>';
234
235 $text = file_rewrite_pluginfile_urls($submission->data1, 'pluginfile.php', $this->context->id, 'assignment_online_submission', $submission->id);
236 return $wordcount . format_text($text, $submission->data2);
6cb1b93e 237
6cb1b93e 238
f77cfb73 239 }
f77cfb73 240
01e2fdfe 241 function preprocess_submission(&$submission) {
ea6432fe 242 if ($this->assignment->var1 && empty($submission->submissioncomment)) { // comment inline
47263937 243 if ($this->usehtmleditor) {
244 // Convert to html, clean & copy student data to teacher
ea6432fe 245 $submission->submissioncomment = format_text($submission->data1, $submission->data2);
6cb1b93e 246 $submission->format = FORMAT_HTML;
47263937 247 } else {
248 // Copy student data to teacher
ea6432fe 249 $submission->submissioncomment = $submission->data1;
6cb1b93e 250 $submission->format = $submission->data2;
47263937 251 }
01e2fdfe 252 }
253 }
254
436cfa9f 255 function setup_elements(&$mform) {
256 global $CFG, $COURSE;
257
258 $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
259
e66841b9
DM
260 $mform->addElement('select', 'resubmit', get_string('allowresubmit', 'assignment'), $ynoptions);
261 $mform->addHelpButton('resubmit', 'allowresubmit', 'assignment');
436cfa9f 262 $mform->setDefault('resubmit', 0);
263
e66841b9
DM
264 $mform->addElement('select', 'emailteachers', get_string('emailteachers', 'assignment'), $ynoptions);
265 $mform->addHelpButton('emailteachers', 'emailteachers', 'assignment');
436cfa9f 266 $mform->setDefault('emailteachers', 0);
267
e66841b9
DM
268 $mform->addElement('select', 'var1', get_string('commentinline', 'assignment'), $ynoptions);
269 $mform->addHelpButton('var1', 'commentinline', 'assignment');
436cfa9f 270 $mform->setDefault('var1', 0);
271
272 }
273
67a87e7d 274 function portfolio_exportable() {
275 return true;
276 }
ffcfd8a7 277
df346604
PL
278 function portfolio_load_data($caller) {
279 $submission = $this->get_submission();
280 $fs = get_file_storage();
281 if ($files = $fs->get_area_files($this->context->id, 'assignment_online_submission', $submission->id, "timemodified", false)) {
282 $caller->set('multifiles', $files);
283 }
284 }
285
286 function portfolio_get_sha1($caller) {
287 $submission = $this->get_submission();
288 $textsha1 = sha1(format_text($submission->data1, $submission->data2));
289 $filesha1 = '';
290 try {
291 $filesha1 = $caller->get_sha1_file();
292 } catch (portfolio_caller_exception $e) {} // no files
293 return sha1($textsha1 . $filesha1);
ffcfd8a7 294 }
295
df346604
PL
296 function portfolio_prepare_package($exporter, $user) {
297 $submission = $this->get_submission($user->id);
59dd457e 298 $html = format_text($submission->data1, $submission->data2);
df346604
PL
299 $html = portfolio_rewrite_pluginfile_urls($html, $this->context->id, 'assignment_online_submission', $submission->id, $exporter->get('format'));
300 if (in_array($exporter->get('formatclass'), array(PORTFOLIO_FORMAT_PLAINHTML, PORTFOLIO_FORMAT_RICHHTML))) {
301 if ($files = $exporter->get('caller')->get('multifiles')) {
302 foreach ($files as $f) {
303 $exporter->copy_existing_file($file);
304 }
305 }
306 return $exporter->write_new_file($html, 'assignment.html', !empty($files));
59dd457e
PL
307 } else if ($exporter->get('formatclass') == PORTFOLIO_FORMAT_LEAP2A) {
308 $leapwriter = $exporter->get('format')->leap2a_writer();
df346604 309 $entry = new portfolio_format_leap2a_entry('assignmentonline' . $this->assignment->id, $this->assignment->name, 'resource', $html);
59dd457e 310 $entry->add_category('web', 'resource_type');
df346604
PL
311 $entry->published = $submission->timecreated;
312 $entry->updated = $submission->timemodified;
313 $entry->author = $user;
59dd457e 314 $leapwriter->add_entry($entry);
df346604
PL
315 if ($files = $exporter->get('caller')->get('multifiles')) {
316 foreach ($files as $f) {
317 $exporter->copy_existing_file($f);
318 $entry->add_attachment($f);
319 }
320 }
321 $exporter->write_new_file($leapwriter->to_xml(), $exporter->get('format')->manifest_name(), true);
59dd457e 322 } else {
df346604 323 debugging('invalid format class: ' . $exporter->get('formatclass'));
59dd457e 324 }
ea0de12f 325 }
47c96a77 326
327 function extend_settings_navigation($node) {
328 global $PAGE, $CFG, $USER;
329
330 // get users submission if there is one
331 $submission = $this->get_submission();
332 if (has_capability('mod/assignment:submit', $PAGE->cm->context)) {
333 $editable = $this->isopen() && (!$submission || $this->assignment->resubmit || !$submission->timemarked);
334 } else {
335 $editable = false;
336 }
337
338 // If the user has submitted something add a bit more stuff
339 if ($submission) {
340 // Add a view link to the settings nav
a6855934 341 $link = new moodle_url('/mod/assignment/view.php', array('id'=>$PAGE->cm->id));
47c96a77 342 $node->add(get_string('viewmysubmission', 'assignment'), $link, navigation_node::TYPE_SETTING);
343
344 if (!empty($submission->timemodified)) {
3406acde
SH
345 $submittednode = $node->add(get_string('submitted', 'assignment') . ' ' . userdate($submission->timemodified));
346 $submittednode->text = preg_replace('#([^,])\s#', '$1&nbsp;', $submittednode->text);
347 $submittednode->add_class('note');
47c96a77 348 if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
3406acde 349 $submittednode->add_class('early');
47c96a77 350 } else {
3406acde 351 $submittednode->add_class('late');
47c96a77 352 }
353 }
354 }
355
356 if (!$submission || $editable) {
357 // If this assignment is editable once submitted add an edit link to the settings nav
a6855934 358 $link = new moodle_url('/mod/assignment/view.php', array('id'=>$PAGE->cm->id, 'edit'=>1, 'sesskey'=>sesskey()));
47c96a77 359 $node->add(get_string('editmysubmission', 'assignment'), $link, navigation_node::TYPE_SETTING);
360 }
361 }
c561f44c
SH
362
363 public function send_file($filearea, $args) {
ff284987 364 global $USER;
c561f44c
SH
365 require_capability('mod/assignment:view', $this->context);
366
367 $fullpath = $this->context->id.$filearea.implode('/', $args);
368
ff284987 369 $fs = get_file_storage();
c561f44c
SH
370 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
371 send_file_not_found();
372 }
373
374 if (($USER->id != $file->get_userid()) && !has_capability('mod/assignment:grade', $this->context)) {
375 send_file_not_found();
376 }
377
378 session_get_instance()->write_close(); // unlock session during fileserving
379 send_stored_file($file, 60*60, 0, true);
380 }
b37ce778
DM
381
382 /**
383 * creates a zip of all assignment submissions and sends a zip to the browser
384 */
385 public function download_submissions() {
386 global $CFG, $DB;
387 require_once($CFG->libdir.'/filelib.php');
f8ffb97e 388
b37ce778
DM
389 $submissions = $this->get_submissions('','');
390 if (empty($submissions)) {
391 error("there are no submissions to download");
392 }
393 $filesforzipping = array();
394 $tempdir = assignment_create_temp_dir($CFG->dataroot."/temp/", "assignment".$this->assignment->id); //location for temp files.
395 //online assignment can use html
396 $filextn=".html";
397
398 $groupmode = groupmode($this->course,$this->cm);
399 $groupid = 0; // All users
400 $groupname = '';
401 if($groupmode) {
402 $group = get_current_group($this->course->id, true);
403 $groupid = $group->id;
404 $groupname = $group->name.'-';
405 }
406 $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file.
407 foreach ($submissions as $submission) {
408 $a_userid = $submission->userid; //get userid
409 if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) {
410 $a_assignid = $submission->assignment; //get name of this assignment for use in the file names.
411 $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname
412 $submissioncontent = "<html><body>". $submission->data1. "</body></html>"; //fetched from database
413 //get file name.html
414 $fileforzipname = $a_user->username . "_" . clean_filename($this->assignment->name) . $filextn;
415 $fd = fopen($tempdir . $fileforzipname,'wb'); //create if not exist, write binary
416 fwrite( $fd, $submissioncontent);
417 fclose( $fd );
418 $filesforzipping[$fileforzipname] = $tempdir.$fileforzipname;
f8ffb97e 419 }
b37ce778
DM
420 } //end of foreach
421 if ($zipfile = assignment_pack_files($filesforzipping)) {
422 remove_dir($tempdir); //remove old tempdir with individual files.
423 send_temp_file($zipfile, $filename); //send file and delete after sending.
424 }
425 }
f77cfb73 426}
427
f07b9627 428class mod_assignment_online_edit_form extends moodleform {
6cb1b93e 429 function definition() {
f8ffb97e
PS
430 $mform = $this->_form;
431
432 list($data, $editoroptions) = $this->_customdata;
6cb1b93e 433
434 // visible elements
f8ffb97e 435 $mform->addElement('editor', 'text_editor', get_string('submission', 'assignment'), null, $editoroptions);
c561f44c 436 $mform->setType('text_editor', PARAM_RAW); // to be cleaned before display
c561f44c 437 $mform->addRule('text_editor', get_string('required'), 'required', null, 'client');
6cb1b93e 438
6117edc7 439 // hidden params
f8ffb97e 440 $mform->addElement('hidden', 'id');
6cb1b93e 441 $mform->setType('id', PARAM_INT);
442
1628ba8b 443 $mform->addElement('hidden', 'edit');
f8ffb97e
PS
444 $mform->setType('edit', PARAM_INT);
445
6cb1b93e 446 // buttons
a23f0aaf 447 $this->add_action_buttons();
c561f44c 448
f8ffb97e 449 $this->set_data($data);
c561f44c 450 }
6cb1b93e 451}
452
e7521559 453