Merge remote-tracking branch 'moodle/master' into MDL-20636_master_new_question_engine

Conflicts:
	lib/db/upgrade.php
	mod/quiz/lib.php
This commit is contained in:
Tim Hunt 2011-06-06 17:14:59 +01:00
commit 54771d89d1
290 changed files with 4637 additions and 1419 deletions

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;
@ -2767,6 +2772,8 @@ function assignment_grade_item_delete($assignment) {
/**
* Returns the users with data in one assignment (students and teachers)
*
* @todo: deprecated - to be deleted in 2.2
*
* @param $assignmentid int
* @return array of user objects
*/

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

@ -430,7 +430,8 @@ function chat_cron () {
* Returns the users with data in one chat
* (users with records in chat_messages, students)
*
* @global object
* @todo: deprecated - to be deleted in 2.2
*
* @param int $chatid
* @param int $groupid
* @return array

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

@ -591,6 +591,8 @@ function choice_delete_instance($id) {
* Returns the users with data in one choice
* (users with records in choice_responses, students)
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $choiceid
* @return array
*/

View file

@ -40,7 +40,7 @@ class mod_choice_renderer extends plugin_renderer_base {
$layoutclass = 'vertical';
}
$target = new moodle_url('/mod/choice/view.php');
$attributes = array('method'=>'POST', 'target'=>$target, 'class'=> $layoutclass);
$attributes = array('method'=>'POST', 'action'=>$target, 'class'=> $layoutclass);
$html = html_writer::start_tag('form', $attributes);
$html .= html_writer::start_tag('ul', array('class'=>'choices' ));

View file

@ -69,7 +69,7 @@ class backup_data_activity_structure_step extends backup_activity_structure_step
$ratings = new backup_nested_element('ratings');
$rating = new backup_nested_element('rating', array('id'), array(
'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
'component', 'ratingarea', 'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
// Build the tree
$data->add_child($fields);
@ -99,8 +99,10 @@ class backup_data_activity_structure_step extends backup_activity_structure_step
$content->set_source_table('data_content', array('recordid' => backup::VAR_PARENTID));
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'itemid' => backup::VAR_PARENTID));
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'itemid' => backup::VAR_PARENTID,
'component' => 'mod_data',
'ratingarea' => 'entry'));
$rating->set_source_alias('rating', 'value');
}

View file

@ -138,6 +138,14 @@ class restore_data_activity_structure_step extends restore_activity_structure_st
$data->timecreated = $this->apply_date_offset($data->timecreated);
$data->timemodified = $this->apply_date_offset($data->timemodified);
// We need to check that component and ratingarea are both set here.
if (empty($data->component)) {
$data->component = 'mod_data';
}
if (empty($data->ratingarea)) {
$data->ratingarea = 'entry';
}
$newitemid = $DB->insert_record('rating', $data);
}

View file

@ -315,6 +315,29 @@ function xmldb_data_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2010100101, 'data');
}
if ($oldversion < 2011052300) {
// rating.component and rating.ratingarea have now been added as mandatory fields.
// Presently you can only rate data entries so component = 'mod_data' and ratingarea = 'entry'
// for all ratings with a data context.
// We want to update all ratings that belong to a data context and don't already have a
// component set.
// This could take a while reset upgrade timeout to 5 min
upgrade_set_timeout(60 * 20);
$sql = "UPDATE {rating}
SET component = 'mod_data', ratingarea = 'entry'
WHERE contextid IN (
SELECT ctx.id
FROM {context} ctx
JOIN {course_modules} cm ON cm.id = ctx.instanceid
JOIN {modules} m ON m.id = cm.module
WHERE ctx.contextlevel = 70 AND
m.name = 'data'
) AND component = 'unknown'";
$DB->execute($sql);
upgrade_mod_savepoint(true, 2011052300, 'data');
}
return true;
}

View file

@ -527,10 +527,10 @@ function data_generate_default_template(&$data, $template, $recordid=0, $form=fa
$cell->attributes['class'] = 'controls';
$table->data[] = new html_table_row(array($cell));
} else if ($template == 'asearchtemplate') {
$row = new html_table_row(get_string('authorfirstname', 'data').': ', '##firstname##');
$row = new html_table_row(array(get_string('authorfirstname', 'data').': ', '##firstname##'));
$row->attributes['class'] = 'searchcontrols';
$table->data[] = $row;
$row = new html_table_row(get_string('authorlastname', 'data').': ', '##lastname##');
$row = new html_table_row(array(get_string('authorlastname', 'data').': ', '##lastname##'));
$row->attributes['class'] = 'searchcontrols';
$table->data[] = $row;
}
@ -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;
@ -1007,9 +1016,10 @@ function data_get_user_grades($data, $userid=0) {
global $CFG;
require_once($CFG->dirroot.'/rating/lib.php');
$rm = new rating_manager();
$ratingoptions = new stdclass();
$ratingoptions = new stdClass;
$ratingoptions->component = 'mod_data';
$ratingoptions->ratingarea = 'entry';
$ratingoptions->modulename = 'data';
$ratingoptions->moduleid = $data->id;
@ -1019,6 +1029,7 @@ function data_get_user_grades($data, $userid=0) {
$ratingoptions->itemtable = 'data_records';
$ratingoptions->itemtableusercolumn = 'userid';
$rm = new rating_manager();
return $rm->get_user_grades($ratingoptions);
}
@ -1135,25 +1146,46 @@ function data_grade_item_delete($data) {
/**
* returns a list of participants of this database
*
* @global object
* Returns the users with data in one data
* (users with records in data_records, data_comments and ratings)
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $dataid
* @return array
*/
function data_get_participants($dataid) {
// Returns the users with data in one data
// (users with records in data_records, data_comments and ratings)
global $DB;
$records = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u, {data_records} r
WHERE r.dataid = ? AND u.id = r.userid", array($dataid));
$params = array('dataid' => $dataid);
$comments = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u, {data_records} r, {comments} c
WHERE r.dataid = ? AND u.id = r.userid AND r.id = c.itemid AND c.commentarea='database_entry'", array($dataid));
$sql = "SELECT DISTINCT u.id, u.id
FROM {user} u,
{data_records} r
WHERE r.dataid = :dataid AND
u.id = r.userid";
$records = $DB->get_records_sql($sql, $params);
$ratings = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u, {data_records} r, {ratings} a
WHERE r.dataid = ? AND u.id = r.userid AND r.id = a.itemid", array($dataid));
$sql = "SELECT DISTINCT u.id, u.id
FROM {user} u,
{data_records} r,
{comments} c
WHERE r.dataid = ? AND
u.id = r.userid AND
r.id = c.itemid AND
c.commentarea = 'database_entry'";
$comments = $DB->get_records_sql($sql, $params);
$sql = "SELECT DISTINCT u.id, u.id
FROM {user} u,
{data_records} r,
{ratings} a
WHERE r.dataid = ? AND
u.id = r.userid AND
r.id = a.itemid AND
a.component = 'mod_data' AND
a.ratingarea = 'entry'";
$ratings = $DB->get_records_sql($sql, $params);
$participants = array();
@ -1348,20 +1380,23 @@ function data_print_template($template, $records, $data, $search='', $page=0, $r
/**
* Return rating related permissions
* @param string $options the context id
*
* @param string $contextid the context id
* @param string $component the component to get rating permissions for
* @param string $ratingarea the rating area to get permissions for
* @return array an associative array of the user's rating permissions
*/
function data_rating_permissions($options) {
$contextid = $options;
$context = get_context_instance_by_id($contextid);
if (!$context) {
print_error('invalidcontext');
function data_rating_permissions($contextid, $component, $ratingarea) {
$context = get_context_instance_by_id($contextid, MUST_EXIST);
if ($component != 'mod_data' || $ratingarea != 'entry') {
return null;
} else {
$ret = new stdclass();
return array('view'=>has_capability('mod/data:viewrating',$context), 'viewany'=>has_capability('mod/data:viewanyrating',$context), 'viewall'=>has_capability('mod/data:viewallratings',$context), 'rate'=>has_capability('mod/data:rate',$context));
}
return array(
'view' => has_capability('mod/data:viewrating',$context),
'viewany' => has_capability('mod/data:viewanyrating',$context),
'viewall' => has_capability('mod/data:viewallratings',$context),
'rate' => has_capability('mod/data:rate',$context)
);
}
/**
@ -1378,11 +1413,22 @@ 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)) {
throw new rating_exception('missingparameter');
// Check the component is mod_data
if ($params['component'] != 'mod_data') {
throw new rating_exception('invalidcomponent');
}
$datasql = "SELECT d.id as did, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid
// Check the ratingarea is entry (the only rating area in data module)
if ($params['ratingarea'] != 'entry') {
throw new rating_exception('invalidratingarea');
}
// Check the rateduserid is not the current user .. you can't rate your own entries
if ($params['rateduserid'] == $USER->id) {
throw new rating_exception('nopermissiontorate');
}
$datasql = "SELECT d.id as dataid, 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,14 +1438,33 @@ function data_rating_validate($params) {
throw new rating_exception('invaliditemid');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own glossary entry
throw new rating_exception('nopermissiontorate');
if ($info->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
if ($params['rateduserid'] != $info->userid) {
//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
// lower limit
if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) {
throw new rating_exception('invalidnum');
}
// upper limit
if ($info->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$info->scale));
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) {
@ -1407,30 +1472,24 @@ function data_rating_validate($params) {
throw new rating_exception('nopermissiontorate');
}
//check the item we're rating was created in the assessable time window
// 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) {
throw new rating_exception('notavailable');
}
}
$dataid = $info->did;
$groupid = $info->groupid;
$courseid = $info->course;
$course = $DB->get_record('course', array('id'=>$info->course), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('data', $info->dataid, $course->id, false, MUST_EXIST);
$context = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST);
$cm = get_coursemodule_from_instance('data', $dataid);
if (empty($cm)) {
throw new rating_exception('unknowncontext');
}
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
//if the supplied context doesnt match the item's context
if (empty($context) || $context->id != $params['context']->id) {
// if the supplied context doesnt match the item's context
if ($context->id != $params['context']->id) {
throw new rating_exception('invalidcontext');
}
// Make sure groups allow this user to see the item they're rating
$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
$groupid = $info->groupid;
if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used
if (!groups_group_exists($groupid)) { // Can't find group
throw new rating_exception('cannotfindgroup');//something is wrong
@ -1640,7 +1699,7 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
*/
function data_print_ratings($data, $record) {
global $OUTPUT;
if( !empty($record->rating) ){
if (!empty($record->rating)){
echo $OUTPUT->render($record->rating);
}
}
@ -2487,7 +2546,9 @@ function data_reset_userdata($data) {
WHERE d.course=?";
$rm = new rating_manager();
$ratingdeloptions = new stdclass();
$ratingdeloptions = new stdClass;
$ratingdeloptions->component = 'mod_data';
$ratingdeloptions->ratingarea = 'entry';
// delete entries if requested
if (!empty($data->reset_data)) {

View file

@ -5,8 +5,8 @@
// This fragment is called by /admin/index.php
////////////////////////////////////////////////////////////////////////////////
$module->version = 2010100101;
$module->requires = 2010080300; // Requires this Moodle version
$module->version = 2011052300;
$module->requires = 2011052300; // Requires this Moodle version
$module->cron = 60;

View file

@ -668,10 +668,11 @@ if ($showactivity) {
//data_print_template() only adds ratings for singletemplate which is why we're attaching them here
//attach ratings to data records
require_once($CFG->dirroot.'/rating/lib.php');
if ($data->assessed!=RATING_AGGREGATE_NONE) {
$ratingoptions = new stdclass();
if ($data->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass;
$ratingoptions->context = $context;
$ratingoptions->component = 'mod_data';
$ratingoptions->ratingarea = 'entry';
$ratingoptions->items = $records;
$ratingoptions->aggregate = $data->assessed;//the aggregation method
$ratingoptions->scaleid = $data->scale;

View file

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

View file

@ -467,6 +467,7 @@ function feedback_cron () {
}
/**
* @todo: deprecated - to be deleted in 2.2
* @return bool false
*/
function feedback_get_participants($feedbackid) {

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

@ -205,6 +205,8 @@ function folder_user_complete($course, $user, $mod, $folder) {
/**
* Returns the users with data in one folder
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $folderid
* @return bool false
*/

View file

@ -63,7 +63,7 @@ class backup_forum_activity_structure_step extends backup_activity_structure_ste
$ratings = new backup_nested_element('ratings');
$rating = new backup_nested_element('rating', array('id'), array(
'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
'component', 'ratingarea', 'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
$subscriptions = new backup_nested_element('subscriptions');
@ -125,8 +125,10 @@ class backup_forum_activity_structure_step extends backup_activity_structure_ste
$track->set_source_table('forum_track_prefs', array('forumid' => backup::VAR_PARENTID));
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'itemid' => backup::VAR_PARENTID));
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'component' => 'mod_forum',
'ratingarea' => 'post',
'itemid' => backup::VAR_PARENTID));
$rating->set_source_alias('rating', 'value');
}

View file

@ -126,6 +126,14 @@ class restore_forum_activity_structure_step extends restore_activity_structure_s
$data->timecreated = $this->apply_date_offset($data->timecreated);
$data->timemodified = $this->apply_date_offset($data->timemodified);
// We need to check that component and ratingarea are both set here.
if (empty($data->component)) {
$data->component = 'mod_forum';
}
if (empty($data->ratingarea)) {
$data->ratingarea = 'post';
}
$newitemid = $DB->insert_record('rating', $data);
}

View file

@ -315,6 +315,28 @@ function xmldb_forum_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2010091900, 'forum');
}
if ($oldversion < 2011052300) {
// rating.component and rating.ratingarea have now been added as mandatory fields.
// Presently you can only rate forum posts so component = 'mod_forum' and ratingarea = 'post'
// for all ratings with a forum context.
// We want to update all ratings that belong to a forum context and don't already have a
// component set.
// This could take a while reset upgrade timeout to 5 min
upgrade_set_timeout(60 * 20);
$sql = "UPDATE {rating}
SET component = 'mod_forum', ratingarea = 'post'
WHERE contextid IN (
SELECT ctx.id
FROM {context} ctx
JOIN {course_modules} cm ON cm.id = ctx.instanceid
JOIN {modules} m ON m.id = cm.module
WHERE ctx.contextlevel = 70 AND
m.name = 'forum'
) AND component = 'unknown'";
$DB->execute($sql);
upgrade_mod_savepoint(true, 2011052300, 'forum');
}
return true;
}

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;
@ -1436,25 +1445,25 @@ function forum_print_recent_activity($course, $viewfullnames, $timestart) {
* @param int $userid optional user id, 0 means all users
* @return array array of grades, false if none
*/
function forum_get_user_grades($forum, $userid=0) {
function forum_get_user_grades($forum, $userid = 0) {
global $CFG;
require_once($CFG->dirroot.'/rating/lib.php');
$rm = new rating_manager();
$ratingoptions = new stdclass();
$ratingoptions = new stdClass;
$ratingoptions->component = 'mod_forum';
$ratingoptions->ratingarea = 'post';
//need these to work backwards to get a context id. Is there a better way to get contextid from a module instance?
$ratingoptions->modulename = 'forum';
$ratingoptions->moduleid = $forum->id;
//$ratingoptions->cmidnumber = $forum->cmidnumber;
$ratingoptions->userid = $userid;
$ratingoptions->aggregationmethod = $forum->assessed;
$ratingoptions->scaleid = $forum->scale;
$ratingoptions->itemtable = 'forum_posts';
$ratingoptions->itemtableusercolumn = 'userid';
$rm = new rating_manager();
return $rm->get_user_grades($ratingoptions);
}
@ -1577,8 +1586,8 @@ function forum_grade_item_delete($forum) {
* Returns the users with data in one forum
* (users with records in forum_subscriptions, forum_posts, students)
*
* @global object
* @global object
* @todo: deprecated - to be deleted in 2.2
*
* @param int $forumid
* @return mixed array or false if none
*/
@ -1586,31 +1595,35 @@ function forum_get_participants($forumid) {
global $CFG, $DB;
$params = array('forumid' => $forumid);
//Get students from forum_subscriptions
$st_subscriptions = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u,
{forum_subscriptions} s
WHERE s.forum = ? AND
u.id = s.userid", array($forumid));
$sql = "SELECT DISTINCT u.id, u.id
FROM {user} u,
{forum_subscriptions} s
WHERE s.forum = :forumid AND
u.id = s.userid";
$st_subscriptions = $DB->get_records_sql($sql, $params);
//Get students from forum_posts
$st_posts = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u,
{forum_discussions} d,
{forum_posts} p
WHERE d.forum = ? AND
p.discussion = d.id AND
u.id = p.userid", array($forumid));
$sql = "SELECT DISTINCT u.id, u.id
FROM {user} u,
{forum_discussions} d,
{forum_posts} p
WHERE d.forum = :forumid AND
p.discussion = d.id AND
u.id = p.userid";
$st_posts = $DB->get_records_sql($sql, $params);
//Get students from the ratings table
$st_ratings = $DB->get_records_sql("SELECT DISTINCT u.id, u.id
FROM {user} u,
{forum_discussions} d,
{forum_posts} p,
{ratings} r
WHERE d.forum = ? AND
p.discussion = d.id AND
r.post = p.id AND
u.id = r.userid", array($forumid));
$sql = "SELECT DISTINCT r.userid, r.userid AS id
FROM {forum_discussions} d
JOIN {forum_posts} p ON p.discussion = d.id
JOIN {rating} r on r.itemid = p.id
WHERE d.forum = :forumid AND
r.component = 'mod_forum' AND
r.ratingarea = 'post'";
$st_ratings = $DB->get_records_sql($sql, $params);
//Add st_posts to st_subscriptions
if ($st_posts) {
@ -2041,29 +2054,29 @@ function forum_search_posts($searchterms, $courseid=0, $limitfrom=0, $limitnum=5
/**
* Returns a list of ratings for a particular post - sorted.
*
* @global object
* @global object
* TODO: Check if this function is actually used anywhere.
* Up until the fix for MDL-27471 this function wasn't even returning.
*
* @param stdClass $context
* @param int $postid
* @param string $sort
* @return array Array of ratings or false
*/
function forum_get_ratings($context, $postid, $sort="u.firstname ASC") {
global $PAGE;
$options = new stdclass();
$options->context = $PAGE->context;
function forum_get_ratings($context, $postid, $sort = "u.firstname ASC") {
$options = new stdClass;
$options->context = $context;
$options->component = 'mod_forum';
$options->ratingarea = 'post';
$options->itemid = $postid;
$options->sort = "ORDER BY $sort";
$rm = new rating_manager();
$rm->get_all_ratings_for_item($options);
return $rm->get_all_ratings_for_item($options);
}
/**
* Returns a list of all new posts that have not been mailed yet
*
* @global object
* @global object
* @param int $starttime posts created after this time
* @param int $endtime posts created before this
* @param int $now used for timed discussions only
@ -2447,29 +2460,35 @@ function forum_count_discussions($forum, $cm, $course) {
/**
* How many posts by other users are unrated by a given user in the given discussion?
*
* @global object
* @global object
* TODO: Is this function still used anywhere?
*
* @param int $discussionid
* @param int $userid
* @return mixed
*/
function forum_count_unrated_posts($discussionid, $userid) {
global $CFG, $DB;
if ($posts = $DB->get_record_sql("SELECT count(*) as num
FROM {forum_posts}
WHERE parent > 0
AND discussion = ?
AND userid <> ? ", array($discussionid, $userid))) {
if ($rated = $DB->get_record_sql("SELECT count(*) as num
FROM {forum_posts} p,
{rating} r
WHERE p.discussion = ?
AND p.id = r.itemid
AND r.userid = ?", array($discussionid, $userid))) {
$difference = $posts->num - $rated->num;
if ($difference > 0) {
return $difference;
$sql = "SELECT COUNT(*) as num
FROM {forum_posts}
WHERE parent > 0
AND discussion = :discussionid
AND userid <> :userid";
$params = array('discussionid' => $discussionid, 'userid' => $userid);
$posts = $DB->get_record_sql($sql, $params);
if ($posts) {
$sql = "SELECT count(*) as num
FROM {forum_posts} p,
{rating} r
WHERE p.discussion = :discussionid AND
p.id = r.itemid AND
r.userid = userid AND
r.component = 'mod_forum' AND
r.ratingarea = 'post'";
$rated = $DB->get_record_sql($sql, $params);
if ($rated) {
if ($posts->num > $rated->num) {
return $posts->num - $rated->num;
} else {
return 0; // Just in case there was a counting error
}
@ -3442,24 +3461,31 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa
/**
* Return rating related permissions
*
* @param string $options the context id
* @return array an associative array of the user's rating permissions
*/
function forum_rating_permissions($contextid) {
$context = get_context_instance_by_id($contextid);
if (!$context) {
print_error('invalidcontext');
function forum_rating_permissions($contextid, $component, $ratingarea) {
$context = get_context_instance_by_id($contextid, MUST_EXIST);
if ($component != 'mod_forum' || $ratingarea != 'post') {
// We don't know about this component/ratingarea so just return null to get the
// default restrictive permissions.
return null;
} else {
return array('view'=>has_capability('mod/forum:viewrating',$context), 'viewany'=>has_capability('mod/forum:viewanyrating',$context), 'viewall'=>has_capability('mod/forum:viewallratings',$context), 'rate'=>has_capability('mod/forum:rate',$context));
}
return array(
'view' => has_capability('mod/forum:viewrating', $context),
'viewany' => has_capability('mod/forum:viewanyrating', $context),
'viewall' => has_capability('mod/forum:viewallratings', $context),
'rate' => has_capability('mod/forum:rate', $context)
);
}
/**
* Validates a submitted rating
* @param array $params submitted data
* context => object the context in which the rated items exists [required]
* component => The component for this module - should always be mod_forum [required]
* ratingarea => object the context in which the rated items exists [required]
* itemid => int the ID of the object being rated [required]
* scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required]
* rating => int the submitted rating [required]
@ -3470,81 +3496,84 @@ 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)) {
throw new rating_exception('missingparameter');
// Check the component is mod_forum
if ($params['component'] != 'mod_forum') {
throw new rating_exception('invalidcomponent');
}
$forumsql = "SELECT f.id as fid, f.course, 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
WHERE p.id = :itemid";
$forumparams = array('itemid'=>$params['itemid']);
if (!$info = $DB->get_record_sql($forumsql, $forumparams)) {
//item doesn't exist
throw new rating_exception('invaliditemid');
// Check the ratingarea is post (the only rating area in forum)
if ($params['ratingarea'] != 'post') {
throw new rating_exception('invalidratingarea');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own post
// Check the rateduserid is not the current user .. you can't rate your own posts
if ($params['rateduserid'] == $USER->id) {
throw new rating_exception('nopermissiontorate');
}
if ($params['rateduserid'] != $info->userid) {
//supplied user ID doesnt match the user ID from the database
throw new rating_exception('invaliduserid');
// Fetch all the related records ... we need to do this anyway to call forum_user_can_see_post
$post = $DB->get_record('forum_posts', array('id' => $params['itemid'], 'userid' => $params['rateduserid']), '*', MUST_EXIST);
$discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion), '*', MUST_EXIST);
$forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('forum', $forum->id, $course->id , false, MUST_EXIST);
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
// Make sure the context provided is the context of the forum
if ($context->id != $params['context']->id) {
throw new rating_exception('invalidcontext');
}
//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) {
if ($forum->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
// check the item we're rating was created in the assessable time window
if (!empty($forum->assesstimestart) && !empty($forum->assesstimefinish)) {
if ($post->created < $forum->assesstimestart || $post->created > $forum->assesstimefinish) {
throw new rating_exception('notavailable');
}
}
$forumid = $info->fid;
$discussionid = $info->did;
$groupid = $info->groupid;
$courseid = $info->course;
//check that the submitted rating is valid for the scale
$cm = get_coursemodule_from_instance('forum', $forumid);
if (empty($cm)) {
throw new rating_exception('unknowncontext');
// lower limit
if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) {
throw new rating_exception('invalidnum');
}
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
//if the supplied context doesnt match the item's context
if (empty($context) || $context->id != $params['context']->id) {
throw new rating_exception('invalidcontext');
// upper limit
if ($forum->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$forum->scale));
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'] > $forum->scale) {
//if its numeric and submitted rating is above maximum
throw new rating_exception('invalidnum');
}
// Make sure groups allow this user to see the item they're rating
$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used
if (!groups_group_exists($groupid)) { // Can't find group
if ($discussion->groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used
if (!groups_group_exists($discussion->groupid)) { // Can't find group
throw new rating_exception('cannotfindgroup');//something is wrong
}
if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) {
if (!groups_is_member($discussion->groupid) and !has_capability('moodle/site:accessallgroups', $context)) {
// do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS
throw new rating_exception('notmemberofgroup');
}
}
//need to load the full objects here as ajax scripts don't like
//the debugging messages produced by forum_user_can_see_post() if you just supply IDs
if (!$forum = $DB->get_record('forum',array('id'=>$forumid))) {
throw new rating_exception('invalidrecordunknown');
}
if (!$post = $DB->get_record('forum_posts',array('id'=>$params['itemid']))) {
throw new rating_exception('invalidrecordunknown');
}
if (!$discussion = $DB->get_record('forum_discussions',array('id'=>$discussionid))) {
throw new rating_exception('invalidrecordunknown');
}
//perform some final capability checks
if( !forum_user_can_see_post($forum, $discussion, $post, $USER, $cm)) {
// perform some final capability checks
if (!forum_user_can_see_post($forum, $discussion, $post, $USER, $cm)) {
throw new rating_exception('nopermissiontorate');
}
@ -4314,8 +4343,10 @@ function forum_delete_post($post, $children, $course, $cm, $forum, $skipcompleti
//delete ratings
require_once($CFG->dirroot.'/rating/lib.php');
$delopt = new stdclass();
$delopt = new stdClass;
$delopt->contextid = $context->id;
$delopt->component = 'mod_forum';
$delopt->ratingarea = 'post';
$delopt->itemid = $post->id;
$rm = new rating_manager();
$rm->delete_ratings($delopt);
@ -5350,32 +5381,29 @@ function forum_print_latest_discussions($course, $forum, $maxdiscussions=-1, $di
/**
* @global object
* @global object
* Prints a forum discussion
*
* @uses CONTEXT_MODULE
* @uses FORUM_MODE_FLATNEWEST
* @uses FORUM_MODE_FLATOLDEST
* @uses FORUM_MODE_THREADED
* @uses FORUM_MODE_NESTED
* @param object $course
* @param object $cm
* @param object $forum
* @param object $discussion
* @param object $post
* @param object $mode
* @param stdClass $course
* @param stdClass $cm
* @param stdClass $forum
* @param stdClass $discussion
* @param stdClass $post
* @param int $mode
* @param mixed $canreply
* @param bool $cancreate
* @param bool $canrate
*/
function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, $canreply=NULL, $canrate=false) {
global $USER, $CFG;
global $USER, $CFG, $DB, $PAGE, $OUTPUT;
require_once($CFG->dirroot.'/rating/lib.php');
if (isloggedin()) {
$ownpost = ($USER->id == $post->userid);
} else {
$ownpost = false;
}
$ownpost = (isloggedin() && $USER->id == $post->userid);
$modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
if ($canreply === NULL) {
$reply = forum_user_can_post($forum, $discussion, $USER, $cm, $course, $modcontext);
@ -5384,7 +5412,7 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode,
}
// $cm holds general cache for forum functions
$cm->cache = new stdClass();
$cm->cache = new stdClass;
$cm->cache->groups = groups_get_all_groups($course->id, 0, $cm->groupingid);
$cm->cache->usersgroups = array();
@ -5417,10 +5445,11 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode,
}
//load ratings
if ($forum->assessed!=RATING_AGGREGATE_NONE) {
$ratingoptions = new stdclass();
if ($forum->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass;
$ratingoptions->context = $modcontext;
$ratingoptions->component = 'mod_forum';
$ratingoptions->ratingarea = 'post';
$ratingoptions->items = $posts;
$ratingoptions->aggregate = $forum->assessed;//the aggregation method
$ratingoptions->scaleid = $forum->scale;
@ -7094,10 +7123,14 @@ function forum_reset_userdata($data) {
WHERE f.course=? AND f.id=fd.forum AND fd.id=fp.discussion";
$forumssql = $forums = $rm = null;
if( $removeposts || !empty($data->reset_forum_ratings) ) {
$forumssql = "$allforumssql $typesql";
$forums = $forums = $DB->get_records_sql($forumssql, $params);
$rm = new rating_manager();
$rm = new rating_manager();;
$ratingdeloptions = new stdClass;
$ratingdeloptions->component = 'mod_forum';
$ratingdeloptions->ratingarea = 'post';
}
if ($removeposts) {
@ -7106,7 +7139,6 @@ function forum_reset_userdata($data) {
// now get rid of all attachments
$fs = get_file_storage();
$ratingdeloptions = new stdclass();
if ($forums) {
foreach ($forums as $forumid=>$unused) {
if (!$cm = get_coursemodule_from_instance('forum', $forumid)) {
@ -7154,8 +7186,6 @@ function forum_reset_userdata($data) {
// remove all ratings in this course's forums
if (!empty($data->reset_forum_ratings)) {
$ratingdeloptions = new stdclass();
if ($forums) {
foreach ($forums as $forumid=>$unused) {
if (!$cm = get_coursemodule_from_instance('forum', $forumid)) {

View file

@ -118,7 +118,8 @@ if ($course->id == SITEID) {
}
// Get the posts.
if ($posts = forum_search_posts($searchterms, $searchcourse, $page*$perpage, $perpage, $totalcount, $extrasql)) {
$posts = forum_search_posts($searchterms, $searchcourse, $page*$perpage, $perpage, $totalcount, $extrasql);
if ($posts) {
require_once($CFG->dirroot.'/rating/lib.php');
@ -127,15 +128,14 @@ if ($posts = forum_search_posts($searchterms, $searchcourse, $page*$perpage, $pe
$discussions = array();
$forums = array();
$cms = array();
//todo Rather than retrieving the ratings for each post individually it would be nice to do them in groups
//however this requires creating arrays of posts with each array containing all of the posts from a particular forum,
//retrieving the ratings then reassembling them all back into a single array sorted by post.modified (descending)
$rm = new rating_manager();
$ratingoptions = new stdclass();
$ratingoptions->plugintype = 'mod';
$ratingoptions->pluginname = 'forum';
$ratingoptions = new stdClass;
$ratingoptions->component = 'mod_forum';
$ratingoptions->ratingarea = 'post';
foreach ($posts as $post) {
@ -149,66 +149,57 @@ if ($posts = forum_search_posts($searchterms, $searchcourse, $page*$perpage, $pe
}
if (!isset($forums[$discussion->forum])) {
if (! $forum = $DB->get_record('forum', array('id' => $discussion->forum))) {
print_error('invalidforumid', 'forum');
}
//hold onto forum cm and context for when we load ratings
if ($forumcm = get_coursemodule_from_instance('forum', $forum->id)) {
$forum->cm = $forumcm;
$forumcontext = get_context_instance(CONTEXT_MODULE, $forum->cm->id);
$forum->context = $forumcontext;
}
$forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
$forum->cm = get_coursemodule_from_instance('forum', $forum->id, 0, false, MUST_EXIST);
$forum->context = get_context_instance(CONTEXT_MODULE, $forum->cm->id);
$forums[$discussion->forum] = $forum;
} else {
$forum = $forums[$discussion->forum];
}
//load ratings
if ($forum->assessed!=RATING_AGGREGATE_NONE) {
$forumurl = new moodle_url('/mod/forum/view.php', array('id' => $forum->cm->id));
$discussionurl = new moodle_url('/mod/forum/discuss.php', array('d' => $discussion->id));
// load ratings
if ($forum->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions->context = $forum->context;
$ratingoptions->component = 'mod_forum';
$ratingoptions->items = array($post);
$ratingoptions->aggregate = $forum->assessed;//the aggregation method
$ratingoptions->scaleid = $forum->scale;
$ratingoptions->userid = $user->id;
if ($forum->type == 'single' or !$discussion->id) {
$ratingoptions->returnurl = "$CFG->wwwroot/mod/forum/view.php?id={$forum->cm->id}";
} else {
$ratingoptions->returnurl = "$CFG->wwwroot/mod/forum/discuss.php?d=$discussion->id";
}
$ratingoptions->assesstimestart = $forum->assesstimestart;
$ratingoptions->assesstimefinish = $forum->assesstimefinish;
if ($forum->type == 'single' or !$discussion->id) {
$ratingoptions->returnurl = $forumurl;
} else {
$ratingoptions->returnurl = $discussionurl;
}
$updatedpost = $rm->get_ratings($ratingoptions);
//updating the array this way because we're iterating over a collection and updating them one by one
$posts[$updatedpost[0]->id] = $updatedpost[0];
}
if (!isset($cms[$forum->id])) {
$cm = get_coursemodule_from_instance('forum', $forum->id, 0, false, MUST_EXIST);
$cms[$forum->id] = $cm;
unset($cm); // do not use cm directly, it would break caching
$fullsubjects = array();
if ($course->id == SITEID && has_capability('moodle/site:config', $syscontext)) {
$postcoursename = $DB->get_field('course', 'shortname', array('id'=>$forum->course));
$courseurl = new moodle_url('/course/view.php', array('id' => $forum->course));
$fullsubjects[] = html_writer::link($courseurl, $postcoursename);
}
$fullsubject = "<a href=\"view.php?f=$forum->id\">".format_string($forum->name,true)."</a>";
$fullsubjects[] = html_writer::link($forumurl, format_string($forum->name, true));
if ($forum->type != 'single') {
$fullsubject .= " -> <a href=\"discuss.php?d=$discussion->id\">".format_string($discussion->name,true)."</a>";
$fullsubjects[] .= html_writer::link($discussionurl, format_string($discussion->name, true));
if ($post->parent != 0) {
$fullsubject .= " -> <a href=\"discuss.php?d=$post->discussion&amp;parent=$post->id\">".format_string($post->subject,true)."</a>";
$parenturl = new moodle_url('/mod/forum/discuss.php', array('d' => $post->discussion, 'parent' => $post->id));
$fullsubjects[] .= html_writer::link($parenturl, format_string($post->subject, true));
}
}
if ($course->id == SITEID && has_capability('moodle/site:config', $syscontext)) {
$postcoursename = $DB->get_field('course', 'shortname', array('id'=>$forum->course));
$fullsubject = '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$forum->course.'">'.$postcoursename.'</a> -> '. $fullsubject;
}
$post->subject = join(' -> ', $fullsubjects);
$discussionurl->set_anchor('p'.$post->id);
$fulllink = html_writer::link($discussionurl, get_string("postincontext", "forum"));
$post->subject = $fullsubject;
$fulllink = "<a href=\"discuss.php?d=$post->discussion#p$post->id\">".
get_string("postincontext", "forum")."</a>";
forum_print_post($post, $discussion, $forum, $cms[$forum->id], $course, false, false, false, $fulllink);
forum_print_post($post, $discussion, $forum, $forum->cm, $course, false, false, false, $fulllink);
echo "<br />";
}

View file

@ -24,8 +24,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$module->version = 2010111500;
$module->requires = 2010111002; // Requires this Moodle version
$module->cron = 60;
$module->version = 2011052300;
$module->requires = 2011052300; // Requires this Moodle version
$module->cron = 60;

View file

@ -102,10 +102,6 @@
$completion->set_module_viewed($cm);
/// Print header.
/// Add ajax-related libs for ratings if required MDL-20119
$PAGE->requires->yui2_lib('event');
$PAGE->requires->yui2_lib('connection');
$PAGE->requires->yui2_lib('json');
$PAGE->set_title(format_string($forum->name));
$PAGE->add_body_class('forumtype-'.$forum->type);

View file

@ -61,7 +61,7 @@ class backup_glossary_activity_structure_step extends backup_activity_structure_
$ratings = new backup_nested_element('ratings');
$rating = new backup_nested_element('rating', array('id'), array(
'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
'component', 'ratingarea', 'scaleid', 'value', 'userid', 'timecreated', 'timemodified'));
$categories = new backup_nested_element('categories');
@ -101,8 +101,10 @@ class backup_glossary_activity_structure_step extends backup_activity_structure_
$alias->set_source_table('glossary_alias', array('entryid' => backup::VAR_PARENTID));
$alias->set_source_alias('alias', 'alias_text');
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'itemid' => backup::VAR_PARENTID));
$rating->set_source_table('rating', array('contextid' => backup::VAR_CONTEXTID,
'itemid' => backup::VAR_PARENTID,
'component' => 'mod_glossary',
'ratingarea' => 'entry'));
$rating->set_source_alias('rating', 'value');
$categoryentry->set_source_table('glossary_entries_categories', array('categoryid' => backup::VAR_PARENTID));

View file

@ -117,6 +117,15 @@ class restore_glossary_activity_structure_step extends restore_activity_structur
$data->timecreated = $this->apply_date_offset($data->timecreated);
$data->timemodified = $this->apply_date_offset($data->timemodified);
// Make sure that we have both component and ratingarea set. These were added in 2.1.
// Prior to that all ratings were for entries so we know what to set them too.
if (empty($data->component)) {
$data->component = 'mod_glossary';
}
if (empty($data->ratingarea)) {
$data->ratingarea = 'entry';
}
$newitemid = $DB->insert_record('rating', $data);
}

View file

@ -326,6 +326,29 @@ function xmldb_glossary_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2010111501, 'glossary');
}
if ($oldversion < 2011052300) {
// rating.component and rating.ratingarea have now been added as mandatory fields.
// Presently you can only rate data entries so component = 'mod_glossary' and ratingarea = 'entry'
// for all ratings with a glossary context.
// We want to update all ratings that belong to a glossary context and don't already have a
// component set.
// This could take a while reset upgrade timeout to 5 min
upgrade_set_timeout(60 * 20);
$sql = "UPDATE {rating}
SET component = 'mod_glossary', ratingarea = 'entry'
WHERE contextid IN (
SELECT ctx.id
FROM {context} ctx
JOIN {course_modules} cm ON cm.id = ctx.instanceid
JOIN {modules} m ON m.id = cm.module
WHERE ctx.contextlevel = 70 AND
m.name = 'glossary'
) AND component = 'unknown'";
$DB->execute($sql);
upgrade_mod_savepoint(true, 2011052300, 'glossary');
}
return true;
}

View file

@ -104,8 +104,10 @@ if ($confirm and confirm_sesskey()) { // the operation was confirmed.
//delete glossary entry ratings
require_once($CFG->dirroot.'/rating/lib.php');
$delopt = new stdclass();
$delopt = new stdClass;
$delopt->contextid = $context->id;
$delopt->component = 'mod_glossary';
$delopt->ratingarea = 'entry';
$delopt->itemid = $entry->id;
$rm = new rating_manager();
$rm->delete_ratings($delopt);

View file

@ -23,7 +23,6 @@
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/rating/lib.php');
require_once($CFG->libdir . '/completionlib.php');
define("GLOSSARY_SHOW_ALL_CATEGORIES", 0);
@ -243,7 +242,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;
@ -436,13 +444,14 @@ function glossary_get_user_grades($glossary, $userid=0) {
global $CFG;
require_once($CFG->dirroot.'/rating/lib.php');
$rm = new rating_manager();
$ratingoptions = new stdclass();
$ratingoptions = new stdClass;
//need these to work backwards to get a context id. Is there a better way to get contextid from a module instance?
$ratingoptions->modulename = 'glossary';
$ratingoptions->moduleid = $glossary->id;
$ratingoptions->component = 'mod_glossary';
$ratingoptions->ratingarea = 'entry';
$ratingoptions->userid = $userid;
$ratingoptions->aggregationmethod = $glossary->assessed;
@ -450,31 +459,40 @@ function glossary_get_user_grades($glossary, $userid=0) {
$ratingoptions->itemtable = 'glossary_entries';
$ratingoptions->itemtableusercolumn = 'userid';
$rm = new rating_manager();
return $rm->get_user_grades($ratingoptions);
}
/**
* Return rating related permissions
* @param string $options the context id
*
* @param int $contextid the context id
* @param string $component The component we want to get permissions for
* @param string $ratingarea The ratingarea that we want to get permissions for
* @return array an associative array of the user's rating permissions
*/
function glossary_rating_permissions($options) {
$contextid = $options;
$context = get_context_instance_by_id($contextid);
if (!$context) {
print_error('invalidcontext');
function glossary_rating_permissions($contextid, $component, $ratingarea) {
if ($component != 'mod_glossary' || $ratingarea != 'entry') {
// We don't know about this component/ratingarea so just return null to get the
// default restrictive permissions.
return null;
} else {
return array('view'=>has_capability('mod/glossary:viewrating',$context), 'viewany'=>has_capability('mod/glossary:viewanyrating',$context), 'viewall'=>has_capability('mod/glossary:viewallratings',$context), 'rate'=>has_capability('mod/glossary:rate',$context));
}
$context = get_context_instance_by_id($contextid);
return array(
'view' => has_capability('mod/glossary:viewrating', $context),
'viewany' => has_capability('mod/glossary:viewanyrating', $context),
'viewall' => has_capability('mod/glossary:viewallratings', $context),
'rate' => has_capability('mod/glossary:rate', $context)
);
}
/**
* Validates a submitted rating
* @param array $params submitted data
* context => object the context in which the rated items exists [required]
* itemid => int the ID of the object being rated
* component => The component for this module - should always be mod_forum [required]
* ratingarea => object the context in which the rated items exists [required]
* itemid => int the ID of the object being rated [required]
* scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required]
* rating => int the submitted rating
* rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required]
@ -484,28 +502,59 @@ 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)) {
throw new rating_exception('missingparameter');
// Check the component is mod_forum
if ($params['component'] != 'mod_glossary') {
throw new rating_exception('invalidcomponent');
}
$glossarysql = "SELECT g.id as gid, e.userid as userid, e.approved, e.timecreated, g.assesstimestart, g.assesstimefinish
// Check the ratingarea is post (the only rating area in forum)
if ($params['ratingarea'] != 'entry') {
throw new rating_exception('invalidratingarea');
}
// Check the rateduserid is not the current user .. you can't rate your own posts
if ($params['rateduserid'] == $USER->id) {
throw new rating_exception('nopermissiontorate');
}
$glossarysql = "SELECT g.id as glossaryid, g.scale, g.course, 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";
$glossaryparams = array('itemid'=>$params['itemid']);
if (!$info = $DB->get_record_sql($glossarysql, $glossaryparams)) {
$glossaryparams = array('itemid' => $params['itemid']);
$info = $DB->get_record_sql($glossarysql, $glossaryparams);
if (!$info) {
//item doesn't exist
throw new rating_exception('invaliditemid');
}
if ($info->userid == $USER->id) {
//user is attempting to rate their own glossary entry
throw new rating_exception('nopermissiontorate');
if ($info->scale != $params['scaleid']) {
//the scale being submitted doesnt match the one in the database
throw new rating_exception('invalidscaleid');
}
if ($params['rateduserid'] != $info->userid) {
//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
// lower limit
if ($params['rating'] < 0 && $params['rating'] != RATING_UNSET_RATING) {
throw new rating_exception('invalidnum');
}
// upper limit
if ($info->scale < 0) {
//its a custom scale
$scalerecord = $DB->get_record('scale', array('id' => -$info->scale));
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) {
@ -520,16 +569,11 @@ function glossary_rating_validate($params) {
}
}
$glossaryid = $info->gid;
$cm = get_coursemodule_from_instance('glossary', $info->glossaryid, $info->course, false, MUST_EXIST);
$context = get_context_instance(CONTEXT_MODULE, $cm->id, MUST_EXIST);
$cm = get_coursemodule_from_instance('glossary', $glossaryid);
if (empty($cm)) {
throw new rating_exception('unknowncontext');
}
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
//if the supplied context doesnt match the item's context
if (empty($context) || $context->id != $params['context']->id) {
// if the supplied context doesnt match the item's context
if ($context->id != $params['context']->id) {
throw new rating_exception('invalidcontext');
}
@ -647,7 +691,8 @@ function glossary_grade_item_delete($glossary) {
* Returns the users with data in one glossary
* (users with records in glossary_entries, students)
*
* @global object
* @todo: deprecated - to be deleted in 2.2
*
* @param int $glossaryid
* @return array
*/
@ -2154,31 +2199,49 @@ function glossary_full_tag($tag,$level=0,$endline=true,$content) {
/**
* How many unrated entries are in the given glossary for a given user?
*
* @global object
* @global moodle_database $DB
* @param int $glossaryid
* @param int $userid
* @return int
*/
function glossary_count_unrated_entries($glossaryid, $userid) {
global $DB;
if ($entries = $DB->get_record_sql("SELECT count('x') as num
FROM {glossary_entries}
WHERE glossaryid = ? AND userid <> ?", array($glossaryid, $userid))) {
if (!$cm = get_coursemodule_from_instance('glossary', $glossaryid)) {
return 0;
}
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
$sql = "SELECT COUNT('x') as num
FROM {glossary_entries}
WHERE glossaryid = :glossaryid AND
userid <> :userid";
$params = array('glossaryid' => $glossaryid, 'userid' => $userid);
$entries = $DB->count_records_sql($sql, $params);
if ($rated = $DB->get_record_sql("SELECT count(*) as num
FROM {glossary_entries} e, {ratings} r
WHERE e.glossaryid = :glossaryid AND e.id = r.itemid
AND r.userid = :userid and r.contextid = :contextid",
array('glossaryid'=>$glossaryid, 'userid'=>$userid, 'contextid'=>$context->id))) {
if ($entries) {
// We need to get the contextid for the glossaryid we have been given.
$sql = "SELECT ctx.id
FROM {context} ctx
JOIN {course_modules} cm ON cm.id = ctx.instanceid
JOIN {modules} m ON m.id = cm.module
JOIN {glossary} g ON g.id = cm.instance
WHERE ctx.contextlevel = :contextlevel AND
m.name = 'glossary' AND
g.id = :glossaryid";
$contextid = $DB->get_field_sql($sql, array('glossaryid' => $glossaryid, 'contextlevel' => CONTEXT_MODULE));
$difference = $entries->num - $rated->num;
if ($difference > 0) {
return $difference;
// Now we need to count the ratings that this user has made
$sql = "SELECT COUNT('x') AS num
FROM {glossary_entries} e
JOIN {ratings} r ON r.itemid = e.id
WHERE e.glossaryid = :glossaryid AND
r.userid = :userid AND
r.component = 'mod_glossary' AND
r.ratingarea = 'entry' AND
r.contextid = :contextid";
$params = array('glossaryid' => $glossaryid, 'userid' => $userid, 'contextid' => $context->id);
$rated = $DB->count_records_sql($sql, $params);
if ($rated) {
// The number or enties minus the number or rated entries equals the number of unrated
// entries
if ($entries->num > $rated->num) {
return $entries->num - $rated->num;
} else {
return 0; // Just in case there was a counting error
}
@ -2430,7 +2493,9 @@ function glossary_reset_userdata($data) {
$fs = get_file_storage();
$rm = new rating_manager();
$ratingdeloptions = new stdclass();
$ratingdeloptions = new stdClass;
$ratingdeloptions->component = 'mod_glossary';
$ratingdeloptions->ratingarea = 'entry';
// delete entries if requested
if (!empty($data->reset_glossary_all)

View file

@ -5,8 +5,8 @@
/// This fragment is called by moodle_needs_upgrading() and /admin/index.php
/////////////////////////////////////////////////////////////////////////////////
$module->version = 2010111501;
$module->requires = 2010080300; // Requires this Moodle version
$module->version = 2011052300;
$module->requires = 2011052300; // Requires this Moodle version
$module->cron = 0; // Period for cron to check this module (secs)

View file

@ -394,13 +394,13 @@ if ($allentries) {
echo $paging;
echo '</div>';
//load ratings
require_once($CFG->dirroot.'/rating/lib.php');
if ($glossary->assessed!=RATING_AGGREGATE_NONE) {
$ratingoptions = new stdclass();
if ($glossary->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass;
$ratingoptions->context = $context;
$ratingoptions->component = 'mod_glossary';
$ratingoptions->ratingarea = 'entry';
$ratingoptions->items = $allentries;
$ratingoptions->aggregate = $glossary->assessed;//the aggregation method
$ratingoptions->scaleid = $glossary->scale;

View file

@ -249,6 +249,8 @@ function imscp_user_complete($course, $user, $mod, $imscp) {
/**
* Returns the users with data in one imscp
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $imscpid
* @return bool false
*/

View file

@ -116,6 +116,8 @@ function label_delete_instance($id) {
* Returns the users with data in one resource
* (NONE, but must exist on EVERY mod !!)
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $labelid
*/
function label_get_participants($labelid) {

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;
}
@ -521,8 +528,8 @@ function lesson_grade_item_delete($lesson) {
* for a given instance of lesson. Must include every user involved
* in the instance, independent of his role (student, teacher, admin...)
*
* @global stdClass
* @global object
* @todo: deprecated - to be deleted in 2.2
*
* @param int $lessonid
* @return array
*/

View file

@ -231,6 +231,8 @@ function page_user_complete($course, $user, $mod, $page) {
/**
* Returns the users with data in one page
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $pageid
* @return bool false
*/

View file

@ -366,7 +366,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

@ -210,6 +210,8 @@ function resource_user_complete($course, $user, $mod, $resource) {
/**
* Returns the users with data in one resource
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $resourceid
* @return bool false
*/

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

@ -271,7 +271,8 @@ function survey_print_recent_activity($course, $viewfullnames, $timestart) {
* Returns the users with data in one survey
* (users with records in survey_analysis and survey_answers, students)
*
* @global object
* @todo: deprecated - to be deleted in 2.2
*
* @param int $surveyid
* @return array
*/

View file

@ -237,6 +237,8 @@ function url_user_complete($course, $user, $mod, $url) {
/**
* Returns the users with data in one url
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $urlid
* @return bool false
*/

View file

@ -382,6 +382,8 @@ function wiki_grades($wikiid) {
* in the instance, independient of his role (student, teacher, admin...)
* See other modules as example.
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $wikiid ID of an instance of this module
* @return mixed boolean/array of students
**/

View file

@ -898,6 +898,8 @@ function workshop_cron () {
* are not returned as the example submission is considered non-user
* data for the purpose of workshop backup.
*
* @todo: deprecated - to be deleted in 2.2
*
* @param int $workshopid ID of an instance of this module
* @return array of user ids, empty if there are no participants
*/