Output the quiz intro.
@param object $quiz the quiz settings.
@param object $cm the course_module object.
@return string HTML to output.
766579
public function quiz_intro($quiz, $cm) {
        if (html_is_blank($quiz->intro)) {
            return '';
        }

        return $this->box(format_module_intro('quiz', $quiz, $cm->id), 'generalbox', 'intro');
    }
59411
public function get_cm($cmid) {
        if (empty($this->cms[$cmid])) {
            throw new moodle_exception('invalidcoursemodule', 'error');
        }
        return $this->cms[$cmid];
    }
806068
public function question(structure $structure, $slot, \moodle_url $pageurl) {
        $output = '';
        $output .= html_writer::start_tag('div');

        if ($structure->can_be_edited()) {
            $output .= $this->question_move_icon($structure, $slot);
        }

        $output .= html_writer::start_div('mod-indent-outer');
        $output .= html_writer::tag('input', '', array('id' => 'selectquestion-' .
                $structure->get_displayed_number_for_slot($slot), 'name' => 'selectquestion[]',
               'type' => 'checkbox', 'class' => 'select-multiple-checkbox',
               'value' => $structure->get_displayed_number_for_slot($slot)));
        $output .= $this->question_number($structure->get_displayed_number_for_slot($slot));

        // This div is used to indent the content.
        $output .= html_writer::div('', 'mod-indent');

        // Display the link to the question (or do nothing if question has no url).
        if ($structure->get_question_type_for_slot($slot) == 'random') {
            $questionname = $this->random_question($structure, $slot, $pageurl);
        } else {
            $questionname = $this->question_name($structure, $slot, $pageurl);
        }

        // Start the div for the activity title, excluding the edit icons.
        $output .= html_writer::start_div('activityinstance');
        $output .= $questionname;

        // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this.
        $output .= html_writer::end_tag('div'); // .activityinstance.

        // Action icons.
        $questionicons = '';
        $questionicons .= $this->question_preview_icon($structure->get_quiz(), $structure->get_question_in_slot($slot));
        if ($structure->can_be_edited()) {
            $questionicons .= $this->question_remove_icon($structure, $slot, $pageurl);
        }
        $questionicons .= $this->marked_out_of_field($structure, $slot);
        $output .= html_writer::span($questionicons, 'actions'); // Required to add js spinner icon.
        if ($structure->can_be_edited()) {
            $output .= $this->question_dependency_icon($structure, $slot);
        }

        // End of indentation div.
        $output .= html_writer::end_tag('div');
        $output .= html_writer::end_tag('div');

        return $output;
    }
619599
protected function render_quiz_nav_question_button(quiz_nav_question_button $button) {
        $classes = array('qnbutton', $button->stateclass, $button->navmethod, 'btn', 'btn-secondary');
        $extrainfo = array();

        if ($button->currentpage) {
            $classes[] = 'thispage';
            $extrainfo[] = get_string('onthispage', 'quiz');
        }

        // Flagged?
        if ($button->flagged) {
            $classes[] = 'flagged';
            $flaglabel = get_string('flagged', 'question');
        } else {
            $flaglabel = '';
        }
        $extrainfo[] = html_writer::tag('span', $flaglabel, array('class' => 'flagstate'));

        if (is_numeric($button->number)) {
            $qnostring = 'questionnonav';
        } else {
            $qnostring = 'questionnonavinfo';
        }

        $a = new stdClass();
        $a->number = $button->number;
        $a->attributes = implode(' ', $extrainfo);
        $tagcontents = html_writer::tag('span', '', array('class' => 'thispageholder')) .
                        html_writer::tag('span', '', array('class' => 'trafficlight')) .
                        get_string($qnostring, 'quiz', $a);
        $tagattributes = array('class' => implode(' ', $classes), 'id' => $button->id,
                                  'title' => $button->statestring, 'data-quiz-page' => $button->page);

        if ($button->url) {
            return html_writer::link($button->url, $tagcontents, $tagattributes);
        } else {
            return html_writer::tag('span', $tagcontents, $tagattributes);
        }
    }
1101017
public function get_quiz() {
        global $DB;

        if (empty($this->quiz)) {
            if (empty($this->record->quizid)) {
                throw new \coding_exception('quizid is not set.');
            }
            $this->quiz = $DB->get_record('quiz', array('id' => $this->record->quizid));
        }

        return $this->quiz;
    }
640199
public static function view_quiz($quizid) {
        global $DB;

        $params = self::validate_parameters(self::view_quiz_parameters(), array('quizid' => $quizid));
        $warnings = array();

        list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']);

        // Trigger course_module_viewed event and completion.
        quiz_view($quiz, $course, $cm, $context);

        $result = array();
        $result['status'] = true;
        $result['warnings'] = $warnings;
        return $result;
    }
1133463
protected function definition() {
        global $CFG, $DB;

        $cm = $this->cm;
        $mform = $this->_form;

        $mform->addElement('header', 'override', get_string('override', 'lesson'));

        if ($this->groupmode) {
            // Group override.
            if ($this->groupid) {
                // There is already a groupid, so freeze the selector.
                $groupchoices = array();
                $groupchoices[$this->groupid] = groups_get_group_name($this->groupid);
                $mform->addElement('select', 'groupid',
                        get_string('overridegroup', 'lesson'), $groupchoices);
                $mform->freeze('groupid');
            } else {
                // Prepare the list of groups.
                $groups = groups_get_all_groups($cm->course);
                if (empty($groups)) {
                    // Generate an error.
                    $link = new moodle_url('/mod/lesson/overrides.php', array('cmid' => $cm->id));
                    print_error('groupsnone', 'lesson', $link);
                }

                $groupchoices = array();
                foreach ($groups as $group) {
                    $groupchoices[$group->id] = $group->name;
                }
                unset($groups);

                if (count($groupchoices) == 0) {
                    $groupchoices[0] = get_string('none');
                }

                $mform->addElement('select', 'groupid',
                        get_string('overridegroup', 'lesson'), $groupchoices);
                $mform->addRule('groupid', get_string('required'), 'required', null, 'client');
            }
        } else {
            // User override.
            if ($this->userid) {
                // There is already a userid, so freeze the selector.
                $user = $DB->get_record('user', array('id' => $this->userid));
                $userchoices = array();
                $userchoices[$this->userid] = fullname($user);
                $mform->addElement('select', 'userid',
                        get_string('overrideuser', 'lesson'), $userchoices);
                $mform->freeze('userid');
            } else {
                // Prepare the list of users.
                $users = get_enrolled_users($this->context, '', 0,
                        'u.id, u.email, ' . get_all_user_name_fields(true, 'u'));

                // Filter users based on any fixed restrictions (groups, profile).
                $info = new \core_availability\info_module($cm);
                $users = $info->filter_user_list($users);

                if (empty($users)) {
                    // Generate an error.
                    $link = new moodle_url('/mod/lesson/overrides.php', array('cmid' => $cm->id));
                    print_error('usersnone', 'lesson', $link);
                }

                $userchoices = array();
                $canviewemail = in_array('email', get_extra_user_fields($this->context));
                foreach ($users as $id => $user) {
                    if (empty($invalidusers[$id]) || (!empty($override) &&
                            $id == $override->userid)) {
                        if ($canviewemail) {
                            $userchoices[$id] = fullname($user) . ', ' . $user->email;
                        } else {
                            $userchoices[$id] = fullname($user);
                        }
                    }
                }
                unset($users);

                if (count($userchoices) == 0) {
                    $userchoices[0] = get_string('none');
                }
                $mform->addElement('searchableselector', 'userid',
                        get_string('overrideuser', 'lesson'), $userchoices);
                $mform->addRule('userid', get_string('required'), 'required', null, 'client');
            }
        }

        // Password.
        // This field has to be above the date and timelimit fields,
        // otherwise browsers will clear it when those fields are changed.
        $mform->addElement('passwordunmask', 'password', get_string('usepassword', 'lesson'));
        $mform->setType('password', PARAM_TEXT);
        $mform->addHelpButton('password', 'usepassword', 'lesson');
        $mform->setDefault('password', $this->lesson->password);;

        // Open and close dates.
        $mform->addElement('date_time_selector', 'available', get_string('available', 'lesson'), array('optional' => true));
        $mform->setDefault('available', $this->lesson->available);

        $mform->addElement('date_time_selector', 'deadline', get_string('deadline', 'lesson'), array('optional' => true));
        $mform->setDefault('deadline', $this->lesson->deadline);

        // Lesson time limit.
        $mform->addElement('duration', 'timelimit',
                get_string('timelimit', 'lesson'), array('optional' => true));
        if ($this->lesson->timelimit != 0) {
            $mform->setDefault('timelimit', 0);
        } else {
            $mform->setDefault('timelimit', $this->lesson->timelimit);
        }

        // Try a question again.
        $mform->addElement('selectyesno', 'review', get_string('displayreview', 'lesson'));
        $mform->addHelpButton('review', 'displayreview', 'lesson');
        $mform->setDefault('review', $this->lesson->review);

        // Number of attempts.
        $numbers = array();
        for ($i = 10; $i > 0; $i--) {
            $numbers[$i] = $i;
        }
        $mform->addElement('select', 'maxattempts', get_string('maximumnumberofattempts', 'lesson'), $numbers);
        $mform->addHelpButton('maxattempts', 'maximumnumberofattempts', 'lesson');
        $mform->setDefault('maxattempts', $this->lesson->maxattempts);

        // Retake allowed.
        $mform->addElement('selectyesno', 'retake', get_string('retakesallowed', 'lesson'));
        $mform->addHelpButton('retake', 'retakesallowed', 'lesson');
        $mform->setDefault('retake', $this->lesson->retake);

        // Submit buttons.
        $mform->addElement('submit', 'resetbutton',
                get_string('reverttodefaults', 'lesson'));

        $buttonarray = array();
        $buttonarray[] = $mform->createElement('submit', 'submitbutton',
                get_string('save', 'lesson'));
        $buttonarray[] = $mform->createElement('submit', 'againbutton',
                get_string('saveoverrideandstay', 'lesson'));
        $buttonarray[] = $mform->createElement('cancel');

        $mform->addGroup($buttonarray, 'buttonbar', '', array(' '), false);
        $mform->closeHeaderBefore('buttonbar');

    }
865411
public function output()
    {
        $TCPDF = new TCPDF($this->_Pdf->orientation(), 'mm', $this->_Pdf->pageSize());
        $TCPDF->AddPage();
        $TCPDF->writeHTML($this->_Pdf->html());

        return $TCPDF->Output('', 'S');
    }
968621
public function writequestion($question) {
        global $CFG, $OUTPUT;

        $invalidquestion = false;
        $fs = get_file_storage();
        $contextid = $question->contextid;
        // Get files used by the questiontext.
        $question->questiontextfiles = $fs->get_area_files(
                $contextid, 'question', 'questiontext', $question->id);
        // Get files used by the generalfeedback.
        $question->generalfeedbackfiles = $fs->get_area_files(
                $contextid, 'question', 'generalfeedback', $question->id);
        if (!empty($question->options->answers)) {
            foreach ($question->options->answers as $answer) {
                $answer->answerfiles = $fs->get_area_files(
                        $contextid, 'question', 'answer', $answer->id);
                $answer->feedbackfiles = $fs->get_area_files(
                        $contextid, 'question', 'answerfeedback', $answer->id);
            }
        }

        $expout = '';

        // Add a comment linking this to the original question id.
        $expout .= "<!-- question: {$question->id}  -->\n";

        // Check question type.
        $questiontype = $this->get_qtype($question->qtype);

        // Categories are a special case.
        if ($question->qtype == 'category') {
            $categorypath = $this->writetext($question->category);
            $categoryinfo = $this->writetext($question->info);
            $infoformat = $this->format($question->infoformat);
            $expout .= "  <question type=\"category\">\n";
            $expout .= "    <category>\n";
            $expout .= "      {$categorypath}";
            $expout .= "    </category>\n";
            $expout .= "    <info {$infoformat}>\n";
            $expout .= "      {$categoryinfo}";
            $expout .= "    </info>\n";
            $expout .= "  </question>\n";
            return $expout;
        }

        // Now we know we are are handing a real question.
        // Output the generic information.
        $expout .= "  <question type=\"{$questiontype}\">\n";
        $expout .= "    <name>\n";
        $expout .= $this->writetext($question->name, 3);
        $expout .= "    </name>\n";
        $expout .= "    <questiontext {$this->format($question->questiontextformat)}>\n";
        $expout .= $this->writetext($question->questiontext, 3);
        $expout .= $this->write_files($question->questiontextfiles);
        $expout .= "    </questiontext>\n";
        $expout .= "    <generalfeedback {$this->format($question->generalfeedbackformat)}>\n";
        $expout .= $this->writetext($question->generalfeedback, 3);
        $expout .= $this->write_files($question->generalfeedbackfiles);
        $expout .= "    </generalfeedback>\n";
        if ($question->qtype != 'multianswer') {
            $expout .= "    <defaultgrade>{$question->defaultmark}</defaultgrade>\n";
        }
        $expout .= "    <penalty>{$question->penalty}</penalty>\n";
        $expout .= "    <hidden>{$question->hidden}</hidden>\n";
        $expout .= "    <idnumber>{$question->idnumber}</idnumber>\n";

        // The rest of the output depends on question type.
        switch($question->qtype) {
            case 'category':
                // Not a qtype really - dummy used for category switching.
                break;

            case 'truefalse':
                $trueanswer = $question->options->answers[$question->options->trueanswer];
                $trueanswer->answer = 'true';
                $expout .= $this->write_answer($trueanswer);

                $falseanswer = $question->options->answers[$question->options->falseanswer];
                $falseanswer->answer = 'false';
                $expout .= $this->write_answer($falseanswer);
                break;

            case 'multichoice':
                $expout .= "    <single>" . $this->get_single($question->options->single) .
                        "</single>\n";
                $expout .= "    <shuffleanswers>" .
                        $this->get_single($question->options->shuffleanswers) .
                        "</shuffleanswers>\n";
                $expout .= "    <answernumbering>" . $question->options->answernumbering .
                        "</answernumbering>\n";
                $expout .= $this->write_combined_feedback($question->options, $question->id, $question->contextid);
                $expout .= $this->write_answers($question->options->answers);
                break;

            case 'shortanswer':
                $expout .= "    <usecase>{$question->options->usecase}</usecase>\n";
                $expout .= $this->write_answers($question->options->answers);
                break;

            case 'numerical':
                foreach ($question->options->answers as $answer) {
                    $expout .= $this->write_answer($answer,
                            "      <tolerance>{$answer->tolerance}</tolerance>\n");
                }

                $units = $question->options->units;
                if (count($units)) {
                    $expout .= "<units>\n";
                    foreach ($units as $unit) {
                        $expout .= "  <unit>\n";
                        $expout .= "    <multiplier>{$unit->multiplier}</multiplier>\n";
                        $expout .= "    <unit_name>{$unit->unit}</unit_name>\n";
                        $expout .= "  </unit>\n";
                    }
                    $expout .= "</units>\n";
                }
                if (isset($question->options->unitgradingtype)) {
                    $expout .= "    <unitgradingtype>" . $question->options->unitgradingtype .
                            "</unitgradingtype>\n";
                }
                if (isset($question->options->unitpenalty)) {
                    $expout .= "    <unitpenalty>{$question->options->unitpenalty}</unitpenalty>\n";
                }
                if (isset($question->options->showunits)) {
                    $expout .= "    <showunits>{$question->options->showunits}</showunits>\n";
                }
                if (isset($question->options->unitsleft)) {
                    $expout .= "    <unitsleft>{$question->options->unitsleft}</unitsleft>\n";
                }
                if (!empty($question->options->instructionsformat)) {
                    $files = $fs->get_area_files($contextid, 'qtype_numerical',
                            'instruction', $question->id);
                    $expout .= "    <instructions " .
                            $this->format($question->options->instructionsformat) . ">\n";
                    $expout .= $this->writetext($question->options->instructions, 3);
                    $expout .= $this->write_files($files);
                    $expout .= "    </instructions>\n";
                }
                break;

            case 'match':
                $expout .= "    <shuffleanswers>" .
                        $this->get_single($question->options->shuffleanswers) .
                        "</shuffleanswers>\n";
                $expout .= $this->write_combined_feedback($question->options, $question->id, $question->contextid);
                foreach ($question->options->subquestions as $subquestion) {
                    $files = $fs->get_area_files($contextid, 'qtype_match',
                            'subquestion', $subquestion->id);
                    $expout .= "    <subquestion " .
                            $this->format($subquestion->questiontextformat) . ">\n";
                    $expout .= $this->writetext($subquestion->questiontext, 3);
                    $expout .= $this->write_files($files);
                    $expout .= "      <answer>\n";
                    $expout .= $this->writetext($subquestion->answertext, 4);
                    $expout .= "      </answer>\n";
                    $expout .= "    </subquestion>\n";
                }
                break;

            case 'description':
                // Nothing else to do.
                break;

            case 'multianswer':
                foreach ($question->options->questions as $index => $subq) {
                    $expout = str_replace('{#' . $index . '}', $subq->questiontext, $expout);
                }
                break;

            case 'essay':
                $expout .= "    <responseformat>" . $question->options->responseformat .
                        "</responseformat>\n";
                $expout .= "    <responserequired>" . $question->options->responserequired .
                        "</responserequired>\n";
                $expout .= "    <responsefieldlines>" . $question->options->responsefieldlines .
                        "</responsefieldlines>\n";
                $expout .= "    <attachments>" . $question->options->attachments .
                        "</attachments>\n";
                $expout .= "    <attachmentsrequired>" . $question->options->attachmentsrequired .
                        "</attachmentsrequired>\n";
                $expout .= "    <graderinfo " .
                        $this->format($question->options->graderinfoformat) . ">\n";
                $expout .= $this->writetext($question->options->graderinfo, 3);
                $expout .= $this->write_files($fs->get_area_files($contextid, 'qtype_essay',
                        'graderinfo', $question->id));
                $expout .= "    </graderinfo>\n";
                $expout .= "    <responsetemplate " .
                        $this->format($question->options->responsetemplateformat) . ">\n";
                $expout .= $this->writetext($question->options->responsetemplate, 3);
                $expout .= "    </responsetemplate>\n";
                break;

            case 'calculated':
            case 'calculatedsimple':
            case 'calculatedmulti':
                $expout .= "    <synchronize>{$question->options->synchronize}</synchronize>\n";
                $expout .= "    <single>{$question->options->single}</single>\n";
                $expout .= "    <answernumbering>" . $question->options->answernumbering .
                        "</answernumbering>\n";
                $expout .= "    <shuffleanswers>" . $question->options->shuffleanswers .
                        "</shuffleanswers>\n";

                $component = 'qtype_' . $question->qtype;
                $files = $fs->get_area_files($contextid, $component,
                        'correctfeedback', $question->id);
                $expout .= "    <correctfeedback>\n";
                $expout .= $this->writetext($question->options->correctfeedback, 3);
                $expout .= $this->write_files($files);
                $expout .= "    </correctfeedback>\n";

                $files = $fs->get_area_files($contextid, $component,
                        'partiallycorrectfeedback', $question->id);
                $expout .= "    <partiallycorrectfeedback>\n";
                $expout .= $this->writetext($question->options->partiallycorrectfeedback, 3);
                $expout .= $this->write_files($files);
                $expout .= "    </partiallycorrectfeedback>\n";

                $files = $fs->get_area_files($contextid, $component,
                        'incorrectfeedback', $question->id);
                $expout .= "    <incorrectfeedback>\n";
                $expout .= $this->writetext($question->options->incorrectfeedback, 3);
                $expout .= $this->write_files($files);
                $expout .= "    </incorrectfeedback>\n";

                foreach ($question->options->answers as $answer) {
                    $percent = 100 * $answer->fraction;
                    $expout .= "<answer fraction=\"{$percent}\">\n";
                    // The "<text/>" tags are an added feature, old files won't have them.
                    $expout .= "    <text>{$answer->answer}</text>\n";
                    $expout .= "    <tolerance>{$answer->tolerance}</tolerance>\n";
                    $expout .= "    <tolerancetype>{$answer->tolerancetype}</tolerancetype>\n";
                    $expout .= "    <correctanswerformat>" .
                            $answer->correctanswerformat . "</correctanswerformat>\n";
                    $expout .= "    <correctanswerlength>" .
                            $answer->correctanswerlength . "</correctanswerlength>\n";
                    $expout .= "    <feedback {$this->format($answer->feedbackformat)}>\n";
                    $files = $fs->get_area_files($contextid, $component,
                            'instruction', $question->id);
                    $expout .= $this->writetext($answer->feedback);
                    $expout .= $this->write_files($answer->feedbackfiles);
                    $expout .= "    </feedback>\n";
                    $expout .= "</answer>\n";
                }
                if (isset($question->options->unitgradingtype)) {
                    $expout .= "    <unitgradingtype>" .
                            $question->options->unitgradingtype . "</unitgradingtype>\n";
                }
                if (isset($question->options->unitpenalty)) {
                    $expout .= "    <unitpenalty>" .
                            $question->options->unitpenalty . "</unitpenalty>\n";
                }
                if (isset($question->options->showunits)) {
                    $expout .= "    <showunits>{$question->options->showunits}</showunits>\n";
                }
                if (isset($question->options->unitsleft)) {
                    $expout .= "    <unitsleft>{$question->options->unitsleft}</unitsleft>\n";
                }

                if (isset($question->options->instructionsformat)) {
                    $files = $fs->get_area_files($contextid, $component,
                            'instruction', $question->id);
                    $expout .= "    <instructions " .
                            $this->format($question->options->instructionsformat) . ">\n";
                    $expout .= $this->writetext($question->options->instructions, 3);
                    $expout .= $this->write_files($files);
                    $expout .= "    </instructions>\n";
                }

                if (isset($question->options->units)) {
                    $units = $question->options->units;
                    if (count($units)) {
                        $expout .= "<units>\n";
                        foreach ($units as $unit) {
                            $expout .= "  <unit>\n";
                            $expout .= "    <multiplier>{$unit->multiplier}</multiplier>\n";
                            $expout .= "    <unit_name>{$unit->unit}</unit_name>\n";
                            $expout .= "  </unit>\n";
                        }
                        $expout .= "</units>\n";
                    }
                }

                // The tag $question->export_process has been set so we get all the
                // data items in the database from the function
                // qtype_calculated::get_question_options calculatedsimple defaults
                // to calculated.
                if (isset($question->options->datasets) && count($question->options->datasets)) {
                    $expout .= "<dataset_definitions>\n";
                    foreach ($question->options->datasets as $def) {
                        $expout .= "<dataset_definition>\n";
                        $expout .= "    <status>".$this->writetext($def->status)."</status>\n";
                        $expout .= "    <name>".$this->writetext($def->name)."</name>\n";
                        if ($question->qtype == 'calculated') {
                            $expout .= "    <type>calculated</type>\n";
                        } else {
                            $expout .= "    <type>calculatedsimple</type>\n";
                        }
                        $expout .= "    <distribution>" . $this->writetext($def->distribution) .
                                "</distribution>\n";
                        $expout .= "    <minimum>" . $this->writetext($def->minimum) .
                                "</minimum>\n";
                        $expout .= "    <maximum>" . $this->writetext($def->maximum) .
                                "</maximum>\n";
                        $expout .= "    <decimals>" . $this->writetext($def->decimals) .
                                "</decimals>\n";
                        $expout .= "    <itemcount>{$def->itemcount}</itemcount>\n";
                        if ($def->itemcount > 0) {
                            $expout .= "    <dataset_items>\n";
                            foreach ($def->items as $item) {
                                  $expout .= "        <dataset_item>\n";
                                  $expout .= "           <number>".$item->itemnumber."</number>\n";
                                  $expout .= "           <value>".$item->value."</value>\n";
                                  $expout .= "        </dataset_item>\n";
                            }
                            $expout .= "    </dataset_items>\n";
                            $expout .= "    <number_of_items>" . $def->number_of_items .
                                    "</number_of_items>\n";
                        }
                        $expout .= "</dataset_definition>\n";
                    }
                    $expout .= "</dataset_definitions>\n";
                }
                break;

            default:
                // Try support by optional plugin.
                if (!$data = $this->try_exporting_using_qtypes($question->qtype, $question)) {
                    $invalidquestion = true;
                } else {
                    $expout .= $data;
                }
        }

        // Output any hints.
        $expout .= $this->write_hints($question);

        // Write the question tags.
        if (core_tag_tag::is_enabled('core_question', 'question')) {
            $tagobjects = core_tag_tag::get_item_tags('core_question', 'question', $question->id);

            if (!empty($tagobjects)) {
                $context = context::instance_by_id($contextid);
                $sortedtagobjects = question_sort_tags($tagobjects, $context, [$this->course]);

                if (!empty($sortedtagobjects->coursetags)) {
                    // Set them on the form to be rendered as existing tags.
                    $expout .= "    <coursetags>\n";
                    foreach ($sortedtagobjects->coursetags as $coursetag) {
                        $expout .= "      <tag>" . $this->writetext($coursetag, 0, true) . "</tag>\n";
                    }
                    $expout .= "    </coursetags>\n";
                }

                if (!empty($sortedtagobjects->tags)) {
                    $expout .= "    <tags>\n";
                    foreach ($sortedtagobjects->tags as $tag) {
                        $expout .= "      <tag>" . $this->writetext($tag, 0, true) . "</tag>\n";
                    }
                    $expout .= "    </tags>\n";
                }
            }
        }

        // Close the question tag.
        $expout .= "  </question>\n";
        if ($invalidquestion) {
            return '';
        } else {
            return $expout;
        }
    }
666860
public function render_questions_table($includeauto, $data, $header) {
        if (empty($data)) {
            return $this->render_quiz_no_grade_question_notification();
        }
        $output = '';

        $table = new html_table();
        $table->class = 'generaltable';
        $table->id = 'questionstograde';
        $table->head = $header;
        $table->data = $data;

        $output .= html_writer::table($table);

        return $output;
    }
1129545
public function cmdGetLanguage()
    {
        $list = $this->getListLanguage();
        $this->outputFormat($list);
        $this->outputFormatTableLanguage($list);
        $this->output();
    }
1098589
public function view_table($quiz, $context, $viewobj) {
        if (!$viewobj->attempts) {
            return '';
        }

        // Prepare table header.
        $table = new html_table();
        $table->attributes['class'] = 'generaltable quizattemptsummary';
        $table->head = array();
        $table->align = array();
        $table->size = array();
        if ($viewobj->attemptcolumn) {
            $table->head[] = get_string('attemptnumber', 'quiz');
            $table->align[] = 'center';
            $table->size[] = '';
        }
        $table->head[] = get_string('attemptstate', 'quiz');
        $table->align[] = 'left';
        $table->size[] = '';
        if ($viewobj->markcolumn) {
            $table->head[] = get_string('marks', 'quiz') . ' / ' .
                    quiz_format_grade($quiz, $quiz->sumgrades);
            $table->align[] = 'center';
            $table->size[] = '';
        }
        if ($viewobj->gradecolumn) {
            $table->head[] = get_string('grade') . ' / ' .
                    quiz_format_grade($quiz, $quiz->grade);
            $table->align[] = 'center';
            $table->size[] = '';
        }
        if ($viewobj->canreviewmine) {
            $table->head[] = get_string('review', 'quiz');
            $table->align[] = 'center';
            $table->size[] = '';
        }
        if ($viewobj->feedbackcolumn) {
            $table->head[] = get_string('feedback', 'quiz');
            $table->align[] = 'left';
            $table->size[] = '';
        }

        // One row for each attempt.
        foreach ($viewobj->attemptobjs as $attemptobj) {
            $attemptoptions = $attemptobj->get_display_options(true);
            $row = array();

            // Add the attempt number.
            if ($viewobj->attemptcolumn) {
                if ($attemptobj->is_preview()) {
                    $row[] = get_string('preview', 'quiz');
                } else {
                    $row[] = $attemptobj->get_attempt_number();
                }
            }

            $row[] = $this->attempt_state($attemptobj);

            if ($viewobj->markcolumn) {
                if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
                        $attemptobj->is_finished()) {
                    $row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks());
                } else {
                    $row[] = '';
                }
            }

            // Ouside the if because we may be showing feedback but not grades.
            $attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false);

            if ($viewobj->gradecolumn) {
                if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX &&
                        $attemptobj->is_finished()) {

                    // Highlight the highest grade if appropriate.
                    if ($viewobj->overallstats && !$attemptobj->is_preview()
                            && $viewobj->numattempts > 1 && !is_null($viewobj->mygrade)
                            && $attemptobj->get_state() == quiz_attempt::FINISHED
                            && $attemptgrade == $viewobj->mygrade
                            && $quiz->grademethod == QUIZ_GRADEHIGHEST) {
                        $table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow';
                    }

                    $row[] = quiz_format_grade($quiz, $attemptgrade);
                } else {
                    $row[] = '';
                }
            }

            if ($viewobj->canreviewmine) {
                $row[] = $viewobj->accessmanager->make_review_link($attemptobj->get_attempt(),
                        $attemptoptions, $this);
            }

            if ($viewobj->feedbackcolumn && $attemptobj->is_finished()) {
                if ($attemptoptions->overallfeedback) {
                    $row[] = quiz_feedback_for_grade($attemptgrade, $quiz, $context);
                } else {
                    $row[] = '';
                }
            }

            if ($attemptobj->is_preview()) {
                $table->data['preview'] = $row;
            } else {
                $table->data[$attemptobj->get_attempt_number()] = $row;
            }
        } // End of loop over attempts.

        $output = '';
        $output .= $this->view_table_heading();
        $output .= html_writer::table($table);
        return $output;
    }
743245
protected function section_summary($section, $course, $mods) {
        $classattr = 'section main section-summary clearfix';
        $linkclasses = '';

        // If section is hidden then display grey section link
        if (!$section->visible) {
            $classattr .= ' hidden';
            $linkclasses .= ' dimmed_text';
        } else if (course_get_format($course)->is_section_current($section)) {
            $classattr .= ' current';
        }

        $title = get_section_name($course, $section);
        $o = '';
        $o .= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
            'class' => $classattr, 'role'=>'region', 'aria-label'=> $title));

        $o .= html_writer::tag('div', '', array('class' => 'left side'));
        $o .= html_writer::tag('div', '', array('class' => 'right side'));
        $o .= html_writer::start_tag('div', array('class' => 'content'));

        if ($section->uservisible) {
            $title = html_writer::tag('a', $title,
                    array('href' => course_get_url($course, $section->section), 'class' => $linkclasses));
        }
        $o .= $this->output->heading($title, 3, 'section-title');

        $o .= $this->section_availability($section);
        $o.= html_writer::start_tag('div', array('class' => 'summarytext'));

        if ($section->uservisible || $section->visible) {
            // Show summary if section is available or has availability restriction information.
            // Do not show summary if section is hidden but we still display it because of course setting
            // "Hidden sections are shown in collapsed form".
            $o .= $this->format_summary_text($section);
        }
        $o.= html_writer::end_tag('div');
        $o.= $this->section_activity_summary($section, $course, null);

        $o .= html_writer::end_tag('div');
        $o .= html_writer::end_tag('li');

        return $o;
    }
1329033
public function display($scorm, $cm, $course, $download) {
        global $DB, $OUTPUT, $PAGE;

        $contextmodule = context_module::instance($cm->id);

        if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used.
            groups_print_activity_menu($cm, new moodle_url($PAGE->url));
        }

        // Find out current restriction.
        $group = groups_get_activity_group($cm, true);
        if (empty($group)) {
            // All users who can attempt scoes.
            $students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id' , '', '', '', '', '', false);
            $allowedlist = empty($students) ? array() : array_keys($students);
        } else {
            // All users who can attempt scoes and who are in the currently selected group.
            $groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', $group, '', false);
            $allowedlist = empty($groupstudents) ? array() : array_keys($groupstudents);
        }

        // Labels.
        $labels = [get_string('invaliddata', 'scormreport_graphs')];
        for ($i = 1; $i <= self::BANDS - 1; $i++) {
            $labels[] = ($i - 1) * self::BANDWIDTH . ' - ' . $i * self::BANDWIDTH;
        }

        if ($scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id')) {
            foreach ($scoes as $sco) {
                if ($sco->launch != '') {

                    $data = $this->get_data($sco->id, $allowedlist);
                    $series = new chart_series($sco->title, $data);

                    $chart = new chart_bar();
                    $chart->set_labels($labels);
                    $chart->add_series($series);
                    $chart->get_xaxis(0, true)->set_label(get_string('percent', 'scormreport_graphs'));
                    $yaxis = $chart->get_yaxis(0, true);
                    $yaxis->set_label(get_string('participants', 'scormreport_graphs'));
                    $yaxis->set_stepsize(max(1, round(max($data) / 10)));

                    echo $OUTPUT->heading($sco->title, 3);
                    echo $OUTPUT->render($chart);
                }
            }
        }
    }
36172
public static function list_course_module_competencies($cmid) {
        global $PAGE;

        $params = self::validate_parameters(self::list_course_module_competencies_parameters(), array(
            'cmid' => $cmid
        ));

        $context = context_module::instance($params['cmid']);
        self::validate_context($context);

        $output = $PAGE->get_renderer('core');

        $apiresult = api::list_course_module_competencies($params['cmid']);
        $result = array();

        foreach ($apiresult as $cmrecord) {
            $one = new \stdClass();
            $exporter = new competency_exporter($cmrecord['competency']);
            $one->competency = $exporter->export($output);
            $exporter = new course_module_competency_exporter($cmrecord['coursemodulecompetency']);
            $one->coursemodulecompetency = $exporter->export($output);

            $result[] = (array) $one;
        }

        return $result;
    }
800801
public function delete_all_state($cm) {
        global $DB;

        // Delete from database
        $DB->delete_records('course_modules_completion', array('coursemoduleid'=>$cm->id));

        // Check if there is an associated course completion criteria
        $criteria = $this->get_criteria(COMPLETION_CRITERIA_TYPE_ACTIVITY);
        $acriteria = false;
        foreach ($criteria as $criterion) {
            if ($criterion->moduleinstance == $cm->id) {
                $acriteria = $criterion;
                break;
            }
        }

        if ($acriteria) {
            // Delete all criteria completions relating to this activity
            $DB->delete_records('course_completion_crit_compl', array('course' => $this->course_id, 'criteriaid' => $acriteria->id));
            $DB->delete_records('course_completions', array('course' => $this->course_id));
        }

        // Difficult to find affected users, just purge all completion cache.
        cache::make('core', 'completion')->purge();
        cache::make('core', 'coursecompletion')->purge();
    }
625332
public static function get_quizzes_by_courses_returns() {
        return new external_single_structure(
            array(
                'quizzes' => new external_multiple_structure(
                    new external_single_structure(
                        array(
                            'id' => new external_value(PARAM_INT, 'Standard Moodle primary key.'),
                            'course' => new external_value(PARAM_INT, 'Foreign key reference to the course this quiz is part of.'),
                            'coursemodule' => new external_value(PARAM_INT, 'Course module id.'),
                            'name' => new external_value(PARAM_RAW, 'Quiz name.'),
                            'intro' => new external_value(PARAM_RAW, 'Quiz introduction text.', VALUE_OPTIONAL),
                            'introformat' => new external_format_value('intro', VALUE_OPTIONAL),
                            'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
                            'timeopen' => new external_value(PARAM_INT, 'The time when this quiz opens. (0 = no restriction.)',
                                                                VALUE_OPTIONAL),
                            'timeclose' => new external_value(PARAM_INT, 'The time when this quiz closes. (0 = no restriction.)',
                                                                VALUE_OPTIONAL),
                            'timelimit' => new external_value(PARAM_INT, 'The time limit for quiz attempts, in seconds.',
                                                                VALUE_OPTIONAL),
                            'overduehandling' => new external_value(PARAM_ALPHA, 'The method used to handle overdue attempts.
                                                                    \'autosubmit\', \'graceperiod\' or \'autoabandon\'.',
                                                                    VALUE_OPTIONAL),
                            'graceperiod' => new external_value(PARAM_INT, 'The amount of time (in seconds) after the time limit
                                                                runs out during which attempts can still be submitted,
                                                                if overduehandling is set to allow it.', VALUE_OPTIONAL),
                            'preferredbehaviour' => new external_value(PARAM_ALPHANUMEXT, 'The behaviour to ask questions to use.',
                                                                        VALUE_OPTIONAL),
                            'canredoquestions' => new external_value(PARAM_INT, 'Allows students to redo any completed question
                                                                        within a quiz attempt.', VALUE_OPTIONAL),
                            'attempts' => new external_value(PARAM_INT, 'The maximum number of attempts a student is allowed.',
                                                                VALUE_OPTIONAL),
                            'attemptonlast' => new external_value(PARAM_INT, 'Whether subsequent attempts start from the answer
                                                                    to the previous attempt (1) or start blank (0).',
                                                                    VALUE_OPTIONAL),
                            'grademethod' => new external_value(PARAM_INT, 'One of the values QUIZ_GRADEHIGHEST, QUIZ_GRADEAVERAGE,
                                                                    QUIZ_ATTEMPTFIRST or QUIZ_ATTEMPTLAST.', VALUE_OPTIONAL),
                            'decimalpoints' => new external_value(PARAM_INT, 'Number of decimal points to use when displaying
                                                                    grades.', VALUE_OPTIONAL),
                            'questiondecimalpoints' => new external_value(PARAM_INT, 'Number of decimal points to use when
                                                                            displaying question grades.
                                                                            (-1 means use decimalpoints.)', VALUE_OPTIONAL),
                            'reviewattempt' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
                                                                    attempts at various times. This is a bit field, decoded by the
                                                                    mod_quiz_display_options class. It is formed by ORing together
                                                                    the constants defined there.', VALUE_OPTIONAL),
                            'reviewcorrectness' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
                                                                        attempts at various times.
                                                                        A bit field, like reviewattempt.', VALUE_OPTIONAL),
                            'reviewmarks' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts
                                                                at various times. A bit field, like reviewattempt.',
                                                                VALUE_OPTIONAL),
                            'reviewspecificfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their
                                                                            quiz attempts at various times. A bit field, like
                                                                            reviewattempt.', VALUE_OPTIONAL),
                            'reviewgeneralfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their
                                                                            quiz attempts at various times. A bit field, like
                                                                            reviewattempt.', VALUE_OPTIONAL),
                            'reviewrightanswer' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
                                                                        attempts at various times. A bit field, like
                                                                        reviewattempt.', VALUE_OPTIONAL),
                            'reviewoverallfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz
                                                                            attempts at various times. A bit field, like
                                                                            reviewattempt.', VALUE_OPTIONAL),
                            'questionsperpage' => new external_value(PARAM_INT, 'How often to insert a page break when editing
                                                                        the quiz, or when shuffling the question order.',
                                                                        VALUE_OPTIONAL),
                            'navmethod' => new external_value(PARAM_ALPHA, 'Any constraints on how the user is allowed to navigate
                                                                around the quiz. Currently recognised values are
                                                                \'free\' and \'seq\'.', VALUE_OPTIONAL),
                            'shuffleanswers' => new external_value(PARAM_INT, 'Whether the parts of the question should be shuffled,
                                                                    in those question types that support it.', VALUE_OPTIONAL),
                            'sumgrades' => new external_value(PARAM_FLOAT, 'The total of all the question instance maxmarks.',
                                                                VALUE_OPTIONAL),
                            'grade' => new external_value(PARAM_FLOAT, 'The total that the quiz overall grade is scaled to be
                                                            out of.', VALUE_OPTIONAL),
                            'timecreated' => new external_value(PARAM_INT, 'The time when the quiz was added to the course.',
                                                                VALUE_OPTIONAL),
                            'timemodified' => new external_value(PARAM_INT, 'Last modified time.',
                                                                    VALUE_OPTIONAL),
                            'password' => new external_value(PARAM_RAW, 'A password that the student must enter before starting or
                                                                continuing a quiz attempt.', VALUE_OPTIONAL),
                            'subnet' => new external_value(PARAM_RAW, 'Used to restrict the IP addresses from which this quiz can
                                                            be attempted. The format is as requried by the address_in_subnet
                                                            function.', VALUE_OPTIONAL),
                            'browsersecurity' => new external_value(PARAM_ALPHANUMEXT, 'Restriciton on the browser the student must
                                                                    use. E.g. \'securewindow\'.', VALUE_OPTIONAL),
                            'delay1' => new external_value(PARAM_INT, 'Delay that must be left between the first and second attempt,
                                                            in seconds.', VALUE_OPTIONAL),
                            'delay2' => new external_value(PARAM_INT, 'Delay that must be left between the second and subsequent
                                                            attempt, in seconds.', VALUE_OPTIONAL),
                            'showuserpicture' => new external_value(PARAM_INT, 'Option to show the user\'s picture during the
                                                                    attempt and on the review page.', VALUE_OPTIONAL),
                            'showblocks' => new external_value(PARAM_INT, 'Whether blocks should be shown on the attempt.php and
                                                                review.php pages.', VALUE_OPTIONAL),
                            'completionattemptsexhausted' => new external_value(PARAM_INT, 'Mark quiz complete when the student has
                                                                                exhausted the maximum number of attempts',
                                                                                VALUE_OPTIONAL),
                            'completionpass' => new external_value(PARAM_INT, 'Whether to require passing grade', VALUE_OPTIONAL),
                            'allowofflineattempts' => new external_value(PARAM_INT, 'Whether to allow the quiz to be attempted
                                                                            offline in the mobile app', VALUE_OPTIONAL),
                            'autosaveperiod' => new external_value(PARAM_INT, 'Auto-save delay', VALUE_OPTIONAL),
                            'hasfeedback' => new external_value(PARAM_INT, 'Whether the quiz has any non-blank feedback text',
                                                                VALUE_OPTIONAL),
                            'hasquestions' => new external_value(PARAM_INT, 'Whether the quiz has questions', VALUE_OPTIONAL),
                            'section' => new external_value(PARAM_INT, 'Course section id', VALUE_OPTIONAL),
                            'visible' => new external_value(PARAM_INT, 'Module visibility', VALUE_OPTIONAL),
                            'groupmode' => new external_value(PARAM_INT, 'Group mode', VALUE_OPTIONAL),
                            'groupingid' => new external_value(PARAM_INT, 'Grouping id', VALUE_OPTIONAL),
                        )
                    )
                ),
                'warnings' => new external_warnings(),
            )
        );
    }