b0f2597e |
1 | <?PHP // $Id$ |
2 | /** |
3 | * assignment_base is the base class for assignment types |
4 | * |
5 | * This class provides all the functionality for an assignment |
6 | */ |
04eba58f |
7 | |
d699cd1e |
8 | |
4909e176 |
9 | if (!isset($CFG->assignment_maxbytes)) { |
10 | set_config("assignment_maxbytes", 1024000); // Default maximum size for all assignments |
04eba58f |
11 | } |
12 | |
13 | |
b0f2597e |
14 | /* |
15 | * Standard base class for all assignment submodules (assignment types). |
16 | * |
17 | * |
18 | */ |
19 | class assignment_base { |
20 | |
21 | var $cm; |
22 | var $course; |
23 | var $assignment; |
24 | |
25 | /** |
26 | * Constructor for the base assignment class |
27 | * |
28 | * Constructor for the base assignment class. |
29 | * If cmid is set create the cm, course, assignment objects. |
30 | * |
31 | * @param cmid integer, the current course module id - not set for new assignments |
32 | */ |
33 | function assignment_base($cmid=0) { |
34 | |
35 | global $CFG; |
36 | |
37 | if ($cmid) { |
38 | if (! $this->cm = get_record("course_modules", "id", $cmid)) { |
39 | error("Course Module ID was incorrect"); |
40 | } |
04eba58f |
41 | |
b0f2597e |
42 | if (! $this->course = get_record("course", "id", $this->cm->course)) { |
43 | error("Course is misconfigured"); |
44 | } |
04eba58f |
45 | |
b0f2597e |
46 | if (! $this->assignment = get_record("assignment", "id", $this->cm->instance)) { |
47 | error("assignment ID was incorrect"); |
48 | } |
e6a4906b |
49 | |
b0f2597e |
50 | $this->strassignment = get_string('modulename', 'assignment'); |
51 | $this->strassignments = get_string('modulenameplural', 'assignment'); |
52 | $this->strsubmissions = get_string('submissions', 'assignment'); |
53 | $this->strlastmodified = get_string('lastmodified'); |
e6a4906b |
54 | |
b0f2597e |
55 | if ($this->course->category) { |
56 | $this->navigation = "<a target=\"{$CFG->framename}\" href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname}</a> -> ". |
57 | "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->"; |
58 | } else { |
59 | $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->"; |
60 | } |
e6a4906b |
61 | |
b0f2597e |
62 | $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.$this->assignment->name); |
e6a4906b |
63 | |
b0f2597e |
64 | if (!$this->cm->visible and !isteacher($this->course->id)) { |
65 | $pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment); |
66 | print_header($pagetitle, $this->course->fullname, "$this->navigation $this->strassignment", |
67 | "", "", true, '', navmenu($this->course, $this->cm)); |
68 | notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}"); |
69 | } |
70 | |
71 | $this->currentgroup = get_current_group($this->course->id); |
e6a4906b |
72 | |
e6a4906b |
73 | } |
74 | } |
75 | |
b0f2597e |
76 | /* |
77 | * Display the assignment to students (sub-modules will most likely override this) |
78 | */ |
04eba58f |
79 | |
b0f2597e |
80 | function view() { |
81 | global $CFG; |
04eba58f |
82 | |
b0f2597e |
83 | add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", |
84 | $this->assignment->id, $this->cm->id); |
04eba58f |
85 | |
b0f2597e |
86 | print_header($this->pagetitle, $this->course->fullname, $this->navigation.' '.$this->assignment->name, '', '', |
87 | true, update_module_button($this->cm->id, $this->course->id, $this->strassignment), |
88 | navmenu($this->course, $this->cm)); |
04eba58f |
89 | |
b0f2597e |
90 | echo '<div class="reportlink">'.$this->submittedlink().'</div>'; |
04eba58f |
91 | |
b0f2597e |
92 | print_simple_box_start('center'); |
93 | echo format_text($this->assignment->description, $this->assignment->format); |
94 | print_simple_box_end(); |
04eba58f |
95 | |
b0f2597e |
96 | print_simple_box_start('center', '', '', '', 'time'); |
97 | echo '<table>'; |
98 | echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>'; |
99 | echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>'; |
100 | echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>'; |
101 | echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>'; |
102 | echo '</table>'; |
103 | |
104 | print_simple_box_end(); |
04eba58f |
105 | |
b0f2597e |
106 | $this->view_feedback(); |
107 | |
108 | print_footer($this->course); |
36eb856f |
109 | } |
110 | |
04eba58f |
111 | |
b0f2597e |
112 | function view_feedback() { |
113 | global $USER; |
e6a4906b |
114 | |
b0f2597e |
115 | /// Get submission for this assignment |
116 | /// If no submission then just return quietly |
117 | $submission = $this->get_submission($USER->id); |
118 | if (empty($submission->timemarked)) { |
119 | return; |
9c48354d |
120 | } |
e6a4906b |
121 | |
b0f2597e |
122 | /// We need the teacher info |
123 | if (! $teacher = get_record('user', 'id', $submission->teacher)) { |
124 | print_object($submission); |
125 | error('Could not find the teacher'); |
126 | } |
e6a4906b |
127 | |
b0f2597e |
128 | /// Print the feedback |
6d4ecaec |
129 | print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher)); |
130 | |
b0f2597e |
131 | echo '<table cellspacing="0" class="feedback">'; |
132 | |
133 | echo '<tr>'; |
134 | echo '<td class="left picture">'; |
135 | print_user_picture($teacher->id, $this->course->id, $teacher->picture); |
136 | echo '</td>'; |
6d4ecaec |
137 | echo '<td class="topic">'; |
138 | echo '<div class="author">'.fullname($teacher).'</div>'; |
139 | echo '<div class="time">'.userdate($submission->timemarked).'</div>'; |
b0f2597e |
140 | echo '</td>'; |
141 | echo '</tr>'; |
142 | |
143 | echo '<tr>'; |
144 | echo '<td class="left side"> </td>'; |
6d4ecaec |
145 | echo '<td class="content">'; |
b0f2597e |
146 | if ($this->assignment->grade) { |
6d4ecaec |
147 | echo '<div class="grade">'; |
b0f2597e |
148 | if ($submission->grade or $submission->timemarked) { |
6d4ecaec |
149 | echo get_string("grade").': '.$this->display_grade($submission->grade); |
b0f2597e |
150 | } else { |
151 | echo get_string("nograde"); |
152 | } |
6d4ecaec |
153 | echo '</div>'; |
e6a4906b |
154 | } |
dcd338ff |
155 | |
6d4ecaec |
156 | echo '<div class="comment">'; |
b0f2597e |
157 | echo text_to_html($submission->comment); |
6d4ecaec |
158 | echo '</div>'; |
b0f2597e |
159 | echo '</tr>'; |
160 | |
161 | echo '</table>'; |
e6a4906b |
162 | } |
e6a4906b |
163 | |
164 | |
77db7e4c |
165 | |
b0f2597e |
166 | /* |
167 | * Print the start of the setup form for the current assignment type |
168 | */ |
169 | function setup(&$form, $action='') { |
170 | global $CFG, $THEME; |
171 | |
172 | if (empty($this->course)) { |
173 | if (! $this->course = get_record("course", "id", $form->course)) { |
174 | error("Course is misconfigured"); |
77db7e4c |
175 | } |
176 | } |
b0f2597e |
177 | if (empty($action)) { // Default destination for this form |
178 | $action = $CFG->wwwroot.'/course/mod.php'; |
179 | } |
77db7e4c |
180 | |
b0f2597e |
181 | if (empty($form->name)) { |
182 | $form->name = ""; |
183 | } |
184 | if (empty($form->assignmenttype)) { |
185 | $form->assignmenttype = ""; |
186 | } |
187 | if (empty($form->description)) { |
188 | $form->description = ""; |
189 | } |
77db7e4c |
190 | |
b0f2597e |
191 | $strname = get_string('name'); |
192 | $strassignments = get_string('modulenameplural', 'assignment'); |
193 | $strheading = empty($form->name) ? get_string("type$form->assignmenttype",'assignment') : $form->name; |
77db7e4c |
194 | |
b0f2597e |
195 | print_header($this->course->shortname.': '.$strheading, "$strheading", |
196 | "<a href=\"$CFG->wwwroot/course/view.php?id={$this->course->id}\">{$this->course->shortname} </a> -> ". |
197 | "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading"); |
77db7e4c |
198 | |
b0f2597e |
199 | print_simple_box_start("center"); |
200 | print_heading(get_string("type$form->assignmenttype",'assignment')); |
201 | include("$CFG->dirroot/mod/assignment/type/common.html"); |
202 | } |
203 | |
204 | /* |
205 | * Print the end of the setup form for the current assignment type |
206 | */ |
207 | function setup_end() { |
208 | global $CFG, $usehtmleditor; |
209 | |
210 | include($CFG->dirroot.'/mod/assignment/type/common_end.html'); |
77db7e4c |
211 | |
212 | print_simple_box_end(); |
213 | |
b0f2597e |
214 | if ($usehtmleditor) { |
215 | use_html_editor(); |
216 | } |
217 | |
218 | print_footer($this->course); |
77db7e4c |
219 | } |
77db7e4c |
220 | |
221 | |
b0f2597e |
222 | function add_instance($assignment) { |
223 | // Given an object containing all the necessary data, |
224 | // (defined by the form in mod.html) this function |
225 | // will create a new instance and return the id number |
226 | // of the new instance. |
227 | |
228 | $assignment->timemodified = time(); |
229 | $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth, |
230 | $assignment->dueday, $assignment->duehour, |
231 | $assignment->dueminute); |
232 | $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth, |
233 | $assignment->availableday, $assignment->availablehour, |
234 | $assignment->availableminute); |
d699cd1e |
235 | |
b0f2597e |
236 | return insert_record("assignment", $assignment); |
237 | } |
d699cd1e |
238 | |
b0f2597e |
239 | function delete_instance($assignment) { |
240 | if (! delete_records("assignment", "id", "$assignment->id")) { |
241 | $result = false; |
242 | } |
243 | return $result; |
244 | } |
d699cd1e |
245 | |
b0f2597e |
246 | function update_instance($assignment) { |
247 | // Given an object containing all the necessary data, |
248 | // (defined by the form in mod.html) this function |
249 | // will create a new instance and return the id number |
250 | // of the new instance. |
251 | |
252 | $assignment->timemodified = time(); |
253 | $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth, |
254 | $assignment->dueday, $assignment->duehour, |
255 | $assignment->dueminute); |
256 | $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth, |
257 | $assignment->availableday, $assignment->availablehour, |
258 | $assignment->availableminute); |
259 | $assignment->id = $assignment->instance; |
260 | return update_record("assignment", $assignment); |
261 | } |
262 | |
263 | |
264 | |
265 | /* |
266 | * Top-level function for handling of submissions called by submissions.php |
267 | * |
268 | */ |
269 | function submissions($mode) { |
270 | switch ($mode) { |
271 | case 'grade': // We are in a popup window grading |
272 | if ($submission = $this->process_feedback()) { |
273 | print_heading(get_string('changessaved')); |
be86672d |
274 | $this->update_main_listing($submission); |
b0f2597e |
275 | } |
276 | close_window(); |
277 | break; |
9cc9b7c1 |
278 | |
b0f2597e |
279 | case 'single': // We are in a popup window displaying submission |
280 | $this->display_submission(); |
281 | break; |
a56d79cd |
282 | |
b0f2597e |
283 | case 'all': // Main window, display everything |
284 | $this->display_submissions(); |
285 | break; |
a56d79cd |
286 | } |
b0f2597e |
287 | } |
a56d79cd |
288 | |
be86672d |
289 | function update_main_listing($submission) { |
290 | global $SESSION; |
291 | |
292 | /// Run some Javascript to try and update the parent page |
293 | echo '<script type="text/javascript">'."\n<!--\n"; |
294 | if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['grade'])) { |
295 | echo 'opener.document.getElementById("g'.$submission->userid. |
296 | '").innerHTML="'.$this->display_grade($submission->grade)."\";\n"; |
297 | } |
298 | if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['comment'])) { |
299 | echo 'opener.document.getElementById("com'.$submission->userid. |
300 | '").innerHTML="'.shorten_text($submission->comment, 15)."\";\n"; |
301 | } |
302 | if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemodified'])) { |
303 | echo 'opener.document.getElementById("ts'.$submission->userid. |
304 | '").innerHTML="'.userdate($submission->timemodified)."\";\n"; |
305 | } |
306 | if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemarked'])) { |
307 | echo 'opener.document.getElementById("tt'.$submission->userid. |
308 | '").innerHTML="'.userdate($submission->timemarked)."\";\n"; |
309 | } |
310 | if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['status'])) { |
311 | echo 'opener.document.getElementById("up'.$submission->userid.'").className="s1";'; |
6d4ecaec |
312 | echo 'opener.document.getElementById("button'.$submission->userid.'").value="'.get_string('update').' ...";'; |
be86672d |
313 | } |
314 | echo "\n-->\n</script>"; |
315 | fflush(); |
316 | } |
d699cd1e |
317 | |
d59269cf |
318 | /* |
319 | * Display a grade in user-friendly form, whether it's a scale or not |
320 | * |
321 | */ |
322 | function display_grade($grade) { |
323 | |
324 | static $scalegrades; // Cached because we only have one per assignment |
325 | |
326 | if ($this->assignment->grade >= 0) { // Normal number |
327 | return $grade; |
328 | |
329 | } else { // Scale |
330 | if (empty($scalegrades)) { |
331 | if ($scale = get_record('scale', 'id', -($this->assignment->grade))) { |
332 | $scalegrades = make_menu_from_list($scale->scale); |
333 | } else { |
334 | return '-'; |
335 | } |
336 | } |
0f7d4e5e |
337 | if (isset($scalegrades[$grade])) { |
338 | return $scalegrades[$grade]; |
339 | } |
340 | return ''; |
d59269cf |
341 | } |
342 | } |
343 | |
b0f2597e |
344 | /* |
345 | * Display a single submission, ready for grading on a popup window |
346 | * |
347 | */ |
348 | function display_submission() { |
b0f2597e |
349 | |
350 | $userid = required_param('userid'); |
d699cd1e |
351 | |
b0f2597e |
352 | if (!$user = get_record('user', 'id', $userid)) { |
353 | error('No such user!'); |
354 | } |
d699cd1e |
355 | |
0f7d4e5e |
356 | if (!$submission = $this->get_submission($user->id, true)) { // Get one or make one |
b0f2597e |
357 | error('Could not find submission!'); |
358 | } |
a5a4cd60 |
359 | |
b0f2597e |
360 | if ($submission->timemodified > $submission->timemarked) { |
361 | $subtype = 'assignmentnew'; |
362 | } else { |
363 | $subtype = 'assignmentold'; |
364 | } |
d699cd1e |
365 | |
b0f2597e |
366 | print_header($this->assignment->name.' '.fullname($user, true)); |
d699cd1e |
367 | |
b0f2597e |
368 | echo '<form action="submissions.php" method="post">'; |
369 | echo '<input type="hidden" name="userid" value="'.$userid.'">'; |
370 | echo '<input type="hidden" name="id" value="'.$this->cm->id.'">'; |
371 | echo '<input type="hidden" name="mode" value="grade">'; |
d699cd1e |
372 | |
b0f2597e |
373 | echo '<table cellspacing="0" class="submission '.$subtype.'" >'; |
d699cd1e |
374 | |
b0f2597e |
375 | echo '<tr>'; |
376 | echo '<td width="35" valign="top" class="picture user">'; |
377 | print_user_picture($user->id, $this->course->id, $user->picture); |
378 | echo '</td>'; |
379 | echo '<td class="heading">'.fullname($user, true).'</td>'; |
380 | echo '</tr>'; |
c69cb506 |
381 | |
b0f2597e |
382 | echo '<tr>'; |
383 | echo '<td width="35" valign="top" class="picture teacher">'; |
384 | if ($submission->teacher) { |
385 | $teacher = get_record('user', 'id', $submission->teacher); |
386 | } else { |
387 | global $USER; |
388 | $teacher = $USER; |
389 | } |
390 | print_user_picture($teacher->id, $this->course->id, $teacher->picture); |
391 | echo '</td>'; |
392 | echo '<td class="content">'; |
d699cd1e |
393 | |
b0f2597e |
394 | if (!$submission->grade and !$submission->timemarked) { |
395 | $submission->grade = -1; /// Hack to stop zero being selected on the menu below (so it shows 'no grade') |
396 | } |
397 | echo get_string('feedback', 'assignment').':'; |
398 | choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', |
399 | $submission->grade, get_string('nograde')); |
400 | |
401 | if ($submission->timemarked) { |
402 | echo ' '.userdate($submission->timemarked); |
d699cd1e |
403 | } |
b0f2597e |
404 | echo '<br />'; |
405 | print_textarea(false, 6, 60, 500, 400, 'comment', $submission->comment, $this->course->id); |
406 | echo '</td></tr>'; |
407 | echo '</table>'; |
408 | |
409 | echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" />'; |
410 | echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />'; |
411 | echo '</form>'; |
412 | print_footer('none'); |
d699cd1e |
413 | } |
414 | |
d699cd1e |
415 | |
b0f2597e |
416 | /* |
417 | * Display all the submissions ready for grading |
418 | */ |
419 | function display_submissions() { |
3446205d |
420 | |
b0f2597e |
421 | global $CFG, $db; |
3446205d |
422 | |
b0f2597e |
423 | $teacherattempts = true; /// Temporary measure |
1b5910c4 |
424 | |
b0f2597e |
425 | $page = optional_param('page', 0); |
426 | $perpage = optional_param('perpage', 10); |
d699cd1e |
427 | |
b0f2597e |
428 | $strsaveallfeedback = get_string('saveallfeedback', 'assignment'); |
d0ac6bc2 |
429 | |
b0f2597e |
430 | /// Some shortcuts to make the code read better |
431 | |
432 | $course = $this->course; |
433 | $assignment = $this->assignment; |
434 | $cm = $this->cm; |
91719320 |
435 | |
91719320 |
436 | |
b0f2597e |
437 | add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id); |
438 | |
439 | print_header_simple($this->assignment->name, "", '<a href="index.php?id='.$course->id.'">'.$this->strassignments.'</a> -> <a href="view.php?a='.$this->assignment->id.'">'.$this->assignment->name.'</a> -> '. $this->strsubmissions, '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm)); |
91719320 |
440 | |
91719320 |
441 | |
9437c854 |
442 | $tablecolumns = array('picture', 'fullname', 'grade', 'comment', 'timemodified', 'timemarked', 'status'); |
443 | $tableheaders = array('', get_string('fullname'), get_string('grade'), get_string('comment', 'assignment'), get_string('lastmodified').' ('.$course->student.')', get_string('lastmodified').' ('.$course->teacher.')', get_string('status')); |
91719320 |
444 | |
d0ac6bc2 |
445 | |
b0f2597e |
446 | require_once($CFG->libdir.'/tablelib.php'); |
447 | $table = new flexible_table('mod-assignment-submissions'); |
448 | |
449 | $table->define_columns($tablecolumns); |
450 | $table->define_headers($tableheaders); |
451 | $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id); |
452 | |
453 | $table->sortable(true); |
454 | $table->collapsible(true); |
455 | $table->initialbars(true); |
456 | |
457 | $table->column_suppress('picture'); |
458 | $table->column_suppress('fullname'); |
459 | |
460 | $table->column_class('picture', 'picture'); |
9437c854 |
461 | $table->column_class('fullname', 'fullname'); |
462 | $table->column_class('grade', 'grade'); |
463 | $table->column_class('comment', 'comment'); |
464 | $table->column_class('timemodified', 'timemodified'); |
465 | $table->column_class('timemarked', 'timemarked'); |
466 | $table->column_class('status', 'status'); |
b0f2597e |
467 | |
468 | $table->set_attribute('cellspacing', '0'); |
469 | $table->set_attribute('id', 'attempts'); |
9437c854 |
470 | $table->set_attribute('class', 'submissions'); |
b0f2597e |
471 | $table->set_attribute('width', '90%'); |
472 | $table->set_attribute('align', 'center'); |
473 | |
474 | // Start working -- this is necessary as soon as the niceties are over |
475 | $table->setup(); |
476 | |
05855091 |
477 | |
05855091 |
478 | |
b0f2597e |
479 | /// Check to see if groups are being used in this assignment |
480 | if ($groupmode = groupmode($course, $cm)) { // Groups are being used |
306dc7e5 |
481 | $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id); |
b0f2597e |
482 | } else { |
483 | $currentgroup = false; |
05855091 |
484 | } |
05855091 |
485 | |
0f1a97c2 |
486 | |
b0f2597e |
487 | /// Get all teachers and students |
488 | if ($currentgroup) { |
489 | $users = get_group_users($currentgroup); |
490 | } else { |
491 | $users = get_course_users($course->id); |
492 | } |
493 | |
494 | if (!$teacherattempts) { |
495 | $teachers = get_course_teachers($course->id); |
496 | if (!empty($teachers)) { |
497 | $keys = array_keys($teachers); |
498 | } |
499 | foreach ($keys as $key) { |
500 | unset($users[$key]); |
501 | } |
502 | } |
503 | |
504 | if (empty($users)) { |
505 | print_heading($strnoattempts); |
506 | return true; |
507 | } |
0f1a97c2 |
508 | |
0f1a97c2 |
509 | |
b0f2597e |
510 | /// Construct the SQL |
0f1a97c2 |
511 | |
b0f2597e |
512 | if ($where = $table->get_sql_where()) { |
513 | $where = str_replace('firstname', 'u.firstname', $where); |
514 | $where = str_replace('lastname', 'u.lastname', $where); |
515 | $where .= ' AND '; |
516 | } |
0f1a97c2 |
517 | |
b0f2597e |
518 | if ($sort = $table->get_sql_sort()) { |
519 | $sortparts = explode(',', $sort); |
520 | $newsort = array(); |
521 | foreach ($sortparts as $sortpart) { |
522 | $sortpart = trim($sortpart); |
523 | $newsort[] = $sortpart; |
524 | } |
525 | $sort = ' ORDER BY '.implode(', ', $newsort); |
526 | } |
9fa49e22 |
527 | |
9fa49e22 |
528 | |
9437c854 |
529 | $select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('s.userid', '0')).' AS uvs, u.id, u.firstname, u.lastname, u.picture, s.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) && (s.timemarked >= s.timemodified)) AS status '; |
d59269cf |
530 | $group = 'GROUP BY uvs '; |
b0f2597e |
531 | $sql = 'FROM '.$CFG->prefix.'user u '. |
306dc7e5 |
532 | 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid AND s.assignment = '.$this->assignment->id.' '. |
533 | 'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') '; |
8ff79e8c |
534 | |
8ff79e8c |
535 | |
d59269cf |
536 | $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('s.userid', '0')).')) '.$sql); |
000cc405 |
537 | |
b0f2597e |
538 | $table->pagesize($perpage, $total); |
539 | |
540 | if($table->get_page_start() !== '' && $table->get_page_size() !== '') { |
541 | $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size()); |
542 | } |
543 | else { |
544 | $limit = ''; |
545 | } |
9fa49e22 |
546 | |
b0f2597e |
547 | $strupdate = get_string('update'); |
9437c854 |
548 | $strgrade = get_string('grade'); |
b0f2597e |
549 | $grademenu = make_grades_menu($this->assignment->grade); |
550 | |
9437c854 |
551 | if (($ausers = get_records_sql($select.$sql.$group.$sort.$limit)) !== false) { |
d59269cf |
552 | |
d59269cf |
553 | foreach ($ausers as $auser) { |
554 | $picture = print_user_picture($auser->id, $course->id, $auser->picture, false, true); |
555 | if (!empty($auser->submissionid)) { |
556 | if ($auser->timemodified > 0) { |
557 | $studentmodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>'; |
d59269cf |
558 | } else { |
9437c854 |
559 | $studentmodified = '<div id="ts'.$auser->id.'"> </div>'; |
d59269cf |
560 | } |
561 | if ($auser->timemarked > 0) { |
562 | $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>'; |
b0f2597e |
563 | } else { |
9437c854 |
564 | $teachermodified = '<div id="tt'.$auser->id.'"> </div>'; |
b0f2597e |
565 | } |
9437c854 |
566 | |
d59269cf |
567 | $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>'; |
9437c854 |
568 | $comment = '<div id="com'.$auser->id.'">'.shorten_text($auser->comment, 15).'</div>'; |
d59269cf |
569 | |
b0f2597e |
570 | } else { |
9437c854 |
571 | $studentmodified = '<div id="ts'.$auser->id.'"> </div>'; |
572 | $teachermodified = '<div id="tt'.$auser->id.'"> </div>'; |
d59269cf |
573 | $status = '<div id="st'.$auser->id.'"></div>'; |
9437c854 |
574 | $grade = '<div id="g'.$auser->id.'"> </div>'; |
575 | $comment = '<div id="com'.$auser->id.'"> </div>'; |
b0f2597e |
576 | } |
9fa49e22 |
577 | |
0f7d4e5e |
578 | if ($auser->status === NULL) { |
579 | $auser->status = 0; |
580 | } |
581 | |
9437c854 |
582 | $buttontext = ($auser->status == 1) ? $strupdate : $strgrade; |
9fa49e22 |
583 | |
9437c854 |
584 | $button = button_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&userid='.$auser->id.'&mode=single', |
0f7d4e5e |
585 | 'grade'.$auser->id, $buttontext, 450, 600, $buttontext, 'none', true, 'button'.$auser->id); |
586 | |
9437c854 |
587 | $status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>'; |
306dc7e5 |
588 | |
9437c854 |
589 | $row = array($picture, fullname($auser), $grade, $comment, $studentmodified, $teachermodified, $status); |
d59269cf |
590 | $table->add_data($row); |
591 | } |
b0f2597e |
592 | } |
d699cd1e |
593 | |
b0f2597e |
594 | $table->print_html(); |
d699cd1e |
595 | |
b0f2597e |
596 | print_footer($this->course); |
d699cd1e |
597 | |
8e340cb0 |
598 | } |
d699cd1e |
599 | |
d699cd1e |
600 | |
d699cd1e |
601 | |
b0f2597e |
602 | /* |
603 | * Display and process the submissions |
604 | */ |
605 | function process_feedback() { |
d699cd1e |
606 | |
b0f2597e |
607 | global $USER; |
d699cd1e |
608 | |
b0f2597e |
609 | if (!$feedback = data_submitted()) { // No incoming data? |
610 | return false; |
d699cd1e |
611 | } |
b7b42874 |
612 | |
b0f2597e |
613 | if (!empty($feedback->cancel)) { // User hit cancel button |
614 | return false; |
615 | } |
d699cd1e |
616 | |
0f7d4e5e |
617 | $newsubmission = $this->get_submission($feedback->userid, true); // Get or make one |
d699cd1e |
618 | |
b0f2597e |
619 | $newsubmission->grade = $feedback->grade; |
620 | $newsubmission->comment = $feedback->comment; |
621 | $newsubmission->teacher = $USER->id; |
622 | $newsubmission->mailed = 0; // Make sure mail goes out (again, even) |
623 | $newsubmission->timemarked = time(); |
d699cd1e |
624 | |
b0f2597e |
625 | if (empty($submission->timemodified)) { // eg for offline assignments |
626 | $newsubmission->timemodified = time(); |
627 | } |
d699cd1e |
628 | |
b0f2597e |
629 | if (! update_record('assignment_submissions', $newsubmission)) { |
630 | return false; |
631 | } |
d699cd1e |
632 | |
b0f2597e |
633 | add_to_log($this->course->id, 'assignment', 'update grades', |
634 | 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id); |
635 | |
636 | return $newsubmission; |
d699cd1e |
637 | |
d699cd1e |
638 | } |
d699cd1e |
639 | |
d699cd1e |
640 | |
0f7d4e5e |
641 | function get_submission($userid, $createnew=false) { |
b0f2597e |
642 | $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); |
d699cd1e |
643 | |
b0f2597e |
644 | if ($submission || !$createnew) { |
645 | return $submission; |
646 | } |
d699cd1e |
647 | |
b0f2597e |
648 | $newsubmission = new Object; |
649 | $newsubmission->assignment = $this->assignment->id; |
650 | $newsubmission->userid = $userid; |
651 | $newsubmission->timecreated = time(); |
652 | if (!insert_record("assignment_submissions", $newsubmission)) { |
653 | error("Could not insert a new empty submission"); |
654 | } |
d699cd1e |
655 | |
b0f2597e |
656 | return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid); |
657 | } |
d699cd1e |
658 | |
3f8247c2 |
659 | |
b0f2597e |
660 | function get_submissions($sort='', $dir='DESC') { |
661 | /// Return all assignment submissions by ENROLLED students (even empty) |
662 | global $CFG; |
663 | |
664 | if ($sort == "lastname" or $sort == "firstname") { |
665 | $sort = "u.$sort $dir"; |
666 | } else if (empty($sort)) { |
667 | $sort = "a.timemodified DESC"; |
668 | } else { |
669 | $sort = "a.$sort $dir"; |
d699cd1e |
670 | } |
d699cd1e |
671 | |
b0f2597e |
672 | $select = "s.course = '$this->assignment->course' AND"; |
673 | $site = get_site(); |
674 | if ($this->assignment->course == $site->id) { |
675 | $select = ''; |
676 | } |
677 | return get_records_sql("SELECT a.* |
678 | FROM {$CFG->prefix}assignment_submissions a, |
679 | {$CFG->prefix}user_students s, |
680 | {$CFG->prefix}user u |
681 | WHERE a.userid = s.userid |
682 | AND u.id = a.userid |
683 | AND $select a.assignment = '$this->assignment->id' |
684 | ORDER BY $sort"); |
685 | } |
686 | |
687 | |
688 | function count_real_submissions($groupid=0) { |
689 | /// Return all real assignment submissions by ENROLLED students (not empty ones) |
690 | global $CFG; |
691 | |
692 | if ($groupid) { /// How many in a particular group? |
693 | return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid) |
694 | FROM {$CFG->prefix}assignment_submissions a, |
695 | {$CFG->prefix}groups_members g |
696 | WHERE a.assignment = {$this->assignment->id} |
697 | AND a.timemodified > 0 |
698 | AND g.groupid = '$groupid' |
699 | AND a.userid = g.userid "); |
700 | } else { |
701 | $select = "s.course = '{$this->assignment->course}' AND"; |
702 | if ($this->assignment->course == SITEID) { |
703 | $select = ''; |
d699cd1e |
704 | } |
b0f2597e |
705 | return count_records_sql("SELECT COUNT(*) |
706 | FROM {$CFG->prefix}assignment_submissions a, |
707 | {$CFG->prefix}user_students s |
708 | WHERE a.assignment = '{$this->assignment->id}' |
709 | AND a.timemodified > 0 |
710 | AND $select a.userid = s.userid "); |
711 | } |
d59269cf |
712 | } |
d699cd1e |
713 | |
b0f2597e |
714 | } ////// End of the assignment_base class |
d699cd1e |
715 | |
18b8fbfa |
716 | |
04eba58f |
717 | |
b0f2597e |
718 | /// OTHER STANDARD FUNCTIONS //////////////////////////////////////////////////////// |
719 | |
720 | |
721 | function assignment_delete_instance($id){ |
26b90e70 |
722 | global $CFG; |
723 | |
b0f2597e |
724 | if (! $assignment = get_record('assignment', 'id', $id)) { |
725 | return false; |
26b90e70 |
726 | } |
727 | |
b0f2597e |
728 | require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); |
729 | $assignmentclass = "assignment_$assignment->assignmenttype"; |
730 | $ass = new $assignmentclass(); |
731 | return $ass->delete_instance($assignment); |
732 | } |
f466c9ed |
733 | |
ac21ad39 |
734 | |
b0f2597e |
735 | function assignment_update_instance($assignment){ |
736 | global $CFG; |
26b90e70 |
737 | |
b0f2597e |
738 | require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); |
739 | $assignmentclass = "assignment_$assignment->assignmenttype"; |
740 | $ass = new $assignmentclass(); |
741 | return $ass->update_instance($assignment); |
742 | } |
26b90e70 |
743 | |
26b90e70 |
744 | |
b0f2597e |
745 | function assignment_add_instance($assignment) { |
746 | global $CFG; |
f466c9ed |
747 | |
b0f2597e |
748 | require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php"); |
749 | $assignmentclass = "assignment_$assignment->assignmenttype"; |
750 | $ass = new $assignmentclass(); |
751 | return $ass->add_instance($assignment); |
752 | } |
f466c9ed |
753 | |
b0f2597e |
754 | function assignment_types() { |
755 | $types = array(); |
756 | $names = get_list_of_plugins('mod/assignment/type'); |
757 | foreach ($names as $name) { |
758 | $types[$name] = get_string('type'.$name, 'assignment'); |
ffeca120 |
759 | } |
b0f2597e |
760 | asort($types); |
761 | return $types; |
f466c9ed |
762 | } |
763 | |
b0f2597e |
764 | function assignment_upgrade_submodules() { |
f1c1d2f1 |
765 | global $CFG; |
26b90e70 |
766 | |
b0f2597e |
767 | $types = assignment_types(); |
26b90e70 |
768 | |
b0f2597e |
769 | include_once($CFG->dirroot.'/mod/assignment/version.php'); // defines $module with version etc |
26b90e70 |
770 | |
b0f2597e |
771 | foreach ($types as $type) { |
26b90e70 |
772 | |
b0f2597e |
773 | $fullpath = $CFG->dirroot.'/mod/assignment/type/'.$type; |
26b90e70 |
774 | |
b0f2597e |
775 | /// Check for an external version file (defines $submodule) |
26b90e70 |
776 | |
b0f2597e |
777 | if (!is_readable($fullpath .'/version.php')) { |
778 | continue; |
ffeca120 |
779 | } |
b0f2597e |
780 | unset($module); |
781 | include_once($fullpath .'/version.php'); |
26b90e70 |
782 | |
b0f2597e |
783 | /// Check whether we need to upgrade |
26b90e70 |
784 | |
b0f2597e |
785 | if (!isset($submodule->version)) { |
786 | continue; |
787 | } |
26b90e70 |
788 | |
b0f2597e |
789 | /// Make sure this submodule will work with this assignment version |
26b90e70 |
790 | |
b0f2597e |
791 | if (isset($submodule->requires) and ($submodules->requires > $module->version)) { |
792 | notify("Assignment submodule '$type' is too new for your assignment"); |
793 | continue; |
794 | } |
f466c9ed |
795 | |
b0f2597e |
796 | /// If we use versions, make sure an internal record exists |
f466c9ed |
797 | |
b0f2597e |
798 | $currentversion = 'assignment_'.$type.'_version'; |
f466c9ed |
799 | |
b0f2597e |
800 | if (!isset($CFG->$currentversion)) { |
801 | set_config($currentversion, 0); |
f466c9ed |
802 | } |
f466c9ed |
803 | |
b0f2597e |
804 | /// See if we need to upgrade |
805 | |
806 | if ($submodule->version <= $CFG->$currentversion) { |
807 | continue; |
59c005b7 |
808 | } |
59c005b7 |
809 | |
b0f2597e |
810 | /// Look for the upgrade file |
59c005b7 |
811 | |
b0f2597e |
812 | if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.php')) { |
813 | continue; |
814 | } |
59c005b7 |
815 | |
b0f2597e |
816 | include_once($fullpath .'/db/'. $CFG->dbtype .'.php'); // defines assignment_xxx_upgrade |
59c005b7 |
817 | |
b0f2597e |
818 | /// Perform the upgrade |
59c005b7 |
819 | |
b0f2597e |
820 | $upgrade_function = 'assignment_'.$type.'_upgrade'; |
821 | if (function_exists($upgrade_function)) { |
822 | $db->debug=true; |
823 | if ($upgrade_function($CFG->$currentversion)) { |
824 | $db->debug=false; |
825 | set_config($currentversion, $submodule->version); |
59c005b7 |
826 | } |
b0f2597e |
827 | $db->debug=false; |
59c005b7 |
828 | } |
829 | } |
9437c854 |
830 | |
831 | |
59c005b7 |
832 | } |
833 | |
04eba58f |
834 | ?> |