Merge remote branch 'github/master' into backup-convert

This commit is contained in:
David Mudrak 2011-05-18 16:08:15 +02:00
commit c18f90f22f
23 changed files with 462 additions and 237 deletions

View File

@ -1316,6 +1316,7 @@ abstract class role_allow_role_page {
foreach ($rs as $allow) {
$this->allowed[$allow->roleid][$allow->{$this->targetcolname}] = true;
}
$rs->close();
}
/**

View File

@ -70,16 +70,6 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
parent::add_path($path);
}
/**
* Notify start of path if selected and not under grouped
*/
public function before_path($path) {
if ($this->path_is_selected($path) && !$this->grouped_parent_exists($path)) {
parent::before_path($path);
}
}
/**
* Dispatch grouped chunks safely once their end tag happens.
* Also notify end of path if selected and not under grouped
@ -110,6 +100,7 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
$path = $data['path'];
// If the chunk is a grouped one, simply put it into currentdata
if ($this->path_is_grouped($path)) {
$this->notify_path_start($path);
$this->currentdata[$path] = $data;
// If the chunk is child of grouped one, add it to currentdata
@ -119,6 +110,7 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
// No grouped nor child of grouped, dispatch it
} else {
$this->notify_path_start($path);
$this->dispatch_chunk($data);
}
}

View File

@ -149,15 +149,6 @@ abstract class simplified_parser_processor extends progressive_parser_processor
return true;
}
/**
* The parser fires this each time one path is going to be parsed
*/
public function before_path($path) {
if ($this->path_is_selected($path)) {
$this->notify_path_start($path);
}
}
/**
* The parser fires this each time one path has been parsed
*/
@ -170,6 +161,7 @@ abstract class simplified_parser_processor extends progressive_parser_processor
// Protected API starts here
protected function postprocess_chunk($data) {
$this->notify_path_start($data['path']);
$this->dispatch_chunk($data);
}

View File

@ -330,6 +330,13 @@ class progressive_parser_test extends UnitTestCase {
sort($snotifs);
sort($enotifs);
$this->assertEqual($snotifs, $enotifs);
// Now verify that the start/process/end order is correct
$allnotifs = $pr->get_all_notifications();
$this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count
// Check integrity of the notifications
$errcount = $this->helper_check_notifications_order_integrity($allnotifs);
$this->assertEqual($errcount, 0); // No errors found, plz
}
/*
@ -498,6 +505,67 @@ class progressive_parser_test extends UnitTestCase {
sort($snotifs);
sort($enotifs);
$this->assertEqual($snotifs, $enotifs);
// Now verify that the start/process/end order is correct
$allnotifs = $pr->get_all_notifications();
$this->assertEqual(count($allnotifs), count($snotifs) + count($enotifs) + count($chunks)); // The count
// Check integrity of the notifications
$errcount = $this->helper_check_notifications_order_integrity($allnotifs);
$this->assertEqual($errcount, 0); // No errors found, plz
}
/**
* Helper function that given one array of ordered start/process/end notifications will
* check it of integrity like:
* - process only happens if start is the previous notification
* - end only happens if dispatch is the previous notification
* - start only happen with level > than last one and if there is no already started like that
*
* @param array $notifications ordered array of notifications with format [start|process|end]:path
* @return int number of integrity problems found (errors)
*/
function helper_check_notifications_order_integrity($notifications) {
$numerrors = 0;
$notifpile = array('pilebase' => 'start');
$lastpile = 'start:pilebase';
foreach ($notifications as $notif) {
$lastpilelevel = strlen(preg_replace('/[^\/]/', '', $lastpile));
$lastpiletype = preg_replace('/:.*/', '', $lastpile);
$lastpilepath = preg_replace('/.*:/', '', $lastpile);
$notiflevel = strlen(preg_replace('/[^\/]/', '', $notif));
$notiftype = preg_replace('/:.*/', '', $notif);
$notifpath = preg_replace('/.*:/', '', $notif);
switch ($notiftype) {
case 'process':
if ($lastpilepath != $notifpath or $lastpiletype != 'start') {
$numerrors++; // Only start for same path is allowed before process
}
$notifpile[$notifpath] = 'process'; // Update the status in the pile
break;
case 'end':
if ($lastpilepath != $notifpath or $lastpiletype != 'process') {
$numerrors++; // Only process for same path is allowed before end
}
unset($notifpile[$notifpath]); // Delete from the pile
break;
case 'start':
if (array_key_exists($notifpath, $notifpile) or $notiflevel <= $lastpilelevel) {
$numerrors++; // If same path exists or the level is < than the last one
}
$notifpile[$notifpath] = 'start'; // Add to the pile
break;
default:
$numerrors++; // Incorrect type of notification => error
}
// Update lastpile
end($notifpile);
$path = key($notifpile);
$type = $notifpile[$path];
$lastpile = $type. ':' . $path;
}
return $numerrors;
}
}
@ -572,17 +640,21 @@ class mock_simplified_parser_processor extends simplified_parser_processor {
private $chunksarr = array(); // To accumulate the found chunks
private $startarr = array(); // To accumulate all the notified path starts
private $endarr = array(); // To accumulate all the notified path ends
private $allnotif = array(); // To accumulate all the notified and dispatched events in an ordered way
public function dispatch_chunk($data) {
$this->chunksarr[] = $data;
$this->allnotif[] = 'process:' . $data['path'];
}
public function notify_path_start($path) {
$this->startarr[] = $path;
$this->allnotif[] = 'start:' . $path;
}
public function notify_path_end($path) {
$this->endarr[] = $path;
$this->allnotif[] = 'end:' . $path;
}
public function get_chunks() {
@ -596,6 +668,10 @@ class mock_simplified_parser_processor extends simplified_parser_processor {
public function get_end_notifications() {
return $this->endarr;
}
public function get_all_notifications() {
return $this->allnotif;
}
}
/*
@ -606,17 +682,21 @@ class mock_grouped_parser_processor extends grouped_parser_processor {
private $chunksarr = array(); // To accumulate the found chunks
private $startarr = array(); // To accumulate all the notified path starts
private $endarr = array(); // To accumulate all the notified path ends
private $allnotif = array(); // To accumulate all the notified and dispatched events in an ordered way
public function dispatch_chunk($data) {
$this->chunksarr[] = $data;
$this->allnotif[] = 'process:' . $data['path'];
}
public function notify_path_start($path) {
$this->startarr[] = $path;
$this->allnotif[] = 'start:' . $path;
}
public function notify_path_end($path) {
$this->endarr[] = $path;
$this->allnotif[] = 'end:' . $path;
}
public function get_chunks() {
@ -630,4 +710,8 @@ class mock_grouped_parser_processor extends grouped_parser_processor {
public function get_end_notifications() {
return $this->endarr;
}
public function get_all_notifications() {
return $this->allnotif;
}
}

View File

@ -13,7 +13,7 @@ if (empty($CFG->enablecalendarexport)) {
}
//Fetch user information
if (!$user = get_complete_user_data('username', $username)) {
if (!$user = $DB->get_record('user', array('username' => $username), 'id,password')) {
//No such user
die('Invalid authentication');
}

View File

@ -127,16 +127,14 @@ class comment {
*/
protected $totalcommentcount = null;
/**
* By default a user must have the generic comment capabilities plus any capabilities the
* component being commented on requires.
* When set to true only the component capabilities are checked, the system capabilities are
* ignored.
* This can be toggled by the component defining a callback in its lib.php e.g.
* function forum_comment_allow_anonymous_access(comment $comment) {}
* Note: On the front page this defaults to true.
* When set to true any user to the system is able to view comments.
*
* This can be set to true by a plugin by implementing a allow_anonymous_access callback.
* By default it is false except on the front page.
*
* @var bool
*/
protected $ignoresystempermissions = false;
protected $allowanonymousaccess = false;
/**#@+
* static variable will be used by non-js comments UI

View File

@ -152,7 +152,7 @@ function profiling_start() {
* Stop profiling, gathering results and storing them
*/
function profiling_stop() {
global $CFG, $SCRIPT;
global $CFG, $DB, $SCRIPT;
// If profiling isn't available, nothing to stop
if (!extension_loaded('xhprof') || !function_exists('xhprof_enable')) {
@ -176,6 +176,14 @@ function profiling_stop() {
profiling_is_running(false);
$data = xhprof_disable();
// We only save the run after ensuring the DB table exists
// (this prevents problems with profiling runs enabled in
// config.php before Moodle is installed. Rare but...
$tables = $DB->get_tables();
if (!in_array('profiling', $tables)) {
return false;
}
$run = new moodle_xhprofrun();
$run->prepare_run($script);
$runid = $run->save_run($data, null);

View File

@ -200,6 +200,8 @@ function message_get_blocked_users($user1=null, $user2=null) {
$user2->isblocked = false;
}
$blockedusers = array();
$userfields = user_picture::fields('u', array('lastaccess'));
$blockeduserssql = "SELECT $userfields, COUNT(m.id) AS messagecount
FROM {message_contacts} mc
@ -210,18 +212,14 @@ function message_get_blocked_users($user1=null, $user2=null) {
ORDER BY u.firstname ASC";
$rs = $DB->get_recordset_sql($blockeduserssql, array('user1id1' => $user1->id, 'user1id2' => $user1->id));
$blockedusers = array();
if (!empty($rs)) {
foreach($rs as $rd) {
$blockedusers[] = $rd;
foreach($rs as $rd) {
$blockedusers[] = $rd;
if (!empty($user2) && $user2->id == $rd->id) {
$user2->isblocked = true;
}
if (!empty($user2) && $user2->id == $rd->id) {
$user2->isblocked = true;
}
unset($rd);
$rs->close();
}
$rs->close();
return $blockedusers;
}
@ -2129,6 +2127,8 @@ function message_mark_messages_read($touserid, $fromuserid){
foreach ($messages as $message) {
message_mark_message_read($message, time());
}
$messages->close();
}
/**

View File

@ -144,12 +144,13 @@ $string['noblogs'] = 'You have no blog entries to submit!';
$string['nofiles'] = 'No files were submitted';
$string['nofilesyet'] = 'No files submitted yet';
$string['nomoresubmissions'] = 'No further submissions are allowed.';
$string['nosubmitusers'] = 'No users were found with permissions to submit this assignment';
$string['notavailableyet'] = 'Sorry, this assignment is not yet available.<br />Assignment instructions will be displayed here on the date given below.';
$string['notes'] = 'Notes';
$string['notesempty'] = 'No entry';
$string['notesupdateerror'] = 'Error when updating notes';
$string['notgradedyet'] = 'Not graded yet';
$string['norequiregrading'] = 'There are no assignments that require grading';
$string['nosubmisson'] = 'No assignments have been submit';
$string['notsubmittedyet'] = 'Not submitted yet';
$string['onceassignmentsent'] = 'Once the assignment is sent for marking, you will no longer be able to delete or attach file(s). Do you want to continue?';
$string['operation'] = 'Operation';

View File

@ -1128,6 +1128,7 @@ class assignment_base {
$course = $this->course;
$assignment = $this->assignment;
$cm = $this->cm;
$hassubmission = false;
$tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id, $this->assignment->id, $this->cm->id);
@ -1264,16 +1265,7 @@ class assignment_base {
// Start working -- this is necessary as soon as the niceties are over
$table->setup();
if (empty($users)) {
echo $OUTPUT->heading(get_string('nosubmitusers','assignment'));
echo '</div>';
return true;
}
if ($this->assignment->assignmenttype=='upload' || $this->assignment->assignmenttype=='online' || $this->assignment->assignmenttype=='uploadsingle') { //TODO: this is an ugly hack, where is the plugin spirit? (skodak)
echo '<div style="text-align:right"><a href="submissions.php?id='.$this->cm->id.'&amp;download=zip">'.get_string('downloadall', 'assignment').'</a></div>';
}
/// Construct the SQL
list($where, $params) = $table->get_sql_where();
if ($where) {
$where .= ' AND ';
@ -1290,179 +1282,192 @@ class assignment_base {
}
$ufields = user_picture::fields('u');
if (!empty($users)) {
$select = "SELECT $ufields,
s.id AS submissionid, s.grade, s.submissioncomment,
s.timemodified, s.timemarked,
COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status ";
$sql = 'FROM {user} u '.
'LEFT JOIN {assignment_submissions} s ON u.id = s.userid
AND s.assignment = '.$this->assignment->id.' '.
'WHERE '.$where.'u.id IN ('.implode(',',$users).') ';
$select = "SELECT $ufields,
s.id AS submissionid, s.grade, s.submissioncomment,
s.timemodified, s.timemarked,
COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status ";
$sql = 'FROM {user} u '.
'LEFT JOIN {assignment_submissions} s ON u.id = s.userid
AND s.assignment = '.$this->assignment->id.' '.
'WHERE '.$where.'u.id IN ('.implode(',',$users).') ';
$ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());
$ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());
$table->pagesize($perpage, count($users));
$table->pagesize($perpage, count($users));
///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
$offset = $page * $perpage;
$strupdate = get_string('update');
$strgrade = get_string('grade');
$grademenu = make_grades_menu($this->assignment->grade);
///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
$offset = $page * $perpage;
$strupdate = get_string('update');
$strgrade = get_string('grade');
$grademenu = make_grades_menu($this->assignment->grade);
if ($ausers !== false) {
$grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers));
$endposition = $offset + $perpage;
$currentposition = 0;
foreach ($ausers as $auser) {
if ($currentposition == $offset && $offset < $endposition) {
$final_grade = $grading_info->items[0]->grades[$auser->id];
$grademax = $grading_info->items[0]->grademax;
$final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2);
$locked_overridden = 'locked';
if ($final_grade->overridden) {
$locked_overridden = 'overridden';
}
if ($ausers !== false) {
$grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers));
$endposition = $offset + $perpage;
$currentposition = 0;
foreach ($ausers as $auser) {
if ($currentposition == $offset && $offset < $endposition) {
$final_grade = $grading_info->items[0]->grades[$auser->id];
$grademax = $grading_info->items[0]->grademax;
$final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2);
$locked_overridden = 'locked';
if ($final_grade->overridden) {
$locked_overridden = 'overridden';
}
/// Calculate user status
$auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified);
$picture = $OUTPUT->user_picture($auser);
/// Calculate user status
$auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified);
$picture = $OUTPUT->user_picture($auser);
if (empty($auser->submissionid)) {
$auser->grade = -1; //no submission yet
}
if (empty($auser->submissionid)) {
$auser->grade = -1; //no submission yet
}
if (!empty($auser->submissionid)) {
$hassubmission = true;
///Prints student answer and student modified date
///attach file or print link to student answer, depending on the type of the assignment.
///Refer to print_student_answer in inherited classes.
if ($auser->timemodified > 0) {
$studentmodified = '<div id="ts'.$auser->id.'">'.$this->print_student_answer($auser->id)
. userdate($auser->timemodified).'</div>';
} else {
$studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
}
///Print grade, dropdown or text
if ($auser->timemarked > 0) {
$teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
if (!empty($auser->submissionid)) {
///Prints student answer and student modified date
///attach file or print link to student answer, depending on the type of the assignment.
///Refer to print_student_answer in inherited classes.
if ($auser->timemodified > 0) {
$studentmodified = '<div id="ts'.$auser->id.'">'.$this->print_student_answer($auser->id)
. userdate($auser->timemodified).'</div>';
if ($final_grade->locked or $final_grade->overridden) {
$grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
} else if ($quickgrade) {
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$menu = html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
$grade = '<div id="g'.$auser->id.'">'. $menu .'</div>';
} else {
$grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
}
} else {
$teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
if ($final_grade->locked or $final_grade->overridden) {
$grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
} else if ($quickgrade) {
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$menu = html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
$grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
} else {
$grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
}
}
///Print Comment
if ($final_grade->locked or $final_grade->overridden) {
$comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($final_grade->str_feedback),15).'</div>';
} else if ($quickgrade) {
$comment = '<div id="com'.$auser->id.'">'
. '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
. $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
} else {
$comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->submissioncomment),15).'</div>';
}
} else {
$studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
}
///Print grade, dropdown or text
if ($auser->timemarked > 0) {
$teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
if ($final_grade->locked or $final_grade->overridden) {
$grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
} else if ($quickgrade) {
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$menu = html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
$grade = '<div id="g'.$auser->id.'">'. $menu .'</div>';
} else {
$grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
}
} else {
$teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
$status = '<div id="st'.$auser->id.'">&nbsp;</div>';
if ($final_grade->locked or $final_grade->overridden) {
$grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
} else if ($quickgrade) {
$grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
$hassubmission = true;
} else if ($quickgrade) { // allow editing
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$menu = html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
$grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
$hassubmission = true;
} else {
$grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
$grade = '<div id="g'.$auser->id.'">-</div>';
}
if ($final_grade->locked or $final_grade->overridden) {
$comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
} else if ($quickgrade) {
$comment = '<div id="com'.$auser->id.'">'
. '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
. $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
} else {
$comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
}
}
///Print Comment
if ($final_grade->locked or $final_grade->overridden) {
$comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($final_grade->str_feedback),15).'</div>';
} else if ($quickgrade) {
$comment = '<div id="com'.$auser->id.'">'
. '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
. $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
$auser->status = 0;
} else {
$comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->submissioncomment),15).'</div>';
}
} else {
$studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
$teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
$status = '<div id="st'.$auser->id.'">&nbsp;</div>';
if ($final_grade->locked or $final_grade->overridden) {
$grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
} else if ($quickgrade) { // allow editing
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$menu = html_writer::select(make_grades_menu($this->assignment->grade), 'menu['.$auser->id.']', $auser->grade, array(-1=>get_string('nograde')), $attributes);
$grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
} else {
$grade = '<div id="g'.$auser->id.'">-</div>';
$auser->status = 1;
}
if ($final_grade->locked or $final_grade->overridden) {
$comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
} else if ($quickgrade) {
$comment = '<div id="com'.$auser->id.'">'
. '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
. $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
} else {
$comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
}
}
$buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
$auser->status = 0;
} else {
$auser->status = 1;
}
///No more buttons, we use popups ;-).
$popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id
. '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;
$buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
$button = $OUTPUT->action_link($popup_url, $buttontext);
///No more buttons, we use popups ;-).
$popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id
. '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;
$status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
$button = $OUTPUT->action_link($popup_url, $buttontext);
$finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
$status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
$outcomes = '';
$finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
if ($uses_outcomes) {
$outcomes = '';
foreach($grading_info->outcomes as $n=>$outcome) {
$outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';
$options = make_grades_menu(-$outcome->scaleid);
if ($uses_outcomes) {
foreach($grading_info->outcomes as $n=>$outcome) {
$outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';
$options = make_grades_menu(-$outcome->scaleid);
if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
$options[0] = get_string('nooutcome', 'grades');
$outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
} else {
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$attributes['id'] = 'outcome_'.$n.'_'.$auser->id;
$outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);
if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
$options[0] = get_string('nooutcome', 'grades');
$outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
} else {
$attributes = array();
$attributes['tabindex'] = $tabindex++;
$attributes['id'] = 'outcome_'.$n.'_'.$auser->id;
$outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);
}
$outcomes .= '</div>';
}
$outcomes .= '</div>';
}
}
$userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $this->context)) . '</a>';
$row = array($picture, $userlink, $grade, $comment, $studentmodified, $teachermodified, $status, $finalgrade);
if ($uses_outcomes) {
$row[] = $outcomes;
$userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $this->context)) . '</a>';
$row = array($picture, $userlink, $grade, $comment, $studentmodified, $teachermodified, $status, $finalgrade);
if ($uses_outcomes) {
$row[] = $outcomes;
}
$table->add_data($row);
}
$table->add_data($row);
$currentposition++;
}
$currentposition++;
}
if ($hassubmission && ($this->assignment->assignmenttype=='upload' || $this->assignment->assignmenttype=='online' || $this->assignment->assignmenttype=='uploadsingle')) { //TODO: this is an ugly hack, where is the plugin spirit? (skodak)
echo html_writer::start_tag('div', array('class' => 'mod-assignment-download-link'));
echo html_writer::link(new moodle_url('/mod/assignment/submissions.php', array('id' => $this->cm->id, 'download' => 'zip')), get_string('downloadall', 'assignment'));
echo html_writer::end_tag('div');
}
$table->print_html(); /// Print the whole table
} else {
if ($filter == self::FILTER_SUBMITTED) {
echo html_writer::tag('div', get_string('nosubmisson', 'assignment'), array('class'=>'nosubmisson'));
} else if ($filter == self::FILTER_REQUIRE_GRADING) {
echo html_writer::tag('div', get_string('norequiregrading', 'assignment'), array('class'=>'norequiregrading'));
}
}
$table->print_html(); /// Print the whole table
/// Print quickgrade form around the table
if ($quickgrade && $table->started_output){
if ($quickgrade && $table->started_output && !empty($users)){
$mailinfopref = false;
if (get_user_preferences('assignment_mailinfo', 1)) {
$mailinfopref = true;

View File

@ -23,6 +23,7 @@
#page-mod-assignment-submissions .submissions .grade,
#page-mod-assignment-submissions .submissions .outcome,
#page-mod-assignment-submissions .submissions .finalgrade {text-align: right;}
#page-mod-assignment-submissions .submissions .header.noheader {display:none;}
#page-mod-assignment-submissions .qgprefs #optiontable {text-align:right;margin-left:auto;}
/** Styles for view.php **/
@ -42,4 +43,6 @@
#page-mod-assignment-submissions.dir-rtl .timemodified,
#page-mod-assignment-submissions.dir-rtl .timemarked {text-align:right;}
#page-mod-assignment-submissions.dir-rtl .mform.optionspref .fitem .fitemtitle {text-align:left;}
#page-mod-assignment-type-uploadsingle-upload.dir-rtl .mdl-left {text-align:right;}
#page-mod-assignment-type-uploadsingle-upload.dir-rtl .mdl-left {text-align:right;}
.mod-assignment-download-link {text-align:right;}

View File

@ -39,7 +39,7 @@ class backup_choice_activity_structure_step extends backup_activity_structure_st
// Define each element separated
$choice = new backup_nested_element('choice', array('id'), array(
'name', 'intro', 'introformat', 'publish',
'showresults', 'display', 'allowupdate', 'allowunanswered',
'showresults', 'display', 'allowupdate', 'showunanswered',
'limitanswers', 'timeopen', 'timeclose', 'timemodified',
'completionsubmit'));

View File

@ -962,7 +962,16 @@ function data_user_outline($course, $user, $mod, $data) {
} else if ($grade) {
$result = new stdClass();
$result->info = get_string('grade') . ': ' . $grade->str_long_grade;
$result->time = $grade->dategraded;
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
return $result;
}
return NULL;
@ -1378,11 +1387,14 @@ function data_rating_permissions($options) {
function data_rating_validate($params) {
global $DB, $USER;
if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params) || !array_key_exists('rateduserid', $params)) {
if (!array_key_exists('itemid', $params)
|| !array_key_exists('context', $params)
|| !array_key_exists('rateduserid', $params)
|| !array_key_exists('scaleid', $params)) {
throw new rating_exception('missingparameter');
}
$datasql = "SELECT d.id as did, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid
$datasql = "SELECT d.id as did, d.scale, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid
FROM {data_records} r
JOIN {data} d ON r.dataid = d.id
WHERE r.id = :itemid";
@ -1392,16 +1404,40 @@ function data_rating_validate($params) {
throw new rating_exception('invaliditemid');
}
if ($info->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own glossary entry
throw new rating_exception('nopermissiontorate');
}
if ($params['rateduserid'] != $info->userid) {
if ($info->userid != $params['rateduserid']) {
//supplied user ID doesnt match the user ID from the database
throw new rating_exception('invaliduserid');
}
//check that the submitted rating is valid for the scale
if ($params['rating'] < 0) {
throw new rating_exception('invalidnum');
} else if ($info->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$params['scaleid']));
if ($scalerecord) {
$scalearray = explode(',', $scalerecord->scale);
if ($params['rating'] > count($scalearray)) {
throw new rating_exception('invalidnum');
}
} else {
throw new rating_exception('invalidscaleid');
}
} else if ($params['rating'] > $info->scale) {
//if its numeric and submitted rating is above maximum
throw new rating_exception('invalidnum');
}
if ($info->approval && !$info->approved) {
//database requires approval but this item isnt approved
throw new rating_exception('nopermissiontorate');

View File

@ -27,6 +27,9 @@ $messageproviders = array (
/// Submitting a feedback
'submission' => array (
),
/// Message to nonrespondents
'message' => array (
)
);

View File

@ -75,8 +75,8 @@
foreach ($messageuser as $userid) {
$senduser = $DB->get_record('user', array('id'=>$userid));
$eventdata = new stdClass();
$eventdata->name = 'feedback';
$eventdata->component = 'mod';
$eventdata->name = 'message';
$eventdata->component = 'mod_feedback';
$eventdata->userfrom = $USER;
$eventdata->userto = $senduser;
$eventdata->subject = $subject;

View File

@ -9,7 +9,7 @@
*/
$module->version = 2010112302; // The current module version (Date: YYYYMMDDXX)
$module->version = 2011051600; // The current module version (Date: YYYYMMDDXX)
$module->requires = 2010080300; // Requires this Moodle version
$feedback_version_intern = 1; //this version is used for restore older backups
$module->cron = 0; // Period for cron to check this module (secs)

View File

@ -1131,7 +1131,16 @@ function forum_user_outline($course, $user, $mod, $forum) {
} else if ($grade) {
$result = new stdClass();
$result->info = get_string('grade') . ': ' . $grade->str_long_grade;
$result->time = $grade->dategraded;
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
return $result;
}
return NULL;
@ -3470,11 +3479,14 @@ function forum_rating_permissions($contextid) {
function forum_rating_validate($params) {
global $DB, $USER;
if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params) || !array_key_exists('rateduserid', $params)) {
if (!array_key_exists('itemid', $params)
|| !array_key_exists('context', $params)
|| !array_key_exists('rateduserid', $params)
|| !array_key_exists('scaleid', $params)) {
throw new rating_exception('missingparameter');
}
$forumsql = "SELECT f.id as fid, f.course, d.id as did, p.userid as userid, p.created, f.assesstimestart, f.assesstimefinish, d.groupid
$forumsql = "SELECT f.id as fid, f.course, f.scale, d.id as did, p.userid as userid, p.created, f.assesstimestart, f.assesstimefinish, d.groupid
FROM {forum_posts} p
JOIN {forum_discussions} d ON p.discussion = d.id
JOIN {forum} f ON d.forum = f.id
@ -3485,16 +3497,40 @@ function forum_rating_validate($params) {
throw new rating_exception('invaliditemid');
}
if ($info->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own post
throw new rating_exception('nopermissiontorate');
}
if ($params['rateduserid'] != $info->userid) {
if ($info->userid != $params['rateduserid']) {
//supplied user ID doesnt match the user ID from the database
throw new rating_exception('invaliduserid');
}
//check that the submitted rating is valid for the scale
if ($params['rating'] < 0) {
throw new rating_exception('invalidnum');
} else if ($info->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$params['scaleid']));
if ($scalerecord) {
$scalearray = explode(',', $scalerecord->scale);
if ($params['rating'] > count($scalearray)) {
throw new rating_exception('invalidnum');
}
} else {
throw new rating_exception('invalidscaleid');
}
} else if ($params['rating'] > $info->scale) {
//if its numeric and submitted rating is above maximum
throw new rating_exception('invalidnum');
}
//check the item we're rating was created in the assessable time window
if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) {
if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) {

View File

@ -243,7 +243,16 @@ function glossary_user_outline($course, $user, $mod, $glossary) {
} else if ($grade) {
$result = new stdClass();
$result->info = get_string('grade') . ': ' . $grade->str_long_grade;
$result->time = $grade->dategraded;
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
return $result;
}
return NULL;
@ -484,11 +493,14 @@ function glossary_rating_permissions($options) {
function glossary_rating_validate($params) {
global $DB, $USER;
if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params) || !array_key_exists('rateduserid', $params)) {
if (!array_key_exists('itemid', $params)
|| !array_key_exists('context', $params)
|| !array_key_exists('rateduserid', $params)
|| !array_key_exists('scaleid', $params)) {
throw new rating_exception('missingparameter');
}
$glossarysql = "SELECT g.id as gid, e.userid as userid, e.approved, e.timecreated, g.assesstimestart, g.assesstimefinish
$glossarysql = "SELECT g.id as gid, g.scale, e.userid as userid, e.approved, e.timecreated, g.assesstimestart, g.assesstimefinish
FROM {glossary_entries} e
JOIN {glossary} g ON e.glossaryid = g.id
WHERE e.id = :itemid";
@ -498,16 +510,40 @@ function glossary_rating_validate($params) {
throw new rating_exception('invaliditemid');
}
if ($info->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own glossary entry
throw new rating_exception('nopermissiontorate');
}
if ($params['rateduserid'] != $info->userid) {
if ($info->userid != $params['rateduserid']) {
//supplied user ID doesnt match the user ID from the database
throw new rating_exception('invaliduserid');
}
//check that the submitted rating is valid for the scale
if ($params['rating'] < 0) {
throw new rating_exception('invalidnum');
} else if ($info->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$params['scaleid']));
if ($scalerecord) {
$scalearray = explode(',', $scalerecord->scale);
if ($params['rating'] > count($scalearray)) {
throw new rating_exception('invalidnum');
}
} else {
throw new rating_exception('invalidscaleid');
}
} else if ($params['rating'] > $info->scale) {
//if its numeric and submitted rating is above maximum
throw new rating_exception('invalidnum');
}
if (!$info->approved) {
//item isnt approved
throw new rating_exception('nopermissiontorate');

View File

@ -46,41 +46,59 @@ if ($mode !== 'display') {
}
$PAGE->set_url($url);
$attempt = new stdClass();
$user = new stdClass();
$attemptid = optional_param('attemptid', 0, PARAM_INT);
if ($attemptid > 0) {
$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid));
$answer = $DB->get_record('lesson_answers', array('lessonid' => $lesson->id, 'pageid' => $attempt->pageid));
$user = $DB->get_record('user', array('id' => $attempt->userid));
$scoreoptions = array();
if ($lesson->custom) {
$i = $answer->score;
while ($i >= 0) {
$scoreoptions[$i] = (string)$i;
$i--;
}
} else {
$scoreoptions[0] = get_string('nocredit', 'lesson');
$scoreoptions[1] = get_string('credit', 'lesson');
}
}
/// Handle any preprocessing before header is printed - based on $mode
switch ($mode) {
case 'grade':
// Grading form - get the necessary data
require_sesskey();
$attemptid = required_param('attemptid', PARAM_INT);
if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid))) {
if (empty($attempt)) {
print_error('cannotfindattempt', 'lesson');
}
$page = $lesson->load_page($attempt->pageid);
if (!$user = $DB->get_record('user', array('id' => $attempt->userid))) {
if (empty($user)) {
print_error('cannotfinduser', 'lesson');
}
if (!$answer = $DB->get_record('lesson_answers', array('lessonid' => $lesson->id, 'pageid' => $page->id))) {
if (empty($answer)) {
print_error('cannotfindanswer', 'lesson');
}
break;
case 'update':
require_sesskey();
$mform = new essay_grading_form();
if (empty($attempt)) {
print_error('cannotfindattempt', 'lesson');
}
if (empty($user)) {
print_error('cannotfinduser', 'lesson');
}
$mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user));
if ($mform->is_cancelled()) {
redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id");
}
if ($form = $mform->get_data()) {
if (optional_param('cancel', false, PARAM_RAW)) {
redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id");
}
$attemptid = required_param('attemptid', PARAM_INT);
$score = optional_param('score', 0, PARAM_INT);
if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid))) {
print_error('cannotfindattempt', 'lesson');
}
if (!$grades = $DB->get_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$attempt->userid), 'completed', '*', $attempt->retry, 1)) {
print_error('cannotfindgrade', 'lesson');
}
@ -89,7 +107,7 @@ switch ($mode) {
$essayinfo = unserialize($attempt->useranswer);
$essayinfo->graded = 1;
$essayinfo->score = $score;
$essayinfo->score = $form->score;
$essayinfo->response = clean_param($form->response, PARAM_RAW);
$essayinfo->sent = 0;
if (!$lesson->custom && $essayinfo->score == 1) {
@ -368,22 +386,9 @@ switch ($mode) {
case 'grade':
// Grading form
// Expects the following to be set: $attemptid, $answer, $user, $page, $attempt
$essayinfo = unserialize($attempt->useranswer);
$options = array();
if ($lesson->custom) {
$i = $answer->score;
while ($i >= 0) {
$options[$i] = (string)$i;
$i--;
}
} else {
$options[0] = get_string('nocredit', 'lesson');
$options[1] = get_string('credit', 'lesson');
}
$mform = new essay_grading_form(null, array('scoreoptions'=>$options, 'user'=>$user));
$mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user));
$data = new stdClass;
$data->id = $cm->id;
$data->attemptid = $attemptid;

View File

@ -166,8 +166,15 @@ function lesson_user_outline($course, $user, $mod, $lesson) {
} else {
$grade = reset($grades->items[0]->grades);
$return->info = get_string("grade") . ': ' . $grade->str_long_grade;
$return->time = $grade->dategraded;
$return->info = get_string("no")." ".get_string("attempts", "lesson");
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
}
return $return;
}

View File

@ -381,7 +381,16 @@ function quiz_user_outline($course, $user, $mod, $quiz) {
$result = new stdClass;
$result->info = get_string('grade') . ': ' . $grade->str_long_grade;
$result->time = $grade->dategraded;
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
return $result;
}

View File

@ -294,7 +294,16 @@ function scorm_user_outline($course, $user, $mod, $scorm) {
$grade = reset($grades->items[0]->grades);
$result = new stdClass();
$result->info = get_string('grade') . ': '. $grade->str_long_grade;
$result->time = $grade->dategraded;
//datesubmitted == time created. dategraded == time modified or time overridden
//if grade was last modified by the user themselves use date graded. Otherwise use date submitted
//TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704
if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) {
$result->time = $grade->dategraded;
} else {
$result->time = $grade->datesubmitted;
}
return $result;
}
return null;

View File

@ -30,10 +30,10 @@
defined('MOODLE_INTERNAL') || die();
$version = 2011051100.00; // YYYYMMDD = weekly release date of this DEV branch
$version = 2011051800.00; // YYYYMMDD = weekly release date of this DEV branch
// RR = release increments - 00 in DEV branches
// .XX = incremental changes
$release = '2.1dev (Build: 20110511)'; // Human-friendly version name
$release = '2.1dev (Build: 20110518)'; // Human-friendly version name
$maturity = MATURITY_ALPHA; // this version's maturity level