moodle/grade/export/lib.php
David Mudrak 995f2d51d7 MDL-12192 Language specific label separator instead of hardcoded ': '
New string is available. Use get_string('labelsep', 'langconfig') to be used
as a separator between a label and the labelled text. If you want to
produce <label> HTML element, you may be interested in the new
html_writer::label() method. Simple selects and URL selects now use it.

There are bambillion places where ': ' is hardcoded as a separator. I do
not think we have to fix them manually now (and mass search and replace
would be tricky) but everybody should stop adding new.

Do not abuse 'labelsep' for any other purposes. Note that it may not be
colon in some languages or sites.
2010-07-02 12:15:36 +00:00

386 lines
13 KiB
PHP
Executable File

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
require_once($CFG->dirroot.'/lib/gradelib.php');
require_once($CFG->dirroot.'/grade/lib.php');
require_once($CFG->dirroot.'/grade/export/grade_export_form.php');
/**
* Base export class
*/
abstract class grade_export {
public $plugin; // plgin name - must be filled in subclasses!
public $grade_items; // list of all course grade items
public $groupid; // groupid, 0 means all groups
public $course; // course object
public $columns; // array of grade_items selected for export
public $previewrows; // number of rows in preview
public $export_letters; // export letters
public $export_feedback; // export feedback
public $userkey; // export using private user key
public $updatedgradesonly; // only export updated grades
public $displaytype; // display type (e.g. real, percentages, letter) for exports
public $decimalpoints; // number of decimal points for exports
/**
* Constructor should set up all the private variables ready to be pulled
* @access public
* @param object $course
* @param int $groupid id of selected group, 0 means all
* @param string $itemlist comma separated list of item ids, empty means all
* @param boolean $export_feedback
* @param boolean $export_letters
* @note Exporting as letters will lead to data loss if that exported set it re-imported.
*/
public function grade_export($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2) {
$this->course = $course;
$this->groupid = $groupid;
$this->grade_items = grade_item::fetch_all(array('courseid'=>$this->course->id));
$this->columns = array();
if (!empty($itemlist)) {
$itemids = explode(',', $itemlist);
// remove items that are not requested
foreach ($itemids as $itemid) {
if (array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
} else {
foreach ($this->grade_items as $itemid=>$unused) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
$this->export_feedback = $export_feedback;
$this->userkey = '';
$this->previewrows = false;
$this->updatedgradesonly = $updatedgradesonly;
$this->displaytype = $displaytype;
$this->decimalpoints = $decimalpoints;
}
/**
* Init object based using data from form
* @param object $formdata
*/
function process_form($formdata) {
global $USER;
$this->columns = array();
if (!empty($formdata->itemids)) {
foreach ($formdata->itemids as $itemid=>$selected) {
if ($selected and array_key_exists($itemid, $this->grade_items)) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
} else {
foreach ($this->grade_items as $itemid=>$unused) {
$this->columns[$itemid] =& $this->grade_items[$itemid];
}
}
if (isset($formdata->key)) {
if ($formdata->key == 1 && isset($formdata->iprestriction) && isset($formdata->validuntil)) {
// Create a new key
$formdata->key = create_user_key('grade/export', $USER->id, $this->course->id, $formdata->iprestriction, $formdata->validuntil);
}
$this->userkey = $formdata->key;
}
if (isset($formdata->export_letters)) {
$this->export_letters = $formdata->export_letters;
}
if (isset($formdata->export_feedback)) {
$this->export_feedback = $formdata->export_feedback;
}
if (isset($formdata->previewrows)) {
$this->previewrows = $formdata->previewrows;
}
}
/**
* Update exported field in grade_grades table
* @return boolean
*/
public function track_exports() {
global $CFG;
/// Whether this plugin is entitled to update export time
if ($expplugins = explode(",", $CFG->gradeexport)) {
if (in_array($this->plugin, $expplugins)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
/**
* Returns string representation of final grade
* @param $object $grade instance of grade_grade class
* @return string
*/
public function format_grade($grade) {
return grade_format_gradevalue($grade->finalgrade, $this->grade_items[$grade->itemid], false, $this->displaytype, $this->decimalpoints);
}
/**
* Returns the name of column in export
* @param object $grade_item
* @param boolena $feedback feedback colum
* &return string
*/
public function format_column_name($grade_item, $feedback=false) {
if ($grade_item->itemtype == 'mod') {
$name = get_string('modulename', $grade_item->itemmodule).get_string('labelsep', 'langconfig').$grade_item->get_name();
} else {
$name = $grade_item->get_name();
}
if ($feedback) {
$name .= ' ('.get_string('feedback').')';
}
return strip_tags($name);
}
/**
* Returns formatted grade feedback
* @param object $feedback object with properties feedback and feedbackformat
* @return string
*/
public function format_feedback($feedback) {
return strip_tags(format_text($feedback->feedback, $feedback->feedbackformat));
}
/**
* Implemented by child class
*/
public abstract function print_grades();
/**
* Prints preview of exported grades on screen as a feedback mechanism
* @param bool $require_user_idnumber true means skip users without idnumber
*/
public function display_preview($require_user_idnumber=false) {
global $OUTPUT;
echo $OUTPUT->heading(get_string('previewrows', 'grades'));
echo '<table>';
echo '<tr>';
echo '<th>'.get_string("firstname")."</th>".
'<th>'.get_string("lastname")."</th>".
'<th>'.get_string("idnumber")."</th>".
'<th>'.get_string("institution")."</th>".
'<th>'.get_string("department")."</th>".
'<th>'.get_string("email")."</th>";
foreach ($this->columns as $grade_item) {
echo '<th>'.$this->format_column_name($grade_item).'</th>';
/// add a column_feedback column
if ($this->export_feedback) {
echo '<th>'.$this->format_column_name($grade_item, true).'</th>';
}
}
echo '</tr>';
/// Print all the lines of data.
$i = 0;
$gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
$gui->init();
while ($userdata = $gui->next_user()) {
// number of preview rows
if ($this->previewrows and $this->previewrows <= $i) {
break;
}
$user = $userdata->user;
if ($require_user_idnumber and empty($user->idnumber)) {
// some exports require user idnumber
continue;
}
$gradeupdated = false; // if no grade is update at all for this user, do not display this row
$rowstr = '';
foreach ($this->columns as $itemid=>$unused) {
$gradetxt = $this->format_grade($userdata->grades[$itemid]);
// get the status of this grade, and put it through track to get the status
$g = new grade_export_update_buffer();
$grade_grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$user->id));
$status = $g->track($grade_grade);
if ($this->updatedgradesonly && ($status == 'nochange' || $status == 'unknown')) {
$rowstr .= '<td>'.get_string('unchangedgrade', 'grades').'</td>';
} else {
$rowstr .= "<td>$gradetxt</td>";
$gradeupdated = true;
}
if ($this->export_feedback) {
$rowstr .= '<td>'.$this->format_feedback($userdata->feedbacks[$itemid]).'</td>';
}
}
// if we are requesting updated grades only, we are not interested in this user at all
if (!$gradeupdated && $this->updatedgradesonly) {
continue;
}
echo '<tr>';
echo "<td>$user->firstname</td><td>$user->lastname</td><td>$user->idnumber</td><td>$user->institution</td><td>$user->department</td><td>$user->email</td>";
echo $rowstr;
echo "</tr>";
$i++; // increment the counter
}
echo '</table>';
$gui->close();
}
/**
* Returns array of parameters used by dump.php and export.php.
* @return array
*/
public function get_export_params() {
$itemids = array_keys($this->columns);
$params = array('id' =>$this->course->id,
'groupid' =>$this->groupid,
'itemids' =>implode(',', $itemids),
'export_letters' =>$this->export_letters,
'export_feedback' =>$this->export_feedback,
'updatedgradesonly' =>$this->updatedgradesonly,
'displaytype' =>$this->displaytype,
'decimalpoints' =>$this->decimalpoints);
return $params;
}
/**
* Either prints a "Export" box, which will redirect the user to the download page,
* or prints the URL for the published data.
* @return void
*/
public function print_continue() {
global $CFG, $OUTPUT;
$params = $this->get_export_params();
echo $OUTPUT->heading(get_string('export', 'grades'));
echo $OUTPUT->container_start('gradeexportlink');
if (!$this->userkey) { // this button should trigger a download prompt
echo $OUTPUT->single_button(new moodle_url('/grade/export/'.$this->plugin.'/export.php', $params), get_string('download', 'admin'));
} else {
$paramstr = '';
$sep = '?';
foreach($params as $name=>$value) {
$paramstr .= $sep.$name.'='.$value;
$sep = '&';
}
$link = $CFG->wwwroot.'/grade/export/'.$this->plugin.'/dump.php'.$paraM.str.'&key='.$this->userkey;
echo get_string('download', 'admin').': ' . html_writer::link($link, $link);
}
echo $OUTPUT->container_end();
}
}
/**
* This class is used to update the exported field in grade_grades.
* It does internal buffering to speedup the db operations.
*/
class grade_export_update_buffer {
public $update_list;
public $export_time;
/**
* Constructor - creates the buffer and initialises the time stamp
*/
public function grade_export_update_buffer() {
$this->update_list = array();
$this->export_time = time();
}
public function flush($buffersize) {
global $CFG, $DB;
if (count($this->update_list) > $buffersize) {
list($usql, $params) = $DB->get_in_or_equal($this->update_list);
$params = array_merge(array($this->export_time), $params);
$sql = "UPDATE {grade_grades} SET exported = ? WHERE id $usql";
$DB->execute($sql, $params);
$this->update_list = array();
}
}
/**
* Track grade export status
* @param object $grade_grade
* @return string $status (unknow, new, regrade, nochange)
*/
public function track($grade_grade) {
if (empty($grade_grade->exported) or empty($grade_grade->timemodified)) {
if (is_null($grade_grade->finalgrade)) {
// grade does not exist yet
$status = 'unknown';
} else {
$status = 'new';
$this->update_list[] = $grade_grade->id;
}
} else if ($grade_grade->exported < $grade_grade->timemodified) {
$status = 'regrade';
$this->update_list[] = $grade_grade->id;
} else if ($grade_grade->exported >= $grade_grade->timemodified) {
$status = 'nochange';
} else {
// something is wrong?
$status = 'unknown';
}
$this->flush(100);
return $status;
}
/**
* Flush and close the buffer.
*/
public function close() {
$this->flush(0);
}
}