mirror of
https://github.com/moodle/moodle.git
synced 2025-02-15 13:24:56 +01:00
657 lines
23 KiB
PHP
657 lines
23 KiB
PHP
<?php // $Id$
|
|
/**
|
|
* Library of functions used by the quiz module.
|
|
*
|
|
* This contains functions that are called from within the quiz module only
|
|
* Functions that are also called by core Moodle are in {@link lib.php}
|
|
* This script also includes the code in {@link questionlib.php} which holds
|
|
* the module-indpendent code for handling questions and which in turn
|
|
* initialises all the questiontype classes.
|
|
* @version $Id$
|
|
* @author Martin Dougiamas and many others. This has recently been completely
|
|
* rewritten by Alex Smith, Julian Sedding and Gustav Delius as part of
|
|
* the Serving Mathematics project
|
|
* {@link http://maths.york.ac.uk/serving_maths}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
|
* @package quiz
|
|
*/
|
|
|
|
/**
|
|
* Include those library functions that are also used by core Moodle or other modules
|
|
*/
|
|
require_once("$CFG->dirroot/mod/quiz/lib.php");
|
|
require_once("$CFG->dirroot/mod/quiz/questionlib.php");
|
|
|
|
/// CONSTANTS ///////////////////////////////////////////////////////////////////
|
|
|
|
/**#@+
|
|
* Options determining how the grades from individual attempts are combined to give
|
|
* the overall grade for a user
|
|
*/
|
|
define("QUIZ_GRADEHIGHEST", "1");
|
|
define("QUIZ_GRADEAVERAGE", "2");
|
|
define("QUIZ_ATTEMPTFIRST", "3");
|
|
define("QUIZ_ATTEMPTLAST", "4");
|
|
$QUIZ_GRADE_METHOD = array ( QUIZ_GRADEHIGHEST => get_string("gradehighest", "quiz"),
|
|
QUIZ_GRADEAVERAGE => get_string("gradeaverage", "quiz"),
|
|
QUIZ_ATTEMPTFIRST => get_string("attemptfirst", "quiz"),
|
|
QUIZ_ATTEMPTLAST => get_string("attemptlast", "quiz"));
|
|
/**#@-*/
|
|
|
|
|
|
/// FUNCTIONS RELATED TO ATTEMPTS /////////////////////////////////////////
|
|
|
|
/**
|
|
* Creates an object to represent a new attempt at a quiz
|
|
*
|
|
* Creates an attempt object to represent an attempt at the quiz by the current
|
|
* user starting at the current time. The ->id field is not set. The object is
|
|
* NOT written to the database.
|
|
* @return object The newly created attempt object.
|
|
* @param object $quiz The quiz to create an attempt for.
|
|
* @param integer $attemptnumber The sequence number for the attempt.
|
|
*/
|
|
function quiz_create_attempt($quiz, $attemptnumber) {
|
|
global $USER, $CFG;
|
|
|
|
if (!$attemptnumber > 1 or !$quiz->attemptonlast or !$attempt = get_record('quiz_attempts', 'quiz', $quiz->id, 'userid', $USER->id, 'attempt', $attemptnumber-1)) {
|
|
// we are not building on last attempt so create a new attempt
|
|
$attempt->quiz = $quiz->id;
|
|
$attempt->userid = $USER->id;
|
|
$attempt->preview = 0;
|
|
if ($quiz->shufflequestions) {
|
|
$attempt->layout = quiz_repaginate($quiz->questions, $quiz->questionsperpage, true);
|
|
} else {
|
|
$attempt->layout = $quiz->questions;
|
|
}
|
|
}
|
|
|
|
$timenow = time();
|
|
$attempt->attempt = $attemptnumber;
|
|
$attempt->sumgrades = 0.0;
|
|
$attempt->timestart = $timenow;
|
|
$attempt->timefinish = 0;
|
|
$attempt->timemodified = $timenow;
|
|
$attempt->uniqueid = $CFG->attemptuniqueid;
|
|
set_config('attemptuniqueid', $CFG->attemptuniqueid + 1);
|
|
|
|
return $attempt;
|
|
}
|
|
|
|
function quiz_get_user_attempt_unfinished($quizid, $userid) {
|
|
// Returns an object containing an unfinished attempt (if there is one)
|
|
return get_record("quiz_attempts", "quiz", $quizid, "userid", $userid, "timefinish", 0);
|
|
}
|
|
|
|
function quiz_get_user_attempts($quizid, $userid) {
|
|
// Returns a list of all attempts by a user
|
|
return get_records_select("quiz_attempts", "quiz = '$quizid' AND userid = '$userid' AND timefinish > 0",
|
|
"attempt ASC");
|
|
}
|
|
|
|
|
|
/// FUNCTIONS TO DO WITH QUIZ LAYOUT AND PAGES ////////////////////////////////
|
|
|
|
/**
|
|
* Returns a comma separated list of question ids for the current page
|
|
*
|
|
* @return string Comma separated list of question ids
|
|
* @param string $layout The string representing the quiz layout. Each page is represented as a
|
|
* comma separated list of question ids and 0 indicating page breaks.
|
|
* So 5,2,0,3,0 means questions 5 and 2 on page 1 and question 3 on page 2
|
|
* @param integer $page The number of the current page.
|
|
*/
|
|
function quiz_questions_on_page($layout, $page) {
|
|
$pages = explode(',0', $layout);
|
|
return trim($pages[$page], ',');
|
|
}
|
|
|
|
/**
|
|
* Returns a comma separated list of question ids for the quiz
|
|
*
|
|
* @return string Comma separated list of question ids
|
|
* @param string $layout The string representing the quiz layout. Each page is represented as a
|
|
* comma separated list of question ids and 0 indicating page breaks.
|
|
* So 5,2,0,3,0 means questions 5 and 2 on page 1 and question 3 on page 2
|
|
*/
|
|
function quiz_questions_in_quiz($layout) {
|
|
return str_replace(',0', '', $layout);
|
|
}
|
|
|
|
/**
|
|
* Returns the number of pages in the quiz layout
|
|
*
|
|
* @return integer Comma separated list of question ids
|
|
* @param string $layout The string representing the quiz layout.
|
|
*/
|
|
function quiz_number_of_pages($layout) {
|
|
return substr_count($layout, ',0');
|
|
}
|
|
|
|
/**
|
|
* Returns the first question number for the current quiz page
|
|
*
|
|
* @return integer The number of the first question
|
|
* @param string $quizlayout The string representing the layout for the whole quiz
|
|
* @param string $pagelayout The string representing the layout for the current page
|
|
*/
|
|
function quiz_first_questionnumber($quizlayout, $pagelayout) {
|
|
// this works by finding all the questions from the quizlayout that
|
|
// come before the current page and then adding up their lengths.
|
|
global $CFG;
|
|
$start = strpos($quizlayout, $pagelayout)-3;
|
|
if ($start > 0) {
|
|
$prevlist = substr($quizlayout, 0, $start);
|
|
return get_field_sql("SELECT sum(length)+1 FROM {$CFG->prefix}quiz_questions
|
|
WHERE id IN ($prevlist)");
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Re-paginates the quiz layout
|
|
*
|
|
* @return string The new layout string
|
|
* @param string $layout The string representing the quiz layout.
|
|
* @param integer $perpage The number of questions per page
|
|
* @param boolean $shuffle Should the questions be reordered randomly?
|
|
*/
|
|
function quiz_repaginate($layout, $perpage, $shuffle=false) {
|
|
$layout = str_replace(',0', '', $layout); // remove existing page breaks
|
|
$questions = explode(',', $layout);
|
|
if ($shuffle) {
|
|
srand((float)microtime() * 1000000); // for php < 4.2
|
|
shuffle($questions);
|
|
}
|
|
$i = 1;
|
|
$layout = '';
|
|
foreach ($questions as $question) {
|
|
if ($perpage and $i > $perpage) {
|
|
$layout .= '0,';
|
|
$i = 1;
|
|
}
|
|
$layout .= $question.',';
|
|
$i++;
|
|
}
|
|
return $layout.'0';
|
|
}
|
|
|
|
/**
|
|
* Print navigation panel for quiz attempt and review pages
|
|
*
|
|
* @param integer $page The number of the current page (counting from 0).
|
|
* @param integer $pages The total number of pages.
|
|
*/
|
|
function quiz_print_navigation_panel($page, $pages) {
|
|
//$page++;
|
|
echo '<div class="pagingbar">';
|
|
echo '<span class="title">' . get_string('page') . ':</span>';
|
|
if ($page > 0) {
|
|
// Print previous link
|
|
$strprev = get_string('previous');
|
|
echo '<a href="javascript:navigate(' . ($page - 1) . ');" title="'
|
|
. $strprev . '">(' . $strprev . ')</a>';
|
|
}
|
|
for ($i = 0; $i < $pages; $i++) {
|
|
if ($i == $page) {
|
|
echo '<span class="thispage">'.($i+1).'</span>';
|
|
} else {
|
|
echo '<a href="javascript:navigate(' . ($i) . ');">'.($i+1).'</a>';
|
|
}
|
|
}
|
|
|
|
if ($page < $pages - 1) {
|
|
// Print next link
|
|
$strnext = get_string('next');
|
|
echo '<a href="javascript:navigate(' . ($page + 1) . ');" title="'
|
|
. $strnext . '">(' . $strnext . ')</a>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
|
|
/// FUNCTIONS TO DO WITH QUIZ GRADES //////////////////////////////////////////
|
|
|
|
/**
|
|
* Creates an array of maximum grades for a quiz
|
|
*
|
|
* The grades are extracted from the quiz_question_instances table.
|
|
* @return array Array of grades indexed by question id
|
|
* These are the maximum possible grades that
|
|
* students can achieve for each of the questions
|
|
* @param integer $quiz The quiz object
|
|
*/
|
|
function quiz_get_all_question_grades($quiz) {
|
|
global $CFG;
|
|
|
|
$questionlist = quiz_questions_in_quiz($quiz->questions);
|
|
if (empty($questionlist)) {
|
|
return array();
|
|
}
|
|
|
|
$instances = get_records_sql("SELECT question,grade,id
|
|
FROM {$CFG->prefix}quiz_question_instances
|
|
WHERE quiz = '$quiz->id'" .
|
|
(is_null($questionlist) ? '' :
|
|
"AND question IN ($questionlist)"));
|
|
|
|
$list = explode(",", $questionlist);
|
|
$grades = array();
|
|
|
|
foreach ($list as $qid) {
|
|
if (isset($instances[$qid])) {
|
|
$grades[$qid] = $instances[$qid]->grade;
|
|
} else {
|
|
$grades[$qid] = 1;
|
|
}
|
|
}
|
|
return $grades;
|
|
}
|
|
|
|
|
|
function quiz_get_best_grade($quiz, $userid) {
|
|
/// Get the best current grade for a particular user in a quiz
|
|
if (!$grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid', $userid)) {
|
|
return NULL;
|
|
}
|
|
|
|
return (round($grade->grade,$quiz->decimalpoints));
|
|
}
|
|
|
|
/**
|
|
* Save the overall grade for a user at a quiz in the quiz_grades table
|
|
*
|
|
* @return boolean Indicates success or failure.
|
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
|
* and then saved.
|
|
* @param integer $userid The id of the user to save the best grade for. Can be
|
|
* null in which case the current user is assumed.
|
|
*/
|
|
function quiz_save_best_grade($quiz, $userid=null) {
|
|
global $USER;
|
|
|
|
// Assume the current user if $userid is null
|
|
if (is_null($userid)) {
|
|
$userid = $USER->id;
|
|
}
|
|
|
|
// Get all the attempts made by the user
|
|
if (!$attempts = quiz_get_user_attempts($quiz->id, $userid)) {
|
|
notify('Could not find any user attempts');
|
|
return false;
|
|
}
|
|
|
|
// Calculate the best grade
|
|
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
|
|
$bestgrade = (($bestgrade / $quiz->sumgrades) * $quiz->grade);
|
|
$bestgrade = round($bestgrade, $quiz->decimalpoints);
|
|
|
|
// Save the best grade in the database
|
|
if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid',
|
|
$userid)) {
|
|
$grade->grade = $bestgrade;
|
|
$grade->timemodified = time();
|
|
if (!update_record('quiz_grades', $grade)) {
|
|
notify('Could not update best grade');
|
|
return false;
|
|
}
|
|
} else {
|
|
$grade->quiz = $quiz->id;
|
|
$grade->userid = $userid;
|
|
$grade->grade = $bestgrade;
|
|
$grade->timemodified = time();
|
|
if (!insert_record('quiz_grades', $grade)) {
|
|
notify('Could not insert new best grade');
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Calculate the overall grade for a quiz given a number of attempts by a particular user.
|
|
*
|
|
* @return float The overall grade
|
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
|
* @param array $attempts An array of all the attempts of the user at the quiz
|
|
*/
|
|
function quiz_calculate_best_grade($quiz, $attempts) {
|
|
|
|
switch ($quiz->grademethod) {
|
|
|
|
case QUIZ_ATTEMPTFIRST:
|
|
foreach ($attempts as $attempt) {
|
|
return $attempt->sumgrades;
|
|
}
|
|
break;
|
|
|
|
case QUIZ_ATTEMPTLAST:
|
|
foreach ($attempts as $attempt) {
|
|
$final = $attempt->sumgrades;
|
|
}
|
|
return $final;
|
|
|
|
case QUIZ_GRADEAVERAGE:
|
|
$sum = 0;
|
|
$count = 0;
|
|
foreach ($attempts as $attempt) {
|
|
$sum += $attempt->sumgrades;
|
|
$count++;
|
|
}
|
|
return (float)$sum/$count;
|
|
|
|
default:
|
|
case QUIZ_GRADEHIGHEST:
|
|
$max = 0;
|
|
foreach ($attempts as $attempt) {
|
|
if ($attempt->sumgrades > $max) {
|
|
$max = $attempt->sumgrades;
|
|
}
|
|
}
|
|
return $max;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the attempt with the best grade for a quiz
|
|
*
|
|
* Which attempt is the best depends on $quiz->grademethod. If the grade
|
|
* method is GRADEAVERAGE then this function simply returns the last attempt.
|
|
* @return object The attempt with the best grade
|
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
|
* @param array $attempts An array of all the attempts of the user at the quiz
|
|
*/
|
|
function quiz_calculate_best_attempt($quiz, $attempts) {
|
|
|
|
switch ($quiz->grademethod) {
|
|
|
|
case QUIZ_ATTEMPTFIRST:
|
|
foreach ($attempts as $attempt) {
|
|
return $attempt;
|
|
}
|
|
break;
|
|
|
|
case QUIZ_GRADEAVERAGE: // need to do something with it :-)
|
|
case QUIZ_ATTEMPTLAST:
|
|
foreach ($attempts as $attempt) {
|
|
$final = $attempt;
|
|
}
|
|
return $final;
|
|
|
|
default:
|
|
case QUIZ_GRADEHIGHEST:
|
|
$max = -1;
|
|
foreach ($attempts as $attempt) {
|
|
if ($attempt->sumgrades > $max) {
|
|
$max = $attempt->sumgrades;
|
|
$maxattempt = $attempt;
|
|
}
|
|
}
|
|
return $maxattempt;
|
|
}
|
|
}
|
|
|
|
|
|
/// OTHER QUIZ FUNCTIONS ////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Array of names of quizzes a question appears in
|
|
*
|
|
* @return array Array of quiz names
|
|
* @param integer $id Question id
|
|
*/
|
|
function quizzes_question_used($id) {
|
|
|
|
$quizlist = array();
|
|
if ($instances = get_records('quiz_question_instances', 'question', $id)) {
|
|
foreach($instances as $instance) {
|
|
$quizlist[$instance->quiz] = get_field('quiz', 'name', 'id', $instance->quiz);
|
|
}
|
|
}
|
|
|
|
return $quizlist;
|
|
}
|
|
|
|
|
|
/**
|
|
* Parse field names used for the replace options on question edit forms
|
|
*/
|
|
function quiz_parse_fieldname($name, $nameprefix='question') {
|
|
$reg = array();
|
|
if (preg_match("/$nameprefix(\\d+)(\w+)/", $name, $reg)) {
|
|
return array('mode' => $reg[2], 'id' => (int)$reg[1]);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Determine render options
|
|
*/
|
|
function quiz_get_renderoptions($quiz, $state) {
|
|
// Show the question in readonly (review) mode if the quiz is in
|
|
// the closed state
|
|
$options->readonly = QUIZ_EVENTCLOSE === $state->event;
|
|
|
|
// Show feedback once the question has been graded (if allowed by the quiz)
|
|
$options->feedback = ('' !== $state->grade) && ($quiz->review & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
|
|
|
|
// Show validation only after a validation event
|
|
$options->validation = QUIZ_EVENTVALIDATE === $state->event;
|
|
|
|
// Show correct responses in readonly mode if the quiz allows it
|
|
$options->correct_responses = $options->readonly && ($quiz->review & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_IMMEDIATELY);
|
|
|
|
// Always show responses and scores
|
|
$options->responses = true;
|
|
$options->scores = true;
|
|
|
|
return $options;
|
|
}
|
|
|
|
|
|
/**
|
|
* Determine review options
|
|
*/
|
|
function quiz_get_reviewoptions($quiz, $attempt, $isteacher=false) {
|
|
$options->readonly = true;
|
|
if ($isteacher and !$attempt->preview) {
|
|
// The teacher should be shown everything except during preview when the teachers
|
|
// wants to see just what the students see
|
|
$options->responses = true;
|
|
$options->scores = true;
|
|
$options->feedback = true;
|
|
$options->correct_responses = true;
|
|
$options->solutions = false;
|
|
return $options;
|
|
}
|
|
if ((time() - $attempt->timefinish) < 120) {
|
|
$options->responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_RESPONSES) ? 1 : 0;
|
|
$options->scores = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SCORES) ? 1 : 0;
|
|
$options->feedback = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_FEEDBACK) ? 1 : 0;
|
|
$options->correct_responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_ANSWERS) ? 1 : 0;
|
|
$options->solutions = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0;
|
|
} else if (time() < $quiz->timeclose) {
|
|
$options->responses = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_RESPONSES) ? 1 : 0;
|
|
$options->scores = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SCORES) ? 1 : 0;
|
|
$options->feedback = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_FEEDBACK) ? 1 : 0;
|
|
$options->correct_responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_ANSWERS) ? 1 : 0;
|
|
$options->solutions = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0;
|
|
} else {
|
|
$options->responses = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_RESPONSES) ? 1 : 0;
|
|
$options->scores = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SCORES) ? 1 : 0;
|
|
$options->feedback = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_FEEDBACK) ? 1 : 0;
|
|
$options->correct_responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_ANSWERS) ? 1 : 0;
|
|
$options->solutions = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0;
|
|
}
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Upgrade states for an attempt to Moodle 1.5 model
|
|
*
|
|
* Any state that does not yet have its timestamp set to nonzero has not yet been upgraded from Moodle 1.4
|
|
* The reason these are still around is that for large sites it would have taken too long to
|
|
* upgrade all states at once. This function sets the timestamp field and creates an entry in the
|
|
* quiz_newest_states table.
|
|
* @param object $attempt The attempt whose states need upgrading
|
|
*/
|
|
function quiz_upgrade_states($attempt) {
|
|
global $CFG;
|
|
// The old quiz model only allowed a single response per quiz attempt so that there will be
|
|
// only one state record per question for this attempt.
|
|
|
|
// We set the timestamp of all states to the timemodified field of the attempt.
|
|
execute_sql("UPDATE {$CFG->prefix}quiz_states SET timestamp = '$attempt->timemodified' WHERE attempt = '$attempt->uniqueid'", false);
|
|
|
|
// For each state we create an entry in the quiz_newest_states table, with both newest and
|
|
// newgraded pointing to this state.
|
|
// Actually we only do this for states whose question is actually listed in $attempt->layout.
|
|
// We do not do it for states associated to wrapped questions like for example the questions
|
|
// used by a RANDOM question
|
|
$newest->attemptid = $attempt->uniqueid;
|
|
$questionlist = quiz_questions_in_quiz($attempt->layout);
|
|
if ($states = get_records_select('quiz_states', "attempt = '$attempt->uniqueid' AND question IN ($questionlist)")) {
|
|
foreach ($states as $state) {
|
|
$newest->newgraded = $state->id;
|
|
$newest->newest = $state->id;
|
|
$newest->questionid = $state->question;
|
|
insert_record('quiz_newest_states', $newest, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ULPGc ecastro
|
|
function quiz_get_question_review($quiz, $question) {
|
|
// returns a question icon
|
|
$qnum = $question->id;
|
|
$strpreview = get_string('previewquestion', 'quiz');
|
|
$context = $quiz->id ? '&contextquiz='.$quiz->id : '';
|
|
$quiz_id = $quiz->id ? '&quizid=' . $quiz->id : '';
|
|
return "<a title=\"$strpreview\" href=\"javascript:void();\" onClick=\"openpopup('/mod/quiz/preview.php?id=$qnum$quiz_id','$strpreview','scrollbars=yes,resizable=yes,width=700,height=480', false)\">
|
|
<img src=\"../../pix/t/preview.gif\" border=\"0\" alt=\"$strpreview\" /></a>";
|
|
}
|
|
|
|
/// FUNCTIONS USED BY IMPORT AND EXPORT ///////////////////////////////
|
|
|
|
/**
|
|
* Create default export filename
|
|
*
|
|
* @return string default export filename
|
|
* @param object $course
|
|
* @param object $category
|
|
*/
|
|
function default_export_filename($course,$category) {
|
|
//Take off some characters in the filename !!
|
|
$takeoff = array(" ", ":", "/", "\\", "|");
|
|
$export_word = str_replace($takeoff,"_",strtolower(get_string("exportfilename","quiz")));
|
|
//If non-translated, use "export"
|
|
if (substr($export_word,0,1) == "[") {
|
|
$export_word= "export";
|
|
}
|
|
|
|
//Calculate the date format string
|
|
$export_date_format = str_replace(" ","_",get_string("exportnameformat","quiz"));
|
|
//If non-translated, use "%Y%m%d-%H%M"
|
|
if (substr($export_date_format,0,1) == "[") {
|
|
$export_date_format = "%%Y%%m%%d-%%H%%M";
|
|
}
|
|
|
|
//Calculate the shortname
|
|
$export_shortname = clean_filename($course->shortname);
|
|
if (empty($export_shortname) or $export_shortname == '_' ) {
|
|
$export_shortname = $course->id;
|
|
}
|
|
|
|
//Calculate the category name
|
|
$export_categoryname = clean_filename($category->name);
|
|
|
|
//Calculate the final export filename
|
|
//The export word
|
|
$export_name = $export_word."-";
|
|
//The shortname
|
|
$export_name .= strtolower($export_shortname)."-";
|
|
//The category name
|
|
$export_name .= strtolower($export_categoryname)."-";
|
|
//The date format
|
|
$export_name .= userdate(time(),$export_date_format,99,false);
|
|
//The extension - no extension, supplied by format
|
|
// $export_name .= ".txt";
|
|
|
|
return $export_name;
|
|
}
|
|
|
|
|
|
/**
|
|
* Array of names of quizzes a category (and optionally its childs) appears in
|
|
*
|
|
* @return array Array of quiz names (with quiz->id as array keys)
|
|
* @param integer Quiz category id
|
|
* @param boolean Examine category childs recursively
|
|
*/
|
|
function quizzes_category_used($id, $recursive = false) {
|
|
|
|
$quizlist = array();
|
|
|
|
//Look for each question in the category
|
|
if ($questions = get_records('quiz_questions', 'category', $id)) {
|
|
foreach ($questions as $question) {
|
|
$qlist = quizzes_question_used($question->id);
|
|
$quizlist = $quizlist + $qlist;
|
|
}
|
|
}
|
|
|
|
//Look under child categories recursively
|
|
if ($recursive) {
|
|
if ($childs = get_records('quiz_categories', 'parent', $id)) {
|
|
foreach ($childs as $child) {
|
|
$quizlist = $quizlist + quizzes_category_used($child->id, $recursive);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $quizlist;
|
|
}
|
|
|
|
/**
|
|
* Get list of available import or export formats
|
|
**/
|
|
function get_import_export_formats( $type ) {
|
|
|
|
global $CFG;
|
|
$fileformats = get_list_of_plugins("mod/quiz/format");
|
|
|
|
$fileformatname=array();
|
|
require_once( "format.php" );
|
|
foreach ($fileformats as $key => $fileformat) {
|
|
$format_file = $CFG->dirroot . "/mod/quiz/format/$fileformat/format.php";
|
|
if (file_exists( $format_file ) ) {
|
|
require_once( $format_file );
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
$classname = "quiz_format_$fileformat";
|
|
$format_class = new $classname();
|
|
if ($type=='import') {
|
|
$provided = $format_class->provide_import();
|
|
}
|
|
else {
|
|
$provided = $format_class->provide_export();
|
|
}
|
|
if ($provided) {
|
|
$formatname = get_string($fileformat, 'quiz');
|
|
if ($formatname == "[[$fileformat]]") {
|
|
$formatname = $fileformat; // Just use the raw folder name
|
|
}
|
|
$fileformatnames[$fileformat] = $formatname;
|
|
}
|
|
}
|
|
natcasesort($fileformatnames);
|
|
|
|
return $fileformatnames;
|
|
}
|
|
?>
|