protected function display_content($question, $rowclasses)
 {
     if (!question_has_capability_on($question, 'use')) {
         return;
     }
     $this->print_icon('t/add', $this->stradd, $this->qbank->add_to_rtq_url($question->id));
 }
Example #2
0
 protected function display_content($question, $rowclasses)
 {
     global $PAGE;
     if (question_has_capability_on($question, 'use')) {
         echo $PAGE->get_renderer('core_question')->question_preview_link($question->id, $this->qbank->get_most_specific_context(), false);
     }
 }
Example #3
0
 function print_question(&$question, &$state, $number, $cmoptions, $options)
 {
     global $CFG;
     $isfinished = question_state_is_graded($state->last_graded) || $state->event == QUESTION_EVENTCLOSE;
     if (!empty($cmoptions->id)) {
         $cm = get_coursemodule_from_instance('quiz', $cmoptions->id);
         $cmorcourseid = '&cmid=' . $cm->id;
     } else {
         if (!empty($cmoptions->course)) {
             $cmorcourseid = '&courseid=' . $cmoptions->course;
         } else {
             error('Need to provide courseid or cmid to print_question.');
         }
     }
     // For editing teachers print a link to an editing popup window
     $editlink = '';
     if (question_has_capability_on($question, 'edit')) {
         $stredit = get_string('edit');
         $linktext = '<img src="' . $CFG->pixpath . '/t/edit.gif" alt="' . $stredit . '" />';
         $editlink = link_to_popup_window('/question/question.php?id=' . $question->id . $cmorcourseid, $stredit, $linktext, 450, 550, $stredit, '', true);
     }
     $questiontext = $this->format_text($question->questiontext, $question->questiontextformat, $cmoptions);
     $image = get_question_image($question);
     $generalfeedback = '';
     if ($isfinished && $options->generalfeedback) {
         $generalfeedback = $this->format_text($question->generalfeedback, $question->questiontextformat, $cmoptions);
     }
     include "{$CFG->dirroot}/question/type/description/question.html";
 }
Example #4
0
/**
 * Called via pluginfile.php -> question_pluginfile to serve files belonging to
 * a question in a question_attempt when that attempt is a preview.
 *
 * @param object $course course settings object
 * @param object $context context object
 * @param string $component the name of the component we are serving files for.
 * @param string $filearea the name of the file area.
 * @param array $args the remaining bits of the file path.
 * @param bool $forcedownload whether the user must be forced to download the file.
 * @return bool false if file not found, does not return if found - justsend the file
 */
function question_preview_question_pluginfile($course, $context, $component, $filearea, $attemptid, $questionid, $args, $forcedownload)
{
    global $USER, $SESSION, $DB, $CFG;
    require_once $CFG->dirroot . '/mod/quiz/locallib.php';
    if (!($question = $DB->get_record('question', array('id' => $questionid)))) {
        return send_file_not_found();
    }
    if (!question_has_capability_on($question, 'use', $question->category)) {
        send_file_not_found();
    }
    if (!isset($SESSION->quizpreview->states) || $SESSION->quizpreview->questionid != $questionid) {
        send_file_not_found();
    }
    $states = end($SESSION->quizpreview->states);
    if (!array_key_exists($question->id, $states)) {
        send_file_not_found();
    }
    $state = $states[$question->id];
    // Build fake cmoptions
    $quiz = new cmoptions();
    $quiz->id = 0;
    $quiz->review = get_config('quiz', 'review');
    if (empty($course->id)) {
        $quiz->course = SITEID;
    } else {
        $quiz->course = $course->id;
    }
    $quiz->decimalpoints = get_config('quiz', 'decimalpoints');
    $questions[$question->id] = $question;
    get_question_options($questions);
    // Build fake attempt
    $timenow = time();
    $attempt = new stdClass();
    $attempt->quiz = $quiz->id;
    $attempt->userid = $USER->id;
    $attempt->attempt = 0;
    $attempt->sumgrades = 0;
    $attempt->timestart = $timenow;
    $attempt->timefinish = 0;
    $attempt->timemodified = $timenow;
    $attempt->uniqueid = 0;
    $attempt->id = 0;
    $attempt->layout = $question->id;
    $options = quiz_get_renderoptions($quiz, $attempt, $context, $state);
    $options->noeditlink = true;
    // XXX: mulitichoice type needs quiz id to get maxgrade
    $options->quizid = 0;
    if (!question_check_file_access($question, $state, $options, $context->id, $component, $filearea, $args, $forcedownload)) {
        send_file_not_found();
    }
    $fs = get_file_storage();
    $relativepath = implode('/', $args);
    $fullpath = "/{$context->id}/{$component}/{$filearea}/{$relativepath}";
    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
        send_file_not_found();
    }
    send_stored_file($file, 0, 0, $forcedownload);
}
Example #5
0
 protected function display_content($question, $rowclasses)
 {
     // To copy a question, you need permission to add a question in the same
     // category as the existing question, and ability to access the details of
     // the question being copied.
     if (question_has_capability_on($question, 'add') && (question_has_capability_on($question, 'edit') || question_has_capability_on($question, 'view'))) {
         $this->print_icon('t/copy', $this->strcopy, $this->qbank->copy_question_url($question->id));
     }
 }
Example #6
0
 protected function display_content($question, $rowclasses)
 {
     if (question_has_capability_on($question, 'edit')) {
         $this->print_icon('t/edit', $this->stredit, $this->qbank->edit_question_url($question->id));
     } else {
         if (question_has_capability_on($question, 'view')) {
             $this->print_icon('i/info', $this->strview, $this->qbank->edit_question_url($question->id));
         }
     }
 }
Example #7
0
 function drop_questions($a)
 {
     global $DB;
     // First sanity check the existance of the context. there may be deleted contexts and some question wreck inside.
     $contextid = $DB->get_field('question_categories', 'contextid', array('id' => $a->category));
     if (!$DB->record_exists('context', array('id' => $contextid))) {
         return false;
     }
     return question_has_capability_on($a->id, 'use');
 }
 protected function display_content($question, $rowclasses)
 {
     if (!question_has_capability_on($question, 'use')) {
         return;
     }
     $disabled = false;
     if ($this->qbank->offlinequiz_contains($question->id)) {
         $disabled = true;
     }
     $this->print_icon('t/add', $this->stradd, $this->qbank->add_to_offlinequiz_url($question->id), $disabled);
 }
Example #9
0
 protected function display_content($question, $rowclasses)
 {
     if (question_has_capability_on($question, 'edit')) {
         if ($question->hidden) {
             $url = new \moodle_url($this->qbank->base_url(), array('unhide' => $question->id, 'sesskey' => sesskey()));
             $this->print_icon('t/restore', $this->strrestore, $url);
         } else {
             $url = new \moodle_url($this->qbank->base_url(), array('deleteselected' => $question->id, 'q' . $question->id => 1, 'sesskey' => sesskey()));
             $this->print_icon('t/delete', $this->strdelete, $url);
         }
     }
 }
Example #10
0
$categorycontext = get_context_instance_by_id($category->contextid);
$addpermission = has_capability('moodle/question:add', $categorycontext);
if ($id) {
    $canview = question_has_capability_on($question, 'view');
    if ($movecontext) {
        $question->formoptions->canedit = false;
        $question->formoptions->canmove = question_has_capability_on($question, 'move') && $contexts->have_cap('moodle/question:add');
        $question->formoptions->cansaveasnew = false;
        $question->formoptions->repeatelements = false;
        $question->formoptions->movecontext = true;
        $formeditable = true;
        question_require_capability_on($question, 'view');
    } else {
        $question->formoptions->canedit = question_has_capability_on($question, 'edit');
        $question->formoptions->canmove = question_has_capability_on($question, 'move') && $addpermission;
        $question->formoptions->cansaveasnew = ($canview || question_has_capability_on($question, 'edit')) && $addpermission;
        $question->formoptions->repeatelements = $question->formoptions->canedit || $question->formoptions->cansaveasnew;
        $formeditable = $question->formoptions->canedit || $question->formoptions->cansaveasnew || $question->formoptions->canmove;
        $question->formoptions->movecontext = false;
        if (!$formeditable) {
            question_require_capability_on($question, 'view');
        }
    }
} else {
    // creating a new question
    require_capability('moodle/question:add', $categorycontext);
    $formeditable = true;
    $question->formoptions->repeatelements = true;
    $question->formoptions->movecontext = false;
}
// Validate the question type.
Example #11
0
 /**
  * Get a link to an edit icon for this question, if the current user is allowed
  * to edit it.
  *
  * @param object $question the question object.
  * @param object $cmoptions the options from the module. If $cmoptions->thispageurl is set
  *      then the link will be to edit the question in this browser window, then return to
  *      $cmoptions->thispageurl. Otherwise the link will be to edit in a popup. $cmoptions->cmid should also be set.
  * @return string the HTML of the link, or nothing it the currenty user is not allowed to edit.
  */
 function get_question_edit_link($question, $cmoptions, $options)
 {
     global $CFG;
     /// Is this user allowed to edit this question?
     if (!empty($options->noeditlink) || !question_has_capability_on($question, 'edit')) {
         return '';
     }
     /// Work out the right URL.
     $linkurl = '/question/question.php?id=' . $question->id;
     if (!empty($cmoptions->cmid)) {
         $linkurl .= '&amp;cmid=' . $cmoptions->cmid;
     } else {
         if (!empty($cmoptions->course)) {
             $linkurl .= '&amp;courseid=' . $cmoptions->course;
         } else {
             error('Need to provide courseid or cmid to get_question_edit_link.');
         }
     }
     /// Work out the contents of the link.
     $stredit = get_string('edit');
     $linktext = '<img src="' . $CFG->pixpath . '/t/edit.gif" alt="' . $stredit . '" />';
     if (!empty($cmoptions->thispageurl)) {
         /// The module allow editing in the same window, print an ordinary link.
         return '<a href="' . $CFG->wwwroot . $linkurl . '&amp;returnurl=' . urlencode($cmoptions->thispageurl) . '" title="' . $stredit . '">' . $linktext . '</a>';
     } else {
         /// We have to edit in a pop-up.
         return link_to_popup_window($linkurl . '&amp;inpopup=1', 'editquestion', $linktext, false, false, $stredit, '', true);
     }
 }
Example #12
0
/**
 * Require capability on question.
 */
function question_require_capability_on($question, $cap)
{
    if (!question_has_capability_on($question, $cap)) {
        print_error('nopermissions', '', '', $cap);
    }
    return true;
}
Example #13
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";
}
Example #14
0
/**
 * @param object $quiz the quiz settings
 * @param object $question the question
 * @param bool $label if true, show the preview question label after the icon
 * @return the HTML for a preview question icon.
 */
function quiz_question_preview_button($quiz, $question, $label = false) {
    global $CFG, $OUTPUT;
    if (!question_has_capability_on($question, 'use', $question->category)) {
        return '';
    }

    $url = quiz_question_preview_url($quiz, $question);

    // Do we want a label?
    $strpreviewlabel = '';
    if ($label) {
        $strpreviewlabel = get_string('preview', 'quiz');
    }

    // Build the icon.
    $strpreviewquestion = get_string('previewquestion', 'quiz');
    $image = $OUTPUT->pix_icon('t/preview', $strpreviewquestion);

    $action = new popup_action('click', $url, 'questionpreview',
            question_preview_popup_params());

    return $OUTPUT->action_link($url, $image, $action, array('title' => $strpreviewquestion));
}
Example #15
0
/**
 * Prints a list of quiz questions for the edit.php main view for edit
 * ($reordertool = false) and order and paging ($reordertool = true) tabs
 *
 * @return int sum of maximum grades
 * @param object $quiz This is not the standard quiz object used elsewhere but
 *     it contains the quiz layout in $quiz->questions and the grades in
 *     $quiz->grades
 * @param object $pageurl The url of the current page with the parameters required
 *     for links returning to the current page, as a moodle_url object
 * @param boolean $allowdelete Indicates whether the delete icons should be displayed
 * @param boolean $reordertool  Indicates whether the reorder tool should be displayed
 * @param boolean $quiz_qbanktool  Indicates whether the question bank should be displayed
 * @param boolean $hasattempts  Indicates whether the quiz has attempts
 */
function quiz_print_question_list($quiz, $pageurl, $allowdelete = true, $reordertool = false, $quiz_qbanktool = false, $hasattempts = false)
{
    global $USER, $CFG, $QTYPES, $DB;
    $strorder = get_string('order');
    $strquestionname = get_string('questionname', 'quiz');
    $strgrade = get_string('grade');
    $strremove = get_string('remove', 'quiz');
    $stredit = get_string('edit');
    $strview = get_string('view');
    $straction = get_string('action');
    $strmove = get_string('move');
    $strmoveup = get_string('moveup');
    $strmovedown = get_string('movedown');
    $strsave = get_string('save', 'quiz');
    $strreorderquestions = get_string('reorderquestions', 'quiz');
    $strselectall = get_string('selectall', 'quiz');
    $strselectnone = get_string('selectnone', 'quiz');
    $strtype = get_string('type', 'quiz');
    $strpreview = get_string('preview', 'quiz');
    if ($quiz->questions) {
        list($usql, $params) = $DB->get_in_or_equal(explode(',', $quiz->questions));
        $questions = $DB->get_records_sql("SELECT q.*,c.contextid\n                              FROM {question} q,\n                                   {question_categories} c\n                             WHERE q.id {$usql}\n                               AND q.category = c.id", $params);
    } else {
        $questions = array();
    }
    $layout = quiz_clean_layout($quiz->questions);
    $order = explode(',', $layout);
    $lastindex = count($order) - 1;
    $disabled = '';
    $pagingdisabled = '';
    if ($hasattempts) {
        $disabled = 'disabled="disabled"';
    }
    if ($hasattempts || $quiz->shufflequestions) {
        $pagingdisabled = 'disabled="disabled"';
    }
    $reordercontrolssetdefaultsubmit = '<div style="display:none;">' . '<input type="submit" name="savechanges" value="' . $strreorderquestions . '" ' . $pagingdisabled . ' /></div>';
    $reordercontrols1 = '<div class="addnewpagesafterselected">' . '<input type="submit" name="addnewpagesafterselected" value="' . get_string('addnewpagesafterselected', 'quiz') . '"  ' . $pagingdisabled . ' /></div>';
    $reordercontrols1 .= '<div class="quizdeleteselected">' . '<input type="submit" name="quizdeleteselected" ' . 'onclick="return confirm(\'' . get_string('areyousureremoveselected', 'quiz') . '\');" value="' . get_string('removeselected', 'quiz') . '"  ' . $disabled . ' /></div>';
    $a = '<input name="moveselectedonpagetop" type="text" size="2" ' . $pagingdisabled . ' />';
    $reordercontrols2top = '<div class="moveselectedonpage">' . get_string('moveselectedonpage', 'quiz', $a) . '<input type="submit" name="savechanges" value="' . $strmove . '"  ' . $pagingdisabled . ' />' . '
        <br /><input type="submit" name="savechanges" value="' . $strreorderquestions . '" /></div>';
    $reordercontrols2bottom = '<div class="moveselectedonpage">' . '<input type="submit" name="savechanges" value="' . $strreorderquestions . '" /><br />' . get_string('moveselectedonpage', 'quiz', $a) . '<input type="submit" name="savechanges" value="' . $strmove . '"  ' . $pagingdisabled . ' /> ' . '</div>';
    $reordercontrols3 = '<a href="javascript:select_all_in(\'FORM\', null, ' . '\'quizquestions\');">' . $strselectall . '</a> /';
    $reordercontrols3 .= ' <a href="javascript:deselect_all_in(\'FORM\', ' . 'null, \'quizquestions\');">' . $strselectnone . '</a>';
    $reordercontrolstop = '<div class="reordercontrols">' . $reordercontrolssetdefaultsubmit . $reordercontrols1 . $reordercontrols2top . $reordercontrols3 . "</div>";
    $reordercontrolsbottom = '<div class="reordercontrols">' . $reordercontrolssetdefaultsubmit . $reordercontrols2bottom . $reordercontrols1 . $reordercontrols3 . "</div>";
    if ($reordertool) {
        echo '<form method="post" action="edit.php" id="quizquestions"><div>';
        echo $pageurl->hidden_params_out();
        echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
        echo $reordercontrolstop;
    }
    //the current question ordinal (no descriptions)
    $qno = 1;
    //the current question (includes questions and descriptions)
    $questioncount = 0;
    //the ordinal of current element in the layout
    //(includes page breaks, questions and descriptions)
    $count = 0;
    //the current page number in iteration
    $pagecount = 0;
    $sumgrade = 0;
    $pageopen = false;
    $returnurl = $pageurl->out();
    $questiontotalcount = count($order);
    foreach ($order as $i => $qnum) {
        $reordercheckbox = '';
        $reordercheckboxlabel = '';
        $reordercheckboxlabelclose = '';
        if ($qnum && empty($questions[$qnum])) {
            continue;
        }
        // If the questiontype is missing change the question type
        if ($qnum && !array_key_exists($questions[$qnum]->qtype, $QTYPES)) {
            $questions[$qnum]->qtype = 'missingtype';
        }
        $deletex = "delete.gif";
        if ($qnum != 0 || $qnum == 0 && !$pageopen) {
            //this is either a question or a page break after another
            //        (no page is currently open)
            if (!$pageopen) {
                //if no page is open, start display of a page
                $pagecount++;
                echo '<div class="quizpage"><span class="pagetitle">' . get_string('page') . '&nbsp;' . $pagecount . '</span><div class="pagecontent">';
                $pageopen = true;
            }
            if ($qnum == 0 && $i < $questiontotalcount) {
                // This is the second successive page break. Tell the user the page is empty.
                echo '<div class="pagestatus">';
                print_string('noquestionsonpage', 'quiz');
                echo '</div>';
                if ($allowdelete && !$quiz->questionsperpage) {
                    echo '<div class="quizpagedelete">';
                    echo '<a title="' . get_string('removeemptypage', 'quiz') . '" href="' . $pageurl->out_action(array('deleteemptypage' => $i - 1)) . '"><img src="' . $CFG->pixpath . '/t/delete.gif" ' . 'class="iconsmall" alt="' . $strremove . '" /></a>';
                    echo '</div>';
                }
            }
            if ($qnum != 0) {
                $question = $questions[$qnum];
                $questionparams = array('returnurl' => $returnurl, 'cmid' => $quiz->cmid, 'id' => $question->id);
                $questionurl = new moodle_url("{$CFG->wwwroot}/question/question.php", $questionparams);
                $questioncount++;
                //this is an actual question
                /* Display question start */
                ?>
<div class="question">
    <div class="questioncontainer <?php 
                echo $question->qtype;
                ?>
">
        <div class="qnum">
        <?php 
                $reordercheckbox = '';
                $reordercheckboxlabel = '';
                $reordercheckboxlabelclose = '';
                if ($reordertool) {
                    $reordercheckbox = '<input type="checkbox" name="s' . $question->id . '" id="s' . $question->id . '" />';
                    $reordercheckboxlabel = '<label for="s' . $question->id . '">';
                    $reordercheckboxlabelclose = '</label>';
                }
                if (!$quiz->shufflequestions) {
                    // Print and increment question number
                    $questioncountstring = '';
                    if ($questioncount > 999 || $reordertool && $questioncount > 99) {
                        $questioncountstring = "{$reordercheckboxlabel}<small>{$questioncount}</small>" . $reordercheckboxlabelclose . $reordercheckbox;
                    } else {
                        $questioncountstring = $reordercheckboxlabel . $questioncount . $reordercheckboxlabelclose . $reordercheckbox;
                    }
                    echo $questioncountstring;
                    $qno += $question->length;
                } else {
                    echo "{$reordercheckboxlabel} ? {$reordercheckboxlabelclose}" . " {$reordercheckbox}";
                }
                ?>
        </div>
        <div class="content">
            <div class="questioncontrols">
                <?php 
                if ($count != 0) {
                    if (!$hasattempts) {
                        $upbuttonclass = '';
                        if ($count >= $lastindex - 1) {
                            $upbuttonclass = 'upwithoutdown';
                        }
                        echo "<a title=\"{$strmoveup}\" href=\"" . $pageurl->out_action(array('up' => $question->id)) . "\"><img\n                             src=\"{$CFG->pixpath}/t/up.gif\" class=\"iconsmall\n                            {$upbuttonclass}\" alt=\"{$strmoveup}\" /></a>";
                    }
                }
                if ($count < $lastindex - 1) {
                    if (!$hasattempts) {
                        echo "<a title=\"{$strmovedown}\" href=\"" . $pageurl->out_action(array('down' => $question->id)) . "\"><img\n                            src=\"{$CFG->pixpath}/t/down.gif\" class=\"iconsmall\"" . " alt=\"{$strmovedown}\" /></a>";
                    }
                }
                if ($allowdelete && question_has_capability_on($question, 'use', $question->category)) {
                    // remove from quiz, not question delete.
                    if (!$hasattempts) {
                        echo "<a title=\"{$strremove}\" href=\"" . $pageurl->out_action(array('remove' => $question->id)) . "\">\n                            <img src=\"{$CFG->pixpath}/t/delete.gif\" " . "class=\"iconsmall\" alt=\"{$strremove}\" /></a>";
                    }
                }
                ?>
            </div><?php 
                if ($question->qtype != 'description' && !$reordertool) {
                    ?>
<div class="points">
<form method="post" action="edit.php"><div>
    <fieldset class="invisiblefieldset" style="display: block;">
    <label for="<?php 
                    echo "inputq{$question->id}";
                    ?>
"><?php 
                    echo $strgrade;
                    ?>
</label>:<br />
    <input type="hidden" name="sesskey" value="<?php 
                    echo sesskey();
                    ?>
" />
    <?php 
                    echo $pageurl->hidden_params_out();
                    ?>
    <input type="hidden" name="savechanges" value="save" />
        <?php 
                    echo '<input type="text" name="g' . $question->id . '" id="inputq' . $question->id . '" size="' . ($quiz->decimalpoints + 2) . '" value="' . (0 + $quiz->grades[$qnum]) . '" tabindex="' . ($lastindex + $qno) . '" />';
                    ?>
        <input type="submit" class="pointssubmitbutton" value="<?php 
                    echo $strsave;
                    ?>
" />
    </fieldset>
<?php 
                    if ($question->qtype == 'random') {
                        echo '<a href="' . $questionurl->out() . '" class="configurerandomquestion">' . get_string("configurerandomquestion", "quiz") . '</a>';
                    }
                    ?>
</div>
</form>

            </div>
<?php 
                } else {
                    if ($reordertool) {
                        if ($qnum) {
                            ?>
<div class="qorder">
        <?php 
                            echo '<input type="text" name="o' . $question->id . '" size="2" value="' . (10 * $count + 10) . '" tabindex="' . ($lastindex + $qno) . '" />';
                            ?>
<!--         <input type="submit" class="pointssubmitbutton" value="<?php 
                            echo $strsave;
                            ?>
" /> -->
</div>
<?php 
                        }
                    }
                }
                ?>
            <div class="questioncontentcontainer">
<?php 
                if ($question->qtype == 'random') {
                    // it is a random question
                    if (!$reordertool) {
                        quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool);
                    } else {
                        quiz_print_randomquestion_reordertool($question, $pageurl, $quiz);
                    }
                } else {
                    // it is a single question
                    if (!$reordertool) {
                        quiz_print_singlequestion($question, $returnurl, $quiz);
                    } else {
                        quiz_print_singlequestion_reordertool($question, $returnurl, $quiz);
                    }
                }
                ?>
            </div>
        </div>
    </div>
</div>

    <?php 
                /* Display question end */
                $count++;
                $sumgrade += $quiz->grades[$qnum];
            }
        }
        //a page break: end the existing page.
        if ($qnum == 0) {
            if ($pageopen) {
                if (!$reordertool && !($quiz->shufflequestions && $i < $questiontotalcount - 1)) {
                    quiz_print_pagecontrols($quiz, $pageurl, $pagecount, $hasattempts);
                } else {
                    if ($i < $questiontotalcount - 1) {
                        //do not include the last page break for reordering
                        //to avoid creating a new extra page in the end
                        echo '<input type="hidden" name="opg' . $pagecount . '" size="2" value="' . (10 * $count + 10) . '" />';
                    }
                }
                echo "</div></div>";
                if (!$reordertool && !$quiz->shufflequestions) {
                    echo "<div class=\"addpage\">";
                    print_single_button($pageurl->out(true), array('cmid' => $quiz->cmid, 'courseid' => $quiz->course, 'addpage' => $count, 'sesskey' => sesskey()), get_string('addpagehere', 'quiz'), 'get', '_self', false, '', $hasattempts);
                    echo "</div>";
                }
                $pageopen = false;
                $count++;
            }
        }
    }
    if ($reordertool) {
        echo $reordercontrolsbottom;
        echo '</div></form>';
    }
    return $sumgrade;
}
Example #16
0
/**
 * Verify that the question exists, and the user has permission to use it.
 * @param object $quiz the quiz settings.
 * @param int $slot which question in the quiz to test.
 * @return bool whether the user can use this question.
 */
function quiz_has_question_use($quiz, $slot)
{
    global $DB;
    $question = $DB->get_record_sql("\n            SELECT q.*\n              FROM {quiz_slots} slot\n              JOIN {question} q ON q.id = slot.questionid\n             WHERE slot.quizid = ? AND slot.slot = ?", array($quiz->id, $slot));
    if (!$question) {
        return false;
    }
    return question_has_capability_on($question, 'use');
}
Example #17
0
 /**
  * Get a link to an edit icon for this question, if the current user is allowed
  * to edit it.
  *
  * @param object $question the question object.
  * @param object $cmoptions the options from the module. If $cmoptions->thispageurl is set
  *      then the link will be to edit the question in this browser window, then return to
  *      $cmoptions->thispageurl. Otherwise the link will be to edit in a popup.
  * @return string the HTML of the link, or nothing it the currenty user is not allowed to edit.
  */
 function get_question_edit_link($question, $cmoptions, $options)
 {
     global $CFG, $OUTPUT;
     /// Is this user allowed to edit this question?
     if (!empty($options->noeditlink) || !question_has_capability_on($question, 'edit')) {
         return '';
     }
     /// Work out the right URL.
     $linkurl = '/question/question.php?id=' . $question->id;
     if (!empty($cmoptions->cmid)) {
         $linkurl .= '&amp;cmid=' . $cmoptions->cmid;
     } else {
         if (!empty($cmoptions->course)) {
             $linkurl .= '&amp;courseid=' . $cmoptions->course;
         } else {
             print_error('missingcourseorcmidtolink', 'question');
         }
     }
     /// Work out the contents of the link.
     $stredit = get_string('edit');
     $linktext = '<img src="' . $OUTPUT->old_icon_url('t/edit') . '" alt="' . $stredit . '" />';
     if (!empty($cmoptions->thispageurl)) {
         /// The module allow editing in the same window, print an ordinary link.
         return '<a href="' . $CFG->wwwroot . $linkurl . '&amp;returnurl=' . urlencode($cmoptions->thispageurl) . '" title="' . $stredit . '">' . $linktext . '</a>';
     } else {
         /// We have to edit in a pop-up.
         $link = html_link::make($linkurl . '&inpopup=1', $linktext);
         $link->add_action(new popup_action('click', $link->url, 'editquestion'));
         $link->title = $stredit;
         return $OUTPUT->link($link);
     }
 }
Example #18
0
 /**
  * Wrapper that the correct mod_quiz_display_options for this quiz at the
  * moment.
  *
  * @param bool $reviewing true for review page, else attempt page.
  * @param int $slot which question is being displayed.
  * @param moodle_url $thispageurl to return to after the editing form is
  *      submitted or cancelled. If null, no edit link will be generated.
  *
  * @return question_display_options the render options for this user on this
  *      attempt, with extra info to generate an edit link, if applicable.
  */
 public function get_display_options_with_edit_link($reviewing, $slot, $thispageurl)
 {
     $options = clone $this->get_display_options($reviewing);
     if (!$thispageurl) {
         return $options;
     }
     if (!($reviewing || $this->is_preview())) {
         return $options;
     }
     $question = $this->quba->get_question($slot);
     if (!question_has_capability_on($question, 'edit', $question->category)) {
         return $options;
     }
     $options->editquestionparams['cmid'] = $this->get_cmid();
     $options->editquestionparams['returnurl'] = $thispageurl;
     return $options;
 }
Example #19
0
        question_require_capability_on($question, 'move');
    } else {
        $question->formoptions->canedit = question_has_capability_on($question, 'edit');
        $question->formoptions->canmove = $addpermission && question_has_capability_on($question, 'move');
        $question->formoptions->cansaveasnew = $addpermission && (question_has_capability_on($question, 'view') || $question->formoptions->canedit);
        $question->formoptions->repeatelements = $question->formoptions->canedit || $question->formoptions->cansaveasnew;
        $formeditable = $question->formoptions->canedit || $question->formoptions->cansaveasnew || $question->formoptions->canmove;
        $question->formoptions->movecontext = false;
        if (!$formeditable) {
            question_require_capability_on($question, 'view');
        }
    }
} else {
    // creating a new question
    $question->formoptions->canedit = question_has_capability_on($question, 'edit');
    $question->formoptions->canmove = question_has_capability_on($question, 'move') && $addpermission;
    $question->formoptions->cansaveasnew = false;
    $question->formoptions->repeatelements = true;
    $question->formoptions->movecontext = false;
    $formeditable = true;
    require_capability('moodle/question:add', $categorycontext);
}
$question->formoptions->mustbeusable = (bool) $appendqnumstring;
// Validate the question type.
$PAGE->set_pagetype('question-type-' . $question->qtype);
// Create the question editing form.
if ($wizardnow !== '' && !$movecontext) {
    $mform = $qtypeobj->next_wizard_form('question.php', $question, $wizardnow, $formeditable);
} else {
    $mform = $qtypeobj->create_editing_form('question.php', $question, $category, $contexts, $formeditable);
}
Example #20
0
/**
 * @param object $quiz the quiz
 * @param object $question the question
 * @return the HTML for a preview question icon.
 */
function quiz_question_preview_button($quiz, $question)
{
    global $CFG, $COURSE;
    if (!question_has_capability_on($question, 'use', $question->category)) {
        return '';
    }
    $strpreview = get_string('previewquestion', 'quiz');
    $quizorcourseid = $quiz->id ? '&amp;quizid=' . $quiz->id : '&amp;courseid=' . $COURSE->id;
    return 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, true);
}
 /**
  * Make some questions and add them to the quiz.
  *
  * @param int $courseid
  * @return stdClass
  */
 public function make_question($courseid)
 {
     $context = context_course::instance($courseid);
     $defaultcategory = question_make_default_categories(array($context));
     $questioncategoryid = $defaultcategory->id;
     global $USER, $DB;
     // Robbed from question/question.php.
     $question = new stdClass();
     $question->category = $questioncategoryid;
     $question->qtype = 'essay';
     $question->createdby = $USER->id;
     $question->formoptions = new stdClass();
     $question->formoptions->canedit = question_has_capability_on($question, 'edit');
     $params = array('id' => $question->category);
     if (!($category = $DB->get_record('question_categories', $params))) {
         print_error('categorydoesnotexist', 'question');
     }
     $categorycontext = context::instance_by_id($category->contextid);
     $addpermission = has_capability('moodle/question:add', $categorycontext);
     $question->formoptions->canmove = question_has_capability_on($question, 'move') && $addpermission;
     $question->formoptions->cansaveasnew = false;
     $question->formoptions->repeatelements = true;
     $question->formoptions->movecontext = false;
     $question->formoptions->mustbeusable = 0;
     $question->errors = array();
     $qtypeobj = question_bank::get_qtype('essay');
     $fromform = new stdClass();
     $fromform->category = $questioncategoryid;
     // Slash separated.
     $fromform->name = '';
     $fromform->parent = '';
     $fromform->penalty = '';
     $fromform->questiontext['text'] = '';
     $fromform->questiontext['format'] = 1;
     $fromform->responseformat = 'editor';
     $fromform->responsefieldlines = 5;
     $fromform->attachments = 0;
     $fromform->graderinfo['text'] = '';
     $fromform->graderinfo['format'] = '';
     return $qtypeobj->save_question($question, $fromform);
 }
Example #22
0
 /**
  * Do the export
  * For most types this should not need to be overrided
  * @return boolean success
  */
 function exportprocess()
 {
     global $CFG;
     // create a directory for the exports (if not already existing)
     if (!($export_dir = make_upload_directory($this->question_get_export_dir()))) {
         error(get_string('cannotcreatepath', 'quiz', $export_dir));
     }
     $path = $CFG->dataroot . '/' . $this->question_get_export_dir();
     // get the questions (from database) in this category
     // only get q's with no parents (no cloze subquestions specifically)
     if ($this->category) {
         $questions = get_questions_category($this->category, true);
     } else {
         $questions = $this->questions;
     }
     notify(get_string('exportingquestions', 'quiz'));
     $count = 0;
     // results are first written into string (and then to a file)
     // so create/initialize the string here
     $expout = "";
     // track which category questions are in
     // if it changes we will record the category change in the output
     // file if selected. 0 means that it will get printed before the 1st question
     $trackcategory = 0;
     // iterate through questions
     foreach ($questions as $question) {
         // do not export hidden questions
         if (!empty($question->hidden)) {
             continue;
         }
         // do not export random questions
         if ($question->qtype == RANDOM) {
             continue;
         }
         // check if we need to record category change
         if ($this->cattofile) {
             if ($question->category != $trackcategory) {
                 $trackcategory = $question->category;
                 $categoryname = $this->get_category_path($trackcategory, '/', $this->contexttofile);
                 // create 'dummy' question for category export
                 $dummyquestion = new object();
                 $dummyquestion->qtype = 'category';
                 $dummyquestion->category = $categoryname;
                 $dummyquestion->name = "switch category to {$categoryname}";
                 $dummyquestion->id = 0;
                 $dummyquestion->questiontextformat = '';
                 $expout .= $this->writequestion($dummyquestion) . "\n";
             }
         }
         // export the question displaying message
         $count++;
         echo "<hr /><p><b>{$count}</b>. " . $this->format_question_text($question) . "</p>";
         if (question_has_capability_on($question, 'view', $question->category)) {
             $expout .= $this->writequestion($question) . "\n";
         }
     }
     // continue path for following error checks
     $course = $this->course;
     $continuepath = "{$CFG->wwwroot}/question/export.php?courseid={$course->id}";
     // did we actually process anything
     if ($count == 0) {
         print_error('noquestions', 'quiz', $continuepath);
     }
     // final pre-process on exported data
     $expout = $this->presave_process($expout);
     // write file
     $filepath = $path . "/" . $this->filename . $this->export_file_extension();
     if (!($fh = fopen($filepath, "w"))) {
         print_error('cannotopen', 'quiz', $continuepath, $filepath);
     }
     if (!fwrite($fh, $expout, strlen($expout))) {
         print_error('cannotwrite', 'quiz', $continuepath, $filepath);
     }
     fclose($fh);
     return true;
 }
Example #23
0
/**
 * Prints a list of quiz questions for the edit.php main view for edit
 * ($reordertool = false) and order and paging ($reordertool = true) tabs
 *
 * @return int sum of maximum grades
 * @param object $quiz This is not the standard quiz object used elsewhere but
 *     it contains the quiz layout in $quiz->questions and the grades in
 *     $quiz->grades
 * @param object $pageurl The url of the current page with the parameters required
 *     for links returning to the current page, as a moodle_url object
 * @param bool $allowdelete Indicates whether the delete icons should be displayed
 * @param bool $reordertool  Indicates whether the reorder tool should be displayed
 * @param bool $quiz_qbanktool  Indicates whether the question bank should be displayed
 * @param bool $hasattempts  Indicates whether the quiz has attempts
 */
function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool,
        $quiz_qbanktool, $hasattempts, $defaultcategoryobj) {
    global $CFG, $DB, $OUTPUT;
    $strorder = get_string('order');
    $strquestionname = get_string('questionname', 'quiz');
    $strgrade = get_string('grade');
    $strremove = get_string('remove', 'quiz');
    $stredit = get_string('edit');
    $strview = get_string('view');
    $straction = get_string('action');
    $strmove = get_string('move');
    $strmoveup = get_string('moveup');
    $strmovedown = get_string('movedown');
    $strsave = get_string('save', 'quiz');
    $strreorderquestions = get_string('reorderquestions', 'quiz');

    $strselectall = get_string('selectall', 'quiz');
    $strselectnone = get_string('selectnone', 'quiz');
    $strtype = get_string('type', 'quiz');
    $strpreview = get_string('preview', 'quiz');

    if ($quiz->questions) {
        list($usql, $params) = $DB->get_in_or_equal(explode(',', $quiz->questions));
        $params[] = $quiz->id;
        $questions = $DB->get_records_sql("SELECT q.*, qc.contextid, qqi.grade as maxmark
                              FROM {question} q
                              JOIN {question_categories} qc ON qc.id = q.category
                              JOIN {quiz_question_instances} qqi ON qqi.question = q.id
                             WHERE q.id $usql AND qqi.quiz = ?", $params);
    } else {
        $questions = array();
    }

    $layout = quiz_clean_layout($quiz->questions);
    $order = explode(',', $layout);
    $lastindex = count($order) - 1;

    $disabled = '';
    $pagingdisabled = '';
    if ($hasattempts) {
        $disabled = 'disabled="disabled"';
    }
    if ($hasattempts || $quiz->shufflequestions) {
        $pagingdisabled = 'disabled="disabled"';
    }

    $reordercontrolssetdefaultsubmit = '<div style="display:none;">' .
        '<input type="submit" name="savechanges" value="' .
        $strreorderquestions . '" ' . $pagingdisabled . ' /></div>';
    $reordercontrols1 = '<div class="addnewpagesafterselected">' .
        '<input type="submit" name="addnewpagesafterselected" value="' .
        get_string('addnewpagesafterselected', 'quiz') . '"  ' .
        $pagingdisabled . ' /></div>';
    $reordercontrols1 .= '<div class="quizdeleteselected">' .
        '<input type="submit" name="quizdeleteselected" ' .
        'onclick="return confirm(\'' .
        get_string('areyousureremoveselected', 'quiz') . '\');" value="' .
        get_string('removeselected', 'quiz') . '"  ' . $disabled . ' /></div>';

    $a = '<input name="moveselectedonpagetop" type="text" size="2" ' .
        $pagingdisabled . ' />';
    $b = '<input name="moveselectedonpagebottom" type="text" size="2" ' .
        $pagingdisabled . ' />';

    $reordercontrols2top = '<div class="moveselectedonpage">' .
        get_string('moveselectedonpage', 'quiz', $a) .
        '<input type="submit" name="savechanges" value="' .
        $strmove . '"  ' . $pagingdisabled . ' />' . '
        <br /><input type="submit" name="savechanges" value="' .
        $strreorderquestions . '" /></div>';
    $reordercontrols2bottom = '<div class="moveselectedonpage">' .
        '<input type="submit" name="savechanges" value="' .
        $strreorderquestions . '" /><br />' .
        get_string('moveselectedonpage', 'quiz', $b) .
        '<input type="submit" name="savechanges" value="' .
        $strmove . '"  ' . $pagingdisabled . ' /> ' . '</div>';

    $reordercontrols3 = '<a href="javascript:select_all_in(\'FORM\', null, ' .
            '\'quizquestions\');">' .
            $strselectall . '</a> /';
    $reordercontrols3.=    ' <a href="javascript:deselect_all_in(\'FORM\', ' .
            'null, \'quizquestions\');">' .
            $strselectnone . '</a>';

    $reordercontrolstop = '<div class="reordercontrols">' .
            $reordercontrolssetdefaultsubmit .
            $reordercontrols1 . $reordercontrols2top . $reordercontrols3 . "</div>";
    $reordercontrolsbottom = '<div class="reordercontrols">' .
            $reordercontrolssetdefaultsubmit .
            $reordercontrols2bottom . $reordercontrols1 . $reordercontrols3 . "</div>";

    if ($reordertool) {
        echo '<form method="post" action="edit.php" id="quizquestions"><div>';

        echo html_writer::input_hidden_params($pageurl);
        echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';

        echo $reordercontrolstop;
    }

    //the current question ordinal (no descriptions)
    $qno = 1;
    //the current question (includes questions and descriptions)
    $questioncount = 0;
    //the current page number in iteration
    $pagecount = 0;

    $pageopen = false;

    $returnurl = $pageurl->out_as_local_url(false);
    $questiontotalcount = count($order);

    foreach ($order as $count => $qnum) {

        $reordercheckbox = '';
        $reordercheckboxlabel = '';
        $reordercheckboxlabelclose = '';

        // If the questiontype is missing change the question type
        if ($qnum && !array_key_exists($qnum, $questions)) {
            $fakequestion = new stdClass();
            $fakequestion->id = $qnum;
            $fakequestion->category = 0;
            $fakequestion->qtype = 'missingtype';
            $fakequestion->name = get_string('missingquestion', 'quiz');
            $fakequestion->questiontext = ' ';
            $fakequestion->questiontextformat = FORMAT_HTML;
            $fakequestion->length = 1;
            $questions[$qnum] = $fakequestion;
            $quiz->grades[$qnum] = 0;

        } else if ($qnum && !question_bank::qtype_exists($questions[$qnum]->qtype)) {
            $questions[$qnum]->qtype = 'missingtype';
        }

        if ($qnum != 0 || ($qnum == 0 && !$pageopen)) {
            //this is either a question or a page break after another
            //        (no page is currently open)
            if (!$pageopen) {
                //if no page is open, start display of a page
                $pagecount++;
                echo  '<div class="quizpage"><span class="pagetitle">' .
                        get_string('page') . '&nbsp;' . $pagecount .
                        '</span><div class="pagecontent">';
                $pageopen = true;
            }
            if ($qnum == 0  && $count < $questiontotalcount) {
                // This is the second successive page break. Tell the user the page is empty.
                echo '<div class="pagestatus">';
                print_string('noquestionsonpage', 'quiz');
                echo '</div>';
                if ($allowdelete) {
                    echo '<div class="quizpagedelete">';
                    echo $OUTPUT->action_icon($pageurl->out(true,
                            array('deleteemptypage' => $count - 1, 'sesskey'=>sesskey())),
                            new pix_icon('t/delete', $strremove),
                            new component_action('click',
                                    'M.core_scroll_manager.save_scroll_action'),
                            array('title' => $strremove));
                    echo '</div>';
                }
            }

            if ($qnum != 0) {
                $question = $questions[$qnum];
                $questionparams = array(
                        'returnurl' => $returnurl,
                        'cmid' => $quiz->cmid,
                        'id' => $question->id);
                $questionurl = new moodle_url('/question/question.php',
                        $questionparams);
                $questioncount++;
                //this is an actual question

                /* Display question start */
                ?>
<div class="question">
    <div class="questioncontainer <?php echo $question->qtype; ?>">
        <div class="qnum">
                <?php
                $reordercheckbox = '';
                $reordercheckboxlabel = '';
                $reordercheckboxlabelclose = '';
                if ($reordertool) {
                    $reordercheckbox = '<input type="checkbox" name="s' . $question->id .
                        '" id="s' . $question->id . '" />';
                    $reordercheckboxlabel = '<label for="s' . $question->id . '">';
                    $reordercheckboxlabelclose = '</label>';
                }
                if ($question->length == 0) {
                    $qnodisplay = get_string('infoshort', 'quiz');
                } else if ($quiz->shufflequestions) {
                    $qnodisplay = '?';
                } else {
                    if ($qno > 999 || ($reordertool && $qno > 99)) {
                        $qnodisplay = html_writer::tag('small', $qno);
                    } else {
                        $qnodisplay = $qno;
                    }
                    $qno += $question->length;
                }
                echo $reordercheckboxlabel . $qnodisplay . $reordercheckboxlabelclose .
                        $reordercheckbox;

                ?>
        </div>
        <div class="content">
            <div class="questioncontrols">
                <?php
                if ($count != 0) {
                    if (!$hasattempts) {
                        $upbuttonclass = '';
                        if ($count >= $lastindex - 1) {
                            $upbuttonclass = 'upwithoutdown';
                        }
                        echo $OUTPUT->action_icon($pageurl->out(true,
                                array('up' => $question->id, 'sesskey'=>sesskey())),
                                new pix_icon('t/up', $strmoveup),
                                new component_action('click',
                                        'M.core_scroll_manager.save_scroll_action'),
                                array('title' => $strmoveup));
                    }

                }
                if ($count < $lastindex - 1) {
                    if (!$hasattempts) {
                        echo $OUTPUT->action_icon($pageurl->out(true,
                                array('down' => $question->id, 'sesskey'=>sesskey())),
                                new pix_icon('t/down', $strmovedown),
                                new component_action('click',
                                        'M.core_scroll_manager.save_scroll_action'),
                                array('title' => $strmovedown));
                    }
                }
                if ($allowdelete && ($question->qtype == 'missingtype' ||
                        question_has_capability_on($question, 'use', $question->category))) {
                    // remove from quiz, not question delete.
                    if (!$hasattempts) {
                        echo $OUTPUT->action_icon($pageurl->out(true,
                                array('remove' => $question->id, 'sesskey'=>sesskey())),
                                new pix_icon('t/delete', $strremove),
                                new component_action('click',
                                        'M.core_scroll_manager.save_scroll_action'),
                                array('title' => $strremove));
                    }
                }
                ?>
            </div><?php
                if (!in_array($question->qtype, array('description', 'missingtype')) && !$reordertool) {
                    ?>
<div class="points">
<form method="post" action="edit.php" class="quizsavegradesform"><div>
    <fieldset class="invisiblefieldset" style="display: block;">
    <label for="<?php echo "inputq$question->id" ?>"><?php echo $strgrade; ?></label>:<br />
    <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
    <?php echo html_writer::input_hidden_params($pageurl); ?>
    <input type="hidden" name="savechanges" value="save" />
                    <?php
                    echo '<input type="text" name="g' . $question->id .
                            '" id="inputq' . $question->id .
                            '" size="' . ($quiz->decimalpoints + 2) .
                            '" value="' . (0 + $quiz->grades[$qnum]) .
                            '" tabindex="' . ($lastindex + $qno) . '" />';
                    ?>
        <input type="submit" class="pointssubmitbutton" value="<?php echo $strsave; ?>" />
    </fieldset>
                    <?php
                    if ($question->qtype == 'random') {
                        echo '<a href="' . $questionurl->out() .
                                '" class="configurerandomquestion">' .
                                get_string("configurerandomquestion", "quiz") . '</a>';
                    }

                    ?>
</div>
</form>

            </div>
                    <?php
                } else if ($reordertool) {
                    if ($qnum) {
                        ?>
<div class="qorder">
                        <?php
                        echo '<input type="text" name="o' . $question->id .
                                '" size="2" value="' . (10*$count + 10) .
                                '" tabindex="' . ($lastindex + $qno) . '" />';
                        ?>
</div>
                        <?php
                    }
                }
                ?>
            <div class="questioncontentcontainer">
                <?php
                if ($question->qtype == 'random') { // it is a random question
                    if (!$reordertool) {
                        quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool);
                    } else {
                        quiz_print_randomquestion_reordertool($question, $pageurl, $quiz);
                    }
                } else { // it is a single question
                    if (!$reordertool) {
                        quiz_print_singlequestion($question, $returnurl, $quiz);
                    } else {
                        quiz_print_singlequestion_reordertool($question, $returnurl, $quiz);
                    }
                }
                ?>
            </div>
        </div>
    </div>
</div>

                <?php
            }
        }
        //a page break: end the existing page.
        if ($qnum == 0) {
            if ($pageopen) {
                if (!$reordertool && !($quiz->shufflequestions &&
                        $count < $questiontotalcount - 1)) {
                    quiz_print_pagecontrols($quiz, $pageurl, $pagecount,
                            $hasattempts, $defaultcategoryobj);
                } else if ($count < $questiontotalcount - 1) {
                    //do not include the last page break for reordering
                    //to avoid creating a new extra page in the end
                    echo '<input type="hidden" name="opg' . $pagecount . '" size="2" value="' .
                            (10*$count + 10) . '" />';
                }
                echo "</div></div>";

                if (!$reordertool && !$quiz->shufflequestions) {
                    echo $OUTPUT->container_start('addpage');
                    $url = new moodle_url($pageurl->out_omit_querystring(),
                            array('cmid' => $quiz->cmid, 'courseid' => $quiz->course,
                                    'addpage' => $count, 'sesskey' => sesskey()));
                    echo $OUTPUT->single_button($url, get_string('addpagehere', 'quiz'), 'post',
                            array('disabled' => $hasattempts,
                            'actions' => array(new component_action('click',
                                    'M.core_scroll_manager.save_scroll_action'))));
                    echo $OUTPUT->container_end();
                }
                $pageopen = false;
                $count++;
            }
        }

    }
    if ($reordertool) {
        echo $reordercontrolsbottom;
        echo '</div></form>';
    }
}
Example #24
0
 function display($quiz, $cm, $course)
 {
     /// This function just displays the report
     global $CFG, $SESSION, $QTYPES;
     $strnoattempts = get_string('noattempts', 'quiz');
     /// Only print headers if not asked to download data
     $download = optional_param('download', NULL);
     if (!$download) {
         $this->print_header_and_tabs($cm, $course, $quiz, $reportmode = "analysis");
     }
     /// Construct the table for this particular report
     if (!$quiz->questions) {
         print_heading($strnoattempts);
         return true;
     }
     /// Check to see if groups are being used in this quiz
     $currentgroup = groups_get_activity_group($cm, true);
     if ($groupmode = groups_get_activity_groupmode($cm)) {
         // Groups are being used
         if (!$download) {
             groups_print_activity_menu($cm, "report.php?id={$cm->id}&amp;mode=analysis");
         }
     }
     // set Table and Analysis stats options
     if (!isset($SESSION->quiz_analysis_table)) {
         $SESSION->quiz_analysis_table = array('attemptselection' => 0, 'lowmarklimit' => 0, 'pagesize' => QUIZ_REPORT_DEFAULT_PAGE_SIZE);
     }
     foreach ($SESSION->quiz_analysis_table as $option => $value) {
         $urlparam = optional_param($option, NULL, PARAM_INT);
         if ($urlparam === NULL) {
             ${$option} = $value;
         } else {
             ${$option} = $SESSION->quiz_analysis_table[$option] = $urlparam;
         }
     }
     if (!isset($pagesize) || (int) $pagesize < 1) {
         $pagesize = QUIZ_REPORT_DEFAULT_PAGE_SIZE;
     }
     $scorelimit = $quiz->sumgrades * $lowmarklimit / 100;
     // ULPGC ecastro DEBUG this is here to allow for different SQL to select attempts
     switch ($attemptselection) {
         case QUIZ_ALLATTEMPTS:
             $limit = '';
             $group = '';
             break;
         case QUIZ_HIGHESTATTEMPT:
             $limit = ', max(qa.sumgrades) ';
             $group = ' GROUP BY qa.userid ';
             break;
         case QUIZ_FIRSTATTEMPT:
             $limit = ', min(qa.timemodified) ';
             $group = ' GROUP BY qa.userid ';
             break;
         case QUIZ_LASTATTEMPT:
             $limit = ', max(qa.timemodified) ';
             $group = ' GROUP BY qa.userid ';
             break;
     }
     if ($attemptselection != QUIZ_ALLATTEMPTS) {
         $sql = 'SELECT qa.userid ' . $limit . 'FROM ' . $CFG->prefix . 'user u LEFT JOIN ' . $CFG->prefix . 'quiz_attempts qa ON u.id = qa.userid ' . 'WHERE qa.quiz = ' . $quiz->id . ' AND qa.preview = 0 ' . $group;
         $usermax = get_records_sql_menu($sql);
     }
     $groupmembers = '';
     $groupwhere = '';
     //Add this to the SQL to show only group users
     if ($currentgroup) {
         $groupmembers = ", {$CFG->prefix}groups_members gm ";
         $groupwhere = "AND gm.groupid = '{$currentgroup}' AND u.id = gm.userid";
     }
     $sql = 'SELECT  qa.* FROM ' . $CFG->prefix . 'quiz_attempts qa, ' . $CFG->prefix . 'user u ' . $groupmembers . 'WHERE u.id = qa.userid AND qa.quiz = ' . $quiz->id . ' AND qa.preview = 0 AND ( qa.sumgrades >= ' . $scorelimit . ' ) ' . $groupwhere;
     // ^^^^^^ es posible seleccionar aqu TODOS los quizzes, como quiere Jussi,
     // pero haba que llevar la cuenta ed cada quiz para restaura las preguntas (quizquestions, states)
     /// Fetch the attempts
     $attempts = get_records_sql($sql);
     if (empty($attempts)) {
         print_heading(get_string('nothingtodisplay'));
         $this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize);
         return true;
     }
     /// Here we rewiew all attempts and record data to construct the table
     $questions = array();
     $statstable = array();
     $questionarray = array();
     foreach ($attempts as $attempt) {
         $questionarray[] = quiz_questions_in_quiz($attempt->layout);
     }
     $questionlist = quiz_questions_in_quiz(implode(",", $questionarray));
     $questionarray = array_unique(explode(",", $questionlist));
     $questionlist = implode(",", $questionarray);
     unset($questionarray);
     foreach ($attempts as $attempt) {
         switch ($attemptselection) {
             case QUIZ_ALLATTEMPTS:
                 $userscore = 0;
                 // can be anything, not used
                 break;
             case QUIZ_HIGHESTATTEMPT:
                 $userscore = $attempt->sumgrades;
                 break;
             case QUIZ_FIRSTATTEMPT:
                 $userscore = $attempt->timemodified;
                 break;
             case QUIZ_LASTATTEMPT:
                 $userscore = $attempt->timemodified;
                 break;
         }
         if ($attemptselection == QUIZ_ALLATTEMPTS || $userscore == $usermax[$attempt->userid]) {
             $sql = "SELECT q.*, i.grade AS maxgrade, i.id AS instance" . "  FROM {$CFG->prefix}question q," . "       {$CFG->prefix}quiz_question_instances i" . " WHERE i.quiz = '{$quiz->id}' AND q.id = i.question" . "   AND q.id IN ({$questionlist})";
             if (!($quizquestions = get_records_sql($sql))) {
                 error('No questions found');
             }
             // Load the question type specific information
             if (!get_question_options($quizquestions)) {
                 error('Could not load question options');
             }
             // Restore the question sessions to their most recent states
             // creating new sessions where required
             if (!($states = get_question_states($quizquestions, $quiz, $attempt))) {
                 error('Could not restore question sessions');
             }
             $numbers = explode(',', $questionlist);
             $statsrow = array();
             foreach ($numbers as $i) {
                 if (!isset($quizquestions[$i]) or !isset($states[$i])) {
                     continue;
                 }
                 $qtype = $quizquestions[$i]->qtype == 'random' ? $states[$i]->options->question->qtype : $quizquestions[$i]->qtype;
                 $q = get_question_responses($quizquestions[$i], $states[$i]);
                 if (empty($q)) {
                     continue;
                 }
                 $qid = $q->id;
                 if (!isset($questions[$qid])) {
                     $questions[$qid]['id'] = $qid;
                     $questions[$qid]['qname'] = $quizquestions[$i]->name;
                     foreach ($q->responses as $answer => $r) {
                         $r->count = 0;
                         $questions[$qid]['responses'][$answer] = $r->answer;
                         $questions[$qid]['rcounts'][$answer] = 0;
                         $questions[$qid]['credits'][$answer] = $r->credit;
                         $statsrow[$qid] = 0;
                     }
                 }
                 $responses = get_question_actual_response($quizquestions[$i], $states[$i]);
                 foreach ($responses as $resp) {
                     if ($resp) {
                         if ($key = array_search($resp, $questions[$qid]['responses'])) {
                             $questions[$qid]['rcounts'][$key]++;
                         } else {
                             $test = new stdClass();
                             $test->responses = $QTYPES[$quizquestions[$i]->qtype]->get_correct_responses($quizquestions[$i], $states[$i]);
                             if ($key = $QTYPES[$quizquestions[$i]->qtype]->check_response($quizquestions[$i], $states[$i], $test)) {
                                 $questions[$qid]['rcounts'][$key]++;
                             } else {
                                 $questions[$qid]['responses'][] = $resp;
                                 $questions[$qid]['rcounts'][] = 1;
                                 $questions[$qid]['credits'][] = 0;
                             }
                         }
                     }
                 }
                 $statsrow[$qid] = get_question_fraction_grade($quizquestions[$i], $states[$i]);
             }
             $attemptscores[$attempt->id] = $attempt->sumgrades;
             $statstable[$attempt->id] = $statsrow;
         }
     }
     // Statistics Data table built
     unset($attempts);
     unset($quizquestions);
     unset($states);
     // now calculate statistics and set the values in the $questions array
     $top = max($attemptscores);
     $bottom = min($attemptscores);
     $gap = ($top - $bottom) / 3;
     $top -= $gap;
     $bottom += $gap;
     foreach ($questions as $qid => $q) {
         $questions[$qid] = $this->report_question_stats($q, $attemptscores, $statstable, $top, $bottom);
     }
     unset($attemptscores);
     unset($statstable);
     /// Now check if asked download of data
     if ($download = optional_param('download', NULL)) {
         $filename = clean_filename("{$course->shortname} " . format_string($quiz->name, true));
         switch ($download) {
             case "Excel":
                 $this->Export_Excel($questions, $filename);
                 break;
             case "ODS":
                 $this->Export_ODS($questions, $filename);
                 break;
             case "CSV":
                 $this->Export_CSV($questions, $filename);
                 break;
         }
     }
     /// Construct the table for this particular report
     $tablecolumns = array('id', 'qname', 'responses', 'credits', 'rcounts', 'rpercent', 'facility', 'qsd', 'disc_index', 'disc_coeff');
     $tableheaders = array(get_string('qidtitle', 'quiz_analysis'), get_string('qtexttitle', 'quiz_analysis'), get_string('responsestitle', 'quiz_analysis'), get_string('rfractiontitle', 'quiz_analysis'), get_string('rcounttitle', 'quiz_analysis'), get_string('rpercenttitle', 'quiz_analysis'), get_string('facilitytitle', 'quiz_analysis'), get_string('stddevtitle', 'quiz_analysis'), get_string('dicsindextitle', 'quiz_analysis'), get_string('disccoefftitle', 'quiz_analysis'));
     $table = new flexible_table('mod-quiz-report-itemanalysis');
     $table->define_columns($tablecolumns);
     $table->define_headers($tableheaders);
     $table->define_baseurl($CFG->wwwroot . '/mod/quiz/report.php?q=' . $quiz->id . '&amp;mode=analysis');
     $table->sortable(true);
     $table->no_sorting('rpercent');
     $table->collapsible(true);
     $table->initialbars(false);
     $table->column_class('id', 'numcol');
     $table->column_class('credits', 'numcol');
     $table->column_class('rcounts', 'numcol');
     $table->column_class('rpercent', 'numcol');
     $table->column_class('facility', 'numcol');
     $table->column_class('qsd', 'numcol');
     $table->column_class('disc_index', 'numcol');
     $table->column_class('disc_coeff', 'numcol');
     $table->column_suppress('id');
     $table->column_suppress('qname');
     $table->column_suppress('facility');
     $table->column_suppress('qsd');
     $table->column_suppress('disc_index');
     $table->column_suppress('disc_coeff');
     $table->set_attribute('cellspacing', '0');
     $table->set_attribute('id', 'itemanalysis');
     $table->set_attribute('class', 'generaltable generalbox');
     // Start working -- this is necessary as soon as the niceties are over
     $table->setup();
     $tablesort = $table->get_sql_sort();
     $sorts = explode(",", trim($tablesort));
     if ($tablesort and is_array($sorts)) {
         $sortindex = array();
         $sortorder = array();
         foreach ($sorts as $sort) {
             $data = explode(" ", trim($sort));
             $sortindex[] = trim($data[0]);
             $s = trim($data[1]);
             if ($s == "ASC") {
                 $sortorder[] = SORT_ASC;
             } else {
                 $sortorder[] = SORT_DESC;
             }
         }
         if (count($sortindex) > 0) {
             $sortindex[] = "id";
             $sortorder[] = SORT_ASC;
             foreach ($questions as $qid => $row) {
                 $index1[$qid] = $row[$sortindex[0]];
                 $index2[$qid] = $row[$sortindex[1]];
             }
             array_multisort($index1, $sortorder[0], $index2, $sortorder[1], $questions);
         }
     }
     $format_options = new stdClass();
     $format_options->para = false;
     $format_options->noclean = true;
     $format_options->newlines = false;
     // Now it is time to page the data, simply slice the keys in the array
     $table->pagesize($pagesize, count($questions));
     $start = $table->get_page_start();
     $pagequestions = array_slice(array_keys($questions), $start, $pagesize);
     foreach ($pagequestions as $qnum) {
         $q = $questions[$qnum];
         $qid = $q['id'];
         $question = get_record('question', 'id', $qid);
         if (question_has_capability_on($question, 'edit') || question_has_capability_on($question, 'view')) {
             $qnumber = " (" . link_to_popup_window('/question/question.php?id=' . $qid . '&amp;cmid=' . $cm->id, 'editquestion', $qid, 450, 550, get_string('edit'), 'none', true) . ") ";
         } else {
             $qnumber = $qid;
         }
         $qname = '<div class="qname">' . format_text($question->name . " :  ", $question->questiontextformat, $format_options, $quiz->course) . '</div>';
         $qicon = print_question_icon($question, true);
         $qreview = quiz_question_preview_button($quiz, $question);
         $qtext = format_text($question->questiontext, $question->questiontextformat, $format_options, $quiz->course);
         $qquestion = $qname . "\n" . $qtext . "\n";
         $responses = array();
         foreach ($q['responses'] as $aid => $resp) {
             $response = new stdClass();
             if ($q['credits'][$aid] <= 0) {
                 $qclass = 'uncorrect';
             } elseif ($q['credits'][$aid] == 1) {
                 $qclass = 'correct';
             } else {
                 $qclass = 'partialcorrect';
             }
             $response->credit = '<span class="' . $qclass . '">(' . format_float($q['credits'][$aid], 2) . ') </span>';
             $response->text = '<span class="' . $qclass . '">' . format_text($resp, FORMAT_MOODLE, $format_options, $quiz->course) . ' </span>';
             $count = $q['rcounts'][$aid] . '/' . $q['count'];
             $response->rcount = $count;
             $response->rpercent = '(' . format_float($q['rcounts'][$aid] / $q['count'] * 100, 0) . '%)';
             $responses[] = $response;
         }
         $facility = format_float($q['facility'] * 100, 0) . "%";
         $qsd = format_float($q['qsd'], 3);
         $di = format_float($q['disc_index'], 2);
         $dc = format_float($q['disc_coeff'], 2);
         $response = array_shift($responses);
         $table->add_data(array($qnumber . "\n<br />" . $qicon . "\n " . $qreview, $qquestion, $response->text, $response->credit, $response->rcount, $response->rpercent, $facility, $qsd, $di, $dc));
         foreach ($responses as $response) {
             $table->add_data(array('', '', $response->text, $response->credit, $response->rcount, $response->rpercent, '', '', '', ''));
         }
     }
     print_heading_with_help(get_string("analysistitle", "quiz_analysis"), "itemanalysis", "quiz");
     echo '<div id="tablecontainer">';
     $table->print_html();
     echo '</div>';
     $this->print_options_form($quiz, $cm, $attemptselection, $lowmarklimit, $pagesize);
     return true;
 }
/**
 * Called via pluginfile.php -> question_pluginfile to serve files belonging to
 * a question in a question_attempt when that attempt is a preview.
 *
 * @param object $course course settings object
 * @param object $context context object
 * @param string $component the name of the component we are serving files for.
 * @param string $filearea the name of the file area.
 * @param int $qubaid the question_usage this image belongs to.
 * @param int $slot the relevant slot within the usage.
 * @param array $args the remaining bits of the file path.
 * @param bool $forcedownload whether the user must be forced to download the file.
 * @return bool false if file not found, does not return if found - justsend the file
 */
function question_preview_question_pluginfile($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload)
{
    global $USER, $DB, $CFG;
    $quba = question_engine::load_questions_usage_by_activity($qubaid);
    if (!question_has_capability_on($quba->get_question($slot), 'use')) {
        send_file_not_found();
    }
    $options = new question_display_options();
    $options->feedback = question_display_options::VISIBLE;
    $options->numpartscorrect = question_display_options::VISIBLE;
    $options->generalfeedback = question_display_options::VISIBLE;
    $options->rightanswer = question_display_options::VISIBLE;
    $options->manualcomment = question_display_options::VISIBLE;
    $options->history = question_display_options::VISIBLE;
    if (!$quba->check_file_access($slot, $options, $component, $filearea, $args, $forcedownload)) {
        send_file_not_found();
    }
    $fs = get_file_storage();
    $relativepath = implode('/', $args);
    $fullpath = "/{$context->id}/{$component}/{$filearea}/{$relativepath}";
    if (!($file = $fs->get_file_by_hash(sha1($fullpath))) or $file->is_directory()) {
        send_file_not_found();
    }
    send_stored_file($file, 0, 0, $forcedownload);
}
Example #26
0
    } else {
        require_login($quiz->course, false, get_coursemodule_from_instance('quiz', $quizid, $quiz->course));
    }
}
if ($maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $id)) {
    $questions[$id]->maxgrade = $maxgrade;
} else {
    $questions[$id]->maxgrade = $questions[$id]->defaultgrade;
}
$quiz->id = 0;
// just for safety
$quiz->questions = $id;
if (!($category = get_record("question_categories", "id", $questions[$id]->category))) {
    error("This question doesn't belong to a valid category!");
}
if (!question_has_capability_on($questions[$id], 'use', $questions[$id]->category)) {
    error("You can't preview these questions!");
}
if (isset($COURSE)) {
    $quiz->course = $COURSE->id;
}
// Load the question type specific information
if (!get_question_options($questions)) {
    print_error('newattemptfail', 'quiz');
}
// Create a dummy quiz attempt
// TODO: find out what of the following we really need. What is $attempt
//       really used for?
$timenow = time();
$attempt->quiz = $quiz->id;
$attempt->userid = $USER->id;
Example #27
0
 protected function display_content($question, $rowclasses) {
     if (!question_has_capability_on($question, 'use')) {
         return;
     }
     // For RTL languages: switch right and left arrows.
     if (right_to_left()) {
         $movearrow = 't/removeright';
     } else {
         $movearrow = 't/moveleft';
     }
     $this->print_icon($movearrow, $this->stradd, $this->qbank->add_to_quiz_url($question->id));
 }
Example #28
0
/**
 * @param object $quiz the quiz
 * @param object $question the question
 * @param boolean $label if true, show the previewquestion label after the icon
 * @return the HTML for a preview question icon.
 */
function quiz_question_preview_button($quiz, $question, $label = false)
{
    global $CFG, $COURSE, $OUTPUT;
    if (!question_has_capability_on($question, 'use', $question->category)) {
        return '';
    }
    // Minor efficiency saving. Only get strings once, even if there are a lot of icons on one page.
    static $strpreview = null;
    static $strpreviewquestion = null;
    if ($strpreview === null) {
        $strpreview = get_string('preview', 'quiz');
        $strpreviewquestion = get_string('previewquestion', 'quiz');
    }
    // Do we want a label?
    $strpreviewlabel = "";
    if ($label) {
        $strpreviewlabel = $strpreview;
    }
    // Build the icon.
    $image = new html_image();
    $image->src = $OUTPUT->old_icon_url('t/preview');
    $image->add_class('iconsmall');
    $image->alt = $strpreviewquestion;
    $link = html_link::make("/question/preview.php?id={$question->id}&quizid={$quiz->id}", $strpreviewlabel);
    parse_str(QUESTION_PREVIEW_POPUP_OPTIONS, $options);
    $link->add_action(new popup_action('click', $link->url, 'questionpreview', $options));
    $link->title = $strpreviewquestion;
    return $OUTPUT->link_to_popup($link, $image);
}
Example #29
0
    /**
     * Do the export
     * For most types this should not need to be overrided
     * @return stored_file
     */
    public function exportprocess() {
        global $CFG, $OUTPUT, $DB, $USER;

        // get the questions (from database) in this category
        // only get q's with no parents (no cloze subquestions specifically)
        if ($this->category) {
            $questions = get_questions_category($this->category, true);
        } else {
            $questions = $this->questions;
        }

        $count = 0;

        // results are first written into string (and then to a file)
        // so create/initialize the string here
        $expout = "";

        // track which category questions are in
        // if it changes we will record the category change in the output
        // file if selected. 0 means that it will get printed before the 1st question
        $trackcategory = 0;

        // iterate through questions
        foreach ($questions as $question) {
            // used by file api
            $contextid = $DB->get_field('question_categories', 'contextid',
                    array('id' => $question->category));
            $question->contextid = $contextid;

            // do not export hidden questions
            if (!empty($question->hidden)) {
                continue;
            }

            // do not export random questions
            if ($question->qtype == 'random') {
                continue;
            }

            // check if we need to record category change
            if ($this->cattofile) {
                if ($question->category != $trackcategory) {
                    $trackcategory = $question->category;
                    $categoryname = $this->get_category_path($trackcategory, $this->contexttofile);

                    // create 'dummy' question for category export
                    $dummyquestion = new stdClass();
                    $dummyquestion->qtype = 'category';
                    $dummyquestion->category = $categoryname;
                    $dummyquestion->name = 'Switch category to ' . $categoryname;
                    $dummyquestion->id = 0;
                    $dummyquestion->questiontextformat = '';
                    $dummyquestion->contextid = 0;
                    $expout .= $this->writequestion($dummyquestion) . "\n";
                }
            }

            // export the question displaying message
            $count++;

            if (question_has_capability_on($question, 'view', $question->category)) {
                $expout .= $this->writequestion($question, $contextid) . "\n";
            }
        }

        // continue path for following error checks
        $course = $this->course;
        $continuepath = "$CFG->wwwroot/question/export.php?courseid=$course->id";

        // did we actually process anything
        if ($count==0) {
            print_error('noquestions', 'question', $continuepath);
        }

        // final pre-process on exported data
        $expout = $this->presave_process($expout);
        return $expout;
    }
Example #30
0
/**
* Prints a list of quiz questions in a small layout form with knobs
*
* @return int sum of maximum grades
* @param object $quiz This is not the standard quiz object used elsewhere but
*     it contains the quiz layout in $quiz->questions and the grades in
*     $quiz->grades
* @param boolean $allowdelete Indicates whether the delete icons should be displayed
* @param boolean $showbreaks  Indicates whether the page breaks should be displayed
* @param boolean $showbreaks  Indicates whether the reorder tool should be displayed
*/
function quiz_print_question_list($quiz, $pageurl, $allowdelete = true, $showbreaks = true, $reordertool = false)
{
    global $USER, $CFG, $QTYPES;
    $strorder = get_string("order");
    $strquestionname = get_string("questionname", "quiz");
    $strgrade = get_string("grade");
    $strremove = get_string('remove', 'quiz');
    $stredit = get_string("edit");
    $strview = get_string("view");
    $straction = get_string("action");
    $strmoveup = get_string("moveup");
    $strmovedown = get_string("movedown");
    $strsavegrades = get_string("savegrades", "quiz");
    $strtype = get_string("type", "quiz");
    $strpreview = get_string("preview", "quiz");
    if (!$quiz->questions) {
        echo "<p class=\"quizquestionlistcontrols\">";
        print_string("noquestions", "quiz");
        echo "</p>";
        return 0;
    }
    if (!($questions = get_records_sql("SELECT q.*,c.contextid\n                              FROM {$CFG->prefix}question q,\n                                   {$CFG->prefix}question_categories c\n                             WHERE q.id in ({$quiz->questions})\n                               AND q.category = c.id"))) {
        echo "<p class=\"quizquestionlistcontrols\">";
        print_string("noquestions", "quiz");
        echo "</p>";
        return 0;
    }
    $count = 0;
    $qno = 1;
    $sumgrade = 0;
    $order = explode(',', $quiz->questions);
    $lastindex = count($order) - 1;
    // If the list does not end with a pagebreak then add it on.
    if ($order[$lastindex] != 0) {
        $order[] = 0;
        $lastindex++;
    }
    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 style=\"width:100%;\">\n";
    echo "<tr><th colspan=\"3\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$strorder}</th>";
    echo "<th class=\"header\" scope=\"col\">#</th>";
    echo "<th align=\"left\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$strquestionname}</th>";
    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$strtype}</th>";
    echo "<th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$strgrade}</th>";
    echo "<th align=\"center\" style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">{$straction}</th>";
    echo "</tr>\n";
    foreach ($order as $i => $qnum) {
        if ($qnum and empty($questions[$qnum])) {
            continue;
        }
        // If the questiontype is missing change the question type
        if ($qnum and !array_key_exists($questions[$qnum]->qtype, $QTYPES)) {
            $questions[$qnum]->qtype = 'missingtype';
        }
        // Show the re-ordering field if the tool is turned on.
        // But don't show it in front of pagebreaks if they are hidden.
        if ($reordertool) {
            if ($qnum or $showbreaks) {
                echo '<tr><td><input type="text" name="o' . $i . '" size="2" value="' . (10 * $count + 10) . '" /></td>';
            } else {
                echo '<tr><td><input type="hidden" name="o' . $i . '" size="2" value="' . (10 * $count + 10) . '" /></td>';
            }
        } else {
            echo '<tr><td></td>';
        }
        if ($qnum == 0) {
            // This is a page break
            if ($showbreaks) {
                echo '<td colspan ="3">&nbsp;</td>';
                echo '<td><table style="width:100%; line-height:11px; font-size:9px; margin: -5px -5px;"><tr>';
                echo '<td><hr /></td>';
                echo '<td style="width:50px;">Page break</td>';
                echo '<td><hr /></td>';
                echo '<td style="width:45px;">';
                if ($count > 1) {
                    echo "<a title=\"{$strmoveup}\" href=\"" . $pageurl->out_action(array('up' => $count)) . "\"><img\n                         src=\"{$CFG->pixpath}/t/up.gif\" class=\"iconsmall\" alt=\"{$strmoveup}\" /></a>";
                }
                echo '&nbsp;';
                if ($count < $lastindex) {
                    echo "<a title=\"{$strmovedown}\" href=\"" . $pageurl->out_action(array('down' => $count)) . "\"><img\n                         src=\"{$CFG->pixpath}/t/down.gif\" class=\"iconsmall\" alt=\"{$strmovedown}\" /></a>";
                    echo "<a title=\"{$strremove}\" href=\"" . $pageurl->out_action(array('delete' => $count)) . "\">\n                          <img src=\"{$CFG->pixpath}/t/delete.gif\" class=\"iconsmall\" alt=\"{$strremove}\" /></a>";
                }
                echo '</td></tr></table></td>';
                echo '<td colspan="2">&nbsp;</td>';
            }
            $count++;
            // missing </tr> here, if loop is broken, need to close the </tr>
            echo "</tr>";
            continue;
        }
        $question = $questions[$qnum];
        echo "<td>";
        if ($count != 0) {
            echo "<a title=\"{$strmoveup}\" href=\"" . $pageurl->out_action(array('up' => $count)) . "\"><img\n                 src=\"{$CFG->pixpath}/t/up.gif\" class=\"iconsmall\" alt=\"{$strmoveup}\" /></a>";
        }
        echo "</td>";
        echo "<td>";
        if ($count < $lastindex - 1) {
            echo "<a title=\"{$strmovedown}\" href=\"" . $pageurl->out_action(array('down' => $count)) . "\"><img\n                 src=\"{$CFG->pixpath}/t/down.gif\" class=\"iconsmall\" alt=\"{$strmovedown}\" /></a>";
        }
        echo "</td>";
        if (!$quiz->shufflequestions) {
            // Print and increment question number
            echo '<td>' . ($question->length ? $qno : '&nbsp;') . '</td>';
            $qno += $question->length;
        } else {
            echo '<td>&nbsp;</td>';
        }
        echo '<td>' . format_string($question->name) . '</td>';
        echo "<td align=\"center\">";
        print_question_icon($question);
        echo "</td>";
        echo '<td align="left">';
        if ($question->qtype == 'description') {
            echo "<input type=\"hidden\" name=\"q{$qnum}\" value=\"0\" /> \n";
        } else {
            echo '<input type="text" name="q' . $qnum . '" size="2" value="' . $quiz->grades[$qnum] . '" tabindex="' . ($lastindex + $qno) . '" />';
        }
        echo '</td><td align="center">';
        if ($question->qtype != 'random') {
            echo quiz_question_preview_button($quiz, $question);
        }
        $returnurl = $pageurl->out();
        $questionparams = array('returnurl' => $returnurl, 'cmid' => $quiz->cmid, 'id' => $question->id);
        $questionurl = new moodle_url("{$CFG->wwwroot}/question/question.php", $questionparams);
        if (question_has_capability_on($question, 'edit', $question->category) || question_has_capability_on($question, 'move', $question->category)) {
            echo "<a title=\"{$stredit}\" href=\"" . $questionurl->out() . "\">\n                    <img src=\"{$CFG->pixpath}/t/edit.gif\" class=\"iconsmall\" alt=\"{$stredit}\" /></a>";
        } 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 ($allowdelete && question_has_capability_on($question, 'use', $question->category)) {
            // remove from quiz, not question delete.
            echo "<a title=\"{$strremove}\" href=\"" . $pageurl->out_action(array('delete' => $count)) . "\">\n                    <img src=\"{$CFG->pixpath}/t/removeright.gif\" class=\"iconsmall\" alt=\"{$strremove}\" /></a>";
        }
        echo "</td></tr>";
        $count++;
        $sumgrade += $quiz->grades[$qnum];
    }
    echo "<tr><td colspan=\"6\" align=\"right\">\n";
    print_string('total');
    echo ": </td>";
    echo "<td align=\"left\">\n";
    echo "<strong>{$sumgrade}</strong>";
    echo "</td><td>&nbsp;\n</td></tr>\n";
    echo "<tr><td colspan=\"6\" align=\"right\">\n";
    print_string('maximumgrade');
    echo ": </td>";
    echo "<td align=\"left\">\n";
    echo '<input type="text" name="maxgrade" size="2" tabindex="' . ($qno + 1) . '" value="' . $quiz->grade . '" />';
    echo '</td><td align="left">';
    helpbutton("maxgrade", get_string("maximumgrade"), "quiz");
    echo "</td></tr></table>\n";
    echo '<div class="quizquestionlistcontrols"><input type="submit" value="' . get_string('savechanges') . '" />';
    echo '<input type="hidden" name="savechanges" value="save" /></div>';
    echo '</fieldset>';
    echo "</form>\n";
    /// Form to choose to show pagebreaks and to repaginate quiz
    echo '<form method="post" action="edit.php" id="showbreaks">';
    echo '<fieldset class="invisiblefieldset">';
    echo $pageurl->hidden_params_out(array('showbreaks', 'reordertool'));
    echo '<input type="hidden" name="sesskey" value="' . $USER->sesskey . '" />';
    echo '<input type="hidden" name="showbreaks" value="0" />';
    echo '<input type="checkbox" name="showbreaks" value="1"';
    if ($showbreaks) {
        echo ' checked="checked"';
    }
    echo ' onchange="getElementById(\'showbreaks\').submit(); return true;" />';
    print_string('showbreaks', 'quiz');
    if ($showbreaks) {
        $perpage = array();
        for ($i = 0; $i <= 50; ++$i) {
            $perpage[$i] = $i;
        }
        $perpage[0] = get_string('allinone', 'quiz');
        echo '<br />&nbsp;&nbsp;';
        print_string('repaginate', 'quiz', choose_from_menu($perpage, 'questionsperpage', $quiz->questionsperpage, '', '', '', true));
    }
    echo '<br /><input type="hidden" name="reordertool" value="0" />';
    echo '<input type="checkbox" name="reordertool" value="1"';
    if ($reordertool) {
        echo ' checked="checked"';
    }
    echo ' onchange="getElementById(\'showbreaks\').submit(); return true;" />';
    print_string('reordertool', 'quiz');
    echo ' ';
    helpbutton('reorderingtool', get_string('reordertool', 'quiz'), 'quiz');
    echo '<div class="quizquestionlistcontrols"><input type="submit" name="repaginate" value="' . get_string('go') . '" /></div>';
    echo '</fieldset>';
    echo '</form>';
    return $sumgrade;
}