/**
 * This page export the game millionaire to html
 * 
 * @author  bdaloukas
 * @version $Id: exporthtml_millionaire.php,v 1.14 2012/07/25 11:16:03 bdaloukas Exp $
 * @package game
 **/
function game_millionaire_html_getquestions($game, $context, &$maxanswers, &$countofquestions, &$retfeedback, $destdir, &$files)
{
    global $CFG, $DB, $USER;
    $maxanswers = 0;
    $countofquestions = 0;
    $files = array();
    if ($game->sourcemodule != 'quiz' and $game->sourcemodule != 'question') {
        print_error(get_string('millionaire_sourcemodule_must_quiz_question', 'game', get_string('modulename', 'quiz')) . ' ' . get_string('modulename', $game->sourcemodule));
    }
    if ($game->sourcemodule == 'quiz') {
        if ($game->quizid == 0) {
            print_error(get_string('must_select_quiz', 'game'));
        }
        $select = "qtype='multichoice' AND quiz='{$game->quizid}' " . " AND qqi.question=q.id";
        $table = "{question} q,{quiz_question_instances} qqi";
    } else {
        if ($game->questioncategoryid == 0) {
            print_error(get_string('must_select_questioncategory', 'game'));
        }
        //include subcategories
        $select = 'category=' . $game->questioncategoryid;
        if ($game->subcategories) {
            $cats = question_categorylist($game->questioncategoryid);
            if (strpos($cats, ',') > 0) {
                $select = 'category in (' . $cats . ')';
            }
        }
        $select .= " AND qtype='multichoice'";
        $table = "{question} q";
    }
    $select .= " AND q.hidden=0";
    $sql = "SELECT q.id as id, q.questiontext FROM {$table} WHERE {$select}";
    $recs = $DB->get_records_sql($sql);
    $ret = '';
    $retfeedback = '';
    foreach ($recs as $rec) {
        $recs2 = $DB->get_records('question_answers', array('question' => $rec->id), 'fraction DESC', 'id,answer,feedback');
        //Must parse the questiontext and get the name of files.
        $line = $rec->questiontext;
        $line = game_export_split_files($game->course, $context, 'questiontext', $rec->id, $rec->questiontext, $destdir, $files);
        $linefeedback = '';
        foreach ($recs2 as $rec2) {
            $line .= '#' . str_replace(array('"', '#'), array("'", ' '), game_export_split_files($game->course, $context, 'answer', $rec2->id, $rec2->answer, $destdir, $files));
            $linefeedback .= '#' . str_replace(array('"', '#'), array("'", ' '), $rec2->feedback);
        }
        if ($ret != '') {
            $ret .= ",\r";
        }
        $ret .= '"' . base64_encode($line) . '"';
        if ($retfeedback != '') {
            $retfeedback .= ",\r";
        }
        $retfeedback .= '"' . base64_encode($linefeedback) . '"';
        if (count($recs2) > $maxanswers) {
            $maxanswers = count($recs2);
        }
        $countofquestions++;
    }
    return $ret;
}
예제 #2
0
/**
* Function to read all questions for category into big array
*
* @param int $category category number
* @param bool $noparent if true only questions with NO parent will be selected
* @param bool $recurse include subdirectories
* @param bool $export set true if this is called by questionbank export
*/
function get_questions_category($category, $noparent = false, $recurse = true, $export = true)
{
    global $DB;
    // Build sql bit for $noparent
    $npsql = '';
    if ($noparent) {
        $npsql = " and parent='0' ";
    }
    // Get list of categories
    if ($recurse) {
        $categorylist = question_categorylist($category->id);
    } else {
        $categorylist = array($category->id);
    }
    // Get the list of questions for the category
    list($usql, $params) = $DB->get_in_or_equal($categorylist);
    $questions = $DB->get_records_select('question', "category {$usql} {$npsql}", $params, 'qtype, name');
    // Iterate through questions, getting stuff we need
    $qresults = array();
    foreach ($questions as $key => $question) {
        $question->export_process = $export;
        $qtype = question_bank::get_qtype($question->qtype, false);
        if ($export && $qtype->name() == 'missingtype') {
            // Unrecognised question type. Skip this question when exporting.
            continue;
        }
        $qtype->get_question_options($question);
        $qresults[] = $question;
    }
    return $qresults;
}
예제 #3
0
 /**
  * Initialize the object so it will be ready to return where() and params()
  */
 private function init()
 {
     global $DB;
     if (!($this->category = $this->get_current_category($this->cat))) {
         return;
     }
     if ($this->recurse) {
         $categoryids = question_categorylist($this->category->id);
     } else {
         $categoryids = array($this->category->id);
     }
     list($catidtest, $this->params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'cat');
     $this->where = 'q.category ' . $catidtest;
 }
예제 #4
0
 function create_session_and_responses(&$question, &$state, $cmoptions, $attempt)
 {
     global $QTYPE_EXCLUDE_FROM_RANDOM;
     // Choose a random question from the category:
     // We need to make sure that no question is used more than once in the
     // quiz. Therfore the following need to be excluded:
     // 1. All questions that are explicitly assigned to the quiz
     // 2. All random questions
     // 3. All questions that are already chosen by an other random question
     // 4. Deleted questions
     if (!isset($cmoptions->questionsinuse)) {
         $cmoptions->questionsinuse = $attempt->layout;
     }
     if (!isset($this->catrandoms[$question->category][$question->questiontext])) {
         // Need to fetch random questions from category $question->category"
         // (Note: $this refers to the questiontype, not the question.)
         global $CFG;
         if ($question->questiontext == "1") {
             // recurse into subcategories
             $categorylist = question_categorylist($question->category);
         } else {
             $categorylist = $question->category;
         }
         if ($catrandoms = get_records_select('question', "category IN ({$categorylist})\n                         AND parent = '0'\n                         AND hidden = '0'\n                         AND id NOT IN ({$cmoptions->questionsinuse})\n                         AND qtype NOT IN ({$QTYPE_EXCLUDE_FROM_RANDOM})", '', 'id')) {
             $this->catrandoms[$question->category][$question->questiontext] = draw_rand_array($catrandoms, count($catrandoms));
             // from bug 1889
         } else {
             $this->catrandoms[$question->category][$question->questiontext] = array();
         }
     }
     while ($wrappedquestion = array_pop($this->catrandoms[$question->category][$question->questiontext])) {
         if (!ereg("(^|,){$wrappedquestion->id}(,|\$)", $cmoptions->questionsinuse)) {
             /// $randomquestion is not in use and will therefore be used
             /// as the randomquestion here...
             $wrappedquestion = get_record('question', 'id', $wrappedquestion->id);
             global $QTYPES;
             $QTYPES[$wrappedquestion->qtype]->get_question_options($wrappedquestion);
             $QTYPES[$wrappedquestion->qtype]->create_session_and_responses($wrappedquestion, $state, $cmoptions, $attempt);
             $wrappedquestion->name_prefix = $question->name_prefix;
             $wrappedquestion->maxgrade = $question->maxgrade;
             $cmoptions->questionsinuse .= ",{$wrappedquestion->id}";
             $state->options->question =& $wrappedquestion;
             return true;
         }
     }
     $question->questiontext = '<span class="notifyproblem">' . get_string('toomanyrandom', 'quiz') . '</span>';
     $question->qtype = 'description';
     $state->responses = array('' => '');
     return true;
 }
/**
 * This page export the game millionaire to html
 * 
 * @author  bdaloukas
 * @version $Id: exporthtml_millionaire.php,v 1.9 2010/07/26 00:43:58 bdaloukas Exp $
 * @package game
 **/
function game_millionaire_html_getquestions($game, &$max)
{
    global $CFG, $DB, $USER;
    $max = 0;
    if ($game->sourcemodule != 'quiz' and $game->sourcemodule != 'question') {
        print_error(get_string('millionaire_sourcemodule_must_quiz_question', 'game', get_string('modulename', 'quiz')) . ' ' . get_string('modulename', $attempt->sourcemodule));
    }
    if ($game->sourcemodule == 'quiz') {
        if ($game->quizid == 0) {
            print_error(get_string('must_select_quiz', 'game'));
        }
        $select = "qtype='multichoice' AND quiz='{$game->quizid}' " . " AND qqi.question=q.id";
        $table = "{question} q,{quiz_question_instances} qqi";
    } else {
        if ($game->questioncategoryid == 0) {
            print_error(get_string('must_select_questioncategory', 'game'));
        }
        //include subcategories
        $select = 'category=' . $game->questioncategoryid;
        if ($game->subcategories) {
            $cats = question_categorylist($game->questioncategoryid);
            if (strpos($cats, ',') > 0) {
                $select = 'category in (' . $cats . ')';
            }
        }
        $select .= " AND qtype='multichoice'";
        $table = "{question} q";
    }
    $select .= " AND q.hidden=0";
    $sql = "SELECT q.id as id, q.questiontext FROM {$table} WHERE {$select}";
    $recs = $DB->get_records_sql($sql);
    $ret = '';
    foreach ($recs as $rec) {
        $recs2 = $DB->get_records('question_answers', array('question' => $rec->id), 'fraction DESC', 'id,answer');
        $line = $rec->questiontext;
        foreach ($recs2 as $rec2) {
            $line .= '#' . str_replace(array('"', '#'), array("'", ' '), $rec2->answer);
        }
        if ($ret != '') {
            $ret .= ",\r";
        }
        $ret .= '"' . base64_encode($line) . '"';
        if (count($recs2) > $max) {
            $max = count($recs2);
        }
    }
    return $ret;
}
function game_showanswers_question($game)
{
    global $DB;
    if ($game->gamekind != 'bookquiz') {
        $select = ' category=' . $game->questioncategoryid;
        if ($game->subcategories) {
            $cats = question_categorylist($game->questioncategoryid);
            if (strpos($cats, ',') > 0) {
                $select = ' category in (' . $cats . ')';
            }
        }
    } else {
        $context = get_context_instance(50, $COURSE->id);
        $select = " contextid in ({$context->id})";
        $select2 = '';
        if ($recs = $DB->get_records_select('question_categories', $select, null, 'id,id')) {
            foreach ($recs as $rec) {
                $select2 .= ',' . $rec->id;
            }
        }
        $select = ' AND category IN (' . substr($select2, 1) . ')';
    }
    $select .= ' AND hidden = 0 ';
    $select .= game_showanswers_appendselect($game);
    $showcategories = $game->gamekind == 'bookquiz';
    $order = $showcategories ? 'category,questiontext' : 'questiontext';
    game_showanswers_question_select($game, '{question} q', $select, '*', $order, $showcategories, $game->course);
}
예제 #7
0
 function create_session_and_responses(&$question, &$state, $cmoptions, $attempt)
 {
     // Choose a random shortanswer question from the category:
     // We need to make sure that no question is used more than once in the
     // quiz. Therfore the following need to be excluded:
     // 1. All questions that are explicitly assigned to the quiz
     // 2. All random questions
     // 3. All questions that are already chosen by an other random question
     global $QTYPES;
     if (!isset($cmoptions->questionsinuse)) {
         $cmoptions->questionsinuse = $cmoptions->questions;
     }
     if ($question->options->subcats) {
         // recurse into subcategories
         $categorylist = question_categorylist($question->category);
     } else {
         $categorylist = $question->category;
     }
     $saquestions = $this->get_sa_candidates($categorylist, $cmoptions->questionsinuse);
     $count = count($saquestions);
     $wanted = $question->options->choose;
     $errorstr = '';
     if ($count < $wanted && isteacherinanycourse()) {
         if ($count >= 2) {
             $errorstr = "Error: could not get enough Short-Answer questions!\n                 Got {$count} Short-Answer questions, but wanted {$wanted}.\n                 Reducing number to choose from to {$count}!";
             $wanted = $question->options->choose = $count;
         } else {
             $errorstr = "Error: could not get enough Short-Answer questions!\n                 This can happen if all available Short-Answer questions are already\n                 taken up by other Random questions or Random Short-Answer question.\n                 Another possible cause for this error is that Short-Answer\n                 questions were deleted after this Random Short-Answer question was\n                 created.";
         }
         notify($errorstr);
         $errorstr = '<span class="notifyproblem">' . $errorstr . '</span>';
     }
     if ($count < $wanted) {
         $question->questiontext = "{$errorstr}<br /><br />Insufficient selection options are\n             available for this question, therefore it is not available in  this\n             quiz. Please inform your teacher.";
         // Treat this as a description from this point on
         $question->qtype = DESCRIPTION;
         return true;
     }
     $saquestions = draw_rand_array($saquestions, $question->options->choose);
     // from bug 1889
     foreach ($saquestions as $key => $wrappedquestion) {
         if (!$QTYPES[$wrappedquestion->qtype]->get_question_options($wrappedquestion)) {
             return false;
         }
         // Now we overwrite the $question->options->answers field to only
         // *one* (the first) correct answer. This loop can be deleted to
         // take all answers into account (i.e. put them all into the
         // drop-down menu.
         $foundcorrect = false;
         foreach ($wrappedquestion->options->answers as $answer) {
             if ($foundcorrect || $answer->fraction != 1.0) {
                 unset($wrappedquestion->options->answers[$answer->id]);
             } else {
                 if (!$foundcorrect) {
                     $foundcorrect = true;
                 }
             }
         }
         if (!$QTYPES[$wrappedquestion->qtype]->create_session_and_responses($wrappedquestion, $state, $cmoptions, $attempt)) {
             return false;
         }
         $wrappedquestion->name_prefix = $question->name_prefix;
         $wrappedquestion->maxgrade = $question->maxgrade;
         $cmoptions->questionsinuse .= ",{$wrappedquestion->id}";
         $state->options->subquestions[$key] = clone $wrappedquestion;
     }
     // Shuffle the answers (Do this always because this is a random question type)
     $subquestionids = array_values(array_map(create_function('$val', 'return $val->id;'), $state->options->subquestions));
     $subquestionids = swapshuffle($subquestionids);
     // Create empty responses
     foreach ($subquestionids as $val) {
         $state->responses[$val] = '';
     }
     return true;
 }
예제 #8
0
 /**
  * Return all the question types used in this quiz.
  *
  * @param  boolean $includepotential if the quiz include random questions, setting this flag to true will make the function to
  * return all the possible question types in the random questions category
  * @return array a sorted array including the different question types
  * @since  Moodle 3.1
  */
 public function get_all_question_types_used($includepotential = false)
 {
     $questiontypes = array();
     // To control if we need to look in categories for questions.
     $qcategories = array();
     // We must be careful with random questions, if we find a random question we must assume that the quiz may content
     // any of the questions in the referenced category (or subcategories).
     foreach ($this->get_questions() as $questiondata) {
         if ($questiondata->qtype == 'random' and $includepotential) {
             $includesubcategories = (bool) $questiondata->questiontext;
             if (!isset($qcategories[$questiondata->category])) {
                 $qcategories[$questiondata->category] = false;
             }
             if ($includesubcategories) {
                 $qcategories[$questiondata->category] = true;
             }
         } else {
             if (!in_array($questiondata->qtype, $questiontypes)) {
                 $questiontypes[] = $questiondata->qtype;
             }
         }
     }
     if (!empty($qcategories)) {
         // We have to look for all the question types in these categories.
         $categoriestolook = array();
         foreach ($qcategories as $cat => $includesubcats) {
             if ($includesubcats) {
                 $categoriestolook = array_merge($categoriestolook, question_categorylist($cat));
             } else {
                 $categoriestolook[] = $cat;
             }
         }
         $questiontypesincategories = question_bank::get_all_question_types_in_categories($categoriestolook);
         $questiontypes = array_merge($questiontypes, $questiontypesincategories);
     }
     $questiontypes = array_unique($questiontypes);
     sort($questiontypes);
     return $questiontypes;
 }
예제 #9
0
function game_questions_shortanswer_question($game)
{
    if ($game->questioncategoryid == 0) {
        print_error(get_string('must_select_questioncategory', 'game'));
    }
    //include subcategories
    $select = 'q.category=' . $game->questioncategoryid;
    if ($game->subcategories) {
        $cats = question_categorylist($game->questioncategoryid);
        if (strpos($cats, ',') > 0) {
            $select = 'q.category in (' . $cats . ')';
        }
    }
    $select .= " AND qtype='shortanswer' " . " AND qa.question=q.id" . " AND q.hidden=0";
    $table = "{question} q,{question_answers} qa";
    $fields = "qa.id as qaid, q.id, q.questiontext as questiontext, " . "qa.answer as answertext, q.id as questionid";
    return game_questions_shortanswer_question_fraction($table, $fields, $select);
}
예제 #10
0
/**
 * @return array of question category ids of the category and all subcategories.
 */
function question_categorylist($categoryid)
{
    global $DB;
    $subcategories = $DB->get_records('question_categories', array('parent' => $categoryid), 'sortorder ASC', 'id, 1');
    $categorylist = array($categoryid);
    foreach ($subcategories as $subcategory) {
        $categorylist = array_merge($categorylist, question_categorylist($subcategory->id));
    }
    return $categorylist;
}
예제 #11
0
 /**
  * Get all the usable questions from a particular question category.
  *
  * @param integer $categoryid the id of a question category.
  * @param boolean whether to include questions from subcategories.
  * @param string $questionsinuse comma-separated list of question ids to exclude from consideration.
  * @return array of question records.
  */
 function get_usable_questions_from_category($categoryid, $subcategories, $questionsinuse) {
     global $DB;
     $this->init_qtype_lists();
     if ($subcategories) {
         $categorylist = question_categorylist($categoryid);
     } else {
         $categorylist = $categoryid;
     }
     if (!$catrandoms = $DB->get_records_select('question',
             "category IN ($categorylist)
                  AND parent = 0
                  AND hidden = 0
                  AND id NOT IN ($questionsinuse)
                  AND qtype NOT IN ($this->excludedqtypes)", null, '', 'id')) {
         $catrandoms = array();
     }
     return $catrandoms;
 }
예제 #12
0
/**
 * Randomly add a number of multichoice questions to an offlinequiz group.
 * 
 * @param unknown_type $offlinequiz
 * @param unknown_type $addonpage
 * @param unknown_type $categoryid
 * @param unknown_type $number
 * @param unknown_type $includesubcategories
 */
function offlinequiz_add_random_questions($offlinequiz, $offlinegroup, $categoryid, $number, $recurse)
{
    global $DB;
    $category = $DB->get_record('question_categories', array('id' => $categoryid));
    if (!$category) {
        print_error('invalidcategoryid', 'error');
    }
    $catcontext = context::instance_by_id($category->contextid);
    require_capability('moodle/question:useall', $catcontext);
    if ($recurse) {
        $categoryids = question_categorylist($category->id);
    } else {
        $categoryids = array($category->id);
    }
    list($qcsql, $qcparams) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'qc');
    // Find all questions in the selected categories that are not in the offline group yet.
    $sql = "SELECT id\n              FROM {question} q\n             WHERE q.category {$qcsql}\n               AND q.parent = 0\n               AND q.hidden = 0\n               AND q.qtype IN ('multichoice', 'multichoiceset')\n               AND NOT EXISTS (SELECT 1 \n                                 FROM {offlinequiz_group_questions} ogq\n                                WHERE ogq.questionid = q.id\n                                  AND ogq.offlinequizid = :offlinequizid\n                                  AND ogq.offlinegroupid = :offlinegroupid)";
    $qcparams['offlinequizid'] = $offlinequiz->id;
    $qcparams['offlinegroupid'] = $offlinegroup->id;
    $questionids = $DB->get_fieldset_sql($sql, $qcparams);
    srand(microtime() * 1000000);
    shuffle($questionids);
    $chosenids = array();
    while (($questionid = array_shift($questionids)) && $number > 0) {
        $chosenids[] = $questionid;
        $number -= 1;
    }
    $maxmarks = array();
    if ($chosenids) {
        // Get the old maxmarks in case questions are already in other offlinequiz groups.
        list($qsql, $params) = $DB->get_in_or_equal($chosenids, SQL_PARAMS_NAMED);
        $sql = "SELECT id, questionid, maxmark\n                  FROM {offlinequiz_group_questions}\n                 WHERE offlinequizid = :offlinequizid\n                   AND questionid {$qsql}";
        $params['offlinequizid'] = $offlinequiz->id;
        if ($slots = $DB->get_records_sql($sql, $params)) {
            foreach ($slots as $slot) {
                if (!array_key_exists($slot->questionid, $maxmarks)) {
                    $maxmarks[$slot->questionid] = $slot->maxmark;
                }
            }
        }
    }
    offlinequiz_add_questionlist_to_group($chosenids, $offlinequiz, $offlinegroup, null, $maxmarks);
}
예제 #13
0
/**
 * Returns a comma separated list of ids of the category and all subcategories
 */
function question_categorylist($categoryid)
{
    global $DB;
    // returns a comma separated list of ids of the category and all subcategories
    $categorylist = $categoryid;
    if ($subcategories = $DB->get_records('question_categories', array('parent' => $categoryid), 'sortorder ASC', 'id, 1')) {
        foreach ($subcategories as $subcategory) {
            $categorylist .= ',' . question_categorylist($subcategory->id);
        }
    }
    return $categorylist;
}
예제 #14
0
/**
* Prints the table of questions in a category with interactions
*
* @param object $course   The course object
* @param int $categoryid  The id of the question category to be displayed
* @param int $cm      The course module record if we are in the context of a particular module, 0 otherwise
* @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
* @param int $page        The number of the page to be displayed
* @param int $perpage     Number of questions to show per page
* @param boolean $showhidden   True if also hidden questions should be displayed
* @param boolean $showquestiontext whether the text of each question should be shown in the list
*/
function question_list($contexts, $pageurl, $categoryandcontext, $cm = null, $recurse = 1, $page = 0, $perpage = 100, $showhidden = false, $sortorder = 'typename', $sortorderdecoded = 'qtype, name ASC', $showquestiontext = false, $addcontexts = array())
{
    global $USER, $CFG, $THEME, $COURSE;
    $lastchangedid = optional_param('lastchanged', 0, PARAM_INT);
    list($categoryid, $contextid) = explode(',', $categoryandcontext);
    $qtypemenu = question_type_menu();
    $strcategory = get_string("category", "quiz");
    $strquestion = get_string("question", "quiz");
    $straddquestions = get_string("addquestions", "quiz");
    $strimportquestions = get_string("importquestions", "quiz");
    $strexportquestions = get_string("exportquestions", "quiz");
    $strnoquestions = get_string("noquestions", "quiz");
    $strselect = get_string("select", "quiz");
    $strselectall = get_string("selectall", "quiz");
    $strselectnone = get_string("selectnone", "quiz");
    $strcreatenewquestion = get_string("createnewquestion", "quiz");
    $strquestionname = get_string("questionname", "quiz");
    $strdelete = get_string("delete");
    $stredit = get_string("edit");
    $strmove = get_string('moveqtoanothercontext', 'question');
    $strview = get_string("view");
    $straction = get_string("action");
    $strrestore = get_string('restore');
    $strtype = get_string("type", "quiz");
    $strcreatemultiple = get_string("createmultiple", "quiz");
    $strpreview = get_string("preview", "quiz");
    if (!$categoryid) {
        echo "<p style=\"text-align:center;\"><b>";
        print_string("selectcategoryabove", "quiz");
        echo "</b></p>";
        return;
    }
    if (!($category = get_record('question_categories', 'id', $categoryid, 'contextid', $contextid))) {
        notify('Category not found!');
        return;
    }
    $catcontext = get_context_instance_by_id($contextid);
    $canadd = has_capability('moodle/question:add', $catcontext);
    //check for capabilities on all questions in category, will also apply to sub cats.
    $caneditall = has_capability('moodle/question:editall', $catcontext);
    $canuseall = has_capability('moodle/question:useall', $catcontext);
    $canmoveall = has_capability('moodle/question:moveall', $catcontext);
    if ($cm and $cm->modname == 'quiz') {
        $quizid = $cm->instance;
    } else {
        $quizid = 0;
    }
    $returnurl = $pageurl->out();
    $questionurl = new moodle_url("{$CFG->wwwroot}/question/question.php", array('returnurl' => $returnurl));
    if ($cm !== null) {
        $questionurl->param('cmid', $cm->id);
    } else {
        $questionurl->param('courseid', $COURSE->id);
    }
    $questionmoveurl = new moodle_url("{$CFG->wwwroot}/question/contextmoveq.php", array('returnurl' => $returnurl));
    if ($cm !== null) {
        $questionmoveurl->param('cmid', $cm->id);
    } else {
        $questionmoveurl->param('courseid', $COURSE->id);
    }
    echo '<div class="boxaligncenter">';
    $formatoptions = new stdClass();
    $formatoptions->noclean = true;
    echo format_text($category->info, FORMAT_MOODLE, $formatoptions, $COURSE->id);
    echo '<table><tr>';
    if ($canadd) {
        echo '<td valign="top" align="right">';
        popup_form($questionurl->out(false, array('category' => $category->id)) . '&amp;qtype=', $qtypemenu, "addquestion", "", "choose", "", "", false, "self", "<strong>{$strcreatenewquestion}</strong>");
        echo '</td><td valign="top" align="right">';
        helpbutton("questiontypes", $strcreatenewquestion, "quiz");
        echo '</td>';
    } else {
        echo '<td>';
        print_string('nopermissionadd', 'question');
        echo '</td>';
    }
    echo '</tr></table>';
    echo '</div>';
    $categorylist = $recurse ? question_categorylist($category->id) : $category->id;
    // hide-feature
    $showhidden = $showhidden ? '' : " AND hidden = '0'";
    if (!($totalnumber = count_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}"))) {
        echo "<p style=\"text-align:center;\">";
        print_string("noquestions", "quiz");
        echo "</p>";
        return;
    }
    if (!($questions = get_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}", $sortorderdecoded, '*', $page * $perpage, $perpage))) {
        // There are no questions on the requested page.
        $page = 0;
        if (!($questions = get_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}", $sortorderdecoded, '*', 0, $perpage))) {
            // There are no questions at all
            echo "<p style=\"text-align:center;\">";
            print_string("noquestions", "quiz");
            echo "</p>";
            return;
        }
    }
    print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage');
    echo question_sort_options($pageurl, $sortorder);
    echo '<form method="post" action="edit.php">';
    echo '<fieldset class="invisiblefieldset" style="display: block;">';
    echo '<input type="hidden" name="sesskey" value="' . $USER->sesskey . '" />';
    echo $pageurl->hidden_params_out();
    echo '<table id="categoryquestions" style="width: 100%"><tr>';
    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$straction}</th>";
    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">{$strquestionname}</th>\n    <th style=\"white-space:nowrap; text-align: right;\" class=\"header\" scope=\"col\">{$strtype}</th>";
    echo "</tr>\n";
    foreach ($questions as $question) {
        $nameclass = '';
        $textclass = '';
        if ($question->hidden) {
            $nameclass = 'dimmed_text';
            $textclass = 'dimmed_text';
        }
        if ($showquestiontext) {
            $nameclass .= ' header';
        }
        if ($question->id == $lastchangedid) {
            $nameclass = 'highlight';
        }
        if ($nameclass) {
            $nameclass = 'class="' . $nameclass . '"';
        }
        if ($textclass) {
            $textclass = 'class="' . $textclass . '"';
        }
        echo "<tr>\n<td style=\"white-space:nowrap;\" {$nameclass}>\n";
        $canuseq = question_has_capability_on($question, 'use', $question->category);
        if (function_exists('module_specific_actions')) {
            echo module_specific_actions($pageurl, $question->id, $cm->id, $canuseq);
        }
        // preview
        if ($canuseq) {
            $quizorcourseid = $quizid ? '&amp;quizid=' . $quizid : '&amp;courseid=' . $COURSE->id;
            link_to_popup_window('/question/preview.php?id=' . $question->id . $quizorcourseid, 'questionpreview', "<img src=\"{$CFG->pixpath}/t/preview.gif\" class=\"iconsmall\" alt=\"{$strpreview}\" />", 0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
        }
        // edit, hide, delete question, using question capabilities, not quiz capabilieies
        if (question_has_capability_on($question, 'edit', $question->category) || question_has_capability_on($question, 'move', $question->category)) {
            echo "<a title=\"{$stredit}\" href=\"" . $questionurl->out(false, array('id' => $question->id)) . "\"><img\n                    src=\"{$CFG->pixpath}/t/edit.gif\" alt=\"{$stredit}\" /></a>&nbsp;";
        } elseif (question_has_capability_on($question, 'view', $question->category)) {
            echo "<a title=\"{$strview}\" href=\"" . $questionurl->out(false, array('id' => $question->id)) . "\"><img\n                    src=\"{$CFG->pixpath}/i/info.gif\" alt=\"{$strview}\" /></a>&nbsp;";
        }
        if (question_has_capability_on($question, 'move', $question->category) && question_has_capability_on($question, 'view', $question->category)) {
            echo "<a title=\"{$strmove}\" href=\"" . $questionurl->out(false, array('id' => $question->id, 'movecontext' => 1)) . "\"><img\n                    src=\"{$CFG->pixpath}/t/move.gif\" alt=\"{$strmove}\" /></a>&nbsp;";
        }
        if (question_has_capability_on($question, 'edit', $question->category)) {
            // hide-feature
            if ($question->hidden) {
                echo "<a title=\"{$strrestore}\" href=\"edit.php?" . $pageurl->get_query_string() . "&amp;unhide={$question->id}&amp;sesskey={$USER->sesskey}\"><img\n                        src=\"{$CFG->pixpath}/t/restore.gif\" alt=\"{$strrestore}\" /></a>";
            } else {
                echo "<a title=\"{$strdelete}\" href=\"edit.php?" . $pageurl->get_query_string() . "&amp;deleteselected={$question->id}&amp;q{$question->id}=1\"><img\n                        src=\"{$CFG->pixpath}/t/delete.gif\" alt=\"{$strdelete}\" /></a>";
            }
        }
        if ($caneditall || $canmoveall || $canuseall) {
            echo "&nbsp;<input title=\"{$strselect}\" type=\"checkbox\" name=\"q{$question->id}\" value=\"1\" />";
        }
        echo "</td>\n";
        echo "<td {$nameclass}>" . format_string($question->name) . "</td>\n";
        echo "<td {$nameclass} style='text-align: right'>\n";
        print_question_icon($question);
        echo "</td>\n";
        echo "</tr>\n";
        if ($showquestiontext) {
            echo '<tr><td colspan="3" ' . $textclass . '>';
            $formatoptions = new stdClass();
            $formatoptions->noclean = true;
            $formatoptions->para = false;
            echo format_text($question->questiontext, $question->questiontextformat, $formatoptions, $COURSE->id);
            echo "</td></tr>\n";
        }
    }
    echo "</table>\n";
    $paging = print_paging_bar($totalnumber, $page, $perpage, $pageurl, 'qpage', false, true);
    if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
        if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
            $showall = '<a href="edit.php?' . $pageurl->get_query_string(array('qperpage' => 1000)) . '">' . get_string('showall', 'moodle', $totalnumber) . '</a>';
        } else {
            $showall = '<a href="edit.php?' . $pageurl->get_query_string(array('qperpage' => DEFAULT_QUESTIONS_PER_PAGE)) . '">' . get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE) . '</a>';
        }
        if ($paging) {
            $paging = substr($paging, 0, strrpos($paging, '</div>'));
            $paging .= "<br />{$showall}</div>";
        } else {
            $paging = "<div class='paging'>{$showall}</div>";
        }
    }
    echo $paging;
    if ($caneditall || $canmoveall || $canuseall) {
        echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">' . $strselectall . '</a> /' . ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">' . $strselectnone . '</a>';
        echo '<br />';
        echo '<strong>&nbsp;' . get_string('withselected', 'quiz') . ':</strong><br />';
        if (function_exists('module_specific_buttons')) {
            echo module_specific_buttons($cm->id);
        }
        // print delete and move selected question
        if ($caneditall) {
            echo '<input type="submit" name="deleteselected" value="' . $strdelete . "\" />\n";
        }
        if ($canmoveall && count($addcontexts)) {
            echo '<input type="submit" name="move" value="' . get_string('moveto', 'quiz') . "\" />\n";
            question_category_select_menu($addcontexts, false, 0, "{$category->id},{$category->contextid}");
        }
        if (function_exists('module_specific_controls') && $canuseall) {
            echo module_specific_controls($totalnumber, $recurse, $category, $cm->id);
        }
    }
    echo '</fieldset>';
    echo "</form>\n";
}
예제 #15
0
 /**
  * Get all the usable shortanswer questions from a particular question category.
  *
  * @param integer $categoryid the id of a question category.
  * @param bool $subcategories whether to include questions from subcategories.
  * @return array of question records.
  */
 public function get_available_saquestions_from_category($categoryid, $subcategories)
 {
     if (isset($this->availablesaquestionsbycategory[$categoryid][$subcategories])) {
         return $this->availablesaquestionsbycategory[$categoryid][$subcategories];
     }
     if ($subcategories) {
         $categoryids = question_categorylist($categoryid);
     } else {
         $categoryids = array($categoryid);
     }
     $questionids = question_bank::get_finder()->get_questions_from_categories($categoryids, "qtype = 'shortanswer'");
     $this->availablesaquestionsbycategory[$categoryid][$subcategories] = $questionids;
     return $questionids;
 }
 private function get_categories()
 {
     $cmid = optional_param('cmid', 0, PARAM_INT);
     $categoryparam = optional_param('category', '', PARAM_TEXT);
     $courseid = optional_param('courseid', 0, PARAM_INT);
     if ($cmid) {
         list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) = question_edit_setup('editq', '/mod/quiz/edit.php', true);
         if ($pagevars['cat']) {
             $categoryparam = $pagevars['cat'];
         }
     }
     if ($categoryparam) {
         $catandcontext = explode(',', $categoryparam);
         $cats = question_categorylist($catandcontext[0]);
         return $cats;
     } else {
         if ($cmid) {
             list($module, $cm) = get_module_from_cmid($cmid);
             $courseid = $cm->course;
             require_login($courseid, false, $cm);
             $thiscontext = context_module::instance($cmid);
         } else {
             $module = null;
             $cm = null;
             if ($courseid) {
                 $thiscontext = context_course::instance($courseid);
             } else {
                 $thiscontext = null;
             }
         }
     }
     $cats = get_categories_for_contexts($thiscontext->id);
     return array_keys($cats);
 }
예제 #17
0
function game_millionaire_selectquestion(&$aanswer, $game, $attempt, &$millionaire, &$query, $context)
{
    global $DB, $USER;
    if ($game->sourcemodule != 'quiz' and $game->sourcemodule != 'question') {
        print_error(get_string('millionaire_sourcemodule_must_quiz_question', 'game', get_string('modulename', 'quiz')) . ' ' . get_string('modulename', $attempt->sourcemodule));
    }
    if ($millionaire->queryid != 0) {
        game_millionaire_loadquestions($game, $millionaire, $query, $aanswer, $context);
        return;
    }
    if ($game->sourcemodule == 'quiz') {
        if ($game->quizid == 0) {
            print_error(get_string('must_select_quiz', 'game'));
        }
        if (game_get_moodle_version() < '02.07') {
            $select = "qtype='multichoice' AND quiz='{$game->quizid}' AND qmo.questionid=q.id" . " AND qqi.question=q.id";
            $table = "{quiz_question_instances} qqi,{question} q, {qtype_multichoice_options} qmo";
            $order = '';
        } else {
            $select = "qtype='multichoice' AND qs.quizid='{$game->quizid}' AND qmo.questionid=q.id" . " AND qs.questionid=q.id";
            $table = "{quiz_slots} qs,{question} q, {qtype_multichoice_options} qmo";
            $order = 'qs.page,qs.slot';
        }
    } else {
        if ($game->questioncategoryid == 0) {
            print_error(get_string('must_select_questioncategory', 'game'));
        }
        // Include subcategories.
        $select = 'category=' . $game->questioncategoryid;
        if ($game->subcategories) {
            $cats = question_categorylist($game->questioncategoryid);
            if (count($cats)) {
                $select = 'q.category in (' . implode(',', $cats) . ')';
            }
        }
        $select .= " AND qtype='multichoice' AND qmo.single=1 AND qmo.questionid=q.id";
        $table = '{question} q, {qtype_multichoice_options} qmo';
    }
    $select .= ' AND hidden=0';
    if ($game->shuffle or $game->quizid == 0) {
        $questionid = game_question_selectrandom($game, $table, $select, 'q.id as id', true);
    } else {
        $questionid = game_millionaire_select_serial_question($game, $table, $select, 'q.id as id', $millionaire->level, $order);
    }
    if ($questionid == 0) {
        print_error(get_string('no_questions', 'game'));
    }
    $q = $DB->get_record('question', array('id' => $questionid), 'id,questiontext');
    $recs = $DB->get_records('question_answers', array('question' => $questionid));
    if ($recs === false) {
        print_error(get_string('no_questions', 'game'));
    }
    $correct = 0;
    $ids = array();
    foreach ($recs as $rec) {
        $aanswer[] = game_filterquestion_answer(str_replace('\\"', '"', $rec->answer), $rec->id, $context->id, $game->course);
        $ids[] = $rec->id;
        if ($rec->fraction == 1) {
            $correct = $rec->id;
        }
    }
    $count = count($aanswer);
    for ($i = 1; $i <= $count; $i++) {
        $sel = mt_rand(0, $count - 1);
        $temp = array_splice($aanswer, $sel, 1);
        $aanswer[] = $temp[0];
        $temp = array_splice($ids, $sel, 1);
        $ids[] = $temp[0];
    }
    $query = new StdClass();
    $query->attemptid = $attempt->id;
    $query->gamekind = $game->gamekind;
    $query->gameid = $game->id;
    $query->userid = $USER->id;
    $query->sourcemodule = $game->sourcemodule;
    $query->glossaryentryid = 0;
    $query->questionid = $questionid;
    $query->questiontext = addslashes($q->questiontext);
    $query->answertext = implode(',', $ids);
    $query->correct = array_search($correct, $ids) + 1;
    if (!($query->id = $DB->insert_record('game_queries', $query))) {
        print_error('error inserting to game_queries');
    }
    $updrec = new StdClass();
    $updrec->id = $millionaire->id;
    $updrec->queryid = $query->id;
    if (!($newid = $DB->update_record('game_millionaire', $updrec))) {
        print_error('error updating in game_millionaire');
    }
    $score = $millionaire->level / 15;
    game_updateattempts($game, $attempt, $score, 0);
    game_update_queries($game, $attempt, $query, $score, '');
}
예제 #18
0
 /**
  * The difference between this method an get_all_responses is that this
  * method is not passed a state object. It is the possible answers to a
  * question no matter what the state.
  * This method is not called for random questions.
  * @return array of possible answers.
  */
 function get_possible_responses(&$question)
 {
     global $QTYPES;
     static $answers = array();
     if (!isset($answers[$question->id])) {
         if ($question->options->subcats) {
             // recurse into subcategories
             $categorylist = question_categorylist($question->category);
         } else {
             $categorylist = $question->category;
         }
         $question->options->subquestions = $this->get_sa_candidates($categorylist);
         foreach ($question->options->subquestions as $key => $wrappedquestion) {
             if (!$QTYPES[$wrappedquestion->qtype]->get_question_options($wrappedquestion)) {
                 return false;
             }
             // Now we overwrite the $question->options->answers field to only
             // *one* (the first) correct answer. This loop can be deleted to
             // take all answers into account (i.e. put them all into the
             // drop-down menu.
             $foundcorrect = false;
             foreach ($wrappedquestion->options->answers as $answer) {
                 if ($foundcorrect || $answer->fraction != 1.0) {
                     unset($wrappedquestion->options->answers[$answer->id]);
                 } else {
                     if (!$foundcorrect) {
                         $foundcorrect = true;
                     }
                 }
             }
         }
         $answers[$question->id] = array();
         if (is_array($question->options->subquestions)) {
             foreach ($question->options->subquestions as $subqid => $answer) {
                 if ($answer->questiontext) {
                     $ans = array_shift($answer->options->answers);
                     $answer->answertext = $ans->answer;
                     $r = new stdClass();
                     $r->answer = $answer->questiontext . ": " . $answer->answertext;
                     $r->credit = 1;
                     $answers[$question->id][$subqid] = array($ans->id => $r);
                 }
             }
         }
     }
     return $answers[$question->id];
 }
예제 #19
0
 /**
  * Get all the usable questions from a particular question category.
  *
  * @param integer $categoryid the id of a question category.
  * @param boolean whether to include questions from subcategories.
  * @param string $questionsinuse comma-separated list of question ids to exclude from consideration.
  * @return array of question records.
  */
 function get_usable_questions_from_category($categoryid, $subcategories, $questionsinuse)
 {
     $this->init_qtype_lists();
     if ($subcategories) {
         $categorylist = question_categorylist($categoryid);
     } else {
         $categorylist = $categoryid;
     }
     if (!($catrandoms = get_records_select('question', "category IN ({$categorylist})\n                     AND parent = 0\n                     AND hidden = 0\n                     AND id NOT IN ({$questionsinuse})\n                     AND qtype NOT IN ({$this->excludedqtypes})", '', 'id'))) {
         $catrandoms = array();
     }
     return $catrandoms;
 }
예제 #20
0
    if (!($toparent = $DB->get_record('question_categories', array('id' => $toparent)))) {
        print_error('invalidcategoryidforparent', 'question', $onerrorurl);
    }
    $contextto = $toparent->contextid;
} else {
    $toparent = new object();
    $toparent->id = 0;
    $toparent->contextid = $contextto;
}
if (!($cattomove = $DB->get_record('question_categories', array('id' => $cattomove)))) {
    print_error('invalidcategoryidtomove', 'question', $onerrorurl);
}
if ($cattomove->contextid == $contextto) {
    print_error('contexterror', '', $onerrorurl);
}
$cattomove->categorylist = question_categorylist($cattomove->id);
$thispageurl->params(array('cattomove' => $cattomove->id, 'toparent' => "{$toparent->id},{$toparent->contextid}", 'totop' => $totop));
$contextfrom = get_context_instance_by_id($cattomove->contextid);
$contextto = get_context_instance_by_id($contextto);
$contexttostring = print_context_name($contextto);
require_capability('moodle/question:managecategory', $contextfrom);
require_capability('moodle/question:managecategory', $contextto);
$fromcoursefilesid = get_filesdir_from_context($contextfrom);
//siteid or courseid
$tocoursefilesid = get_filesdir_from_context($contextto);
//siteid or courseid
if ($fromcoursefilesid != $tocoursefilesid) {
    list($usql, $params) = $DB->get_in_or_equal(explode(',', $cattomove->categorylist));
    $questions = $DB->get_records_select('question', "category {$usql}", $params);
    $urls = array();
    if ($questions) {
function game_millionaire_SelectQuestion(&$aAnswer, $game, $attempt, &$millionaire, &$query)
{
    global $CFG, $USER;
    if ($game->sourcemodule != 'quiz' and $game->sourcemodule != 'question') {
        error(get_string('millionaire_sourcemodule_must_quiz_question', 'game', get_string('modulename', 'quiz')) . ' ' . get_string('modulename', $attempt->sourcemodule));
    }
    if ($millionaire->queryid != 0) {
        game_millionaire_loadquestions($millionaire, $query, $aAnswer);
        return;
    }
    if ($game->sourcemodule == 'quiz') {
        if ($game->quizid == 0) {
            error(get_string('must_select_quiz', 'game'));
        }
        $select = "qtype='multichoice' AND quiz='{$game->quizid}' " . " AND {$CFG->prefix}quiz_question_instances.question={$CFG->prefix}question.id";
        $table = "question,{$CFG->prefix}quiz_question_instances";
    } else {
        if ($game->questioncategoryid == 0) {
            error(get_string('must_select_questioncategory', 'game'));
        }
        //include subcategories
        $select = 'category=' . $game->questioncategoryid;
        if ($game->subcategories) {
            $cats = question_categorylist($game->questioncategoryid);
            if (strpos($cats, ',') > 0) {
                $select = 'category in (' . $cats . ')';
            }
        }
        $select .= " AND qtype='multichoice'";
        $table = "question";
    }
    $select .= " AND {$CFG->prefix}question.hidden=0";
    if ($game->shuffle or $game->quizid == 0) {
        $questionid = game_question_selectrandom($game, $table, $select, "{$CFG->prefix}question.id as id");
    } else {
        $questionid = game_millionaire_select_serial_question($game, $table, $select, "{$CFG->prefix}question.id as id", $millionaire->level);
    }
    if ($questionid == 0) {
        error(get_string('millionaire_nowords', 'game'));
    }
    $q = get_record_select('question', "id={$questionid}", 'id,questiontext');
    $recs = get_records_select('question_answers', "question={$questionid}");
    if ($recs === false) {
        error(get_string('millionaire_no_questions', 'game'));
    }
    $correct = 0;
    $ids = array();
    foreach ($recs as $rec) {
        $aAnswer[] = $rec->answer;
        $ids[] = $rec->id;
        if ($rec->fraction == 1) {
            $correct = $rec->id;
        }
    }
    $count = count($aAnswer);
    for ($i = 1; $i <= $count; $i++) {
        $sel = mt_rand(0, $count - 1);
        $temp = array_splice($aAnswer, $sel, 1);
        $aAnswer[] = $temp[0];
        $temp = array_splice($ids, $sel, 1);
        $ids[] = $temp[0];
    }
    $query = new StdClass();
    $query->attemptid = $attempt->id;
    $query->gamekind = $game->gamekind;
    $query->gameid = $game->id;
    $query->userid = $USER->id;
    $query->sourcemodule = $game->sourcemodule;
    $query->questionid = $questionid;
    $query->questiontext = addslashes($q->questiontext);
    $query->answertext = implode(',', $ids);
    $query->correct = array_search($correct, $ids) + 1;
    if (!($query->id = insert_record('game_queries', $query))) {
        print_object($query);
        error('error inserting to game_queries');
    }
    $updrec->id = $millionaire->id;
    $updrec->queryid = $query->id;
    if (!($newid = update_record('game_millionaire', $updrec))) {
        error('error updating in game_millionaire');
    }
    $score = $millionaire->level / 15;
    game_updateattempts($game, $attempt, $score, 0);
    game_update_queries($game, $attempt, $query, $score, '');
}
예제 #22
0
/**
 * Returns a comma separated list of ids of the category and all subcategories
 */
function question_categorylist($categoryid)
{
    // returns a comma separated list of ids of the category and all subcategories
    $categorylist = $categoryid;
    if ($subcategories = get_records('question_categories', 'parent', $categoryid, 'sortorder ASC', 'id, 1 AS notused')) {
        foreach ($subcategories as $subcategory) {
            $categorylist .= ',' . question_categorylist($subcategory->id);
        }
    }
    return $categorylist;
}
예제 #23
0
파일: editlib.php 프로젝트: verbazend/AWFA
    protected function build_query_sql($category, $recurse, $showhidden) {
        global $DB;

    /// Get the required tables.
        $joins = array();
        foreach ($this->requiredcolumns as $column) {
            $extrajoins = $column->get_extra_joins();
            foreach ($extrajoins as $prefix => $join) {
                if (isset($joins[$prefix]) && $joins[$prefix] != $join) {
                    throw new coding_exception('Join ' . $join . ' conflicts with previous join ' . $joins[$prefix]);
                }
                $joins[$prefix] = $join;
            }
        }

    /// Get the required fields.
        $fields = array('q.hidden', 'q.category');
        foreach ($this->visiblecolumns as $column) {
            $fields = array_merge($fields, $column->get_required_fields());
        }
        foreach ($this->extrarows as $row) {
            $fields = array_merge($fields, $row->get_required_fields());
        }
        $fields = array_unique($fields);

    /// Build the order by clause.
        $sorts = array();
        foreach ($this->sort as $sort => $order) {
            list($colname, $subsort) = $this->parse_subsort($sort);
            $sorts[] = $this->requiredcolumns[$colname]->sort_expression($order < 0, $subsort);
        }

    /// Build the where clause.
        $tests = array('q.parent = 0');

        if (!$showhidden) {
            $tests[] = 'q.hidden = 0';
        }

        if ($recurse) {
            $categoryids = question_categorylist($category->id);
        } else {
            $categoryids = array($category->id);
        }
        list($catidtest, $params) = $DB->get_in_or_equal($categoryids, SQL_PARAMS_NAMED, 'cat');
        $tests[] = 'q.category ' . $catidtest;
        $this->sqlparams = $params;

    /// Build the SQL.
        $sql = ' FROM {question} q ' . implode(' ', $joins);
        $sql .= ' WHERE ' . implode(' AND ', $tests);
        $this->countsql = 'SELECT count(1)' . $sql;
        $this->loadsql = 'SELECT ' . implode(', ', $fields) . $sql . ' ORDER BY ' . implode(', ', $sorts);
        $this->sqlparams = $params;
    }
예제 #24
0
/**
* Prints the table of questions in a category with interactions
*
* @param object $course   The course object
* @param int $categoryid  The id of the question category to be displayed
* @param int $quizid      The quiz id if we are in the context of a particular quiz, 0 otherwise
* @param int $recurse     This is 1 if subcategories should be included, 0 otherwise
* @param int $page        The number of the page to be displayed
* @param int $perpage     Number of questions to show per page
* @param boolean $showhidden   True if also hidden questions should be displayed
* @param boolean $showquestiontext whether the text of each question should be shown in the list
*/
function question_list($course, $categoryid, $quizid = 0, $recurse = 1, $page = 0, $perpage = 100, $showhidden = false, $sortorder = 'qtype, name ASC', $showquestiontext = false)
{
    global $USER, $CFG, $THEME;
    $qtypemenu = question_type_menu();
    if ($rqp_types = get_records('question_rqp_types')) {
        foreach ($rqp_types as $type) {
            $qtypemenu['rqp_' . $type->id] = $type->name;
        }
    }
    $strcategory = get_string("category", "quiz");
    $strquestion = get_string("question", "quiz");
    $straddquestions = get_string("addquestions", "quiz");
    $strimportquestions = get_string("importquestions", "quiz");
    $strexportquestions = get_string("exportquestions", "quiz");
    $strnoquestions = get_string("noquestions", "quiz");
    $strselect = get_string("select", "quiz");
    $strselectall = get_string("selectall", "quiz");
    $strselectnone = get_string("selectnone", "quiz");
    $strcreatenewquestion = get_string("createnewquestion", "quiz");
    $strquestionname = get_string("questionname", "quiz");
    $strdelete = get_string("delete");
    $stredit = get_string("edit");
    $straction = get_string("action");
    $strrestore = get_string('restore');
    $straddtoquiz = get_string("addtoquiz", "quiz");
    $strtype = get_string("type", "quiz");
    $strcreatemultiple = get_string("createmultiple", "quiz");
    $strpreview = get_string("preview", "quiz");
    if (!$categoryid) {
        echo "<p style=\"text-align:center;\"><b>";
        print_string("selectcategoryabove", "quiz");
        echo "</b></p>";
        if ($quizid) {
            echo "<p>";
            print_string("addingquestions", "quiz");
            echo "</p>";
        }
        return;
    }
    if (!($category = get_record('question_categories', 'id', $categoryid))) {
        notify('Category not found!');
        return;
    }
    $canedit = has_capability('moodle/question:manage', get_context_instance(CONTEXT_COURSE, $category->course));
    $editingquiz = false;
    if ($quizid) {
        $cm = get_coursemodule_from_instance('quiz', $quizid);
        $editingquiz = has_capability('mod/quiz:manage', get_context_instance(CONTEXT_MODULE, $cm->id));
    }
    echo '<div class="boxaligncenter">';
    $formatoptions = new stdClass();
    $formatoptions->noclean = true;
    echo format_text($category->info, FORMAT_MOODLE, $formatoptions, $course->id);
    echo '<table><tr>';
    // check if editing questions in this category is allowed
    if ($canedit) {
        echo "<td valign=\"top\"><b>{$strcreatenewquestion}:</b></td>";
        echo '<td valign="top" align="right">';
        popup_form("{$CFG->wwwroot}/question/question.php?category={$category->id}&amp;qtype=", $qtypemenu, "addquestion", "", "choose", "", "", false, "self");
        echo '</td><td valign="top" align="right">';
        helpbutton("questiontypes", $strcreatenewquestion, "quiz");
        echo '</td>';
    } else {
        echo '<td>';
        print_string("publishedit", "quiz");
        echo '</td>';
    }
    echo '</tr></table>';
    echo '</div>';
    $categorylist = $recurse ? question_categorylist($category->id) : $category->id;
    // hide-feature
    $showhidden = $showhidden ? '' : " AND hidden = '0'";
    if (!($totalnumber = count_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}"))) {
        echo "<p style=\"text-align:center;\">";
        print_string("noquestions", "quiz");
        echo "</p>";
        return;
    }
    if (!($questions = get_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}", $sortorder, '*', $page * $perpage, $perpage))) {
        // There are no questions on the requested page.
        $page = 0;
        if (!($questions = get_records_select('question', "category IN ({$categorylist}) AND parent = '0' {$showhidden}", $sortorder, '*', 0, $perpage))) {
            // There are no questions at all
            echo "<p style=\"text-align:center;\">";
            print_string("noquestions", "quiz");
            echo "</p>";
            return;
        }
    }
    print_paging_bar($totalnumber, $page, $perpage, "edit.php?courseid={$course->id}&amp;perpage={$perpage}&amp;");
    echo '<form method="post" action="edit.php?courseid=' . $course->id . '">';
    echo '<fieldset class="invisiblefieldset" style="display: block;">';
    echo '<input type="hidden" name="sesskey" value="' . $USER->sesskey . '" />';
    echo '<table id="categoryquestions" style="width: 100%"><tr>';
    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$straction}</th>";
    $sortoptions = array('name, qtype ASC' => get_string("sortalpha", "quiz"), 'qtype, name ASC' => get_string("sorttypealpha", "quiz"), 'id ASC' => get_string("sortage", "quiz"));
    $orderselect = choose_from_menu($sortoptions, 'sortorder', $sortorder, false, 'this.form.submit();', '0', true);
    $orderselect .= '<noscript><div><input type="submit" value="' . get_string("sortsubmit", "quiz") . '" /></div></noscript>';
    echo "<th style=\"white-space:nowrap; text-align: left;\" class=\"header\" scope=\"col\">{$strquestionname} {$orderselect}</th>\n    <th style=\"white-space:nowrap; text-align: right;\" class=\"header\" scope=\"col\">{$strtype}</th>";
    echo "</tr>\n";
    foreach ($questions as $question) {
        $nameclass = '';
        $textclass = '';
        if ($question->hidden) {
            $nameclass = 'dimmed_text';
            $textclass = 'dimmed_text';
        }
        if ($showquestiontext) {
            $nameclass .= ' header';
        }
        if ($nameclass) {
            $nameclass = 'class="' . $nameclass . '"';
        }
        if ($textclass) {
            $textclass = 'class="' . $textclass . '"';
        }
        echo "<tr>\n<td style=\"white-space:nowrap;\" {$nameclass}>\n";
        // add to quiz
        if ($editingquiz) {
            echo "<a title=\"{$straddtoquiz}\" href=\"edit.php?addquestion={$question->id}&amp;quizid={$quizid}&amp;sesskey={$USER->sesskey}\"><img\n                  src=\"{$CFG->pixpath}/t/moveleft.gif\" alt=\"{$straddtoquiz}\" /></a>&nbsp;";
        }
        // preview
        link_to_popup_window('/question/preview.php?id=' . $question->id . '&amp;quizid=' . $quizid, 'questionpreview', "<img src=\"{$CFG->pixpath}/t/preview.gif\" class=\"iconsmall\" alt=\"{$strpreview}\" />", 0, 0, $strpreview, QUESTION_PREVIEW_POPUP_OPTIONS);
        // edit, hide, delete question, using question capabilities, not quiz capabilieies
        if ($canedit) {
            echo "<a title=\"{$stredit}\" href=\"{$CFG->wwwroot}/question/question.php?id={$question->id}\"><img\n                    src=\"{$CFG->pixpath}/t/edit.gif\" alt=\"{$stredit}\" /></a>&nbsp;";
            // hide-feature
            if ($question->hidden) {
                echo "<a title=\"{$strrestore}\" href=\"edit.php?courseid={$course->id}&amp;unhide={$question->id}&amp;sesskey={$USER->sesskey}\"><img\n                        src=\"{$CFG->pixpath}/t/restore.gif\" alt=\"{$strrestore}\" /></a>";
            } else {
                echo "<a title=\"{$strdelete}\" href=\"edit.php?courseid={$course->id}&amp;deleteselected={$question->id}&amp;q{$question->id}=1\"><img\n                        src=\"{$CFG->pixpath}/t/delete.gif\" alt=\"{$strdelete}\" /></a>";
            }
        }
        echo "&nbsp;<input title=\"{$strselect}\" type=\"checkbox\" name=\"q{$question->id}\" value=\"1\" />";
        echo "</td>\n";
        echo "<td {$nameclass}>" . format_string($question->name) . "</td>\n";
        echo "<td {$nameclass} style='text-align: right'>\n";
        print_question_icon($question);
        echo "</td>\n";
        echo "</tr>\n";
        if ($showquestiontext) {
            echo '<tr><td colspan="3" ' . $textclass . '>';
            $formatoptions = new stdClass();
            $formatoptions->noclean = true;
            $formatoptions->para = false;
            echo format_text($question->questiontext, $question->questiontextformat, $formatoptions, $course->id);
            echo "</td></tr>\n";
        }
    }
    echo "</table>\n";
    $paging = print_paging_bar($totalnumber, $page, $perpage, "edit.php?courseid={$course->id}&amp;perpage={$perpage}&amp;", 'page', false, true);
    if ($totalnumber > DEFAULT_QUESTIONS_PER_PAGE) {
        if ($perpage == DEFAULT_QUESTIONS_PER_PAGE) {
            $showall = '<a href="edit.php?courseid=' . $course->id . '&amp;perpage=1000">' . get_string('showall', 'moodle', $totalnumber) . '</a>';
        } else {
            $showall = '<a href="edit.php?courseid=' . $course->id . '&amp;perpage=' . DEFAULT_QUESTIONS_PER_PAGE . '">' . get_string('showperpage', 'moodle', DEFAULT_QUESTIONS_PER_PAGE) . '</a>';
        }
        if ($paging) {
            $paging = substr($paging, 0, strrpos($paging, '</div>'));
            $paging .= "<br />{$showall}</div>";
        } else {
            $paging = "<div class='paging'>{$showall}</div>";
        }
    }
    echo $paging;
    echo '<table class="quiz-edit-selected"><tr><td colspan="2">';
    echo '<a href="javascript:select_all_in(\'TABLE\',null,\'categoryquestions\');">' . $strselectall . '</a> /' . ' <a href="javascript:deselect_all_in(\'TABLE\',null,\'categoryquestions\');">' . $strselectnone . '</a>' . '</td><td align="right"><b>&nbsp;' . get_string('withselected', 'quiz') . ':</b></td></tr><tr><td>';
    if ($editingquiz) {
        echo "<input type=\"submit\" name=\"add\" value=\"{$THEME->larrow} {$straddtoquiz}\" />\n";
        echo '</td><td>';
    }
    // print delete and move selected question
    if ($canedit) {
        echo '<input type="submit" name="deleteselected" value="' . $strdelete . "\" /></td><td>\n";
        echo '<input type="submit" name="move" value="' . get_string('moveto', 'quiz') . "\" />\n";
        question_category_select_menu($course->id, false, true, $category->id);
    }
    echo "</td></tr></table>";
    // add random question
    if ($editingquiz) {
        for ($i = 1; $i <= min(10, $totalnumber); $i++) {
            $randomcount[$i] = $i;
        }
        for ($i = 20; $i <= min(100, $totalnumber); $i += 10) {
            $randomcount[$i] = $i;
        }
        echo '<br />';
        print_string('addrandom', 'quiz', choose_from_menu($randomcount, 'randomcount', '1', '', '', '', true));
        echo '<input type="hidden" name="recurse" value="' . $recurse . '" />';
        echo "<input type=\"hidden\" name=\"categoryid\" value=\"{$category->id}\" />";
        echo ' <input type="submit" name="addrandom" value="' . get_string('add') . '" />';
        helpbutton('random', get_string('random', 'quiz'), 'quiz');
    }
    echo '</fieldset>';
    echo "</form>\n";
}
예제 #25
0
 public function create_session_and_responses(&$question, &$state, $cmoptions, $attempt)
 {
     // Choose a random shortanswer question from the category:
     // We need to make sure that no question is used more than once in the
     // quiz. Therfore the following need to be excluded:
     // 1. All questions that are explicitly assigned to the quiz
     // 2. All random questions
     // 3. All questions that are already chosen by an other random question.
     global $QTYPES, $OUTPUT, $USER;
     if (!isset($cmoptions->questionsinuse)) {
         $cmoptions->questionsinuse = $cmoptions->questions;
     }
     if ($question->options->subcats) {
         // Recurse into subcategories.
         $categorylist = question_categorylist($question->category);
     } else {
         $categorylist = array($question->category);
     }
     $saquestions = $this->get_sa_candidates($categorylist, $cmoptions->questionsinuse);
     $count = count($saquestions);
     $wanted = $question->options->choose;
     if ($count < $wanted) {
         $question->questiontext = "Insufficient selection options are\n                available for this question, therefore it is not available in  this\n                quiz. Please inform your teacher.";
         // Treat this as a description from this point on.
         $question->qtype = 'description';
         return true;
     }
     $saquestions = draw_rand_array($saquestions, $question->options->choose);
     // From bug 1889.
     foreach ($saquestions as $key => $wrappedquestion) {
         if (!$QTYPES[$wrappedquestion->qtype]->get_question_options($wrappedquestion)) {
             return false;
         }
         // Now we overwrite the $question->options->answers field to only
         // *one* (the first) correct answer. This loop can be deleted to
         // take all answers into account (i.e. put them all into the
         // drop-down menu.
         $foundcorrect = false;
         foreach ($wrappedquestion->options->answers as $answer) {
             if ($foundcorrect || $answer->fraction != 1.0) {
                 unset($wrappedquestion->options->answers[$answer->id]);
             } else {
                 if (!$foundcorrect) {
                     $foundcorrect = true;
                 }
             }
         }
         if (!$QTYPES[$wrappedquestion->qtype]->create_session_and_responses($wrappedquestion, $state, $cmoptions, $attempt)) {
             return false;
         }
         $wrappedquestion->name_prefix = $question->name_prefix;
         $wrappedquestion->maxgrade = $question->maxgrade;
         $cmoptions->questionsinuse .= ",{$wrappedquestion->id}";
         $state->options->subquestions[$key] = clone $wrappedquestion;
     }
     // Shuffle the answers (Do this always because this is a random question type).
     $subquestionids = array_values(array_map(create_function('$val', 'return $val->id;'), $state->options->subquestions));
     $subquestionids = swapshuffle($subquestionids);
     // Create empty responses.
     foreach ($subquestionids as $val) {
         $state->responses[$val] = '';
     }
     return true;
 }
예제 #26
0
    /**
     * Get all the usable questions from a particular question category.
     *
     * @param int $categoryid the id of a question category.
     * @param bool whether to include questions from subcategories.
     * @param string $questionsinuse comma-separated list of question ids to
     *      exclude from consideration.
     * @return array of question records.
     */
    public function get_available_questions_from_category($categoryid, $subcategories) {
        if (isset($this->availablequestionsbycategory[$categoryid][$subcategories])) {
            return $this->availablequestionsbycategory[$categoryid][$subcategories];
        }

        $this->init_qtype_lists();
        if ($subcategories) {
            $categoryids = question_categorylist($categoryid);
        } else {
            $categoryids = array($categoryid);
        }

        $questionids = question_bank::get_finder()->get_questions_from_categories(
                $categoryids, 'qtype NOT IN (' . $this->excludedqtypes . ')');
        $this->availablequestionsbycategory[$categoryid][$subcategories] = $questionids;
        return $questionids;
    }
예제 #27
0
 /**
  * Populate {@link $availablequestionscache} for this combination of options.
  * @param int $categoryid the id of a category in the question bank.
  * @param bool $includesubcategories wether to pick a question from exactly
  *      that category, or that category and subcategories.
  */
 protected function ensure_questions_for_category_loaded($categoryid, $includesubcategories)
 {
     global $DB;
     $categorykey = $this->get_category_key($categoryid, $includesubcategories);
     if (isset($this->availablequestionscache[$categorykey])) {
         // Data is already in the cache, nothing to do.
         return;
     }
     // Load the available questions from the question bank.
     if ($includesubcategories) {
         $categoryids = question_categorylist($categoryid);
     } else {
         $categoryids = array($categoryid);
     }
     list($extraconditions, $extraparams) = $DB->get_in_or_equal($this->excludedqtypes, SQL_PARAMS_NAMED, 'excludedqtype', false);
     $questionidsandcounts = \question_bank::get_finder()->get_questions_from_categories_with_usage_counts($categoryids, $this->qubaids, 'q.qtype ' . $extraconditions, $extraparams);
     if (!$questionidsandcounts) {
         // No questions in this category.
         $this->availablequestionscache[$categorykey] = array();
         return;
     }
     // Put all the questions with each value of $prevusecount in separate arrays.
     $idsbyusecount = array();
     foreach ($questionidsandcounts as $questionid => $prevusecount) {
         if (isset($this->recentlyusedquestions[$questionid])) {
             // Recently used questions are never returned.
             continue;
         }
         $idsbyusecount[$prevusecount][] = $questionid;
     }
     // Now put that data into our cache. For each count, we need to shuffle
     // questionids, and make those the keys of an array.
     $this->availablequestionscache[$categorykey] = array();
     foreach ($idsbyusecount as $prevusecount => $questionids) {
         shuffle($questionids);
         $this->availablequestionscache[$categorykey][$prevusecount] = array_combine($questionids, array_fill(0, count($questionids), 1));
     }
     ksort($this->availablequestionscache[$categorykey]);
 }