removed bad newlines, which caused double-spacing in PHP source

This commit is contained in:
gbateson 2005-11-24 05:40:36 +00:00
parent 2cc57707a8
commit 64b4e0f155
18 changed files with 7181 additions and 8464 deletions

View File

@ -1,151 +1,105 @@
This is v2.1.5 of the HotPot module
This module allows teachers to administer Hot Potatoes and TexToys quizzes via Moodle.
It has been tested on:
- Hot Potatoes 6
- Moodle 1.1 thru 1.6
- PHP 4.1 thru 5.0
- MySQL and PostgreSQL databases
This module may be distributed under the terms of the General Public License
(see http://www.gnu.org/licenses/gpl.txt for details)
This software is provided "AS IS" without a warranty of any kind.
Sponsors who have generously contributed to the development of this software:
- Agencia de Gestio d'Ajuts Universitaris i de Recerca (AGAUR),
Autonomous Government of Catalonia, Spain
(via Josep M. Fontana, Universitat Pompeu Fabra)
- Rikkyo Univeristy, Japan (via Paul Allum)
- Universite de Franche-Comte, France (via Glenys Hanson)
================
IMPORTANT NOTICE
================
* Please be sure to use Hot Potatoes according to the conditions of use which are listed at the end of this file. If you restrict use via a required Moodle login, you most likely can still meet the 'freely available' condition if you make the same material on a separate URL that permits free access. Otherwise, please purchase a license.
TO INSTALL OR UPDATE THIS MODULE
1. Install the core scripts of the hotpot module
EITHER:
(a) download the zip file into the "moodle/mod" folder on your Moodle site
(b) unzip the zip file. This will create a folder called "moodle/mod/hotpot" on your Moodle site
OR:
(a) download the zip file onto your PC
(b) upzip the zip file on your PC. This will create a "hotpot" folder on your PC
(c) create a folder called "hotpot" on your Moodle site in the "moodle/mod" folder
(d) upload the contents of the "hotpot" folder on your PC to the "moodle/mod/hotpot" folder on the Moodle site
2. Install the messages and help files of the hotpot module
EITHER:
(a) copy "moodle/mod/hotpot/lang/en/hotpot.php" on the Moodle site to "moodle/lang/en/hotpot.php"
(b) copy "moodle/mod/hotpot/lang/en/help/hotpot" on the Moodle site to "moodle/lang/en/help/hotpot"
(c) repeat for other languages you require from the "moodle/mod/hotpot/lang" folder
OR:
(a) upload the "hotpot/lang/en/hotpot.php" file on your PC to "moodle/lang/en/hotpot.php" on the Moodle site
(b) create a folder called "hotpot" on your Moodle site in the "moodle/lang/en/help" folder
(c) upload the contents of the "hotpot/lang/en/help/hotpot" folder on your PC to the "moodle/lang/en/help/hotpot" folder on the Moodle site
(d) repeat for other languages you require from the "moodle/mod/hotpot/lang" folder
3. copy and set up the file icons
[This step is not required for Moodle 1.5 and later, and is optional for Moodle 1.1 to 1.4]
(a) copy the files in the "mod/hotpot/pix/f" folder on your Moodle site to "moodle/pix/f"
(b) open the "moodle/files/mimetypes.php" file on your Moodle site with a text editor
(c) insert the following lines just AFTER the line which reads "$mimeinfo = array (":
// additional mimetypes for the "hotpot" module
"jcb" => array ("type"=>"text/xml", "icon"=>"jcb.gif"),
"jcl" => array ("type"=>"text/xml", "icon"=>"jcl.gif"),
"jcw" => array ("type"=>"text/xml", "icon"=>"jcw.gif"),
"jmt" => array ("type"=>"text/xml", "icon"=>"jmt.gif"),
"jmx" => array ("type"=>"text/xml", "icon"=>"jmx.gif"),
"jqz" => array ("type"=>"text/xml", "icon"=>"jqz.gif"),
"rhb" => array ("type"=>"text/xml", "icon"=>"xml.gif"),
"sqt" => array ("type"=>"text/xml", "icon"=>"xml.gif"),
(d) save the changes and close the file
4. enable import from Hot Potatoes XML files to Moodle's Quiz module
[This step is not required for Moodle 1.5 and later, and is optional for Moodle 1.1 to 1.4]
(a) create a folder called "hotpot" on your Moodle site in the "moodle/mod/quiz/format" folder
(b) copy the "contents of the "moodle/mod/hotpot/quiz/format/hotpot" folder on your Moodle site to the "moodle/mod/quiz/format/hotpot" folder
(c) open the "moodle/lang/en/quiz.php" file on your Moodle site with a text editor
(d) insert the following line just BEFORE the final line which reads "?>":
$string['hotpot'] = 'Hot Potatoes XML format';
(d) save the changes and close the file
Steps (e), (f) and (g) are only required on Moodle 1.4.5
(e) open the "moodle/mod/quiz/import.php" file on your Moodle site with a text editor
(f) if necessary, add 'hotpot' to the "fileformats" array on lines 9-10:
$fileformats = array('aiken','aon','blackboard','coursetestmanager',
'gift','learnwise','missingword','webct','xml','hotpot' );
(g) save the changes and close the file
5. Login to your Moodle site as an administrator.
a) If you are installing this module for the first time, you should see a report saying that the following (prefix)_hotpot tables have been successfuly created:
hotpot
hotpot_attempts
hotpot_questions
hotpot_responses
hotpot_strings
b) If you are updating the module, you will probably see messages indicating the progress of the update
c) If you get error messages, please copy and save them to a file on your PC, and then ask for help on Moodle's HotPot support forum:
go to http://moodle.org
then click "Free Support",
then click "HotPot"
TO USE THIS MODULE:
1. Create a Hot Potatoes quiz of any type using Version 6 of Hot Potatoes.
2. Upload the quiz's source file (".jcl", ".jcw", ".jmt", ".jmx", ".jqz") or ".html" file to the file area of the intended course.
3. Also upload any graphics, sound files, stylesheets or javascripts that the quiz uses
4. On the main page for the course, confirm editing is turned on (click the "Turn editing on" button) then select "ADD / Hot Potatoes XML Quiz".
6, The "Adding a new Hot Potatoes Quiz" page appears. Click the "Choose or Upload a file ..." button and select the desired quiz file.
7. Review the other settings for the quiz and click "Save Changes" when you are ready
8. You can view reports of the results via the "Hot Potatoes Quizzes" link on the "Activities menu". Students will see links to all the quizzes. Administrators and teachers will additionally see links to the statistical reports for each quiz.
9. You can also import the questions from the Hot Potatoes source file to the Moodle Quiz database, if you installed "mod/quiz/format/hotpot/format.php"
==============================
HOT POTATOES CONDITIONS OF USE
==============================
**Reproduced from the Hot Potatoes site**
Hot Potatoes is offered free to the educational community by the University of Victoria Humanities Computing and Media Centre (formerly the Language Centre), under certain conditions. Hot Potatoes is free for use by state educational institutions which are non-profit making, on the condition that the material produced using the program is freely available to anyone via the WWW. However, you need to purchase a licence under any of the following conditions:
* You do not work for a public sector educational establishment.
* You charge money for access to the material you make with Hot Potatoes.
* You restrict access to the material in some way. (The only exception here is if you have an account on www.hotpot.net, where you ARE allowed to use password restrictions.)
* You want to use the Masher program included with the Hot Potatoes suite.
For more information on licences, and details on how to purchase one, check out our Website at:
http://www.halfbakedsoftware.com/hotpot/
If you intend using the programs to generate more than a handful of exercises, please make sure you register. This costs you nothing -- see How to register for details.
Martin Holmes, Half-Baked Software and the University of Victoria HCMC, 1998-2004.
This is v2.1.5 of the HotPot module
This module allows teachers to administer Hot Potatoes and TexToys quizzes via Moodle.
It has been tested on:
- Hot Potatoes 6
- Moodle 1.1 thru 1.6
- PHP 4.1 thru 5.0
- MySQL and PostgreSQL databases
This module may be distributed under the terms of the General Public License
(see http://www.gnu.org/licenses/gpl.txt for details)
This software is provided "AS IS" without a warranty of any kind.
Sponsors who have generously contributed to the development of this software:
- Agencia de Gestio d'Ajuts Universitaris i de Recerca (AGAUR),
Autonomous Government of Catalonia, Spain
(via Josep M. Fontana, Universitat Pompeu Fabra)
- Rikkyo Univeristy, Japan (via Paul Allum)
- Universite de Franche-Comte, France (via Glenys Hanson)
================
IMPORTANT NOTICE
================
* Please be sure to use Hot Potatoes according to the conditions of use which are listed at the end of this file. If you restrict use via a required Moodle login, you most likely can still meet the 'freely available' condition if you make the same material on a separate URL that permits free access. Otherwise, please purchase a license.
TO INSTALL OR UPDATE THIS MODULE
1. Install the core scripts of the hotpot module
EITHER:
(a) download the zip file into the "moodle/mod" folder on your Moodle site
(b) unzip the zip file. This will create a folder called "moodle/mod/hotpot" on your Moodle site
OR:
(a) download the zip file onto your PC
(b) upzip the zip file on your PC. This will create a "hotpot" folder on your PC
(c) create a folder called "hotpot" on your Moodle site in the "moodle/mod" folder
(d) upload the contents of the "hotpot" folder on your PC to the "moodle/mod/hotpot" folder on the Moodle site
2. Install the messages and help files of the hotpot module
EITHER:
(a) copy "moodle/mod/hotpot/lang/en/hotpot.php" on the Moodle site to "moodle/lang/en/hotpot.php"
(b) copy "moodle/mod/hotpot/lang/en/help/hotpot" on the Moodle site to "moodle/lang/en/help/hotpot"
(c) repeat for other languages you require from the "moodle/mod/hotpot/lang" folder
OR:
(a) upload the "hotpot/lang/en/hotpot.php" file on your PC to "moodle/lang/en/hotpot.php" on the Moodle site
(b) create a folder called "hotpot" on your Moodle site in the "moodle/lang/en/help" folder
(c) upload the contents of the "hotpot/lang/en/help/hotpot" folder on your PC to the "moodle/lang/en/help/hotpot" folder on the Moodle site
(d) repeat for other languages you require from the "moodle/mod/hotpot/lang" folder
3. copy and set up the file icons
[This step is not required for Moodle 1.5 and later, and is optional for Moodle 1.1 to 1.4]
(a) copy the files in the "mod/hotpot/pix/f" folder on your Moodle site to "moodle/pix/f"
(b) open the "moodle/files/mimetypes.php" file on your Moodle site with a text editor
(c) insert the following lines just AFTER the line which reads "$mimeinfo = array (":
// additional mimetypes for the "hotpot" module
"jcb" => array ("type"=>"text/xml", "icon"=>"jcb.gif"),
"jcl" => array ("type"=>"text/xml", "icon"=>"jcl.gif"),
"jcw" => array ("type"=>"text/xml", "icon"=>"jcw.gif"),
"jmt" => array ("type"=>"text/xml", "icon"=>"jmt.gif"),
"jmx" => array ("type"=>"text/xml", "icon"=>"jmx.gif"),
"jqz" => array ("type"=>"text/xml", "icon"=>"jqz.gif"),
"rhb" => array ("type"=>"text/xml", "icon"=>"xml.gif"),
"sqt" => array ("type"=>"text/xml", "icon"=>"xml.gif"),
(d) save the changes and close the file
4. enable import from Hot Potatoes XML files to Moodle's Quiz module
[This step is not required for Moodle 1.5 and later, and is optional for Moodle 1.1 to 1.4]
(a) create a folder called "hotpot" on your Moodle site in the "moodle/mod/quiz/format" folder
(b) copy the "contents of the "moodle/mod/hotpot/quiz/format/hotpot" folder on your Moodle site to the "moodle/mod/quiz/format/hotpot" folder
(c) open the "moodle/lang/en/quiz.php" file on your Moodle site with a text editor
(d) insert the following line just BEFORE the final line which reads "?>":
$string['hotpot'] = 'Hot Potatoes XML format';
(d) save the changes and close the file
Steps (e), (f) and (g) are only required on Moodle 1.4.5
(e) open the "moodle/mod/quiz/import.php" file on your Moodle site with a text editor
(f) if necessary, add 'hotpot' to the "fileformats" array on lines 9-10:
$fileformats = array('aiken','aon','blackboard','coursetestmanager',
'gift','learnwise','missingword','webct','xml','hotpot' );
(g) save the changes and close the file
5. Login to your Moodle site as an administrator.
a) If you are installing this module for the first time, you should see a report saying that the following (prefix)_hotpot tables have been successfuly created:
hotpot
hotpot_attempts
hotpot_questions
hotpot_responses
hotpot_strings
b) If you are updating the module, you will probably see messages indicating the progress of the update
c) If you get error messages, please copy and save them to a file on your PC, and then ask for help on Moodle's HotPot support forum:
go to http://moodle.org
then click "Free Support",
then click "HotPot"
TO USE THIS MODULE:
1. Create a Hot Potatoes quiz of any type using Version 6 of Hot Potatoes.
2. Upload the quiz's source file (".jcl", ".jcw", ".jmt", ".jmx", ".jqz") or ".html" file to the file area of the intended course.
3. Also upload any graphics, sound files, stylesheets or javascripts that the quiz uses
4. On the main page for the course, confirm editing is turned on (click the "Turn editing on" button) then select "ADD / Hot Potatoes XML Quiz".
6, The "Adding a new Hot Potatoes Quiz" page appears. Click the "Choose or Upload a file ..." button and select the desired quiz file.
7. Review the other settings for the quiz and click "Save Changes" when you are ready
8. You can view reports of the results via the "Hot Potatoes Quizzes" link on the "Activities menu". Students will see links to all the quizzes. Administrators and teachers will additionally see links to the statistical reports for each quiz.
9. You can also import the questions from the Hot Potatoes source file to the Moodle Quiz database, if you installed "mod/quiz/format/hotpot/format.php"
==============================
HOT POTATOES CONDITIONS OF USE
==============================
**Reproduced from the Hot Potatoes site**
Hot Potatoes is offered free to the educational community by the University of Victoria Humanities Computing and Media Centre (formerly the Language Centre), under certain conditions. Hot Potatoes is free for use by state educational institutions which are non-profit making, on the condition that the material produced using the program is freely available to anyone via the WWW. However, you need to purchase a licence under any of the following conditions:
* You do not work for a public sector educational establishment.
* You charge money for access to the material you make with Hot Potatoes.
* You restrict access to the material in some way. (The only exception here is if you have an account on www.hotpot.net, where you ARE allowed to use password restrictions.)
* You want to use the Masher program included with the Hot Potatoes suite.
For more information on licences, and details on how to purchase one, check out our Website at:
http://www.halfbakedsoftware.com/hotpot/
If you intend using the programs to generate more than a handful of exercises, please make sure you register. This costs you nothing -- see How to register for details.
Martin Holmes, Half-Baked Software and the University of Victoria HCMC, 1998-2004.

View File

@ -1,330 +1,267 @@
<?PHP //$Id$
//This php script contains all the stuff to backup/restore
//quiz mods
//-----------------------------------------------------------
// This is the "graphical" structure of the hotpot mod:
//-----------------------------------------------------------
//
// hotpot
// (CL, pk->id,
// fk->course, files)
// |
// +--------------+---------------+
// | |
// hotpot_attempts hotpot_questions
// (UL, pk->id, (UL, pk->id,
// fk->hotpot) fk->hotpot, text)
// | | |
// +-------------------+----------+ |
// | | |
// hotpot_details hotpot_responses |
// (UL, pk->id, (UL, pk->id, |
// fk->attempt) fk->attempt, question, |
// correct, wrong, ignored) |
// | |
// +-------+-------+
// |
// hotpot_strings
// (UL, pk->id)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files
//
//-----------------------------------------------------------
function hotpot_backup_mods($bf, $preferences) {
// $bf : resource id for b(ackup) f(ile)
// $preferences : object containing switches and settings for this backup
$level = 3;
$status = true;
$table = 'hotpot';
$select = "course=$preferences->backup_course";
$records_tag = '';
$records_tags = array();
$record_tag = 'MOD';
$record_tags = array('MODTYPE'=>'hotpot');
$excluded_tags = array();
$more_backup = '';
if ($preferences->mods['hotpot']->userinfo) {
$more_backup .= '$GLOBALS["hotpot_backup_string_ids"] = array();';
$more_backup .= '$status = hotpot_backup_attempts($bf, $record, $level, $status);';
$more_backup .= '$status = hotpot_backup_questions($bf, $record, $level, $status);';
$more_backup .= '$status = hotpot_backup_strings($bf, $record, $level, $status);';
$more_backup .= 'unset($GLOBALS["hotpot_backup_string_ids"]);'; // tidy up
}
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_attempts($bf, &$parent, $level, $status) {
// $parent is a reference to a hotpot record
$table = 'hotpot_attempts';
$select = "hotpot=$parent->id";
$records_tag = 'ATTEMPT_DATA';
$records_tags = array();
$record_tag = 'ATTEMPT';
$record_tags = array();
$more_backup = '';
$more_backup .= 'hotpot_backup_details($bf, $record, $level, $status);';
$more_backup .= 'hotpot_backup_responses($bf, $record, $level, $status);';
$excluded_tags = array('hotpot');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_details($bf, &$parent, $level, $status) {
// $parent is a reference to an attempt record
$table = 'hotpot_details';
$select = "attempt=$parent->id";
$records_tag = '';
$records_tags = array();
$record_tag = '';
$record_tags = array();
$more_backup = '';
$excluded_tags = array('id','attempt');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_responses($bf, &$parent, $level, $status) {
// $parent is a reference to an attempt record
$table = 'hotpot_responses';
$select = "attempt=$parent->id";
$records_tag = 'RESPONSE_DATA';
$records_tags = array();
$record_tag = 'RESPONSE';
$record_tags = array();
$more_backup = 'hotpot_backup_string_ids($record, array("correct","wrong","ignored"));';
$excluded_tags = array('id','attempt');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_questions($bf, &$parent, $level, $status) {
// $parent is a reference to an hotpot record
$table = 'hotpot_questions';
$select = "hotpot=$parent->id";
$records_tag = 'QUESTION_DATA';
$records_tags = array();
$record_tag = 'QUESTION';
$record_tags = array();
$more_backup = 'hotpot_backup_string_ids($record, array("text"));';
$excluded_tags = array('hotpot');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_string_ids(&$record, $fields) {
// as the questions and responses tables are backed up
// this function is called to store the ids of strings.
// The string ids are used later by "hotpot_backup_strings"
// $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
// store the ids of strings used in this $record's $fields
foreach ($fields as $field) {
if (empty($record->$field)) {
// do nothing
} else {
$value = $record->$field;
$ids = explode(',', "$value");
foreach ($ids as $id) {
if (empty($id)) {
// do nothing
} else {
$GLOBALS['hotpot_backup_string_ids'][$id] = true;
}
}
}
}
}
function hotpot_backup_strings($bf, $record, $level, $status) {
// This functions backups the strings used
// in the question and responses for a single hotpot activity
// The ids of the strings were stored by "hotpot_backup_string_ids"
// $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
// retrieve $ids of strings to be backed up
$ids = array_keys($GLOBALS['hotpot_backup_string_ids']);
if (empty($ids)) {
// no strings to backup
} else {
sort($ids);
$ids = implode(',', $ids);
$table = 'hotpot_strings';
$select = "id IN ($ids)";
$records_tag = 'STRING_DATA';
$records_tags = array();
$record_tag = 'STRING';
$record_tags = array();
$more_backup = '';
$excluded_tags = array('');
$status = hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
return $status;
}
function hotpot_backup_records(&$bf, $status, $level, $table, $select, $records_tag, $records_tags, $record_tag, $record_tags, $excluded_tags, $more_backup) {
// general purpose backup function
// $bf : resource id of backup file
// $status : current status of backup (true or false)
// $level : current depth level in the backup XML tree
// $table : table from which records will be selected and backed up
// $select : SQL selection string
// $records_tag : optional XML tag which starts a group of records (and descends a level)
// $records_tags : optional XML tags to be inserted at the start of a group of records
// $record_tag : optional XML tag which starts a record (and descends a level)
// $record_tags : optional XML tags to be inserted at the start of a record
// $excluded_tags : fields which will NOT be backed up from the records
// $more_backup : optional PHP code to be eval(uated) for each record
// If any of the "fwrite" statements fail,
// no further "fwrite"s will be attempted
// and the function returns "false".
// Otherwise, the function returns "true".
if ($status && ($records = get_records_select($table, $select, 'id'))) {
// start a group of records
if ($records_tag) {
$status = $status && fwrite($bf, start_tag($records_tag, $level, true));
$level++;
foreach ($records_tags as $tag) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
foreach ($records as $record) {
// start a single record
if ($record_tag) {
$status = $status && fwrite($bf, start_tag($record_tag, $level, true));
$level++;
foreach ($record_tags as $tag=>$value) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
// backup fields in this record
$tags = get_object_vars($record);
foreach ($tags as $tag=>$value) {
if (!is_numeric($tag) && !in_array($tag, $excluded_tags)) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
// backup related records, if required
if ($more_backup) {
eval($more_backup);
}
// end a single record
if ($record_tag) {
$level--;
$status = $status && fwrite($bf, end_tag($record_tag, $level, true));
}
}
// end a group of records
if ($records_tag) {
$level--;
$status = $status && fwrite($bf, end_tag($records_tag, $level, true));
}
}
return $status;
}
////Return an array of info (name, value)
function hotpot_check_backup_mods($course, $user_data=false, $backup_unique_code) {
// the course data
$info[0][0] = get_string('modulenameplural','hotpot');
$info[0][1] = count_records('hotpot', 'course', $course);
// the user_data, if requested
if ($user_data) {
global $CFG;
$table = "{$CFG->prefix}hotpot h, {$CFG->prefix}hotpot_attempts a";
$select = "h.course = $course AND h.id = a.hotpot";
$info[1][0] = get_string('attempts', 'quiz');
$info[1][1] = count_records_sql("SELECT COUNT(*) FROM $table WHERE $select");
}
return $info;
}
?>
<?PHP //$Id$
//This php script contains all the stuff to backup/restore
//quiz mods
//-----------------------------------------------------------
// This is the "graphical" structure of the hotpot mod:
//-----------------------------------------------------------
//
// hotpot
// (CL, pk->id,
// fk->course, files)
// |
// +--------------+---------------+
// | |
// hotpot_attempts hotpot_questions
// (UL, pk->id, (UL, pk->id,
// fk->hotpot) fk->hotpot, text)
// | | |
// +-------------------+----------+ |
// | | |
// hotpot_details hotpot_responses |
// (UL, pk->id, (UL, pk->id, |
// fk->attempt) fk->attempt, question, |
// correct, wrong, ignored) |
// | |
// +-------+-------+
// |
// hotpot_strings
// (UL, pk->id)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files
//
//-----------------------------------------------------------
function hotpot_backup_mods($bf, $preferences) {
// $bf : resource id for b(ackup) f(ile)
// $preferences : object containing switches and settings for this backup
$level = 3;
$status = true;
$table = 'hotpot';
$select = "course=$preferences->backup_course";
$records_tag = '';
$records_tags = array();
$record_tag = 'MOD';
$record_tags = array('MODTYPE'=>'hotpot');
$excluded_tags = array();
$more_backup = '';
if ($preferences->mods['hotpot']->userinfo) {
$more_backup .= '$GLOBALS["hotpot_backup_string_ids"] = array();';
$more_backup .= '$status = hotpot_backup_attempts($bf, $record, $level, $status);';
$more_backup .= '$status = hotpot_backup_questions($bf, $record, $level, $status);';
$more_backup .= '$status = hotpot_backup_strings($bf, $record, $level, $status);';
$more_backup .= 'unset($GLOBALS["hotpot_backup_string_ids"]);'; // tidy up
}
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_attempts($bf, &$parent, $level, $status) {
// $parent is a reference to a hotpot record
$table = 'hotpot_attempts';
$select = "hotpot=$parent->id";
$records_tag = 'ATTEMPT_DATA';
$records_tags = array();
$record_tag = 'ATTEMPT';
$record_tags = array();
$more_backup = '';
$more_backup .= 'hotpot_backup_details($bf, $record, $level, $status);';
$more_backup .= 'hotpot_backup_responses($bf, $record, $level, $status);';
$excluded_tags = array('hotpot');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_details($bf, &$parent, $level, $status) {
// $parent is a reference to an attempt record
$table = 'hotpot_details';
$select = "attempt=$parent->id";
$records_tag = '';
$records_tags = array();
$record_tag = '';
$record_tags = array();
$more_backup = '';
$excluded_tags = array('id','attempt');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_responses($bf, &$parent, $level, $status) {
// $parent is a reference to an attempt record
$table = 'hotpot_responses';
$select = "attempt=$parent->id";
$records_tag = 'RESPONSE_DATA';
$records_tags = array();
$record_tag = 'RESPONSE';
$record_tags = array();
$more_backup = 'hotpot_backup_string_ids($record, array("correct","wrong","ignored"));';
$excluded_tags = array('id','attempt');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_questions($bf, &$parent, $level, $status) {
// $parent is a reference to an hotpot record
$table = 'hotpot_questions';
$select = "hotpot=$parent->id";
$records_tag = 'QUESTION_DATA';
$records_tags = array();
$record_tag = 'QUESTION';
$record_tags = array();
$more_backup = 'hotpot_backup_string_ids($record, array("text"));';
$excluded_tags = array('hotpot');
return hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
function hotpot_backup_string_ids(&$record, $fields) {
// as the questions and responses tables are backed up
// this function is called to store the ids of strings.
// The string ids are used later by "hotpot_backup_strings"
// $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
// store the ids of strings used in this $record's $fields
foreach ($fields as $field) {
if (empty($record->$field)) {
// do nothing
} else {
$value = $record->$field;
$ids = explode(',', "$value");
foreach ($ids as $id) {
if (empty($id)) {
// do nothing
} else {
$GLOBALS['hotpot_backup_string_ids'][$id] = true;
}
}
}
}
}
function hotpot_backup_strings($bf, $record, $level, $status) {
// This functions backups the strings used
// in the question and responses for a single hotpot activity
// The ids of the strings were stored by "hotpot_backup_string_ids"
// $GLOBALS['hotpot_backup_string_ids'] was initialized in "hotpot_backup_mods"
// retrieve $ids of strings to be backed up
$ids = array_keys($GLOBALS['hotpot_backup_string_ids']);
if (empty($ids)) {
// no strings to backup
} else {
sort($ids);
$ids = implode(',', $ids);
$table = 'hotpot_strings';
$select = "id IN ($ids)";
$records_tag = 'STRING_DATA';
$records_tags = array();
$record_tag = 'STRING';
$record_tags = array();
$more_backup = '';
$excluded_tags = array('');
$status = hotpot_backup_records(
$bf, $status, $level,
$table, $select,
$records_tag, $records_tags,
$record_tag, $record_tags,
$excluded_tags, $more_backup
);
}
return $status;
}
function hotpot_backup_records(&$bf, $status, $level, $table, $select, $records_tag, $records_tags, $record_tag, $record_tags, $excluded_tags, $more_backup) {
// general purpose backup function
// $bf : resource id of backup file
// $status : current status of backup (true or false)
// $level : current depth level in the backup XML tree
// $table : table from which records will be selected and backed up
// $select : SQL selection string
// $records_tag : optional XML tag which starts a group of records (and descends a level)
// $records_tags : optional XML tags to be inserted at the start of a group of records
// $record_tag : optional XML tag which starts a record (and descends a level)
// $record_tags : optional XML tags to be inserted at the start of a record
// $excluded_tags : fields which will NOT be backed up from the records
// $more_backup : optional PHP code to be eval(uated) for each record
// If any of the "fwrite" statements fail,
// no further "fwrite"s will be attempted
// and the function returns "false".
// Otherwise, the function returns "true".
if ($status && ($records = get_records_select($table, $select, 'id'))) {
// start a group of records
if ($records_tag) {
$status = $status && fwrite($bf, start_tag($records_tag, $level, true));
$level++;
foreach ($records_tags as $tag) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
foreach ($records as $record) {
// start a single record
if ($record_tag) {
$status = $status && fwrite($bf, start_tag($record_tag, $level, true));
$level++;
foreach ($record_tags as $tag=>$value) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
// backup fields in this record
$tags = get_object_vars($record);
foreach ($tags as $tag=>$value) {
if (!is_numeric($tag) && !in_array($tag, $excluded_tags)) {
$status = $status && fwrite($bf, full_tag($tag, $level, false, $value));
}
}
// backup related records, if required
if ($more_backup) {
eval($more_backup);
}
// end a single record
if ($record_tag) {
$level--;
$status = $status && fwrite($bf, end_tag($record_tag, $level, true));
}
}
// end a group of records
if ($records_tag) {
$level--;
$status = $status && fwrite($bf, end_tag($records_tag, $level, true));
}
}
return $status;
}
////Return an array of info (name, value)
function hotpot_check_backup_mods($course, $user_data=false, $backup_unique_code) {
// the course data
$info[0][0] = get_string('modulenameplural','hotpot');
$info[0][1] = count_records('hotpot', 'course', $course);
// the user_data, if requested
if ($user_data) {
global $CFG;
$table = "{$CFG->prefix}hotpot h, {$CFG->prefix}hotpot_attempts a";
$select = "h.course = $course AND h.id = a.hotpot";
$info[1][0] = get_string('attempts', 'quiz');
$info[1][1] = count_records_sql("SELECT COUNT(*) FROM $table WHERE $select");
}
return $info;
}
?>

View File

@ -1,43 +1,37 @@
<?PHP
function hotpot_upgrade($oldversion) {
global $CFG;
$ok = true;
if ($oldversion < 2004021400) {
execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `starttime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `endtime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
}
// update from HotPot v1 to HotPot v2
if ($oldversion < 2005031400) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_from_v1();
}
// update to HotPot v2.1
if ($oldversion < 2005090700) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1();
}
// update to from HotPot v2.1.0 or v2.1.1 to HotPot v2.1.2
if ($oldversion > 2005031419 && $oldversion < 2005090702) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1_2();
}
return $ok;
}
function hotpot_get_update_to_v2() {
global $CFG;
$filepath = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
if (file_exists($filepath) && is_readable($filepath)) {
include_once $filepath;
$ok = true;
} else {
$ok = false;
}
return $ok;
}
?>
<?PHP
function hotpot_upgrade($oldversion) {
global $CFG;
$ok = true;
if ($oldversion < 2004021400) {
execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `starttime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `endtime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
}
// update from HotPot v1 to HotPot v2
if ($oldversion < 2005031400) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_from_v1();
}
// update to HotPot v2.1
if ($oldversion < 2005090700) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1();
}
// update to from HotPot v2.1.0 or v2.1.1 to HotPot v2.1.2
if ($oldversion > 2005031419 && $oldversion < 2005090702) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1_2();
}
return $ok;
}
function hotpot_get_update_to_v2() {
global $CFG;
$filepath = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
if (file_exists($filepath) && is_readable($filepath)) {
include_once $filepath;
$ok = true;
} else {
$ok = false;
}
return $ok;
}
?>

View File

@ -1,112 +1,101 @@
#
# Table structure for table `hotpot`
#
CREATE TABLE prefix_hotpot (
id int(10) unsigned NOT NULL auto_increment,
course int(10) unsigned NOT NULL default '0',
name varchar(255) NOT NULL default '',
reference varchar(255) NOT NULL default '',
summary text NOT NULL,
timeopen int(10) unsigned NOT NULL default '0',
timeclose int(10) unsigned NOT NULL default '0',
attempts smallint(6) NOT NULL default '0',
grademethod tinyint(4) NOT NULL default '1',
review tinyint(4) NOT NULL default '0',
grade int(10) NOT NULL default '0',
timecreated int(10) unsigned NOT NULL default '0',
timemodified int(10) unsigned NOT NULL default '0',
location int(4) unsigned NOT NULL default '0',
navigation int(4) unsigned NOT NULL default '1',
outputformat int(4) unsigned NOT NULL default '1',
shownextquiz int(4) unsigned NOT NULL default '0',
forceplugins int(4) unsigned NOT NULL default '0',
password varchar(255) NOT NULL default '',
subnet varchar(255) NOT NULL default '',
clickreporting tinyint(4) unsigned NOT NULL default '0',
studentfeedback tinyint(4) unsigned NOT NULL default '0',
studentfeedbackurl varchar(255) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM COMMENT='details about Hot Potatoes quizzes';
#
# Table structure for table `hotpot_attempts`
#
CREATE TABLE prefix_hotpot_attempts (
id int(10) unsigned NOT NULL auto_increment,
hotpot int(10) unsigned NOT NULL default '0',
userid int(10) unsigned NOT NULL default '0',
starttime int(10) unsigned default NULL,
endtime int(10) unsigned default NULL,
score int(6) unsigned default NULL,
penalties int(6) unsigned default NULL,
attempt int(6) unsigned NOT NULL default '0',
timestart int(10) unsigned default NULL,
timefinish int(10) unsigned default NULL,
status tinyint(4) unsigned NOT NULL default '1',
clickreportid int(10) unsigned default NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_attempts_hotpot_idx (hotpot),
KEY prefix_hotpot_attempts_userid_idx (userid)
) TYPE=MyISAM COMMENT='details about Hot Potatoes quiz attempts';
#
# Table structure for table `hotpot_details`
#
CREATE TABLE prefix_hotpot_details (
id int(10) unsigned NOT NULL auto_increment,
attempt int(10) unsigned NOT NULL,
details text,
PRIMARY KEY (id),
KEY prefix_hotpot_details_attempt_idx (attempt)
) TYPE=MyISAM COMMENT='raw details (as XML) of Hot Potatoes quiz attempts';
#
# Table structure for table `hotpot_questions`
#
CREATE TABLE prefix_hotpot_questions (
id int(10) unsigned NOT NULL auto_increment,
name text NOT NULL,
type tinyint(4) unsigned default NULL,
text int(10) unsigned default NULL,
hotpot int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id),
KEY prefix_hotpot_questions_name_idx (name(20)),
KEY prefix_hotpot_questions_hotpot_idx (hotpot)
) TYPE=MyISAM COMMENT='details about questions in Hot Potatatoes quiz attempts';
#
# Table structure for table `hotpot_responses`
#
CREATE TABLE prefix_hotpot_responses (
id int(10) unsigned NOT NULL auto_increment,
attempt int(10) unsigned NOT NULL default '0',
question int(10) unsigned NOT NULL default '0',
score smallint(8) default NULL,
weighting smallint(8) default NULL,
correct varchar(255) default NULL,
wrong varchar(255) default NULL,
ignored varchar(255) default NULL,
hints smallint(6) default NULL,
clues smallint(6) default NULL,
checks smallint(6) default NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_responses_attempt_idx (attempt),
KEY prefix_hotpot_responses_question_idx (question)
) TYPE=MyISAM COMMENT='details about responses in Hot Potatatoes quiz attempts';
#
# Table structure for table `hotpot_strings`
#
CREATE TABLE prefix_hotpot_strings (
id int(10) unsigned NOT NULL auto_increment,
string text NOT NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_strings_string_idx (string(20))
) TYPE=MyISAM COMMENT='strings used in Hot Potatatoes questions and responses';
#
# Table structure for table `hotpot`
#
CREATE TABLE prefix_hotpot (
id int(10) unsigned NOT NULL auto_increment,
course int(10) unsigned NOT NULL default '0',
name varchar(255) NOT NULL default '',
reference varchar(255) NOT NULL default '',
summary text NOT NULL,
timeopen int(10) unsigned NOT NULL default '0',
timeclose int(10) unsigned NOT NULL default '0',
attempts smallint(6) NOT NULL default '0',
grademethod tinyint(4) NOT NULL default '1',
review tinyint(4) NOT NULL default '0',
grade int(10) NOT NULL default '0',
timecreated int(10) unsigned NOT NULL default '0',
timemodified int(10) unsigned NOT NULL default '0',
location int(4) unsigned NOT NULL default '0',
navigation int(4) unsigned NOT NULL default '1',
outputformat int(4) unsigned NOT NULL default '1',
shownextquiz int(4) unsigned NOT NULL default '0',
forceplugins int(4) unsigned NOT NULL default '0',
password varchar(255) NOT NULL default '',
subnet varchar(255) NOT NULL default '',
clickreporting tinyint(4) unsigned NOT NULL default '0',
studentfeedback tinyint(4) unsigned NOT NULL default '0',
studentfeedbackurl varchar(255) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM COMMENT='details about Hot Potatoes quizzes';
#
# Table structure for table `hotpot_attempts`
#
CREATE TABLE prefix_hotpot_attempts (
id int(10) unsigned NOT NULL auto_increment,
hotpot int(10) unsigned NOT NULL default '0',
userid int(10) unsigned NOT NULL default '0',
starttime int(10) unsigned default NULL,
endtime int(10) unsigned default NULL,
score int(6) unsigned default NULL,
penalties int(6) unsigned default NULL,
attempt int(6) unsigned NOT NULL default '0',
timestart int(10) unsigned default NULL,
timefinish int(10) unsigned default NULL,
status tinyint(4) unsigned NOT NULL default '1',
clickreportid int(10) unsigned default NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_attempts_hotpot_idx (hotpot),
KEY prefix_hotpot_attempts_userid_idx (userid)
) TYPE=MyISAM COMMENT='details about Hot Potatoes quiz attempts';
#
# Table structure for table `hotpot_details`
#
CREATE TABLE prefix_hotpot_details (
id int(10) unsigned NOT NULL auto_increment,
attempt int(10) unsigned NOT NULL,
details text,
PRIMARY KEY (id),
KEY prefix_hotpot_details_attempt_idx (attempt)
) TYPE=MyISAM COMMENT='raw details (as XML) of Hot Potatoes quiz attempts';
#
# Table structure for table `hotpot_questions`
#
CREATE TABLE prefix_hotpot_questions (
id int(10) unsigned NOT NULL auto_increment,
name text NOT NULL,
type tinyint(4) unsigned default NULL,
text int(10) unsigned default NULL,
hotpot int(10) unsigned NOT NULL default '0',
PRIMARY KEY (id),
KEY prefix_hotpot_questions_name_idx (name(20)),
KEY prefix_hotpot_questions_hotpot_idx (hotpot)
) TYPE=MyISAM COMMENT='details about questions in Hot Potatatoes quiz attempts';
#
# Table structure for table `hotpot_responses`
#
CREATE TABLE prefix_hotpot_responses (
id int(10) unsigned NOT NULL auto_increment,
attempt int(10) unsigned NOT NULL default '0',
question int(10) unsigned NOT NULL default '0',
score smallint(8) default NULL,
weighting smallint(8) default NULL,
correct varchar(255) default NULL,
wrong varchar(255) default NULL,
ignored varchar(255) default NULL,
hints smallint(6) default NULL,
clues smallint(6) default NULL,
checks smallint(6) default NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_responses_attempt_idx (attempt),
KEY prefix_hotpot_responses_question_idx (question)
) TYPE=MyISAM COMMENT='details about responses in Hot Potatatoes quiz attempts';
#
# Table structure for table `hotpot_strings`
#
CREATE TABLE prefix_hotpot_strings (
id int(10) unsigned NOT NULL auto_increment,
string text NOT NULL,
PRIMARY KEY (id),
KEY prefix_hotpot_strings_string_idx (string(20))
) TYPE=MyISAM COMMENT='strings used in Hot Potatatoes questions and responses';

View File

@ -1,39 +1,33 @@
<?PHP
function hotpot_upgrade($oldversion) {
global $CFG;
$ok = true;
// update from HotPot v1 to HotPot v2
if ($oldversion < 2005031400) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_from_v1();
}
// update to HotPot v2.1
if ($oldversion < 2005090700) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1();
}
// update to from HotPot v2.1.0 or v2.1.1 to HotPot v2.1.2
if ($oldversion > 2005031419 && $oldversion < 2005090702) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1_2();
}
return $ok;
}
function hotpot_get_update_to_v2() {
global $CFG;
$filepath = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
if (file_exists($filepath) && is_readable($filepath)) {
include_once $filepath;
$ok = true;
} else {
$ok = false;
}
return $ok;
}
?>
<?PHP
function hotpot_upgrade($oldversion) {
global $CFG;
$ok = true;
// update from HotPot v1 to HotPot v2
if ($oldversion < 2005031400) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_from_v1();
}
// update to HotPot v2.1
if ($oldversion < 2005090700) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1();
}
// update to from HotPot v2.1.0 or v2.1.1 to HotPot v2.1.2
if ($oldversion > 2005031419 && $oldversion < 2005090702) {
$ok = $ok && hotpot_get_update_to_v2();
$ok = $ok && hotpot_update_to_v2_1_2();
}
return $ok;
}
function hotpot_get_update_to_v2() {
global $CFG;
$filepath = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
if (file_exists($filepath) && is_readable($filepath)) {
include_once $filepath;
$ok = true;
} else {
$ok = false;
}
return $ok;
}
?>

View File

@ -1,114 +1,98 @@
#
# Table structure for table `hotpot`
#
CREATE TABLE prefix_hotpot (
id SERIAL PRIMARY KEY,
course INT4 NOT NULL default '0',
name VARCHAR(255) NOT NULL default '',
summary TEXT,
timeopen INT4 NOT NULL default '0',
timeclose INT4 NOT NULL default '0',
location INT2 NOT NULL default '0',
reference VARCHAR(255) NOT NULL default '',
navigation INT2 NOT NULL default '1',
outputformat INT2 NOT NULL default '1',
forceplugins INT2 NOT NULL default '0',
shownextquiz INT2 NOT NULL default '0',
microreporting INT2 NOT NULL default '0',
studentfeedback VARCHAR(255) NOT NULL default '0',
review INT2 NOT NULL default '0',
grade INT4 NOT NULL default '0',
grademethod INT2 NOT NULL default '1',
attempts INT2 NOT NULL default '0',
password VARCHAR(255) NOT NULL default '',
subnet VARCHAR(255) NOT NULL default '',
timecreated INT4 NOT NULL default '0',
timemodified INT4 NOT NULL default '0'
);
COMMENT ON TABLE prefix_hotpot IS 'details about Hot Potatoes quizzes';
#
# Table structure for table `hotpot_attempts`
#
CREATE TABLE prefix_hotpot_attempts (
id SERIAL PRIMARY KEY,
hotpot INT4 NOT NULL default '0',
userid INT4 NOT NULL default '0',
groupid INT4 NOT NULL default '0',
attempt INT2 NOT NULL default '0',
score INT2,
penalties INT2,
starttime INT4,
endtime INT4,
timestart INT4 NOT NULL default '0',
timefinish INT4 NOT NULL default '0',
status INT2 NOT NULL default '1',
microreportid INT4
);
COMMENT ON TABLE prefix_hotpot IS 'details about Hot Potatoes quiz attempts';
CREATE INDEX prefix_hotpot_attempts_hotpot_idx ON prefix_hotpot_attempts (hotpot);
CREATE INDEX prefix_hotpot_attempts_userid_idx ON prefix_hotpot_attempts (userid);
#
# Table structure for table `prefix_hotpot_details`
#
CREATE TABLE prefix_hotpot_details (
id SERIAL PRIMARY KEY,
attempt INT4 NOT NULL default '0',
details TEXT
);
COMMENT ON TABLE prefix_hotpot_details IS 'raw details (as XML) of Hot Potatoes quiz attempts';
CREATE INDEX prefix_hotpot_details_attempt_idx ON prefix_hotpot_details (attempt);
#
# Table structure for table `hotpot_questions`
#
CREATE TABLE prefix_hotpot_questions (
id SERIAL PRIMARY KEY,
name TEXT,
type INT2 NOT NULL default '0',
text INT4 NULL,
hotpot INT4 NOT NULL default '0'
);
COMMENT ON TABLE prefix_hotpot_questions IS 'details about questions in Hot Potatatoes quiz attempts';
CREATE INDEX prefix_hotpot_questions_hotpot_idx ON prefix_hotpot_questions (hotpot);
#
# Table structure for table `hotpot_responses`
#
CREATE TABLE prefix_hotpot_responses (
id SERIAL PRIMARY KEY,
attempt INT4 NOT NULL default '0',
question INT4 NOT NULL default '0',
score INT2,
weighting INT2,
correct VARCHAR(255),
wrong VARCHAR(255),
ignored VARCHAR(255),
hints INT2,
clues INT2,
checks INT2
);
COMMENT ON TABLE prefix_hotpot_responses IS 'details about responses in Hot Potatatoes quiz attempts';
CREATE INDEX prefix_hotpot_responses_attempt_idx ON prefix_hotpot_responses (attempt);
CREATE INDEX prefix_hotpot_responses_question_idx ON prefix_hotpot_responses (question);
#
# Table structure for table `hotpot_strings`
#
CREATE TABLE prefix_hotpot_strings (
id SERIAL PRIMARY KEY,
string TEXT NOT NULL
);
COMMENT ON TABLE prefix_hotpot_strings IS 'strings used in Hot Potatatoes questions and responses';
#
# Table structure for table `hotpot`
#
CREATE TABLE prefix_hotpot (
id SERIAL PRIMARY KEY,
course INT4 NOT NULL default '0',
name VARCHAR(255) NOT NULL default '',
summary TEXT,
timeopen INT4 NOT NULL default '0',
timeclose INT4 NOT NULL default '0',
location INT2 NOT NULL default '0',
reference VARCHAR(255) NOT NULL default '',
navigation INT2 NOT NULL default '1',
outputformat INT2 NOT NULL default '1',
forceplugins INT2 NOT NULL default '0',
shownextquiz INT2 NOT NULL default '0',
microreporting INT2 NOT NULL default '0',
studentfeedback VARCHAR(255) NOT NULL default '0',
review INT2 NOT NULL default '0',
grade INT4 NOT NULL default '0',
grademethod INT2 NOT NULL default '1',
attempts INT2 NOT NULL default '0',
password VARCHAR(255) NOT NULL default '',
subnet VARCHAR(255) NOT NULL default '',
timecreated INT4 NOT NULL default '0',
timemodified INT4 NOT NULL default '0'
);
COMMENT ON TABLE prefix_hotpot IS 'details about Hot Potatoes quizzes';
#
# Table structure for table `hotpot_attempts`
#
CREATE TABLE prefix_hotpot_attempts (
id SERIAL PRIMARY KEY,
hotpot INT4 NOT NULL default '0',
userid INT4 NOT NULL default '0',
groupid INT4 NOT NULL default '0',
attempt INT2 NOT NULL default '0',
score INT2,
penalties INT2,
starttime INT4,
endtime INT4,
timestart INT4 NOT NULL default '0',
timefinish INT4 NOT NULL default '0',
status INT2 NOT NULL default '1',
microreportid INT4
);
COMMENT ON TABLE prefix_hotpot IS 'details about Hot Potatoes quiz attempts';
CREATE INDEX prefix_hotpot_attempts_hotpot_idx ON prefix_hotpot_attempts (hotpot);
CREATE INDEX prefix_hotpot_attempts_userid_idx ON prefix_hotpot_attempts (userid);
#
# Table structure for table `prefix_hotpot_details`
#
CREATE TABLE prefix_hotpot_details (
id SERIAL PRIMARY KEY,
attempt INT4 NOT NULL default '0',
details TEXT
);
COMMENT ON TABLE prefix_hotpot_details IS 'raw details (as XML) of Hot Potatoes quiz attempts';
CREATE INDEX prefix_hotpot_details_attempt_idx ON prefix_hotpot_details (attempt);
#
# Table structure for table `hotpot_questions`
#
CREATE TABLE prefix_hotpot_questions (
id SERIAL PRIMARY KEY,
name TEXT,
type INT2 NOT NULL default '0',
text INT4 NULL,
hotpot INT4 NOT NULL default '0'
);
COMMENT ON TABLE prefix_hotpot_questions IS 'details about questions in Hot Potatatoes quiz attempts';
CREATE INDEX prefix_hotpot_questions_hotpot_idx ON prefix_hotpot_questions (hotpot);
#
# Table structure for table `hotpot_responses`
#
CREATE TABLE prefix_hotpot_responses (
id SERIAL PRIMARY KEY,
attempt INT4 NOT NULL default '0',
question INT4 NOT NULL default '0',
score INT2,
weighting INT2,
correct VARCHAR(255),
wrong VARCHAR(255),
ignored VARCHAR(255),
hints INT2,
clues INT2,
checks INT2
);
COMMENT ON TABLE prefix_hotpot_responses IS 'details about responses in Hot Potatatoes quiz attempts';
CREATE INDEX prefix_hotpot_responses_attempt_idx ON prefix_hotpot_responses (attempt);
CREATE INDEX prefix_hotpot_responses_question_idx ON prefix_hotpot_responses (question);
#
# Table structure for table `hotpot_strings`
#
CREATE TABLE prefix_hotpot_strings (
id SERIAL PRIMARY KEY,
string TEXT NOT NULL
);
COMMENT ON TABLE prefix_hotpot_strings IS 'strings used in Hot Potatatoes questions and responses';

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +1,52 @@
<!--
function domSniffer() {
var t = true;
var s = navigator.userAgent;
if (s.indexOf("Mac") >=0) this.mac = t;
if (s.indexOf("Opera") >=0) this.opera = t;
var d = document;
if (d.layers) this.n4 = t;
if (d.childNodes) this.dom = t;
if (d.all && d.plugins) this.ie = t;
}
function getContentH(lyr) {
return (is.n4) ? lyr.document.height : (is.ie) ? (is.mac ? lyr.offsetHeight : lyr.scrollHeight) : (is.opera) ? lyr.style.pixelHeight : (is.dom) ? lyr.offsetHeight : 0;
}
function px(i) {
return i + "px";
}
function setSize(obj, w, h) {
if (is.n4) {
if (w) obj.width = w;
if (h) obj.height = h;
} else if (is.opera) {
// opera 5 needs pixelWidth/Height
if (w) obj.style.pixelWidth = w;
if (h) obj.style.pixelHeight = h;
} else {
if (w) obj.style.width = px(w);
if (h) obj.style.height = px(h);
}
}
function getElement(id, lyr) {
var d = (document.layers && lyr) ? lyr.document : document;
var obj = (document.layers) ? eval("d."+id) : (d.all) ? d.all[id] : (d.getElementById) ? d.getElementById(id) : null;
return obj;
}
is = new domSniffer();
function set_iframe_height(id) {
var iframe = getElement(id);
if (iframe) {
var obj = iframe.document || iframe.contentDocument || null; // IE || FireFox
if (obj) {
if (obj.body) {
obj = obj.body;
}
var h = getContentH(obj);
if (h) {
setSize(iframe, 0, h);
}
}
}
}
//-->
<!--
function domSniffer() {
var t = true;
var s = navigator.userAgent;
if (s.indexOf("Mac") >=0) this.mac = t;
if (s.indexOf("Opera") >=0) this.opera = t;
var d = document;
if (d.layers) this.n4 = t;
if (d.childNodes) this.dom = t;
if (d.all && d.plugins) this.ie = t;
}
function getContentH(lyr) {
return (is.n4) ? lyr.document.height : (is.ie) ? (is.mac ? lyr.offsetHeight : lyr.scrollHeight) : (is.opera) ? lyr.style.pixelHeight : (is.dom) ? lyr.offsetHeight : 0;
}
function px(i) {
return i + "px";
}
function setSize(obj, w, h) {
if (is.n4) {
if (w) obj.width = w;
if (h) obj.height = h;
} else if (is.opera) {
// opera 5 needs pixelWidth/Height
if (w) obj.style.pixelWidth = w;
if (h) obj.style.pixelHeight = h;
} else {
if (w) obj.style.width = px(w);
if (h) obj.style.height = px(h);
}
}
function getElement(id, lyr) {
var d = (document.layers && lyr) ? lyr.document : document;
var obj = (document.layers) ? eval("d."+id) : (d.all) ? d.all[id] : (d.getElementById) ? d.getElementById(id) : null;
return obj;
}
is = new domSniffer();
function set_iframe_height(id) {
var iframe = getElement(id);
if (iframe) {
var obj = iframe.document || iframe.contentDocument || null; // IE || FireFox
if (obj) {
if (obj.body) {
obj = obj.body;
}
var h = getContentH(obj);
if (h) {
setSize(iframe, 0, h);
}
}
}
}
//-->

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,210 +1,167 @@
<?php // $Id$
/// Overview report just displays a big table of all the attempts
class hotpot_report extends hotpot_default_report {
function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
$this->create_overview_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables=array());
$this->print_report($course, $hotpot, $tables, $options);
return true;
}
function create_overview_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
global $CFG;
$strtimeformat = get_string('strftimedatetime');
$is_html = ($options['reportformat']=='htm');
$spacer = $is_html ? '&nbsp;' : ' ';
$br = $is_html ? "<br />\n" : "\n";
// initialize $table
unset($table);
$table->border = 1;
$table->width = 10;
$table->head = array();
$table->align = array();
$table->size = array();
$table->wrap = array();
// picture column, if required
if ($is_html) {
$table->head[] = $spacer;
$table->align[] = 'center';
$table->size[] = 10;
$table->wrap[] = "nowrap";
}
array_push($table->head,
get_string("name"),
hotpot_grade_heading($hotpot, $options),
get_string("attempt", "quiz"),
get_string("time", "quiz"),
get_string("reportstatus", "hotpot"),
get_string("timetaken", "quiz"),
get_string("score", "quiz")
);
array_push($table->align, "left", "center", "center", "left", "center", "center", "center");
array_push($table->wrap, "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");
array_push($table->size, "*", "*", "*", "*", "*", "*", "*");
$abandoned = 0;
foreach ($users as $user) {
// shortcut to user info held in first attempt record
$u = &$user->attempts[0];
$picture = '';
$name = fullname($u);
if ($is_html) {
$picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);
$name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';
}
$grade = isset($user->grade) ? $user->grade : $spacer;
$attemptcount = count($user->attempts);
if ($attemptcount>1) {
$text = $name;
$name = NULL;
$name->text = $text;
$name->rowspan = $attemptcount;
$text = $grade;
$grade = NULL;
$grade->text = $text;
$grade->rowspan = $attemptcount;
}
$data = array();
if ($is_html) {
if ($attemptcount>1) {
$text = $picture;
$picture = NULL;
$picture->text = $text;
$picture->rowspan = $attemptcount;
}
$data[] = $picture;
}
array_push($data, $name, $grade);
foreach ($user->attempts as $attempt) {
// increment count of abandoned attempts
// if attempt is marked as finished but has no score
if ($attempt->status==HOTPOT_STATUS_ABANDONED) {
$abandoned++;
}
$attemptnumber = $attempt->attempt;
$starttime = trim(userdate($attempt->timestart, $strtimeformat));
if ($is_html && isset($attempt->score) && (isteacher($course->id) || $hotpot->review)) {
$attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';
$starttime = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$starttime.'</a>';
}
if ($is_html && isteacher($course->id)) {
$checkbox = '<input type=checkbox name="box'.$attempt->clickreportid.'" value="'.$attempt->clickreportid.'">'.$spacer;
} else {
$checkbox = '';
}
$timetaken = empty($attempt->timefinish) ? $spacer : format_time($attempt->timefinish - $attempt->timestart);
$score = hotpot_format_score($attempt);
if ($is_html && is_numeric($score) && $score==$user->grade) { // best grade
$score = '<span class="highlight">'.$score.'</span>';
}
array_push($data,
$attemptnumber,
$checkbox.$starttime,
hotpot_format_status($attempt),
$timetaken,
$score
);
$table->data[] = $data;
$data = array();
} // end foreach $attempt
$table->data[] = 'hr';
} // end foreach $user
// remove final 'hr' from data rows
array_pop($table->data);
// add the "delete" form to the table
if ($options['reportformat']=='htm' && isteacher($course->id)) {
$strdeletecheck = get_string('deleteattemptcheck','quiz');
$table->start = $this->deleteform_javascript();
$table->start .= '<form method="post" action="report.php" name="deleteform" onsubmit="'."return deletecheck('".$strdeletecheck."', 'selection')".'">'."\n";
$table->start .= '<input type="hidden" name="del" value="selection">'."\n";
$table->start .= '<input type="hidden" name="id" value="'.$cm->id.'">'."\n";
$table->finish = '<center>'."\n";
$table->finish .= '<input type="submit" value="'.get_string("deleteselected").'">&nbsp;'."\n";
if ($abandoned) {
$table->finish .= '<input type=button value="'.get_string('deleteabandoned', 'hotpot').'" onClick="if(deletecheck('."'".addslashes(get_string('deleteabandonedcheck', 'hotpot', $abandoned))."', 'abandoned', true".'))document.deleteform.submit();">'."\n";
}
$table->finish .= '<input type=button value="'.get_string("deleteall").'" onClick="if(deletecheck('."'".addslashes($strdeletecheck)."', 'all', true".'))document.deleteform.submit();">'."\n";
$table->finish .= '</center>'."\n";
$table->finish .= '</form>'."\n";
}
$tables[] = &$table;
}
function deleteform_javascript() {
$strselectattempt = addslashes(get_string('selectattempt','hotpot'));
return <<<END_OF_JAVASCRIPT
<script type="text/javascript">
<!--
function deletecheck(p, v, x) {
var r = false; // result
// get length of form elements
var f = document.deleteform;
var l = f ? f.elements.length : 0;
// count selected items, if necessary
if (!x) {
x = 0;
for (var i=0; i<l; i++) {
var obj = f.elements[i];
if (obj.type && obj.type=='checkbox' && obj.checked) {
x++;
}
}
}
// confirm deletion
var n = navigator;
if (x || (n.appName=='Netscape' && parseint(n.appVersion)==2)) {
r = confirm(p);
if (r) {
f.del.value = v;
}
} else {
alert('$strselectattempt');
}
return r;
}
//-->
</script>
END_OF_JAVASCRIPT
;
} // end function
} // end class
?>
<?php // $Id$
/// Overview report just displays a big table of all the attempts
class hotpot_report extends hotpot_default_report {
function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
$this->create_overview_table($hotpot, $cm, $course, $users, $attempts, $questions, $options, $tables=array());
$this->print_report($course, $hotpot, $tables, $options);
return true;
}
function create_overview_table(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
global $CFG;
$strtimeformat = get_string('strftimedatetime');
$is_html = ($options['reportformat']=='htm');
$spacer = $is_html ? '&nbsp;' : ' ';
$br = $is_html ? "<br />\n" : "\n";
// initialize $table
unset($table);
$table->border = 1;
$table->width = 10;
$table->head = array();
$table->align = array();
$table->size = array();
$table->wrap = array();
// picture column, if required
if ($is_html) {
$table->head[] = $spacer;
$table->align[] = 'center';
$table->size[] = 10;
$table->wrap[] = "nowrap";
}
array_push($table->head,
get_string("name"),
hotpot_grade_heading($hotpot, $options),
get_string("attempt", "quiz"),
get_string("time", "quiz"),
get_string("reportstatus", "hotpot"),
get_string("timetaken", "quiz"),
get_string("score", "quiz")
);
array_push($table->align, "left", "center", "center", "left", "center", "center", "center");
array_push($table->wrap, "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");
array_push($table->size, "*", "*", "*", "*", "*", "*", "*");
$abandoned = 0;
foreach ($users as $user) {
// shortcut to user info held in first attempt record
$u = &$user->attempts[0];
$picture = '';
$name = fullname($u);
if ($is_html) {
$picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);
$name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';
}
$grade = isset($user->grade) ? $user->grade : $spacer;
$attemptcount = count($user->attempts);
if ($attemptcount>1) {
$text = $name;
$name = NULL;
$name->text = $text;
$name->rowspan = $attemptcount;
$text = $grade;
$grade = NULL;
$grade->text = $text;
$grade->rowspan = $attemptcount;
}
$data = array();
if ($is_html) {
if ($attemptcount>1) {
$text = $picture;
$picture = NULL;
$picture->text = $text;
$picture->rowspan = $attemptcount;
}
$data[] = $picture;
}
array_push($data, $name, $grade);
foreach ($user->attempts as $attempt) {
// increment count of abandoned attempts
// if attempt is marked as finished but has no score
if ($attempt->status==HOTPOT_STATUS_ABANDONED) {
$abandoned++;
}
$attemptnumber = $attempt->attempt;
$starttime = trim(userdate($attempt->timestart, $strtimeformat));
if ($is_html && isset($attempt->score) && (isteacher($course->id) || $hotpot->review)) {
$attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';
$starttime = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$starttime.'</a>';
}
if ($is_html && isteacher($course->id)) {
$checkbox = '<input type=checkbox name="box'.$attempt->clickreportid.'" value="'.$attempt->clickreportid.'">'.$spacer;
} else {
$checkbox = '';
}
$timetaken = empty($attempt->timefinish) ? $spacer : format_time($attempt->timefinish - $attempt->timestart);
$score = hotpot_format_score($attempt);
if ($is_html && is_numeric($score) && $score==$user->grade) { // best grade
$score = '<span class="highlight">'.$score.'</span>';
}
array_push($data,
$attemptnumber,
$checkbox.$starttime,
hotpot_format_status($attempt),
$timetaken,
$score
);
$table->data[] = $data;
$data = array();
} // end foreach $attempt
$table->data[] = 'hr';
} // end foreach $user
// remove final 'hr' from data rows
array_pop($table->data);
// add the "delete" form to the table
if ($options['reportformat']=='htm' && isteacher($course->id)) {
$strdeletecheck = get_string('deleteattemptcheck','quiz');
$table->start = $this->deleteform_javascript();
$table->start .= '<form method="post" action="report.php" name="deleteform" onsubmit="'."return deletecheck('".$strdeletecheck."', 'selection')".'">'."\n";
$table->start .= '<input type="hidden" name="del" value="selection">'."\n";
$table->start .= '<input type="hidden" name="id" value="'.$cm->id.'">'."\n";
$table->finish = '<center>'."\n";
$table->finish .= '<input type="submit" value="'.get_string("deleteselected").'">&nbsp;'."\n";
if ($abandoned) {
$table->finish .= '<input type=button value="'.get_string('deleteabandoned', 'hotpot').'" onClick="if(deletecheck('."'".addslashes(get_string('deleteabandonedcheck', 'hotpot', $abandoned))."', 'abandoned', true".'))document.deleteform.submit();">'."\n";
}
$table->finish .= '<input type=button value="'.get_string("deleteall").'" onClick="if(deletecheck('."'".addslashes($strdeletecheck)."', 'all', true".'))document.deleteform.submit();">'."\n";
$table->finish .= '</center>'."\n";
$table->finish .= '</form>'."\n";
}
$tables[] = &$table;
}
function deleteform_javascript() {
$strselectattempt = addslashes(get_string('selectattempt','hotpot'));
return <<<END_OF_JAVASCRIPT
<script type="text/javascript">
<!--
function deletecheck(p, v, x) {
var r = false; // result
// get length of form elements
var f = document.deleteform;
var l = f ? f.elements.length : 0;
// count selected items, if necessary
if (!x) {
x = 0;
for (var i=0; i<l; i++) {
var obj = f.elements[i];
if (obj.type && obj.type=='checkbox' && obj.checked) {
x++;
}
}
}
// confirm deletion
var n = navigator;
if (x || (n.appName=='Netscape' && parseint(n.appVersion)==2)) {
r = confirm(p);
if (r) {
f.del.value = v;
}
} else {
alert('$strselectattempt');
}
return r;
}
//-->
</script>
END_OF_JAVASCRIPT
;
} // end function
} // end class
?>

View File

@ -1,250 +1,203 @@
<?php // $Id$
/// Overview report: displays a big table of all the attempts
class hotpot_report extends hotpot_default_report {
function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
global $CFG;
// create the table
$tables = array();
$this->create_scores_table($hotpot, $course, $users, $attempts, $questions, $options, $tables);
$this->print_report($course, $hotpot, $tables, $options);
return true;
}
function create_scores_table(&$hotpot, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
global $CFG;
$download = ($options['reportformat']=='htm') ? false : true;
$is_html = ($options['reportformat']=='htm');
$blank = ($download ? '' : '&nbsp;');
$no_value = ($download ? '' : '-');
$allow_review = true; // ($options['reportformat']=='htm' && (isteacher($course->id) || $hotpot->review));
// start the table
unset($table);
$table->border = 1;
$table->head = array();
$table->align = array();
$table->size = array();
// picture column, if required
if ($is_html) {
$table->head[] = '&nbsp;';
$table->align[] = 'center';
$table->size[] = 10;
}
// name, grade and attempt number
array_push($table->head,
get_string("name"),
hotpot_grade_heading($hotpot, $options),
get_string("attempt", "quiz")
);
array_push($table->align, "left", "center", "center");
array_push($table->size, '', '', '');
// question headings
$this->add_question_headings($questions, $table);
// penalties and raw score
array_push($table->head,
get_string('penalties', 'hotpot'),
get_string('score', 'quiz')
);
array_push($table->align, "center", "center");
array_push($table->size, '', '');
$table->data = array();
$q = array(
'grade' => array('count'=>0, 'total'=>0),
'penalties' => array('count'=>0, 'total'=>0),
'score' => array('count'=>0, 'total'=>0),
);
foreach ($users as $user) {
// shortcut to user info held in first attempt record
$u = &$user->attempts[0];
$picture = '';
$name = fullname($u);
if ($is_html) {
$picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);
$name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';
}
if (isset($user->grade)) {
$grade = $user->grade;
$q['grade']['count'] ++;
if (is_numeric($grade)) {
$q['grade']['total'] += $grade;
}
} else {
$grade = $no_value;
}
$attemptcount = count($user->attempts);
if ($attemptcount>1) {
$text = $name;
$name = NULL;
$name->text = $text;
$name->rowspan = $attemptcount;
$text = $grade;
$grade = NULL;
$grade->text = $text;
$grade->rowspan = $attemptcount;
}
$data = array();
if ($is_html) {
if ($attemptcount>1) {
$text = $picture;
$picture = NULL;
$picture->text = $text;
$picture->rowspan = $attemptcount;
}
$data[] = $picture;
}
array_push($data, $name, $grade);
foreach ($user->attempts as $attempt) {
// set flag if this is best grade
$is_best_grade = ($is_html && $attempt->score==$user->grade);
// get attempt number
$attemptnumber= $attempt->attempt;
if ($is_html && $allow_review) {
$attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';
}
if ($is_best_grade) {
$score = '<span class="highlight">'.$attemptnumber.'</span>';
}
$data[] = $attemptnumber;
// get responses to questions in this attempt by this user
foreach ($questions as $id=>$question) {
if (!isset($q[$id])) {
$q[$id] = array('count'=>0, 'total'=>0);
}
if (isset($attempt->responses[$id])) {
$score = $attempt->responses[$id]->score;
if (is_numeric($score)) {
$q[$id]['count'] ++;
$q[$id]['total'] += $score;
if ($is_best_grade) {
$score = '<span class="highlight">'.$score.'</span>';
}
} else if (empty($score)) {
$score = $no_value;
}
} else {
$score = $no_value;
}
$data[] = $score;
} // foreach $questions
if (isset($attempt->penalties)) {
$penalties = $attempt->penalties;
if (is_numeric($penalties)) {
$q['penalties']['count'] ++;
$q['penalties']['total'] += $penalties;
}
if ($is_best_grade) {
$penalties = '<span class="highlight">'.$penalties.'</span>';
}
} else {
$penalties = $no_value;
}
$data[] = $penalties;
if (isset($attempt->score)) {
$score = $attempt->score;
if (is_numeric($score)) {
$q['score']['total'] += $score;
$q['score']['count'] ++;
}
if ($is_best_grade) {
$score = '<span class="highlight">'.$score.'</span>';
}
} else {
$score = $no_value;
}
$data[] = $score;
// append data for this attempt
$table->data[] = $data;
// reset data array for next attempt, if any
$data = array();
} // end foreach $attempt
$table->data[] = 'hr';
} // end foreach $user
// remove final 'hr' from data rows
array_pop($table->data);
// add averages to foot of table
$averages = array();
if ($is_html) {
$averages[] = $blank;
}
array_push($averages, get_string('average', 'hotpot'));
$col = count($averages);
if (empty($q['grade']['count'])) {
// remove score $col from $table
$this->remove_column($table, $col);
} else {
$precision = ($hotpot->grademethod==HOTPOT_GRADEMETHOD_AVERAGE || $hotpot->grade<100) ? 1 : 0;
$averages[] = round($q['grade']['total'] / $q['grade']['count'], $precision);
$col++;
}
// skip the attempt number column
$averages[$col++] = $blank;
foreach ($questions as $id=>$question) {
if (empty($q[$id]['count'])) {
// remove this question $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q[$id]['total'] / $q[$id]['count']);
}
}
if (empty($q['penalties']['count'])) {
// remove penalties $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q['penalties']['total'] / $q['penalties']['count']);
}
if (empty($q['score']['count'])) {
// remove score $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q['score']['total'] / $q['score']['count']);
}
$table->foot = array($averages);
$tables[] = &$table;
}
} // end class
?>
<?php // $Id$
/// Overview report: displays a big table of all the attempts
class hotpot_report extends hotpot_default_report {
function display(&$hotpot, &$cm, &$course, &$users, &$attempts, &$questions, &$options) {
global $CFG;
// create the table
$tables = array();
$this->create_scores_table($hotpot, $course, $users, $attempts, $questions, $options, $tables);
$this->print_report($course, $hotpot, $tables, $options);
return true;
}
function create_scores_table(&$hotpot, &$course, &$users, &$attempts, &$questions, &$options, &$tables) {
global $CFG;
$download = ($options['reportformat']=='htm') ? false : true;
$is_html = ($options['reportformat']=='htm');
$blank = ($download ? '' : '&nbsp;');
$no_value = ($download ? '' : '-');
$allow_review = true; // ($options['reportformat']=='htm' && (isteacher($course->id) || $hotpot->review));
// start the table
unset($table);
$table->border = 1;
$table->head = array();
$table->align = array();
$table->size = array();
// picture column, if required
if ($is_html) {
$table->head[] = '&nbsp;';
$table->align[] = 'center';
$table->size[] = 10;
}
// name, grade and attempt number
array_push($table->head,
get_string("name"),
hotpot_grade_heading($hotpot, $options),
get_string("attempt", "quiz")
);
array_push($table->align, "left", "center", "center");
array_push($table->size, '', '', '');
// question headings
$this->add_question_headings($questions, $table);
// penalties and raw score
array_push($table->head,
get_string('penalties', 'hotpot'),
get_string('score', 'quiz')
);
array_push($table->align, "center", "center");
array_push($table->size, '', '');
$table->data = array();
$q = array(
'grade' => array('count'=>0, 'total'=>0),
'penalties' => array('count'=>0, 'total'=>0),
'score' => array('count'=>0, 'total'=>0),
);
foreach ($users as $user) {
// shortcut to user info held in first attempt record
$u = &$user->attempts[0];
$picture = '';
$name = fullname($u);
if ($is_html) {
$picture = print_user_picture($u->userid, $course->id, $u->picture, false, true);
$name = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$u->userid.'&course='.$course->id.'">'.$name.'</a>';
}
if (isset($user->grade)) {
$grade = $user->grade;
$q['grade']['count'] ++;
if (is_numeric($grade)) {
$q['grade']['total'] += $grade;
}
} else {
$grade = $no_value;
}
$attemptcount = count($user->attempts);
if ($attemptcount>1) {
$text = $name;
$name = NULL;
$name->text = $text;
$name->rowspan = $attemptcount;
$text = $grade;
$grade = NULL;
$grade->text = $text;
$grade->rowspan = $attemptcount;
}
$data = array();
if ($is_html) {
if ($attemptcount>1) {
$text = $picture;
$picture = NULL;
$picture->text = $text;
$picture->rowspan = $attemptcount;
}
$data[] = $picture;
}
array_push($data, $name, $grade);
foreach ($user->attempts as $attempt) {
// set flag if this is best grade
$is_best_grade = ($is_html && $attempt->score==$user->grade);
// get attempt number
$attemptnumber= $attempt->attempt;
if ($is_html && $allow_review) {
$attemptnumber = '<a href="review.php?hp='.$hotpot->id.'&attempt='.$attempt->id.'">'.$attemptnumber.'</a>';
}
if ($is_best_grade) {
$score = '<span class="highlight">'.$attemptnumber.'</span>';
}
$data[] = $attemptnumber;
// get responses to questions in this attempt by this user
foreach ($questions as $id=>$question) {
if (!isset($q[$id])) {
$q[$id] = array('count'=>0, 'total'=>0);
}
if (isset($attempt->responses[$id])) {
$score = $attempt->responses[$id]->score;
if (is_numeric($score)) {
$q[$id]['count'] ++;
$q[$id]['total'] += $score;
if ($is_best_grade) {
$score = '<span class="highlight">'.$score.'</span>';
}
} else if (empty($score)) {
$score = $no_value;
}
} else {
$score = $no_value;
}
$data[] = $score;
} // foreach $questions
if (isset($attempt->penalties)) {
$penalties = $attempt->penalties;
if (is_numeric($penalties)) {
$q['penalties']['count'] ++;
$q['penalties']['total'] += $penalties;
}
if ($is_best_grade) {
$penalties = '<span class="highlight">'.$penalties.'</span>';
}
} else {
$penalties = $no_value;
}
$data[] = $penalties;
if (isset($attempt->score)) {
$score = $attempt->score;
if (is_numeric($score)) {
$q['score']['total'] += $score;
$q['score']['count'] ++;
}
if ($is_best_grade) {
$score = '<span class="highlight">'.$score.'</span>';
}
} else {
$score = $no_value;
}
$data[] = $score;
// append data for this attempt
$table->data[] = $data;
// reset data array for next attempt, if any
$data = array();
} // end foreach $attempt
$table->data[] = 'hr';
} // end foreach $user
// remove final 'hr' from data rows
array_pop($table->data);
// add averages to foot of table
$averages = array();
if ($is_html) {
$averages[] = $blank;
}
array_push($averages, get_string('average', 'hotpot'));
$col = count($averages);
if (empty($q['grade']['count'])) {
// remove score $col from $table
$this->remove_column($table, $col);
} else {
$precision = ($hotpot->grademethod==HOTPOT_GRADEMETHOD_AVERAGE || $hotpot->grade<100) ? 1 : 0;
$averages[] = round($q['grade']['total'] / $q['grade']['count'], $precision);
$col++;
}
// skip the attempt number column
$averages[$col++] = $blank;
foreach ($questions as $id=>$question) {
if (empty($q[$id]['count'])) {
// remove this question $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q[$id]['total'] / $q[$id]['count']);
}
}
if (empty($q['penalties']['count'])) {
// remove penalties $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q['penalties']['total'] / $q['penalties']['count']);
}
if (empty($q['score']['count'])) {
// remove score $col from $table
$this->remove_column($table, $col);
} else {
$averages[$col++] = round($q['score']['total'] / $q['score']['count']);
}
$table->foot = array($averages);
$tables[] = &$table;
}
} // end class
?>

View File

@ -1,463 +1,399 @@
<?PHP //$Id$
//This php script contains all the stuff to restore hotpot mods
//-----------------------------------------------------------
// This is the "graphical" structure of the hotpot mod:
//-----------------------------------------------------------
//
// hotpot
// (CL, pk->id,
// fk->course, files)
// |
// +--------------+---------------+
// | |
// hotpot_attempts hotpot_questions
// (UL, pk->id, (UL, pk->id,
// fk->hotpot) fk->hotpot, text)
// | | |
// +-------------------+----------+ |
// | | |
// hotpot_details hotpot_responses |
// (UL, pk->id, (UL, pk->id, |
// fk->attempt) fk->attempt, question, |
// correct, wrong, ignored) |
// | |
// +-------+-------+
// |
// hotpot_strings
// (UL, pk->id)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files
//
//-----------------------------------------------------------
require_once ("$CFG->dirroot/mod/hotpot/lib.php");
//This function restores a single hotpot activity
function hotpot_restore_mods($mod, $restore) {
// this function is called by "restore_create_modules" (in "backup/restorelib.php")
// which is called by "backup/restore_execute.html" (included by "backup/restore.php")
// $mod is an object
// id : id field in 'modtype' table
// modtype : 'hotpot'
// $restore is an object
// backup_unique_code : xxxxxxxxxx
// file : '/full/path/to/backupfile.zip'
// mods : an array of $modinfo's (see below)
// restoreto : 0=existing course (replace), 1=existing course (append), 2=new course
// users : 0=all, 1=course, 2=none
// logs : 0=no, 1=yes
// user_files : 0=no, 1=yes
// course_files : 0=no, 1=yes
// course_id : id of course into which data is to be restored
// deleting : true if 'restoreto'==0, otherwise false
// original_wwwroot : 'http://your.server.com/moodle'
// $modinfo is an array
// 'modname' : array( 'restore'=> 0=no 1=yes, 'userinfo' => 0=no 1=yes)
$status = true;
// get course module data this hotpot activity
$data = backup_getid($restore->backup_unique_code, 'hotpot', $mod->id);
if ($data) {
// $data is an object
// backup_code => xxxxxxxxxx,
// table_name => 'hotpot',
// old_id => xxx,
// new_id => NULL,
// info => xml tree array of info backed up for this hotpot activity
$xml = &$data->info['MOD']['#'];
$table = 'hotpot';
$foreign_keys = array('course' => $restore->course_id);
$more_restore = '';
// print a message after each hotpot is backed up
$more_restore .= 'print "<li>".get_string("modulename", "hotpot")." &quot;".$record->name."&quot;</li>";';
$more_restore .= 'backup_flush(300);';
if ($restore->mods['hotpot']->userinfo) {
if (isset($xml["STRING_DATA"]) && isset($xml["QUESTION_DATA"])) {
// HotPot v2.1+
$more_restore .= '$status = hotpot_restore_strings($restore, $status, $xml, $record);';
$more_restore .= '$status = hotpot_restore_questions($restore, $status, $xml, $record);';
$more_restore .= '$status = hotpot_restore_attempts($restore, $status, $xml, $record);';
} else {
// HotPot v2.0.x (regenerate questions, responses and strings from attempt details)
$more_restore .= '$status = hotpot_restore_attempts($restore, $status, $xml, $record, true);';
}
}
$status = hotpot_restore_records(
$restore, $status, $xml, $table, $foreign_keys, $more_restore
);
}
return $status;
}
function hotpot_restore_strings(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_strings', array(), '', 'STRING_DATA', 'STRING', 'string'
);
}
function hotpot_restore_questions(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
$foreignkeys = array(
'hotpot'=>$record->id,
'text'=>'hotpot_strings'
);
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_questions', $foreignkeys, '', 'QUESTION_DATA', 'QUESTION'
);
}
function hotpot_restore_attempts(&$restore, $status, &$xml, &$record, $hotpot_v20=false) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
$foreignkeys = array(
'userid'=>'user',
'hotpot'=>$record->id,
);
$more_restore = '';
$more_restore .= 'hotpot_restore_details($restore, $status, $xml, $record);';
if ($hotpot_v20) {
// HotPot v2.0.x (regenerate questions and responses from details)
$more_restore .= '$record->details=stripslashes($record->details);';
$more_restore .= 'hotpot_add_attempt_details($record);'; // see "hotpot/lib.php"
} else {
// HotPot v2.1+
$more_restore .= '$status = hotpot_restore_responses($restore, $status, $xml, $record);';
// save clickreportid (to be updated it later)
$more_restore .= 'if (!empty($record->clickreportid)) {';
$more_restore .= '$GLOBALS["hotpot_backup_clickreportids"][$record->id]=$record->clickreportid;';
$more_restore .= '}';
// initialize global array to store clickreportids
$GLOBALS["hotpot_backup_clickreportids"] = array();
}
$status = hotpot_restore_records(
$restore, $status, $xml, 'hotpot_attempts', $foreignkeys, $more_restore, 'ATTEMPT_DATA', 'ATTEMPT'
);
if ($hotpot_v20) {
if ($status) {
global $CFG;
// based on code in "mod/hotpot/db/update_to_v2.php"
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=1 WHERE hotpot=$record->id AND timefinish=0 AND score IS NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=3 WHERE hotpot=$record->id AND timefinish>0 AND score IS NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=4 WHERE hotpot=$record->id AND timefinish>0 AND score IS NOT NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=id WHERE hotpot=$record->id AND clickreportid IS NULL", false);
}
} else {
$status = hotpot_restore_clickreportids($restore, $status);
unset($GLOBALS["hotpot_backup_clickreportids"]); // tidy up
}
return $status;
}
function hotpot_restore_clickreportids(&$restore, $status) {
// update clickreport ids, if any
global $CFG;
foreach ($GLOBALS["hotpot_backup_clickreportids"] as $id=>$clickreportid) {
if ($status) {
$attempt_record = backup_getid($restore->backup_unique_code, 'hotpot_attempts', $clickreportid);
if ($attempt_record) {
$new_clickreportid = $attempt_record->new_id;
$status = execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=$new_clickreportid WHERE id=$id", false);
} else {
// New clickreport id could not be found
print "<ul><li>New clickreportid could not be found: attempt id=$id, clickreportid=$clickreportid</li></ul>";
$status = false;
}
}
}
return $status;
}
function hotpot_restore_responses(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for an attempt record
// $record is the newly added attempt record
$foreignkeys = array(
'attempt'=>$record->id,
'question'=>'hotpot_questions',
'correct'=>'hotpot_strings',
'wrong'=>'hotpot_strings',
'ignored'=>'hotpot_strings'
);
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_responses', $foreignkeys, '', 'RESPONSE_DATA', 'RESPONSE'
);
}
function hotpot_restore_details(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for an attempt record
// $record is the newly added attempt record
if (empty($record->details)) {
$status = true;
} else {
unset($details);
$details->attempt = $record->id;
$details->details = $record->details;
if (insert_record('hotpot_details', $details)) {
$status = true;
} else {
print "<ul><li>Details record could not be updated: attempt=$record->attempt</li></ul>";
$status = false;
}
}
return $status;
}
function hotpot_restore_records(&$restore, $status, &$xml, $table, $foreign_keys, $more_restore='', $records_TAG='', $record_TAG='', $secondary_key='') {
// general purpose function to restore a group of records
// $restore : (see "hotpot_restore_mods" above)
// $xml : an XML tree (or sub-tree)
// $records_TAG : (optional) the name of an XML tag which starts a block of records
// If no $records_TAG is specified, $xml is assumed to be a block of records
// $record_TAG : (optional) the name of an XML tag which starts a single record
// If no $record_TAG is specified, the block of records is assumed to be a single record
// other parameters are explained in "hotpot_restore_record" below
$i = 0;
do {
unset($xml_records);
if ($records_TAG) {
if (isset($xml[$records_TAG][$i]['#'])) {
$xml_records = &$xml[$records_TAG][$i]['#'];
}
} else {
if ($i==0) {
$xml_records = &$xml;
}
}
if (empty($xml_records)) {
// do nothing
} else {
$ii = 0;
do {
unset($xml_record);
if ($record_TAG) {
if (isset($xml_records[$record_TAG][$ii]['#'])) {
$xml_record = &$xml_records[$record_TAG][$ii]['#'];
}
} else {
if ($ii==0) {
$xml_record = &$xml_records;
}
}
if (empty($xml_record)) {
// do nothing
} else {
$status = hotpot_restore_record(
$restore, $status, $xml_record, $table, $foreign_keys, $more_restore, $secondary_key
);
}
$ii++;
} while ($status && isset($xml_record));
}
$i++;
} while ($status && isset($xml_records));
return $status;
}
function hotpot_restore_record(&$restore, $status, &$xml, $table, $foreign_keys, $more_restore, $secondary_key) {
// general purpose function to restore a single record
// $restore : (see "hotpot_restore_mods" above)
// $status : current status of backup (true or false)
// $xml : XML tree of current record
// $table : name of Moodle database table to restore to
// $foreign_keys : array of foreign keys, if any, specifed as $key=>$value
// $key : the name of a field in the current $record
// $value : if $value is numeric, then $record->$key is set to $value.
// Otherwise $value is assumed to be a table name and $record->$key
// is treated as a comma separated list of ids in that table
// $more_restore : optional PHP code to be eval(uated) for each record
// $secondary_key :
// the name of the secondary key field, if any, in the current $record.
// If this field is specified, then the current record will only be added
// if the $record->$secondarykey value does not already exist in $table
unset($record);
$TAGS = array_keys($xml);
foreach ($TAGS as $TAG) {
$value = $xml[$TAG][0]['#'];
if (is_string($value)) {
$tag = strtolower($TAG);
$record->$tag = backup_todb($value);
}
}
foreach ($foreign_keys as $key=>$value) {
if (is_numeric($value)) {
$record->$key = $value;
} else {
if (empty($record->$key)) {
$record->$key = NULL;
} else {
$key_table = $value;
$new_ids = array();
$old_ids = explode(',', $record->$key);
foreach ($old_ids as $old_id) {
$key_record = backup_getid($restore->backup_unique_code, $key_table, $old_id);
if ($key_record) {
$new_ids[] = $key_record->new_id;
} else {
// foreign key could not be updated
print "<ul><li>Foreign key could not be updated: table=$table, $key=".$record->$key."</li></ul>";
$status = false;
}
}
$record->$key = implode(',', $new_ids);
}
}
}
// check everything is OK so far
if ($status && isset($record)) {
// store old record id, if necessary
if (isset($record->id)) {
$record->old_id = $record->id;
unset($record->id);
}
// if there is a secondary key field ...
if ($secondary_key) {
// check to see if a record with the same value already exists
$key_record = get_record($table, $secondary_key, $record->$secondary_key);
if ($key_record) {
// set new record id from already existing record
$record->id = $key_record->id;
}
}
if (empty($record->id)) {
// add the $record (and get new id)
$record->id = insert_record ($table, $record);
}
// check $record was added (or found)
if (is_numeric($record->id)) {
// if there was an old id, save a mapping to the new id
if (isset($record->old_id)) {
backup_putid($restore->backup_unique_code, $table, $record->old_id, $record->id);
}
} else {
// failed to add (or find) $record
print "<ul><li>Record could not be added: table=$table</li></ul>";
$status = false;
}
// restore related records, if required
if ($more_restore) {
eval($more_restore);
}
}
return $status;
}
//This function returns a log record with all the necessay transformations
//done. It's used by restore_log_module() to restore modules log.
function hotpot_restore_logs($restore, $log) {
// assume the worst
$status = false;
switch ($log->action) {
case "add":
case "update":
case "view":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code, $log->module, $log->info);
if ($mod) {
$log->url = "view.php?id=".$log->cmid;
$log->info = $mod->new_id;
$status = true;
}
}
break;
case "view all":
$log->url = "index.php?id=".$log->course;
$status = true;
break;
case "report":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code,$log->module,$log->info);
if ($mod) {
$log->url = "report.php?id=".$log->cmid;
$log->info = $mod->new_id;
$status = true;
}
}
break;
case "attempt":
case "submit":
case "review":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code,$log->module,$log->info);
if ($mod) {
//Extract the attempt id from the url field
$attemptid = substr(strrchr($log->url,"="),1);
//Get the new_id of the attempt (to recode the url field)
$attempt = backup_getid($restore->backup_unique_code,"hotpot_attempts",$attemptid);
if ($attempt) {
$log->url = "review.php?id=".$log->cmid."&attempt=".$attempt->new_id;
$log->info = $mod->new_id;
$status = true;
}
}
}
break;
default:
// Oops, unknown $log->action
print "<p>action (".$log->module."-".$log->action.") unknown. Not restored</p>";
break;
} // end switch
return $status ? $log : false;
}
?>
<?PHP //$Id$
//This php script contains all the stuff to restore hotpot mods
//-----------------------------------------------------------
// This is the "graphical" structure of the hotpot mod:
//-----------------------------------------------------------
//
// hotpot
// (CL, pk->id,
// fk->course, files)
// |
// +--------------+---------------+
// | |
// hotpot_attempts hotpot_questions
// (UL, pk->id, (UL, pk->id,
// fk->hotpot) fk->hotpot, text)
// | | |
// +-------------------+----------+ |
// | | |
// hotpot_details hotpot_responses |
// (UL, pk->id, (UL, pk->id, |
// fk->attempt) fk->attempt, question, |
// correct, wrong, ignored) |
// | |
// +-------+-------+
// |
// hotpot_strings
// (UL, pk->id)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files
//
//-----------------------------------------------------------
require_once ("$CFG->dirroot/mod/hotpot/lib.php");
//This function restores a single hotpot activity
function hotpot_restore_mods($mod, $restore) {
// this function is called by "restore_create_modules" (in "backup/restorelib.php")
// which is called by "backup/restore_execute.html" (included by "backup/restore.php")
// $mod is an object
// id : id field in 'modtype' table
// modtype : 'hotpot'
// $restore is an object
// backup_unique_code : xxxxxxxxxx
// file : '/full/path/to/backupfile.zip'
// mods : an array of $modinfo's (see below)
// restoreto : 0=existing course (replace), 1=existing course (append), 2=new course
// users : 0=all, 1=course, 2=none
// logs : 0=no, 1=yes
// user_files : 0=no, 1=yes
// course_files : 0=no, 1=yes
// course_id : id of course into which data is to be restored
// deleting : true if 'restoreto'==0, otherwise false
// original_wwwroot : 'http://your.server.com/moodle'
// $modinfo is an array
// 'modname' : array( 'restore'=> 0=no 1=yes, 'userinfo' => 0=no 1=yes)
$status = true;
// get course module data this hotpot activity
$data = backup_getid($restore->backup_unique_code, 'hotpot', $mod->id);
if ($data) {
// $data is an object
// backup_code => xxxxxxxxxx,
// table_name => 'hotpot',
// old_id => xxx,
// new_id => NULL,
// info => xml tree array of info backed up for this hotpot activity
$xml = &$data->info['MOD']['#'];
$table = 'hotpot';
$foreign_keys = array('course' => $restore->course_id);
$more_restore = '';
// print a message after each hotpot is backed up
$more_restore .= 'print "<li>".get_string("modulename", "hotpot")." &quot;".$record->name."&quot;</li>";';
$more_restore .= 'backup_flush(300);';
if ($restore->mods['hotpot']->userinfo) {
if (isset($xml["STRING_DATA"]) && isset($xml["QUESTION_DATA"])) {
// HotPot v2.1+
$more_restore .= '$status = hotpot_restore_strings($restore, $status, $xml, $record);';
$more_restore .= '$status = hotpot_restore_questions($restore, $status, $xml, $record);';
$more_restore .= '$status = hotpot_restore_attempts($restore, $status, $xml, $record);';
} else {
// HotPot v2.0.x (regenerate questions, responses and strings from attempt details)
$more_restore .= '$status = hotpot_restore_attempts($restore, $status, $xml, $record, true);';
}
}
$status = hotpot_restore_records(
$restore, $status, $xml, $table, $foreign_keys, $more_restore
);
}
return $status;
}
function hotpot_restore_strings(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_strings', array(), '', 'STRING_DATA', 'STRING', 'string'
);
}
function hotpot_restore_questions(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
$foreignkeys = array(
'hotpot'=>$record->id,
'text'=>'hotpot_strings'
);
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_questions', $foreignkeys, '', 'QUESTION_DATA', 'QUESTION'
);
}
function hotpot_restore_attempts(&$restore, $status, &$xml, &$record, $hotpot_v20=false) {
// $xml is an XML tree for a hotpot record
// $record is the newly added hotpot record
$foreignkeys = array(
'userid'=>'user',
'hotpot'=>$record->id,
);
$more_restore = '';
$more_restore .= 'hotpot_restore_details($restore, $status, $xml, $record);';
if ($hotpot_v20) {
// HotPot v2.0.x (regenerate questions and responses from details)
$more_restore .= '$record->details=stripslashes($record->details);';
$more_restore .= 'hotpot_add_attempt_details($record);'; // see "hotpot/lib.php"
} else {
// HotPot v2.1+
$more_restore .= '$status = hotpot_restore_responses($restore, $status, $xml, $record);';
// save clickreportid (to be updated it later)
$more_restore .= 'if (!empty($record->clickreportid)) {';
$more_restore .= '$GLOBALS["hotpot_backup_clickreportids"][$record->id]=$record->clickreportid;';
$more_restore .= '}';
// initialize global array to store clickreportids
$GLOBALS["hotpot_backup_clickreportids"] = array();
}
$status = hotpot_restore_records(
$restore, $status, $xml, 'hotpot_attempts', $foreignkeys, $more_restore, 'ATTEMPT_DATA', 'ATTEMPT'
);
if ($hotpot_v20) {
if ($status) {
global $CFG;
// based on code in "mod/hotpot/db/update_to_v2.php"
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=1 WHERE hotpot=$record->id AND timefinish=0 AND score IS NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=3 WHERE hotpot=$record->id AND timefinish>0 AND score IS NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=4 WHERE hotpot=$record->id AND timefinish>0 AND score IS NOT NULL", false);
execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=id WHERE hotpot=$record->id AND clickreportid IS NULL", false);
}
} else {
$status = hotpot_restore_clickreportids($restore, $status);
unset($GLOBALS["hotpot_backup_clickreportids"]); // tidy up
}
return $status;
}
function hotpot_restore_clickreportids(&$restore, $status) {
// update clickreport ids, if any
global $CFG;
foreach ($GLOBALS["hotpot_backup_clickreportids"] as $id=>$clickreportid) {
if ($status) {
$attempt_record = backup_getid($restore->backup_unique_code, 'hotpot_attempts', $clickreportid);
if ($attempt_record) {
$new_clickreportid = $attempt_record->new_id;
$status = execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=$new_clickreportid WHERE id=$id", false);
} else {
// New clickreport id could not be found
print "<ul><li>New clickreportid could not be found: attempt id=$id, clickreportid=$clickreportid</li></ul>";
$status = false;
}
}
}
return $status;
}
function hotpot_restore_responses(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for an attempt record
// $record is the newly added attempt record
$foreignkeys = array(
'attempt'=>$record->id,
'question'=>'hotpot_questions',
'correct'=>'hotpot_strings',
'wrong'=>'hotpot_strings',
'ignored'=>'hotpot_strings'
);
return hotpot_restore_records(
$restore, $status, $xml, 'hotpot_responses', $foreignkeys, '', 'RESPONSE_DATA', 'RESPONSE'
);
}
function hotpot_restore_details(&$restore, $status, &$xml, &$record) {
// $xml is an XML tree for an attempt record
// $record is the newly added attempt record
if (empty($record->details)) {
$status = true;
} else {
unset($details);
$details->attempt = $record->id;
$details->details = $record->details;
if (insert_record('hotpot_details', $details)) {
$status = true;
} else {
print "<ul><li>Details record could not be updated: attempt=$record->attempt</li></ul>";
$status = false;
}
}
return $status;
}
function hotpot_restore_records(&$restore, $status, &$xml, $table, $foreign_keys, $more_restore='', $records_TAG='', $record_TAG='', $secondary_key='') {
// general purpose function to restore a group of records
// $restore : (see "hotpot_restore_mods" above)
// $xml : an XML tree (or sub-tree)
// $records_TAG : (optional) the name of an XML tag which starts a block of records
// If no $records_TAG is specified, $xml is assumed to be a block of records
// $record_TAG : (optional) the name of an XML tag which starts a single record
// If no $record_TAG is specified, the block of records is assumed to be a single record
// other parameters are explained in "hotpot_restore_record" below
$i = 0;
do {
unset($xml_records);
if ($records_TAG) {
if (isset($xml[$records_TAG][$i]['#'])) {
$xml_records = &$xml[$records_TAG][$i]['#'];
}
} else {
if ($i==0) {
$xml_records = &$xml;
}
}
if (empty($xml_records)) {
// do nothing
} else {
$ii = 0;
do {
unset($xml_record);
if ($record_TAG) {
if (isset($xml_records[$record_TAG][$ii]['#'])) {
$xml_record = &$xml_records[$record_TAG][$ii]['#'];
}
} else {
if ($ii==0) {
$xml_record = &$xml_records;
}
}
if (empty($xml_record)) {
// do nothing
} else {
$status = hotpot_restore_record(
$restore, $status, $xml_record, $table, $foreign_keys, $more_restore, $secondary_key
);
}
$ii++;
} while ($status && isset($xml_record));
}
$i++;
} while ($status && isset($xml_records));
return $status;
}
function hotpot_restore_record(&$restore, $status, &$xml, $table, $foreign_keys, $more_restore, $secondary_key) {
// general purpose function to restore a single record
// $restore : (see "hotpot_restore_mods" above)
// $status : current status of backup (true or false)
// $xml : XML tree of current record
// $table : name of Moodle database table to restore to
// $foreign_keys : array of foreign keys, if any, specifed as $key=>$value
// $key : the name of a field in the current $record
// $value : if $value is numeric, then $record->$key is set to $value.
// Otherwise $value is assumed to be a table name and $record->$key
// is treated as a comma separated list of ids in that table
// $more_restore : optional PHP code to be eval(uated) for each record
// $secondary_key :
// the name of the secondary key field, if any, in the current $record.
// If this field is specified, then the current record will only be added
// if the $record->$secondarykey value does not already exist in $table
unset($record);
$TAGS = array_keys($xml);
foreach ($TAGS as $TAG) {
$value = $xml[$TAG][0]['#'];
if (is_string($value)) {
$tag = strtolower($TAG);
$record->$tag = backup_todb($value);
}
}
foreach ($foreign_keys as $key=>$value) {
if (is_numeric($value)) {
$record->$key = $value;
} else {
if (empty($record->$key)) {
$record->$key = NULL;
} else {
$key_table = $value;
$new_ids = array();
$old_ids = explode(',', $record->$key);
foreach ($old_ids as $old_id) {
$key_record = backup_getid($restore->backup_unique_code, $key_table, $old_id);
if ($key_record) {
$new_ids[] = $key_record->new_id;
} else {
// foreign key could not be updated
print "<ul><li>Foreign key could not be updated: table=$table, $key=".$record->$key."</li></ul>";
$status = false;
}
}
$record->$key = implode(',', $new_ids);
}
}
}
// check everything is OK so far
if ($status && isset($record)) {
// store old record id, if necessary
if (isset($record->id)) {
$record->old_id = $record->id;
unset($record->id);
}
// if there is a secondary key field ...
if ($secondary_key) {
// check to see if a record with the same value already exists
$key_record = get_record($table, $secondary_key, $record->$secondary_key);
if ($key_record) {
// set new record id from already existing record
$record->id = $key_record->id;
}
}
if (empty($record->id)) {
// add the $record (and get new id)
$record->id = insert_record ($table, $record);
}
// check $record was added (or found)
if (is_numeric($record->id)) {
// if there was an old id, save a mapping to the new id
if (isset($record->old_id)) {
backup_putid($restore->backup_unique_code, $table, $record->old_id, $record->id);
}
} else {
// failed to add (or find) $record
print "<ul><li>Record could not be added: table=$table</li></ul>";
$status = false;
}
// restore related records, if required
if ($more_restore) {
eval($more_restore);
}
}
return $status;
}
//This function returns a log record with all the necessay transformations
//done. It's used by restore_log_module() to restore modules log.
function hotpot_restore_logs($restore, $log) {
// assume the worst
$status = false;
switch ($log->action) {
case "add":
case "update":
case "view":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code, $log->module, $log->info);
if ($mod) {
$log->url = "view.php?id=".$log->cmid;
$log->info = $mod->new_id;
$status = true;
}
}
break;
case "view all":
$log->url = "index.php?id=".$log->course;
$status = true;
break;
case "report":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code,$log->module,$log->info);
if ($mod) {
$log->url = "report.php?id=".$log->cmid;
$log->info = $mod->new_id;
$status = true;
}
}
break;
case "attempt":
case "submit":
case "review":
if ($log->cmid) {
//Get the new_id of the module (to recode the info field)
$mod = backup_getid($restore->backup_unique_code,$log->module,$log->info);
if ($mod) {
//Extract the attempt id from the url field
$attemptid = substr(strrchr($log->url,"="),1);
//Get the new_id of the attempt (to recode the url field)
$attempt = backup_getid($restore->backup_unique_code,"hotpot_attempts",$attemptid);
if ($attempt) {
$log->url = "review.php?id=".$log->cmid."&attempt=".$attempt->new_id;
$log->info = $mod->new_id;
$status = true;
}
}
}
break;
default:
// Oops, unknown $log->action
print "<p>action (".$log->module."-".$log->action.") unknown. Not restored</p>";
break;
} // end switch
return $status ? $log : false;
}
?>

View File

@ -1,290 +1,240 @@
<?PHP // $Id$
// This page prints a review of a particular quiz attempt
require_once("../../config.php");
require_once("lib.php");
$id = optional_param("id"); // Course Module ID, or
$hp = optional_param("hp"); // hotpot ID
$attempt = required_param("attempt"); // A particular attempt ID for review
if ($id) {
if (! $cm = get_record("course_modules", "id", $id)) {
error("Course Module ID was incorrect");
}
if (! $course = get_record("course", "id", $cm->course)) {
error("Course is misconfigured");
}
if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
error("Course module is incorrect");
}
} else {
if (! $hotpot = get_record("hotpot", "id", $hp)) {
error("Course module is incorrect");
}
if (! $course = get_record("course", "id", $hotpot->course)) {
error("Course is misconfigured");
}
if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
error("Course Module ID was incorrect");
}
}
if (! $attempt = get_record("hotpot_attempts", "id", $attempt)) {
error("Attempt ID was incorrect");
}
require_login($course->id);
if (!isteacher($course->id)) {
if (!$hotpot->review) {
error(get_string("noreview", "quiz"));
}
//if (time() < $hotpot->timeclose) {
// error(get_string("noreviewuntil", "quiz", userdate($hotpot->timeclose)));
//}
if ($attempt->userid != $USER->id) {
error("This is not your attempt!");
}
}
add_to_log($course->id, "hotpot", "review", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
// Print the page header
$strmodulenameplural = get_string("modulenameplural", "hotpot");
$strmodulename = get_string("modulename", "hotpot");
// print header
$title = "$course->shortname: $hotpot->name";
$heading = "$course->fullname";
$navigation = "<a href=\"index.php?id=$course->id\">$strmodulenameplural</a> -> ".get_string("review", "quiz");
if ($course->category) {
$navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
}
$button = update_module_button($cm->id, $course->id, $strmodulename);
print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
print '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
print_heading($hotpot->name);
hotpot_print_attempt_summary($hotpot, $attempt);
hotpot_print_review_buttons($course, $hotpot, $attempt);
$action = isteacher($course->id) ? optional_param('action') : '';
if ($action) {
$xml = get_field('hotpot_details', 'details', 'attempt', $attempt->id);
print '<hr>';
switch ($action) {
case 'showxmltree':
print '<pre id="contents">';
$xml_tree = new hotpot_xml_tree($xml, "['hpjsresult']['#']");
print_r ($xml_tree->xml_value('fields'));
print '</pre>';
break;
case 'showxmlsource':
print htmlspecialchars($xml);
break;
default:
print "Action '$action' not recognized";
}
print '<hr>';
} else {
hotpot_print_attempt_details($hotpot, $attempt);
}
hotpot_print_review_buttons($course, $hotpot, $attempt);
print_footer($course);
///////////////////////////
// functions
///////////////////////////
function hotpot_print_attempt_summary(&$hotpot, &$attempt) {
// start table
print_simple_box_start("center", "80%", "#ffffff", 0);
print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
// add attempt properties
$fields = array('attempt', 'score', 'penalties', 'status', 'timetaken', 'timerecorded');
foreach ($fields as $field) {
switch ($field) {
case 'score':
$value = hotpot_format_score($attempt);
break;
case 'status':
$value = hotpot_format_status($attempt);
break;
case 'timerecorded':
$value = empty($attempt->timefinish) ? '-' : userdate($attempt->timefinish);
break;
case 'timetaken':
$value = empty($attempt->timefinish) ? '-' : format_time($attempt->timefinish - $attempt->timestart);
break;
default:
$value = isset($attempt->$field) ? $attempt->$field : NULL;
}
if (isset($value)) {
switch ($field) {
case 'status':
case 'timerecorded':
$name = get_string('report'.$field, 'hotpot');
break;
case 'penalties':
$name = get_string('penalties', 'hotpot');
break;
default:
$name = get_string($field, 'quiz');
}
print '<tr><th align="right" width="100" class="generaltableheader">'.$name.':</th><td class="generaltablecell">'.$value.'</td></tr>';
}
}
// finish table
print '</table>';
print_simple_box_end();
}
function hotpot_print_review_buttons(&$course, &$hotpot, &$attempt) {
print "\n".'<table border="0" align="center" cellpadding="2" cellspacing="2" class="generaltable">';
print "\n<tr>\n".'<td align="center">';
print_single_button("report.php?hp=$hotpot->id", NULL, get_string('continue'), 'post');
if (isteacher($course->id) && record_exists('hotpot_details', 'attempt', $attempt->id)) {
print "</td>\n".'<td align="center">';
print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmlsource", NULL, get_string('showxmlsource', 'hotpot'), 'post');
print "</td>\n".'<td align="center">';
print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmltree", NULL, get_string('showxmltree', 'hotpot'), 'post');
$colspan = 3;
} else {
$colspan = 1;
}
print "</td>\n</tr>\n";
print '<tr><td colspan="'.$colspan.'">';
print_spacer(4, 1, false); // height=4, width=1, no <br />
print "</td></tr>\n";
print "</table>\n";
}
function hotpot_print_attempt_details(&$hotpot, &$attempt) {
// define fields to print
$textfields = array('correct', 'ignored', 'wrong');
$numfields = array('score', 'weighting', 'hints', 'clues', 'checks');
$fields = array_merge($textfields, $numfields);
$q = array(); // questions
$f = array(); // fields
foreach ($fields as $field) {
$name = get_string($field, 'hotpot');
$f[$field] = array('count'=>0, 'name'=>$name);
}
// get questions and responses for this attempt
$questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'", 'id');
$responses = get_records_select('hotpot_responses', "attempt='$attempt->id'", 'id');
if ($questions && $responses) {
foreach ($responses as $response) {
$id = $response->question;
foreach ($fields as $field) {
if (!isset($f[$field])) {
$name = get_string($field, 'hotpot');
$f[$field] = array('count'=>0, 'name'=>$name);
}
if (isset($response->$field)) {
$f[$field]['count']++;
if (!isset($q[$id])) {
$name = hotpot_get_question_name($questions[$id]);
$q[$id] = array('name'=>$name);
}
$q[$id][$field] = $response->$field;
}
}
}
}
// count the number of columns required in the table
$colspan = 0;
foreach ($numfields as $field) {
if ($f[$field]['count']) {
$colspan += 2;
}
}
$colspan = max(2, $colspan);
// start table of questions and responses
print_simple_box_start("center", "80%", "#ffffff", 0);
print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
if (empty($q)) {
print '<tr><td align="center" class="generaltablecell"><b>'.get_string("noresponses", "hotpot")."</b></td></tr>\n";
} else {
// flag to ensure separators are only printed before the 2nd and subsequent questions
$printseparator = false;
foreach ($q as $i=>$question) {
// flag to ensure questions are only printed when there is at least one response
$printedquestion = false;
// add rows of text fields
foreach ($textfields as $field) {
if (isset($question[$field])) {
$text = hotpot_strings($question[$field]);
if (trim($text)) {
// print question if necessary
if (!$printedquestion) {
if ($printseparator) {
print '<tr><td colspan="'.$colspan.'"><div class="tabledivider"></div></td></tr>'."\n";
}
$printseparator = true;
print '<tr><td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name'].'</b></td></tr>'."\n";
$printedquestion = true;
}
// print response
print '<tr><th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td colspan="'.($colspan-1).'" class="generaltablecell">'.$text.'</td></tr>'."\n";
}
}
}
// add row of numeric fields
print '<tr>';
foreach ($numfields as $field) {
if ($f[$field]['count']) {
// print question if necessary
if (!$printedquestion) {
print '<td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name']."</b></td></tr>\n<tr>";
$printedquestion = true;
}
// print numeric response
$value = isset($question[$field]) ? $question[$field] : '-';
print '<th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td class="generaltablecell">'.$value.'</td>';
}
}
print "</tr>\n";
} // foreach $q
}
// finish table
print "</table>\n";
print_simple_box_end();
}
?>
<?PHP // $Id$
// This page prints a review of a particular quiz attempt
require_once("../../config.php");
require_once("lib.php");
$id = optional_param("id"); // Course Module ID, or
$hp = optional_param("hp"); // hotpot ID
$attempt = required_param("attempt"); // A particular attempt ID for review
if ($id) {
if (! $cm = get_record("course_modules", "id", $id)) {
error("Course Module ID was incorrect");
}
if (! $course = get_record("course", "id", $cm->course)) {
error("Course is misconfigured");
}
if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
error("Course module is incorrect");
}
} else {
if (! $hotpot = get_record("hotpot", "id", $hp)) {
error("Course module is incorrect");
}
if (! $course = get_record("course", "id", $hotpot->course)) {
error("Course is misconfigured");
}
if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
error("Course Module ID was incorrect");
}
}
if (! $attempt = get_record("hotpot_attempts", "id", $attempt)) {
error("Attempt ID was incorrect");
}
require_login($course->id);
if (!isteacher($course->id)) {
if (!$hotpot->review) {
error(get_string("noreview", "quiz"));
}
//if (time() < $hotpot->timeclose) {
// error(get_string("noreviewuntil", "quiz", userdate($hotpot->timeclose)));
//}
if ($attempt->userid != $USER->id) {
error("This is not your attempt!");
}
}
add_to_log($course->id, "hotpot", "review", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
// Print the page header
$strmodulenameplural = get_string("modulenameplural", "hotpot");
$strmodulename = get_string("modulename", "hotpot");
// print header
$title = "$course->shortname: $hotpot->name";
$heading = "$course->fullname";
$navigation = "<a href=\"index.php?id=$course->id\">$strmodulenameplural</a> -> ".get_string("review", "quiz");
if ($course->category) {
$navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
}
$button = update_module_button($cm->id, $course->id, $strmodulename);
print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
print '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
print_heading($hotpot->name);
hotpot_print_attempt_summary($hotpot, $attempt);
hotpot_print_review_buttons($course, $hotpot, $attempt);
$action = isteacher($course->id) ? optional_param('action') : '';
if ($action) {
$xml = get_field('hotpot_details', 'details', 'attempt', $attempt->id);
print '<hr>';
switch ($action) {
case 'showxmltree':
print '<pre id="contents">';
$xml_tree = new hotpot_xml_tree($xml, "['hpjsresult']['#']");
print_r ($xml_tree->xml_value('fields'));
print '</pre>';
break;
case 'showxmlsource':
print htmlspecialchars($xml);
break;
default:
print "Action '$action' not recognized";
}
print '<hr>';
} else {
hotpot_print_attempt_details($hotpot, $attempt);
}
hotpot_print_review_buttons($course, $hotpot, $attempt);
print_footer($course);
///////////////////////////
// functions
///////////////////////////
function hotpot_print_attempt_summary(&$hotpot, &$attempt) {
// start table
print_simple_box_start("center", "80%", "#ffffff", 0);
print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
// add attempt properties
$fields = array('attempt', 'score', 'penalties', 'status', 'timetaken', 'timerecorded');
foreach ($fields as $field) {
switch ($field) {
case 'score':
$value = hotpot_format_score($attempt);
break;
case 'status':
$value = hotpot_format_status($attempt);
break;
case 'timerecorded':
$value = empty($attempt->timefinish) ? '-' : userdate($attempt->timefinish);
break;
case 'timetaken':
$value = empty($attempt->timefinish) ? '-' : format_time($attempt->timefinish - $attempt->timestart);
break;
default:
$value = isset($attempt->$field) ? $attempt->$field : NULL;
}
if (isset($value)) {
switch ($field) {
case 'status':
case 'timerecorded':
$name = get_string('report'.$field, 'hotpot');
break;
case 'penalties':
$name = get_string('penalties', 'hotpot');
break;
default:
$name = get_string($field, 'quiz');
}
print '<tr><th align="right" width="100" class="generaltableheader">'.$name.':</th><td class="generaltablecell">'.$value.'</td></tr>';
}
}
// finish table
print '</table>';
print_simple_box_end();
}
function hotpot_print_review_buttons(&$course, &$hotpot, &$attempt) {
print "\n".'<table border="0" align="center" cellpadding="2" cellspacing="2" class="generaltable">';
print "\n<tr>\n".'<td align="center">';
print_single_button("report.php?hp=$hotpot->id", NULL, get_string('continue'), 'post');
if (isteacher($course->id) && record_exists('hotpot_details', 'attempt', $attempt->id)) {
print "</td>\n".'<td align="center">';
print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmlsource", NULL, get_string('showxmlsource', 'hotpot'), 'post');
print "</td>\n".'<td align="center">';
print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmltree", NULL, get_string('showxmltree', 'hotpot'), 'post');
$colspan = 3;
} else {
$colspan = 1;
}
print "</td>\n</tr>\n";
print '<tr><td colspan="'.$colspan.'">';
print_spacer(4, 1, false); // height=4, width=1, no <br />
print "</td></tr>\n";
print "</table>\n";
}
function hotpot_print_attempt_details(&$hotpot, &$attempt) {
// define fields to print
$textfields = array('correct', 'ignored', 'wrong');
$numfields = array('score', 'weighting', 'hints', 'clues', 'checks');
$fields = array_merge($textfields, $numfields);
$q = array(); // questions
$f = array(); // fields
foreach ($fields as $field) {
$name = get_string($field, 'hotpot');
$f[$field] = array('count'=>0, 'name'=>$name);
}
// get questions and responses for this attempt
$questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'", 'id');
$responses = get_records_select('hotpot_responses', "attempt='$attempt->id'", 'id');
if ($questions && $responses) {
foreach ($responses as $response) {
$id = $response->question;
foreach ($fields as $field) {
if (!isset($f[$field])) {
$name = get_string($field, 'hotpot');
$f[$field] = array('count'=>0, 'name'=>$name);
}
if (isset($response->$field)) {
$f[$field]['count']++;
if (!isset($q[$id])) {
$name = hotpot_get_question_name($questions[$id]);
$q[$id] = array('name'=>$name);
}
$q[$id][$field] = $response->$field;
}
}
}
}
// count the number of columns required in the table
$colspan = 0;
foreach ($numfields as $field) {
if ($f[$field]['count']) {
$colspan += 2;
}
}
$colspan = max(2, $colspan);
// start table of questions and responses
print_simple_box_start("center", "80%", "#ffffff", 0);
print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
if (empty($q)) {
print '<tr><td align="center" class="generaltablecell"><b>'.get_string("noresponses", "hotpot")."</b></td></tr>\n";
} else {
// flag to ensure separators are only printed before the 2nd and subsequent questions
$printseparator = false;
foreach ($q as $i=>$question) {
// flag to ensure questions are only printed when there is at least one response
$printedquestion = false;
// add rows of text fields
foreach ($textfields as $field) {
if (isset($question[$field])) {
$text = hotpot_strings($question[$field]);
if (trim($text)) {
// print question if necessary
if (!$printedquestion) {
if ($printseparator) {
print '<tr><td colspan="'.$colspan.'"><div class="tabledivider"></div></td></tr>'."\n";
}
$printseparator = true;
print '<tr><td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name'].'</b></td></tr>'."\n";
$printedquestion = true;
}
// print response
print '<tr><th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td colspan="'.($colspan-1).'" class="generaltablecell">'.$text.'</td></tr>'."\n";
}
}
}
// add row of numeric fields
print '<tr>';
foreach ($numfields as $field) {
if ($f[$field]['count']) {
// print question if necessary
if (!$printedquestion) {
print '<td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name']."</b></td></tr>\n<tr>";
$printedquestion = true;
}
// print numeric response
$value = isset($question[$field]) ? $question[$field] : '-';
print '<th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td class="generaltablecell">'.$value.'</td>';
}
}
print "</tr>\n";
} // foreach $q
}
// finish table
print "</table>\n";
print_simple_box_end();
}
?>

View File

@ -1,78 +1,68 @@
<?php // $Id$
require_once("../../config.php");
require_once("lib.php");
require_login();
// fetch and clean the required $_GET parameters
// (script stops here if any parameters are missing)
unset($params);
$params->action = required_param('action');
$params->course = required_param('course');
$params->reference = required_param('reference');
require_login($params->course);
if (!isteacher($params->course)) {
error("You are not allowed to view this page!");
}
if (isadmin()) {
$params->location = optional_param('location', HOTPOT_LOCATION_COURSEFILES);
} else {
$params->location = HOTPOT_LOCATION_COURSEFILES;
}
$title = get_string($params->action, 'hotpot').': '.$params->reference;
print_header($title, $title);
hotpot_print_show_links($params->course, $params->location, $params->reference);
?>
<script type="text/javascript" language="javascript">
<!--
// http://www.krikkit.net/howto_javascript_copy_clipboard.html
function copy_contents(id) {
if (id==null) {
id = 'contents';
}
var obj = null;
if (document.getElementById) {
obj = document.getElementById(id);
}
if (obj && window.clipboardData) {
window.clipboardData.setData("Text", obj.innerText);
alert('<? print_string('copiedtoclipboard', 'hotpot') ?>');
}
}
document.write('<span class="helplink"> &nbsp; <a href="javascript:copy_contents()"><? print_string('copytoclipboard', 'hotpot') ?></A></span>');
-->
</script>
<?php
print_simple_box_start("center", "96%");
if($hp = new hotpot_xml_quiz($params)) {
print '<pre id="contents">';
switch ($params->action) {
case 'showxmlsource':
print htmlspecialchars($hp->source);
break;
case 'showxmltree':
print_r($hp->xml);
break;
case 'showhtmlsource':
print htmlspecialchars($hp->html);
break;
case 'showhtmlquiz':
print $hp->html;
break;
}
print '</pre>';
} else {
print_simple_box("Could not open Hot Potatoes XML file", "center", "", "#FFBBBB");
}
print_simple_box_end();
print '<br />';
close_window_button();
?>
<?php // $Id$
require_once("../../config.php");
require_once("lib.php");
require_login();
// fetch and clean the required $_GET parameters
// (script stops here if any parameters are missing)
unset($params);
$params->action = required_param('action');
$params->course = required_param('course');
$params->reference = required_param('reference');
require_login($params->course);
if (!isteacher($params->course)) {
error("You are not allowed to view this page!");
}
if (isadmin()) {
$params->location = optional_param('location', HOTPOT_LOCATION_COURSEFILES);
} else {
$params->location = HOTPOT_LOCATION_COURSEFILES;
}
$title = get_string($params->action, 'hotpot').': '.$params->reference;
print_header($title, $title);
hotpot_print_show_links($params->course, $params->location, $params->reference);
?>
<script type="text/javascript" language="javascript">
<!--
// http://www.krikkit.net/howto_javascript_copy_clipboard.html
function copy_contents(id) {
if (id==null) {
id = 'contents';
}
var obj = null;
if (document.getElementById) {
obj = document.getElementById(id);
}
if (obj && window.clipboardData) {
window.clipboardData.setData("Text", obj.innerText);
alert('<? print_string('copiedtoclipboard', 'hotpot') ?>');
}
}
document.write('<span class="helplink"> &nbsp; <a href="javascript:copy_contents()"><? print_string('copytoclipboard', 'hotpot') ?></A></span>');
-->
</script>
<?php
print_simple_box_start("center", "96%");
if($hp = new hotpot_xml_quiz($params)) {
print '<pre id="contents">';
switch ($params->action) {
case 'showxmlsource':
print htmlspecialchars($hp->source);
break;
case 'showxmltree':
print_r($hp->xml);
break;
case 'showhtmlsource':
print htmlspecialchars($hp->html);
break;
case 'showhtmlquiz':
print $hp->html;
break;
}
print '</pre>';
} else {
print_simple_box("Could not open Hot Potatoes XML file", "center", "", "#FFBBBB");
}
print_simple_box_end();
print '<br />';
close_window_button();
?>

View File

@ -1,19 +1,15 @@
<?PHP // $Id$
/////////////////////////////////////////////////////////////////////////////////
/// Code fragment to define the version of hotpot
/// This fragment is called by moodle_needs_upgrading() and /admin/index.php
/////////////////////////////////////////////////////////////////////////////////
$module->version = 2005090705; // release date of this version (see note below)
$module->release = 'v2.1.5'; // human-friendly version name (used in mod/hotpot/lib.php)
$module->cron = 0; // period for cron to check this module (secs)
// interpretation of YYYYMMDDXY version numbers
// YYYY : year
// MM : month
// DD : day
// X : point release version 1,2,3 etc
// Y : increment between point releases
?>
<?PHP // $Id$
/////////////////////////////////////////////////////////////////////////////////
/// Code fragment to define the version of hotpot
/// This fragment is called by moodle_needs_upgrading() and /admin/index.php
/////////////////////////////////////////////////////////////////////////////////
$module->version = 2005090705; // release date of this version (see note below)
$module->release = 'v2.1.5'; // human-friendly version name (used in mod/hotpot/lib.php)
$module->cron = 0; // period for cron to check this module (secs)
// interpretation of YYYYMMDDXY version numbers
// YYYY : year
// MM : month
// DD : day
// X : point release version 1,2,3 etc
// Y : increment between point releases
?>

View File

@ -1,536 +1,455 @@
<?PHP // $Id$
/// This page prints a hotpot quiz
if (defined('HOTPOT_FIRST_ATTEMPT') && HOTPOT_FIRST_ATTEMPT==false) {
// this script is being included (by attempt.php)
} else {
// this script is being called directly from the browser
define('HOTPOT_FIRST_ATTEMPT', true);
require_once("../../config.php");
require_once("lib.php");
$id = optional_param("id"); // Course Module ID, or
$hp = optional_param("hp"); // hotpot ID
if ($id) {
if (! $cm = get_record("course_modules", "id", $id)) {
error("Course Module ID was incorrect");
}
if (! $course = get_record("course", "id", $cm->course)) {
error("Course is misconfigured");
}
if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
error("Course module is incorrect");
}
} else {
if (! $hotpot = get_record("hotpot", "id", $hp)) {
error("Course module is incorrect");
}
if (! $course = get_record("course", "id", $hotpot->course)) {
error("Course is misconfigured");
}
if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
error("Course Module ID was incorrect");
}
}
require_login($course->id);
}
// set nextpage (for error messages)
$nextpage = "$CFG->wwwroot/course/view.php?id=$course->id";
// header strings
$title = strip_tags($course->shortname.': '.$hotpot->name);
$heading = "$course->fullname";
$target = empty($CFG->framename) ? '' : ' target="'.$CFG->framename.'"';
$navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/mod/hotpot/index.php?id='.$course->id.'">'.get_string("modulenameplural", "hotpot")."</a> -> $hotpot->name";
if ($course->category) {
$navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$course->shortname.'</a> -> '.$navigation;
}
$button = update_module_button($cm->id, $course->id, get_string("modulename", "hotpot").'" style="font-size:0.75em;');
$loggedinas = '<span class="logininfo">'.user_login_string($course, $USER).'</span>';
$time = time();
$hppassword = optional_param('hppassword');
if (HOTPOT_FIRST_ATTEMPT && !isteacher($course->id)) {
// check this quiz is available to this student
// error message, if quiz is unavailable
$error = '';
// check quiz is visible
if (!hotpot_is_visible($cm)) {
$error = get_string("activityiscurrentlyhidden");
// check network address
} else if ($hotpot->subnet && !address_in_subnet($_SERVER['REMOTE_ADDR'], $hotpot->subnet)) {
$error = get_string("subneterror", "quiz");
// check number of attempts
} else if ($hotpot->attempts && $hotpot->attempts <= count_records('hotpot_attempts', 'hotpot', $hotpot->id, 'userid', $USER->id)) {
$error = get_string("nomoreattempts", "quiz");
// get password
} else if ($hotpot->password && empty($hppassword)) {
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
print_heading($hotpot->name);
$boxalign = 'center';
$boxwidth = 500;
if (trim(strip_tags($hotpot->summary))) {
print_simple_box_start($boxalign, $boxwidth);
print '<div align="center">'.format_text($hotpot->summary)."</div>\n";
print_simple_box_end();
print "<br />\n";
}
print '<form name="passwordform" method="post" action="view.php?id='.$cm->id.'">'."\n";
print_simple_box_start($boxalign, $boxwidth);
print '<div align="center">';
print get_string('requirepasswordmessage', 'quiz').'<br /><br />';
print '<b>'.get_string('password').':</b> ';
print '<input name="hppassword" type="password" value=""> ';
print '<input type="submit" value="'.get_string("ok").'"> ';
print "</div>\n";
print_simple_box_end();
print "</form>\n";
print_footer();
exit;
// check password
} else if ($hotpot->password && strcmp($hotpot->password, $hppassword)) {
$error = get_string("passworderror", "quiz");
$nextpage = "view.php?id=$cm->id";
// check quiz is open
} else if ($hotpot->timeopen && $hotpot->timeopen > $time) {
$error = get_string("quiznotavailable", "quiz", userdate($hotpot->timeopen))."<br />\n";
// check quiz is not closed
} else if ($hotpot->timeclose && $hotpot->timeclose < $time) {
$error = get_string("quizclosed", "quiz", userdate($hotpot->timeclose))."<br />\n";
}
if ($error) {
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
notice($error, $nextpage);
//
// script stops here, if quiz is unavailable to student
//
}
}
$available_msg = '';
if (!empty($hotpot->timeclose) && $hotpot->timeclose > $time) {
// quiz is available until 'timeclose'
$available_msg = get_string("quizavailable", "quiz", userdate($hotpot->timeclose))."<br />\n";
}
// open and parse the source file
if(!$hp = new hotpot_xml_quiz($hotpot)) {
error("Quiz is unavailable at the moment");
}
$get_js = optional_param('js');
$get_css = optional_param('css');
$framename = optional_param('framename');
// look for <frameset> (HP5 v5)
$frameset = '';
$frameset_tags = '';
if (preg_match_all('|<frameset([^>]*)>(.*?)</frameset>|is', $hp->html, $matches)) {
$last = count($matches[0])-1;
$frameset = $matches[2][$last];
$frameset_tags = $matches[1][$last];
}
// if HTML is being requested ...
if (empty($get_js) && empty($get_css)) {
if (empty($frameset)) {
// HP v6
if ($hotpot->navigation==HOTPOT_NAVIGATION_FRAME || $hotpot->navigation==HOTPOT_NAVIGATION_IFRAME) {
$get_html = ($framename=='main') ? true : false;
} else {
$get_html = true;
}
} else {
// HP5 v5
$get_html = empty($framename) ? true : false;
}
if ($get_html) {
if (HOTPOT_FIRST_ATTEMPT) {
add_to_log($course->id, "hotpot", "view", "view.php?id=$cm->id", "$hotpot->id", "$cm->id");
$attemptid = hotpot_add_attempt($hotpot->id);
if (! is_numeric($attemptid)) {
error('Could not insert attempt record: '.$db->ErrorMsg);
}
}
$hp->adjust_media_urls();
if (empty($frameset)) {
// HP6 v6
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BUTTONS:
// do nothing (i.e. leave buttons as they are)
break;
case HOTPOT_NAVIGATION_GIVEUP:
$hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
break;
default:
$hp->remove_nav_buttons();
}
if (isset($hp->real_outputformat) && $hp->real_outputformat==HOTPOT_OUTPUTFORMAT_MOBILE) {
$hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->', true);
} else {
$hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->');
}
} else {
// HP5 v5
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BUTTONS:
// convert URLs in nav buttons
break;
case HOTPOT_NAVIGATION_GIVEUP:
// $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
break;
default:
// remove navigation buttons
$hp->html = preg_replace('#NavBar\+=(.*);#', '', $hp->html);
}
$hp->insert_submission_form($attemptid, "var NavBar='", "';");
}
}
}
//FEEDBACK = new Array();
//FEEDBACK[0] = ''; // url of feedback page/script
//FEEDBACK[1] = ''; // array of array('teachername', 'value');
//FEEDBACK[2] = ''; // 'student name' [formmail only]
//FEEDBACK[3] = ''; // 'student email' [formmail only]
//FEEDBACK[4] = ''; // window width
//FEEDBACK[5] = ''; // window height
//FEEDBACK[6] = ''; // 'Send a message to teacher' [prompt/button text]
//FEEDBACK[7] = ''; // 'Title'
//FEEDBACK[8] = ''; // 'Teacher'
//FEEDBACK[9] = ''; // 'Message'
//FEEDBACK[10] = ''; // 'Close this window'
$feedback = array();
switch ($hotpot->studentfeedback) {
case HOTPOT_FEEDBACK_NONE:
// do nothing
break;
case HOTPOT_FEEDBACK_WEBPAGE:
if (empty($hotpot->studentfeedbackurl)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$hotpot->studentfeedbackurl'";
}
break;
case HOTPOT_FEEDBACK_FORMMAIL:
$teachers = hotpot_feedback_teachers($course, $hotpot);
if (empty($teachers) || empty($hotpot->studentfeedbackurl)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$hotpot->studentfeedbackurl'";
$feedback[1] = $teachers;
$feedback[2] = "'".fullname($USER)."'";
$feedback[3] = "'".$USER->email."'";
$feedback[4] = 500; // width
$feedback[5] = 300; // height
}
break;
case HOTPOT_FEEDBACK_MOODLEFORUM:
$module = get_record('modules', 'name', 'forum');
$forums = get_records('forum', 'course', "$course->id");
if (empty($module) || empty($module->visible) || empty($forums)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$CFG->wwwroot/mod/forum/index.php?id=$course->id'";
}
break;
case HOTPOT_FEEDBACK_MOODLEMESSAGING:
$teachers = hotpot_feedback_teachers($course, $hotpot);
if (empty($CFG->messaging) || empty($teachers)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$CFG->wwwroot/message/discussion.php?id='";
$feedback[1] = $teachers;
$feedback[4] = 400; // width
$feedback[5] = 500; // height
}
break;
default:
// do nothing
}
if ($hotpot->studentfeedback != HOTPOT_FEEDBACK_NONE) {
$feedback[6] = "'Send a message to teacher'";
$feedback[7] = "'Title'";
$feedback[8] = "'Teacher'";
$feedback[9] = "'Message'";
$feedback[10] = "'Close this window'";
$js = '';
foreach ($feedback as $i=>$str) {
$js .= 'FEEDBACK['.$i."] = $str;\n";
}
$js = '<script type="text/javascript" language="javascript">'."<!--\n"."FEEDBACK = new Array();\n".$js."//--></script>\n";
$hp->html = preg_replace('|</head>|i', "$js</head>", $hp->html, 1);
}
// insert hot-potatoes.js
$hp->insert_script(HOTPOT_JS);
// extract first <head> tag
$head = '';
$pattern = '|<head([^>]*)>(.*?)</head>|is';
if (preg_match($pattern, $hp->html, $matches)) {
$head = $matches[2];
// remove <title>
$head = preg_replace('|<title[^>]*>(.*?)</title>|is', '', $head);
}
// extract <style> tags (and remove from $head)
$styles = '';
$pattern = '|<style([^>]*)>(.*?)</style>|is';
if (preg_match_all($pattern, $head, $matches)) {
$count = count($matches[0]);
for ($i=0; $i<$count; $i++) {
$styles .= $matches[0][$i]."\n";
$head = str_replace($matches[0][$i], '', $head);
}
}
// extract <script> tags (and remove from $head)
$scripts = '';
$pattern = '|<script([^>]*)>(.*?)</script>|is';
if (preg_match_all($pattern, $head, $matches)) {
$count = count($matches[0]);
for ($i=0; $i<$count; $i++) {
$scripts .= $matches[0][$i]."\n";
$head = str_replace($matches[0][$i], '', $head);
}
}
// extract <body> tags
$body = '';
$body_tags = '';
$footer = '</html>';
// HP6 and some HP5 (v6 and v4)
if (preg_match('|<body'.'([^>]*'.'onLoad=(["\'])(.*?)(\\2)'.'[^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
$body = $matches[5]; // contents of first <body onload="StartUp()">...</body> block
$body_tags = $matches[1];
// workaround to ensure javascript onload routine for quiz is always executed
// $body_tags will only be inserted into the <body ...> tag
// if it is included in the theme/$CFG->theme/header.html,
// so some old or modified themes may not insert $body_tags
$body .= ""
. '<script type="text/javascript">'."\n"
. "<!--\n"
. " var s = (typeof(window.onload)=='function') ? onload.toString() : '';\n"
. " if (s.indexOf('".$matches[3]."')<0) {\n"
. " if (s=='') {\n" // no previous onload
. " window.onload = new Function('".$matches[3]."');\n"
. " } else {\n"
. " window.onload_hotpot = onload;\n"
. " window.onload = new Function('window.onload_hotpot();'+'".$matches[3]."');\n"
. " }\n"
. " }\n"
. "//-->\n"
. "</script>\n"
;
$footer = '</body>'.$footer;
} else if ($frameset) { // HP5 v5
switch ($framename) {
case 'top':
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
print $footer;
break;
default:
// add a HotPot navigation frame at the top of the page
//$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
//$frameset = "\n\t".'<frame src="view.php?id='.$cm->id.'&framename=top" frameborder="0" name="top"></frame>'.$frameset;
//$frameset_tags = preg_replace('|rows="(.*?)"|', 'rows="'.$rows.',\\1"', $frameset_tags);
// put navigation into var NavBar='';
// add form to TopFrame in "WriteFeedback" function
// OR add form to BottomFrame in "DisplayExercise" function
// submission form: '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->'
// give up form: '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->'
print "<html>\n";
print "<head>\n<title>$title</title>\n$styles\n$scripts</head>\n";
print "<frameset$frameset_tags>$frameset</frameset>\n";
print "</html>\n";
break;
} // end switch $framename
exit;
// other files (maybe not even a HotPots)
} else if (preg_match('|<body'.'([^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
$body = $matches[2];
$body_tags = $matches[1];
}
// print the quiz to the browser
if ($get_js) {
print($scripts);
exit;
}
if ($get_css) {
print($styles);
exit;
}
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BAR:
//update_module_button($cm->id, $course->id, $strmodulename.'" style="font-size:0.8em')
print_header(
$title, $heading, $navigation,
"", $head.$styles.$scripts, true, $button,
$loggedinas, false, $body_tags
);
if (!empty($available_msg)) {
notify($available_msg);
}
print $body.$footer;
break;
case HOTPOT_NAVIGATION_FRAME:
switch ($framename) {
case 'top':
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
print $footer;
break;
case 'main':
if (!empty($available_msg)) {
$hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
}
print $hp->html;
break;
default:
$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
print "<html>\n";
print "<head><title>$title</title></head>\n";
print "<frameset rows=$rows,*>\n";
print "<frame src=\"view.php?id=$cm->id&framename=top\">\n";
print "<frame src=\"view.php?id=$cm->id&framename=main\">\n";
print "</frameset>\n";
print "</html>\n";
break;
} // end switch $framename
break;
case HOTPOT_NAVIGATION_IFRAME:
switch ($framename) {
case 'main';
print $hp->html;
break;
default:
$iframe_id = 'hotpot_iframe';
$body_tags = " onload=\"set_iframe_height('$iframe_id')\"";
$iframe_js = '<script src="iframe.js" type="text/javascript" language="javascript"></script>'."\n";
print_header(
$title, $heading, $navigation,
"", $head.$styles.$scripts.$iframe_js, true, $button,
$loggedinas, false, $body_tags
);
if (!empty($available_msg)) {
notify($available_msg);
}
print "<iframe id=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
print "<ilayer name=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
print "</ilayer>\n";
print "</iframe>\n";
print $footer;
break;
} // end switch $framename
break;
default:
// HOTPOT_NAVIGATION_BUTTONS
// HOTPOT_NAVIGATION_GIVEUP
// HOTPOT_NAVIGATION_NONE
if (!empty($available_msg)) {
$hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
}
print($hp->html);
}
///////////////////////////////////
/// functions
///////////////////////////////////
function hotpot_feedback_teachers(&$course, &$hotpot) {
global $CFG;
$teachers = get_records_sql("
SELECT
u.*
FROM
{$CFG->prefix}user AS u,
{$CFG->prefix}user_teachers AS t
WHERE
t.userid = u.id
AND t.course = $course->id
");
$teacherdetails = '';
if (!empty($teachers)) {
$details = array();
foreach ($teachers as $teacher) {
if ($hotpot->studentfeedback==HOTPOT_FEEDBACK_MOODLEMESSAGING) {
$detail = $teacher->id;
} else {
$detail =$teacher->email;
}
$details[] = "new Array('".fullname($teacher)."', '$detail')";
}
$teacherdetails = 'new Array('.implode(',', $details).");\n";
}
return $teacherdetails;
}
?>
<?PHP // $Id$
/// This page prints a hotpot quiz
if (defined('HOTPOT_FIRST_ATTEMPT') && HOTPOT_FIRST_ATTEMPT==false) {
// this script is being included (by attempt.php)
} else {
// this script is being called directly from the browser
define('HOTPOT_FIRST_ATTEMPT', true);
require_once("../../config.php");
require_once("lib.php");
$id = optional_param("id"); // Course Module ID, or
$hp = optional_param("hp"); // hotpot ID
if ($id) {
if (! $cm = get_record("course_modules", "id", $id)) {
error("Course Module ID was incorrect");
}
if (! $course = get_record("course", "id", $cm->course)) {
error("Course is misconfigured");
}
if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
error("Course module is incorrect");
}
} else {
if (! $hotpot = get_record("hotpot", "id", $hp)) {
error("Course module is incorrect");
}
if (! $course = get_record("course", "id", $hotpot->course)) {
error("Course is misconfigured");
}
if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
error("Course Module ID was incorrect");
}
}
require_login($course->id);
}
// set nextpage (for error messages)
$nextpage = "$CFG->wwwroot/course/view.php?id=$course->id";
// header strings
$title = strip_tags($course->shortname.': '.$hotpot->name);
$heading = "$course->fullname";
$target = empty($CFG->framename) ? '' : ' target="'.$CFG->framename.'"';
$navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/mod/hotpot/index.php?id='.$course->id.'">'.get_string("modulenameplural", "hotpot")."</a> -> $hotpot->name";
if ($course->category) {
$navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$course->shortname.'</a> -> '.$navigation;
}
$button = update_module_button($cm->id, $course->id, get_string("modulename", "hotpot").'" style="font-size:0.75em;');
$loggedinas = '<span class="logininfo">'.user_login_string($course, $USER).'</span>';
$time = time();
$hppassword = optional_param('hppassword');
if (HOTPOT_FIRST_ATTEMPT && !isteacher($course->id)) {
// check this quiz is available to this student
// error message, if quiz is unavailable
$error = '';
// check quiz is visible
if (!hotpot_is_visible($cm)) {
$error = get_string("activityiscurrentlyhidden");
// check network address
} else if ($hotpot->subnet && !address_in_subnet($_SERVER['REMOTE_ADDR'], $hotpot->subnet)) {
$error = get_string("subneterror", "quiz");
// check number of attempts
} else if ($hotpot->attempts && $hotpot->attempts <= count_records('hotpot_attempts', 'hotpot', $hotpot->id, 'userid', $USER->id)) {
$error = get_string("nomoreattempts", "quiz");
// get password
} else if ($hotpot->password && empty($hppassword)) {
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
print_heading($hotpot->name);
$boxalign = 'center';
$boxwidth = 500;
if (trim(strip_tags($hotpot->summary))) {
print_simple_box_start($boxalign, $boxwidth);
print '<div align="center">'.format_text($hotpot->summary)."</div>\n";
print_simple_box_end();
print "<br />\n";
}
print '<form name="passwordform" method="post" action="view.php?id='.$cm->id.'">'."\n";
print_simple_box_start($boxalign, $boxwidth);
print '<div align="center">';
print get_string('requirepasswordmessage', 'quiz').'<br /><br />';
print '<b>'.get_string('password').':</b> ';
print '<input name="hppassword" type="password" value=""> ';
print '<input type="submit" value="'.get_string("ok").'"> ';
print "</div>\n";
print_simple_box_end();
print "</form>\n";
print_footer();
exit;
// check password
} else if ($hotpot->password && strcmp($hotpot->password, $hppassword)) {
$error = get_string("passworderror", "quiz");
$nextpage = "view.php?id=$cm->id";
// check quiz is open
} else if ($hotpot->timeopen && $hotpot->timeopen > $time) {
$error = get_string("quiznotavailable", "quiz", userdate($hotpot->timeopen))."<br />\n";
// check quiz is not closed
} else if ($hotpot->timeclose && $hotpot->timeclose < $time) {
$error = get_string("quizclosed", "quiz", userdate($hotpot->timeclose))."<br />\n";
}
if ($error) {
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
notice($error, $nextpage);
//
// script stops here, if quiz is unavailable to student
//
}
}
$available_msg = '';
if (!empty($hotpot->timeclose) && $hotpot->timeclose > $time) {
// quiz is available until 'timeclose'
$available_msg = get_string("quizavailable", "quiz", userdate($hotpot->timeclose))."<br />\n";
}
// open and parse the source file
if(!$hp = new hotpot_xml_quiz($hotpot)) {
error("Quiz is unavailable at the moment");
}
$get_js = optional_param('js');
$get_css = optional_param('css');
$framename = optional_param('framename');
// look for <frameset> (HP5 v5)
$frameset = '';
$frameset_tags = '';
if (preg_match_all('|<frameset([^>]*)>(.*?)</frameset>|is', $hp->html, $matches)) {
$last = count($matches[0])-1;
$frameset = $matches[2][$last];
$frameset_tags = $matches[1][$last];
}
// if HTML is being requested ...
if (empty($get_js) && empty($get_css)) {
if (empty($frameset)) {
// HP v6
if ($hotpot->navigation==HOTPOT_NAVIGATION_FRAME || $hotpot->navigation==HOTPOT_NAVIGATION_IFRAME) {
$get_html = ($framename=='main') ? true : false;
} else {
$get_html = true;
}
} else {
// HP5 v5
$get_html = empty($framename) ? true : false;
}
if ($get_html) {
if (HOTPOT_FIRST_ATTEMPT) {
add_to_log($course->id, "hotpot", "view", "view.php?id=$cm->id", "$hotpot->id", "$cm->id");
$attemptid = hotpot_add_attempt($hotpot->id);
if (! is_numeric($attemptid)) {
error('Could not insert attempt record: '.$db->ErrorMsg);
}
}
$hp->adjust_media_urls();
if (empty($frameset)) {
// HP6 v6
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BUTTONS:
// do nothing (i.e. leave buttons as they are)
break;
case HOTPOT_NAVIGATION_GIVEUP:
$hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
break;
default:
$hp->remove_nav_buttons();
}
if (isset($hp->real_outputformat) && $hp->real_outputformat==HOTPOT_OUTPUTFORMAT_MOBILE) {
$hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->', true);
} else {
$hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->');
}
} else {
// HP5 v5
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BUTTONS:
// convert URLs in nav buttons
break;
case HOTPOT_NAVIGATION_GIVEUP:
// $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
break;
default:
// remove navigation buttons
$hp->html = preg_replace('#NavBar\+=(.*);#', '', $hp->html);
}
$hp->insert_submission_form($attemptid, "var NavBar='", "';");
}
}
}
//FEEDBACK = new Array();
//FEEDBACK[0] = ''; // url of feedback page/script
//FEEDBACK[1] = ''; // array of array('teachername', 'value');
//FEEDBACK[2] = ''; // 'student name' [formmail only]
//FEEDBACK[3] = ''; // 'student email' [formmail only]
//FEEDBACK[4] = ''; // window width
//FEEDBACK[5] = ''; // window height
//FEEDBACK[6] = ''; // 'Send a message to teacher' [prompt/button text]
//FEEDBACK[7] = ''; // 'Title'
//FEEDBACK[8] = ''; // 'Teacher'
//FEEDBACK[9] = ''; // 'Message'
//FEEDBACK[10] = ''; // 'Close this window'
$feedback = array();
switch ($hotpot->studentfeedback) {
case HOTPOT_FEEDBACK_NONE:
// do nothing
break;
case HOTPOT_FEEDBACK_WEBPAGE:
if (empty($hotpot->studentfeedbackurl)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$hotpot->studentfeedbackurl'";
}
break;
case HOTPOT_FEEDBACK_FORMMAIL:
$teachers = hotpot_feedback_teachers($course, $hotpot);
if (empty($teachers) || empty($hotpot->studentfeedbackurl)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$hotpot->studentfeedbackurl'";
$feedback[1] = $teachers;
$feedback[2] = "'".fullname($USER)."'";
$feedback[3] = "'".$USER->email."'";
$feedback[4] = 500; // width
$feedback[5] = 300; // height
}
break;
case HOTPOT_FEEDBACK_MOODLEFORUM:
$module = get_record('modules', 'name', 'forum');
$forums = get_records('forum', 'course', "$course->id");
if (empty($module) || empty($module->visible) || empty($forums)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$CFG->wwwroot/mod/forum/index.php?id=$course->id'";
}
break;
case HOTPOT_FEEDBACK_MOODLEMESSAGING:
$teachers = hotpot_feedback_teachers($course, $hotpot);
if (empty($CFG->messaging) || empty($teachers)) {
$hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
} else {
$feedback[0] = "'$CFG->wwwroot/message/discussion.php?id='";
$feedback[1] = $teachers;
$feedback[4] = 400; // width
$feedback[5] = 500; // height
}
break;
default:
// do nothing
}
if ($hotpot->studentfeedback != HOTPOT_FEEDBACK_NONE) {
$feedback[6] = "'Send a message to teacher'";
$feedback[7] = "'Title'";
$feedback[8] = "'Teacher'";
$feedback[9] = "'Message'";
$feedback[10] = "'Close this window'";
$js = '';
foreach ($feedback as $i=>$str) {
$js .= 'FEEDBACK['.$i."] = $str;\n";
}
$js = '<script type="text/javascript" language="javascript">'."<!--\n"."FEEDBACK = new Array();\n".$js."//--></script>\n";
$hp->html = preg_replace('|</head>|i', "$js</head>", $hp->html, 1);
}
// insert hot-potatoes.js
$hp->insert_script(HOTPOT_JS);
// extract first <head> tag
$head = '';
$pattern = '|<head([^>]*)>(.*?)</head>|is';
if (preg_match($pattern, $hp->html, $matches)) {
$head = $matches[2];
// remove <title>
$head = preg_replace('|<title[^>]*>(.*?)</title>|is', '', $head);
}
// extract <style> tags (and remove from $head)
$styles = '';
$pattern = '|<style([^>]*)>(.*?)</style>|is';
if (preg_match_all($pattern, $head, $matches)) {
$count = count($matches[0]);
for ($i=0; $i<$count; $i++) {
$styles .= $matches[0][$i]."\n";
$head = str_replace($matches[0][$i], '', $head);
}
}
// extract <script> tags (and remove from $head)
$scripts = '';
$pattern = '|<script([^>]*)>(.*?)</script>|is';
if (preg_match_all($pattern, $head, $matches)) {
$count = count($matches[0]);
for ($i=0; $i<$count; $i++) {
$scripts .= $matches[0][$i]."\n";
$head = str_replace($matches[0][$i], '', $head);
}
}
// extract <body> tags
$body = '';
$body_tags = '';
$footer = '</html>';
// HP6 and some HP5 (v6 and v4)
if (preg_match('|<body'.'([^>]*'.'onLoad=(["\'])(.*?)(\\2)'.'[^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
$body = $matches[5]; // contents of first <body onload="StartUp()">...</body> block
$body_tags = $matches[1];
// workaround to ensure javascript onload routine for quiz is always executed
// $body_tags will only be inserted into the <body ...> tag
// if it is included in the theme/$CFG->theme/header.html,
// so some old or modified themes may not insert $body_tags
$body .= ""
. '<script type="text/javascript">'."\n"
. "<!--\n"
. " var s = (typeof(window.onload)=='function') ? onload.toString() : '';\n"
. " if (s.indexOf('".$matches[3]."')<0) {\n"
. " if (s=='') {\n" // no previous onload
. " window.onload = new Function('".$matches[3]."');\n"
. " } else {\n"
. " window.onload_hotpot = onload;\n"
. " window.onload = new Function('window.onload_hotpot();'+'".$matches[3]."');\n"
. " }\n"
. " }\n"
. "//-->\n"
. "</script>\n"
;
$footer = '</body>'.$footer;
} else if ($frameset) { // HP5 v5
switch ($framename) {
case 'top':
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
print $footer;
break;
default:
// add a HotPot navigation frame at the top of the page
//$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
//$frameset = "\n\t".'<frame src="view.php?id='.$cm->id.'&framename=top" frameborder="0" name="top"></frame>'.$frameset;
//$frameset_tags = preg_replace('|rows="(.*?)"|', 'rows="'.$rows.',\\1"', $frameset_tags);
// put navigation into var NavBar='';
// add form to TopFrame in "WriteFeedback" function
// OR add form to BottomFrame in "DisplayExercise" function
// submission form: '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->'
// give up form: '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->'
print "<html>\n";
print "<head>\n<title>$title</title>\n$styles\n$scripts</head>\n";
print "<frameset$frameset_tags>$frameset</frameset>\n";
print "</html>\n";
break;
} // end switch $framename
exit;
// other files (maybe not even a HotPots)
} else if (preg_match('|<body'.'([^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
$body = $matches[2];
$body_tags = $matches[1];
}
// print the quiz to the browser
if ($get_js) {
print($scripts);
exit;
}
if ($get_css) {
print($styles);
exit;
}
switch ($hotpot->navigation) {
case HOTPOT_NAVIGATION_BAR:
//update_module_button($cm->id, $course->id, $strmodulename.'" style="font-size:0.8em')
print_header(
$title, $heading, $navigation,
"", $head.$styles.$scripts, true, $button,
$loggedinas, false, $body_tags
);
if (!empty($available_msg)) {
notify($available_msg);
}
print $body.$footer;
break;
case HOTPOT_NAVIGATION_FRAME:
switch ($framename) {
case 'top':
print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
print $footer;
break;
case 'main':
if (!empty($available_msg)) {
$hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
}
print $hp->html;
break;
default:
$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
print "<html>\n";
print "<head><title>$title</title></head>\n";
print "<frameset rows=$rows,*>\n";
print "<frame src=\"view.php?id=$cm->id&framename=top\">\n";
print "<frame src=\"view.php?id=$cm->id&framename=main\">\n";
print "</frameset>\n";
print "</html>\n";
break;
} // end switch $framename
break;
case HOTPOT_NAVIGATION_IFRAME:
switch ($framename) {
case 'main';
print $hp->html;
break;
default:
$iframe_id = 'hotpot_iframe';
$body_tags = " onload=\"set_iframe_height('$iframe_id')\"";
$iframe_js = '<script src="iframe.js" type="text/javascript" language="javascript"></script>'."\n";
print_header(
$title, $heading, $navigation,
"", $head.$styles.$scripts.$iframe_js, true, $button,
$loggedinas, false, $body_tags
);
if (!empty($available_msg)) {
notify($available_msg);
}
print "<iframe id=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
print "<ilayer name=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
print "</ilayer>\n";
print "</iframe>\n";
print $footer;
break;
} // end switch $framename
break;
default:
// HOTPOT_NAVIGATION_BUTTONS
// HOTPOT_NAVIGATION_GIVEUP
// HOTPOT_NAVIGATION_NONE
if (!empty($available_msg)) {
$hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
}
print($hp->html);
}
///////////////////////////////////
/// functions
///////////////////////////////////
function hotpot_feedback_teachers(&$course, &$hotpot) {
global $CFG;
$teachers = get_records_sql("
SELECT
u.*
FROM
{$CFG->prefix}user AS u,
{$CFG->prefix}user_teachers AS t
WHERE
t.userid = u.id
AND t.course = $course->id
");
$teacherdetails = '';
if (!empty($teachers)) {
$details = array();
foreach ($teachers as $teacher) {
if ($hotpot->studentfeedback==HOTPOT_FEEDBACK_MOODLEMESSAGING) {
$detail = $teacher->id;
} else {
$detail =$teacher->email;
}
$details[] = "new Array('".fullname($teacher)."', '$detail')";
}
$teacherdetails = 'new Array('.implode(',', $details).");\n";
}
return $teacherdetails;
}
?>